aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/test/ssh_to_openssh_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/test/ssh_to_openssh_SUITE.erl')
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl147
1 files changed, 129 insertions, 18 deletions
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index a914938c41..547f759a00 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. 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.
@@ -29,13 +29,14 @@
-define(TIMEOUT, 50000).
-define(SSH_DEFAULT_PORT, 22).
+-define(REKEY_DATA_TMO, 65000).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
- [{timetrap,{seconds,20}}].
+ [{timetrap,{seconds,60}}].
all() ->
case os:find_executable("ssh") of
@@ -55,10 +56,12 @@ groups() ->
erlang_client_openssh_server_publickey_rsa,
erlang_client_openssh_server_password,
erlang_client_openssh_server_kexs,
- erlang_client_openssh_server_nonexistent_subsystem
+ erlang_client_openssh_server_nonexistent_subsystem,
+ erlang_client_openssh_server_renegotiate
]},
{erlang_server, [], [erlang_server_openssh_client_public_key_dsa,
- erlang_server_openssh_client_public_key_rsa
+ erlang_server_openssh_client_public_key_rsa,
+ erlang_server_openssh_client_renegotiate
]}
].
@@ -104,6 +107,11 @@ init_per_testcase(erlang_server_openssh_client_public_key_rsa, Config) ->
chk_key(sshc, 'ssh-rsa', ".ssh/id_rsa", Config);
init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) ->
chk_key(sshd, 'ssh-dss', ".ssh/id_dsa", Config);
+init_per_testcase(erlang_server_openssh_client_renegotiate, Config) ->
+ case os:type() of
+ {unix,_} -> ssh:start(), Config;
+ Type -> {skip, io_lib:format("Unsupported test on ~p",[Type])}
+ end;
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -145,7 +153,7 @@ erlang_shell_client_openssh_server(Config) when is_list(Config) ->
IO = ssh_test_lib:start_io_server(),
Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO),
IO ! {input, self(), "echo Hej\n"},
- receive_hej(),
+ receive_data("Hej"),
IO ! {input, self(), "exit\n"},
receive_logout(),
receive_normal_exit(Shell).
@@ -386,6 +394,112 @@ erlang_server_openssh_client_public_key_X(Config, PubKeyAlg) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+%% Test that the Erlang/OTP server can renegotiate with openSSH
+erlang_server_openssh_client_renegotiate(Config) ->
+ 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},
+ {public_key_alg, PubKeyAlg},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ct:sleep(500),
+
+ RenegLimitK = 3,
+ DataFile = filename:join(PrivDir, "renegotiate_openssh_client.data"),
+ 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}),
+
+ Expect = fun({data,R}) ->
+ try
+ NonAlphaChars = [C || C<-lists:seq(1,255),
+ not lists:member(C,lists:seq($a,$z)),
+ not lists:member(C,lists:seq($A,$Z))
+ ],
+ Lines = string:tokens(binary_to_list(R), NonAlphaChars),
+ lists:any(fun(L) -> length(L)>1 andalso lists:prefix(L, Data) end,
+ Lines)
+ catch
+ _:_ -> false
+ end;
+
+ ({exit_status,E}) when E=/=0 ->
+ ct:log("exit_status ~p",[E]),
+ throw({skip,"exit status"});
+
+ (_) ->
+ false
+ end,
+
+ try
+ ssh_test_lib:rcv_expected(Expect, OpenSsh, ?TIMEOUT)
+ of
+ _ ->
+ %% Unfortunatly we can't check that there has been a renegotiation, just trust OpenSSH.
+ ssh:stop_daemon(Pid)
+ catch
+ throw:{skip,R} -> {skip,R}
+ end.
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_renegotiate(_Config) ->
+ process_flag(trap_exit, true),
+
+ IO = ssh_test_lib:start_io_server(),
+ Ref = make_ref(),
+ Parent = self(),
+
+ Shell =
+ spawn_link(
+ fun() ->
+ Host = ssh_test_lib:hostname(),
+ Options = [{user_interaction, false},
+ {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]),
+ case ssh_connection:session_channel(ConnRef, infinity) of
+ {ok,ChannelId} ->
+ success = ssh_connection:ptty_alloc(ConnRef, ChannelId, []),
+ Args = [{channel_cb, ssh_shell},
+ {init_args,[ConnRef, ChannelId]},
+ {cm, ConnRef}, {channel_id, ChannelId}],
+ {ok, State} = ssh_channel:init([Args]),
+ Parent ! {ok, Ref, ConnRef},
+ ssh_channel:enter_loop(State);
+ Error ->
+ Parent ! {error, Ref, Error}
+ end,
+ receive
+ nothing -> ok
+ end
+ end),
+
+ receive
+ {error, Ref, Error} ->
+ ct:fail("Error=~p",[Error]);
+ {ok, Ref, ConnectionRef} ->
+ IO ! {input, self(), "echo Hej1\n"},
+ receive_data("Hej1"),
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ ssh_connection_handler:renegotiate(ConnectionRef),
+ IO ! {input, self(), "echo Hej2\n"},
+ receive_data("Hej2"),
+ Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
+ IO ! {input, self(), "exit\n"},
+ receive_logout(),
+ receive_normal_exit(Shell),
+ true = (Kex1 =/= Kex2)
+ end.
+
+%%--------------------------------------------------------------------
erlang_client_openssh_server_password() ->
[{doc, "Test client password option"}].
erlang_client_openssh_server_password(Config) when is_list(Config) ->
@@ -440,27 +554,24 @@ erlang_client_openssh_server_nonexistent_subsystem(Config) when is_list(Config)
%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
-receive_hej() ->
+receive_data(Data) ->
receive
- <<"Hej", _binary>> = Hej ->
- ct:log("Expected result: ~p~n", [Hej]);
- <<"Hej\n", _binary>> = Hej ->
- ct:log("Expected result: ~p~n", [Hej]);
- <<"Hej\r\n", _/binary>> = Hej ->
- ct:log("Expected result: ~p~n", [Hej]);
- Info ->
- Lines = binary:split(Info, [<<"\r\n">>], [global]),
- case lists:member(<<"Hej">>, Lines) of
+ Info when is_binary(Info) ->
+ Lines = string:tokens(binary_to_list(Info), "\r\n "),
+ case lists:member(Data, Lines) of
true ->
ct:log("Expected result found in lines: ~p~n", [Lines]),
ok;
false ->
ct:log("Extra info: ~p~n", [Info]),
- receive_hej()
- end
+ receive_data(Data)
+ end;
+ Other ->
+ ct:log("Unexpected: ~p",[Other]),
+ receive_data(Data)
after
30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
- end.
+ end.
receive_logout() ->
receive