From 9b9d1cfa157134d8b14aaa2de5b36db28cb8b17a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 25 Nov 2015 20:02:36 +0100 Subject: ssh: implemented server side SSH_MSG_KEX_DH_GEX_REQUEST_OLD for putty client --- lib/ssh/src/ssh_connection_handler.erl | 6 ++++++ lib/ssh/src/ssh_transport.erl | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'lib/ssh/src') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index fcd66b80c0..5b4f6081c1 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -425,6 +425,12 @@ key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg, send_msg(GexGroup, State), {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})}; +key_exchange(#ssh_msg_kex_dh_gex_request_old{} = Msg, + #state{ssh_params = #ssh{role = server} = Ssh0} = State) -> + {ok, GexGroup, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0), + send_msg(GexGroup, State), + {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})}; + key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> {ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0), diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 2b6f0a3cdc..1fbe50e758 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -427,6 +427,32 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, keyex_info = {Min, Max, NBits} }}; + +handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits}, + Ssh0=#ssh{opts=Opts}) -> + %% server + %% + %% This message was in the draft-00 of rfc4419 + %% (https://tools.ietf.org/html/draft-ietf-secsh-dh-group-exchange-00) + %% In later drafts and the rfc is "is used for backward compatibility". + %% Unfortunatly the rfc does not specify how to treat the parameter n + %% if there is no group of that modulus length :( + %% The draft-00 however specifies that n is the "... number of bits + %% the subgroup should have at least". + %% Further, it says that "Servers and clients SHOULD support groups + %% with a modulus length of k bits, where 1024 <= k <= 8192." + %% + Min = NBits, + Max = 8192, + {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)), + {Public, Private} = generate_key(dh, [P,G]), + {SshPacket, Ssh} = + ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), + {ok, SshPacket, + Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, + keyex_info = {-1, -1, NBits} % flag for kex_h hash calc + }}; + handle_kex_dh_gex_request(_, _) -> throw({{error,bad_ssh_msg_kex_dh_gex_request}, #ssh_msg_disconnect{ @@ -1286,6 +1312,9 @@ kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> L = if Min==-1; Max==-1 -> + %% flag from 'ssh_msg_kex_dh_gex_request_old' + %% It was like this before that message was supported, + %% why? Ts = [string,string,binary,binary,binary, uint32, mpint,mpint,mpint,mpint,mpint], -- cgit v1.2.3 From ecf301d7dbd173cc18f86026ecf88597b15a7c69 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 26 Nov 2015 10:45:13 +0100 Subject: ssh: Improve group selection Now it chooses the first found if no exact match. --- lib/ssh/src/ssh_transport.erl | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) (limited to 'lib/ssh/src') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 1fbe50e758..e3ee399b8e 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1378,35 +1378,23 @@ dh_gex_default_groups() -> ?dh_default_groups. dh_gex_group(Min, N, Max, undefined) -> dh_gex_group(Min, N, Max, dh_gex_default_groups()); dh_gex_group(Min, N, Max, Groups) -> - %% First try to find an exact match. If not an exact match, select the largest possible. - {_,Group} = - lists:foldl( - fun(_, {I,G}) when I==N -> - %% If we have an exact match already: use that one - {I,G}; - ({I,G}, _) when I==N -> - %% If we now found an exact match: use that very one - {I,G}; - ({I,G}, {Imax,_Gmax}) when Min=Imax -> % b) {I,G} is larger than current max - %% A group within the limits and better than the one we have - {I,G}; - (_, IGmax) -> - %% Keep the one we have - IGmax - end, {-1,undefined}, Groups), - - case Group of - undefined -> - throw(#ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "No possible diffie-hellman-group-exchange group found", - language = ""}); - _ -> - Group + %% Try to find an exact match. If not an exact match, select the first found. + case lists:keyfind(N, 1, Groups) of + {N,Grp} -> + Grp; + false -> + case lists:dropwhile(fun({I,_}) -> I < Min-1 orelse I > Max+1 end, + Groups) of + [{_,Grp}|_] -> + Grp; + [] -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group found", + language = ""}) + end end. - generate_key(Algorithm, Args) -> {Public,Private} = crypto:generate_key(Algorithm, Args), {crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}. -- cgit v1.2.3