diff options
Diffstat (limited to 'lib/ssh/test')
45 files changed, 1546 insertions, 470 deletions
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 21359a0386..e221e94075 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2017. All Rights Reserved. +# Copyright Ericsson AB 2004-2018. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -34,11 +34,12 @@ VSN=$(GS_VSN) MODULES= \ ssh_algorithms_SUITE \ ssh_options_SUITE \ - ssh_renegotiate_SUITE \ ssh_basic_SUITE \ ssh_bench_SUITE \ + ssh_chan_behaviours_SUITE \ ssh_compat_SUITE \ ssh_connection_SUITE \ + ssh_dbg_SUITE \ ssh_engine_SUITE \ ssh_protocol_SUITE \ ssh_property_test_SUITE \ @@ -53,6 +54,8 @@ MODULES= \ ssh_key_cb_options \ ssh_key_cb_engine_keys \ ssh_trpt_test_lib \ + ssh_chan_behaviours_client \ + ssh_chan_behaviours_server \ ssh_echo_server \ ssh_bench_dev_null \ ssh_peername_sockname_server \ @@ -136,6 +139,6 @@ release_tests_spec: opt $(INSTALL_DATA) ssh.spec ssh_bench.spec ssh.cover "$(RELSYSDIR)" $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" - @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) + @tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -) release_docs_spec: diff --git a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl index 19e2754eba..6d0d8f5d99 100644 --- a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl +++ b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/ssh/test/property_test/ssh_eqc_subsys.erl b/lib/ssh/test/property_test/ssh_eqc_subsys.erl index 30b254b9c0..087b3ebfa7 100644 --- a/lib/ssh/test/property_test/ssh_eqc_subsys.erl +++ b/lib/ssh/test/property_test/ssh_eqc_subsys.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ -module(ssh_eqc_subsys). --behaviour(ssh_daemon_channel). +-behaviour(ssh_server_channel). -export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]). diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index de6e448ebd..5e589e585f 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{seconds,round(1.5*?TIMEOUT/1000)}}]. + {timetrap,{seconds,60}}]. all() -> %% [{group,kex},{group,cipher}... etc @@ -100,7 +100,7 @@ init_per_suite(Config) -> ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]), ssh:start(), [{std_simple_sftp_size,25000} % Sftp transferred data size - | setup_pubkey(Config)] + | Config] end ). @@ -257,15 +257,14 @@ try_exec_simple_group(Group, Config) -> of _ -> ct:fail("Exec though no group available") catch - error:{badmatch,{error,"No possible diffie-hellman-group-exchange group found"}} -> ok; - error:{badmatch,{error,"Connection closed"}} -> ok + error:{badmatch,{error,"Key exchange failed"}} -> ok end. %%-------------------------------------------------------------------- %% Testing all default groups simple_exec_groups() -> - [{timetrap,{seconds,120}}]. + [{timetrap,{seconds,180}}]. simple_exec_groups(Config) -> Sizes = interpolate( public_key:dh_gex_group_sizes() ), @@ -460,17 +459,6 @@ pubkey_opts(Config) -> {system_dir, SystemDir}]. -setup_pubkey(Config) -> - DataDir = proplists:get_value(data_dir, Config), - UserDir = proplists:get_value(priv_dir, Config), - Keys = - [ssh_test_lib:setup_dsa(DataDir, UserDir), - ssh_test_lib:setup_rsa(DataDir, UserDir), - ssh_test_lib:setup_ecdsa("256", DataDir, UserDir) - ], - ssh_test_lib:write_auth_keys(Keys, UserDir), % 'authorized_keys' shall contain ALL pub keys - Config. - setup_pubkey(Alg, Config) -> DataDir = proplists:get_value(data_dir, Config), UserDir = proplists:get_value(priv_dir, Config), diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 365f25fabb..778ae1e7b6 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -28,60 +28,12 @@ -include("ssh_test_lib.hrl"). %% Note: This directive should only be used in test suites. -%%-compile(export_all). - -%%% Test cases --export([ - app_test/1, - appup_test/1, - cli/1, - close/1, - daemon_already_started/1, - daemon_opt_fd/1, - multi_daemon_opt_fd/1, - double_close/1, - exec/1, - exec_compressed/1, - exec_key_differs1/1, - exec_key_differs2/1, - exec_key_differs3/1, - exec_key_differs_fail/1, - fail_daemon_start/1, - idle_time_client/1, - idle_time_server/1, - inet6_option/1, - inet_option/1, - internal_error/1, - known_hosts/1, - login_bad_pwd_no_retry1/1, - login_bad_pwd_no_retry2/1, - login_bad_pwd_no_retry3/1, - login_bad_pwd_no_retry4/1, - login_bad_pwd_no_retry5/1, - misc_ssh_options/1, - openssh_zlib_basic_test/1, - packet_size/1, - pass_phrase/1, - peername_sockname/1, - send/1, - shell/1, - shell_no_unicode/1, - shell_unicode_string/1, - ssh_info_print/1, - key_callback/1, - key_callback_options/1, - shell_exit_status/1 - ]). - -%%% Common test callbacks --export([suite/0, all/0, groups/0, - init_per_suite/1, end_per_suite/1, - init_per_group/2, end_per_group/2, - init_per_testcase/2, end_per_testcase/2 - ]). +-compile(export_all). -define(NEWLINE, <<"\r\n">>). +-define(REKEY_DATA_TMO, 1 * 60000). % Should be multiples of 60000 + %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- @@ -91,76 +43,105 @@ suite() -> {timetrap,{seconds,40}}]. all() -> - [app_test, - appup_test, - {group, dsa_key}, - {group, rsa_key}, - {group, ecdsa_sha2_nistp256_key}, - {group, ecdsa_sha2_nistp384_key}, - {group, ecdsa_sha2_nistp521_key}, - {group, dsa_pass_key}, - {group, rsa_pass_key}, - {group, ecdsa_sha2_nistp256_pass_key}, - {group, ecdsa_sha2_nistp384_pass_key}, - {group, ecdsa_sha2_nistp521_pass_key}, - {group, host_user_key_differs}, - {group, key_cb}, - {group, internal_error}, - {group, rsa_host_key_is_actualy_ecdsa}, - daemon_already_started, - double_close, - daemon_opt_fd, - multi_daemon_opt_fd, - packet_size, - ssh_info_print, - {group, login_bad_pwd_no_retry}, - shell_exit_status - ]. + [{group, all_tests}]. groups() -> - [{dsa_key, [], basic_tests()}, - {rsa_key, [], basic_tests()}, - {ecdsa_sha2_nistp256_key, [], basic_tests()}, - {ecdsa_sha2_nistp384_key, [], basic_tests()}, - {ecdsa_sha2_nistp521_key, [], basic_tests()}, + [{all_tests, [parallel], [{group, ssh_renegotiate_SUITE}, + {group, ssh_basic_SUITE} + ]}, + {ssh_basic_SUITE, [], [app_test, + appup_test, + {group, dsa_key}, + {group, rsa_key}, + {group, ecdsa_sha2_nistp256_key}, + {group, ecdsa_sha2_nistp384_key}, + {group, ecdsa_sha2_nistp521_key}, + {group, dsa_pass_key}, + {group, rsa_pass_key}, + {group, ecdsa_sha2_nistp256_pass_key}, + {group, ecdsa_sha2_nistp384_pass_key}, + {group, ecdsa_sha2_nistp521_pass_key}, + {group, host_user_key_differs}, + {group, key_cb}, + {group, internal_error}, + {group, rsa_host_key_is_actualy_ecdsa}, + daemon_already_started, + double_close, + daemon_opt_fd, + multi_daemon_opt_fd, + packet_size, + ssh_info_print, + {group, login_bad_pwd_no_retry}, + shell_exit_status + ]}, + + {ssh_renegotiate_SUITE, [parallel], [rekey0, + rekey1, + rekey2, + rekey3, + rekey4, + rekey_limit_client, + rekey_limit_daemon, + rekey_time_limit_client, + rekey_time_limit_daemon, + norekey_limit_client, + norekey_limit_daemon, + renegotiate1, + renegotiate2]}, + + {dsa_key, [], [{group, basic}]}, + {rsa_key, [], [{group, basic}]}, + {ecdsa_sha2_nistp256_key, [], [{group, basic}]}, + {ecdsa_sha2_nistp384_key, [], [{group, basic}]}, + {ecdsa_sha2_nistp521_key, [], [{group, basic}]}, {rsa_host_key_is_actualy_ecdsa, [], [fail_daemon_start]}, - {host_user_key_differs, [], [exec_key_differs1, - exec_key_differs2, - exec_key_differs3, - exec_key_differs_fail]}, + {host_user_key_differs, [parallel], [exec_key_differs1, + exec_key_differs2, + exec_key_differs3, + exec_key_differs_fail]}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {ecdsa_sha2_nistp256_pass_key, [], [pass_phrase]}, {ecdsa_sha2_nistp384_pass_key, [], [pass_phrase]}, {ecdsa_sha2_nistp521_pass_key, [], [pass_phrase]}, - {key_cb, [], [key_callback, key_callback_options]}, + {key_cb, [parallel], [key_callback, key_callback_options]}, {internal_error, [], [internal_error]}, - {login_bad_pwd_no_retry, [], [login_bad_pwd_no_retry1, - login_bad_pwd_no_retry2, - login_bad_pwd_no_retry3, - login_bad_pwd_no_retry4, - login_bad_pwd_no_retry5 - ]} + {login_bad_pwd_no_retry, [parallel], [login_bad_pwd_no_retry1, + login_bad_pwd_no_retry2, + login_bad_pwd_no_retry3, + login_bad_pwd_no_retry4, + login_bad_pwd_no_retry5 + ]}, + + {basic, [], [{group,p_basic}, + shell, shell_no_unicode, shell_unicode_string, + close, + known_hosts + ]}, + {p_basic, [parallel], [send, peername_sockname, + exec, exec_compressed, + cli, + idle_time_client, idle_time_server, openssh_zlib_basic_test, + misc_ssh_options, inet_option, inet6_option]} ]. -basic_tests() -> - [send, close, peername_sockname, - exec, exec_compressed, - shell, shell_no_unicode, shell_unicode_string, - cli, known_hosts, - idle_time_client, idle_time_server, openssh_zlib_basic_test, - misc_ssh_options, inet_option, inet6_option]. + %%-------------------------------------------------------------------- init_per_suite(Config) -> - ?CHECK_CRYPTO(Config). + ?CHECK_CRYPTO(begin + ssh:start(), + Config + end). end_per_suite(_Config) -> ssh:stop(). %%-------------------------------------------------------------------- +init_per_group(ssh_renegotiate_SUITE, Config) -> + [{preferred_algorithms, ssh:default_algorithms()} | Config]; init_per_group(dsa_key, Config) -> case lists:member('ssh-dss', ssh_transport:default_algorithms(public_key)) of @@ -414,7 +395,6 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ; PrivDir = proplists:get_value(priv_dir, Config), UserDir = proplists:get_value(priv_dir, Config), SysDir = proplists:get_value(data_dir, Config), - ssh:start(), Sftpd = {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, PrivDir}, @@ -437,7 +417,6 @@ init_per_testcase(inet6_option, Config) -> {skip,"No ipv6 interface address"} end; init_per_testcase(_TestCase, Config) -> - ssh:start(), Config. end_per_testcase(TestCase, Config) when TestCase == server_password_option; @@ -458,7 +437,6 @@ end_per_testcase(_TestCase, Config) -> end_per_testcase(Config). end_per_testcase(_Config) -> - ssh:stop(), ok. %%-------------------------------------------------------------------- @@ -480,8 +458,8 @@ misc_ssh_options(Config) when is_list(Config) -> SystemDir = filename:join(proplists:get_value(priv_dir, Config), system), UserDir = proplists:get_value(priv_dir, Config), - CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}], - CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}], + CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}, {silently_accept_hosts, true}], + CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}, {silently_accept_hosts, true}], SMiscOpt0 = [{user_dir, UserDir}, {system_dir, SystemDir}], SMiscOpt1 = [{user_dir, UserDir}, {system_dir, SystemDir}], @@ -1124,11 +1102,14 @@ packet_size(Config) -> ct:log("Try max_packet_size=~p",[MaxPacketSize]), {ok,Ch} = ssh_connection:session_channel(Conn, 1000, MaxPacketSize, 60000), ok = ssh_connection:shell(Conn, Ch), - rec(Server, Conn, Ch, MaxPacketSize) + rec(Server, Conn, Ch, MaxPacketSize), + ssh_connection:close(Conn, Ch) end, [0, 1, 10, 25]), ssh:close(Conn), - ssh:stop_daemon(Server). + ssh:stop_daemon(Server), + ok. + rec(Server, Conn, Ch, MaxSz) -> receive @@ -1141,7 +1122,9 @@ rec(Server, Conn, Ch, MaxSz) -> ssh:stop_daemon(Server), ct:fail("Does not obey max_packet_size=~p",[MaxSz]) after - 2000 -> ok + 2000 -> + ct:log("~p: ok!",[MaxSz]), + ok end. %%-------------------------------------------------------------------- @@ -1350,6 +1333,318 @@ shell_exit_status(Config) when is_list(Config) -> ssh:stop_daemon(Pid). +%%---------------------------------------------------------------------------- +%%% Idle timeout test +rekey0() -> [{timetrap,{seconds,90}}]. +rekey1() -> [{timetrap,{seconds,90}}]. +rekey2() -> [{timetrap,{seconds,90}}]. +rekey3() -> [{timetrap,{seconds,90}}]. +rekey4() -> [{timetrap,{seconds,90}}]. + +rekey0(Config) -> rekey_chk(Config, 0, 0). +rekey1(Config) -> rekey_chk(Config, infinity, 0). +rekey2(Config) -> rekey_chk(Config, {infinity,infinity}, 0). +rekey3(Config) -> rekey_chk(Config, 0, infinity). +rekey4(Config) -> rekey_chk(Config, 0, {infinity,infinity}). + +rekey_chk(Config, RLdaemon, RLclient) -> + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, [{rekey_limit, RLdaemon}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, RLclient}]), + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + + %% Make both sides send something: + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + %% Check rekeying + timer:sleep(?REKEY_DATA_TMO), + ?wait_match(false, Kex1==ssh_test_lib:get_kex_init(ConnectionRef), [], 2000, 10), + + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +%%% Test rekeying by data volume + +rekey_limit_client() -> [{timetrap,{seconds,400}}]. +rekey_limit_client(Config) -> + Limit = 6000, + UserDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(UserDir, "rekey.data"), + Data = lists:duplicate(Limit+10,1), + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, Limit}, + {max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + %% Check that it doesn't rekey without data transfer + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that datatransfer triggers rekeying + ok = ssh_sftp:write_file(SftpPid, DataFile, Data), + timer:sleep(?REKEY_DATA_TMO), + ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10), + + %% Check that datatransfer continues to trigger rekeying + ok = ssh_sftp:write_file(SftpPid, DataFile, Data), + timer:sleep(?REKEY_DATA_TMO), + ?wait_match(false, Kex2==(Kex3=ssh_test_lib:get_kex_init(ConnectionRef)), Kex3, 2000, 10), + + %% Check that it doesn't rekey without data transfer + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that it doesn't rekey on a small datatransfer + ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that it doesn't rekey without data transfer + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + + + +rekey_limit_daemon() -> [{timetrap,{seconds,400}}]. +rekey_limit_daemon(Config) -> + Limit = 6000, + UserDir = proplists:get_value(priv_dir, Config), + DataFile1 = filename:join(UserDir, "rekey1.data"), + DataFile2 = filename:join(UserDir, "rekey2.data"), + file:write_file(DataFile1, lists:duplicate(Limit+10,1)), + file:write_file(DataFile2, "hi\n"), + + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, Limit}, + {max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + %% Check that it doesn't rekey without data transfer + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + timer:sleep(?REKEY_DATA_TMO), + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + + %% Check that datatransfer triggers rekeying + {ok,_} = ssh_sftp:read_file(SftpPid, DataFile1), + timer:sleep(?REKEY_DATA_TMO), + ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10), + + %% Check that datatransfer continues to trigger rekeying + {ok,_} = ssh_sftp:read_file(SftpPid, DataFile1), + timer:sleep(?REKEY_DATA_TMO), + ?wait_match(false, Kex2==(Kex3=ssh_test_lib:get_kex_init(ConnectionRef)), Kex3, 2000, 10), + + %% Check that it doesn't rekey without data transfer + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that it doesn't rekey on a small datatransfer + {ok,_} = ssh_sftp:read_file(SftpPid, DataFile2), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that it doesn't rekey without data transfer + timer:sleep(?REKEY_DATA_TMO), + true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + + +%%-------------------------------------------------------------------- +%% Check that datatransfer in the other direction does not trigger re-keying +norekey_limit_client() -> [{timetrap,{seconds,400}}]. +norekey_limit_client(Config) -> + Limit = 6000, + UserDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(UserDir, "rekey3.data"), + file:write_file(DataFile, lists:duplicate(Limit+10,1)), + + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, Limit}, + {max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + {ok,_} = ssh_sftp:read_file(SftpPid, DataFile), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%% Check that datatransfer in the other direction does not trigger re-keying +norekey_limit_daemon() -> [{timetrap,{seconds,400}}]. +norekey_limit_daemon(Config) -> + Limit = 6000, + UserDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(UserDir, "rekey4.data"), + + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, Limit}, + {max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + ok = ssh_sftp:write_file(SftpPid, DataFile, lists:duplicate(Limit+10,1)), + timer:sleep(?REKEY_DATA_TMO), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +%%% Test rekeying by time + +rekey_time_limit_client() -> [{timetrap,{seconds,400}}]. +rekey_time_limit_client(Config) -> + Minutes = ?REKEY_DATA_TMO div 60000, + GB = 1024*1000*1000, + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, {Minutes, GB}}, + {max_random_length_padding,0}]), + rekey_time_limit(Pid, ConnectionRef). + +rekey_time_limit_daemon() -> [{timetrap,{seconds,400}}]. +rekey_time_limit_daemon(Config) -> + Minutes = ?REKEY_DATA_TMO div 60000, + GB = 1024*1000*1000, + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, {Minutes, GB}}, + {max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]), + rekey_time_limit(Pid, ConnectionRef). + + +rekey_time_limit(Pid, ConnectionRef) -> + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + + timer:sleep(5000), + true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)), + + %% Check that it rekeys when the max time + 30s has passed + timer:sleep(?REKEY_DATA_TMO + 30*1000), + ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10), + + %% Check that it does not rekey when nothing is transferred + timer:sleep(?REKEY_DATA_TMO + 30*1000), + ?wait_match(false, Kex2==ssh_test_lib:get_kex_init(ConnectionRef), [], 2000, 10), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +%%% Test rekeying with simultaneous send request + +renegotiate1(Config) -> + UserDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(UserDir, "renegotiate1.data"), + + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + + RPort = ssh_test_lib:inet_port(), + {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), + + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + + {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), + + ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), + + ssh_relay:hold(RelayPid, rx, 20, 1000), + ssh_connection_handler:renegotiate(ConnectionRef), + spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), + + timer:sleep(2000), + + Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + ssh_relay:stop(RelayPid), + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +%%% Test rekeying with inflight messages from peer + +renegotiate2(Config) -> + UserDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(UserDir, "renegotiate2.data"), + + Algs = proplists:get_value(preferred_algorithms, Config), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), + + RPort = ssh_test_lib:inet_port(), + {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), + + {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), + + ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), + + ssh_relay:hold(RelayPid, rx, 20, infinity), + spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), + %% need a small pause here to ensure ssh_sftp:write is executed + ct:sleep(10), + ssh_connection_handler:renegotiate(ConnectionRef), + ssh_relay:release(RelayPid, rx), + + timer:sleep(2000), + + Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + ssh_relay:stop(RelayPid), + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl index b6c6147646..441cf97234 100644 --- a/lib/ssh/test/ssh_bench_SUITE.erl +++ b/lib/ssh/test/ssh_bench_SUITE.erl @@ -65,10 +65,10 @@ init_per_suite(Config) -> {preferred_algorithms, Algs}, {modify_algorithms,[{prepend,[{cipher,[none]}, {mac,[none]} - ]}, - {rm, [{cipher,['[email protected]', - '[email protected]']} - ]} + ]} + %% ,{rm, [{cipher,['[email protected]', + %% '[email protected]']} + %% ]} ]}, {max_random_length_padding, 0}, {subsystems, [{"/dev/null", {ssh_bench_dev_null,[DataSize]}}]} @@ -152,7 +152,8 @@ transfer_text(Config) -> || {Crypto,Mac} <- [{ none, none}, {'aes128-ctr', 'hmac-sha1'}, {'aes256-ctr', 'hmac-sha1'}, -%% {'[email protected]', 'hmac-sha1'}, +{'[email protected]', 'hmac-sha1'}, +{'[email protected]', 'hmac-sha1'}, {'aes128-cbc', 'hmac-sha1'}, {'3des-cbc', 'hmac-sha1'}, {'aes128-ctr', 'hmac-sha2-256'}, @@ -182,29 +183,31 @@ gen_data(DataSz) -> %% {suite, ?MODULE}, %% {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]); connect_measure(Port, Cipher, Mac, Data, Options) -> - AES_GCM = {cipher,['[email protected]', - '[email protected]']}, + AES_GCM = {cipher, + []}, + %% ['[email protected]', + %% '[email protected]']}, AlgOpt = case {Cipher,Mac} of {none,none} -> [{modify_algorithms,[{prepend, [{cipher,[Cipher]}, - {mac,[Mac]}]}, - {rm,[AES_GCM]} + {mac,[Mac]}]} +%%% ,{rm,[AES_GCM]} ]}]; {none,_} -> - [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]}, - {rm,[AES_GCM]} + [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]} +%%% ,{rm,[AES_GCM]} ]}, {preferred_algorithms, [{mac,[Mac]}]}]; {_,none} -> - [{modify_algorithms,[{prepend, [{mac,[Mac]}]}, - {rm,[AES_GCM]} + [{modify_algorithms,[{prepend, [{mac,[Mac]}]} +%%% ,{rm,[AES_GCM]} ]}, {preferred_algorithms, [{cipher,[Cipher]}]}]; _ -> [{preferred_algorithms, [{cipher,[Cipher]}, - {mac,[Mac]}]}, - {modify_algorithms, [{rm,[AES_GCM]}]} + {mac,[Mac]}]} +%%% ,{modify_algorithms, [{rm,[AES_GCM]}]} ] end, Times = diff --git a/lib/ssh/test/ssh_bench_dev_null.erl b/lib/ssh/test/ssh_bench_dev_null.erl index 5166247714..868eea5643 100644 --- a/lib/ssh/test/ssh_bench_dev_null.erl +++ b/lib/ssh/test/ssh_bench_dev_null.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2017. All Rights Reserved. +%% Copyright Ericsson AB 2005-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ %%% Description: Example ssh server -module(ssh_bench_dev_null). --behaviour(ssh_daemon_channel). +-behaviour(ssh_server_channel). -record(state, { cm, diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE.erl b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl new file mode 100644 index 0000000000..16ed152bcd --- /dev/null +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl @@ -0,0 +1,152 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssh_chan_behaviours_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh.hrl"). +-include("ssh_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,60}}]. + +all() -> + [ + noexist_subsystem, + undefined_subsystem, + defined_subsystem, + subsystem_client + ]. + +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ?CHECK_CRYPTO( + begin + ssh:start(), + Config + end). + +end_per_suite(_Config) -> + {Time,R} = timer:tc(ssh, stop, []), + ct:log("Stop ssh: ~p ms",[(100*(Time div 1000)) / 100]), + R. + +init_per_testcase(_TC, Config) -> + SubSystems = [ + {"bad_cb", {ssh_chan_behaviours_undefined, []}}, % A non-existing file + {"ch1", {ssh_chan_behaviours_server, [self(),true]}} + ], + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, [{subsystems,SubSystems}]), + C = ssh_test_lib:std_connect(Config, Host, Port, []), + [{connref,C}, {daemon_pid,Pid}| Config]. + +end_per_testcase(_TC, Config) -> + {Time,_} = timer:tc(ssh, stop_daemon, [proplists:get_value(daemon_pid,Config)]), + ct:log("Stop daemon: ~p ms",[(100*(Time div 1000)) / 100]), + case flush() of + [] -> ok; + Msgs -> ct:pal("Unhandled messages:~n~p", [Msgs]) + end. + + +-define(EXPECT(What, Bind), + Bind = + (fun() -> + receive What -> + ct:log("~p:~p ~p got ~p",[?MODULE,?LINE,self(),What]), + Bind + after 5000 -> + ct:log("~p:~p ~p Flushed:~n~p",[?MODULE,?LINE,self(),flush()]), + ct:fail("Timeout!",[]) + end + end)() + ). + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +%% Try start a subsystem whos name is not known by the server +noexist_subsystem(Config) -> + C = proplists:get_value(connref, Config), + {ok, Ch} = ssh_connection:session_channel(C, infinity), + failure = ssh_connection:subsystem(C, Ch, "noexist", infinity), + ok = ssh_connection:close(C, Ch), + ?EXPECT({ssh_cm,C,{closed,Ch}},[]), + ok. + +%% Try to start a subsystem with a known name, but without any callback file +undefined_subsystem(Config) -> + C = proplists:get_value(connref, Config), + {ok, Ch} = ssh_connection:session_channel(C, infinity), + failure = ssh_connection:subsystem(C, Ch, "bad_cb", infinity), + ok = ssh_connection:close(C, Ch), + ?EXPECT({ssh_cm,C,{closed,Ch}},[]), % self() is instead of a proper channel handler + ok. + +%% Try to start and stop a subsystem with known name and defined callback file +defined_subsystem(Config) -> + C = proplists:get_value(connref, Config), + {ok, Ch1} = ssh_connection:session_channel(C, infinity), + + success = ssh_connection:subsystem(C, Ch1, "ch1", infinity), + IDsrv = ?EXPECT({{_Csrv,_Ch1srv}, {ssh_channel_up,_Ch1srv,_Csrv}}, {_Csrv,_Ch1srv}), + + ok = ssh_connection:close(C, Ch1), + ?EXPECT({IDsrv, {terminate,normal}}, []), + ?EXPECT({ssh_cm, C, {closed,Ch1}}, []), % self() is instead of a proper channel handler + ok. + +%% Try to start and stop a subsystem from a ssh_client_channel behviour +subsystem_client(Config) -> + C = proplists:get_value(connref, Config), + + {ok,ChRef} = ssh_chan_behaviours_client:start_link(C), + IDclt = ?EXPECT({{C,Ch1clt}, {ssh_channel_up,Ch1clt,C}}, {C,Ch1clt}), + IDsrv = ?EXPECT({{_Csrv,Ch1srv}, {ssh_channel_up,Ch1srv,_Csrv}}, {_Csrv,Ch1srv}), + + ok = ssh_chan_behaviours_client:stop(ChRef), + ?EXPECT({IDclt, {terminate,normal}}, []), % From the proper channel handler + ?EXPECT({IDsrv, {terminate,normal}}, []), + ok. + +%%%================================================================ +%%% +%%% + +flush() -> lists:reverse(flush([])). + +flush(Acc) -> + receive + M -> + flush([M|Acc]) + after 0 -> + Acc + end. + diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key index 51ab6fbd88..51ab6fbd88 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key.pub index 4dbb1305b0..4dbb1305b0 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key.pub diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key new file mode 100644 index 0000000000..fb1a862ded --- /dev/null +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw +mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3 +CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7 +Hneb/99fIYopdMH5NMnk60zGO1uZ2vc= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub new file mode 100644 index 0000000000..428d5fb7d7 --- /dev/null +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key index 79968bdd7d..79968bdd7d 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key.pub index 75d2025c71..75d2025c71 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub +++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key.pub diff --git a/lib/ssh/test/ssh_chan_behaviours_client.erl b/lib/ssh/test/ssh_chan_behaviours_client.erl new file mode 100644 index 0000000000..15f17733d6 --- /dev/null +++ b/lib/ssh/test/ssh_chan_behaviours_client.erl @@ -0,0 +1,143 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2018. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +%%% Description: Example ssh client +-module(ssh_chan_behaviours_client). +-behaviour(ssh_client_channel). +-record(state, { + parent, + cm, + ch, + dbg + }). +-export([start_link/1, start/1, + stop/1, send_eof/1, + init/1, handle_msg/2, handle_ssh_msg/2, terminate/2, + code_change/3, handle_call/3, handle_cast/2 + ]). + +-define(DBG(State,Fmt,Args), + case State#state.dbg of + true -> ct:log("~p:~p ~p C=~p Ch=~p "++Fmt, + [?MODULE,?LINE,self(),State#state.cm,State#state.ch|Args]); + false -> ok + end). + + +start_link(C) -> + {ok, Ch} = ssh_connection:session_channel(C, infinity), + ssh_client_channel:start_link(C, Ch, ssh_chan_behaviours_client, [C, Ch, self(), true]). + +start(C) -> + {ok, Ch} = ssh_connection:session_channel(C, infinity), + ssh_client_channel:start(C, Ch, ssh_chan_behaviours_client, [C, Ch, self(), true]). + +send_eof(ChRef) -> + ssh_client_channel:call(ChRef, send_eof). + +stop(ChRef) -> + ssh_client_channel:call(ChRef, stop). + + +init([C, Ch, Parent, Dbg|_Exec]) -> + case ssh_connection:subsystem(C, Ch, "ch1", infinity) of + success -> + State = #state{cm = C, + ch = Ch, + parent=Parent, + dbg=Dbg}, + ?DBG(State, "callback spawned, parent = ~p", [Parent]), + {ok, State}; + + Other -> + {stop, Other} + end. + +handle_msg({ssh_channel_up, ChannelId, ConnectionManager}=M, State0) -> + State = State0#state{cm = ConnectionManager, + ch = ChannelId}, + tell_parent(M, State), + ?DBG(State, "ssh_channel_up",[]), + {ok, State}. + +handle_ssh_msg({ssh_cm, C, {data, Ch, 0, Data}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "ssh_cm data size(Data)=~p",[size(Data)]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {data, Ch, Type, Data}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "ssh_cm data Type=~p : ~p",[Type,Data]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {eof, Ch}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "eof",[]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {signal, _Ch, _SigNameStr}=Sig} = M, #state{ch=Ch,cm=C} = State) -> + %% Ignore signals according to RFC 4254 section 6.9. + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {exit_signal, Ch, _, _Error, _}=Sig}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {stop, Ch, State}; + +handle_ssh_msg({ssh_cm, C, {exit_status, Ch, _Status}=Sig}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {stop, Ch, State}. + + +handle_call(send_eof, _From,#state{ch=Ch,cm=C} = State) -> + {reply, ssh_connection:send_eof(C,Ch), State}; + +handle_call(stop, _From, State) -> + {stop, normal, ok, State}; + +handle_call(Msg, _From, State) -> + ?DBG(State, "Unknown call ~p", [Msg]), + {reply, {unknown_call,Msg}, State}. + + +terminate(Reason, State) -> + tell_parent({terminate,Reason}, State), + ?DBG(State, "terminate Reason = ~p",[Reason]). + + +handle_cast(Msg, State) -> + ?DBG(State, "Unknown cast ~p", [Msg]), + {noreply, State}. + +code_change(_OldVsn, State, _Extra) -> {ok, State}. + +%%%================================================================ +%%% +%%% + +tell_parent(Msg, #state{parent = Parent, + cm = C, + ch = Ch}) -> Parent ! {{C,Ch}, Msg}. + diff --git a/lib/ssh/test/ssh_chan_behaviours_server.erl b/lib/ssh/test/ssh_chan_behaviours_server.erl new file mode 100644 index 0000000000..1408675a6e --- /dev/null +++ b/lib/ssh/test/ssh_chan_behaviours_server.erl @@ -0,0 +1,96 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2018. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +%%% Description: Example ssh server +-module(ssh_chan_behaviours_server). +-behaviour(ssh_server_channel). +-record(state, { + parent, + cm, + ch, + dbg + }). +-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]). + +-define(DBG(State,Fmt,Args), + case State#state.dbg of + true -> ct:log("~p:~p ~p C=~p Ch=~p "++Fmt, + [?MODULE,?LINE,self(),State#state.cm,State#state.ch|Args]); + false -> ok + end). + + +init([Pid,Dbg|_Exec]) -> + {ok, #state{parent=Pid, + dbg=Dbg}}. + +handle_msg({ssh_channel_up, ChannelId, ConnectionManager}=M, State0) -> + State = State0#state{cm = ConnectionManager, + ch = ChannelId}, + tell_parent(M, State), + ?DBG(State, "ssh_channel_up",[]), + {ok, State}. + +handle_ssh_msg({ssh_cm, C, {data, Ch, 0, Data}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "ssh_cm data size(Data)=~p",[size(Data)]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {data, Ch, Type, Data}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "ssh_cm data Type=~p : ~p",[Type,Data]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {eof, Ch}}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "eof",[]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {signal, _Ch, _SigNameStr}=Sig} = M, #state{ch=Ch,cm=C} = State) -> + %% Ignore signals according to RFC 4254 section 6.9. + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {ok, State}; + +handle_ssh_msg({ssh_cm, C, {exit_signal, Ch, _, _Error, _}=Sig}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {stop, Ch, State}; + +handle_ssh_msg({ssh_cm, C, {exit_status, Ch, _Status}=Sig}=M, #state{ch=Ch,cm=C} = State) -> + tell_parent(M, State), + ?DBG(State, "~p",[Sig]), + {stop, Ch, State}. + +terminate(Reason, State) -> + tell_parent({terminate,Reason}, State), + ?DBG(State, "terminate Reason = ~p",[Reason]), + ok. + +%%%================================================================ +%%% +%%% + +tell_parent(Msg, #state{parent = Parent, + cm = C, + ch = Ch}) -> Parent ! {{C,Ch}, Msg}. + diff --git a/lib/ssh/test/ssh_compat_SUITE.erl b/lib/ssh/test/ssh_compat_SUITE.erl index f7eda1dc08..1c607bebe8 100644 --- a/lib/ssh/test/ssh_compat_SUITE.erl +++ b/lib/ssh/test/ssh_compat_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -41,8 +41,7 @@ %%-------------------------------------------------------------------- suite() -> - [%%{ct_hooks,[ts_install_cth]}, - {timetrap,{seconds,40}}]. + [{timetrap,{seconds,60}}]. all() -> %% [check_docker_present] ++ diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index 9587c0c251..778e4a5fc8 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -50,6 +50,13 @@ all() -> start_shell, start_shell_exec, start_shell_exec_fun, + start_shell_exec_fun2, + start_shell_exec_fun3, + start_shell_exec_direct_fun, + start_shell_exec_direct_fun2, + start_shell_exec_direct_fun3, + start_shell_exec_direct_fun1_error, + start_shell_exec_direct_fun1_error_type, start_shell_sock_exec_fun, start_shell_sock_daemon_exec, connect_sock_not_tcp, @@ -522,7 +529,7 @@ start_shell_exec(Config) when is_list(Config) -> {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, - {exec, {?MODULE,ssh_exec,[]}} ]), + {exec, {?MODULE,ssh_exec_echo,[]}} ]), ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user, "foo"}, @@ -535,7 +542,7 @@ start_shell_exec(Config) when is_list(Config) -> success = ssh_connection:exec(ConnectionRef, ChannelId0, "testing", infinity), receive - {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} -> + {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} -> ok after 5000 -> ct:fail("Exec Timeout") @@ -618,10 +625,49 @@ exec_erlang_term_non_default_shell(Config) when is_list(Config) -> TestResult. %%-------------------------------------------------------------------- -start_shell_exec_fun() -> - [{doc, "start shell to exec command"}]. +start_shell_exec_fun(Config) -> + do_start_shell_exec_fun(fun ssh_exec_echo/1, + "testing", <<"echo testing\r\n">>, 0, + Config). + +start_shell_exec_fun2(Config) -> + do_start_shell_exec_fun(fun ssh_exec_echo/2, + "testing", <<"echo foo testing\r\n">>, 0, + Config). + +start_shell_exec_fun3(Config) -> + do_start_shell_exec_fun(fun ssh_exec_echo/3, + "testing", <<"echo foo testing\r\n">>, 0, + Config). + +start_shell_exec_direct_fun(Config) -> + do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/1}, + "testing", <<"echo testing\n">>, 0, + Config). + +start_shell_exec_direct_fun2(Config) -> + do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/2}, + "testing", <<"echo foo testing">>, 0, + Config). + +start_shell_exec_direct_fun3(Config) -> + do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/3}, + "testing", <<"echo foo testing">>, 0, + Config). + +start_shell_exec_direct_fun1_error(Config) -> + do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo_error_return/1}, + "testing", <<"Error in \"testing\": {bad}\n">>, 1, + Config). + +start_shell_exec_direct_fun1_error_type(Config) -> + do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo_error_return_type/1}, + "testing", <<"Error in \"testing\": Bad exec-plugin return: very_bad\n">>, 1, + Config). + + -start_shell_exec_fun(Config) when is_list(Config) -> +do_start_shell_exec_fun(Fun, Command, Expect, ExpectType, Config) -> PrivDir = proplists:get_value(priv_dir, Config), UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth file:make_dir(UserDir), @@ -629,7 +675,7 @@ start_shell_exec_fun(Config) when is_list(Config) -> {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, - {exec, fun ssh_exec/1}]), + {exec, Fun}]), ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user, "foo"}, @@ -639,14 +685,19 @@ start_shell_exec_fun(Config) when is_list(Config) -> {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId0, - "testing", infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId0, Command, infinity), receive - {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} -> + {ssh_cm, ConnectionRef, {data, _ChannelId, ExpectType, Expect}} -> ok after 5000 -> - ct:fail("Exec Timeout") + receive + Other -> + ct:pal("Received other:~n~p",[Other]), + ct:fail("Unexpected response") + after 0 -> + ct:fail("Exec Timeout") + end end, ssh:close(ConnectionRef), @@ -664,7 +715,7 @@ start_shell_sock_exec_fun(Config) when is_list(Config) -> {Pid, HostD, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, - {exec, fun ssh_exec/1}]), + {exec, fun ssh_exec_echo/1}]), Host = ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(HostD)), {ok, Sock} = ssh_test_lib:gen_tcp_connect(Host, Port, [{active,false}]), @@ -680,7 +731,7 @@ start_shell_sock_exec_fun(Config) when is_list(Config) -> "testing", infinity), receive - {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} -> + {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} -> ok after 5000 -> ct:fail("Exec Timeout") @@ -704,7 +755,7 @@ start_shell_sock_daemon_exec(Config) -> {ok, _Pid} = ssh:daemon(Ss, [{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, - {exec, fun ssh_exec/1}]) + {exec, fun ssh_exec_echo/1}]) end), {ok,Sc} = gen_tcp:accept(Sl), {ok,ConnectionRef} = ssh:connect(Sc, [{silently_accept_hosts, true}, @@ -719,7 +770,7 @@ start_shell_sock_daemon_exec(Config) -> "testing", infinity), receive - {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} -> + {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} -> ok after 5000 -> ct:fail("Exec Timeout") @@ -830,7 +881,7 @@ stop_listener(Config) when is_list(Config) -> {Pid0, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, - {exec, fun ssh_exec/1}]), + {exec, fun ssh_exec_echo/1}]), ConnectionRef0 = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user, "foo"}, @@ -850,7 +901,7 @@ stop_listener(Config) when is_list(Config) -> success = ssh_connection:exec(ConnectionRef0, ChannelId0, "testing", infinity), receive - {ssh_cm, ConnectionRef0, {data, ChannelId0, 0, <<"testing\r\n">>}} -> + {ssh_cm, ConnectionRef0, {data, ChannelId0, 0, <<"echo testing\r\n">>}} -> ok after 5000 -> ct:fail("Exec Timeout") @@ -859,7 +910,7 @@ stop_listener(Config) when is_list(Config) -> case ssh_test_lib:daemon(Port, [{system_dir, SysDir}, {user_dir, UserDir}, {password, "potatis"}, - {exec, fun ssh_exec/1}]) of + {exec, fun ssh_exec_echo/1}]) of {Pid1, Host, Port} -> ConnectionRef1 = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user, "foo"}, @@ -1070,7 +1121,22 @@ start_our_shell(_User, _Peer) -> %% Don't actually loop, just exit end). -ssh_exec(Cmd) -> + +ssh_exec_echo(Cmd) -> spawn(fun() -> - io:format(Cmd ++ "\n") + io:format("echo "++Cmd ++ "\n") end). + +ssh_exec_echo(Cmd, User) -> + spawn(fun() -> + io:format(io_lib:format("echo ~s ~s\n",[User,Cmd])) + end). +ssh_exec_echo(Cmd, User, _PeerAddr) -> + ssh_exec_echo(Cmd,User). + +ssh_exec_direct_echo(Cmd) -> {ok, io_lib:format("echo ~s~n",[Cmd])}. +ssh_exec_direct_echo(Cmd, User) -> {ok, io_lib:format("echo ~s ~s",[User,Cmd])}. +ssh_exec_direct_echo(Cmd, User, _PeerAddr) -> ssh_exec_direct_echo(Cmd,User). + +ssh_exec_direct_echo_error_return(_Cmd) -> {error, {bad}}. +ssh_exec_direct_echo_error_return_type(_Cmd) -> very_bad. diff --git a/lib/ssh/test/ssh_dbg_SUITE.erl b/lib/ssh/test/ssh_dbg_SUITE.erl new file mode 100644 index 0000000000..ab7918fa90 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE.erl @@ -0,0 +1,465 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssh_dbg_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh.hrl"). +-include("ssh_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,60}}]. + +all() -> + [{group, dbg}, + {group, circ_buf} + ]. + +groups() -> + [{dbg, [], [dbg_basic, + dbg_alg_terminate, + dbg_ssh_messages, + dbg_connections, + dbg_channels]}, + {circ_buf, [], [cb_basic, + cb_print, + cb_macros_print + ]} + ]. + +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ?CHECK_CRYPTO(begin + ssh:start(), + Config + end). + +end_per_suite(_Config) -> + ssh:stop(). + +%%-------------------------------------------------------------------- +init_per_testcase(_TC, Config) -> + Config. + +end_per_testcase(_TC, Config) -> + ssh_dbg:stop(), + Config. + +%%-------------------------------------------------------------------- +-define(USR, "foo"). +-define(PWD, "bar"). + +-define(DBG_RECEIVE(ExpectPfx, Ref, C, Pid), + receive + {Ref, [_, C, ExpectPfx++_]} -> + ok + + after 5000 -> + ssh_dbg:stop(), + ssh:stop_daemon(Pid), + ct:fail("No '~s' debug message",[ExpectPfx]) + end + ). +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- + +dbg_basic(_Config) -> + L0 = ssh_dbg:start(), + true = is_pid(whereis(ssh_dbg)), + true = is_list(L0), + + {ok,L0} = ssh_dbg:on(), + {ok,L0} = ssh_dbg:on(), + + L1 = [hd(L0)], + {ok,L1} = ssh_dbg:off(tl(L0)), + + {ok,L1} = ssh_dbg:go_on(), + + {ok,[]} = ssh_dbg:off(), + {ok,[]} = ssh_dbg:off(), + + ok = ssh_dbg:stop(), + undefined = whereis(ssh_dbg). + + +%%-------------------------------------------------------------------- +dbg_alg_terminate(Config) -> + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + Ref = ssh_dbg_start(), + {ok,[alg,connections,terminate]} = ssh_dbg:on([alg,terminate,connections]), + {ok,[alg,terminate]} = ssh_dbg:off(connections), % just testing that terminate is not canceled + + Parent = self(), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{?USR,?PWD}]}, + {connectfun, fun(_,_,_) -> + Parent ! {daemon_c,Ref,self()} + end}, + {failfun, fun ssh_test_lib:failfun/2}]), + C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user,?USR}, + {password,?PWD}, + {user_interaction, false}]), + + %% Daemon connection ref (D): + D = receive + {daemon_c,Ref,D0} -> D0 + end, + ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]), + + ?DBG_RECEIVE("Negotiated algorithms:", Ref, C, Pid), + ?DBG_RECEIVE("Negotiated algorithms:", Ref, D, Pid), + + ssh:close(C), + ?DBG_RECEIVE("Connection Terminating:", Ref, C, Pid), + ?DBG_RECEIVE("Connection Terminating:", Ref, D, Pid), + + stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid). + +%%-------------------------------------------------------------------- +dbg_connections(Config) -> + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + Ref = ssh_dbg_start(), + {ok,[connections,terminate]} = ssh_dbg:on([connections, terminate]), + {ok,[connections]} = ssh_dbg:off(terminate), % Just testing that terminate doesn't cancel connections + + Parent = self(), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{?USR,?PWD}]}, + {connectfun, fun(_,_,_) -> + Parent ! {daemon_c,Ref,self()} + end}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ?DBG_RECEIVE("Starting LISTENER on ", Ref, _, Pid), + + C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user,?USR}, + {password,?PWD}, + {user_interaction, false}]), + + %% Daemon connection ref (D): + D = receive + {daemon_c,Ref,D0} -> D0 + end, + ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]), + + ?DBG_RECEIVE("Starting server connection:", Ref, D, Pid), + ?DBG_RECEIVE("Starting client connection:", Ref, C, Pid), + + ssh:close(C), + ?DBG_RECEIVE("Connection Terminating:", Ref, C, Pid), + ?DBG_RECEIVE("Connection Terminating:", Ref, D, Pid), + + stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid). + +%%-------------------------------------------------------------------- +dbg_ssh_messages(Config) -> + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + Parent = self(), + Ref = make_ref(), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{?USR,?PWD}]}, + {connectfun, fun(_,_,_) -> + Parent ! {daemon_c,Ref,self()} + end}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ssh_dbg_start(Ref), + {ok,[ssh_messages]} = ssh_dbg:on([ssh_messages]), + + C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user,?USR}, + {password,?PWD}, + {user_interaction, false}]), + + %% Daemon connection ref (D): + D = receive + {daemon_c,Ref,D0} -> D0 + end, + ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]), + + ?DBG_RECEIVE("Going to send hello message:", Ref, C, Pid), + ?DBG_RECEIVE("Received hello message:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send hello message:", Ref, D, Pid), + ?DBG_RECEIVE("Received hello message:", Ref, C, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_KEXINIT:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEXINIT:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_KEXINIT:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEXINIT:", Ref, C, Pid), + + case atom_to_list( (ssh_connection_handler:alg(C))#alg.kex ) of + "ecdh-"++_ -> + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_ECDH_INIT:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_ECDH_INIT:", Ref, D, Pid), + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_ECDH_REPLY:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_ECDH_REPLY:", Ref, C, Pid); + + "diffie-hellman-group-exchange-"++_ -> + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_REQUEST:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_REQUEST:", Ref, D, Pid), + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_GROUP:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_GROUP:", Ref, C, Pid), + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_INIT:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_INIT:", Ref, D, Pid), + ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_REPLY:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_REPLY:", Ref, C, Pid); + + "diffie-hellman-group"++_ -> + ?DBG_RECEIVE("Going to send SSH_MSG_KEXDH_INIT:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEXDH_INIT:", Ref, D, Pid), + ?DBG_RECEIVE("Going to send SSH_MSG_KEXDH_REPLY:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_KEXDH_REPLY:", Ref, C, Pid) + end, + + + ?DBG_RECEIVE("Going to send SSH_MSG_NEWKEYS:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_NEWKEYS:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_NEWKEYS:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_NEWKEYS:", Ref, C, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_SERVICE_REQUEST:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_SERVICE_REQUEST:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_SERVICE_ACCEPT:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_SERVICE_ACCEPT:", Ref, C, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_REQUEST:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_REQUEST:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_FAILURE:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_FAILURE:", Ref, C, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_REQUEST:", Ref, C, Pid), + ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_REQUEST:", Ref, D, Pid), + + ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_SUCCESS:", Ref, D, Pid), + ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_SUCCESS:", Ref, C, Pid), + + + UnexpectedMsgs = + dbg_SKIP(Ref, + [S_R ++ P ++ ":" || P <- ["SSH_MSG_USERAUTH_REQUEST", + "SSH_MSG_USERAUTH_INFO_REQUEST", + "SSH_MSG_USERAUTH_INFO_RESPONSE", + "SSH_MSG_USERAUTH_FAILURE", + "SSH_MSG_EXT_INFO" + ], + S_R <- ["Going to send ", + "Received " + ] + ]), + + ssh:close(C), + stop_and_fail_if_unhandled_dbg_msgs(UnexpectedMsgs, Ref, [C,D], Pid). + +%%-------------------------------------------------------------------- +dbg_channels(Config) -> + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + Ref = ssh_dbg_start(), + {ok,[channels,connections]} = ssh_dbg:on([connections, channels]), + + Parent = self(), + TimeoutShell = + fun() -> + io:format("TimeoutShell started!~n",[]), + timer:sleep(1000), + Parent ! {daemon_channel,Ref,self()}, + ct:log("~p TIMEOUT!",[self()]) + end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{?USR,?PWD}]}, + {connectfun, fun(_,_,_) -> + Parent ! {daemon_c,Ref,self()} + end}, + {shell, fun(_User) -> + spawn(TimeoutShell) + end + }, + {failfun, fun ssh_test_lib:failfun/2}]), + + ?DBG_RECEIVE("Starting LISTENER on ", Ref, _, Pid), + + C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user,?USR}, + {password,?PWD}, + {user_interaction, false}]), + {ok, Ch0} = ssh_connection:session_channel(C, infinity), + ok = ssh_connection:shell(C, Ch0), + + %% Daemon connection ref (D): + D = receive {daemon_c,Ref,D0} -> D0 end, + + %% Daemon channel (Dch): + Dch = receive {daemon_channel,Ref,Dch0} -> Dch0 end, + ct:log("~p:~p~nC = ~p, D=~p, Dch=~p~n~s",[?MODULE,?LINE, C, D, Dch, ssh_info:string()]), + + ?DBG_RECEIVE("Starting server connection:", Ref, D, Pid), + ?DBG_RECEIVE("Starting client connection:", Ref, C, Pid), + ?DBG_RECEIVE("Server Channel Starting:", Ref, _, Pid), + ?DBG_RECEIVE("Server Channel Terminating:", Ref, _, Pid), + + stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid). + +%%-------------------------------------------------------------------- +cb_basic(_Config) -> + %% Check that the circular buffer is disabled at start: + [] = ssh_dbg:cbuf_list(), + disabled = ssh_dbg:cbuf_in(anything), + [] = ssh_dbg:cbuf_list(), + %% Start it and enter three values, first is duplicated; + ok = ssh_dbg:cbuf_start(3), + ok = ssh_dbg:cbuf_in(v1), + ok = ssh_dbg:cbuf_in(v1), + ok = ssh_dbg:cbuf_in(v2), + ok = ssh_dbg:cbuf_in(v3), + [{v3,_,1}, {v2,_,1}, {v1,_,2}] = ssh_dbg:cbuf_list(), + %% Check that a fourth value erase the first entered: + ok = ssh_dbg:cbuf_in(v4), + [{v4,_,1}, {v3,_,1}, {v2,_,1}] = ssh_dbg:cbuf_list(), + %% Check that entering a value that is in the tail but not in the head is treated as a new value: + ok = ssh_dbg:cbuf_in(v2), + [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_list(), + %% Stop and check that the buffer is returned: + [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_stop_clear(), + %% Stopping a stopped buffer returns empty: + [] = ssh_dbg:cbuf_stop_clear(), + %% Check that a value can't be entered in a stopped buffer: + disabled = ssh_dbg:cbuf_in(v2). + +%%-------------------------------------------------------------------- +cb_print(_Config) -> + ssh_dbg:cbuf_start(), + [begin + ssh_dbg:cbuf_in(V), + ct:log("Enter ~p",[V]) + end || V <- lists:seq(1,10)], + ct:log("~s",[ssh_dbg:fmt_cbuf_items()]), + ssh_dbg:cbuf_stop_clear(). + +%%-------------------------------------------------------------------- +cb_macros_print(_Config) -> + ssh_dbg:cbuf_start(), + [begin + V = {test,V0}, + ?CIRC_BUF_IN(V), + ct:log("Enter ~p",[V]) + end || V0 <- lists:seq(1,5)], + ct:log("~s",[ssh_dbg:fmt_cbuf_items()]), + ssh_dbg:cbuf_stop_clear(). + +%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- + +ssh_dbg_start() -> + ssh_dbg_start(make_ref()). + +ssh_dbg_start(Ref) -> + Parent = self(), + [_|_] = ssh_dbg:start(fun(_F,A) -> + Parent ! {Ref,A} + end), + Ref. + +%%-------------------------------------------------------------------- +queued_msgs(Ref, Conns) -> + queued_msgs(Ref, Conns, []). + +queued_msgs(Ref, Conns, Acc) -> + receive + {Ref, [_, C, _]=Msg} -> + case is_list(Conns) andalso lists:member(C, Conns) of + true -> + queued_msgs(Ref, [Msg|Acc]); + false -> + queued_msgs(Ref, Conns, Acc) + end + after 0 -> + lists:reverse(Acc) + end. + +%%-------------------------------------------------------------------- +stop_and_fail_if_unhandled_dbg_msgs(Ref, Conns, DaemonPid) -> + stop_and_fail_if_unhandled_dbg_msgs(queued_msgs(Ref,Conns), Ref, Conns, DaemonPid). + +stop_and_fail_if_unhandled_dbg_msgs(Msgs, _Ref, _Conns, DaemonPid) -> + ssh:stop_daemon(DaemonPid), + case Msgs of + [] -> + ok; + _ -> + ct:log("Unexpected messages:~n~p",[Msgs]), + ct:fail("Unexpected messages") + end. + +%%-------------------------------------------------------------------- +dbg_SKIP(Ref, Prefixes) -> + dbg_SKIP(Ref, Prefixes, []). + +dbg_SKIP(Ref, Prefixes, UnexpectedAcc) -> + receive + {Ref, [_, _C, Msg]=M} -> + case lists:any( + fun(Pfx) -> + lists:prefix(Pfx, Msg) + end, Prefixes) of + true -> + ct:log("Skip:~n~p", [M]), + dbg_SKIP(Ref, Prefixes, UnexpectedAcc); + false -> + dbg_SKIP(Ref, Prefixes, [Msg|UnexpectedAcc]) + end + after 0 -> + lists:reverse(UnexpectedAcc) + end. + diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256 new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384 new file mode 100644 index 0000000000..fb1a862ded --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw +mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3 +CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7 +Hneb/99fIYopdMH5NMnk60zGO1uZ2vc= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub new file mode 100644 index 0000000000..428d5fb7d7 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521 new file mode 100644 index 0000000000..3e51ec2ecd --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIB8O1BFkl2HQjQLRLonEZ97da/h39DMa9/0/hvPZWAI8gUPEQcHxRx +U7b09p3Zh+EBbMFq8+1ae9ds+ZTxE4WFSvKgBwYFK4EEACOhgYkDgYYABAAlWVjq +Bzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/ +vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5 +ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub new file mode 100644 index 0000000000..017a29f4da --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAlWVjqBzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl index 5387d21efd..e039439f87 100644 --- a/lib/ssh/test/ssh_echo_server.erl +++ b/lib/ssh/test/ssh_echo_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2016. All Rights Reserved. +%% Copyright Ericsson AB 2005-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ %%% Description: Example ssh server -module(ssh_echo_server). --behaviour(ssh_daemon_channel). +-behaviour(ssh_server_channel). -record(state, { n, id, diff --git a/lib/ssh/test/ssh_engine_SUITE.erl b/lib/ssh/test/ssh_engine_SUITE.erl index c131a70973..c2e6ac1fee 100644 --- a/lib/ssh/test/ssh_engine_SUITE.erl +++ b/lib/ssh/test/ssh_engine_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index 12a85c40aa..daf62483cd 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1227,7 +1227,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> [_|_] = Connections, %% Now try one more than alowed: - ct:log("Info Report might come here...",[]), + ct:pal("Info Report expected here (if not disabled) ...",[]), try Connect(Host,Port) of _ConnectionRef1 -> @@ -1235,8 +1235,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> {fail,"Too many connections accepted"} catch error:{badmatch,{error,"Connection closed"}} -> - %% Step 2 ok: could not set up max_sessions+1 connections - %% This is expected + ct:log("Step 2 ok: could not set up too many connections. Good.",[]), %% Now stop one connection and try to open one more ok = ssh:close(hd(Connections)), try_to_connect(Connect, Host, Port, Pid) @@ -1249,16 +1248,15 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> try_to_connect(Connect, Host, Port, Pid) -> - {ok,Tref} = timer:send_after(3000, timeout_no_connection), % give the supervisors some time... + {ok,Tref} = timer:send_after(30000, timeout_no_connection), % give the supervisors some time... try_to_connect(Connect, Host, Port, Pid, Tref, 1). % will take max 3300 ms after 11 tries try_to_connect(Connect, Host, Port, Pid, Tref, N) -> try Connect(Host,Port) of _ConnectionRef1 -> - %% Step 3 ok: could set up one more connection after killing one - %% Thats good. timer:cancel(Tref), + ct:log("Step 3 ok: could set up one more connection after killing one. Thats good.",[]), ssh:stop_daemon(Pid), receive % flush. timeout_no_connection -> ok diff --git a/lib/ssh/test/ssh_peername_sockname_server.erl b/lib/ssh/test/ssh_peername_sockname_server.erl index 8731d80f62..1cc53edf6d 100644 --- a/lib/ssh/test/ssh_peername_sockname_server.erl +++ b/lib/ssh/test/ssh_peername_sockname_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ %% ssh connection. --behaviour(ssh_daemon_channel). +-behaviour(ssh_server_channel). -record(state, {}). -export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]). diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl deleted file mode 100644 index 74bbc291b2..0000000000 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ /dev/null @@ -1,237 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(ssh_renegotiate_SUITE). - --include_lib("common_test/include/ct.hrl"). --include("ssh_test_lib.hrl"). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --define(REKEY_DATA_TMO, 65000). -%%-------------------------------------------------------------------- -%% Common Test interface functions ----------------------------------- -%%-------------------------------------------------------------------- - -suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{seconds,40}}]. - -all() -> [{group,default_algs}, - {group,aes_gcm} - ]. - -groups() -> [{default_algs, [], tests()}, - {aes_gcm, [], tests()} - ]. - -tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2]. - -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - ?CHECK_CRYPTO(Config). - -end_per_suite(_Config) -> - ssh:stop(). - -%%-------------------------------------------------------------------- -init_per_group(aes_gcm, Config) -> - case lists:member({client2server,['[email protected]']}, - ssh_transport:supported_algorithms(cipher)) of - true -> - [{preferred_algorithms, [{cipher,[{client2server,['[email protected]']}, - {server2client,['[email protected]']}]}]} - | Config]; - false -> - {skip, "aes_gcm not supported"} - end; -init_per_group(_, Config) -> - [{preferred_algorithms, ssh:default_algorithms()} | Config]. - - -end_per_group(_, Config) -> - Config. - -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> - ssh:start(), - Config. - -end_per_testcase(_TestCase, _Config) -> - ssh:stop(), - ok. - -%%-------------------------------------------------------------------- -%% Test Cases -------------------------------------------------------- -%%-------------------------------------------------------------------- - -%%% Idle timeout test -rekey() -> [{timetrap,{seconds,90}}]. - -rekey(Config) -> - {Pid, Host, Port} = - ssh_test_lib:std_daemon(Config, - [{rekey_limit, 0}]), - ConnectionRef = - ssh_test_lib:std_connect(Config, Host, Port, - [{rekey_limit, 0}]), - Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), - receive - after ?REKEY_DATA_TMO -> - %%By this time rekeying would have been done - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - false = (Kex2 == Kex1), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid) - end. - -%%-------------------------------------------------------------------- - -%%% Test rekeying by data volume - -rekey_limit() -> [{timetrap,{seconds,400}}]. - -rekey_limit(Config) -> - UserDir = proplists:get_value(priv_dir, Config), - DataFile = filename:join(UserDir, "rekey.data"), - - Algs = proplists:get_value(preferred_algorithms, Config), - {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, - {preferred_algorithms,Algs}]), - - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000}, - {max_random_length_padding,0}]), - {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), - - Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), - - timer:sleep(?REKEY_DATA_TMO), - Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), - - Data = lists:duplicate(159000,1), - ok = ssh_sftp:write_file(SftpPid, DataFile, Data), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- - -%%% Test rekeying with simulataneous send request - -renegotiate1(Config) -> - UserDir = proplists:get_value(priv_dir, Config), - DataFile = filename:join(UserDir, "renegotiate1.data"), - - Algs = proplists:get_value(preferred_algorithms, Config), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, - {preferred_algorithms,Algs}]), - - RPort = ssh_test_lib:inet_port(), - {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - - - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), - {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), - - Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), - - {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), - - ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), - - ssh_relay:hold(RelayPid, rx, 20, 1000), - ssh_connection_handler:renegotiate(ConnectionRef), - spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), - - timer:sleep(2000), - - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - ssh_relay:stop(RelayPid), - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- - -%%% Test rekeying with inflight messages from peer - -renegotiate2(Config) -> - UserDir = proplists:get_value(priv_dir, Config), - DataFile = filename:join(UserDir, "renegotiate2.data"), - - Algs = proplists:get_value(preferred_algorithms, Config), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, - {preferred_algorithms,Algs}]), - - RPort = ssh_test_lib:inet_port(), - {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), - {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), - - Kex1 = ssh_test_lib:get_kex_init(ConnectionRef), - - {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), - - ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), - - ssh_relay:hold(RelayPid, rx, 20, infinity), - spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), - %% need a small pause here to ensure ssh_sftp:write is executed - ct:sleep(10), - ssh_connection_handler:renegotiate(ConnectionRef), - ssh_relay:release(RelayPid, rx), - - timer:sleep(2000), - - Kex2 = ssh_test_lib:get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - ssh_relay:stop(RelayPid), - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -%% Internal functions ------------------------------------------------ -%%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa deleted file mode 100644 index d306f8b26e..0000000000 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ -APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod -/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP -kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW -JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD -OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt -+9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e -uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX -Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE -ZU8w8Q+H7z0j+a+70x2iAw== ------END DSA PRIVATE KEY----- - diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa deleted file mode 100644 index 9d7e0dd5fb..0000000000 --- a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU -DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl -zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB -AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V -TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 -CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK -SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p -z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd -WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 -sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 -xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ -dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x -ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= ------END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index 1df55834b1..a0e3d809be 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2015-2017. All Rights Reserved. +%% Copyright Ericsson AB 2015-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -201,8 +201,6 @@ killed_acceptor_restarts(Config) -> Port2 = ssh_test_lib:daemon_port(DaemonPid2), true = (Port /= Port2), - ct:log("~s",[lists:flatten(ssh_info:string())]), - {ok,[{AccPid,ListenAddr,Port}]} = acceptor_pid(DaemonPid), {ok,[{AccPid2,ListenAddr,Port2}]} = acceptor_pid(DaemonPid2), @@ -216,23 +214,34 @@ killed_acceptor_restarts(Config) -> {user_dir, UserDir}]), [{client_version,_}] = ssh:connection_info(C1,[client_version]), + ct:log("~s",[lists:flatten(ssh_info:string())]), + %% Make acceptor restart: exit(AccPid, kill), ?wait_match(undefined, process_info(AccPid)), - %% Check it is a new acceptor: + %% Check it is a new acceptor and wait if it is not: ?wait_match({ok,[{AccPid1,ListenAddr,Port}]}, AccPid1=/=AccPid, acceptor_pid(DaemonPid), AccPid1, 500, 30), - AccPid1 =/= AccPid2, + + true = (AccPid1 =/= AccPid2), %% Connect second client and check it is alive: - {ok,C2} = ssh:connect("localhost", Port, [{silently_accept_hosts, true}, - {user_interaction, false}, - {user, ?USER}, - {password, ?PASSWD}, - {user_dir, UserDir}]), + C2 = + case ssh:connect("localhost", Port, [{silently_accept_hosts, true}, + {user_interaction, false}, + {user, ?USER}, + {password, ?PASSWD}, + {user_dir, UserDir}]) of + {ok,_C2} -> + _C2; + _Other -> + ct:log("new connect failed: ~p~n~n~s",[_Other,lists:flatten(ssh_info:string())]), + ct:fail("Re-connect failed!", []) + end, + [{client_version,_}] = ssh:connection_info(C2,[client_version]), ct:log("~s",[lists:flatten(ssh_info:string())]), @@ -247,8 +256,8 @@ killed_acceptor_restarts(Config) -> ok = ssh:stop_daemon(DaemonPid), ?wait_match(undefined, process_info(DaemonPid), 1000, 30), - {error,closed} = ssh:connection_info(C1,[client_version]), - {error,closed} = ssh:connection_info(C2,[client_version]). + ?wait_match({error,closed}, ssh:connection_info(C1,[client_version]), 1000, 5), + ?wait_match({error,closed}, ssh:connection_info(C2,[client_version]), 1000, 5). %%------------------------------------------------------------------------- shell_channel_tree(Config) -> @@ -281,7 +290,7 @@ shell_channel_tree(Config) -> {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), ok = ssh_connection:shell(ConnectionRef,ChannelId0), - ?wait_match([{_, GroupPid,worker,[ssh_channel]}], + ?wait_match([{_, GroupPid,worker,[ssh_server_channel]}], supervisor:which_children(ChannelSup), [GroupPid]), {links,GroupLinks} = erlang:process_info(GroupPid, links), @@ -330,9 +339,9 @@ chk_empty_con_daemon(Daemon) -> ?wait_match([{{server,ssh_connection_sup, _,_}, ConnectionSup, supervisor, [ssh_connection_sup]}, - {{server,ssh_channel_sup,_ ,_}, + {{server,ssh_server_channel_sup,_ ,_}, ChannelSup,supervisor, - [ssh_channel_sup]}], + [ssh_server_channel_sup]}], supervisor:which_children(SubSysSup), [ConnectionSup,ChannelSup]), ?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}], @@ -363,9 +372,9 @@ check_sshd_system_tree(Daemon, Config) -> ?wait_match([{{server,ssh_connection_sup, _,_}, ConnectionSup, supervisor, [ssh_connection_sup]}, - {{server,ssh_channel_sup,_ ,_}, + {{server,ssh_server_channel_sup,_ ,_}, ChannelSup,supervisor, - [ssh_channel_sup]}], + [ssh_server_channel_sup]}], supervisor:which_children(SubSysSup), [ConnectionSup,ChannelSup]), @@ -379,7 +388,7 @@ check_sshd_system_tree(Daemon, Config) -> ssh_sftp:start_channel(Client), - ?wait_match([{_, _,worker,[ssh_channel]}], + ?wait_match([{_, _,worker,[ssh_server_channel]}], supervisor:which_children(ChannelSup)), ssh:close(Client). diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 57ae2dbac2..416cc301db 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2017. All Rights Reserved. +%% Copyright Ericsson AB 2004-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -926,7 +926,7 @@ get_kex_init(Conn, Ref, TRef) -> end; false -> - ct:log("Not in 'connected' state: ~p",[State]), + ct:log("~p:~p Not in 'connected' state: ~p",[?MODULE,?LINE,State]), receive {reneg_timeout,Ref} -> ct:log("S = ~p", [S]), diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 9df404d7ed..334281f53b 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2017. All Rights Reserved. +%% Copyright Ericsson AB 2008-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. |