aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/test/ssh_connection_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/test/ssh_connection_SUITE.erl')
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl188
1 files changed, 134 insertions, 54 deletions
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index 952fb8da99..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-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.
@@ -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,
@@ -87,13 +94,14 @@ init_per_suite(Config) ->
?CHECK_CRYPTO(Config).
end_per_suite(Config) ->
+ catch ssh:stop(),
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"};
+ {skip,"No openssh deamon (econnrefused)"};
{ok, Socket} ->
gen_tcp:close(Socket),
ssh_test_lib:openssh_sanity_check(Config)
@@ -128,7 +136,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).
@@ -181,13 +189,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).
@@ -521,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"},
@@ -534,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")
@@ -617,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),
@@ -628,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"},
@@ -638,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),
@@ -660,12 +712,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_echo/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"},
@@ -678,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")
@@ -698,11 +751,11 @@ 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"},
- {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},
@@ -717,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")
@@ -733,10 +786,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 ->
@@ -755,10 +808,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 ->
@@ -777,10 +830,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 ->
@@ -800,10 +853,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 ->
@@ -828,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"},
@@ -848,33 +901,34 @@ 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")
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_echo/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),
ssh:stop_daemon(Pid1);
Error ->
+ ssh:close(ConnectionRef0),
+ ssh:stop_daemon(Pid0),
ct:fail({unexpected, Error})
end.
@@ -894,11 +948,22 @@ start_subsystem_on_closed_channel(Config) ->
{user_interaction, false},
{user_dir, UserDir}]),
- {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, ChannelId),
+ {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, ChannelId1),
+ {error, closed} = ssh_connection:ptty_alloc(ConnectionRef, ChannelId1, []),
+ {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId1, "echo_n", 5000),
+ {error, closed} = ssh_connection:exec(ConnectionRef, ChannelId1, "testing1.\n", 5000),
+ {error, closed} = ssh_connection:send(ConnectionRef, ChannelId1, "exit().\n", 5000),
- {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity),
+ %% Test that there could be a gap between close and an operation (Bugfix OTP-14939):
+ {ok, ChannelId2} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, ChannelId2),
+ timer:sleep(2000),
+ {error, closed} = ssh_connection:ptty_alloc(ConnectionRef, ChannelId2, []),
+ {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId2, "echo_n", 5000),
+ {error, closed} = ssh_connection:exec(ConnectionRef, ChannelId2, "testing1.\n", 5000),
+ {error, closed} = ssh_connection:send(ConnectionRef, ChannelId2, "exit().\n", 5000),
ssh:close(ConnectionRef),
ssh:stop_daemon(Pid).
@@ -1056,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("echo "++Cmd ++ "\n")
+ end).
+
+ssh_exec_echo(Cmd, User) ->
spawn(fun() ->
- io:format(Cmd ++ "\n")
+ 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.