Skip to content

Commit 63aec63

Browse files
committed
ssh: tolerate extra ssh_msg_service_request
{userauth,server} guard added due to interoperability with clients sending extra ssh_msg_service_request (e.g. Paramiko for Python,see erlangGH-6463)
1 parent 412bff5 commit 63aec63

2 files changed

Lines changed: 48 additions & 5 deletions

File tree

lib/ssh/src/ssh_connection_handler.erl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,9 +661,12 @@ handle_event(state_timeout, no_hello_received, {hello,_Role}=StateName, D0 = #da
661661
{stop, Shutdown, D};
662662

663663

664-
%%% ######## {service_request, client|server} ####
665-
666-
handle_event(internal, Msg = #ssh_msg_service_request{name=ServiceName}, StateName = {service_request,server}, D0) ->
664+
%%% ######## {service_request, client|server} #### StateName ==
665+
%% {userauth,server} guard added due to interoperability with clients
666+
%% sending extra ssh_msg_service_request (e.g. Paramiko for Python,
667+
%% see GH-6463)
668+
handle_event(internal, Msg = #ssh_msg_service_request{name=ServiceName}, StateName, D0)
669+
when StateName == {service_request,server}; StateName == {userauth,server} ->
667670
case ServiceName of
668671
"ssh-userauth" ->
669672
Ssh0 = #ssh{session_id=SessionId} = D0#data.ssh_params,

lib/ssh/test/ssh_protocol_SUITE.erl

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@
8080
preferred_algorithms/1,
8181
service_name_length_too_large/1,
8282
service_name_length_too_short/1,
83-
client_close_after_hello/1
83+
client_close_after_hello/1,
84+
extra_ssh_msg_service_request/1
8485
]).
8586

8687
-define(NEWLINE, <<"\r\n">>).
@@ -148,7 +149,8 @@ groups() ->
148149
bad_long_service_name,
149150
bad_very_long_service_name,
150151
empty_service_name,
151-
bad_service_name_then_correct
152+
bad_service_name_then_correct,
153+
extra_ssh_msg_service_request
152154
]},
153155
{authentication, [], [client_handles_keyboard_interactive_0_pwds
154156
]},
@@ -1055,6 +1057,44 @@ client_close_after_hello(Config0) ->
10551057
{fail, no_handshakers}
10561058
end.
10571059

1060+
%%% Connect to an erlang server and pretend client sending extra
1061+
%%% ssh_msg_service_request (Paramiko client behavior)
1062+
extra_ssh_msg_service_request(Config) ->
1063+
%% Connect and negotiate keys
1064+
{ok,InitialState} = ssh_trpt_test_lib:exec(
1065+
[{set_options, [print_ops, print_seqnums, print_messages]}]
1066+
),
1067+
{ok,AfterKexState} = connect_and_kex(Config, InitialState),
1068+
%% Do the authentcation
1069+
{User,Pwd} = server_user_password(Config),
1070+
UserAuthFlow =
1071+
fun(P) ->
1072+
[{send, #ssh_msg_service_request{name = "ssh-userauth"}},
1073+
{match, #ssh_msg_service_accept{name = "ssh-userauth"}, receive_msg},
1074+
{send, #ssh_msg_userauth_request{user = User,
1075+
service = "ssh-connection",
1076+
method = "password",
1077+
data = <<?BOOLEAN(?FALSE),
1078+
?STRING(unicode:characters_to_binary(P))>>
1079+
}}]
1080+
end,
1081+
{ok,EndState} =
1082+
ssh_trpt_test_lib:exec(
1083+
UserAuthFlow("WRONG") ++
1084+
[{match, #ssh_msg_userauth_failure{_='_'}, receive_msg}] ++
1085+
UserAuthFlow(Pwd) ++
1086+
[{match, #ssh_msg_userauth_success{_='_'}, receive_msg}],
1087+
AfterKexState),
1088+
%% Disconnect
1089+
{ok,_} =
1090+
ssh_trpt_test_lib:exec(
1091+
[{send, #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
1092+
description = "End of the fun",
1093+
language = ""
1094+
}},
1095+
close_socket
1096+
], EndState),
1097+
ok.
10581098

10591099
%%%================================================================
10601100
%%%==== Internal functions ========================================

0 commit comments

Comments
 (0)