diff options
Diffstat (limited to 'lib/ssh')
-rw-r--r-- | lib/ssh/src/ssh_connection_handler.erl | 50 | ||||
-rw-r--r-- | lib/ssh/src/ssh_message.erl | 10 | ||||
-rw-r--r-- | lib/ssh/test/ssh_algorithms_SUITE.erl | 57 | ||||
-rw-r--r-- | lib/ssh/test/ssh_benchmark_SUITE.erl | 31 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sftp_SUITE.erl | 86 | ||||
-rw-r--r-- | lib/ssh/test/ssh_sup_SUITE.erl | 9 | ||||
-rw-r--r-- | lib/ssh/test/ssh_test_lib.erl | 53 | ||||
-rw-r--r-- | lib/ssh/test/ssh_upgrade_SUITE.erl | 3 |
8 files changed, 197 insertions, 102 deletions
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 0327a72c12..e952a333ff 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1514,39 +1514,35 @@ call(FsmPid, Event, Timeout) -> end. -handle_connection_msg(Msg, StateName, State0 = - #data{starter = User, - connection_state = Connection0, - event_queue = Qev0}) -> +handle_connection_msg(Msg, StateName, D0 = #data{starter = User, + connection_state = Connection0, + event_queue = Qev0}) -> Renegotiation = renegotiation(StateName), Role = role(StateName), try ssh_connection:handle_msg(Msg, Connection0, Role) of {{replies, Replies}, Connection} -> - case StateName of - {connected,_} -> - {Repls, State} = send_replies(Replies, - State0#data{connection_state=Connection}), - {keep_state, State, Repls}; - _ -> - {ConnReplies, Replies} = - lists:splitwith(fun not_connected_filter/1, Replies), - {Repls, State} = send_replies(Replies, - State0#data{event_queue = Qev0 ++ ConnReplies}), - {keep_state, State, Repls} - end; + {Repls, D} = + case StateName of + {connected,_} -> + send_replies(Replies, D0#data{connection_state=Connection}); + _ -> + {ConnReplies, NonConnReplies} = lists:splitwith(fun not_connected_filter/1, Replies), + send_replies(NonConnReplies, D0#data{event_queue = Qev0 ++ ConnReplies}) + end, + {keep_state, D, Repls}; {noreply, Connection} -> - {keep_state, State0#data{connection_state = Connection}}; + {keep_state, D0#data{connection_state = Connection}}; {disconnect, Reason0, {{replies, Replies}, Connection}} -> - {Repls,State} = send_replies(Replies, State0#data{connection_state = Connection}), - case {Reason0,Role} of - {{_, Reason}, client} when ((StateName =/= {connected,client}) and (not Renegotiation)) -> - User ! {self(), not_connected, Reason}; - _ -> - ok - end, - {stop, {shutdown,normal}, Repls, State#data{connection_state = Connection}} + {Repls, D} = send_replies(Replies, D0#data{connection_state = Connection}), + case {Reason0,Role} of + {{_, Reason}, client} when ((StateName =/= {connected,client}) and (not Renegotiation)) -> + User ! {self(), not_connected, Reason}; + _ -> + ok + end, + {stop_and_reply, {shutdown,normal}, Repls, D#data{connection_state = Connection}} catch _:Error -> @@ -1555,8 +1551,8 @@ handle_connection_msg(Msg, StateName, State0 = #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, description = "Internal error"}, Connection0, Role), - {Repls,State} = send_replies(Replies, State0#data{connection_state = Connection}), - {stop, {shutdown,Error}, Repls, State#data{connection_state = Connection}} + {Repls, D} = send_replies(Replies, D0#data{connection_state = Connection}), + {stop_and_reply, {shutdown,Error}, Repls, D#data{connection_state = Connection}} end. 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/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 9910b8f1d7..6894f83547 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -28,7 +28,7 @@ %% Note: This directive should only be used in test suites. -compile(export_all). --define(TIMEOUT, 10000). +-define(TIMEOUT, 35000). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- @@ -70,10 +70,10 @@ 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" + 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" "Installed ssh client:~n=====================~n~p~n~n~n" @@ -82,7 +82,9 @@ init_per_suite(Config) -> " -- Default dh group exchange parameters ({min,def,max}): ~p~n" " -- dh_default_groups: ~p~n" " -- Max num algorithms: ~p~n" - ,[os:cmd("ssh -V"), + ,[os:getenv("HOME"), + init:get_argument(home), + os:cmd("ssh -V"), ssh:default_algorithms(), ssh_test_lib:default_algorithms(sshc), ssh_test_lib:default_algorithms(sshd), @@ -136,14 +138,14 @@ end_per_group(_Alg, Config) -> -init_per_testcase(sshc_simple_exec, Config) -> +init_per_testcase(sshc_simple_exec_os_cmd, Config) -> start_pubkey_daemon([?config(pref_algs,Config)], Config); init_per_testcase(_TC, Config) -> Config. -end_per_testcase(sshc_simple_exec, Config) -> +end_per_testcase(sshc_simple_exec_os_cmd, Config) -> case ?config(srvr_pid,Config) of Pid when is_pid(Pid) -> ssh:stop_daemon(Pid), @@ -154,7 +156,6 @@ end_per_testcase(sshc_simple_exec, Config) -> end_per_testcase(_TC, Config) -> Config. - %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- @@ -221,18 +222,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 +318,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; diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 1f11fee350..5d8c94be73 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -184,7 +184,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} @@ -215,6 +215,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 +232,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 +261,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} @@ -334,16 +335,16 @@ find_time(accept_to_hello, L) -> C#call.t_call end, ?LINE, - fun(C=#call{mfa = {ssh_connection_handler,handle_event,5}, - args = [_, {version_exchange,_}, _, {hello,_}, _]}) -> + fun(C=#call{mfa = {ssh_connection_handler,handle_event,4}, + args = [_, {version_exchange,_}, {hello,_}, _]}) -> C#call.t_call end, ?LINE ], L, []), {accept_to_hello, now2micro_sec(now_diff(T1,T0)), microsec}; find_time(kex, L) -> - [T0,T1] = find([fun(C=#call{mfa = {ssh_connection_handler,handle_event,5}, - args = [_, {version_exchange,_}, _, {hello,_}, _]}) -> + [T0,T1] = find([fun(C=#call{mfa = {ssh_connection_handler,handle_event,4}, + args = [_, {version_exchange,_}, {hello,_}, _]}) -> C#call.t_call end, ?LINE, @@ -445,10 +446,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() -> @@ -466,8 +475,8 @@ erlang_trace() -> {ssh_message,decode,1}, {public_key,dh_gex_group,4} % To find dh_gex group size ]], - init_trace({ssh_connection_handler,handle_event,5}, - [{['_', {version_exchange,'_'}, '_', {hello,'_'}, '_'], + init_trace({ssh_connection_handler,handle_event,4}, + [{['_', {version_exchange,'_'}, {hello,'_'}, '_'], [], [return_trace]}]), {ok, TracerPid}. diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index f6d7be41d6..26fe0935e1 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. @@ -93,35 +93,35 @@ groups() -> init_per_group(not_unicode, Config) -> ct:comment("Begin ~p",[grps(Config)]), DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_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), 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, @@ -228,8 +228,8 @@ 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), @@ -246,8 +246,8 @@ 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), @@ -279,7 +279,7 @@ 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. @@ -329,7 +329,7 @@ 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), + PrivDir = ?config(sftp_priv_dir, Config), {Sftp, _} = ?config(sftp, Config), FileName = ?config(filename, Config), @@ -351,7 +351,7 @@ 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), + PrivDir = ?config(sftp_priv_dir, Config), {Sftp, _} = ?config(sftp, Config), {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), ct:log("sftp list dir: ~p~n", [Files]). @@ -415,7 +415,7 @@ 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), + PrivDir = ?config(sftp_priv_dir, Config), FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), @@ -429,7 +429,7 @@ 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), + PrivDir = ?config(sftp_priv_dir, Config), FileName = ?config(filename, Config), NewFileName = ?config(testfile, Config), @@ -449,7 +449,7 @@ 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), + PrivDir = ?config(sftp_priv_dir, Config), {Sftp, _} = ?config(sftp, Config), DirName = filename:join(PrivDir, "test"), @@ -945,7 +945,7 @@ aes_ctr_stream_crypto_tar(Config) -> %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- -prep(Config) -> +oldprep(Config) -> DataDir = ?config(data_dir, Config), TestFile = ?config(filename, Config), TestFile1 = ?config(testfile, Config), @@ -965,6 +965,36 @@ 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, []). diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index 2dc4263603..f8929b30ff 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -108,18 +108,19 @@ sshc_subtree(Config) when is_list(Config) -> {ok, Pid1} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, {user_interaction, false}, {user, ?USER}, {password, ?PASSWD},{user_dir, UserDir}]), - ?wait_match([{_, _,supervisor,[ssh_connection_handler]}], + + ?wait_match([{_, _,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), {ok, Pid2} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, {user_interaction, false}, {user, ?USER}, {password, ?PASSWD}, {user_dir, UserDir}]), - ?wait_match([{_,_,supervisor,[ssh_connection_handler]}, - {_,_,supervisor,[ssh_connection_handler]}], + ?wait_match([{_,_,worker,[ssh_connection_handler]}, + {_,_,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), ssh:close(Pid1), - ?wait_match([{_,_,supervisor,[ssh_connection_handler]}], + ?wait_match([{_,_,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), ssh:close(Pid2), ?wait_match([], supervisor:which_children(sshc_sup)). diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index c6541461a1..a1291146e4 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -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_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl index 5c7ec17dac..06bef2455e 100644 --- a/lib/ssh/test/ssh_upgrade_SUITE.erl +++ b/lib/ssh/test/ssh_upgrade_SUITE.erl @@ -146,7 +146,8 @@ setup_server_client(#state{config=Config} = State) -> SFTP = ssh_sftpd:subsystem_spec([{root,FtpRootDir},{cwd,FtpRootDir}]), - {Server,Host,Port} = ssh_test_lib:daemon([{system_dir,DataDir}, + {Server,Host,Port} = ssh_test_lib:daemon(ssh_test_lib:inet_port(), % when lower rel is 18.x + [{system_dir,DataDir}, {user_passwords,[{"hej","hopp"}]}, {subsystems,[SFTP]}]), |