diff options
Diffstat (limited to 'lib/ssh/src')
-rw-r--r-- | lib/ssh/src/ssh.erl | 117 | ||||
-rw-r--r-- | lib/ssh/src/ssh.hrl | 1 | ||||
-rw-r--r-- | lib/ssh/src/ssh_auth.erl | 60 | ||||
-rw-r--r-- | lib/ssh/src/ssh_connection_handler.erl | 18 | ||||
-rw-r--r-- | lib/ssh/src/ssh_file.erl | 16 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 176 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.hrl | 35 |
7 files changed, 230 insertions, 193 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 049018b21c..5bde184070 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -33,7 +33,8 @@ default_algorithms/0, stop_listener/1, stop_listener/2, stop_listener/3, stop_daemon/1, stop_daemon/2, stop_daemon/3, - shell/1, shell/2, shell/3]). + shell/1, shell/2, shell/3 + ]). %%-------------------------------------------------------------------- -spec start() -> ok | {error, term()}. @@ -337,6 +338,8 @@ handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{keyboard_interact_fun, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); %%Backwards compatibility handle_option([{allow_user_interaction, Value} | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option({user_interaction, Value}) | SshOptions]); @@ -420,27 +423,67 @@ handle_ssh_option({user_interaction, Value} = Opt) when is_boolean(Value) -> Opt; handle_ssh_option({preferred_algorithms,[_|_]} = Opt) -> handle_pref_algs(Opt); -handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0, - is_integer(I2), I2>0, - is_integer(I3), I3>0 -> - {dh_gex_groups, lists:map(fun({N,G,P}) -> {N,{G,P}} end, L)}; -handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 -> - %% A string, (file name) - case file:consult(File) of - {ok, List} -> - try handle_ssh_option({dh_gex_groups,List}) of - {dh_gex_groups,_} = NewOpt -> - NewOpt - catch - _:_ -> - throw({error, {{eoptions, Opt}, "Bad format in file"}}) - end; - Error -> - throw({error, {{eoptions, Opt},{"Error reading file",Error}}}) - end; + +handle_ssh_option({dh_gex_groups,L0}) when is_list(L0) -> + {dh_gex_groups, + collect_per_size( + lists:foldl( + fun({N,G,P}, Acc) when is_integer(N),N>0, + is_integer(G),G>0, + is_integer(P),P>0 -> + [{N,{G,P}} | Acc]; + ({N,{G,P}}, Acc) when is_integer(N),N>0, + is_integer(G),G>0, + is_integer(P),P>0 -> + [{N,{G,P}} | Acc]; + ({N,GPs}, Acc) when is_list(GPs) -> + lists:foldr(fun({Gi,Pi}, Acci) when is_integer(Gi),Gi>0, + is_integer(Pi),Pi>0 -> + [{N,{Gi,Pi}} | Acci] + end, Acc, GPs) + end, [], L0))}; + +handle_ssh_option({dh_gex_groups,{Tag,File=[C|_]}}=Opt) when is_integer(C), C>0, + Tag == file ; + Tag == ssh_moduli_file -> + {ok,GroupDefs} = + case Tag of + file -> + file:consult(File); + ssh_moduli_file -> + case file:open(File,[read]) of + {ok,D} -> + try + {ok,Moduli} = read_moduli_file(D, 1, []), + file:close(D), + {ok, Moduli} + catch + _:_ -> + throw({error, {{eoptions, Opt}, "Bad format in file "++File}}) + end; + {error,enoent} -> + throw({error, {{eoptions, Opt}, "File not found:"++File}}); + {error,Error} -> + throw({error, {{eoptions, Opt}, io_lib:format("Error reading file ~s: ~p",[File,Error])}}) + end + end, + + try + handle_ssh_option({dh_gex_groups,GroupDefs}) + catch + _:_ -> + throw({error, {{eoptions, Opt}, "Bad format in file: "++File}}) + end; + + +handle_ssh_option({dh_gex_limits,{Min,Max}} = Opt) when is_integer(Min), Min>0, + is_integer(Max), Max>=Min -> + %% Server + Opt; handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0, is_integer(I), I>=Min, is_integer(Max), Max>=I -> + %% Client Opt; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; @@ -462,10 +505,14 @@ handle_ssh_option({password, Value} = Opt) when is_list(Value) -> Opt; handle_ssh_option({user_passwords, Value} = Opt) when is_list(Value)-> Opt; -handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value) -> +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,2) -> + Opt; +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) -> Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; +handle_ssh_option({keyboard_interact_fun, Value} = Opt) when is_function(Value,3) -> + Opt; handle_ssh_option({compression, Value} = Opt) when is_atom(Value) -> Opt; handle_ssh_option({exec, {Module, Function, _}} = Opt) when is_atom(Module), @@ -660,3 +707,33 @@ directory_exist_readable(Dir) -> +collect_per_size(L) -> + lists:foldr( + fun({Sz,GP}, [{Sz,GPs}|Acc]) -> [{Sz,[GP|GPs]}|Acc]; + ({Sz,GP}, Acc) -> [{Sz,[GP]}|Acc] + end, [], lists:sort(L)). + +read_moduli_file(D, I, Acc) -> + case io:get_line(D,"") of + {error,Error} -> + {error,Error}; + eof -> + {ok, Acc}; + "#" ++ _ -> read_moduli_file(D, I+1, Acc); + <<"#",_/binary>> -> read_moduli_file(D, I+1, Acc); + Data -> + Line = if is_binary(Data) -> binary_to_list(Data); + is_list(Data) -> Data + end, + try + [_Time,_Type,_Tests,_Tries,Size,G,P] = string:tokens(Line," \r\n"), + M = {list_to_integer(Size), + {list_to_integer(G), list_to_integer(P,16)} + }, + read_moduli_file(D, I+1, [M|Acc]) + catch + _:_ -> + read_moduli_file(D, I+1, Acc) + end + end. + diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index fc9d60c500..4ad936f742 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -138,6 +138,7 @@ kb_tries_left = 0, % integer(), num tries left for "keyboard-interactive" userauth_preference, available_host_keys, + pwdfun_user_state, authenticated = false }). diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 04749fcf8e..4967a2e4cd 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -174,15 +174,15 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, #ssh{opts = Opts, userauth_supported_methods = Methods} = Ssh) -> Password = unicode:characters_to_list(BinPwd), - case check_password(User, Password, Opts) of - true -> + case check_password(User, Password, Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, - partial_success = false}, Ssh)} + partial_success = false}, Ssh1)} end; handle_userauth_request(#ssh_msg_userauth_request{user = User, @@ -335,16 +335,16 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, kb_tries_left = KbTriesLeft, user = User, userauth_supported_methods = Methods} = Ssh) -> - case check_password(User, unicode:characters_to_list(Password), Opts) of - true -> + case check_password(User, unicode:characters_to_list(Password), Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, - Ssh#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} + Ssh1#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} )} end; @@ -364,6 +364,11 @@ method_preference(Algs) -> [{"publickey", ?MODULE, publickey_msg, [A]} | Acc] end, [{"password", ?MODULE, password_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []} ], Algs). @@ -387,13 +392,34 @@ user_name(Opts) -> {ok, User} end. -check_password(User, Password, Opts) -> +check_password(User, Password, Opts, Ssh) -> case proplists:get_value(pwdfun, Opts) of undefined -> Static = get_password_option(Opts, User), - Password == Static; - Cheker -> - Cheker(User, Password) + {Password == Static, Ssh}; + + Checker when is_function(Checker,2) -> + {Checker(User, Password), Ssh}; + + Checker when is_function(Checker,4) -> + #ssh{pwdfun_user_state = PrivateState, + peer = {_,PeerAddr={_,_}} + } = Ssh, + case Checker(User, Password, PeerAddr, PrivateState) of + true -> + {true,Ssh}; + false -> + {false,Ssh}; + {true,NewState} -> + {true, Ssh#ssh{pwdfun_user_state=NewState}}; + {false,NewState} -> + {false, Ssh#ssh{pwdfun_user_state=NewState}}; + disconnect -> + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, + description = + "Unable to connect using the available authentication methods", + language = ""}) + end end. get_password_option(Opts, User) -> @@ -451,14 +477,14 @@ keyboard_interact_get_responses(false, undefined, undefined, _, _, _, [Prompt|_] ssh_no_io:read_line(Prompt, Opts); %% Throws error as keyboard interaction is not allowed keyboard_interact_get_responses(true, undefined, _,IoCb, Name, Instr, PromptInfos, Opts, _) -> keyboard_interact(IoCb, Name, Instr, PromptInfos, Opts); -keyboard_interact_get_responses(true, Fun, _, Name, Instr, PromptInfos, _, _, NumPrompts) -> +keyboard_interact_get_responses(true, Fun, _Pwd, _IoCb, Name, Instr, PromptInfos, _Opts, NumPrompts) -> keyboard_interact_fun(Fun, Name, Instr, PromptInfos, NumPrompts). keyboard_interact(IoCb, Name, Instr, Prompts, Opts) -> - if Name /= "" -> IoCb:format("~s", [Name]); + if Name /= "" -> IoCb:format("~s~n", [Name]); true -> ok end, - if Instr /= "" -> IoCb:format("~s", [Instr]); + if Instr /= "" -> IoCb:format("~s~n", [Instr]); true -> ok end, lists:map(fun({Prompt, true}) -> IoCb:read_line(Prompt, Opts); diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 7fb86c1108..a2d1b5b810 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -627,14 +627,24 @@ userauth_keyboard_interactive(#ssh_msg_userauth_info_response{} = Msg, retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} - end. - + end; +userauth_keyboard_interactive(Msg = #ssh_msg_userauth_failure{}, + #state{ssh_params = Ssh0 = + #ssh{role = client, + userauth_preference = Prefs0}} + = State) -> + Prefs = [{Method,M,F,A} || {Method,M,F,A} <- Prefs0, + Method =/= "keyboard-interactive"], + userauth(Msg, State#state{ssh_params = Ssh0#ssh{userauth_preference=Prefs}}). + -userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, State) -> +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, + #state{ssh_params = #ssh{role = client}} = State) -> userauth(Msg, State); -userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, State) -> +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, + #state{ssh_params = #ssh{role = client}} = State) -> userauth(Msg, State). %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index c087ce14d7..2f16a31cba 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -221,9 +221,11 @@ do_lookup_host_key(KeyToMatch, Host, Alg, Opts) -> {ok, Fd} -> Res = lookup_host_key_fd(Fd, KeyToMatch, Host, Alg), file:close(Fd), - {ok, Res}; - {error, enoent} -> {error, not_found}; - Error -> Error + Res; + {error, enoent} -> + {error, not_found}; + Error -> + Error end. identity_key_filename('ssh-dss' ) -> "id_dsa"; @@ -242,6 +244,9 @@ lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) -> case io:get_line(Fd, '') of eof -> {error, not_found}; + {error,Error} -> + %% Rare... For example NFS errors + {error,Error}; Line -> case ssh_decode_line(Line, known_hosts) of [{Key, Attributes}] -> @@ -262,7 +267,7 @@ handle_host(Fd, KeyToMatch, Host, HostList, Key, KeyType) -> Host1 = host_name(Host), case lists:member(Host1, HostList) andalso key_match(Key, KeyType) of true when KeyToMatch == Key -> - Key; + {ok,Key}; _ -> lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) end. @@ -309,6 +314,9 @@ lookup_user_key_fd(Fd, Key) -> case io:get_line(Fd, '') of eof -> {error, not_found}; + {error,Error} -> + %% Rare... For example NFS errors + {error,Error}; Line -> case ssh_decode_line(Line, auth_keys) of [{AuthKey, _}] -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d622ec27fc..0c999b96cc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -441,19 +441,29 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey, %%% %%% diffie-hellman-group-exchange-sha1 %%% -handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, +handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min0, n = NBits, - max = Max}, - Ssh0=#ssh{opts=Opts}) when Min=<NBits, NBits=<Max -> + max = Max0}, + Ssh0=#ssh{opts=Opts}) when Min0=<NBits, NBits=<Max0 -> %% server - {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 = {Min, Max, NBits} - }}; + {Min, Max} = adjust_gex_min_max(Min0, Max0, Opts), + case public_key:dh_gex_group(Min, NBits, Max, + proplists:get_value(dh_gex_groups,Opts)) of + {ok, {_Sz, {G,P}}} -> + {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 = {Min, Max, NBits} + }}; + {error,_} -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group found", + language = ""}) + end; + handle_kex_dh_gex_request(_, _) -> throw({{error,bad_ssh_msg_kex_dh_gex_request}, #ssh_msg_disconnect{ @@ -462,6 +472,26 @@ handle_kex_dh_gex_request(_, _) -> language = ""} }). + +adjust_gex_min_max(Min0, Max0, Opts) -> + case proplists:get_value(dh_gex_limits, Opts) of + undefined -> + {Min0, Max0}; + {Min1, Max1} -> + Min2 = max(Min0, Min1), + Max2 = min(Max0, Max1), + if + Min2 =< Max2 -> + {Min2, Max2}; + Max2 < Min2 -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group possible", + language = ""}) + end + end. + + handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> %% client {Public, Private} = generate_key(dh, [P,G]), @@ -563,10 +593,11 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) -> %% at server Curve = ecdh_curve(Kex), - case ecdh_validate_public_key(PeerPublic, Curve) of - true -> - {MyPublic, MyPrivate} = generate_key(ecdh, Curve), - K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + {MyPublic, MyPrivate} = generate_key(ecdh, Curve), + try + compute_key(ecdh, PeerPublic, MyPrivate, Curve) + of + K -> MyPrivHostKey = get_host_key(Ssh0), MyPubHostKey = extract_public_key(MyPrivHostKey), H = kex_h(Ssh0, Curve, MyPubHostKey, PeerPublic, MyPublic, K), @@ -579,9 +610,9 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, {ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve}, shared_secret = K, exchanged_hash = H, - session_id = sid(Ssh1, H)}}; - - false -> + session_id = sid(Ssh1, H)}} + catch + _:_ -> throw({{error,invalid_peer_public_key}, #ssh_msg_disconnect{ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, @@ -596,9 +627,10 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0 ) -> %% at client - case ecdh_validate_public_key(PeerPublic, Curve) of - true -> - K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + try + compute_key(ecdh, PeerPublic, MyPrivate, Curve) + of + K -> H = kex_h(Ssh0, Curve, PeerPubHostKey, MyPublic, PeerPublic, K), case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> @@ -613,9 +645,9 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, description = "Key exchange failed", language = ""} }) - end; - - false -> + end + catch + _:_ -> throw({{error,invalid_peer_public_key}, #ssh_msg_disconnect{ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, @@ -626,62 +658,6 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, %%%---------------------------------------------------------------- -%%% -%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1 -%%% Section 3.2.2.1 -%%% - -ecdh_validate_public_key(Key, Curve) -> - case key_size(Curve) of - undefined -> - false; - - Sz -> - case dec_key(Key, Sz) of - {ok,Q} -> - case crypto:ec_curve(Curve) of - {{prime_field,P}, {A, B, _Seed}, - _P0Bin, _OrderBin, _CoFactorBin} -> - on_curve(Q, bin2int(A), bin2int(B), bin2int(P)) - end; - - {error,compressed_not_implemented} -> % Be a bit generous... - true; - - _Error -> - false - end - end. - - -on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1), - 0 =< Y,Y =< (P-1) -> - %% Section 3.2.2.1, point 2 - (Y*Y) rem P == (X*X*X + A*X + B) rem P; -on_curve(_, _, _, _) -> - false. - - -bin2int(B) -> - Sz = erlang:bit_size(B), - <<I:Sz/big-unsigned-integer>> = B, - I. - -key_size(secp256r1) -> 256; -key_size(secp384r1) -> 384; -key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits. -key_size(_) -> undefined. - - -dec_key(Key, NBits) -> - Size = 8 + 2*NBits, - case <<Key:Size>> of - <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}}; - <<4:8, _/binary>> -> {error,bad_format}; - _ -> {error,compressed_not_implemented} - end. - -%%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> try install_alg(Ssh0) of #ssh{} = Ssh -> @@ -1482,44 +1458,10 @@ peer_name({Host, _}) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dh_group('diffie-hellman-group1-sha1') -> element(2, ?dh_group1); -dh_group('diffie-hellman-group14-sha1') -> element(2, ?dh_group14). - -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. - {_Size,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=<I,I=<Max, % a) {I,G} fullfills the requirements - I>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 - end. - +dh_group('diffie-hellman-group1-sha1') -> ?dh_group1; +dh_group('diffie-hellman-group14-sha1') -> ?dh_group14. +%%%---------------------------------------------------------------- generate_key(Algorithm, Args) -> {Public,Private} = crypto:generate_key(Algorithm, Args), {crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}. diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 337f455279..fd43326f0d 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -229,40 +229,13 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% rfc 2489, ch 6.2 +%%% Size 1024 -define(dh_group1, - {1024, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}}). + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}). %%% rfc 3526, ch3 +%%% Size 2048 -define(dh_group14, - {2048, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch4 --define(dh_group15, - {3072, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch5 --define(dh_group16, - {4096, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch6 --define(dh_group17, - {6144, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch7 --define(dh_group18, - {8192, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}}). - --define(dh_default_groups, [?dh_group1, - ?dh_group14, - ?dh_group15, - ?dh_group16, - ?dh_group17, - ?dh_group18] ). + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}). -endif. % -ifdef(ssh_transport). |