diff options
Diffstat (limited to 'lib/ssh/test')
-rw-r--r-- | lib/ssh/test/ssh_algorithms_SUITE.erl | 13 | ||||
-rw-r--r-- | lib/ssh/test/ssh_basic_SUITE.erl | 34 | ||||
-rw-r--r-- | lib/ssh/test/ssh_bench_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/ssh/test/ssh_connection_SUITE.erl | 64 | ||||
-rw-r--r-- | lib/ssh/test/ssh_options_SUITE.erl | 24 | ||||
-rw-r--r-- | lib/ssh/test/ssh_relay.erl | 3 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sftp_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sftpd_SUITE.erl | 10 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sup_SUITE.erl | 142 | ||||
-rw-r--r-- | lib/ssh/test/ssh_test_lib.erl | 127 | ||||
-rw-r--r-- | lib/ssh/test/ssh_to_openssh_SUITE.erl | 28 | ||||
-rw-r--r-- | lib/ssh/test/ssh_trpt_test_lib.erl | 3 |
13 files changed, 350 insertions, 108 deletions
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 6f75d83c4a..2990d1e02a 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -235,13 +235,12 @@ sshc_simple_exec_os_cmd(Config) -> Parent = self(), Client = spawn( fun() -> - Cmd = lists:concat(["ssh -p ",Port, - " -C" - " -o UserKnownHostsFile=",KnownHosts, - " -o StrictHostKeyChecking=no" - " ",Host," 1+1."]), - Result = os:cmd(Cmd), - ct:log("~p~n = ~p",[Cmd, Result]), + Result = ssh_test_lib:open_sshc(Host, Port, + [" -C" + " -o UserKnownHostsFile=",KnownHosts, + " -o StrictHostKeyChecking=no" + ], + " 1+1."), Parent ! {result, self(), Result, "2"} end), receive diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index cdf6cf9ae1..089d191fea 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -46,7 +46,8 @@ exec_key_differs2/1, exec_key_differs3/1, exec_key_differs_fail/1, - idle_time/1, + idle_time_client/1, + idle_time_server/1, inet6_option/1, inet_option/1, internal_error/1, @@ -139,7 +140,7 @@ basic_tests() -> exec, exec_compressed, shell, shell_no_unicode, shell_unicode_string, cli, known_hosts, - idle_time, openssh_zlib_basic_test, + idle_time_client, idle_time_server, openssh_zlib_basic_test, misc_ssh_options, inet_option, inet6_option]. @@ -522,8 +523,8 @@ exec_compressed(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -%%% Idle timeout test -idle_time(Config) -> +%%% Idle timeout test, client +idle_time_client(Config) -> SystemDir = filename:join(proplists:get_value(priv_dir, Config), system), UserDir = proplists:get_value(priv_dir, Config), @@ -544,6 +545,28 @@ idle_time(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- +%%% Idle timeout test, server +idle_time_server(Config) -> + SystemDir = filename:join(proplists:get_value(priv_dir, Config), system), + UserDir = proplists:get_value(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {idle_time, 2000}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}]), + {ok, Id} = ssh_connection:session_channel(ConnectionRef, 1000), + ssh_connection:close(ConnectionRef, Id), + receive + after 10000 -> + {error, closed} = ssh_connection:session_channel(ConnectionRef, 1000) + end, + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- %%% Test that ssh:shell/2 works shell(Config) when is_list(Config) -> process_flag(trap_exit, true), @@ -719,7 +742,8 @@ known_hosts(Config) when is_list(Config) -> Lines = string:tokens(binary_to_list(Binary), "\n"), [Line] = Lines, [HostAndIp, Alg, _KeyData] = string:tokens(Line, " "), - [Host, _Ip] = string:tokens(HostAndIp, ","), + [StoredHost, _Ip] = string:tokens(HostAndIp, ","), + true = ssh_test_lib:match_ip(StoredHost, Host), "ssh-" ++ _ = Alg, ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl index ac52bb7e28..317e50ed1d 100644 --- a/lib/ssh/test/ssh_bench_SUITE.erl +++ b/lib/ssh/test/ssh_bench_SUITE.erl @@ -98,7 +98,7 @@ end_per_testcase(_Func, _Conf) -> connect(Config) -> KexAlgs = proplists:get_value(kex, ssh:default_algorithms()), - ct:pal("KexAlgs = ~p",[KexAlgs]), + ct:log("KexAlgs = ~p",[KexAlgs]), lists:foreach( fun(KexAlg) -> PrefAlgs = preferred_algorithms(KexAlg), @@ -242,11 +242,11 @@ median(Data) when is_list(Data) -> 1 -> lists:nth(N div 2 + 1, SortedData) end, - ct:pal("median(~p) = ~p",[SortedData,Median]), + ct:log("median(~p) = ~p",[SortedData,Median]), Median. report(Data) -> - ct:pal("EventData = ~p",[Data]), + ct:log("EventData = ~p",[Data]), ct_event:notify(#event{name = benchmark_data, data = Data}). diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index 2819a4dbd9..b911cf0e9e 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -89,7 +89,7 @@ end_per_suite(Config) -> %%-------------------------------------------------------------------- init_per_group(openssh, Config) -> - case gen_tcp:connect("localhost", 22, []) of + case ssh_test_lib:gen_tcp_connect("localhost", 22, []) of {error,econnrefused} -> {skip,"No openssh deamon"}; {ok, Socket} -> @@ -126,7 +126,7 @@ simple_exec(Config) when is_list(Config) -> simple_exec_sock(_Config) -> - {ok, Sock} = gen_tcp:connect("localhost", ?SSH_DEFAULT_PORT, [{active,false}]), + {ok, Sock} = ssh_test_lib:gen_tcp_connect("localhost", ?SSH_DEFAULT_PORT, [{active,false}]), {ok, ConnectionRef} = ssh:connect(Sock, [{silently_accept_hosts, true}, {user_interaction, false}]), do_simple_exec(ConnectionRef). @@ -179,13 +179,13 @@ daemon_sock_not_tcp(_Config) -> %%-------------------------------------------------------------------- connect_sock_not_passive(_Config) -> - {ok,Sock} = gen_tcp:connect("localhost", ?SSH_DEFAULT_PORT, []), + {ok,Sock} = ssh_test_lib:gen_tcp_connect("localhost", ?SSH_DEFAULT_PORT, []), {error, not_passive_mode} = ssh:connect(Sock, []), gen_tcp:close(Sock). %%-------------------------------------------------------------------- daemon_sock_not_passive(_Config) -> - {ok,Sock} = gen_tcp:connect("localhost", ?SSH_DEFAULT_PORT, []), + {ok,Sock} = ssh_test_lib:gen_tcp_connect("localhost", ?SSH_DEFAULT_PORT, []), {error, not_passive_mode} = ssh:daemon(Sock), gen_tcp:close(Sock). @@ -585,12 +585,13 @@ start_shell_sock_exec_fun(Config) when is_list(Config) -> UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth file:make_dir(UserDir), SysDir = proplists:get_value(data_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {exec, fun ssh_exec/1}]), + {Pid, HostD, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {exec, fun ssh_exec/1}]), + Host = ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(HostD)), - {ok, Sock} = gen_tcp:connect(Host, Port, [{active,false}]), + {ok, Sock} = ssh_test_lib:gen_tcp_connect(Host, Port, [{active,false}]), {ok,ConnectionRef} = ssh:connect(Sock, [{silently_accept_hosts, true}, {user, "foo"}, {password, "morot"}, @@ -623,7 +624,7 @@ start_shell_sock_daemon_exec(Config) -> {ok,{_IP,Port}} = inet:sockname(Sl), % _IP is likely to be {0,0,0,0}. Win don't like... spawn_link(fun() -> - {ok,Ss} = gen_tcp:connect("localhost", Port, [{active,false}]), + {ok,Ss} = ssh_test_lib:gen_tcp_connect("localhost", Port, [{active,false}]), {ok, _Pid} = ssh:daemon(Ss, [{system_dir, SysDir}, {user_dir, UserDir}, {password, "morot"}, @@ -658,10 +659,10 @@ gracefull_invalid_version(Config) when is_list(Config) -> SysDir = proplists:get_value(data_dir, Config), {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}]), + {user_dir, UserDir}, + {password, "morot"}]), - {ok, S} = gen_tcp:connect(Host, Port, []), + {ok, S} = ssh_test_lib:gen_tcp_connect(Host, Port, []), ok = gen_tcp:send(S, ["SSH-8.-1","\r\n"]), receive Verstring -> @@ -680,10 +681,10 @@ gracefull_invalid_start(Config) when is_list(Config) -> file:make_dir(UserDir), SysDir = proplists:get_value(data_dir, Config), {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}]), + {user_dir, UserDir}, + {password, "morot"}]), - {ok, S} = gen_tcp:connect(Host, Port, []), + {ok, S} = ssh_test_lib:gen_tcp_connect(Host, Port, []), ok = gen_tcp:send(S, ["foobar","\r\n"]), receive Verstring -> @@ -702,10 +703,10 @@ gracefull_invalid_long_start(Config) when is_list(Config) -> file:make_dir(UserDir), SysDir = proplists:get_value(data_dir, Config), {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}]), + {user_dir, UserDir}, + {password, "morot"}]), - {ok, S} = gen_tcp:connect(Host, Port, []), + {ok, S} = ssh_test_lib:gen_tcp_connect(Host, Port, []), ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]), receive Verstring -> @@ -725,10 +726,10 @@ gracefull_invalid_long_start_no_nl(Config) when is_list(Config) -> file:make_dir(UserDir), SysDir = proplists:get_value(data_dir, Config), {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}]), + {user_dir, UserDir}, + {password, "morot"}]), - {ok, S} = gen_tcp:connect(Host, Port, []), + {ok, S} = ssh_test_lib:gen_tcp_connect(Host, Port, []), ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]), receive Verstring -> @@ -779,22 +780,21 @@ stop_listener(Config) when is_list(Config) -> ct:fail("Exec Timeout") end, - {ok, HostAddr} = inet:getaddr(Host, inet), - case ssh_test_lib:daemon(HostAddr, Port, [{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "potatis"}, - {exec, fun ssh_exec/1}]) of - {Pid1, HostAddr, Port} -> + case ssh_test_lib:daemon(Port, [{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "potatis"}, + {exec, fun ssh_exec/1}]) of + {Pid1, Host, Port} -> ConnectionRef1 = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, {user, "foo"}, {password, "potatis"}, {user_interaction, true}, {user_dir, UserDir}]), {error, _} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, true}, - {user_dir, UserDir}]), + {user, "foo"}, + {password, "morot"}, + {user_interaction, true}, + {user_dir, UserDir}]), ssh:close(ConnectionRef0), ssh:close(ConnectionRef1), ssh:stop_daemon(Pid0), diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index 758c20e2b8..344a042d79 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -868,13 +868,13 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) -> ct:log("Fingerprints(~p) = ~p",[HashAlg,FPs]), %% Start daemon with the public keys that we got fingerprints from - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {Pid, Host0, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, UserDirServer}, {password, "morot"}]), - + Host = ssh_test_lib:ntoa(Host0), FP_check_fun = fun(PeerName, FP) -> - ct:pal("PeerName = ~p, FP = ~p",[PeerName,FP]), - HostCheck = (Host == PeerName), + ct:log("PeerName = ~p, FP = ~p",[PeerName,FP]), + HostCheck = ssh_test_lib:match_ip(Host, PeerName), FPCheck = if is_atom(HashAlg) -> lists:member(FP, FPs); is_list(HashAlg) -> lists:all(fun(FP1) -> lists:member(FP1,FPs) end, @@ -1052,20 +1052,20 @@ id_string_random_client(Config) -> %%-------------------------------------------------------------------- id_string_no_opt_server(Config) -> {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, []), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,S1}=ssh_test_lib:gen_tcp_connect(Host,Port,[{active,false},{packet,line}]), {ok,"SSH-2.0-Erlang/"++Vsn} = gen_tcp:recv(S1, 0, 2000), true = expected_ssh_vsn(Vsn). %%-------------------------------------------------------------------- id_string_own_string_server(Config) -> {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,"Olle"}]), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,S1}=ssh_test_lib:gen_tcp_connect(Host,Port,[{active,false},{packet,line}]), {ok,"SSH-2.0-Olle\r\n"} = gen_tcp:recv(S1, 0, 2000). %%-------------------------------------------------------------------- id_string_random_server(Config) -> {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,random}]), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,S1}=ssh_test_lib:gen_tcp_connect(Host,Port,[{active,false},{packet,line}]), {ok,"SSH-2.0-"++Rnd} = gen_tcp:recv(S1, 0, 2000), case Rnd of "Erlang"++_ -> ct:log("Id=~p",[Rnd]), @@ -1086,11 +1086,11 @@ ssh_connect_negtimeout(Config, Parallel) -> ct:log("Parallel: ~p",[Parallel]), {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, - {parallel_login, Parallel}, - {negotiation_timeout, NegTimeOut}, - {failfun, fun ssh_test_lib:failfun/2}]), - - {ok,Socket} = gen_tcp:connect(Host, Port, []), + {parallel_login, Parallel}, + {negotiation_timeout, NegTimeOut}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok,Socket} = ssh_test_lib:gen_tcp_connect(Host, Port, []), Factor = 2, ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), diff --git a/lib/ssh/test/ssh_relay.erl b/lib/ssh/test/ssh_relay.erl index 28000fbb97..1e3810e9d4 100644 --- a/lib/ssh/test/ssh_relay.erl +++ b/lib/ssh/test/ssh_relay.erl @@ -131,7 +131,8 @@ init([ListenAddr, ListenPort, PeerAddr, PeerPort | _Options]) -> S = #state{local_addr = ListenAddr, local_port = ListenPort, lpid = LPid, - peer_addr = PeerAddr, + peer_addr = ssh_test_lib:ntoa( + ssh_test_lib:mangle_connect_address(PeerAddr)), peer_port = PeerPort }, {ok, S}; diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index acf76157a2..7efeb3a0ad 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -660,7 +660,7 @@ start_channel_sock(Config) -> {Host,Port} = proplists:get_value(peer, Config), %% Get a tcp socket - {ok, Sock} = gen_tcp:connect(Host, Port, [{active,false}]), + {ok, Sock} = ssh_test_lib:gen_tcp_connect(Host, Port, [{active,false}]), %% and open one channel on one new Connection {ok, ChPid1, Conn} = ssh_sftp:start_channel(Sock, Opts), diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index b167f98ac8..379c0bcb0a 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -151,8 +151,8 @@ init_per_testcase(TestCase, Config) -> SubSystems = [ssh_sftpd:subsystem_spec([])], ssh:daemon(0, [{subsystems, SubSystems}|Options]) end, - {ok,Dinf} = ssh:daemon_info(Sftpd), - Port = proplists:get_value(port, Dinf), + + Port = ssh_test_lib:daemon_port(Sftpd), Cm = ssh_test_lib:connect(Port, [{user_dir, ClientUserDir}, @@ -187,7 +187,7 @@ init_per_testcase(TestCase, Config) -> [{sftp, {Cm, Channel}}, {sftpd, Sftpd }| Config]. end_per_testcase(_TestCase, Config) -> - ssh_sftpd:stop(proplists:get_value(sftpd, Config)), + catch ssh:stop_daemon(proplists:get_value(sftpd, Config)), {Cm, Channel} = proplists:get_value(sftp, Config), ssh_connection:close(Cm, Channel), ssh:close(Cm), @@ -705,10 +705,10 @@ try_access(Path, Cm, Channel, ReqId) -> {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), ?UINT32(Code), Rest/binary>>, <<>>} -> case Code of ?SSH_FX_FILE_IS_A_DIRECTORY -> - ct:pal("Got the expected SSH_FX_FILE_IS_A_DIRECTORY status",[]), + ct:log("Got the expected SSH_FX_FILE_IS_A_DIRECTORY status",[]), ok; ?SSH_FX_FAILURE -> - ct:pal("Got the expected SSH_FX_FAILURE status",[]), + ct:log("Got the expected SSH_FX_FAILURE status",[]), ok; _ -> case Rest of diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index b4d7eadfa4..9b5d6b5fae 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -138,7 +138,7 @@ init_per_testcase(TestCase, Config) -> [{port, Port}, {sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig]. end_per_testcase(_TestCase, Config) -> - catch ssh_sftpd:stop(proplists:get_value(sftpd, Config)), + catch ssh:stop_daemon(proplists:get_value(sftpd, Config)), {Sftp, Connection} = proplists:get_value(sftp, Config), catch ssh_sftp:stop_channel(Sftp), catch ssh:close(Connection), diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index ff53e1c4c6..dd7c4b1473 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -41,7 +41,8 @@ suite() -> {timetrap,{seconds,100}}]. all() -> - [default_tree, sshc_subtree, sshd_subtree, sshd_subtree_profile]. + [default_tree, sshc_subtree, sshd_subtree, sshd_subtree_profile, + killed_acceptor_restarts]. groups() -> []. @@ -100,6 +101,7 @@ default_tree(Config) when is_list(Config) -> ?wait_match([], supervisor:which_children(sshc_sup)), ?wait_match([], supervisor:which_children(sshd_sup)). +%%------------------------------------------------------------------------- sshc_subtree() -> [{doc, "Make sure the sshc subtree is correct"}]. sshc_subtree(Config) when is_list(Config) -> @@ -128,27 +130,31 @@ sshc_subtree(Config) when is_list(Config) -> ssh:close(Pid2), ?wait_match([], supervisor:which_children(sshc_sup)). +%%------------------------------------------------------------------------- sshd_subtree() -> [{doc, "Make sure the sshd subtree is correct"}]. sshd_subtree(Config) when is_list(Config) -> HostIP = proplists:get_value(host_ip, Config), Port = proplists:get_value(port, Config), SystemDir = proplists:get_value(data_dir, Config), - ssh:daemon(HostIP, Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}, - {user_passwords, - [{?USER, ?PASSWD}]}]), + {ok,Daemon} = ssh:daemon(HostIP, Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}, + {user_passwords, + [{?USER, ?PASSWD}]}]), - ?wait_match([{{server,ssh_system_sup, HostIP, Port, ?DEFAULT_PROFILE}, + ct:log("Expect HostIP=~p, Port=~p, Daemon=~p",[HostIP,Port,Daemon]), + ?wait_match([{{server,ssh_system_sup, ListenIP, Port, ?DEFAULT_PROFILE}, Daemon, supervisor, [ssh_system_sup]}], supervisor:which_children(sshd_sup), - Daemon), + [ListenIP,Daemon]), + true = ssh_test_lib:match_ip(HostIP, ListenIP), check_sshd_system_tree(Daemon, Config), ssh:stop_daemon(HostIP, Port), ct:sleep(?WAIT_FOR_SHUTDOWN), ?wait_match([], supervisor:which_children(sshd_sup)). +%%------------------------------------------------------------------------- sshd_subtree_profile() -> [{doc, "Make sure the sshd subtree using profile option is correct"}]. sshd_subtree_profile(Config) when is_list(Config) -> @@ -157,34 +163,105 @@ sshd_subtree_profile(Config) when is_list(Config) -> Profile = proplists:get_value(profile, Config), SystemDir = proplists:get_value(data_dir, Config), - {ok, _} = ssh:daemon(HostIP, Port, [{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}, - {user_passwords, - [{?USER, ?PASSWD}]}, - {profile, Profile}]), - ?wait_match([{{server,ssh_system_sup, HostIP,Port,Profile}, + {ok, Daemon} = ssh:daemon(HostIP, Port, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}, + {user_passwords, + [{?USER, ?PASSWD}]}, + {profile, Profile}]), + ct:log("Expect HostIP=~p, Port=~p, Profile=~p, Daemon=~p",[HostIP,Port,Profile,Daemon]), + ?wait_match([{{server,ssh_system_sup, ListenIP,Port,Profile}, Daemon, supervisor, [ssh_system_sup]}], supervisor:which_children(sshd_sup), - Daemon), + [ListenIP,Daemon]), + true = ssh_test_lib:match_ip(HostIP, ListenIP), check_sshd_system_tree(Daemon, Config), ssh:stop_daemon(HostIP, Port, Profile), ct:sleep(?WAIT_FOR_SHUTDOWN), ?wait_match([], supervisor:which_children(sshd_sup)). +%%------------------------------------------------------------------------- +killed_acceptor_restarts(Config) -> + Profile = proplists:get_value(profile, Config), + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(userdir, Config), + {ok, DaemonPid} = ssh:daemon(0, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}, + {user_passwords, [{?USER, ?PASSWD}]}, + {profile, Profile}]), + + {ok, DaemonPid2} = ssh:daemon(0, [{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}, + {user_passwords, [{?USER, ?PASSWD}]}, + {profile, Profile}]), + + Port = ssh_test_lib:daemon_port(DaemonPid), + Port2 = ssh_test_lib:daemon_port(DaemonPid2), + true = (Port /= Port2), + + ct:pal("~s",[lists:flatten(ssh_info:string())]), + + {ok,[{AccPid,ListenAddr,Port}]} = acceptor_pid(DaemonPid), + {ok,[{AccPid2,ListenAddr,Port2}]} = acceptor_pid(DaemonPid2), + + true = (AccPid /= AccPid2), + + %% Connect first client and check it is alive: + {ok,C1} = ssh:connect("localhost", Port, [{silently_accept_hosts, true}, + {user_interaction, false}, + {user, ?USER}, + {password, ?PASSWD}, + {user_dir, UserDir}]), + [{client_version,_}] = ssh:connection_info(C1,[client_version]), + + %% Make acceptor restart: + exit(AccPid, kill), + %% Check it is a new acceptor: + {ok,[{AccPid1,ListenAddr,Port}]} = acceptor_pid(DaemonPid), + true = (AccPid /= AccPid1), + true = (AccPid2 /= AccPid1), + + %% 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}]), + [{client_version,_}] = ssh:connection_info(C2,[client_version]), + + ct:pal("~s",[lists:flatten(ssh_info:string())]), + + %% Check first client is still alive: + [{client_version,_}] = ssh:connection_info(C1,[client_version]), + + ok = ssh:stop_daemon(DaemonPid2), + timer:sleep(15000), + [{client_version,_}] = ssh:connection_info(C1,[client_version]), + [{client_version,_}] = ssh:connection_info(C2,[client_version]), + + ok = ssh:stop_daemon(DaemonPid), + timer:sleep(15000), + {error,closed} = ssh:connection_info(C1,[client_version]), + {error,closed} = ssh:connection_info(C2,[client_version]). + +%%------------------------------------------------------------------------- +%% Help functions +%%------------------------------------------------------------------------- check_sshd_system_tree(Daemon, Config) -> Host = proplists:get_value(host, Config), Port = proplists:get_value(port, Config), UserDir = proplists:get_value(userdir, Config), {ok, Client} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user_interaction, false}, - {user, ?USER}, {password, ?PASSWD},{user_dir, UserDir}]), + {user_interaction, false}, + {user, ?USER}, + {password, ?PASSWD}, + {user_dir, UserDir}]), ?wait_match([{_,SubSysSup, supervisor,[ssh_subsystem_sup]}, {{ssh_acceptor_sup,_,_,_}, AccSup, supervisor,[ssh_acceptor_sup]}], supervisor:which_children(Daemon), - [SubSysSup,AccSup]), + [SubSysSup,AccSup]), ?wait_match([{{server,ssh_connection_sup, _,_}, ConnectionSup, supervisor, @@ -208,4 +285,33 @@ check_sshd_system_tree(Daemon, Config) -> ?wait_match([{_, _,worker,[ssh_channel]}], supervisor:which_children(ChannelSup)), ssh:close(Client). - + +acceptor_pid(DaemonPid) -> + Parent = self(), + Pid = spawn(fun() -> + Parent ! {self(), supsearch, + [{AccPid,ListenAddr,Port} + + || {{server,ssh_system_sup,ListenAddr,Port,NS}, + DPid,supervisor, + [ssh_system_sup]} <- supervisor:which_children(sshd_sup), + DPid == DaemonPid, + + {{ssh_acceptor_sup,L1,P1,NS1}, + AccSupPid,supervisor, + [ssh_acceptor_sup]} <- supervisor:which_children(DaemonPid), + L1 == ListenAddr, + P1 == Port, + NS1 == NS1, + + {{ssh_acceptor_sup,L2,P2,NS2}, + AccPid,worker, + [ssh_acceptor]} <- supervisor:which_children(AccSupPid), + L2 == ListenAddr, + P2 == Port, + NS2 == NS]} + end), + receive {Pid, supsearch, L} -> {ok,L} + after 2000 -> timeout + end. + diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 1673f52821..6186d44890 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -32,15 +32,18 @@ -define(TIMEOUT, 50000). +%%%---------------------------------------------------------------- connect(Port, Options) when is_integer(Port) -> connect(hostname(), Port, Options). connect(any, Port, Options) -> connect(hostname(), Port, Options); connect(Host, Port, Options) -> + ct:log("~p:~p Calling ssh:connect(~p, ~p, ~p)",[?MODULE,?LINE,Host, Port, Options]), {ok, ConnectionRef} = ssh:connect(Host, Port, Options), ConnectionRef. +%%%---------------------------------------------------------------- daemon(Options) -> daemon(any, 0, Options). @@ -53,23 +56,57 @@ daemon(Host, Options) -> daemon(Host, Port, Options) -> ct:log("~p:~p Calling ssh:daemon(~p, ~p, ~p)",[?MODULE,?LINE,Host,Port,Options]), case ssh:daemon(Host, Port, Options) of - {ok, Pid} when Host == any -> - ct:log("ssh:daemon ok (1)",[]), - {Pid, hostname(), daemon_port(Port,Pid)}; {ok, Pid} -> - ct:log("ssh:daemon ok (2)",[]), - {Pid, Host, daemon_port(Port,Pid)}; + {ok,L} = ssh:daemon_info(Pid), + ListenPort = proplists:get_value(port, L), + ListenIP = proplists:get_value(ip, L), + {Pid, ListenIP, ListenPort}; Error -> ct:log("ssh:daemon error ~p",[Error]), Error end. +%%%---------------------------------------------------------------- +daemon_port(Pid) -> daemon_port(0, Pid). + + daemon_port(0, Pid) -> {ok,Dinf} = ssh:daemon_info(Pid), proplists:get_value(port, Dinf); daemon_port(Port, _) -> Port. - +%%%---------------------------------------------------------------- +gen_tcp_connect(Host0, Port, Options) -> + Host = ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(Host0)), + ct:log("~p:~p gen_tcp:connect(~p, ~p, ~p)~nHost0 = ~p", + [?MODULE,?LINE, Host, Port, Options, Host0]), + Result = gen_tcp:connect(Host, Port, Options), + ct:log("~p:~p Result = ~p", [?MODULE,?LINE, Result]), + Result. + +%%%---------------------------------------------------------------- +open_sshc(Host0, Port, OptStr) -> + open_sshc(Host0, Port, OptStr, ""). +open_sshc(Host0, Port, OptStr, ExecStr) -> + Cmd = open_sshc_cmd(Host0, Port, OptStr, ExecStr), + Result = os:cmd(Cmd), + ct:log("~p:~p Result = ~p", [?MODULE,?LINE, Result]), + Result. + + +open_sshc_cmd(Host, Port, OptStr) -> + open_sshc_cmd(Host, Port, OptStr, ""). + +open_sshc_cmd(Host0, Port, OptStr, ExecStr) -> + Host = ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(Host0)), + Cmd = lists:flatten(["ssh -p ", integer_to_list(Port), + " ", OptStr, + " ", Host, + " ", ExecStr]), + ct:log("~p:~p OpenSSH Cmd = ~p", [?MODULE,?LINE, Cmd]), + Cmd. + +%%%---------------------------------------------------------------- std_daemon(Config, ExtraOpts) -> PrivDir = proplists:get_value(priv_dir, Config), UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth @@ -85,6 +122,7 @@ std_daemon1(Config, ExtraOpts) -> {failfun, fun ssh_test_lib:failfun/2} | ExtraOpts]). +%%%---------------------------------------------------------------- std_connect(Config, Host, Port, ExtraOpts) -> UserDir = proplists:get_value(priv_dir, Config), _ConnectionRef = @@ -95,6 +133,7 @@ std_connect(Config, Host, Port, ExtraOpts) -> {user_interaction, false} | ExtraOpts]). +%%%---------------------------------------------------------------- std_simple_sftp(Host, Port, Config) -> std_simple_sftp(Host, Port, Config, []). @@ -109,6 +148,7 @@ std_simple_sftp(Host, Port, Config, Opts) -> ok = ssh:close(ConnectionRef), Data == ReadData. +%%%---------------------------------------------------------------- std_simple_exec(Host, Port, Config) -> std_simple_exec(Host, Port, Config, []). @@ -135,6 +175,7 @@ std_simple_exec(Host, Port, Config, Opts) -> ct:fail(ExecResult) end. +%%%---------------------------------------------------------------- start_shell(Port, IOServer) -> start_shell(Port, IOServer, []). @@ -149,6 +190,7 @@ start_shell(Port, IOServer, ExtraOptions) -> end). +%%%---------------------------------------------------------------- start_io_server() -> spawn_link(?MODULE, init_io_server, [self()]). @@ -207,8 +249,7 @@ reply(TestCase, Result) -> %%ct:log("reply ~p sending ~p ! ~p",[self(), TestCase, Result]), TestCase ! Result. - - +%%%---------------------------------------------------------------- rcv_expected(Expect, SshPort, Timeout) -> receive {SshPort, Recvd} when is_function(Expect) -> @@ -862,3 +903,73 @@ create_random_dir(Config) -> %% The likelyhood of always generating an existing file name is low create_random_dir(Config) end. + +%%%---------------------------------------------------------------- +match_ip(A, B) -> + R = match_ip0(A,B) orelse match_ip0(B,A), + ct:log("match_ip(~p, ~p) -> ~p",[A, B, R]), + R. + +match_ip0(A, A) -> + true; +match_ip0(any, _) -> + true; +match_ip0(A, B) -> + case match_ip1(A, B) of + true -> + true; + false when is_list(A) -> + case inet:parse_address(A) of + {ok,IPa} -> match_ip0(IPa, B); + _ -> false + end; + false when is_list(B) -> + case inet:parse_address(B) of + {ok,IPb} -> match_ip0(A, IPb); + _ -> false + end; + false -> + false + end. + +match_ip1(any, _) -> true; +match_ip1(loopback, {127,_,_,_}) -> true; +match_ip1({0,0,0,0}, {127,_,_,_}) -> true; +match_ip1(loopback, {0,0,0,0,0,0,0,1}) -> true; +match_ip1({0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1}) -> true; +match_ip1(_, _) -> false. + +%%%---------------------------------------------------------------- +mangle_connect_address(A) -> + mangle_connect_address(A, []). + +mangle_connect_address(A, SockOpts) -> + mangle_connect_address1(A, proplists:get_value(inet6,SockOpts,false)). + +loopback(true) -> {0,0,0,0,0,0,0,1}; +loopback(false) -> {127,0,0,1}. + +mangle_connect_address1( loopback, V6flg) -> loopback(V6flg); +mangle_connect_address1( any, V6flg) -> loopback(V6flg); +mangle_connect_address1({0,0,0,0}, _) -> loopback(false); +mangle_connect_address1({0,0,0,0,0,0,0,0}, _) -> loopback(true); +mangle_connect_address1( IP, _) when is_tuple(IP) -> IP; +mangle_connect_address1(A, _) -> + case catch inet:parse_address(A) of + {ok, {0,0,0,0}} -> loopback(false); + {ok, {0,0,0,0,0,0,0,0}} -> loopback(true); + _ -> A + end. + +%%%---------------------------------------------------------------- +ntoa(A) -> + try inet:ntoa(A) + of + {error,_} when is_atom(A) -> atom_to_list(A); + {error,_} when is_list(A) -> A; + S when is_list(S) -> S + catch + _:_ when is_atom(A) -> atom_to_list(A); + _:_ when is_list(A) -> A + end. + diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 7eda009552..35e3ee3edf 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -376,18 +376,18 @@ erlang_server_openssh_client_public_key_rsa(Config) when is_list(Config) -> erlang_server_openssh_client_public_key_X(Config, ssh_rsa). -erlang_server_openssh_client_public_key_X(Config, PubKeyAlg) -> +erlang_server_openssh_client_public_key_X(Config, _PubKeyAlg) -> SystemDir = proplists:get_value(data_dir, Config), PrivDir = proplists:get_value(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {failfun, fun ssh_test_lib:failfun/2}]), - ct:sleep(500), - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ - " " ++ Host ++ " 1+1.", + Cmd = ssh_test_lib:open_sshc_cmd(Host, Port, + [" -o UserKnownHostsFile=", KnownHosts, + " -o StrictHostKeyChecking=no"], + "1+1."), OpenSsh = ssh_test_lib:open_port({spawn, Cmd}), ssh_test_lib:rcv_expected({data,<<"2\n">>}, OpenSsh, ?TIMEOUT), ssh:stop_daemon(Pid). @@ -395,13 +395,13 @@ erlang_server_openssh_client_public_key_X(Config, PubKeyAlg) -> %%-------------------------------------------------------------------- %% Test that the Erlang/OTP server can renegotiate with openSSH erlang_server_openssh_client_renegotiate(Config) -> - PubKeyAlg = ssh_rsa, + _PubKeyAlg = ssh_rsa, SystemDir = proplists:get_value(data_dir, Config), PrivDir = proplists:get_value(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {failfun, fun ssh_test_lib:failfun/2}]), ct:sleep(500), RenegLimitK = 3, @@ -409,11 +409,13 @@ erlang_server_openssh_client_renegotiate(Config) -> Data = lists:duplicate(trunc(1.1*RenegLimitK*1024), $a), ok = file:write_file(DataFile, Data), - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ - " -o RekeyLimit=" ++ integer_to_list(RenegLimitK) ++"K" ++ - " " ++ Host ++ " < " ++ DataFile, - OpenSsh = ssh_test_lib:open_port({spawn, Cmd}), + Cmd = ssh_test_lib:open_sshc_cmd(Host, Port, + [" -o UserKnownHostsFile=", KnownHosts, + " -o StrictHostKeyChecking=no", + " -o RekeyLimit=",integer_to_list(RenegLimitK),"K"]), + + + OpenSsh = ssh_test_lib:open_port({spawn, Cmd++" < "++DataFile}), Expect = fun({data,R}) -> try @@ -462,7 +464,7 @@ erlang_client_openssh_server_renegotiate(_Config) -> {silently_accept_hosts,true}], group_leader(IO, self()), {ok, ConnRef} = ssh:connect(Host, ?SSH_DEFAULT_PORT, Options), - ct:pal("Parent = ~p, IO = ~p, Shell = ~p, ConnRef = ~p~n",[Parent, IO, self(), ConnRef]), + ct:log("Parent = ~p, IO = ~p, Shell = ~p, ConnRef = ~p~n",[Parent, IO, self(), ConnRef]), case ssh_connection:session_channel(ConnRef, infinity) of {ok,ChannelId} -> success = ssh_connection:ptty_alloc(ConnRef, ChannelId, []), diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 261239c152..e1f4c65300 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -314,8 +314,7 @@ mangle_opts(Options) -> lists:keydelete(K,1,Opts) end, Options, SysOpts). -host({0,0,0,0}) -> "localhost"; -host(H) -> H. +host(H) -> ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(H)). %%%---------------------------------------------------------------- send(S=#s{ssh=C}, hello) -> |