aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh')
-rw-r--r--lib/ssh/doc/src/ssh.xml20
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml15
-rw-r--r--lib/ssh/src/ssh.erl240
-rw-r--r--lib/ssh/src/ssh_acceptor.erl3
-rw-r--r--lib/ssh/src/ssh_acceptor_sup.erl2
-rw-r--r--lib/ssh/src/ssh_channel_sup.erl2
-rw-r--r--lib/ssh/src/ssh_cli.erl15
-rw-r--r--lib/ssh/src/ssh_client_key_api.erl24
-rw-r--r--lib/ssh/src/ssh_connection_sup.erl2
-rw-r--r--lib/ssh/src/ssh_dbg.erl44
-rw-r--r--lib/ssh/src/ssh_file.erl23
-rw-r--r--lib/ssh/src/ssh_message.erl10
-rw-r--r--lib/ssh/src/ssh_server_key_api.erl15
-rw-r--r--lib/ssh/src/ssh_sftp.erl23
-rw-r--r--lib/ssh/src/ssh_sftpd.erl16
-rw-r--r--lib/ssh/src/ssh_shell.erl15
-rw-r--r--lib/ssh/src/ssh_subsystem_sup.erl2
-rw-r--r--lib/ssh/src/ssh_sup.erl2
-rw-r--r--lib/ssh/src/ssh_system_sup.erl7
-rw-r--r--lib/ssh/src/sshc_sup.erl2
-rw-r--r--lib/ssh/src/sshd_sup.erl2
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl126
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl181
-rw-r--r--lib/ssh/test/ssh_benchmark_SUITE.erl45
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl306
-rw-r--r--lib/ssh/test/ssh_echo_server.erl35
-rw-r--r--lib/ssh/test/ssh_options_SUITE.erl82
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE.erl2
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl17
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE.erl15
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl393
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl102
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl64
-rw-r--r--lib/ssh/test/ssh_sup_SUITE.erl41
-rw-r--r--lib/ssh/test/ssh_test_lib.erl61
-rw-r--r--lib/ssh/test/ssh_test_lib.hrl10
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl29
-rw-r--r--lib/ssh/test/ssh_upgrade_SUITE.erl23
38 files changed, 1362 insertions, 654 deletions
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index ff2d6e082a..e6c54d27bf 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -125,8 +125,10 @@
<func>
<name>connect(Host, Port, Options) -> </name>
- <name>connect(Host, Port, Options, Timeout) -> {ok,
- ssh_connection_ref()} | {error, Reason}</name>
+ <name>connect(Host, Port, Options, Timeout) -> </name>
+ <name>connect(TcpSocket, Options) -> </name>
+ <name>connect(TcpSocket, Options, Timeout) ->
+ {ok, ssh_connection_ref()} | {error, Reason}</name>
<fsummary>Connects to an SSH server.</fsummary>
<type>
<v>Host = string()</v>
@@ -137,6 +139,8 @@
<v>Timeout = infinity | integer()</v>
<d>Negotiation time-out in milli-seconds. The default value is <c>infinity</c>.
For connection time-out, use option <c>{connect_timeout, timeout()}</c>.</d>
+ <v>TcpSocket = port()</v>
+ <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
</type>
<desc>
<p>Connects to an SSH server. No channel is started. This is done
@@ -347,8 +351,9 @@
<func>
<name>daemon(Port) -> </name>
<name>daemon(Port, Options) -> </name>
- <name>daemon(HostAddress, Port, Options) -> {ok,
- ssh_daemon_ref()} | {error, atom()}</name>
+ <name>daemon(HostAddress, Port, Options) -> </name>
+ <name>daemon(TcpSocket) -> </name>
+ <name>daemon(TcpSocket, Options) -> {ok, ssh_daemon_ref()} | {error, atom()}</name>
<fsummary>Starts a server listening for SSH connections
on the given port.</fsummary>
<type>
@@ -357,6 +362,8 @@
<v>Options = [{Option, Value}]</v>
<v>Option = atom()</v>
<v>Value = term()</v>
+ <v>TcpSocket = port()</v>
+ <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
</type>
<desc>
<p>Starts a server listening for SSH connections on the given
@@ -718,12 +725,15 @@
<func>
<name>shell(Host) -> </name>
<name>shell(Host, Option) -> </name>
- <name>shell(Host, Port, Option) -> _</name>
+ <name>shell(Host, Port, Option) -> </name>
+ <name>shell(TcpSocket) -> _</name>
<fsummary>Starts an interactive shell over an SSH server.</fsummary>
<type>
<v>Host = string()</v>
<v>Port = integer()</v>
<v>Options - see ssh:connect/3</v>
+ <v>TcpSocket = port()</v>
+ <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
</type>
<desc>
<p>Starts an interactive shell over an SSH server on the
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index 071d46ec57..eb6f43d417 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -527,15 +527,24 @@
<func>
<name>start_channel(ConnectionRef) -></name>
- <name>start_channel(ConnectionRef, Options) -></name>
+ <name>start_channel(ConnectionRef, Options) ->
+ {ok, Pid} | {error, reason()|term()}</name>
+
<name>start_channel(Host, Options) -></name>
- <name>start_channel(Host, Port, Options) -> {ok, Pid} | {ok, Pid, ConnectionRef} |
- {error, reason()|term()}</name>
+ <name>start_channel(Host, Port, Options) ->
+ {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
+
+ <name>start_channel(TcpSocket) -></name>
+ <name>start_channel(TcpSocket, Options) ->
+ {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
+
<fsummary>Starts an SFTP client.</fsummary>
<type>
<v>Host = string()</v>
<v>ConnectionRef = ssh_connection_ref()</v>
<v>Port = integer()</v>
+ <v>TcpSocket = port()</v>
+ <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
<v>Options = [{Option, Value}]</v>
</type>
<desc>
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 09b07b7a2a..0570853a9b 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -27,7 +27,9 @@
-include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
--export([start/0, start/1, stop/0, connect/3, connect/4, close/1, connection_info/2,
+-export([start/0, start/1, stop/0,
+ connect/2, connect/3, connect/4,
+ close/1, connection_info/2,
channel_info/3,
daemon/1, daemon/2, daemon/3,
daemon_info/1,
@@ -70,13 +72,36 @@ stop() ->
application:stop(ssh).
%%--------------------------------------------------------------------
--spec connect(string(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
+-spec connect(port(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
+
+-spec connect(port(), proplists:proplist(), timeout()) -> {ok, pid()} | {error, term()}
+ ; (string(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
+
-spec connect(string(), integer(), proplists:proplist(), timeout()) -> {ok, pid()} | {error, term()}.
%%
%% Description: Starts an ssh connection.
%%--------------------------------------------------------------------
-connect(Host, Port, Options) ->
+connect(Socket, Options) ->
+ connect(Socket, Options, infinity).
+
+connect(Socket, Options, Timeout) when is_port(Socket) ->
+ case handle_options(Options) of
+ {error, Error} ->
+ {error, Error};
+ {_SocketOptions, SshOptions} ->
+ case valid_socket_to_use(Socket, Options) of
+ ok ->
+ {ok, {Host,_Port}} = inet:sockname(Socket),
+ Opts = [{user_pid,self()}, {host,fmt_host(Host)} | SshOptions],
+ ssh_connection_handler:start_connection(client, Socket, Opts, Timeout);
+ {error,SockError} ->
+ {error,SockError}
+ end
+ end;
+
+connect(Host, Port, Options) when is_integer(Port), Port>0 ->
connect(Host, Port, Options, infinity).
+
connect(Host, Port, Options, Timeout) ->
case handle_options(Options) of
{error, _Reason} = Error ->
@@ -125,7 +150,7 @@ channel_info(ConnectionRef, ChannelId, Options) ->
%%--------------------------------------------------------------------
-spec daemon(integer()) -> {ok, pid()} | {error, term()}.
--spec daemon(integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
+-spec daemon(integer()|port(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
-spec daemon(any | inet:ip_address(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
%% Description: Starts a server listening for SSH connections
@@ -134,28 +159,16 @@ channel_info(ConnectionRef, ChannelId, Options) ->
daemon(Port) ->
daemon(Port, []).
-daemon(Port, Options) ->
- daemon(any, Port, Options).
+daemon(Port, Options) when is_integer(Port) ->
+ daemon(any, Port, Options);
+
+daemon(Socket, Options0) when is_port(Socket) ->
+ Options = daemon_shell_opt(Options0),
+ start_daemon(Socket, Options).
daemon(HostAddr, Port, Options0) ->
- Options1 = case proplists:get_value(shell, Options0) of
- undefined ->
- [{shell, {shell, start, []}} | Options0];
- _ ->
- Options0
- end,
-
- {Host, Inet, Options} = case HostAddr of
- any ->
- {ok, Host0} = inet:gethostname(),
- {Host0, proplists:get_value(inet, Options1, inet), Options1};
- {_,_,_,_} ->
- {HostAddr, inet,
- [{ip, HostAddr} | Options1]};
- {_,_,_,_,_,_,_,_} ->
- {HostAddr, inet6,
- [{ip, HostAddr} | Options1]}
- end,
+ Options1 = daemon_shell_opt(Options0),
+ {Host, Inet, Options} = daemon_host_inet_opt(HostAddr, Options1),
start_daemon(Host, Port, Options, Inet).
%%--------------------------------------------------------------------
@@ -199,8 +212,8 @@ stop_daemon(Address, Port) ->
stop_daemon(Address, Port, Profile) ->
ssh_system_sup:stop_system(Address, Port, Profile).
%%--------------------------------------------------------------------
--spec shell(string()) -> _.
--spec shell(string(), proplists:proplist()) -> _.
+-spec shell(port() | string()) -> _.
+-spec shell(port() | string(), proplists:proplist()) -> _.
-spec shell(string(), integer(), proplists:proplist()) -> _.
%% Host = string()
@@ -212,27 +225,34 @@ stop_daemon(Address, Port, Profile) ->
%% and will not return until the remote shell is ended.(e.g. on
%% exit from the shell)
%%--------------------------------------------------------------------
+shell(Socket) when is_port(Socket) ->
+ shell(Socket, []);
shell(Host) ->
shell(Host, ?SSH_DEFAULT_PORT, []).
+
+shell(Socket, Options) when is_port(Socket) ->
+ start_shell( connect(Socket, Options) );
shell(Host, Options) ->
shell(Host, ?SSH_DEFAULT_PORT, Options).
+
shell(Host, Port, Options) ->
- case connect(Host, Port, Options) of
- {ok, ConnectionRef} ->
- case ssh_connection:session_channel(ConnectionRef, infinity) of
- {ok,ChannelId} ->
- success = ssh_connection:ptty_alloc(ConnectionRef, ChannelId, []),
- Args = [{channel_cb, ssh_shell},
- {init_args,[ConnectionRef, ChannelId]},
- {cm, ConnectionRef}, {channel_id, ChannelId}],
- {ok, State} = ssh_channel:init([Args]),
- ssh_channel:enter_loop(State);
- Error ->
- Error
- end;
+ start_shell( connect(Host, Port, Options) ).
+
+
+start_shell({ok, ConnectionRef}) ->
+ case ssh_connection:session_channel(ConnectionRef, infinity) of
+ {ok,ChannelId} ->
+ success = ssh_connection:ptty_alloc(ConnectionRef, ChannelId, []),
+ Args = [{channel_cb, ssh_shell},
+ {init_args,[ConnectionRef, ChannelId]},
+ {cm, ConnectionRef}, {channel_id, ChannelId}],
+ {ok, State} = ssh_channel:init([Args]),
+ ssh_channel:enter_loop(State);
Error ->
Error
- end.
+ end;
+start_shell(Error) ->
+ Error.
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
@@ -242,19 +262,128 @@ default_algorithms() ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+valid_socket_to_use(Socket, Options) ->
+ case proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}) of
+ {tcp,_,_} ->
+ %% Is this tcp-socket a valid socket?
+ case {is_tcp_socket(Socket),
+ {ok,[{active,false}]} == inet:getopts(Socket, [active])
+ }
+ of
+ {true, true} ->
+ ok;
+ {true, false} ->
+ {error, not_passive_mode};
+ _ ->
+ {error, not_tcp_socket}
+ end;
+ {L4,_,_} ->
+ {error, {unsupported,L4}}
+ end.
+
+is_tcp_socket(Socket) -> {ok,[]} =/= inet:getopts(Socket, [delay_send]).
+
+
+
+daemon_shell_opt(Options) ->
+ case proplists:get_value(shell, Options) of
+ undefined ->
+ [{shell, {shell, start, []}} | Options];
+ _ ->
+ Options
+ end.
+
+daemon_host_inet_opt(HostAddr, Options1) ->
+ case HostAddr of
+ any ->
+ {ok, Host0} = inet:gethostname(),
+ {Host0, proplists:get_value(inet, Options1, inet), Options1};
+ {_,_,_,_} ->
+ {HostAddr, inet,
+ [{ip, HostAddr} | Options1]};
+ {_,_,_,_,_,_,_,_} ->
+ {HostAddr, inet6,
+ [{ip, HostAddr} | Options1]}
+ end.
+
+
+start_daemon(Socket, Options) ->
+ case handle_options(Options) of
+ {error, Error} ->
+ {error, Error};
+ {SocketOptions, SshOptions} ->
+ case valid_socket_to_use(Socket, Options) of
+ ok ->
+ try
+ do_start_daemon(Socket, [{role,server}|SshOptions], SocketOptions)
+ catch
+ throw:bad_fd -> {error,bad_fd};
+ _C:_E -> {error,{cannot_start_daemon,_C,_E}}
+ end;
+ {error,SockError} ->
+ {error,SockError}
+ end
+ end.
+
start_daemon(Host, Port, Options, Inet) ->
case handle_options(Options) of
{error, _Reason} = Error ->
Error;
{SocketOptions, SshOptions}->
try
- do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions])
+ do_start_daemon(Host, Port, [{role,server}|SshOptions] , [Inet|SocketOptions])
catch
throw:bad_fd -> {error,bad_fd};
_C:_E -> {error,{cannot_start_daemon,_C,_E}}
end
end.
+do_start_daemon(Socket, SshOptions, SocketOptions) ->
+ {ok, {IP,Port}} =
+ try {ok,_} = inet:sockname(Socket)
+ catch
+ _:_ -> throw(bad_socket)
+ end,
+ Host = fmt_host(IP),
+ Profile = proplists:get_value(profile, SshOptions, ?DEFAULT_PROFILE),
+ Opts = [{asocket, Socket},
+ {asock_owner,self()},
+ {address, Host},
+ {port, Port},
+ {role, server},
+ {socket_opts, SocketOptions},
+ {ssh_opts, SshOptions}],
+ {_, Callback, _} = proplists:get_value(transport, SshOptions, {tcp, gen_tcp, tcp_closed}),
+ case ssh_system_sup:system_supervisor(Host, Port, Profile) of
+ undefined ->
+ %% It would proably make more sense to call the
+ %% address option host but that is a too big change at the
+ %% monent. The name is a legacy name!
+ try sshd_sup:start_child(Opts) of
+ {error, {already_started, _}} ->
+ {error, eaddrinuse};
+ Result = {ok,_} ->
+ ssh_acceptor:handle_connection(Callback, Host, Port, Opts, Socket),
+ Result;
+ Result = {error, _} ->
+ Result
+ catch
+ exit:{noproc, _} ->
+ {error, ssh_not_started}
+ end;
+ Sup ->
+ AccPid = ssh_system_sup:acceptor_supervisor(Sup),
+ case ssh_acceptor_sup:start_child(AccPid, Opts) of
+ {error, {already_started, _}} ->
+ {error, eaddrinuse};
+ {ok, _} ->
+ ssh_acceptor:handle_connection(Callback, Host, Port, Opts, Socket),
+ {ok, Sup};
+ Other ->
+ Other
+ end
+ end.
+
do_start_daemon(Host0, Port0, SshOptions, SocketOptions) ->
{Host,Port1} =
try
@@ -270,7 +399,7 @@ do_start_daemon(Host0, Port0, SshOptions, SocketOptions) ->
_:_ -> throw(bad_fd)
end,
Profile = proplists:get_value(profile, SshOptions, ?DEFAULT_PROFILE),
- {Port, WaitRequestControl, Opts} =
+ {Port, WaitRequestControl, Opts0} =
case Port1 of
0 -> %% Allocate the socket here to get the port number...
{_, Callback, _} =
@@ -284,17 +413,17 @@ do_start_daemon(Host0, Port0, SshOptions, SocketOptions) ->
_ ->
{Port1, false, []}
end,
+ Opts = [{address, Host},
+ {port, Port},
+ {role, server},
+ {socket_opts, SocketOptions},
+ {ssh_opts, SshOptions} | Opts0],
case ssh_system_sup:system_supervisor(Host, Port, Profile) of
undefined ->
%% It would proably make more sense to call the
%% address option host but that is a too big change at the
%% monent. The name is a legacy name!
- try sshd_sup:start_child([{address, Host},
- {port, Port},
- {role, server},
- {socket_opts, SocketOptions},
- {ssh_opts, SshOptions}
- | Opts]) of
+ try sshd_sup:start_child(Opts) of
{error, {already_started, _}} ->
{error, eaddrinuse};
Result = {ok,_} ->
@@ -308,12 +437,7 @@ do_start_daemon(Host0, Port0, SshOptions, SocketOptions) ->
end;
Sup ->
AccPid = ssh_system_sup:acceptor_supervisor(Sup),
- case ssh_acceptor_sup:start_child(AccPid, [{address, Host},
- {port, Port},
- {role, server},
- {socket_opts, SocketOptions},
- {ssh_opts, SshOptions}
- | Opts]) of
+ case ssh_acceptor_sup:start_child(AccPid, Opts) of
{error, {already_started, _}} ->
{error, eaddrinuse};
{ok, _} ->
@@ -477,10 +601,13 @@ handle_option([{profile, _ID} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{max_random_length_padding, _Bool} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{tstflg, _} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
+handle_ssh_option({tstflg,_F} = Opt) -> Opt;
handle_ssh_option({minimal_remote_max_packet_size, Value} = Opt) when is_integer(Value), Value >=0 ->
Opt;
handle_ssh_option({system_dir, Value} = Opt) when is_list(Value) ->
@@ -835,3 +962,8 @@ handle_user_pref_pubkey_algs([H|T], Acc) ->
false ->
false
end.
+
+fmt_host({A,B,C,D}) ->
+ lists:concat([A,".",B,".",C,".",D]);
+fmt_host(T={_,_,_,_,_,_,_,_}) ->
+ lists:flatten(string:join([io_lib:format("~.16B",[A]) || A <- tuple_to_list(T)], ":")).
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index 90fd951dcd..9f3e60bd62 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -27,7 +27,8 @@
%% Internal application API
-export([start_link/5,
number_of_connections/1,
- callback_listen/3]).
+ callback_listen/3,
+ handle_connection/5]).
%% spawn export
-export([acceptor_init/6, acceptor_loop/6]).
diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl
index 4f76dbe6f0..129f85a3e0 100644
--- a/lib/ssh/src/ssh_acceptor_sup.erl
+++ b/lib/ssh/src/ssh_acceptor_sup.erl
@@ -36,6 +36,8 @@
-define(DEFAULT_TIMEOUT, 50000).
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
%%%=========================================================================
%%% API
%%%=========================================================================
diff --git a/lib/ssh/src/ssh_channel_sup.erl b/lib/ssh/src/ssh_channel_sup.erl
index 8eaa85f795..6b01dc334d 100644
--- a/lib/ssh/src/ssh_channel_sup.erl
+++ b/lib/ssh/src/ssh_channel_sup.erl
@@ -43,6 +43,8 @@ start_child(Sup, ChildSpec) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init(_Args) ->
RestartStrategy = one_for_one,
MaxR = 10,
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index 2d60008de6..74cd2e081a 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -47,6 +47,21 @@
%%====================================================================
%% ssh_channel callbacks
%%====================================================================
+-spec init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+
+-spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+
+-spec handle_msg(Msg ::term(), State :: term()) ->
+ {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
+-spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::integer(),
+ State::term()}.
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State}
diff --git a/lib/ssh/src/ssh_client_key_api.erl b/lib/ssh/src/ssh_client_key_api.erl
index 039a7dea9b..6e994ff292 100644
--- a/lib/ssh/src/ssh_client_key_api.erl
+++ b/lib/ssh/src/ssh_client_key_api.erl
@@ -23,14 +23,26 @@
-include_lib("public_key/include/public_key.hrl").
-include("ssh.hrl").
--callback is_host_key(PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term() , Host :: string(),
- Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplist()) ->
+-export_type([algorithm/0]).
+
+-type algorithm() :: 'ssh-rsa'
+ | 'ssh-dss'
+ | 'ecdsa-sha2-nistp256'
+ | 'ecdsa-sha2-nistp384'
+ | 'ecdsa-sha2-nistp521'
+ .
+
+-callback is_host_key(PublicKey :: public_key:public_key(),
+ Host :: string(),
+ Algorithm :: algorithm(),
+ ConnectOptions :: proplists:proplist()) ->
boolean().
--callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), ConnectOptions :: proplists:proplist()) ->
- {ok, PrivateKey :: #'RSAPrivateKey'{}| #'DSAPrivateKey'{} | term()} | {error, string()}.
+-callback user_key(Algorithm :: algorithm(),
+ ConnectOptions :: proplists:proplist()) ->
+ {ok, PrivateKey::public_key:private_key()} | {error, term()}.
--callback add_host_key(Host :: string(), PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term(),
- Options :: list()) ->
+-callback add_host_key(Host :: string(), PublicKey :: public_key:public_key(),
+ Options :: proplists:proplist()) ->
ok | {error, Error::term()}.
diff --git a/lib/ssh/src/ssh_connection_sup.erl b/lib/ssh/src/ssh_connection_sup.erl
index 8c7628e909..0f54053f52 100644
--- a/lib/ssh/src/ssh_connection_sup.erl
+++ b/lib/ssh/src/ssh_connection_sup.erl
@@ -45,6 +45,8 @@ start_child(Sup, Args) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init(_) ->
RestartStrategy = simple_one_for_one,
MaxR = 0,
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index fbf85cfcfc..480795cfc7 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -23,7 +23,8 @@
-module(ssh_dbg).
-export([messages/0,
- messages/1
+ messages/1,
+ stop/0
]).
-include("ssh.hrl").
@@ -40,34 +41,59 @@ messages() -> messages(fun(String,_D) -> io:format(String) end).
messages(Write) when is_function(Write,2) ->
catch dbg:start(),
-
- Handler = fun msg_formater/2,
- InitialData = #data{writer = Write},
- {ok,_} = dbg:tracer(process, {Handler, InitialData}),
-
+ setup_tracer(Write),
dbg:p(new,c),
+ dbg_ssh_messages().
+
+dbg_ssh_messages() ->
dbg:tp(ssh_message,encode,1, x),
dbg:tp(ssh_message,decode,1, x),
dbg:tpl(ssh_transport,select_algorithm,3, x).
+%%%----------------------------------------------------------------
+stop() ->
+ dbg:stop().
+
%%%================================================================
msg_formater({trace,Pid,call,{ssh_message,encode,[Msg]}}, D) ->
fmt("~nSEND ~p ~s~n", [Pid,wr_record(shrink_bin(Msg))], D);
-
+msg_formater({trace,_Pid,return_from,{ssh_message,encode,1},_Res}, D) ->
+ D;
+
+msg_formater({trace,_Pid,call,{ssh_message,decode,_}}, D) ->
+ D;
msg_formater({trace,Pid,return_from,{ssh_message,decode,1},Msg}, D) ->
fmt("~nRECV ~p ~s~n", [Pid,wr_record(shrink_bin(Msg))], D);
+msg_formater({trace,_Pid,call,{ssh_transport,select_algorithm,_}}, D) ->
+ D;
msg_formater({trace,Pid,return_from,{ssh_transport,select_algorithm,3},{ok,Alg}}, D) ->
fmt("~nALGORITHMS ~p~n~s~n", [Pid, wr_record(Alg)], D);
-msg_formater(_, D) ->
- D.
+msg_formater({trace,Pid,send,ErlangMsg,Dest}, D) ->
+ fmt("~nERL MSG ~p SEND TO ~p~n ~p~n", [Pid,Dest, shrink_bin(ErlangMsg)], D);
+
+msg_formater({trace,Pid,'receive',ErlangMsg}, D) ->
+ fmt("~nERL MSG ~p RECIEVE~n ~p~n", [Pid,shrink_bin(ErlangMsg)], D);
+
+msg_formater(M, D) ->
+ fmt("~nDBG ~n~p~n", [shrink_bin(M)], D).
+
+%% msg_formater(_, D) ->
+%% D.
fmt(Fmt, Args, D=#data{writer=Write,acc=Acc}) ->
D#data{acc = Write(io_lib:format(Fmt, Args), Acc)}.
%%%----------------------------------------------------------------
+setup_tracer(Write) ->
+ Handler = fun msg_formater/2,
+ InitialData = #data{writer = Write},
+ {ok,_} = dbg:tracer(process, {Handler, InitialData}),
+ ok.
+
+%%%----------------------------------------------------------------
shrink_bin(B) when is_binary(B), size(B)>100 -> {'*** SHRINKED BIN',size(B),element(1,split_binary(B,20)),'***'};
shrink_bin(L) when is_list(L) -> lists:map(fun shrink_bin/1, L);
shrink_bin(T) when is_tuple(T) -> list_to_tuple(shrink_bin(tuple_to_list(T)));
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 4486d36fe4..216f65f33a 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -43,7 +43,28 @@
-define(PERM_644, 8#644).
-%% API
+%%% API
+
+%%% client
+-spec add_host_key(string(),
+ public_key:public_key(),
+ proplists:proplist()) -> ok | {error,term()}.
+
+-spec is_host_key(public_key:public_key(),
+ string(),
+ ssh_client_key_api:algorithm(),
+ proplists:proplist()) -> boolean().
+
+-spec user_key(ssh_client_key_api:algorithm(),
+ proplists:proplist()) -> {ok, public_key:private_key()} | {error,term()}.
+
+%%% server
+-spec host_key(ssh_server_key_api:algorithm(),
+ proplists:proplist()) -> {ok, public_key:private_key()} | {error,term()}.
+
+-spec is_auth_key(public_key:public_key(),
+ string(), proplists:proplist()) -> boolean().
+
%% Used by server
host_key(Algorithm, Opts) ->
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index db80d4c9e3..562f040477 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -50,7 +50,15 @@
-define(Empint(X), (ssh_bits:mpint(X))/binary ).
-define(Ebinary(X), ?STRING(X) ).
--define(unicode_list(B), unicode:characters_to_list(B)).
+ucl(B) ->
+ try unicode:characters_to_list(B) of
+ L when is_list(L) -> L;
+ {error,_Matched,Rest} -> throw({error,{bad_unicode,Rest}})
+ catch
+ _:_ -> throw({error,bad_unicode})
+ end.
+
+-define(unicode_list(B), ucl(B)).
encode(#ssh_msg_global_request{
name = Name,
diff --git a/lib/ssh/src/ssh_server_key_api.erl b/lib/ssh/src/ssh_server_key_api.erl
index c1d43a486c..3f1b886fa7 100644
--- a/lib/ssh/src/ssh_server_key_api.erl
+++ b/lib/ssh/src/ssh_server_key_api.erl
@@ -23,9 +23,16 @@
-include_lib("public_key/include/public_key.hrl").
-include("ssh.hrl").
--callback host_key(Algorithm :: 'ssh-rsa'| 'ssh-dss'| atom(), DaemonOptions :: proplists:proplist()) ->
- {ok, PrivateKey :: #'RSAPrivateKey'{}| #'DSAPrivateKey'{} | term()} | {error, string()}.
+-export_type([algorithm/0]).
--callback is_auth_key(PublicKey :: #'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term(),
- User :: string(), DaemonOptions :: proplists:proplist()) ->
+-type algorithm() :: ssh_client_key_api:algorithm().
+
+
+-callback host_key(Algorithm :: algorithm(),
+ DaemonOptions :: proplists:proplist()) ->
+ {ok, PrivateKey :: public_key:private_key()} | {error, term()}.
+
+-callback is_auth_key(PublicKey :: public_key:public_key(),
+ User :: string(),
+ DaemonOptions :: proplists:proplist()) ->
boolean().
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index b03652a136..afc2fb88ff 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -95,8 +95,31 @@
%%====================================================================
start_channel(Cm) when is_pid(Cm) ->
start_channel(Cm, []);
+start_channel(Socket) when is_port(Socket) ->
+ start_channel(Socket, []);
start_channel(Host) when is_list(Host) ->
start_channel(Host, []).
+
+start_channel(Socket, Options) when is_port(Socket) ->
+ Timeout =
+ %% A mixture of ssh:connect and ssh_sftp:start_channel:
+ case proplists:get_value(connect_timeout, Options, undefined) of
+ undefined ->
+ proplists:get_value(timeout, Options, infinity);
+ TO ->
+ TO
+ end,
+ case ssh:connect(Socket, Options, Timeout) of
+ {ok,Cm} ->
+ case start_channel(Cm, Options) of
+ {ok, Pid} ->
+ {ok, Pid, Cm};
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
+ end;
start_channel(Cm, Opts) when is_pid(Cm) ->
Timeout = proplists:get_value(timeout, Opts, infinity),
{_, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []),
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 819cba697e..dca018f20f 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -57,6 +57,22 @@
%%====================================================================
%% API
%%====================================================================
+-spec init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+
+-spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+
+-spec handle_msg(Msg ::term(), State :: term()) ->
+ {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
+-spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::integer(),
+ State::term()}.
+
subsystem_spec(Options) ->
{"sftp", {?MODULE, Options}}.
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
index d31d5a297d..17224b6ef4 100644
--- a/lib/ssh/src/ssh_shell.erl
+++ b/lib/ssh/src/ssh_shell.erl
@@ -45,6 +45,21 @@
%%====================================================================
%% ssh_channel callbacks
%%====================================================================
+-spec init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+
+-spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+
+-spec handle_msg(Msg ::term(), State :: term()) ->
+ {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
+-spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::integer(),
+ State::term()}.
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State}
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
index 11e02491c4..637f5f398f 100644
--- a/lib/ssh/src/ssh_subsystem_sup.erl
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -51,6 +51,8 @@ channel_supervisor(SupPid) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init([Opts]) ->
RestartStrategy = one_for_all,
MaxR = 0,
diff --git a/lib/ssh/src/ssh_sup.erl b/lib/ssh/src/ssh_sup.erl
index f827594717..8b57387589 100644
--- a/lib/ssh/src/ssh_sup.erl
+++ b/lib/ssh/src/ssh_sup.erl
@@ -31,6 +31,8 @@
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init([]) ->
SupFlags = {one_for_one, 10, 3600},
Children = children(),
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index 9a9786a914..e97ac7b01a 100644
--- a/lib/ssh/src/ssh_system_sup.erl
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -125,11 +125,16 @@ restart_acceptor(Address, Port, Profile) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init([ServerOpts]) ->
RestartStrategy = one_for_one,
MaxR = 0,
MaxT = 3600,
- Children = child_specs(ServerOpts),
+ Children = case proplists:get_value(asocket,ServerOpts) of
+ undefined -> child_specs(ServerOpts);
+ _ -> []
+ end,
{ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
%%%=========================================================================
diff --git a/lib/ssh/src/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl
index 71b5c2c46a..15858f36e1 100644
--- a/lib/ssh/src/sshc_sup.erl
+++ b/lib/ssh/src/sshc_sup.erl
@@ -51,6 +51,8 @@ stop_child(Client) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init(Args) ->
RestartStrategy = simple_one_for_one,
MaxR = 0,
diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl
index ac9e232b3a..04d2df30f7 100644
--- a/lib/ssh/src/sshd_sup.erl
+++ b/lib/ssh/src/sshd_sup.erl
@@ -75,6 +75,8 @@ system_name(SysSup) ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
+-spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
+
init([Servers]) ->
RestartStrategy = one_for_one,
MaxR = 10,
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 9910b8f1d7..0f68130a05 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -24,11 +24,12 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("ssh/src/ssh_transport.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 10000).
+-define(TIMEOUT, 35000).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -70,30 +71,39 @@ two_way_tags() -> [cipher,mac,compression].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- ct:log("os:getenv(\"HOME\") = ~p~n"
- "init:get_argument(home) = ~p",
- [os:getenv("HOME"), init:get_argument(home)]),
- ct:log("~n~n"
- "OS ssh:~n=======~n~p~n~n~n"
- "Erl ssh:~n========~n~p~n~n~n"
- "Installed ssh client:~n=====================~n~p~n~n~n"
- "Installed ssh server:~n=====================~n~p~n~n~n"
- "Misc values:~n============~n"
- " -- Default dh group exchange parameters ({min,def,max}): ~p~n"
- " -- dh_default_groups: ~p~n"
- " -- Max num algorithms: ~p~n"
- ,[os:cmd("ssh -V"),
- ssh:default_algorithms(),
- ssh_test_lib:default_algorithms(sshc),
- ssh_test_lib:default_algorithms(sshd),
- {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX},
- public_key:dh_gex_group_sizes(),
- ?MAX_NUM_ALGORITHMS
- ]),
- ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]),
- ssh:start(),
- [{std_simple_sftp_size,25000} % Sftp transferred data size
- | setup_pubkey(Config)].
+ ?CHECK_CRYPTO(
+ begin
+ ct:log("~n"
+ "Environment:~n============~n"
+ "os:getenv(\"HOME\") = ~p~n"
+ "init:get_argument(home) = ~p~n~n~n"
+ "OS ssh:~n=======~n~p~n~n~n"
+ "Erl ssh:~n========~n~p~n~n~n"
+ "crypto:info_lib():~n========~n~p~n~n~n"
+ "Installed ssh client:~n=====================~n~p~n~n~n"
+ "Installed ssh server:~n=====================~n~p~n~n~n"
+ "Misc values:~n============~n"
+ " -- Default dh group exchange parameters ({min,def,max}): ~p~n"
+ " -- dh_default_groups: ~p~n"
+ " -- Max num algorithms: ~p~n"
+ ,[os:getenv("HOME"),
+ init:get_argument(home),
+ os:cmd("ssh -V"),
+ ssh:default_algorithms(),
+ crypto:info_lib(),
+ ssh_test_lib:default_algorithms(sshc),
+ ssh_test_lib:default_algorithms(sshd),
+ {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX},
+ public_key:dh_gex_group_sizes(),
+ ?MAX_NUM_ALGORITHMS
+ ]),
+ ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]),
+ ssh:start(),
+ [{std_simple_sftp_size,25000} % Sftp transferred data size
+ | setup_pubkey(Config)]
+ end
+ ).
+
end_per_suite(_Config) ->
ssh:stop().
@@ -109,7 +119,7 @@ init_per_group(Group, Config) ->
false ->
%% An algorithm group
Tag = proplists:get_value(name,
- hd(?config(tc_group_path, Config))),
+ hd(proplists:get_value(tc_group_path, Config))),
Alg = Group,
PA =
case split(Alg) of
@@ -126,47 +136,45 @@ init_per_group(Group, Config) ->
end.
end_per_group(_Alg, Config) ->
- case ?config(srvr_pid,Config) of
+ case proplists:get_value(srvr_pid,Config) of
Pid when is_pid(Pid) ->
ssh:stop_daemon(Pid),
- ct:log("stopped ~p",[?config(srvr_addr,Config)]);
+ ct:log("stopped ~p",[proplists:get_value(srvr_addr,Config)]);
_ ->
ok
end.
-init_per_testcase(sshc_simple_exec, Config) ->
- start_pubkey_daemon([?config(pref_algs,Config)], Config);
-
+init_per_testcase(sshc_simple_exec_os_cmd, Config) ->
+ start_pubkey_daemon([proplists:get_value(pref_algs,Config)], Config);
init_per_testcase(_TC, Config) ->
Config.
-end_per_testcase(sshc_simple_exec, Config) ->
- case ?config(srvr_pid,Config) of
+end_per_testcase(sshc_simple_exec_os_cmd, Config) ->
+ case proplists:get_value(srvr_pid,Config) of
Pid when is_pid(Pid) ->
ssh:stop_daemon(Pid),
- ct:log("stopped ~p",[?config(srvr_addr,Config)]);
+ ct:log("stopped ~p",[proplists:get_value(srvr_addr,Config)]);
_ ->
ok
end;
end_per_testcase(_TC, Config) ->
Config.
-
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
%% A simple sftp transfer
simple_sftp(Config) ->
- {Host,Port} = ?config(srvr_addr, Config),
+ {Host,Port} = proplists:get_value(srvr_addr, Config),
ssh_test_lib:std_simple_sftp(Host, Port, Config).
%%--------------------------------------------------------------------
%% A simple exec call
simple_exec(Config) ->
- {Host,Port} = ?config(srvr_addr, Config),
+ {Host,Port} = proplists:get_value(srvr_addr, Config),
ssh_test_lib:std_simple_exec(Host, Port, Config).
%%--------------------------------------------------------------------
@@ -221,18 +229,36 @@ interpolate(Is) ->
%%--------------------------------------------------------------------
%% Use the ssh client of the OS to connect
-sshc_simple_exec(Config) ->
+sshc_simple_exec_os_cmd(Config) ->
PrivDir = ?config(priv_dir, Config),
KnownHosts = filename:join(PrivDir, "known_hosts"),
{Host,Port} = ?config(srvr_addr, Config),
- Cmd = lists:concat(["ssh -p ",Port,
- " -C",
- " -o UserKnownHostsFile=",KnownHosts,
- " -o StrictHostKeyChecking=no",
- " ",Host," 1+1."]),
- ct:log("~p",[Cmd]),
- OpenSsh = ssh_test_lib:open_port({spawn, Cmd}, [eof,exit_status]),
- ssh_test_lib:rcv_expected({data,<<"2\n">>}, OpenSsh, ?TIMEOUT).
+ 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]),
+ Parent ! {result, self(), Result, "2"}
+ end),
+ receive
+ {result, Client, RawResult, Expect} ->
+ Lines = string:tokens(RawResult, "\r\n"),
+ case lists:any(fun(Line) -> Line==Expect end,
+ Lines) of
+ true ->
+ ok;
+ false ->
+ ct:log("Bad result: ~p~nExpected: ~p~nMangled result: ~p", [RawResult,Expect,Lines]),
+ {fail, "Bad result"}
+ end
+ after ?TIMEOUT ->
+ ct:fail("Did not receive answer")
+ end.
%%--------------------------------------------------------------------
%% Connect to the ssh server of the OS
@@ -299,7 +325,7 @@ specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) ->
true ->
case ssh_test_lib:ssh_type() of
openSSH ->
- [sshc_simple_exec];
+ [sshc_simple_exec_os_cmd];
_ ->
[]
end;
@@ -359,8 +385,8 @@ start_pubkey_daemon(Opts0, Config) ->
setup_pubkey(Config) ->
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, UserDir),
ssh_test_lib:setup_rsa(DataDir, UserDir),
ssh_test_lib:setup_ecdsa("256", DataDir, UserDir),
@@ -370,7 +396,7 @@ setup_pubkey(Config) ->
simple_exec_group(I, Config) when is_integer(I) ->
simple_exec_group({I,I,I}, Config);
simple_exec_group({Min,I,Max}, Config) ->
- {Host,Port} = ?config(srvr_addr, Config),
+ {Host,Port} = proplists:get_value(srvr_addr, Config),
ssh_test_lib:std_simple_exec(Host, Port, Config,
[{dh_gex_limits,{Min,I,Max}}]).
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 0fa44ded4f..733414e23a 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -25,6 +25,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/file.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
%%-compile(export_all).
@@ -130,28 +131,28 @@ basic_tests() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
%%--------------------------------------------------------------------
init_per_group(dsa_key, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
init_per_group(rsa_key, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_rsa(DataDir, PrivDir),
Config;
init_per_group(ecdsa_sha2_nistp256_key, Config) ->
case lists:member('ecdsa-sha2-nistp256',
ssh_transport:default_algorithms(public_key)) of
true ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_ecdsa("256", DataDir, PrivDir),
Config;
false ->
@@ -161,8 +162,8 @@ init_per_group(ecdsa_sha2_nistp384_key, Config) ->
case lists:member('ecdsa-sha2-nistp384',
ssh_transport:default_algorithms(public_key)) of
true ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_ecdsa("384", DataDir, PrivDir),
Config;
false ->
@@ -172,28 +173,28 @@ init_per_group(ecdsa_sha2_nistp521_key, Config) ->
case lists:member('ecdsa-sha2-nistp521',
ssh_transport:default_algorithms(public_key)) of
true ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_ecdsa("521", DataDir, PrivDir),
Config;
false ->
{skip, unsupported_pub_key}
end;
init_per_group(rsa_pass_key, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_rsa_pass_pharse(DataDir, PrivDir, "Password"),
[{pass_phrase, {rsa_pass_phrase, "Password"}}| Config];
init_per_group(dsa_pass_key, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"),
[{pass_phrase, {dsa_pass_phrase, "Password"}}| Config];
init_per_group(host_user_key_differs, Config) ->
- Data = ?config(data_dir, Config),
- Sys = filename:join(?config(priv_dir, Config), system_rsa),
+ Data = proplists:get_value(data_dir, Config),
+ Sys = filename:join(proplists:get_value(priv_dir, Config), system_rsa),
SysUsr = filename:join(Sys, user),
- Usr = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+ Usr = filename:join(proplists:get_value(priv_dir, Config), user_ecdsa_256),
file:make_dir(Sys),
file:make_dir(SysUsr),
file:make_dir(Usr),
@@ -205,18 +206,18 @@ init_per_group(host_user_key_differs, Config) ->
ssh_test_lib:setup_rsa_known_host(Sys, Usr),
Config;
init_per_group(key_cb, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
init_per_group(internal_error, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, PrivDir),
file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
Config;
init_per_group(dir_options, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Make unreadable dir:
Dir_unreadable = filename:join(PrivDir, "unread"),
ok = file:make_dir(Dir_unreadable),
@@ -261,27 +262,27 @@ init_per_group(_, Config) ->
Config.
end_per_group(dsa_key, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
Config;
end_per_group(rsa_key, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_rsa(PrivDir),
Config;
end_per_group(dsa_pass_key, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
Config;
end_per_group(rsa_pass_key, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_rsa(PrivDir),
Config;
end_per_group(key_cb, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
Config;
end_per_group(internal_error, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
Config;
@@ -290,9 +291,9 @@ end_per_group(_, Config) ->
%%--------------------------------------------------------------------
init_per_testcase(TC, Config) when TC==shell_no_unicode ;
TC==shell_unicode_string ->
- PrivDir = ?config(priv_dir, Config),
- UserDir = ?config(priv_dir, Config),
- SysDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
ssh:start(),
Sftpd = {_Pid, _Host, Port} =
ssh_test_lib:daemon([{system_dir, SysDir},
@@ -321,12 +322,12 @@ init_per_testcase(_TestCase, Config) ->
end_per_testcase(TestCase, Config) when TestCase == server_password_option;
TestCase == server_userpassword_option ->
- UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
ssh_test_lib:del_dirs(UserDir),
end_per_testcase(Config);
end_per_testcase(TC, Config) when TC==shell_no_unicode ;
TC==shell_unicode_string ->
- case ?config(sftpd, Config) of
+ case proplists:get_value(sftpd, Config) of
{Pid, _, _} ->
ssh:stop_daemon(Pid),
ssh:stop();
@@ -355,8 +356,8 @@ appup_test(Config) when is_list(Config) ->
%%% some options not yet present are not decided if we should support or
%%% if they need thier own test case.
misc_ssh_options(Config) when is_list(Config) ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}],
CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}],
@@ -369,8 +370,8 @@ misc_ssh_options(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% Test configuring IPv4
inet_option(Config) when is_list(Config) ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
ClientOpts = [{silently_accept_hosts, true},
{user_dir, UserDir},
@@ -385,8 +386,8 @@ inet_option(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% Test configuring IPv6
inet6_option(Config) when is_list(Config) ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
ClientOpts = [{silently_accept_hosts, true},
{user_dir, UserDir},
@@ -402,8 +403,8 @@ inet6_option(Config) when is_list(Config) ->
%%% Test api function ssh_connection:exec
exec(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -449,8 +450,8 @@ exec_compressed(Config) when is_list(Config) ->
true ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
{preferred_algorithms,[{compression, [zlib]}]},
@@ -478,8 +479,8 @@ exec_compressed(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% Idle timeout test
idle_time(Config) ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -501,8 +502,8 @@ idle_time(Config) ->
%%% Test that ssh:shell/2 works
shell(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -536,9 +537,9 @@ exec_key_differs(Config, UserPKAlgs) ->
of
[] ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system_rsa),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system_rsa),
SystemUserDir = filename:join(SystemDir, user),
- UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), user_ecdsa_256),
{_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, SystemUserDir},
@@ -570,9 +571,9 @@ exec_key_differs(Config, UserPKAlgs) ->
%%--------------------------------------------------------------------
exec_key_differs_fail(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system_rsa),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system_rsa),
SystemUserDir = filename:join(SystemDir, user),
- UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), user_ecdsa_256),
{_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, SystemUserDir},
@@ -597,10 +598,10 @@ exec_key_differs_fail(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
cli(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
- TmpDir = filename:join(?config(priv_dir,Config), "tmp"),
+ TmpDir = filename:join(proplists:get_value(priv_dir,Config), "tmp"),
ok = ssh_test_lib:del_dirs(TmpDir),
ok = file:make_dir(TmpDir),
@@ -639,8 +640,8 @@ cli(Config) when is_list(Config) ->
%%% Test that get correct error message if you try to start a daemon
%%% on an adress that already runs a daemon see also seq10667
daemon_already_started(Config) when is_list(Config) ->
- SystemDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
{Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
@@ -654,8 +655,8 @@ daemon_already_started(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% check that known_hosts is updated correctly
known_hosts(Config) when is_list(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, PrivDir},{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -681,9 +682,9 @@ known_hosts(Config) when is_list(Config) ->
%%% Test that we can use keyes protected by pass phrases
pass_phrase(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
- PhraseArg = ?config(pass_phrase, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
+ PhraseArg = proplists:get_value(pass_phrase, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
@@ -700,8 +701,8 @@ pass_phrase(Config) when is_list(Config) ->
%%% Test that we can use key callback
key_callback(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
NoPubKeyDir = filename:join(UserDir, "nopubkey"),
file:make_dir(NoPubKeyDir),
@@ -724,8 +725,8 @@ key_callback(Config) when is_list(Config) ->
%%% Test that we can use key callback with callback options
key_callback_options(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
NoPubKeyDir = filename:join(UserDir, "nopubkey"),
file:make_dir(NoPubKeyDir),
@@ -751,8 +752,8 @@ key_callback_options(Config) when is_list(Config) ->
%%% Test that client does not hang if disconnects due to internal error
internal_error(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -768,8 +769,8 @@ internal_error(Config) when is_list(Config) ->
%%% Test ssh_connection:send/3
send(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -788,8 +789,8 @@ send(Config) when is_list(Config) ->
%%% Test ssh:connection_info([peername, sockname])
peername_sockname(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -838,8 +839,8 @@ ips(Name) when is_list(Name) ->
%%% Client receives close when server closes
close(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
{Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
@@ -861,8 +862,8 @@ close(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% Simulate that we try to close an already closed connection
double_close(Config) when is_list(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, 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),
@@ -881,8 +882,8 @@ double_close(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
daemon_opt_fd(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, 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),
@@ -908,8 +909,8 @@ daemon_opt_fd(Config) ->
%%--------------------------------------------------------------------
multi_daemon_opt_fd(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, 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),
@@ -943,8 +944,8 @@ multi_daemon_opt_fd(Config) ->
%%--------------------------------------------------------------------
packet_size_zero(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, 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),
@@ -974,7 +975,7 @@ packet_size_zero(Config) ->
%%--------------------------------------------------------------------
shell_no_unicode(Config) ->
- new_do_shell(?config(io,Config),
+ new_do_shell(proplists:get_value(io,Config),
[new_prompt,
{type,"io:format(\"hej ~p~n\",[42])."},
{expect,"hej 42"},
@@ -985,7 +986,7 @@ shell_no_unicode(Config) ->
%%--------------------------------------------------------------------
shell_unicode_string(Config) ->
- new_do_shell(?config(io,Config),
+ new_do_shell(proplists:get_value(io,Config),
[new_prompt,
{type,"io:format(\"こにちわ~ts~n\",[\"四二\"])."},
{expect,"こにちわ四二"},
@@ -1002,8 +1003,8 @@ openssh_zlib_basic_test(Config) ->
{skip, io_lib:format("~p compression is not supported",[L])};
true ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, 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},
@@ -1023,11 +1024,11 @@ openssh_zlib_basic_test(Config) ->
%%--------------------------------------------------------------------
ssh_info_print(Config) ->
%% Just check that ssh_print:info() crashes
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
PrintFile = filename:join(PrivDir,info),
UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
UnexpFun = fun(Msg,_Peer) ->
@@ -1103,8 +1104,8 @@ check_error(Error) ->
ct:fail(Error).
basic_test(Config) ->
- ClientOpts = ?config(client_opts, Config),
- ServerOpts = ?config(server_opts, Config),
+ ClientOpts = proplists:get_value(client_opts, Config),
+ ServerOpts = proplists:get_value(server_opts, Config),
{Pid, Host, Port} = ssh_test_lib:daemon(ServerOpts),
{ok, CM} = ssh:connect(Host, Port, ClientOpts),
diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl
index d9be1a32b7..c2bfc48449 100644
--- a/lib/ssh/test/ssh_benchmark_SUITE.erl
+++ b/lib/ssh/test/ssh_benchmark_SUITE.erl
@@ -29,7 +29,9 @@
-include_lib("ssh/src/ssh_userauth.hrl").
-suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
+suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]},
+ {timetrap,{minutes,3}}
+ ].
%%suite() -> [{ct_hooks,[ts_install_cth]}].
all() -> [{group, opensshc_erld}
@@ -63,8 +65,8 @@ end_per_suite(_Config) ->
init_per_group(opensshc_erld, Config) ->
case ssh_test_lib:ssh_type() of
openSSH ->
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, UserDir),
ssh_test_lib:setup_rsa(DataDir, UserDir),
ssh_test_lib:setup_ecdsa("256", DataDir, UserDir),
@@ -97,7 +99,7 @@ end_per_testcase(_Func, _Conf) ->
init_sftp_dirs(Config) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
SrcDir = filename:join(UserDir, "sftp_src"),
ok = file:make_dir(SrcDir),
SrcFile = "big_data",
@@ -127,8 +129,8 @@ openssh_client_shell(Config) ->
openssh_client_shell(Config, Options) ->
- SystemDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
KnownHosts = filename:join(UserDir, "known_hosts"),
{ok, TracerPid} = erlang_trace(),
@@ -184,7 +186,7 @@ openssh_client_shell(Config, Options) ->
end, Times),
ssh:stop_daemon(ServerPid),
ok
- after 10000 ->
+ after 60*1000 ->
ssh:stop_daemon(ServerPid),
exit(SlavePid, kill),
{fail, timeout}
@@ -200,11 +202,11 @@ openssh_client_sftp(Config) ->
openssh_client_sftp(Config, Options) ->
- SystemDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
- SftpSrcDir = ?config(sftp_src_dir, Config),
- SrcFile = ?config(src_file, Config),
- SrcSize = ?config(sftp_size, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+ SftpSrcDir = proplists:get_value(sftp_src_dir, Config),
+ SrcFile = proplists:get_value(src_file, Config),
+ SrcSize = proplists:get_value(sftp_size, Config),
KnownHosts = filename:join(UserDir, "known_hosts"),
{ok, TracerPid} = erlang_trace(),
@@ -215,6 +217,7 @@ openssh_client_sftp(Config, Options) ->
{root, SftpSrcDir}])]},
{failfun, fun ssh_test_lib:failfun/2}
| Options]),
+ ct:pal("ServerPid = ~p",[ServerPid]),
ct:sleep(500),
Cmd = lists:concat(["sftp",
" -b -",
@@ -231,7 +234,7 @@ openssh_client_sftp(Config, Options) ->
end),
receive
{SlavePid, _ClientResponse} ->
- ct:pal("ClientResponse = ~p",[_ClientResponse]),
+ ct:pal("ClientResponse = ~p~nServerPid = ~p",[_ClientResponse,ServerPid]),
{ok, List} = get_trace_list(TracerPid),
%%ct:pal("List=~p",[List]),
Times = find_times(List, [channel_open_close]),
@@ -260,7 +263,7 @@ openssh_client_sftp(Config, Options) ->
end, Times),
ssh:stop_daemon(ServerPid),
ok
- after 10000 ->
+ after 2*60*1000 ->
ssh:stop_daemon(ServerPid),
exit(SlavePid, kill),
{fail, timeout}
@@ -274,7 +277,7 @@ variants(Tag, Config) ->
[A|_] when is_atom(A) -> two_way
end,
[ [{Tag,tag_value(TagType,Alg)}]
- || Alg <- proplists:get_value(Tag, ?config(common_algs,Config))
+ || Alg <- proplists:get_value(Tag, proplists:get_value(common_algs,Config))
].
tag_value(two_way, Alg) -> [Alg];
@@ -445,10 +448,18 @@ increment({Alg,Sz,T},[]) ->
%%% API for the traceing
%%%
get_trace_list(TracerPid) ->
+ MonRef = monitor(process, TracerPid),
TracerPid ! {get_trace_list,self()},
receive
- {trace_list,L} -> {ok, pair_events(lists:reverse(L))}
- after 5000 -> {error,no_reply}
+ {trace_list,L} ->
+ demonitor(MonRef),
+ {ok, pair_events(lists:reverse(L))};
+ {'DOWN', MonRef, process, TracerPid, Info} ->
+ {error, {tracer_down,Info}}
+
+ after 3*60*1000 ->
+ demonitor(MonRef),
+ {error,no_reply}
end.
erlang_trace() ->
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index 0f757a0322..bcf3b01824 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -43,10 +43,15 @@ suite() ->
all() ->
[
{group, openssh},
+ small_interrupted_send,
interrupted_send,
start_shell,
start_shell_exec,
start_shell_exec_fun,
+ start_shell_sock_exec_fun,
+ start_shell_sock_daemon_exec,
+ connect_sock_not_tcp,
+ daemon_sock_not_tcp,
gracefull_invalid_version,
gracefull_invalid_start,
gracefull_invalid_long_start,
@@ -56,10 +61,11 @@ all() ->
max_channels_option
].
groups() ->
- [{openssh, [], payload() ++ ptty()}].
+ [{openssh, [], payload() ++ ptty() ++ sock()}].
payload() ->
[simple_exec,
+ simple_exec_sock,
small_cat,
big_cat,
send_after_exit].
@@ -69,9 +75,14 @@ ptty() ->
ptty_alloc,
ptty_alloc_pixel].
+sock() ->
+ [connect_sock_not_passive,
+ daemon_sock_not_passive
+ ].
+
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(Config) ->
Config.
@@ -111,6 +122,18 @@ simple_exec() ->
simple_exec(Config) when is_list(Config) ->
ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
{user_interaction, false}]),
+ do_simple_exec(ConnectionRef).
+
+
+simple_exec_sock(_Config) ->
+ {ok, Sock} = 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).
+
+
+
+do_simple_exec(ConnectionRef) ->
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId0,
"echo testing", infinity),
@@ -143,6 +166,30 @@ simple_exec(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
+connect_sock_not_tcp(_Config) ->
+ {ok,Sock} = gen_udp:open(0, []),
+ {error, not_tcp_socket} = ssh:connect(Sock, []),
+ gen_udp:close(Sock).
+
+%%--------------------------------------------------------------------
+daemon_sock_not_tcp(_Config) ->
+ {ok,Sock} = gen_udp:open(0, []),
+ {error, not_tcp_socket} = ssh:daemon(Sock),
+ gen_udp:close(Sock).
+
+%%--------------------------------------------------------------------
+connect_sock_not_passive(_Config) ->
+ {ok,Sock} = 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, []),
+ {error, not_passive_mode} = ssh:daemon(Sock),
+ gen_tcp:close(Sock).
+
+%%--------------------------------------------------------------------
small_cat() ->
[{doc, "Use 'cat' to echo small data block back to us."}].
@@ -315,54 +362,106 @@ ptty_alloc_pixel(Config) when is_list(Config) ->
ssh:close(ConnectionRef).
%%--------------------------------------------------------------------
+small_interrupted_send(Config) ->
+ K = 1024,
+ M = K*K,
+ do_interrupted_send(Config, 10*M, 4*K).
interrupted_send(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ M = 1024*1024,
+ do_interrupted_send(Config, 10*M, 4*M).
+
+do_interrupted_send(Config, SendSize, EchoSize) ->
+ 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
+ EchoSS_spec = {ssh_echo_server, [EchoSize,[{dbg,true}]]},
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {subsystems, [{"echo_n", {ssh_echo_server, [4000000]}}]}]),
-
+ {subsystems, [{"echo_n",EchoSS_spec}]}]),
+
+ ct:log("connect", []),
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),
-
- success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity),
-
- %% build 10MB binary
- Data = << <<X:32>> || X <- lists:seq(1,2500000)>>,
-
- %% expect remote end to send us 4MB back
- <<ExpectedData:4000000/binary, _/binary>> = Data,
-
- %% pre-adjust receive window so the other end doesn't block
- ssh_connection:adjust_window(ConnectionRef, ChannelId, size(ExpectedData) + 1),
-
- case ssh_connection:send(ConnectionRef, ChannelId, Data, 10000) of
- {error, closed} ->
- ok;
- Msg ->
- ct:fail({expected,{error,closed}, got, Msg})
- end,
- receive_data(ExpectedData, ConnectionRef, ChannelId),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid).
+ ct:log("connected", []),
+
+ %% build big binary
+ Data = << <<X:32>> || X <- lists:seq(1,SendSize div 4)>>,
+
+ %% expect remote end to send us EchoSize back
+ <<ExpectedData:EchoSize/binary, _/binary>> = Data,
+
+ %% Spawn listener. Otherwise we could get a deadlock due to filled buffers
+ Parent = self(),
+ ResultPid = spawn(
+ fun() ->
+ ct:log("open channel",[]),
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ct:log("start subsystem", []),
+ case ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity) of
+ success ->
+ Parent ! {self(), channelId, ChannelId},
+
+ Result =
+ try collect_data(ConnectionRef, ChannelId)
+ of
+ ExpectedData ->
+ ok;
+ _ ->
+ {fail,"unexpected result"}
+ catch
+ Class:Exception ->
+ {fail, io_lib:format("Exception ~p:~p",[Class,Exception])}
+ end,
+ Parent ! {self(), Result};
+ Other ->
+ Parent ! {self(), channelId, error, Other}
+ end
+ end),
+
+ receive
+ {ResultPid, channelId, ChannelId} ->
+ %% pre-adjust receive window so the other end doesn't block
+ ct:log("adjust window", []),
+ ssh_connection:adjust_window(ConnectionRef, ChannelId, size(ExpectedData) + 1),
+
+ ct:log("going to send ~p bytes", [size(Data)]),
+ case ssh_connection:send(ConnectionRef, ChannelId, Data, 30000) of
+ {error, closed} ->
+ ct:log("{error,closed} - That's what we expect :)", []),
+ ok;
+ Msg ->
+ ct:log("Got ~p - that's bad, very bad indeed",[Msg]),
+ ct:fail({expected,{error,closed}, got, Msg})
+ end,
+ ct:log("going to check the result (if it is available)", []),
+ receive
+ {ResultPid, Result} ->
+ ct:log("Got result: ~p", [Result]),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ Result
+ end;
+
+ {ResultPid, channelId, error, Other} ->
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ {fail, io_lib:format("ssh_connection:subsystem: ~p",[Other])}
+ end.
%%--------------------------------------------------------------------
start_shell() ->
[{doc, "Start a shell"}].
start_shell(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
@@ -391,10 +490,10 @@ start_shell_exec() ->
[{doc, "start shell to exec command"}].
start_shell_exec(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
@@ -425,10 +524,10 @@ start_shell_exec_fun() ->
[{doc, "start shell to exec command"}].
start_shell_exec_fun(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
@@ -456,12 +555,85 @@ start_shell_exec_fun(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+start_shell_sock_exec_fun() ->
+ [{doc, "start shell on tcp-socket to exec command"}].
+
+start_shell_sock_exec_fun(Config) when is_list(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),
+ 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}]),
+
+ {ok, Sock} = gen_tcp:connect(Host, Port, [{active,false}]),
+ {ok,ConnectionRef} = ssh:connect(Sock, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, true},
+ {user_dir, UserDir}]),
+
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "testing", infinity),
+
+ receive
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ ok
+ after 5000 ->
+ ct:fail("Exec Timeout")
+ end,
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+start_shell_sock_daemon_exec(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),
+ SysDir = proplists:get_value(data_dir, Config),
+ {ok,Sl} = gen_tcp:listen(0, [{active,false}]),
+ {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, _Pid} = ssh:daemon(Ss, [{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"},
+ {exec, fun ssh_exec/1}])
+ end),
+ {ok,Sc} = gen_tcp:accept(Sl),
+ {ok,ConnectionRef} = ssh:connect(Sc, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, true},
+ {user_dir, UserDir}]),
+
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "testing", infinity),
+
+ receive
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ ok
+ after 5000 ->
+ ct:fail("Exec Timeout")
+ end,
+
+ ssh:close(ConnectionRef).
+
+%%--------------------------------------------------------------------
gracefull_invalid_version(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
@@ -481,10 +653,10 @@ gracefull_invalid_version(Config) when is_list(Config) ->
end.
gracefull_invalid_start(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"}]),
@@ -503,10 +675,10 @@ gracefull_invalid_start(Config) when is_list(Config) ->
end.
gracefull_invalid_long_start(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"}]),
@@ -526,10 +698,10 @@ gracefull_invalid_long_start(Config) when is_list(Config) ->
gracefull_invalid_long_start_no_nl(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"}]),
@@ -551,10 +723,10 @@ stop_listener() ->
[{doc, "start ssh daemon, setup connections, stop listener, restart listner"}].
stop_listener(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid0, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
@@ -610,10 +782,10 @@ stop_listener(Config) when is_list(Config) ->
end.
start_subsystem_on_closed_channel(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
@@ -639,10 +811,10 @@ max_channels_option() ->
[{doc, "Test max_channels option"}].
max_channels_option(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
@@ -737,20 +909,36 @@ big_cat_rx(ConnectionRef, ChannelId, Acc) ->
timeout
end.
-receive_data(ExpectedData, ConnectionRef, ChannelId) ->
- ExpectedData = collect_data(ConnectionRef, ChannelId).
-
collect_data(ConnectionRef, ChannelId) ->
- collect_data(ConnectionRef, ChannelId, []).
+ ct:log("Listener ~p running! ConnectionRef=~p, ChannelId=~p",[self(),ConnectionRef,ChannelId]),
+ collect_data(ConnectionRef, ChannelId, [], 0).
-collect_data(ConnectionRef, ChannelId, Acc) ->
+collect_data(ConnectionRef, ChannelId, Acc, Sum) ->
+ TO = 5000,
receive
- {ssh_cm, ConnectionRef, {data, ChannelId, 0, Data}} ->
- collect_data(ConnectionRef, ChannelId, [Data | Acc]);
+ {ssh_cm, ConnectionRef, {data, ChannelId, 0, Data}} when is_binary(Data) ->
+ ct:log("collect_data: received ~p bytes. total ~p bytes",[size(Data),Sum+size(Data)]),
+ collect_data(ConnectionRef, ChannelId, [Data | Acc], Sum+size(Data));
{ssh_cm, ConnectionRef, {eof, ChannelId}} ->
- iolist_to_binary(lists:reverse(Acc))
- after 5000 ->
- timeout
+ try
+ iolist_to_binary(lists:reverse(Acc))
+ of
+ Bin ->
+ ct:log("collect_data: received eof.~nGot in total ~p bytes",[size(Bin)]),
+ Bin
+ catch
+ C:E ->
+ ct:log("collect_data: received eof.~nAcc is strange...~nException=~p:~p~nAcc=~p",
+ [C,E,Acc]),
+ {error,{C,E}}
+ end;
+ Msg ->
+ ct:log("collect_data: ***** unexpected message *****~n~p",[Msg]),
+ collect_data(ConnectionRef, ChannelId, Acc, Sum)
+
+ after TO ->
+ ct:log("collect_data: ----- Nothing received for ~p seconds -----~n",[]),
+ collect_data(ConnectionRef, ChannelId, Acc, Sum)
end.
%%%-------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl
index ed9bbe1b67..5387d21efd 100644
--- a/lib/ssh/test/ssh_echo_server.erl
+++ b/lib/ssh/test/ssh_echo_server.erl
@@ -26,15 +26,29 @@
-record(state, {
n,
id,
- cm
+ cm,
+ dbg = false
}).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
+-define(DBG(State,Fmt,Args),
+ case State#state.dbg of
+ true -> ct:log("~p:~p ~p "++Fmt, [?MODULE,?LINE,self()|Args]);
+ false -> ok
+ end).
+
+
init([N]) ->
- ct:pal("Echo server: ~p",[self()]),
- {ok, #state{n = N}}.
+ {ok, #state{n = N}};
+init([N,Opts]) ->
+ State = #state{n = N,
+ dbg = proplists:get_value(dbg,Opts,false)
+ },
+ ?DBG(State, "init([~p])",[N]),
+ {ok, State}.
handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
+ ?DBG(State, "ssh_channel_up Cid=~p ConnMngr=~p",[ChannelId,ConnectionManager]),
{ok, State#state{id = ChannelId,
cm = ConnectionManager}}.
@@ -42,32 +56,39 @@ handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State)
M = N - size(Data),
case M > 0 of
true ->
+ ?DBG(State, "ssh_cm data Cid=~p size(Data)=~p M=~p",[ChannelId,size(Data),M]),
ssh_connection:send(CM, ChannelId, Data),
{ok, State#state{n = M}};
false ->
<<SendData:N/binary, _/binary>> = Data,
+ ?DBG(State, "ssh_cm data Cid=~p size(Data)=~p M=~p size(SendData)=~p~nSend eof",[ChannelId,size(Data),M,size(SendData)]),
ssh_connection:send(CM, ChannelId, SendData),
ssh_connection:send_eof(CM, ChannelId),
{stop, ChannelId, State}
end;
handle_ssh_msg({ssh_cm, _ConnectionManager,
{data, _ChannelId, 1, Data}}, State) ->
+ ?DBG(State, "stderr: ~p",[Data]),
error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]),
{ok, State};
handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
+ ?DBG(State, "{eof ~p}",[_ChannelId]),
{ok, State};
-handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
+ ?DBG(State, "~p",[_Sig]),
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, _Error, _}},
- State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={exit_signal, ChannelId, _, _Error, _}}, State) ->
+ ?DBG(State, "~p",[_Sig]),
{stop, ChannelId, State};
-handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={exit_status, ChannelId, _Status}}, State) ->
+ ?DBG(State, "~p",[_Sig]),
{stop, ChannelId, State}.
terminate(_Reason, _State) ->
+ ?DBG(_State, "terminate ~p",[_Reason]),
ok.
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index 4ca6a473fa..61883c0647 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -27,7 +27,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-
+-include("ssh_test_lib.hrl").
%%% Test cases
-export([connectfun_disconnectfun_client/1,
@@ -126,19 +126,19 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
%%--------------------------------------------------------------------
init_per_group(hardening_tests, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
init_per_group(dir_options, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Make unreadable dir:
Dir_unreadable = filename:join(PrivDir, "unread"),
ok = file:make_dir(Dir_unreadable),
@@ -193,7 +193,7 @@ end_per_testcase(TestCase, Config) when TestCase == server_password_option;
TestCase == server_userpassword_option;
TestCase == server_pwdfun_option;
TestCase == server_pwdfun_4_option ->
- UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
ssh_test_lib:del_dirs(UserDir),
end_per_testcase(Config);
end_per_testcase(_TestCase, Config) ->
@@ -210,10 +210,10 @@ end_per_testcase(_Config) ->
%%% validate to server that uses the 'password' option
server_password_option(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"}]),
@@ -243,10 +243,10 @@ server_password_option(Config) when is_list(Config) ->
%%% validate to server that uses the 'password' option
server_userpassword_option(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, PrivDir},
{user_passwords, [{"vego", "morot"}]}]),
@@ -278,10 +278,10 @@ server_userpassword_option(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% validate to server that uses the 'pwdfun' option
server_pwdfun_option(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
CHKPWD = fun("foo",Pwd) -> Pwd=="bar";
(_,_) -> false
end,
@@ -316,10 +316,10 @@ server_pwdfun_option(Config) ->
%%--------------------------------------------------------------------
%%% validate to server that uses the 'pwdfun/4' option
server_pwdfun_4_option(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
PWDFUN = fun("foo",Pwd,{_,_},undefined) -> Pwd=="bar";
("fie",Pwd,{_,_},undefined) -> {Pwd=="bar",new_state};
("bandit",_,_,_) -> disconnect;
@@ -376,10 +376,10 @@ server_pwdfun_4_option(Config) ->
%%--------------------------------------------------------------------
server_pwdfun_4_option_repeat(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
%% Test that the state works
Parent = self(),
PWDFUN = fun("foo",P="bar",_,S) -> Parent!{P,S},true;
@@ -471,10 +471,10 @@ user_dir_option(Config) ->
%%--------------------------------------------------------------------
%%% validate client that uses the 'ssh_msg_debug_fun' option
ssh_msg_debug_fun_option_client(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
@@ -511,10 +511,10 @@ ssh_msg_debug_fun_option_client(Config) ->
%%--------------------------------------------------------------------
connectfun_disconnectfun_server(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
Ref = make_ref(),
@@ -549,10 +549,10 @@ connectfun_disconnectfun_server(Config) ->
%%--------------------------------------------------------------------
connectfun_disconnectfun_client(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
Ref = make_ref(),
@@ -580,10 +580,10 @@ connectfun_disconnectfun_client(Config) ->
%%--------------------------------------------------------------------
%%% validate client that uses the 'ssh_msg_debug_fun' option
ssh_msg_debug_fun_option_server(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end,
@@ -624,10 +624,10 @@ ssh_msg_debug_fun_option_server(Config) ->
%%--------------------------------------------------------------------
disconnectfun_option_server(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end,
@@ -659,10 +659,10 @@ disconnectfun_option_server(Config) ->
%%--------------------------------------------------------------------
disconnectfun_option_client(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end,
@@ -693,10 +693,10 @@ disconnectfun_option_client(Config) ->
%%--------------------------------------------------------------------
unexpectedfun_option_server(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end,
@@ -736,10 +736,10 @@ unexpectedfun_option_server(Config) ->
%%--------------------------------------------------------------------
unexpectedfun_option_client(Config) ->
- PrivDir = ?config(priv_dir, 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),
- SysDir = ?config(data_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
UnexpFun = fun(Msg,Peer) ->
@@ -859,8 +859,8 @@ ms_passed(T0) ->
%%--------------------------------------------------------------------
ssh_daemon_minimal_remote_max_packet_size_option(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ SystemDir = proplists:get_value(data_dir, 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),
@@ -957,8 +957,8 @@ ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false
ssh_connect_negtimeout(Config, Parallel) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
NegTimeOut = 2000, % ms
ct:log("Parallel: ~p",[Parallel]),
@@ -990,8 +990,8 @@ ssh_connect_nonegtimeout_connected_sequential(Config) ->
ssh_connect_nonegtimeout_connected(Config, Parallel) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
NegTimeOut = 2000, % ms
ct:log("Parallel: ~p",[Parallel]),
@@ -1067,7 +1067,7 @@ connect_fun(ssh__connect, Config) ->
fun(Host,Port) ->
ssh_test_lib:connect(Host, Port,
[{silently_accept_hosts, true},
- {user_dir, ?config(priv_dir,Config)},
+ {user_dir, proplists:get_value(priv_dir,Config)},
{user_interaction, false},
{user, "carni"},
{password, "meat"}
@@ -1092,8 +1092,8 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
ct:log("Connect(~p,~p) -> ~p",[Host,Port,R]),
R
end,
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
MaxSessions = 5,
{Pid, Host, Port} = ssh_test_lib:daemon([
{system_dir, SystemDir},
diff --git a/lib/ssh/test/ssh_property_test_SUITE.erl b/lib/ssh/test/ssh_property_test_SUITE.erl
index c5cc36c45e..c8aabcedb7 100644
--- a/lib/ssh/test/ssh_property_test_SUITE.erl
+++ b/lib/ssh/test/ssh_property_test_SUITE.erl
@@ -57,7 +57,7 @@ init_per_suite(Config) ->
%%% One group in this suite happens to support only QuickCheck, so skip it
%%% if we run proper.
init_per_group(client_server, Config) ->
- case ?config(property_test_tool,Config) of
+ case proplists:get_value(property_test_tool,Config) of
eqc -> Config;
X -> {skip, lists:concat([X," is not supported"])}
end;
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 57404f40db..4fac1f718a 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("ssh/src/ssh.hrl"). % ?UINT32, ?BYTE, #ssh{} ...
-include_lib("ssh/src/ssh_transport.hrl").
-include_lib("ssh/src/ssh_auth.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -87,7 +88,7 @@ groups() ->
init_per_suite(Config) ->
- start_std_daemon( setup_dirs( start_apps(Config))).
+ ?CHECK_CRYPTO(start_std_daemon( setup_dirs( start_apps(Config)))).
end_per_suite(Config) ->
stop_apps(Config).
@@ -107,11 +108,11 @@ init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ;
gex_client_init_option_groups ->
[{dh_gex_groups, [{2345, 3, 41}]}];
gex_client_init_option_groups_file ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
F = filename:join(DataDir, "dh_group_test"),
[{dh_gex_groups, {file,F}}];
gex_client_init_option_groups_moduli_file ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
F = filename:join(DataDir, "dh_group_test.moduli"),
[{dh_gex_groups, {ssh_moduli_file,F}}];
_ when TC == gex_server_gex_limit ;
@@ -589,21 +590,21 @@ stop_apps(_Config) ->
setup_dirs(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_rsa(DataDir, PrivDir),
Config.
-system_dir(Config) -> filename:join(?config(priv_dir, Config), system).
+system_dir(Config) -> filename:join(proplists:get_value(priv_dir, Config), system).
-user_dir(Config) -> ?config(priv_dir, Config).
+user_dir(Config) -> proplists:get_value(priv_dir, Config).
%%%----------------------------------------------------------------
start_std_daemon(Config) ->
start_std_daemon(Config, []).
start_std_daemon(Config, ExtraOpts) ->
- PrivDir = ?config(priv_dir, 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),
UserPasswords = [{"user1","pwd1"}],
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl
index f1a909cbd0..b10ec3707f 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE.erl
+++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl
@@ -21,6 +21,7 @@
-module(ssh_renegotiate_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -45,7 +46,7 @@ tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
@@ -108,10 +109,10 @@ rekey(Config) ->
rekey_limit() -> [{timetrap,{seconds,400}}].
rekey_limit(Config) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
DataFile = filename:join(UserDir, "rekey.data"),
- Algs = ?config(preferred_algorithms, Config),
+ Algs = proplists:get_value(preferred_algorithms, Config),
{Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
{preferred_algorithms,Algs}]),
@@ -154,10 +155,10 @@ rekey_limit(Config) ->
%%% Test rekeying with simulataneous send request
renegotiate1(Config) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
DataFile = filename:join(UserDir, "renegotiate1.data"),
- Algs = ?config(preferred_algorithms, Config),
+ Algs = proplists:get_value(preferred_algorithms, Config),
{Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
{preferred_algorithms,Algs}]),
@@ -194,10 +195,10 @@ renegotiate1(Config) ->
%%% Test rekeying with inflight messages from peer
renegotiate2(Config) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
DataFile = filename:join(UserDir, "renegotiate2.data"),
- Algs = ?config(preferred_algorithms, Config),
+ Algs = proplists:get_value(preferred_algorithms, Config),
{Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
{preferred_algorithms,Algs}]),
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index f6d7be41d6..19ad81e7da 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -1,4 +1,4 @@
-%%
+%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
@@ -26,7 +26,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-
+-include("ssh_test_lib.hrl").
% Default timetrap timeout
-define(default_timeout, ?t:minutes(1)).
@@ -45,10 +45,13 @@ all() ->
init_per_suite(Config) ->
- ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
- [file:native_name_encoding(),io:getopts()]),
- ssh:start(),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
+ [file:native_name_encoding(),io:getopts()]),
+ ssh:start(),
+ Config
+ end).
end_per_suite(_onfig) ->
ssh:stop().
@@ -86,42 +89,43 @@ groups() ->
write_file, write_file_iolist, write_big_file, sftp_read_big_file,
rename_file, mk_rm_dir, remove_file, links,
retrieve_attributes, set_attributes, async_read,
- async_write, position, pos_read, pos_write
+ async_write, position, pos_read, pos_write,
+ start_channel_sock
]}
].
init_per_group(not_unicode, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
[{user, "Alladin"},
{passwd, "Sesame"},
{data, <<"Hello world!">>},
- {filename, filename:join(PrivDir, "sftp.txt")},
- {testfile, filename:join(PrivDir, "test.txt")},
- {linktest, filename:join(PrivDir, "link_test.txt")},
- {tar_filename, filename:join(PrivDir, "sftp_tar_test.tar")},
- {tar_F1_txt, "f1.txt"},
+ {filename, "sftp.txt"},
+ {testfile, "test.txt"},
+ {linktest, "link_test.txt"},
+ {tar_filename, "sftp_tar_test.tar"},
+ {tar_F1_txt, "f1.txt"},
{datadir_tar, filename:join(DataDir,"sftp_tar_test_data")}
| Config];
init_per_group(unicode, Config) ->
- case file:native_name_encoding() of
- utf8 ->
+ case (file:native_name_encoding() == utf8)
+ andalso ("四" == [22235])
+ of
+ true ->
ct:comment("Begin ~p",[grps(Config)]),
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
NewConfig =
[{user, "åke高兴"},
{passwd, "ärlig日本じん"},
{data, <<"foobar å 一二三四いちにさんち">>},
- {filename, filename:join(PrivDir, "sftp瑞点.txt")},
- {testfile, filename:join(PrivDir, "testハンス.txt")},
- {linktest, filename:join(PrivDir, "link_test語.txt")},
- {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")},
- {tar_F1_txt, "F一.txt"},
- {tar_F3_txt, "f3.txt"},
- {tar_F4_txt, "g四.txt"},
+ {filename, "sftp瑞点.txt"},
+ {testfile, "testハンス.txt"},
+ {linktest, "link_test語.txt"},
+ {tar_filename, "sftp_tar_test一二三.tar"},
+ {tar_F1_txt, "F一.txt"},
+ {tar_F3_txt, "f3.txt"},
+ {tar_F4_txt, "g四.txt"},
{datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")}
| lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end,
Config,
@@ -131,7 +135,7 @@ init_per_group(unicode, Config) ->
]
)
],
- FN = fn(?config(tar_F1_txt,NewConfig), NewConfig),
+ FN = fn(proplists:get_value(tar_F1_txt,NewConfig), NewConfig),
case catch file:read_file(FN) of
{ok,FN_contents} ->
ct:log("Readable file:read_file(~tp) ->~n~tp",[FN,FN_contents]),
@@ -147,10 +151,10 @@ init_per_group(unicode, Config) ->
init_per_group(erlang_server, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
- PrivDir = ?config(priv_dir, Config),
- SysDir = ?config(data_dir, Config),
- User = ?config(user, Config),
- Passwd = ?config(passwd, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
+ User = proplists:get_value(user, Config),
+ Passwd = proplists:get_value(passwd, Config),
Sftpd = {_, HostX, PortX} =
ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, PrivDir},
@@ -176,12 +180,12 @@ init_per_group(openssh_server, Config) ->
init_per_group(remote_tar, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
- {Host,Port} = ?config(peer, Config),
- ct:log("Server (~p) at ~p:~p",[?config(group,Config),Host,Port]),
- User = ?config(user, Config),
- Passwd = ?config(passwd, Config),
+ {Host,Port} = proplists:get_value(peer, Config),
+ ct:log("Server (~p) at ~p:~p",[proplists:get_value(group,Config),Host,Port]),
+ User = proplists:get_value(user, Config),
+ Passwd = proplists:get_value(passwd, Config),
{ok, Connection} =
- case ?config(group, Config) of
+ case proplists:get_value(group, Config) of
erlang_server ->
ssh:connect(Host, Port,
[{user, User},
@@ -216,10 +220,10 @@ end_per_group(_, Config) ->
%%--------------------------------------------------------------------
init_per_testcase(sftp_nonexistent_subsystem, Config) ->
- PrivDir = ?config(priv_dir, Config),
- SysDir = ?config(data_dir, Config),
- User = ?config(user, Config),
- Passwd = ?config(passwd, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SysDir = proplists:get_value(data_dir, Config),
+ User = proplists:get_value(user, Config),
+ Passwd = proplists:get_value(passwd, Config),
Sftpd = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, PrivDir},
{subsystems, []},
@@ -228,14 +232,14 @@ init_per_testcase(sftp_nonexistent_subsystem, Config) ->
]),
[{sftpd, Sftpd} | Config];
-init_per_testcase(version_option, Config) ->
- prep(Config),
+init_per_testcase(version_option, Config0) ->
+ Config = prepare(Config0),
TmpConfig0 = lists:keydelete(watchdog, 1, Config),
TmpConfig = lists:keydelete(sftp, 1, TmpConfig0),
Dog = ct:timetrap(?default_timeout),
- {_,Host, Port} = ?config(sftpd, Config),
- User = ?config(user, Config),
- Passwd = ?config(passwd, Config),
+ {_,Host, Port} = proplists:get_value(sftpd, Config),
+ User = proplists:get_value(user, Config),
+ Passwd = proplists:get_value(passwd, Config),
{ok, ChannelPid, Connection} =
ssh_sftp:start_channel(Host, Port,
[{sftp_vsn, 3},
@@ -246,18 +250,18 @@ init_per_testcase(version_option, Config) ->
Sftp = {ChannelPid, Connection},
[{sftp,Sftp}, {watchdog, Dog} | TmpConfig];
-init_per_testcase(Case, Config0) ->
- prep(Config0),
+init_per_testcase(Case, Config00) ->
+ Config0 = prepare(Config00),
Config1 = lists:keydelete(watchdog, 1, Config0),
Config2 = lists:keydelete(sftp, 1, Config1),
Dog = ct:timetrap(2 * ?default_timeout),
- User = ?config(user, Config0),
- Passwd = ?config(passwd, Config0),
+ User = proplists:get_value(user, Config0),
+ Passwd = proplists:get_value(passwd, Config0),
Config =
- case ?config(group,Config2) of
+ case proplists:get_value(group,Config2) of
erlang_server ->
- {_,Host, Port} = ?config(sftpd, Config2),
+ {_,Host, Port} = proplists:get_value(sftpd, Config2),
{ok, ChannelPid, Connection} =
ssh_sftp:start_channel(Host, Port,
[{user, User},
@@ -279,11 +283,11 @@ init_per_testcase(Case, Config0) ->
[{sftp, Sftp}, {watchdog, Dog} | Config2]
end,
- case catch ?config(remote_tar,Config) of
+ case catch proplists:get_value(remote_tar,Config) of
%% The 'catch' is for the case of Config={skip,...}
true ->
%% Provide a ChannelPid independent of the sftp-channel already opened.
- {ok,ChPid2} = ssh_sftp:start_channel(?config(connection,Config)),
+ {ok,ChPid2} = ssh_sftp:start_channel(proplists:get_value(connection,Config)),
[{channel_pid2,ChPid2} | Config];
_ ->
Config
@@ -292,16 +296,16 @@ init_per_testcase(Case, Config0) ->
end_per_testcase(sftp_nonexistent_subsystem, Config) ->
Config;
end_per_testcase(rename_file, Config) ->
- NewFileName = ?config(testfile, Config),
+ NewFileName = proplists:get_value(testfile, Config),
file:delete(NewFileName),
end_per_testcase(Config);
end_per_testcase(_, Config) ->
end_per_testcase(Config).
end_per_testcase(Config) ->
- {Sftp, Connection} = ?config(sftp, Config),
+ {Sftp, Connection} = proplists:get_value(sftp, Config),
ok = ssh_sftp:stop_channel(Sftp),
- catch ssh_sftp:stop_channel(?config(channel_pid2, Config)),
+ catch ssh_sftp:stop_channel(proplists:get_value(channel_pid2, Config)),
ok = ssh:close(Connection).
%%--------------------------------------------------------------------
@@ -310,9 +314,9 @@ end_per_testcase(Config) ->
open_close_file() ->
[{doc, "Test API functions open/3 and close/2"}].
open_close_file(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
+ FileName = proplists:get_value(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
ok = open_close_file(Sftp, FileName, [read]),
ok = open_close_file(Sftp, FileName, [write]),
@@ -329,9 +333,9 @@ open_close_file(Server, File, Mode) ->
open_close_dir() ->
[{doc, "Test API functions opendir/2 and close/2"}].
open_close_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Sftp, _} = ?config(sftp, Config),
- FileName = ?config(filename, Config),
+ PrivDir = proplists:get_value(sftp_priv_dir, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
{ok, Handle} = ssh_sftp:opendir(Sftp, PrivDir),
ok = ssh_sftp:close(Sftp, Handle),
@@ -341,8 +345,8 @@ open_close_dir(Config) when is_list(Config) ->
read_file() ->
[{doc, "Test API funtion read_file/2"}].
read_file(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Data} = ssh_sftp:read_file(Sftp, FileName),
{ok, Data} = ssh_sftp:read_file(Sftp, FileName),
{ok, Data} = file:read_file(FileName).
@@ -351,8 +355,8 @@ read_file(Config) when is_list(Config) ->
read_dir() ->
[{doc,"Test API function list_dir/2"}].
read_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Sftp, _} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(sftp_priv_dir, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
ct:log("sftp list dir: ~p~n", [Files]).
@@ -360,8 +364,8 @@ read_dir(Config) when is_list(Config) ->
write_file() ->
[{doc, "Test API function write_file/2"}].
write_file(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary("Hej hopp!"),
ok = ssh_sftp:write_file(Sftp, FileName, [Data]),
@@ -371,8 +375,8 @@ write_file(Config) when is_list(Config) ->
write_file_iolist() ->
[{doc, "Test API function write_file/2 with iolists"}].
write_file_iolist(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary("Hej hopp!"),
lists:foreach(
@@ -392,8 +396,8 @@ write_file_iolist(Config) when is_list(Config) ->
write_big_file() ->
[{doc, "Test API function write_file/2 with big data"}].
write_big_file(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary(lists:duplicate(750000,"a")),
ok = ssh_sftp:write_file(Sftp, FileName, [Data]),
@@ -403,8 +407,8 @@ write_big_file(Config) when is_list(Config) ->
sftp_read_big_file() ->
[{doc, "Test API function read_file/2 with big data"}].
sftp_read_big_file(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary(lists:duplicate(750000,"a")),
ct:log("Data size to write is ~p bytes",[size(Data)]),
@@ -415,9 +419,9 @@ sftp_read_big_file(Config) when is_list(Config) ->
remove_file() ->
[{doc,"Test API function delete/2"}].
remove_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- FileName = ?config(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(sftp_priv_dir, Config),
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
true = lists:member(filename:basename(FileName), Files),
@@ -429,11 +433,11 @@ remove_file(Config) when is_list(Config) ->
rename_file() ->
[{doc, "Test API function rename_file/2"}].
rename_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- FileName = ?config(filename, Config),
- NewFileName = ?config(testfile, Config),
+ PrivDir = proplists:get_value(sftp_priv_dir, Config),
+ FileName = proplists:get_value(filename, Config),
+ NewFileName = proplists:get_value(testfile, Config),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
ct:log("FileName: ~p, Files: ~p~n", [FileName, Files]),
true = lists:member(filename:basename(FileName), Files),
@@ -449,8 +453,8 @@ rename_file(Config) when is_list(Config) ->
mk_rm_dir() ->
[{doc,"Test API functions make_dir/2, del_dir/2"}].
mk_rm_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Sftp, _} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(sftp_priv_dir, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
DirName = filename:join(PrivDir, "test"),
ok = ssh_sftp:make_dir(Sftp, DirName),
@@ -467,9 +471,9 @@ links(Config) when is_list(Config) ->
{win32, _} ->
{skip, "Links are not fully supported by windows"};
_ ->
- {Sftp, _} = ?config(sftp, Config),
- FileName = ?config(filename, Config),
- LinkFileName = ?config(linktest, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
+ FileName = proplists:get_value(filename, Config),
+ LinkFileName = proplists:get_value(linktest, Config),
ok = ssh_sftp:make_symlink(Sftp, LinkFileName, FileName),
{ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName)
@@ -479,9 +483,9 @@ links(Config) when is_list(Config) ->
retrieve_attributes() ->
[{doc, "Test API function read_file_info/3"}].
retrieve_attributes(Config) when is_list(Config) ->
- FileName = ?config(filename, Config),
+ FileName = proplists:get_value(filename, Config),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, FileInfo} = ssh_sftp:read_file_info(Sftp, FileName),
{ok, NewFileInfo} = file:read_file_info(FileName),
@@ -492,9 +496,9 @@ retrieve_attributes(Config) when is_list(Config) ->
set_attributes() ->
[{doc,"Test API function write_file_info/3"}].
set_attributes(Config) when is_list(Config) ->
- FileName = ?config(testfile, Config),
+ FileName = proplists:get_value(testfile, Config),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok,Fd} = file:open(FileName, write),
io:put_chars(Fd,"foo"),
ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#400}),
@@ -507,9 +511,9 @@ set_attributes(Config) when is_list(Config) ->
async_read() ->
[{doc,"Test API aread/3"}].
async_read(Config) when is_list(Config) ->
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
- FileName = ?config(filename, Config),
+ FileName = proplists:get_value(filename, Config),
{ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]),
{async, Ref} = ssh_sftp:aread(Sftp, Handle, 20),
@@ -526,8 +530,8 @@ async_read(Config) when is_list(Config) ->
async_write() ->
[{doc,"Test API awrite/3"}].
async_write(Config) when is_list(Config) ->
- {Sftp, _} = ?config(sftp, Config),
- FileName = ?config(testfile, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
+ FileName = proplists:get_value(testfile, Config),
{ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]),
Data = list_to_binary("foobar"),
{async, Ref} = ssh_sftp:awrite(Sftp, Handle, Data),
@@ -544,8 +548,8 @@ async_write(Config) when is_list(Config) ->
position() ->
[{doc, "Test API functions position/3"}].
position(Config) when is_list(Config) ->
- FileName = ?config(testfile, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(testfile, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary("1234567890"),
ok = ssh_sftp:write_file(Sftp, FileName, [Data]),
@@ -573,8 +577,8 @@ position(Config) when is_list(Config) ->
pos_read() ->
[{doc,"Test API functions pread/3 and apread/3"}].
pos_read(Config) when is_list(Config) ->
- FileName = ?config(testfile, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(testfile, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
Data = list_to_binary("Hej hopp!"),
ok = ssh_sftp:write_file(Sftp, FileName, [Data]),
@@ -600,8 +604,8 @@ pos_read(Config) when is_list(Config) ->
pos_write() ->
[{doc,"Test API functions pwrite/4 and apwrite/4"}].
pos_write(Config) when is_list(Config) ->
- FileName = ?config(testfile, Config),
- {Sftp, _} = ?config(sftp, Config),
+ FileName = proplists:get_value(testfile, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]),
@@ -625,12 +629,65 @@ pos_write(Config) when is_list(Config) ->
{ok, NewData1} = ssh_sftp:read_file(Sftp, FileName).
%%--------------------------------------------------------------------
+start_channel_sock(Config) ->
+ LoginOpts =
+ case proplists:get_value(group,Config) of
+ erlang_server ->
+ [{user, proplists:get_value(user, Config)},
+ {password, proplists:get_value(passwd, Config)}];
+ openssh_server ->
+ [] % Use public key
+ end,
+
+ Opts = [{user_interaction, false},
+ {silently_accept_hosts, true}
+ | LoginOpts],
+
+ {Host,Port} = proplists:get_value(peer, Config),
+
+ %% Get a tcp socket
+ {ok, Sock} = gen_tcp:connect(Host, Port, [{active,false}]),
+
+ %% and open one channel on one new Connection
+ {ok, ChPid1, Conn} = ssh_sftp:start_channel(Sock, Opts),
+
+ %% Test that the channel is usable
+ FileName = proplists:get_value(filename, Config),
+ ok = open_close_file(ChPid1, FileName, [read]),
+ ok = open_close_file(ChPid1, FileName, [write]),
+
+ %% Try to open a second channel on the Connection
+ {ok, ChPid2} = ssh_sftp:start_channel(Conn, Opts),
+ ok = open_close_file(ChPid1, FileName, [read]),
+ ok = open_close_file(ChPid2, FileName, [read]),
+
+ %% Test that the second channel still works after closing the first one
+ ok = ssh_sftp:stop_channel(ChPid1),
+ ok = open_close_file(ChPid2, FileName, [write]),
+
+ %% Test the Connection survives that all channels are closed
+ ok = ssh_sftp:stop_channel(ChPid2),
+ {ok, ChPid3} = ssh_sftp:start_channel(Conn, Opts),
+ ok = open_close_file(ChPid3, FileName, [write]),
+
+ %% Test that a closed channel really is closed
+ {error, closed} = ssh_sftp:open(ChPid2, FileName, [write]),
+ ok = ssh_sftp:stop_channel(ChPid3),
+
+ %% Test that the socket is closed when the Connection closes
+ ok = ssh:close(Conn),
+ timer:sleep(400), %% Until the stop sequence is fixed
+ {error,einval} = inet:getopts(Sock, [active]),
+
+ ok.
+
+%%--------------------------------------------------------------------
sftp_nonexistent_subsystem() ->
[{doc, "Try to execute sftp subsystem on a server that does not support it"}].
sftp_nonexistent_subsystem(Config) when is_list(Config) ->
- {_,Host, Port} = ?config(sftpd, Config),
- User = ?config(user, Config),
- Passwd = ?config(passwd, Config),
+ {_,Host, Port} = proplists:get_value(sftpd, Config),
+ User = proplists:get_value(user, Config),
+ Passwd = proplists:get_value(passwd, Config),
{error,"server failed to start sftp subsystem"} =
ssh_sftp:start_channel(Host, Port,
[{user_interaction, false},
@@ -646,20 +703,20 @@ version_option(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
create_empty_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
erl_tar:close(Handle),
- {ChPid,_} = ?config(sftp,Config),
+ {ChPid,_} = proplists:get_value(sftp,Config),
{ok, #file_info{type=regular}} =
ssh_sftp:read_file_info(ChPid, TarFileName).
%%--------------------------------------------------------------------
files_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
- F1 = ?config(tar_F1_txt, Config),
+ F1 = proplists:get_value(tar_F1_txt, Config),
ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose]),
ok = erl_tar:add(Handle, fn("f2.txt",Config), "f2.txt", [verbose]),
ok = erl_tar:close(Handle),
@@ -667,8 +724,8 @@ files_to_tar(Config) ->
%%--------------------------------------------------------------------
ascii_filename_ascii_contents_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
ok = erl_tar:add(Handle, fn("f2.txt",Config), "f2.txt", [verbose]),
ok = erl_tar:close(Handle),
@@ -676,12 +733,12 @@ ascii_filename_ascii_contents_to_tar(Config) ->
%%--------------------------------------------------------------------
ascii_filename_unicode_contents_to_tar(Config) ->
- case ?config(tar_F3_txt, Config) of
+ case proplists:get_value(tar_F3_txt, Config) of
undefined ->
{skip, "Unicode test"};
Fn ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]),
ok = erl_tar:close(Handle),
@@ -690,12 +747,12 @@ ascii_filename_unicode_contents_to_tar(Config) ->
%%--------------------------------------------------------------------
unicode_filename_ascii_contents_to_tar(Config) ->
- case ?config(tar_F4_txt, Config) of
+ case proplists:get_value(tar_F4_txt, Config) of
undefined ->
{skip, "Unicode test"};
Fn ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]),
ok = erl_tar:close(Handle),
@@ -704,8 +761,8 @@ unicode_filename_ascii_contents_to_tar(Config) ->
%%--------------------------------------------------------------------
big_file_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose]),
ok = erl_tar:close(Handle),
@@ -714,18 +771,18 @@ big_file_to_tar(Config) ->
%%--------------------------------------------------------------------
files_chunked_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
- F1 = ?config(tar_F1_txt, Config),
+ F1 = proplists:get_value(tar_F1_txt, Config),
ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]),
ok = erl_tar:close(Handle),
chk_tar([F1], Config).
%%--------------------------------------------------------------------
directory_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
ok = erl_tar:add(Handle, fn("d1",Config), "d1", [verbose]),
ok = erl_tar:close(Handle),
@@ -733,8 +790,8 @@ directory_to_tar(Config) ->
%%--------------------------------------------------------------------
binaries_to_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
- TarFileName = ?config(tar_filename, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
Bin = <<"A binary">>,
ok = erl_tar:add(Handle, Bin, "b1", [verbose]),
@@ -743,15 +800,15 @@ binaries_to_tar(Config) ->
%%--------------------------------------------------------------------
null_crypto_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
Cinit = fun() -> {ok, no_state, _SendSize=5} end,
Cenc = fun(Bin,CState) -> {ok,Bin,CState,_SendSize=5} end,
Cend = fun(Bin,_CState) -> {ok,Bin} end,
C = {Cinit,Cenc,Cend},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]),
Bin = <<"A binary">>,
- F1 = ?config(tar_F1_txt, Config),
+ F1 = proplists:get_value(tar_F1_txt, Config),
ok = erl_tar:add(Handle, Bin, "b1", [verbose]),
ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]),
ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose,{chunks,15000}]),
@@ -760,16 +817,16 @@ null_crypto_tar(Config) ->
%%--------------------------------------------------------------------
simple_crypto_tar_small(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
Cinit = fun() -> {ok, no_state, _Size=6} end,
Cenc = fun(Bin,CState) -> {ok,stuff(Bin),CState,_SendSize=5} end,
Cdec = fun(Bin,CState) -> {ok,unstuff(Bin),CState,_Size=4} end,
Cend = fun(Bin,_CState) -> {ok,stuff(Bin)} end,
C = {Cinit,Cenc,Cend},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]),
Bin = <<"A binary">>,
- F1 = ?config(tar_F1_txt, Config),
+ F1 = proplists:get_value(tar_F1_txt, Config),
ok = erl_tar:add(Handle, Bin, "b1", [verbose]),
ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]),
ok = erl_tar:close(Handle),
@@ -777,16 +834,16 @@ simple_crypto_tar_small(Config) ->
%%--------------------------------------------------------------------
simple_crypto_tar_big(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
Cinit = fun() -> {ok, no_state, _SendSize=6} end,
Cenc = fun(Bin,CState) -> {ok,stuff(Bin),CState,_SendSize=5} end,
Cdec = fun(Bin,CState) -> {ok,unstuff(Bin),CState,_SendSize=4} end,
Cend = fun(Bin,_CState) -> {ok,stuff(Bin)} end,
C = {Cinit,Cenc,Cend},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]),
Bin = <<"A binary">>,
- F1 = ?config(tar_F1_txt, Config),
+ F1 = proplists:get_value(tar_F1_txt, Config),
ok = erl_tar:add(Handle, Bin, "b1", [verbose]),
ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]),
ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose,{chunks,15000}]),
@@ -799,12 +856,12 @@ unstuff(Bin) -> << <<C>> || <<C,C>> <= Bin >>.
%%--------------------------------------------------------------------
read_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
NameBins = lists:sort(
[{"b1",<<"A binary">>},
{"b2",list_to_binary(lists:duplicate(750000,"a"))}
]),
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
[ok = erl_tar:add(HandleWrite, Bin, Name, [verbose])
|| {Name,Bin} <- NameBins],
@@ -814,7 +871,7 @@ read_tar(Config) ->
%%--------------------------------------------------------------------
read_null_crypto_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
NameBins = lists:sort(
[{"b1",<<"A binary">>},
{"b2",list_to_binary(lists:duplicate(750000,"a"))}
@@ -827,7 +884,7 @@ read_null_crypto_tar(Config) ->
Cw = {Cinitw,Cenc,Cendw},
Cr = {Cinitr,Cdec},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]),
[ok = erl_tar:add(HandleWrite, Bin, Name, [verbose])
|| {Name,Bin} <- NameBins],
@@ -837,7 +894,7 @@ read_null_crypto_tar(Config) ->
%%--------------------------------------------------------------------
read_crypto_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
NameBins = lists:sort(
[{"b1",<<"A binary">>},
{"b2",list_to_binary(lists:duplicate(750000,"a"))}
@@ -851,7 +908,7 @@ read_crypto_tar(Config) ->
Cw = {Cinitw,Cenc,Cendw},
Cr = {Cinitr,Cdec},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]),
[ok = erl_tar:add(HandleWrite, Bin, Name, [verbose])
|| {Name,Bin} <- NameBins],
@@ -861,7 +918,7 @@ read_crypto_tar(Config) ->
%%--------------------------------------------------------------------
aes_cbc256_crypto_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
NameBins = lists:sort(
[{"b1",<<"A binary">>},
{"b2",list_to_binary(lists:duplicate(750000,"a"))},
@@ -891,7 +948,7 @@ aes_cbc256_crypto_tar(Config) ->
end,
Cw = {Cinitw,Cenc,Cendw},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]),
[ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins],
ok = erl_tar:close(HandleWrite),
@@ -906,7 +963,7 @@ pad(BlockSize, Bin) ->
%%--------------------------------------------------------------------
aes_ctr_stream_crypto_tar(Config) ->
- ChPid2 = ?config(channel_pid2, Config),
+ ChPid2 = proplists:get_value(channel_pid2, Config),
NameBins = lists:sort(
[{"b1",<<"A binary">>},
{"b2",list_to_binary(lists:duplicate(750000,"a"))},
@@ -934,7 +991,7 @@ aes_ctr_stream_crypto_tar(Config) ->
end,
Cw = {Cinitw,Cenc,Cendw},
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
{ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]),
[ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins],
ok = erl_tar:close(HandleWrite),
@@ -945,12 +1002,12 @@ aes_ctr_stream_crypto_tar(Config) ->
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-prep(Config) ->
- DataDir = ?config(data_dir, Config),
- TestFile = ?config(filename, Config),
- TestFile1 = ?config(testfile, Config),
- TestLink = ?config(linktest, Config),
- TarFileName = ?config(tar_filename, Config),
+oldprep(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ TestFile = proplists:get_value(filename, Config),
+ TestFile1 = proplists:get_value(testfile, Config),
+ TestLink = proplists:get_value(linktest, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
file:delete(TestFile),
file:delete(TestFile1),
@@ -965,16 +1022,46 @@ prep(Config) ->
ok = file:write_file_info(TestFile,
FileInfo#file_info{mode = Mode}).
+prepare(Config0) ->
+ PrivDir = proplists:get_value(priv_dir, Config0),
+ Dir = filename:join(PrivDir, random_chars(10)),
+ file:make_dir(Dir),
+ Keys = [filename,
+ testfile,
+ linktest,
+ tar_filename],
+ Config1 = foldl_keydelete(Keys, Config0),
+ Config2 = lists:foldl(fun({Key,Name}, ConfAcc) ->
+ [{Key, filename:join(Dir,Name)} | ConfAcc]
+ end,
+ Config1,
+ lists:zip(Keys, [proplists:get_value(K,Config0) || K<-Keys])),
+
+ DataDir = proplists:get_value(data_dir, Config2),
+ FilenameSrc = filename:join(DataDir, "sftp.txt"),
+ FilenameDst = proplists:get_value(filename, Config2),
+ {ok,_} = file:copy(FilenameSrc, FilenameDst),
+ [{sftp_priv_dir,Dir} | Config2].
+
+
+random_chars(N) -> [crypto:rand_uniform($a,$z) || _<-lists:duplicate(N,x)].
+
+foldl_keydelete(Keys, L) ->
+ lists:foldl(fun(K,E) -> lists:keydelete(K,1,E) end,
+ L,
+ Keys).
+
+
chk_tar(Items, Config) ->
chk_tar(Items, Config, []).
chk_tar(Items, Config, Opts) ->
- TarFileName = ?config(tar_filename, Config),
+ TarFileName = proplists:get_value(tar_filename, Config),
chk_tar(Items, TarFileName, Config, Opts).
chk_tar(Items, TarFileName, Config, Opts) when is_list(Opts) ->
tar_size(TarFileName, Config),
- {ChPid,_} = ?config(sftp,Config),
+ {ChPid,_} = proplists:get_value(sftp,Config),
{ok,HandleRead} = ssh_sftp:open_tar(ChPid, TarFileName, [read|Opts]),
{ok,NameValueList} = erl_tar:extract(HandleRead,[memory,verbose]),
ok = erl_tar:close(HandleRead),
@@ -1016,7 +1103,7 @@ analyze_report([], []) ->
"".
tar_size(TarFileName, Config) ->
- {ChPid,_} = ?config(sftp,Config),
+ {ChPid,_} = proplists:get_value(sftp,Config),
{ok,Data} = ssh_sftp:read_file(ChPid, TarFileName),
io:format('Tar file ~p is~n ~p bytes.~n',[TarFileName, size(Data)]).
@@ -1043,7 +1130,7 @@ read_item_contents(ItemName, FileName) ->
end.
fn(Name, Config) ->
- Dir = ?config(datadir_tar, Config),
+ Dir = proplists:get_value(datadir_tar, Config),
filename:join(Dir,Name).
fmt_host({A,B,C,D}) -> lists:concat([A,".",B,".",C,".",D]);
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 9385bd127d..52a26110c4 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -28,6 +28,7 @@
-include_lib("kernel/include/file.hrl").
-include("ssh_xfer.hrl").
-include("ssh.hrl").
+-include("ssh_test_lib.hrl").
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -72,19 +73,22 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
- ssh_test_lib:setup_dsa(DataDir, PrivDir),
- %% to make sure we don't use public-key-auth
- %% this should be tested by other test suites
- UserDir = filename:join(?config(priv_dir, Config), nopubkey),
- file:make_dir(UserDir),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ %% to make sure we don't use public-key-auth
+ %% this should be tested by other test suites
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
+ file:make_dir(UserDir),
+ Config
+ end).
end_per_suite(Config) ->
- SysDir = ?config(priv_dir, Config),
+ SysDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(SysDir),
- UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
file:del_dir(UserDir),
ssh:stop().
@@ -101,9 +105,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
prep(Config),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ClientUserDir = filename:join(PrivDir, nopubkey),
- SystemDir = filename:join(?config(priv_dir, Config), system),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
Options = [{system_dir, SystemDir},
{user_dir, PrivDir},
@@ -154,8 +158,8 @@ init_per_testcase(TestCase, Config) ->
[{sftp, {Cm, Channel}}, {sftpd, Sftpd }| Config].
end_per_testcase(_TestCase, Config) ->
- ssh_sftpd:stop(?config(sftpd, Config)),
- {Cm, Channel} = ?config(sftp, Config),
+ ssh_sftpd:stop(proplists:get_value(sftpd, Config)),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
ssh_connection:close(Cm, Channel),
ssh:close(Cm),
ssh:stop().
@@ -166,9 +170,9 @@ end_per_testcase(_TestCase, Config) ->
open_close_file() ->
[{doc, "Test SSH_FXP_OPEN and SSH_FXP_CLOSE commands"}].
open_close_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
ReqId = 0,
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
@@ -196,9 +200,9 @@ open_close_file(Config) when is_list(Config) ->
ver3_open_flags() ->
[{doc, "Test open flags"}].
ver3_open_flags(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "not_exist.txt"),
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
ReqId = 0,
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
@@ -230,8 +234,8 @@ ver3_open_flags(Config) when is_list(Config) ->
open_close_dir() ->
[{doc,"Test SSH_FXP_OPENDIR and SSH_FXP_CLOSE commands"}].
open_close_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Cm, Channel} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
@@ -257,11 +261,11 @@ open_close_dir(Config) when is_list(Config) ->
read_file() ->
[{doc, "Test SSH_FXP_READ command"}].
read_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
open_file(FileName, Cm, Channel, ReqId,
@@ -280,8 +284,8 @@ read_file(Config) when is_list(Config) ->
read_dir() ->
[{doc,"Test SSH_FXP_READDIR command"}].
read_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Cm, Channel} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
ReqId = 0,
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
open_dir(PrivDir, Cm, Channel, ReqId),
@@ -291,11 +295,11 @@ read_dir(Config) when is_list(Config) ->
write_file() ->
[{doc, "Test SSH_FXP_WRITE command"}].
write_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
open_file(FileName, Cm, Channel, ReqId,
@@ -315,10 +319,10 @@ write_file(Config) when is_list(Config) ->
remove_file() ->
[{doc, "Test SSH_FXP_REMOVE command"}].
remove_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
?UINT32(?SSH_FX_OK), _/binary>>, _} =
@@ -336,11 +340,11 @@ remove_file(Config) when is_list(Config) ->
rename_file() ->
[{doc, "Test SSH_FXP_RENAME command"}].
rename_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
NewFileName = filename:join(PrivDir, "test1.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
?UINT32(?SSH_FX_OK), _/binary>>, _} =
@@ -373,8 +377,8 @@ rename_file(Config) when is_list(Config) ->
mk_rm_dir() ->
[{doc, "Test SSH_FXP_MKDIR and SSH_FXP_RMDIR command"}].
mk_rm_dir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- {Cm, Channel} = ?config(sftp, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
DirName = filename:join(PrivDir, "test"),
ReqId = 0,
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), ?UINT32(?SSH_FX_OK),
@@ -401,8 +405,8 @@ real_path(Config) when is_list(Config) ->
{skip, "Not a relevant test on windows"};
_ ->
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
- PrivDir = ?config(priv_dir, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
TestDir = filename:join(PrivDir, "ssh_test"),
ok = file:make_dir(TestDir),
@@ -427,8 +431,8 @@ links(Config) when is_list(Config) ->
{skip, "Links are not fully supported by windows"};
_ ->
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
- PrivDir = ?config(priv_dir, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
LinkFileName = filename:join(PrivDir, "link_test.txt"),
@@ -451,10 +455,10 @@ links(Config) when is_list(Config) ->
retrieve_attributes() ->
[{"Test SSH_FXP_STAT, SSH_FXP_LSTAT AND SSH_FXP_FSTAT commands"}].
retrieve_attributes(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, FileInfo} = file:read_file_info(FileName),
@@ -520,10 +524,10 @@ set_attributes(Config) when is_list(Config) ->
{win32, _} ->
{skip, "Known error bug in erts file:read_file_info"};
_ ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, FileInfo} = file:read_file_info(FileName),
@@ -574,11 +578,11 @@ set_attributes(Config) when is_list(Config) ->
ver3_rename() ->
[{doc, "Test that ver3 rename message is handled OTP 6352"}].
ver3_rename(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
NewFileName = filename:join(PrivDir, "test1.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
?UINT32(?SSH_FX_OK), _/binary>>, _} =
@@ -589,7 +593,7 @@ relpath() ->
[{doc, "Check that realpath works ok seq10670"}].
relpath(Config) when is_list(Config) ->
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
case os:type() of
{win32, _} ->
@@ -611,11 +615,11 @@ relpath(Config) when is_list(Config) ->
sshd_read_file() ->
[{doc,"Test SSH_FXP_READ command, using sshd-server"}].
sshd_read_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(PrivDir, "test.txt"),
ReqId = 0,
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
{ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
open_file(FileName, Cm, Channel, ReqId,
@@ -633,9 +637,9 @@ sshd_read_file(Config) when is_list(Config) ->
ver6_basic() ->
[{doc, "Test SFTP Version 6"}].
ver6_basic(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%FileName = filename:join(PrivDir, "test.txt"),
- {Cm, Channel} = ?config(sftp, Config),
+ {Cm, Channel} = proplists:get_value(sftp, Config),
ReqId = 0,
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), % Ver 6 we have 5
?UINT32(?SSH_FX_FILE_IS_A_DIRECTORY), _/binary>>, _} =
@@ -646,7 +650,7 @@ ver6_basic(Config) when is_list(Config) ->
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
prep(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
TestFile = filename:join(PrivDir, "test.txt"),
TestFile1 = filename:join(PrivDir, "test1.txt"),
@@ -654,7 +658,7 @@ prep(Config) ->
file:delete(TestFile1),
%% Initial config
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
file:copy(FileName, TestFile),
Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 355ce6a8f5..56a33d6349 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
+-include("ssh_test_lib.hrl").
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -53,22 +54,25 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- catch ssh:stop(),
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
- FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
- c:c(FileAlt),
- FileName = filename:join(DataDir, "test.txt"),
- {ok, FileInfo} = file:read_file_info(FileName),
- ok = file:write_file_info(FileName,
- FileInfo#file_info{mode = 8#400}),
- ssh_test_lib:setup_dsa(DataDir, PrivDir),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ catch ssh:stop(),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
+ c:c(FileAlt),
+ FileName = filename:join(DataDir, "test.txt"),
+ {ok, FileInfo} = file:read_file_info(FileName),
+ ok = file:write_file_info(FileName,
+ FileInfo#file_info{mode = 8#400}),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config
+ end).
end_per_suite(Config) ->
- UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
file:del_dir(UserDir),
- SysDir = ?config(priv_dir, Config),
+ SysDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(SysDir),
ok.
@@ -83,7 +87,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
SystemDir = filename:join(PrivDir, system),
Options =
@@ -96,7 +100,7 @@ init_per_testcase(TestCase, Config) ->
{user_dir, PrivDir},
{subsystems, [Spec]}];
"root_dir" ->
- Privdir = ?config(priv_dir, Config),
+ Privdir = proplists:get_value(priv_dir, Config),
Root = filename:join(Privdir, root),
file:make_dir(Root),
Spec = ssh_sftpd:subsystem_spec([{root,Root}]),
@@ -132,8 +136,8 @@ init_per_testcase(TestCase, Config) ->
[{port, Port}, {sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
end_per_testcase(_TestCase, Config) ->
- catch ssh_sftpd:stop(?config(sftpd, Config)),
- {Sftp, Connection} = ?config(sftp, Config),
+ catch ssh_sftpd:stop(proplists:get_value(sftpd, Config)),
+ {Sftp, Connection} = proplists:get_value(sftp, Config),
catch ssh_sftp:stop_channel(Sftp),
catch ssh:close(Connection),
ssh:stop().
@@ -146,10 +150,10 @@ close_file() ->
"transfer OTP-6350"}].
close_file(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
NumOfPorts = length(erlang:ports()),
@@ -167,12 +171,12 @@ quit() ->
"client hanging. OTP-6349"}].
quit(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
- UserDir = ?config(priv_dir, Config),
- Port = ?config(port, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+ Port = proplists:get_value(port, Config),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName),
@@ -198,13 +202,13 @@ file_cb() ->
" the sftpds filehandling. OTP-6356"}].
file_cb(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
register(sftpd_file_alt_tester, self()),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Bin} = ssh_sftp:read_file(Sftp, FileName),
alt_file_handler_check(alt_open),
@@ -242,7 +246,7 @@ file_cb(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
root_dir(Config) when is_list(Config) ->
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
FileName = "test.txt",
Bin = <<"Test file for root dir option">>,
ok = ssh_sftp:write_file(Sftp, FileName, Bin),
@@ -253,7 +257,7 @@ root_dir(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
list_dir_limited(Config) when is_list(Config) ->
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
{ok, Listing} =
ssh_sftp:list_dir(Sftp, "."),
ct:log("Listing: ~p~n", [Listing]).
@@ -262,9 +266,9 @@ list_dir_limited(Config) when is_list(Config) ->
ver6_basic() ->
[{doc, "Test some version 6 features"}].
ver6_basic(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
NewDir = filename:join(PrivDir, "testdir2"),
- {Sftp, _} = ?config(sftp, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
ok = ssh_sftp:make_dir(Sftp, NewDir),
%%Test file_is_a_directory
{error, file_is_a_directory} = ssh_sftp:delete(Sftp, NewDir).
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index f8929b30ff..ff53e1c4c6 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -53,18 +53,21 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_suite(Config) ->
- Port = ssh_test_lib:inet_port(node()),
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- [{userdir, UserDir},{port, Port}, {host, "localhost"}, {host_ip, any} | Config].
+ ?CHECK_CRYPTO(
+ begin
+ Port = ssh_test_lib:inet_port(node()),
+ 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),
+ [{userdir, UserDir},{port, Port}, {host, "localhost"}, {host_ip, any} | Config]
+ end).
end_per_suite(_) ->
ok.
init_per_testcase(sshc_subtree, Config) ->
ssh:start(),
- SystemDir = ?config(data_dir, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2},
{user_passwords,
@@ -75,7 +78,7 @@ init_per_testcase(Case, Config) ->
ssh:start(),
Config.
end_per_testcase(sshc_subtree, Config) ->
- {Pid,_,_} = ?config(server, Config),
+ {Pid,_,_} = proplists:get_value(server, Config),
ssh:stop_daemon(Pid),
ssh:stop();
end_per_testcase(_, _Config) ->
@@ -100,8 +103,8 @@ default_tree(Config) when is_list(Config) ->
sshc_subtree() ->
[{doc, "Make sure the sshc subtree is correct"}].
sshc_subtree(Config) when is_list(Config) ->
- {_Pid, Host, Port} = ?config(server, Config),
- UserDir = ?config(userdir, Config),
+ {_Pid, Host, Port} = proplists:get_value(server, Config),
+ UserDir = proplists:get_value(userdir, Config),
?wait_match([], supervisor:which_children(sshc_sup)),
@@ -128,9 +131,9 @@ sshc_subtree(Config) when is_list(Config) ->
sshd_subtree() ->
[{doc, "Make sure the sshd subtree is correct"}].
sshd_subtree(Config) when is_list(Config) ->
- HostIP = ?config(host_ip, Config),
- Port = ?config(port, Config),
- SystemDir = ?config(data_dir, 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,
@@ -149,10 +152,10 @@ sshd_subtree(Config) when is_list(Config) ->
sshd_subtree_profile() ->
[{doc, "Make sure the sshd subtree using profile option is correct"}].
sshd_subtree_profile(Config) when is_list(Config) ->
- HostIP = ?config(host_ip, Config),
- Port = ?config(port, Config),
- Profile = ?config(profile, Config),
- SystemDir = ?config(data_dir, Config),
+ HostIP = proplists:get_value(host_ip, Config),
+ Port = proplists:get_value(port, 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},
@@ -171,9 +174,9 @@ sshd_subtree_profile(Config) when is_list(Config) ->
check_sshd_system_tree(Daemon, Config) ->
- Host = ?config(host, Config),
- Port = ?config(port, Config),
- UserDir = ?config(userdir, 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}]),
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index c6541461a1..6233680dce 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -71,7 +71,7 @@ daemon_port(Port, _) -> Port.
std_daemon(Config, ExtraOpts) ->
- PrivDir = ?config(priv_dir, 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),
std_daemon1(Config,
@@ -80,13 +80,13 @@ std_daemon(Config, ExtraOpts) ->
{user_passwords, [{"usr1","pwd1"}]}]).
std_daemon1(Config, ExtraOpts) ->
- SystemDir = ?config(data_dir, Config),
+ SystemDir = proplists:get_value(data_dir, Config),
{_Server, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}
| ExtraOpts]).
std_connect(Config, Host, Port, ExtraOpts) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
_ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user_dir, UserDir},
@@ -99,7 +99,7 @@ std_simple_sftp(Host, Port, Config) ->
std_simple_sftp(Host, Port, Config, []).
std_simple_sftp(Host, Port, Config, Opts) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
DataFile = filename:join(UserDir, "test.data"),
ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, Opts),
{ok, ChannelRef} = ssh_sftp:start_channel(ConnectionRef),
@@ -655,17 +655,48 @@ sshc(Tag) ->
).
ssh_type() ->
- case os:find_executable("ssh") of
- false -> not_found;
- _ ->
- case os:cmd("ssh -V") of
- "OpenSSH" ++ _ ->
- openSSH;
- Str ->
- ct:log("ssh client ~p is unknown",[Str]),
- unknown
- end
- end.
+ Parent = self(),
+ Pid = spawn(fun() ->
+ Parent ! {ssh_type,self(),ssh_type1()}
+ end),
+ MonitorRef = monitor(process, Pid),
+ receive
+ {ssh_type, Pid, Result} ->
+ demonitor(MonitorRef),
+ Result;
+ {'DOWN', MonitorRef, process, Pid, _Info} ->
+ ct:log("~p:~p Process DOWN",[?MODULE,?LINE]),
+ not_found
+ after
+ 10000 ->
+ ct:log("~p:~p Timeout",[?MODULE,?LINE]),
+ demonitor(MonitorRef),
+ not_found
+ end.
+
+
+ssh_type1() ->
+ try
+ case os:find_executable("ssh") of
+ false ->
+ ct:log("~p:~p Executable \"ssh\" not found",[?MODULE,?LINE]),
+ not_found;
+ _ ->
+ case os:cmd("ssh -V") of
+ "OpenSSH" ++ _ ->
+ openSSH;
+ Str ->
+ ct:log("ssh client ~p is unknown",[Str]),
+ unknown
+ end
+ end
+ catch
+ Class:Exception ->
+ ct:log("~p:~p Exception ~p:~p",[?MODULE,?LINE,Class,Exception]),
+ not_found
+ end.
+
+
algo_intersection([], _) -> [];
algo_intersection(_, []) -> [];
diff --git a/lib/ssh/test/ssh_test_lib.hrl b/lib/ssh/test/ssh_test_lib.hrl
index 7cb7edeaa8..54c93b7e87 100644
--- a/lib/ssh/test/ssh_test_lib.hrl
+++ b/lib/ssh/test/ssh_test_lib.hrl
@@ -1,4 +1,14 @@
%%-------------------------------------------------------------------------
+%% Check for usable crypt
+%%-------------------------------------------------------------------------
+-define(CHECK_CRYPTO(Available),
+ try crypto:start()
+ of _ -> Available
+ catch _:_ -> {skip, "Can't start crypto"}
+ end
+ ).
+
+%%-------------------------------------------------------------------------
%% Help macro
%%-------------------------------------------------------------------------
-define(wait_match(Pattern, FunctionCall, Bind, Timeout, Ntries),
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index 2be75fd7f3..a914938c41 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -22,6 +22,7 @@
-module(ssh_to_openssh_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -62,19 +63,21 @@ groups() ->
].
init_per_suite(Config) ->
- case gen_tcp:connect("localhost", 22, []) of
- {error,econnrefused} ->
- {skip,"No openssh deamon"};
- _ ->
- ssh_test_lib:openssh_sanity_check(Config)
- end.
+ ?CHECK_CRYPTO(
+ case gen_tcp:connect("localhost", 22, []) of
+ {error,econnrefused} ->
+ {skip,"No openssh deamon"};
+ _ ->
+ ssh_test_lib:openssh_sanity_check(Config)
+ end
+ ).
end_per_suite(_Config) ->
ok.
init_per_group(erlang_server, Config) ->
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa_known_host(DataDir, UserDir),
ssh_test_lib:setup_rsa_known_host(DataDir, UserDir),
Config;
@@ -87,7 +90,7 @@ init_per_group(_, Config) ->
Config.
end_per_group(erlang_server, Config) ->
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(UserDir),
ssh_test_lib:clean_rsa(UserDir),
Config;
@@ -222,7 +225,7 @@ erlang_client_openssh_server_kexs() ->
[{doc, "Test that we can connect with different KEXs."}].
erlang_client_openssh_server_kexs(Config) when is_list(Config) ->
- KexAlgos = try proplists:get_value(kex, ?config(common_algs,Config))
+ KexAlgos = try proplists:get_value(kex, proplists:get_value(common_algs,Config))
catch _:_ -> []
end,
comment(KexAlgos),
@@ -366,8 +369,8 @@ erlang_server_openssh_client_public_key_rsa(Config) when is_list(Config) ->
erlang_server_openssh_client_public_key_X(Config, PubKeyAlg) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ 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},
@@ -387,7 +390,7 @@ erlang_client_openssh_server_password() ->
[{doc, "Test client password option"}].
erlang_client_openssh_server_password(Config) when is_list(Config) ->
%% to make sure we don't public-key-auth
- UserDir = ?config(data_dir, Config),
+ UserDir = proplists:get_value(data_dir, Config),
{error, Reason0} =
ssh:connect(any, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
{user, "foo"},
diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl
index 06bef2455e..b5b27c369a 100644
--- a/lib/ssh/test/ssh_upgrade_SUITE.erl
+++ b/lib/ssh/test/ssh_upgrade_SUITE.erl
@@ -23,6 +23,7 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
-record(state, {
config,
@@ -48,18 +49,20 @@ all() ->
].
init_per_suite(Config0) ->
- case ct_release_test:init(Config0) of
- {skip, Reason} ->
- {skip, Reason};
- Config ->
- ssh:start(),
- Config
- end.
+ ?CHECK_CRYPTO(
+ case ct_release_test:init(Config0) of
+ {skip, Reason} ->
+ {skip, Reason};
+ Config ->
+ ssh:start(),
+ Config
+ end
+ ).
end_per_suite(Config) ->
ct_release_test:cleanup(Config),
ssh:stop(),
- UserDir = ?config(priv_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_rsa(UserDir).
init_per_testcase(_TestCase, Config) ->
@@ -138,8 +141,8 @@ test_soft(State0, FileName) ->
setup_server_client(#state{config=Config} = State) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FtpRootDir = filename:join(PrivDir, "ftp_root"),
catch file:make_dir(FtpRootDir),