summaryrefslogtreecommitdiff
path: root/lib/ssh/test/ssh_test_lib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/test/ssh_test_lib.erl')
-rw-r--r--lib/ssh/test/ssh_test_lib.erl653
1 files changed, 352 insertions, 301 deletions
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index bf533fc553..ae8f7abb70 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -22,12 +22,109 @@
%%----------------------------------------------------------------------
-module(ssh_test_lib).
-%% Note: This directive should only be used in test suites.
--compile(export_all).
+-export([
+connect/2,
+connect/3,
+daemon/1,
+daemon/2,
+daemon/3,
+daemon_port/1,
+daemon_port/2,
+gen_tcp_connect/3,
+open_sshc/3,
+open_sshc/4,
+open_sshc_cmd/3,
+open_sshc_cmd/4,
+std_daemon/2,
+std_daemon1/2,
+std_connect/4,
+std_simple_sftp/3,
+std_simple_sftp/4,
+std_simple_exec/3,
+std_simple_exec/4,
+start_shell/2,
+start_shell/3,
+start_io_server/0,
+init_io_server/1,
+loop_io_server/2,
+io_request/5,
+io_reply/3,
+reply/2,
+rcv_expected/3,
+rcv_lingering/1,
+receive_exec_result/1,
+receive_exec_result_or_fail/1,
+receive_exec_end/2,
+receive_exec_end/3,
+receive_exec_result/3,
+failfun/2,
+hostname/0,
+del_dirs/1,
+del_dir_contents/1,
+do_del_files/2,
+openssh_sanity_check/1,
+default_algorithms/1,
+default_algorithms/3,
+default_algorithms/2,
+run_fake_ssh/1,
+extract_algos/1,
+get_atoms/1,
+intersection/2,
+intersect/2,
+intersect_bi_dir/1,
+some_empty/1,
+sort_spec/1,
+sshc/1,
+ssh_type/0,
+ssh_type1/0,
+installed_ssh_version/1,
+algo_intersection/2,
+to_atoms/1,
+ssh_supports/2,
+has_inet6_address/0,
+open_port/1,
+open_port/2,
+sleep_millisec/1,
+sleep_microsec/1,
+busy_wait/2,
+get_kex_init/1,
+get_kex_init/3,
+expected_state/1,
+random_chars/1,
+create_random_dir/1,
+match_ip/2,
+match_ip0/2,
+match_ip1/2,
+mangle_connect_address/1,
+mangle_connect_address/2,
+loopback/1,
+mangle_connect_address1/2,
+ntoa/1,
+try_enable_fips_mode/0,
+is_cryptolib_fips_capable/0,
+report/2,
+lc_name_in/1,
+ptty_supported/0,
+has_WSL/0,
+winpath_to_linuxpath/1,
+copy_recursive/2,
+mk_dir_path/1,
+setup_all_user_host_keys/1,
+setup_all_user_host_keys/2,
+setup_all_user_host_keys/3,
+setup_all_host_keys/1,
+setup_all_host_keys/2,
+setup_all_user_keys/2,
+setup_user_key/3,
+setup_host_key_create_dir/3,
+setup_host_key/3,
+setup_known_host/3,
+get_addr_str/0,
+file_base_name/2
+ ]).
--include_lib("public_key/include/public_key.hrl").
-include_lib("common_test/include/ct.hrl").
--include_lib("ssh/src/ssh_transport.hrl").
+-include("ssh_transport.hrl").
-include_lib("kernel/include/file.hrl").
-include("ssh_test_lib.hrl").
@@ -184,11 +281,44 @@ start_shell(Port, IOServer) ->
start_shell(Port, IOServer, ExtraOptions) ->
spawn_link(
fun() ->
- Host = hostname(),
+ ct:log("~p:~p:~p ssh_test_lib:start_shell(~p, ~p, ~p)",
+ [?MODULE,?LINE,self(), Port, IOServer, ExtraOptions]),
Options = [{user_interaction, false},
{silently_accept_hosts,true} | ExtraOptions],
- group_leader(IOServer, self()),
- ssh:shell(Host, Port, Options)
+ try
+ group_leader(IOServer, self()),
+ case Port of
+ 22 ->
+ Host = hostname(),
+ ct:log("Port==22 Call ssh:shell(~p, ~p)",
+ [Host, Options]),
+ ssh:shell(Host, Options);
+ _ when is_integer(Port) ->
+ Host = hostname(),
+ ct:log("is_integer(Port) Call ssh:shell(~p, ~p, ~p)",
+ [Host, Port, Options]),
+ ssh:shell(Host, Port, Options);
+ Socket when is_port(Socket) ->
+ receive
+ start -> ok
+ end,
+ ct:log("is_port(Socket) Call ssh:shell(~p, ~p)",
+ [Socket, Options]),
+ ssh:shell(Socket, Options);
+ ConnRef when is_pid(ConnRef) ->
+ ct:log("is_pid(ConnRef) Call ssh:shell(~p)",
+ [ConnRef]),
+ ssh:shell(ConnRef) % Options were given in ssh:connect
+ end
+ of
+ R ->
+ ct:log("~p:~p ssh_test_lib:start_shell(~p, ~p, ~p) -> ~p",
+ [?MODULE,?LINE,Port, IOServer, ExtraOptions, R])
+ catch
+ C:E:S ->
+ ct:log("Exception ~p:~p~n~p", [C,E,S]),
+ ct:fail("Exception",[])
+ end
end).
@@ -209,6 +339,7 @@ loop_io_server(TestCase, Buff0) ->
%%ct:log("io_server ~p:~p ~p got ~p",[?MODULE,?LINE,self(),_REQ]),
{ok, Reply, Buff} = io_request(Request, TestCase, From,
ReplyAs, Buff0),
+ %%ct:log("io_server ~p:~p ~p going to reply ~p",[?MODULE,?LINE,self(),Reply]),
io_reply(From, ReplyAs, Reply),
loop_io_server(TestCase, Buff);
{'EXIT',_, _} = _Exit ->
@@ -218,6 +349,12 @@ loop_io_server(TestCase, Buff0) ->
30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
end.
+io_request(getopts,_TestCase, _, _, Buff) ->
+ {ok, [], Buff};
+io_request({get_geometry,columns},_TestCase, _, _, Buff) ->
+ {ok, 80, Buff};
+io_request({get_geometry,rows},_TestCase, _, _, Buff) ->
+ {ok, 24, Buff};
io_request({put_chars, Chars}, TestCase, _, _, Buff) ->
reply(TestCase, Chars),
{ok, ok, Buff};
@@ -225,7 +362,7 @@ io_request({put_chars, unicode, Chars}, TestCase, _, _, Buff) when is_binary(Cha
reply(TestCase, Chars),
{ok, ok, Buff};
io_request({put_chars, unicode, io_lib, format, [Fmt,Args]}, TestCase, _, _, Buff) ->
- reply(TestCase, io_lib:format(Fmt,Args)),
+ reply(TestCase, unicode:characters_to_binary(io_lib:format(Fmt,Args))),
{ok, ok, Buff};
io_request({put_chars, Enc, Chars}, TestCase, _, _, Buff) ->
reply(TestCase, unicode:characters_to_binary(Chars,Enc,latin1)),
@@ -241,6 +378,7 @@ io_request({get_line, _Enc, _Prompt} = Request, _, From, ReplyAs, [] = Buff) ->
io_request({get_line, _Enc,_}, _, _, _, [Line | Buff]) ->
{ok, Line, Buff}.
+
io_reply(_, _, []) ->
ok;
io_reply(From, ReplyAs, Reply) ->
@@ -294,25 +432,37 @@ rcv_lingering(Timeout) ->
receive_exec_result([]) ->
expected;
receive_exec_result(Msgs) when is_list(Msgs) ->
- ct:log("Expect data! ~p", [Msgs]),
+ ct:log("~p:~p Expect data! ~p", [?MODULE,?FUNCTION_NAME,Msgs]),
receive
Msg ->
- case lists:member(Msg, Msgs) of
+ case lists:member(Msg, Msgs)
+ orelse lists:member({optional,Msg}, Msgs)
+ of
true ->
- ct:log("Collected data ~p", [Msg]),
- receive_exec_result(Msgs--[Msg]);
+ ct:log("~p:~p Collected data ~p", [?MODULE,?FUNCTION_NAME,Msg]),
+ receive_exec_result(Msgs--[Msg,{optional,Msg}]);
false ->
case Msg of
{ssh_cm,_,{data,_,1, Data}} ->
- ct:log("StdErr: ~p~n", [Data]),
+ ct:log("~p:~p unexpected StdErr: ~p~n~p~n", [?MODULE,?FUNCTION_NAME,Data,Msg]),
receive_exec_result(Msgs);
Other ->
- ct:log("Other ~p", [Other]),
+ ct:log("~p:~p unexpected Other ~p", [?MODULE,?FUNCTION_NAME,Other]),
{unexpected_msg, Other}
end
end
after
- 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
+ 30000 ->
+ case lists:all(fun(M) ->
+ is_tuple(M) andalso (element(1,M) == optional)
+ end, Msgs)
+ of
+ false ->
+ ct:fail("timeout ~p:~p",[?MODULE,?FUNCTION_NAME]);
+ true ->
+ ct:log("~p:~p Only optional messages expected!~n ~p", [?MODULE,?FUNCTION_NAME,Msgs]),
+ expected
+ end
end;
receive_exec_result(Msg) ->
receive_exec_result([Msg]).
@@ -325,26 +475,14 @@ receive_exec_result_or_fail(Msg) ->
end.
receive_exec_end(ConnectionRef, ChannelId) ->
- Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
- ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}},
- Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}},
- case receive_exec_result(ExitStatus) of
- {unexpected_msg, Eof} -> %% Open ssh seems to not allways send these messages
- %% in the same order!
- ct:log("2: Collected data ~p", [Eof]),
- case receive_exec_result(ExitStatus) of
- expected ->
- expected = receive_exec_result(Closed);
- {unexpected_msg, Closed} ->
- ct:log("3: Collected data ~p", [Closed])
- end;
- expected ->
- ct:log("4: Collected data ~p", [ExitStatus]),
- expected = receive_exec_result(Eof),
- expected = receive_exec_result(Closed);
- Other ->
- ct:fail({unexpected_msg, Other})
- end.
+ receive_exec_end(ConnectionRef, ChannelId, 0).
+
+receive_exec_end(ConnectionRef, ChannelId, ExitStatus) ->
+ receive_exec_result(
+ [{ssh_cm, ConnectionRef, {eof, ChannelId}},
+ {optional, {ssh_cm, ConnectionRef, {exit_status, ChannelId, ExitStatus}}},
+ {ssh_cm, ConnectionRef, {closed, ChannelId}}
+ ]).
receive_exec_result(Data, ConnectionRef, ChannelId) ->
Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
@@ -354,21 +492,6 @@ receive_exec_result(Data, ConnectionRef, ChannelId) ->
expected = receive_exec_result(Closed).
-setup_ssh_auth_keys(RSAFile, DSAFile, Dir) ->
- Entries = ssh_file_entry(RSAFile) ++ ssh_file_entry(DSAFile),
- AuthKeys = public_key:ssh_encode(Entries , auth_keys),
- AuthKeysFile = filename:join(Dir, "authorized_keys"),
- file:write_file(AuthKeysFile, AuthKeys).
-
-ssh_file_entry(PubFile) ->
- case file:read_file(PubFile) of
- {ok, Ssh} ->
- [{Key, _}] = public_key:ssh_decode(Ssh, public_key),
- [{Key, [{comment, "Test"}]}];
- _ ->
- []
- end.
-
failfun(_User, {authmethod,none}) ->
ok;
failfun(User, Reason) ->
@@ -378,233 +501,31 @@ hostname() ->
{ok,Host} = inet:gethostname(),
Host.
-known_hosts(BR) ->
- KnownHosts = ssh_file:file_name(user, "known_hosts", []),
- B = KnownHosts ++ "xxx",
- case BR of
- backup ->
- file:rename(KnownHosts, B);
- restore ->
- file:delete(KnownHosts),
- file:rename(B, KnownHosts)
- end.
+del_dirs(Dir) ->
+ del_dir_contents(Dir),
+ file:del_dir(Dir),
+ ok.
-setup_dsa(DataDir, UserDir) ->
- file:copy(filename:join(DataDir, "id_dsa"), filename:join(UserDir, "id_dsa")),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
-ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
- setup_dsa_known_host(DataDir, UserDir),
- setup_dsa_auth_keys(DataDir, UserDir).
-
-setup_rsa(DataDir, UserDir) ->
- file:copy(filename:join(DataDir, "id_rsa"), filename:join(UserDir, "id_rsa")),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
-ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
- setup_rsa_known_host(DataDir, UserDir),
- setup_rsa_auth_keys(DataDir, UserDir).
-
-setup_ecdsa(Size, DataDir, UserDir) ->
- file:copy(filename:join(DataDir, "id_ecdsa"++Size), filename:join(UserDir, "id_ecdsa")),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")),
-ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
- setup_ecdsa_known_host(Size, System, UserDir),
- setup_ecdsa_auth_keys(Size, DataDir, UserDir).
-
-setup_eddsa(Alg, DataDir, UserDir) ->
- {IdPriv, _IdPub, HostPriv, HostPub} =
- case Alg of
- ed25519 -> {"id_ed25519", "id_ed25519.pub", "ssh_host_ed25519_key", "ssh_host_ed25519_key.pub"};
- ed448 -> {"id_ed448", "id_ed448.pub", "ssh_host_ed448_key", "ssh_host_ed448_key.pub"}
- end,
- file:copy(filename:join(DataDir, IdPriv), filename:join(UserDir, IdPriv)),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, HostPriv), filename:join(System, HostPriv)),
- file:copy(filename:join(DataDir, HostPub), filename:join(System, HostPub)),
-ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
- setup_eddsa_known_host(HostPub, DataDir, UserDir),
- setup_eddsa_auth_keys(IdPriv, DataDir, UserDir).
-
-clean_dsa(UserDir) ->
- del_dirs(filename:join(UserDir, "system")),
- file:delete(filename:join(UserDir,"id_dsa")),
- file:delete(filename:join(UserDir,"known_hosts")),
- file:delete(filename:join(UserDir,"authorized_keys")).
-
-clean_rsa(UserDir) ->
- del_dirs(filename:join(UserDir, "system")),
- file:delete(filename:join(UserDir,"id_rsa")),
- file:delete(filename:join(UserDir,"known_hosts")),
- file:delete(filename:join(UserDir,"authorized_keys")).
-
-setup_dsa_pass_phrase(DataDir, UserDir, Phrase) ->
- try
- {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_dsa")),
- setup_pass_phrase(KeyBin, filename:join(UserDir, "id_dsa"), Phrase),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
- setup_dsa_known_host(DataDir, UserDir),
- setup_dsa_auth_keys(DataDir, UserDir)
- of
- _ -> true
- catch
- _:_ -> false
- end.
-setup_rsa_pass_phrase(DataDir, UserDir, Phrase) ->
- try
- {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_rsa")),
- setup_pass_phrase(KeyBin, filename:join(UserDir, "id_rsa"), Phrase),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
- setup_rsa_known_host(DataDir, UserDir),
- setup_rsa_auth_keys(DataDir, UserDir)
- of
- _ -> true
- catch
- _:_ -> false
+del_dir_contents(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, Files} ->
+ do_del_files(Dir, Files);
+ _ ->
+ ok
end.
-setup_ecdsa_pass_phrase(Size, DataDir, UserDir, Phrase) ->
- try
- {ok, KeyBin} =
- case file:read_file(F=filename:join(DataDir, "id_ecdsa"++Size)) of
- {error,E} ->
- ct:log("Failed (~p) to read ~p~nFiles: ~p", [E,F,file:list_dir(DataDir)]),
- file:read_file(filename:join(DataDir, "id_ecdsa"));
- Other ->
- Other
- end,
- setup_pass_phrase(KeyBin, filename:join(UserDir, "id_ecdsa"), Phrase),
- System = filename:join(UserDir, "system"),
- file:make_dir(System),
- file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")),
- file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")),
- setup_ecdsa_known_host(Size, System, UserDir),
- setup_ecdsa_auth_keys(Size, DataDir, UserDir)
- of
- _ -> true
- catch
- _:_ -> false
- end.
+do_del_files(Dir, Files) ->
+ lists:foreach(fun(File) ->
+ FullPath = filename:join(Dir,File),
+ case filelib:is_dir(FullPath) of
+ true ->
+ del_dirs(FullPath);
+ false ->
+ file:delete(FullPath)
+ end
+ end, Files).
-setup_pass_phrase(KeyBin, OutFile, Phrase) ->
- [{KeyType, _,_} = Entry0] = public_key:pem_decode(KeyBin),
- Key = public_key:pem_entry_decode(Entry0),
- Salt = crypto:strong_rand_bytes(8),
- Entry = public_key:pem_entry_encode(KeyType, Key,
- {{"DES-CBC", Salt}, Phrase}),
- Pem = public_key:pem_encode([Entry]),
- file:write_file(OutFile, Pem).
-
-setup_dsa_known_host(SystemDir, UserDir) ->
- {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_dsa_key.pub")),
- [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
- setup_known_hosts(Key, UserDir).
-
-setup_rsa_known_host(SystemDir, UserDir) ->
- {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_rsa_key.pub")),
- [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
- setup_known_hosts(Key, UserDir).
-
-setup_ecdsa_known_host(_Size, SystemDir, UserDir) ->
- {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_ecdsa_key.pub")),
- [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
- setup_known_hosts(Key, UserDir).
-
-setup_eddsa_known_host(HostPub, SystemDir, UserDir) ->
- {ok, SshBin} = file:read_file(filename:join(SystemDir, HostPub)),
- [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
- setup_known_hosts(Key, UserDir).
-
-setup_known_hosts(Key, UserDir) ->
- {ok, Hostname} = inet:gethostname(),
- {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
- IP = lists:concat([A, ".", B, ".", C, ".", D]),
- HostNames = [{hostnames,[Hostname, IP]}],
- KnownHosts = [{Key, HostNames}],
- KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts),
- KHFile = filename:join(UserDir, "known_hosts"),
- file:write_file(KHFile, KnownHostsEnc).
-
-setup_dsa_auth_keys(Dir, UserDir) ->
- {ok, Pem} = file:read_file(filename:join(Dir, "id_dsa")),
- DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
- PKey = DSA#'DSAPrivateKey'.y,
- P = DSA#'DSAPrivateKey'.p,
- Q = DSA#'DSAPrivateKey'.q,
- G = DSA#'DSAPrivateKey'.g,
- Dss = #'Dss-Parms'{p=P, q=Q, g=G},
- setup_auth_keys([{{PKey, Dss}, [{comment, "Test"}]}], UserDir).
-
-setup_rsa_auth_keys(Dir, UserDir) ->
- {ok, Pem} = file:read_file(filename:join(Dir, "id_rsa")),
- RSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
- #'RSAPrivateKey'{publicExponent = E, modulus = N} = RSA,
- PKey = #'RSAPublicKey'{publicExponent = E, modulus = N},
- setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir).
-
-setup_ecdsa_auth_keys(Size, Dir, UserDir) ->
- {ok, Pem} =
- case file:read_file(F=filename:join(Dir, "id_ecdsa"++Size)) of
- {error,E} ->
- ct:log("Failed (~p) to read ~p~nFiles: ~p", [E,F,file:list_dir(Dir)]),
- file:read_file(filename:join(Dir, "id_ecdsa"));
- Other ->
- Other
- end,
- ECDSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
- #'ECPrivateKey'{publicKey = Q,
- parameters = Param = {namedCurve,_Id0}} = ECDSA,
- PKey = #'ECPoint'{point = Q},
- setup_auth_keys([{ {PKey,Param}, [{comment, "Test"}]}], UserDir).
-
-setup_eddsa_auth_keys(IdPriv, Dir, UserDir) ->
- {ok, Pem} = file:read_file(filename:join(Dir, IdPriv)),
- {ed_pri, Alg, Pub, _} = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
- setup_auth_keys([{{ed_pub,Alg,Pub}, [{comment, "Test"}]}], UserDir).
-
-setup_auth_keys(Keys, Dir) ->
- AuthKeys = public_key:ssh_encode(Keys, auth_keys),
- AuthKeysFile = filename:join(Dir, "authorized_keys"),
- ok = file:write_file(AuthKeysFile, AuthKeys),
- AuthKeys.
-
-write_auth_keys(Keys, Dir) ->
- AuthKeysFile = filename:join(Dir, "authorized_keys"),
- file:write_file(AuthKeysFile, Keys).
-
-del_dirs(Dir) ->
- case file:list_dir(Dir) of
- {ok, []} ->
- file:del_dir(Dir);
- {ok, Files} ->
- lists:foreach(fun(File) ->
- FullPath = filename:join(Dir,File),
- case filelib:is_dir(FullPath) of
- true ->
- del_dirs(FullPath),
- file:del_dir(FullPath);
- false ->
- file:delete(FullPath)
- end
- end, Files);
- _ ->
- ok
- end.
openssh_sanity_check(Config) ->
ssh:start(),
@@ -622,34 +543,6 @@ openssh_sanity_check(Config) ->
{skip, Str}
end.
-openssh_supports(ClientOrServer, Tag, Alg) when ClientOrServer == sshc ;
- ClientOrServer == sshd ->
- SSH_algos = ssh_test_lib:default_algorithms(ClientOrServer),
- L = proplists:get_value(Tag, SSH_algos, []),
- lists:member(Alg, L) orelse
- lists:member(Alg, proplists:get_value(client2server, L, [])) orelse
- lists:member(Alg, proplists:get_value(server2client, L, [])).
-
-%%--------------------------------------------------------------------
-%% Check if we have a "newer" ssh client that supports these test cases
-
-ssh_client_supports_Q() ->
- 0 == check_ssh_client_support2(
- ?MODULE:open_port({spawn, "ssh -Q cipher"})
- ).
-
-check_ssh_client_support2(P) ->
- receive
- {P, {data, _A}} ->
- check_ssh_client_support2(P);
- {P, {exit_status, E}} ->
- ct:log("~p:~p exit_status:~n~p",[?MODULE,?LINE,E]),
- E
- after 5000 ->
- ct:log("Openssh command timed out ~n"),
- -1
- end.
-
%%%--------------------------------------------------------------------
%%% Probe a server or a client about algorithm support
@@ -776,6 +669,15 @@ intersect_bi_dir([H={_,[A|_]}|T]) when is_atom(A) ->
intersect_bi_dir([]) ->
[].
+some_empty([]) ->
+ false;
+some_empty([{_,[]}|_]) ->
+ true;
+some_empty([{_,L}|T]) when is_atom(hd(L)) ->
+ some_empty(T);
+some_empty([{_,L}|T]) when is_tuple(hd(L)) ->
+ some_empty(L) orelse some_empty(T).
+
sort_spec(L = [{_,_}|_] ) -> [{Tag,sort_spec(Es)} || {Tag,Es} <- L];
sort_spec(L) -> lists:usort(L).
@@ -967,12 +869,14 @@ get_kex_init(Conn, Ref, TRef) ->
end;
false ->
- ct:log("~p:~p Not in 'connected' state: ~p",[?MODULE,?LINE,State]),
receive
{reneg_timeout,Ref} ->
+ ct:log("~p:~p Not in 'connected' state: ~p but reneg_timeout received. Fail.",
+ [?MODULE,?LINE,State]),
ct:log("S = ~p", [S]),
ct:fail(reneg_timeout)
after 0 ->
+ ct:log("~p:~p Not in 'connected' state: ~p, Will try again after 100ms",[?MODULE,?LINE,State]),
timer:sleep(100), % If renegotiation is complete we do not
% want to exit on the reneg_timeout
get_kex_init(Conn, Ref, TRef)
@@ -1177,3 +1081,150 @@ mk_dir_path(DirPath) ->
%%ct:log("~p:~p return Other ~p ~ts", [?MODULE,?LINE,Other,DirPath]),
Other
end.
+
+%%%----------------------------------------------------------------
+%%% New
+
+setup_all_user_host_keys(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ setup_all_user_host_keys(DataDir, PrivDir).
+
+setup_all_user_host_keys(DataDir, PrivDir) ->
+ setup_all_user_host_keys(DataDir, PrivDir, filename:join(PrivDir,"system")).
+
+setup_all_user_host_keys(DataDir, UserDir, SysDir) ->
+ lists:foldl(fun(Alg, OkAlgs) ->
+ try
+ ok = ssh_test_lib:setup_user_key(Alg, DataDir, UserDir),
+ ok = ssh_test_lib:setup_host_key(Alg, DataDir, SysDir)
+ of
+ ok -> [Alg|OkAlgs]
+ catch
+ error:{badmatch, {error,enoent}} ->
+ OkAlgs;
+ C:E:S ->
+ ct:log("Exception in ~p:~p for alg ~p: ~p:~p~n~p",
+ [?MODULE,?FUNCTION_NAME,Alg,C,E,S]),
+ OkAlgs
+ end
+ end, [], ssh_transport:supported_algorithms(public_key)).
+
+
+setup_all_host_keys(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ setup_all_host_keys(DataDir, filename:join(PrivDir,"system")).
+
+setup_all_host_keys(DataDir, SysDir) ->
+ lists:foldl(fun(Alg, OkAlgs) ->
+ try
+ ok = ssh_test_lib:setup_host_key(Alg, DataDir, SysDir)
+ of
+ ok -> [Alg|OkAlgs]
+ catch
+ error:{badmatch, {error,enoent}} ->
+ OkAlgs;
+ C:E:S ->
+ ct:log("Exception in ~p:~p for alg ~p: ~p:~p~n~p",
+ [?MODULE,?FUNCTION_NAME,Alg,C,E,S]),
+ OkAlgs
+ end
+ end, [], ssh_transport:supported_algorithms(public_key)).
+
+
+setup_all_user_keys(DataDir, UserDir) ->
+ lists:foldl(fun(Alg, OkAlgs) ->
+ try
+ ok = ssh_test_lib:setup_user_key(Alg, DataDir, UserDir)
+ of
+ ok -> [Alg|OkAlgs]
+ catch
+ error:{badmatch, {error,enoent}} ->
+ OkAlgs;
+ C:E:S ->
+ ct:log("Exception in ~p:~p for alg ~p: ~p:~p~n~p",
+ [?MODULE,?FUNCTION_NAME,Alg,C,E,S]),
+ OkAlgs
+ end
+ end, [], ssh_transport:supported_algorithms(public_key)).
+
+
+setup_user_key(SshAlg, DataDir, UserDir) ->
+ file:make_dir(UserDir),
+ %% Copy private user key to user's dir
+ {ok,_} = file:copy(filename:join(DataDir, file_base_name(user_src,SshAlg)),
+ filename:join(UserDir, file_base_name(user,SshAlg))),
+ %% Setup authorized_keys in user's dir
+ {ok,Pub} = file:read_file(filename:join(DataDir, file_base_name(user_src,SshAlg)++".pub")),
+ ok = file:write_file(filename:join(UserDir, "authorized_keys"),
+ io_lib:format("~n~s~n",[Pub]),
+ [append]),
+ ?ct_log_show_file( filename:join(DataDir, file_base_name(user_src,SshAlg)++".pub") ),
+ ?ct_log_show_file( filename:join(UserDir, "authorized_keys") ),
+ ok.
+
+setup_host_key_create_dir(SshAlg, DataDir, BaseDir) ->
+ SysDir = filename:join(BaseDir,"system"),
+ ct:log("~p:~p SshAlg=~p~nDataDir = ~p~nBaseDir = ~p~nSysDir = ~p",[?MODULE,?LINE,SshAlg, DataDir, BaseDir,SysDir]),
+ file:make_dir(SysDir),
+ setup_host_key(SshAlg, DataDir, SysDir),
+ SysDir.
+
+setup_host_key(SshAlg, DataDir, SysDir) ->
+ mk_dir_path(SysDir),
+ %% Copy private host key to system's dir
+ {ok,_} = file:copy(filename:join(DataDir, file_base_name(system_src,SshAlg)),
+ filename:join(SysDir, file_base_name(system,SshAlg))),
+ ?ct_log_show_file( filename:join(SysDir, file_base_name(system,SshAlg)) ),
+ ok.
+
+setup_known_host(SshAlg, DataDir, UserDir) ->
+ {ok,Pub} = file:read_file(filename:join(DataDir, file_base_name(system_src,SshAlg)++".pub")),
+ S = lists:join(" ", lists:reverse(tl(lists:reverse(string:tokens(binary_to_list(Pub), " "))))),
+ ok = file:write_file(filename:join(UserDir, "known_hosts"),
+ io_lib:format("~p~n",[S])),
+ ?ct_log_show_file( filename:join(UserDir, "known_hosts") ),
+ ok.
+
+
+get_addr_str() ->
+ {ok, Hostname} = inet:gethostname(),
+ {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
+ IP = lists:concat([A, ".", B, ".", C, ".", D]),
+ lists:concat([Hostname,",",IP]).
+
+
+file_base_name(user, 'ecdsa-sha2-nistp256') -> "id_ecdsa";
+file_base_name(user, 'ecdsa-sha2-nistp384') -> "id_ecdsa";
+file_base_name(user, 'ecdsa-sha2-nistp521') -> "id_ecdsa";
+file_base_name(user, 'rsa-sha2-256' ) -> "id_rsa";
+file_base_name(user, 'rsa-sha2-384' ) -> "id_rsa";
+file_base_name(user, 'rsa-sha2-512' ) -> "id_rsa";
+file_base_name(user, 'ssh-dss' ) -> "id_dsa";
+file_base_name(user, 'ssh-ed25519' ) -> "id_ed25519";
+file_base_name(user, 'ssh-ed448' ) -> "id_ed448";
+file_base_name(user, 'ssh-rsa' ) -> "id_rsa";
+
+file_base_name(user_src, 'ecdsa-sha2-nistp256') -> "id_ecdsa256";
+file_base_name(user_src, 'ecdsa-sha2-nistp384') -> "id_ecdsa384";
+file_base_name(user_src, 'ecdsa-sha2-nistp521') -> "id_ecdsa521";
+file_base_name(user_src, Alg) -> file_base_name(user, Alg);
+
+file_base_name(system, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key";
+file_base_name(system, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key";
+file_base_name(system, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key";
+file_base_name(system, 'rsa-sha2-256' ) -> "ssh_host_rsa_key";
+file_base_name(system, 'rsa-sha2-384' ) -> "ssh_host_rsa_key";
+file_base_name(system, 'rsa-sha2-512' ) -> "ssh_host_rsa_key";
+file_base_name(system, 'ssh-dss' ) -> "ssh_host_dsa_key";
+file_base_name(system, 'ssh-ed25519' ) -> "ssh_host_ed25519_key";
+file_base_name(system, 'ssh-ed448' ) -> "ssh_host_ed448_key";
+file_base_name(system, 'ssh-rsa' ) -> "ssh_host_rsa_key";
+
+file_base_name(system_src, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key256";
+file_base_name(system_src, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key384";
+file_base_name(system_src, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key521";
+file_base_name(system_src, Alg) -> file_base_name(system, Alg).
+
+%%%----------------------------------------------------------------