Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/ssh/src/ssh.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,6 @@ Experimental options that should not to be used in products.
-type mod_args() :: {Module::atom(), Args::list()} .
-type mod_fun_args() :: {Module::atom(), Function::atom(), Args::list()} .


%% Records
-record(address, {address,
port,
Expand Down Expand Up @@ -1469,6 +1468,6 @@ Experimental options that should not to be used in products.
(fun() ->
#{level := __Level} = logger:get_primary_config(),
__Fun(__Level)
end)()).
end)()).

-endif. % SSH_HRL defined
228 changes: 122 additions & 106 deletions lib/ssh/src/ssh_connection_handler.erl

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions lib/ssh/src/ssh_fsm.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,16 @@
%%====================================================================
%% Macros
%%====================================================================
-define(send_disconnect(Code, DetailedText, StateName, State),
ssh_connection_handler:send_disconnect(Code, DetailedText, ?MODULE, ?LINE, StateName, State)).

-define(send_disconnect(Code, Reason, DetailedText, StateName, State),
ssh_connection_handler:send_disconnect(Code, Reason, DetailedText, ?MODULE, ?LINE, StateName, State)).
-define(SEND_DISCONNECT(Code, Details, StateName, State),
ssh_connection_handler:send_disconnect(#{code => Code, state_name => StateName,
details => Details, module => ?MODULE, line => ?LINE},
State)).

-define(SEND_DISCONNECT(Code, Reason, Details, StateName, State),
ssh_connection_handler:send_disconnect(Reason,
#{code => Code, state_name => StateName,
details => Details, module => ?MODULE, line => ?LINE},
State)).

-define(CALL_FUN(Key,D), catch (?GET_OPT(Key, (D#data.ssh_params)#ssh.opts)) ).

Expand Down
11 changes: 5 additions & 6 deletions lib/ssh/src/ssh_fsm_kexinit.erl
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,9 @@ callback_mode() ->
state_enter].

%%--------------------------------------------------------------------


handle_event(Type, Event = prepare_next_packet, StateName, D) ->
ssh_connection_handler:handle_event(Type, Event, StateName, D);
handle_event(Type, Event = {send_disconnect, _, _, _, _}, StateName, D) ->
handle_event(Type, Event = {send_disconnect, _}, StateName, D) ->
ssh_connection_handler:handle_event(Type, Event, StateName, D);

%%% ######## {kexinit, client|server, init|renegotiate} ####
Expand Down Expand Up @@ -172,9 +170,10 @@ handle_event(internal, _Event, {key_exchange,_Role,init},
#data{ssh_params = #ssh{algorithms = #alg{kex_strict_negotiated = true},
send_sequence = SendSeq,
recv_sequence = RecvSeq}}) ->
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
io_lib:format("KEX strict violation: send_sequence = ~p recv_sequence = ~p",
[SendSeq, RecvSeq]));
Details =
io_lib:format("KEX strict violation: send_sequence = ~p recv_sequence = ~p",
[SendSeq, RecvSeq]),
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, Details);

%%% ######## {key_exchange_dh_gex_init, server, init|renegotiate} ####
handle_event(internal, #ssh_msg_kex_dh_gex_init{} = Msg, {key_exchange_dh_gex_init,server,ReNeg}, D) ->
Expand Down
18 changes: 8 additions & 10 deletions lib/ssh/src/ssh_fsm_userauth_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,9 @@ handle_event(internal, #ssh_msg_userauth_success{}, {userauth,client}, D0=#data{
%%---- userauth failure response to clientfrom the server
handle_event(internal, #ssh_msg_userauth_failure{}, {userauth,client}=StateName,
#data{ssh_params = #ssh{userauth_methods = []}} = D0) ->
Details = io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
{Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
StateName, D0),
?SEND_DISCONNECT(?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, Details, StateName, D0),
{stop, Shutdown, D};

handle_event(internal, #ssh_msg_userauth_failure{authentications = Methods}, StateName={userauth,client},
Expand All @@ -92,16 +91,15 @@ handle_event(internal, #ssh_msg_userauth_failure{authentications = Methods}, Sta
none ->
%% Server tells us which authentication methods that are allowed
Ssh0#ssh{userauth_methods = string:tokens(Methods, ",")};
_ ->
%% We already know...
Ssh0
end,
_ ->
%% We already know...
Ssh0
end,
case ssh_auth:userauth_request_msg(Ssh1) of
{send_disconnect, Code, Ssh} ->
Details = io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
{Shutdown, D} =
?send_disconnect(Code,
io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
StateName, D0#data{ssh_params = Ssh}),
?SEND_DISCONNECT(Code, Details, StateName, D0#data{ssh_params = Ssh}),
{stop, Shutdown, D};
{"keyboard-interactive", {Msg, Ssh}} ->
D = ssh_connection_handler:send_msg(Msg, D0#data{ssh_params = Ssh}),
Expand Down
7 changes: 3 additions & 4 deletions lib/ssh/src/ssh_fsm_userauth_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,9 @@ handle_event(internal,
%% {ServiceName, Expected, Method} when Expected =/= ServiceName -> Do what?

{ServiceName, _, _} when ServiceName =/= "ssh-connection" ->
{Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
io_lib:format("Unknown service: ~p",[ServiceName]),
StateName, D1),
Details = io_lib:format("Unknown service: ~p",[ServiceName]),
{Shutdown, D} =
?SEND_DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, Details, StateName, D1),
{stop, Shutdown, D}
end;

Expand Down
48 changes: 27 additions & 21 deletions lib/ssh/src/ssh_transport.erl
Original file line number Diff line number Diff line change
Expand Up @@ -419,16 +419,17 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
true = verify_kexinit_is_first_msg(Algorithms, Ssh, ReNeg),
Algorithms
of
Algos ->
key_exchange_first_msg(Algos#alg.kex,
Ssh#ssh{algorithms = Algos})
Algos ->
key_exchange_first_msg(Algos#alg.kex,
Ssh#ssh{algorithms = Algos})
catch
Class:Reason0 ->
Reason = ssh_lib:trim_reason(Reason0),
Msg = kexinit_error(Class, Reason, client, Own, CounterPart, Ssh),
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, Msg)
DisconnectContext = kexinit_error(Class, Reason, client, Own, CounterPart, Ssh),
?DISCONNECT_CONTEXT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, DisconnectContext)
end;


handle_kexinit_msg(#ssh_msg_kexinit{first_kex_packet_follows = CounterGuess} = CounterPart,
#ssh_msg_kexinit{} = Own,
#ssh{role = server} = Ssh, ReNeg) ->
Expand All @@ -445,10 +446,11 @@ handle_kexinit_msg(#ssh_msg_kexinit{first_kex_packet_follows = CounterGuess} = C
catch
Class:Reason0 ->
Reason = ssh_lib:trim_reason(Reason0),
Msg = kexinit_error(Class, Reason, server, Own, CounterPart, Ssh),
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, Msg)
DisconnectContext = kexinit_error(Class, Reason, server, Own, CounterPart, Ssh),
?DISCONNECT_CONTEXT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, DisconnectContext)
end.


%% RFC 4253 section 7 check if guess is wrong
is_guess_wrong(false, _, _) ->
false;
Expand All @@ -461,9 +463,9 @@ is_guess_wrong(true,
is_guess_wrong(true, _, _) ->
true.

kexinit_error(Class, Error, Role, Own, CounterPart, Ssh) ->
kexinit_error(Class, Reason, Role, Own, CounterPart, Ssh) ->
{Fmt,Args} =
case {Class,Error} of
case {Class,Reason} of
{error, {badmatch,{false,Alg}}} ->
{Txt,W,C} = alg_info(Role, Alg),
MsgFun =
Expand All @@ -479,15 +481,19 @@ kexinit_error(Class, Error, Role, Own, CounterPart, Ssh) ->
end,
?SELECT_MSG(MsgFun);
_ ->
{"Kexinit failed in ~p: ~p:~p", [Role,Class,Error]}
{"Kexinit failed in ~p: ~p:~p", [Role,Class,Reason]}
end,
try io_lib:format(Fmt, Args, [{chars_limit, ssh_lib:max_log_len(Ssh)}]) of
R -> R
catch
_:_ ->
io_lib:format("Kexinit failed in ~p: ~p:~p", [Role, Class, Error],
[{chars_limit, ssh_lib:max_log_len(Ssh)}])
end.
Details =
try io_lib:format(Fmt, Args, [{chars_limit, ssh_lib:max_log_len(Ssh)}]) of
R -> R
catch
_:_ ->
io_lib:format("Kexinit failed in ~p: ~p:~p", [Role, Class, Reason],
[{chars_limit, ssh_lib:max_log_len(Ssh)}])
end,
#{own_proposal => Own,
peer_proposal => CounterPart,
details => Details}.

alg_info(client, Alg) ->
alg_info(Alg);
Expand Down Expand Up @@ -713,10 +719,10 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min0,
keyex_info = {Min0, Max0, NBits}
}};
{error,_} ->
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
io_lib:format("No possible diffie-hellman-group-exchange group found",[],
[{chars_limit, ssh_lib:max_log_len(Opts)}])
)
Details =
io_lib:format("No possible diffie-hellman-group-exchange group found",[],
[{chars_limit, ssh_lib:max_log_len(Opts)}]),
?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, Details)
end;

handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits},
Expand Down
11 changes: 9 additions & 2 deletions lib/ssh/src/ssh_transport.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,15 @@
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(DISCONNECT(Code, DetailedText),
ssh_connection_handler:disconnect(Code, DetailedText, ?MODULE, ?LINE)).
-define(DISCONNECT_CONTEXT(__Code, __DisconnectContext0),
begin
__DisconnectContext =
maps:merge(__DisconnectContext0, #{code => __Code, module => ?MODULE, line => ?LINE}),
ssh_connection_handler:disconnect(__DisconnectContext)
end).

-define(DISCONNECT(__Code, __Msg),
?DISCONNECT_CONTEXT(__Code, #{details => __Msg})).

-define(SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, 1).
-define(SSH_DISCONNECT_PROTOCOL_ERROR, 2).
Expand Down
Loading
Loading