aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/ssh/test/Makefile3
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl47
-rw-r--r--lib/ssh/test/ssh_test_cli.erl81
3 files changed, 126 insertions, 5 deletions
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 13caafc055..740dbd0235 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -39,7 +39,8 @@ MODULES= \
ssh_sftpd_erlclient_SUITE \
ssh_connection_SUITE \
ssh_echo_server \
- ssh_peername_sockname_server
+ ssh_peername_sockname_server \
+ ssh_test_cli
HRL_FILES_NEEDED_IN_TEST= \
$(ERL_TOP)/lib/ssh/src/ssh.hrl \
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index b9745dda9c..b3281e433e 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -49,14 +49,18 @@ all() ->
close].
groups() ->
- [{dsa_key, [], [send,
- peername_sockname,
- exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]},
- {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey, openssh_zlib_basic_test]},
+ [{dsa_key, [], basic_tests()},
+ {rsa_key, [], basic_tests()},
{dsa_pass_key, [], [pass_phrase]},
{rsa_pass_key, [], [pass_phrase]},
{internal_error, [], [internal_error]}
].
+
+basic_tests() ->
+ [send, peername_sockname,
+ exec, exec_compressed, shell, cli, known_hosts,
+ idle_time, rekey, openssh_zlib_basic_test].
+
%%--------------------------------------------------------------------
init_per_suite(Config) ->
case catch crypto:start() of
@@ -303,6 +307,41 @@ shell(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
+cli() ->
+ [{doc, ""}].
+cli(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
+ {password, "morot"},
+ {ssh_cli, {ssh_test_cli, [cli]}},
+ {subsystems, []},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ct:sleep(500),
+
+ ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh_connection:shell(ConnectionRef, ChannelId),
+ ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>),
+ receive
+ {ssh_cm, ConnectionRef,
+ {data,0,0, <<"\r\nYou are accessing a dummy, type \"q\" to exit\r\n\n">>}} ->
+ ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>)
+ end,
+
+ receive
+ {ssh_cm, ConnectionRef,{closed, ChannelId}} ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
daemon_already_started() ->
[{doc, "Test that get correct error message if you try to start a daemon",
"on an adress that already runs a daemon see also seq10667"}].
diff --git a/lib/ssh/test/ssh_test_cli.erl b/lib/ssh/test/ssh_test_cli.erl
new file mode 100644
index 0000000000..cd9ad5f2ff
--- /dev/null
+++ b/lib/ssh/test/ssh_test_cli.erl
@@ -0,0 +1,81 @@
+-module(ssh_test_cli).
+
+-export([init/1, terminate/2, handle_ssh_msg/2, handle_msg/2]).
+
+-record(state, {
+ type,
+ id,
+ ref,
+ port
+ }).
+
+init([Type]) ->
+ {ok, #state{type = Type}}.
+
+handle_msg({ssh_channel_up, Id, Ref}, S) ->
+ User = get_ssh_user(Ref),
+ ok = ssh_connection:send(Ref,
+ Id,
+ << "\r\nYou are accessing a dummy, type \"q\" to exit\r\n\n" >>),
+ Port = run_portprog(User, S#state.type),
+ {ok, S#state{port = Port, id = Id, ref = Ref}};
+
+handle_msg({Port, {data, Data}}, S = #state{port = Port}) ->
+ ok = ssh_connection:send(S#state.ref, S#state.id, Data),
+ {ok, S};
+handle_msg({Port, {exit_status, Exit}}, S = #state{port = Port}) ->
+ if
+ S#state.type =:= cli ->
+ ok = ssh_connection:send(S#state.ref, S#state.id, << "\r\n" >>);
+ true ->
+ ok
+ end,
+ ok = ssh_connection:exit_status(S#state.ref, S#state.id, Exit),
+ {stop, S#state.id, S#state{port = undefined}};
+handle_msg({'EXIT', Port, _}, S = #state{port = Port}) ->
+ ok = ssh_connection:exit_status(S#state.ref, S#state.id, 0),
+ {stop, S#state.id, S#state{port = undefined}};
+handle_msg(_Msg, S) ->
+ {ok, S}.
+
+handle_ssh_msg({ssh_cm, Ref, {data, Id, _Type, <<"q">>}}, S) ->
+ ssh_connection:send_eof(Ref, Id),
+ {stop, Id, S};
+handle_ssh_msg({ssh_cm, _Ref, {data, _Id, _Type, Data}}, S) ->
+ true = port_command(S#state.port, Data),
+ {ok, S};
+handle_ssh_msg({ssh_cm, _, {eof, _}}, S) ->
+ {ok, S};
+handle_ssh_msg({ssh_cm, Ref, {env, Id, WantReply, _Var, _Value}}, S) ->
+ ok = ssh_connection:reply_request(Ref, WantReply, success, Id),
+ {ok, S};
+handle_ssh_msg({ssh_cm, Ref, {pty, Id, WantReply, _Terminal_jox}}, S) ->
+ ok = ssh_connection:reply_request(Ref, WantReply, success, Id),
+ {ok, S};
+handle_ssh_msg({ssh_cm, Ref, {shell, Id, WantReply}}, S) ->
+ ok = ssh_connection:reply_request(Ref, WantReply, success, Id),
+ {ok, S};
+handle_ssh_msg({ssh_cm, _, {signal, _, _}}, S) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ {ok, S};
+handle_ssh_msg({ssh_cm, _,
+ {window_change, _Id, _Width, _Height, _Pixw, _PixH}}, S) ->
+ {ok, S};
+handle_ssh_msg({ssh_cm, _, {exit_signal, Id, _, _, _}},
+ S) ->
+ {stop, Id, S}.
+
+terminate(_Why, _S) ->
+ nop.
+
+run_portprog(User, cli) ->
+ Pty_bin = os:find_executable("cat"),
+ open_port({spawn_executable, Pty_bin},
+ [stream, {cd, "/tmp"}, {env, [{"USER", User}]},
+ {args, []}, binary,
+ exit_status, use_stdio, stderr_to_stdout]).
+
+get_ssh_user(Ref) ->
+ [{user, User}] = ssh:connection_info(Ref, [user]),
+ User.
+