From b22a68377d3026572e7859f712674b319767eb7e Mon Sep 17 00:00:00 2001
From: Louis-Philippe Gauthier <lpgauth@gmail.com>
Date: Thu, 20 Jun 2013 01:48:31 -0400
Subject: Add openssh_zlib compression type to ssh_transport

http://www.openssh.org/txt/draft-miller-secsh-compression-delayed-00.txt
---
 lib/ssh/src/ssh.hrl                    |  3 ++-
 lib/ssh/src/ssh_connection_handler.erl |  4 ++--
 lib/ssh/src/ssh_transport.erl          | 37 ++++++++++++++++++++++++++++++----
 3 files changed, 37 insertions(+), 7 deletions(-)

(limited to 'lib')

diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index da5750b6c3..4fd347ba8f 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -127,7 +127,8 @@
 	  userauth_supported_methods , %  
 	  userauth_methods,
 	  userauth_preference,
-	  available_host_keys
+	  available_host_keys,
+	  authenticated = false
 	 }).
 
 -record(alg,
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 1c4477aeb3..d2792727db 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -426,10 +426,10 @@ userauth(#ssh_msg_userauth_info_response{} = Msg,
 						  language = "en"}, State)
     end;
 			
-userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client},
+userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client} = Ssh,
 					     manager = Pid} = State) ->
     Pid ! ssh_connected,
-    {next_state, connected, next_packet(State)};
+    {next_state, connected, next_packet(State#state{ssh_params = Ssh#ssh{authenticated = true}})};
 
 userauth(#ssh_msg_userauth_failure{},  
 	 #state{ssh_params = #ssh{role = client,
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index beaffdc025..682d766d99 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -206,6 +206,7 @@ key_exchange_init_msg(Ssh0) ->
 kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) ->
     Random = ssh_bits:random(16),
     Compression = case proplists:get_value(compression, Opts, none) of
+		      openssh_zlib -> ["zlib@openssh.com", "none"];
 		      zlib -> ["zlib", "none"];
 		      none -> ["none", "zlib"]
 		  end,
@@ -855,33 +856,47 @@ decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key,
     IV = crypto:next_iv(aes_cbc, Data),
     {Ssh#ssh{decrypt_ctx = IV}, Dec}.
 
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Compression
 %%
-%%     none     REQUIRED        no compression
-%%     zlib     OPTIONAL        ZLIB (LZ77) compression
+%%     none             REQUIRED        no compression
+%%     zlib             OPTIONAL        ZLIB (LZ77) compression
+%%     openssh_zlib     OPTIONAL        ZLIB (LZ77) compression
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 compress_init(SSH) ->
     compress_init(SSH, 1).
 
 compress_init(#ssh{compress = none} = Ssh, _) ->
     {ok, Ssh};
 compress_init(#ssh{compress = zlib} = Ssh, Level) ->
+    Zlib = zlib:open(),
+    ok = zlib:deflateInit(Zlib, Level),
+    {ok, Ssh#ssh{compress_ctx = Zlib}};
+compress_init(#ssh{compress = 'zlib@openssh.com'} = Ssh, Level) ->
     Zlib = zlib:open(),
     ok = zlib:deflateInit(Zlib, Level),
     {ok, Ssh#ssh{compress_ctx = Zlib}}.
 
-
 compress_final(#ssh{compress = none} = Ssh) ->
     {ok, Ssh};
 compress_final(#ssh{compress = zlib, compress_ctx = Context} = Ssh) ->
+    zlib:close(Context),
+    {ok, Ssh#ssh{compress = none, compress_ctx = undefined}};
+compress_final(#ssh{compress = 'zlib@openssh.com', authenticated = false} = Ssh) ->
+    {ok, Ssh};
+compress_final(#ssh{compress = 'zlib@openssh.com', compress_ctx = Context, authenticated = true} = Ssh) ->
     zlib:close(Context),
     {ok, Ssh#ssh{compress = none, compress_ctx = undefined}}.
 
 compress(#ssh{compress = none} = Ssh, Data) ->
     {Ssh, Data};
 compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
+    Compressed = zlib:deflate(Context, Data, sync),
+    {Ssh, list_to_binary(Compressed)};
+compress(#ssh{compress = 'zlib@openssh.com', authenticated = false} = Ssh, Data) ->
+    {Ssh, Data};
+compress(#ssh{compress = 'zlib@openssh.com', compress_ctx = Context, authenticated = true} = Ssh, Data) ->
     Compressed = zlib:deflate(Context, Data, sync),
     {Ssh, list_to_binary(Compressed)}.
 
@@ -892,6 +907,10 @@ compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
 decompress_init(#ssh{decompress = none} = Ssh) ->
     {ok, Ssh};
 decompress_init(#ssh{decompress = zlib} = Ssh) ->
+    Zlib = zlib:open(),
+    ok = zlib:inflateInit(Zlib),
+    {ok, Ssh#ssh{decompress_ctx = Zlib}};
+decompress_init(#ssh{decompress = 'zlib@openssh.com'} = Ssh) ->
     Zlib = zlib:open(),
     ok = zlib:inflateInit(Zlib),
     {ok, Ssh#ssh{decompress_ctx = Zlib}}.
@@ -899,12 +918,22 @@ decompress_init(#ssh{decompress = zlib} = Ssh) ->
 decompress_final(#ssh{decompress = none} = Ssh) ->
     {ok, Ssh};
 decompress_final(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh) ->
+    zlib:close(Context),
+    {ok, Ssh#ssh{decompress = none, decompress_ctx = undefined}};
+decompress_final(#ssh{decompress = 'zlib@openssh.com', authenticated = false} = Ssh) ->
+    {ok, Ssh};
+decompress_final(#ssh{decompress = 'zlib@openssh.com', decompress_ctx = Context, authenticated = true} = Ssh) ->
     zlib:close(Context),
     {ok, Ssh#ssh{decompress = none, decompress_ctx = undefined}}.
 
 decompress(#ssh{decompress = none} = Ssh, Data) ->
     {Ssh, Data};
 decompress(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh, Data) ->
+    Decompressed = zlib:inflate(Context, Data),
+    {Ssh, list_to_binary(Decompressed)};
+decompress(#ssh{decompress = 'zlib@openssh.com', authenticated = false} = Ssh, Data) ->
+    {Ssh, Data};
+decompress(#ssh{decompress = 'zlib@openssh.com', decompress_ctx = Context, authenticated = true} = Ssh, Data) ->
     Decompressed = zlib:inflate(Context, Data),
     {Ssh, list_to_binary(Decompressed)}.
 
-- 
cgit v1.2.3


From 4f0f336665ea63a7865881e1f41e435de4342077 Mon Sep 17 00:00:00 2001
From: Fredrik Gustafsson <fredrik@erlang.org>
Date: Tue, 20 Aug 2013 15:56:11 +0200
Subject: ssh: added basic connection testcase for openssh zlib

---
 lib/ssh/test/ssh_basic_SUITE.erl | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

(limited to 'lib')

diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 93029c5038..0aa60624bf 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -48,8 +48,8 @@ all() ->
      close].
 
 groups() -> 
-    [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey]},
-     {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey]},
+    [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]},
+     {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]},
      {dsa_pass_key, [], [pass_phrase]},
      {rsa_pass_key, [], [pass_phrase]},
      {internal_error, [], [internal_error]}
@@ -493,7 +493,24 @@ close(Config) when is_list(Config) ->
     
     exit(CM, {shutdown, normal}),
     ok = ssh:close(CM).
-    
+
+openssh_zlib_basic_test() ->
+    [{doc, "Test basic connection with openssh_zlib"}].
+openssh_zlib_basic_test(Config) ->
+    SystemDir = filename:join(?config(priv_dir, Config), system),
+    UserDir = ?config(priv_dir, Config),
+
+    {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+					     {user_dir, UserDir},
+					     {failfun, fun ssh_test_lib:failfun/2}]),
+    ConnectionRef =
+	ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+					  {user_dir, UserDir},
+					  {user_interaction, false},
+					  {compression, openssh_zlib}]),
+    ok = ssh:close(ConnectionRef),
+    ssh:stop_daemon(Pid).
+
 %%--------------------------------------------------------------------
 %% Internal functions ------------------------------------------------
 %%--------------------------------------------------------------------
-- 
cgit v1.2.3