diff options
-rw-r--r-- | lib/ssh/test/Makefile | 3 | ||||
-rw-r--r-- | lib/ssh/test/ssh_basic_SUITE.erl | 47 | ||||
-rw-r--r-- | lib/ssh/test/ssh_test_cli.erl | 81 |
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. + |