From 9f23065062eb724e58f39a65e416e5b0e1e9d95d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 10 Feb 2017 14:37:41 +0100 Subject: ssh: allow a list of fingerprint algos in silently_accept_hosts option --- lib/ssh/doc/src/ssh.xml | 13 ++++++++++--- lib/ssh/src/ssh.erl | 21 ++++++++++++++++----- lib/ssh/test/ssh_options_SUITE.erl | 26 +++++++++++++++++++------- 3 files changed, 45 insertions(+), 15 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 6b49f89449..1a6bac8355 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -175,9 +175,11 @@ supplied with this option.

- +
- boolean()]]> + +
+ boolean()]]>

When true, hosts are added to the @@ -188,8 +190,13 @@ (PeerName, PeerHostKeyFingerPrint). The fingerprint is calculated on the Peer's Host Key with public_key:ssh_hostkey_fingerprint/1.

-

If the crypto:digest_type() is present, the fingerprint is calculated with that digest type by the function +

If the HashAlgoSpec is present and is an crypto:digest_type(), the fingerprint is calculated + with that digest type by the function public_key:ssh_hostkey_fingerprint/2. +

+

If the HashAlgoSpec is present and is a list of crypto:digest_type(), the fingerprint is calulated for + each digest_type and PeerHostKeyFingerPrint is the list of the results in order corresponding to the + HashAlgoSpec.

diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 31e343e81b..f408086c0f 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -620,11 +620,22 @@ handle_ssh_option({silently_accept_hosts, Value} = Opt) when is_boolean(Value) - handle_ssh_option({silently_accept_hosts, Value} = Opt) when is_function(Value,2) -> Opt; handle_ssh_option({silently_accept_hosts, {DigestAlg,Value}} = Opt) when is_function(Value,2) -> - case lists:member(DigestAlg, [md5, sha, sha224, sha256, sha384, sha512]) of - true -> - Opt; - false -> - throw({error, {eoptions, Opt}}) + Algs = if is_atom(DigestAlg) -> [DigestAlg]; + is_list(DigestAlg) -> DigestAlg; + true -> throw({error, {eoptions, Opt}}) + end, + case [A || A <- Algs, + not lists:member(A, [md5, sha, sha224, sha256, sha384, sha512])] of + [_|_] = UnSup1 -> + throw({error, {{eoptions, Opt}, {not_fingerprint_algos,UnSup1}}}); + [] -> + CryptoHashAlgs = proplists:get_value(hashs, crypto:supports(), []), + case [A || A <- Algs, + not lists:member(A, CryptoHashAlgs)] of + [_|_] = UnSup2 -> + throw({error, {{eoptions, Opt}, {unsupported_algo,UnSup2}}}); + [] -> Opt + end end; handle_ssh_option({user_interaction, Value} = Opt) when is_boolean(Value) -> Opt; diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index 86f5cb1746..d07c596411 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -67,7 +67,8 @@ hostkey_fingerprint_check_sha/1, hostkey_fingerprint_check_sha256/1, hostkey_fingerprint_check_sha384/1, - hostkey_fingerprint_check_sha512/1 + hostkey_fingerprint_check_sha512/1, + hostkey_fingerprint_check_list/1 ]). %%% Common test callbacks @@ -112,6 +113,7 @@ all() -> hostkey_fingerprint_check_sha256, hostkey_fingerprint_check_sha384, hostkey_fingerprint_check_sha512, + hostkey_fingerprint_check_list, id_string_no_opt_client, id_string_own_string_client, id_string_random_client, @@ -812,6 +814,8 @@ hostkey_fingerprint_check_sha384(Config) -> hostkey_fingerprint_check_sha512(Config) -> do_hostkey_fingerprint_check(Config, sha512). +hostkey_fingerprint_check_list(Config) -> + do_hostkey_fingerprint_check(Config, [sha,md5,sha256]). %%%---- do_hostkey_fingerprint_check(Config, HashAlg) -> @@ -824,9 +828,10 @@ do_hostkey_fingerprint_check(Config, HashAlg) -> supported_hash(old) -> true; supported_hash(HashAlg) -> - proplists:get_value(HashAlg, - proplists:get_value(hashs, crypto:supports(), []), - false). + Hs = if is_atom(HashAlg) -> [HashAlg]; + is_list(HashAlg) -> HashAlg + end, + [] == (Hs -- proplists:get_value(hashs, crypto:supports(), [])). really_do_hostkey_fingerprint_check(Config, HashAlg) -> @@ -840,7 +845,7 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) -> %% All host key fingerprints. Trust that public_key has checked the ssh_hostkey_fingerprint %% function since that function is used by the ssh client... - FPs = [case HashAlg of + FPs0 = [case HashAlg of old -> public_key:ssh_hostkey_fingerprint(Key); _ -> public_key:ssh_hostkey_fingerprint(HashAlg, Key) end @@ -856,6 +861,9 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) -> _:_ -> [] end end], + FPs = if is_atom(HashAlg) -> FPs0; + is_list(HashAlg) -> lists:concat(FPs0) + end, ct:log("Fingerprints(~p) = ~p",[HashAlg,FPs]), %% Start daemon with the public keys that we got fingerprints from @@ -866,8 +874,12 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) -> FP_check_fun = fun(PeerName, FP) -> ct:pal("PeerName = ~p, FP = ~p",[PeerName,FP]), HostCheck = (Host == PeerName), - FPCheck = lists:member(FP, FPs), - ct:log("check ~p == ~p (~p) and ~n~p in ~p (~p)~n", + FPCheck = + if is_atom(HashAlg) -> lists:member(FP, FPs); + is_list(HashAlg) -> lists:all(fun(FP1) -> lists:member(FP1,FPs) end, + FP) + end, + ct:log("check ~p == ~p (~p) and ~n~p~n in ~p (~p)~n", [PeerName,Host,HostCheck,FP,FPs,FPCheck]), HostCheck and FPCheck end, -- cgit v1.2.3 From 82a5b5f3b8824ab7c1da403c3a40bcf0fc98c690 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 15 Feb 2017 13:26:18 +0100 Subject: ssh: reword documentation --- lib/ssh/doc/src/ssh.xml | 61 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 21 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 1a6bac8355..e42f16ebd0 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -153,7 +153,7 @@

IP version to use.

- +

Sets the user directory, that is, the directory containing ssh configuration files for the user, such as @@ -175,29 +175,48 @@ supplied with this option.

- -
- -
- boolean()]]> + +
+
+
+
+
+ boolean()]]>
+
+
-

When true, hosts are added to the - file without asking the user. - Defaults to false which will give a user question on stdio of whether to accept or reject a previously - unseen host.

-

If the option value is has an accept_fun(), that fun will called with the arguments - (PeerName, PeerHostKeyFingerPrint). The fingerprint is calculated on the Peer's Host Key with - public_key:ssh_hostkey_fingerprint/1. -

-

If the HashAlgoSpec is present and is an crypto:digest_type(), the fingerprint is calculated - with that digest type by the function - public_key:ssh_hostkey_fingerprint/2. +

This option guides the connect function how to act when the connected server presents a Host + Key that the client has not seen before. The default is to ask the user with a question on stdio of whether to + accept or reject the new Host Key. + See also the option user_dir + for the path to the file known_hosts where previously accepted Host Keys are recorded.

-

If the HashAlgoSpec is present and is a list of crypto:digest_type(), the fingerprint is calulated for - each digest_type and PeerHostKeyFingerPrint is the list of the results in order corresponding to the - HashAlgoSpec. -

+

The option can be given in three different forms as seen above:

+ + The value is a boolean(). The value true will make the client accept any unknown + Host Key without any user interaction. The value false keeps the default behaviour of asking the + the user on stdio. + + A CallbackFun will be called and the boolean return value true will make the client + accept the Host Key. A reurn value of false will make the client to reject the Host Key and therefore + also the connection will be closed. The arguments to the fun are: + + PeerName - a string with the name or address of the remote host. + FingerPrint - the fingerprint of the Host Key as + public_key:ssh_hostkey_fingerprint/1 + calculates it. + + + + A tuple {HashAlgoSpec, CallbackFun}. The HashAlgoSpec specifies which hash algorithm + shall be used to calculate the fingerprint used in the call of the CallbackFun. The HashALgoSpec + is either an atom or a list of atoms as the first argument in + public_key:ssh_hostkey_fingerprint/2. + If it is a list of hash algorithm names, the FingerPrint argument in the CallbackFun will be + a list of fingerprints in the same order as the corresponding name in the HashAlgoSpec list. + +
-- cgit v1.2.3 From 2869472d38814d8ab5f034e383c7aa063aab4618 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 15 Feb 2017 13:29:32 +0100 Subject: ssh: speling error --- lib/ssh/doc/src/ssh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index e42f16ebd0..20508a73a6 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -226,7 +226,7 @@ supplying a password. Defaults to true. Even if user interaction is allowed it can be suppressed by other options, such as silently_accept_hosts - and password. However, those optins are not always desirable + and password. However, those options are not always desirable to use from a security point of view.

-- cgit v1.2.3 From 5fa9ae3f7cce55047061b94f35940d6eaf94d9ee Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 15 Feb 2017 13:34:16 +0100 Subject: ssh: speling error --- lib/ssh/doc/src/ssh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/ssh') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 20508a73a6..f6e26f5ee8 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -199,7 +199,7 @@ the user on stdio. A CallbackFun will be called and the boolean return value true will make the client - accept the Host Key. A reurn value of false will make the client to reject the Host Key and therefore + accept the Host Key. A return value of false will make the client to reject the Host Key and therefore also the connection will be closed. The arguments to the fun are: PeerName - a string with the name or address of the remote host. -- cgit v1.2.3