diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 73e9b3e9980b..ecaa5432c701 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -63,6 +63,7 @@ kex_strict_violation_key_exchange/1, kex_strict_violation_new_keys/1, kex_strict_violation/1, + kex_strict_violation_2/1, kex_strict_msg_unknown/1, gex_client_init_option_groups/1, gex_client_init_option_groups_file/1, @@ -103,6 +104,18 @@ [{client2server,Ciphs}, {server2client,Ciphs}] end)() ). +-define(HARDCODED_KEXDH_REPLY, + #ssh_msg_kexdh_reply{ + public_host_key = {{{'ECPoint',<<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>}, + {namedCurve,{1,3,101,112}}}, + 'ssh-ed25519'}, + f = 18504393053016436370762156176197081926381112956345797067569792020930728564439992620494295053804030674742529174859108487694089045521619258420515443400605141150065440678508889060925968846155921972385560196703381004650914261218463420313738628465563288022895912907728767735629532940627575655703806353550720122093175255090704443612257683903495753071530605378193139909567971489952258218767352348904221407081210633467414579377014704081235998044497191940270966762124544755076128392259615566530695493013708460088312025006678879288856957348606386230195080105197251789635675011844976120745546472873505352732719507783227210178188, + h_sig = <<90,247,44,240,136,196,82,215,56,165,53,33,230,101,253, + 34,112,201,21,131,162,169,10,129,174,14,69,25,39,174, + 92,210,130,249,103,2,215,245,7,213,110,235,136,134,11, + 124,248,139,79,17,225,77,125,182,204,84,137,167,99,186, + 167,42,192,10>>}). + %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- @@ -147,6 +160,7 @@ groups() -> kex_strict_violation_key_exchange, kex_strict_violation_new_keys, kex_strict_violation, + kex_strict_violation_2, kex_strict_msg_unknown]}, {service_requests, [], [bad_service_name, bad_long_service_name, @@ -406,7 +420,7 @@ early_rce(Config) -> DataReq = <>)>>, SshMsgChannelRequest = ssh_connection:channel_request_msg(Id, TypeReq, WantReply, DataReq), - {ok,_} = + {ok, _AfterKexState} = ssh_trpt_test_lib:exec( [{connect, ssh_test_lib:server_host(Config),ssh_test_lib:server_port(Config), @@ -1128,20 +1142,8 @@ kex_strict_violation_new_keys(Config) -> %% Connect to an erlang server and inject unexpected SSH message %% duplicated KEXINIT kex_strict_violation(Config) -> - KexDhReply = - #ssh_msg_kexdh_reply{ - public_host_key = {{{'ECPoint',<<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>}, - {namedCurve,{1,3,101,112}}}, - 'ssh-ed25519'}, - f = 18504393053016436370762156176197081926381112956345797067569792020930728564439992620494295053804030674742529174859108487694089045521619258420515443400605141150065440678508889060925968846155921972385560196703381004650914261218463420313738628465563288022895912907728767735629532940627575655703806353550720122093175255090704443612257683903495753071530605378193139909567971489952258218767352348904221407081210633467414579377014704081235998044497191940270966762124544755076128392259615566530695493013708460088312025006678879288856957348606386230195080105197251789635675011844976120745546472873505352732719507783227210178188, - h_sig = <<90,247,44,240,136,196,82,215,56,165,53,33,230,101,253, - 34,112,201,21,131,162,169,10,129,174,14,69,25,39,174, - 92,210,130,249,103,2,215,245,7,213,110,235,136,134,11, - 124,248,139,79,17,225,77,125,182,204,84,137,167,99,186, - 167,42,192,10>>}, TestFlows = - [ - {kexinit, "KEX strict violation", + [{kexinit, "KEX strict violation", [receive_hello, {send, hello}, {send, ssh_msg_kexinit}, @@ -1181,20 +1183,8 @@ kex_strict_violation(Config) -> {send, ssh_msg_kexinit}, {match, #ssh_msg_kexinit{_='_'}, receive_msg}, %% client should not send message below - {send, KexDhReply}, - {match, disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED), receive_msg}]}, - {wrong_role2, "KEX strict violation", - [receive_hello, - {send, hello}, - {send, ssh_msg_kexinit}, - {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, ssh_msg_kexdh_init}, - {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, - %% client should not send message below - {send, KexDhReply}, - {match, #ssh_msg_newkeys{_='_'}, receive_msg}, - {match, disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED), receive_msg}]} - ], + {send, ?HARDCODED_KEXDH_REPLY}, + {match, disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED), receive_msg}]}], TestProcedure = fun({Msg, _, P}) -> ct:log( @@ -1207,6 +1197,58 @@ kex_strict_violation(Config) -> ct:log("==== END ====="), ok. +kex_strict_violation_2(Config) -> + ExpectedReason = "KEX strict violation", + {ok, TestRef} = ssh_test_lib:add_log_handler(), + Level = ssh_test_lib:get_log_level(), + ssh_test_lib:set_log_level(debug), + %% Connect and negotiate keys + {ok, InitialState} = ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}]), + {ok, UpToUnexpectedKexDHReply} = + ssh_trpt_test_lib:exec( + [{connect, + ssh_test_lib:server_host(Config),ssh_test_lib:server_port(Config), + [{preferred_algorithms,[{kex,[?DEFAULT_KEX]}, + {cipher,?DEFAULT_CIPHERS} + ]}, + {silently_accept_hosts, true}, + {recv_ext_info, false}, + {user_dir, user_dir(Config)}, + {user_interaction, false} + | proplists:get_value(extra_options,Config,[]) + ]}] ++ + [receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_init}, + {match, #ssh_msg_kexdh_reply{_='_'}, receive_msg}, + %% client should not send message below + {send, ?HARDCODED_KEXDH_REPLY}, + {match, {'or', [#ssh_msg_newkeys{_='_'}, + disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED)]}, + receive_msg}], + InitialState), + case ssh_trpt_test_lib:return_value(UpToUnexpectedKexDHReply) of + {ssh_msg_newkeys} -> + ct:log("1st flow - extra match for disconnect needed"), + ssh_trpt_test_lib:exec( + [{match, disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED), receive_msg}], + UpToUnexpectedKexDHReply); + _ -> + ct:log("2nd flow disconnect already received") + end, + ct:sleep(100), + {ok, Events} = ssh_test_lib:get_log_events(TestRef), + ssh_test_lib:rm_log_handler(), + ct:log("Events = ~p", [Events]), + true = ssh_test_lib:kex_strict_negotiated(client, Events), + true = ssh_test_lib:kex_strict_negotiated(server, Events), + true = ssh_test_lib:event_logged(server, Events, ExpectedReason), + ssh_test_lib:set_log_level(Level), + ok. + %% Connect to an erlang server and inject unexpected non-SSH binary kex_strict_msg_unknown(Config) -> ct:log("START: ~p~n=================================", [?FUNCTION_NAME]), @@ -1228,8 +1270,7 @@ kex_strict_helper(Config, TestMessages, ExpectedReason) -> ssh_test_lib:set_log_level(debug), %% Connect and negotiate keys {ok, InitialState} = ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_seqnums, print_messages]}] - ), + [{set_options, [print_ops, print_seqnums, print_messages]}]), {ok, _AfterKexState} = ssh_trpt_test_lib:exec( [{connect, diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 622265096097..3b39285aea9e 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -26,7 +26,8 @@ -export([exec/1, exec/2, instantiate/2, format_msg/1, - server_host_port/1 + server_host_port/1, + return_value/1 ] ). @@ -816,3 +817,6 @@ opt(Flag, S, Fun) when is_function(Fun,1) -> save_prints({Fmt,Args}, S) -> S#s{prints = [{Fmt,Args}|S#s.prints]}. + +return_value(#s{return_value = ReturnValue}) -> + ReturnValue.