From 4bdb8f52303ceecb5e7c00592b53aa8dcaa49ab9 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 28 Aug 2017 11:49:46 +0200 Subject: ssh: Added option 'modify_algorithms' with prepend, append and rm If a user wants to enable one non-default algorithm or remove a default one, the option preferred_algorithms is too complicated since it replaces the whole set of algorithms. --- lib/ssh/src/ssh_options.erl | 270 ++++++++++++++++++++++++++++++------------ lib/ssh/src/ssh_transport.erl | 19 +++ 2 files changed, 214 insertions(+), 75 deletions(-) diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl index b41ad8b33b..d8931da774 100644 --- a/lib/ssh/src/ssh_options.erl +++ b/lib/ssh/src/ssh_options.erl @@ -170,9 +170,10 @@ handle_options(Role, PropList0, Opts0) when is_map(Opts0), OptionDefinitions), %% Enter the user's values into the map; unknown keys are %% treated as socket options - lists:foldl(fun(KV, Vals) -> - save(KV, OptionDefinitions, Vals) - end, InitialMap, PropList1) + final_preferred_algorithms( + lists:foldl(fun(KV, Vals) -> + save(KV, OptionDefinitions, Vals) + end, InitialMap, PropList1)) catch error:{eoptions, KV, undefined} -> {error, {eoptions,KV}}; @@ -509,6 +510,15 @@ default(common) -> class => user_options }, + %% NOTE: This option is supposed to be used only in this very module (?MODULE). There is + %% a final stage in handle_options that "merges" the preferred_algorithms option and this one. + %% The preferred_algorithms is the one to use in the rest of the ssh application! + {modify_algorithms, def} => + #{default => undefined, % signals error if unsupported algo in preferred_algorithms :( + chk => fun check_modify_algorithms/1, + class => user_options + }, + {id_string, def} => #{default => undefined, % FIXME: see ssh_transport:ssh_vsn/0 chk => fun(random) -> @@ -820,83 +830,193 @@ valid_hash(L, Ss) when is_list(L) -> lists:all(fun(S) -> valid_hash(S,Ss) end, L valid_hash(X, _) -> error_in_check(X, "Expect atom or list in fingerprint spec"). %%%---------------------------------------------------------------- -check_preferred_algorithms(Algs) -> - [error_in_check(K,"Bad preferred_algorithms key") - || {K,_} <- Algs, - not lists:keymember(K,1,ssh:default_algorithms())], +check_modify_algorithms(M) when is_list(M) -> + [error_in_check(Op_KVs, "Bad modify_algorithms") + || Op_KVs <- M, + not is_tuple(Op_KVs) + orelse (size(Op_KVs) =/= 2) + orelse (not lists:member(element(1,Op_KVs), [append,prepend,rm]))], + {true, [{Op,normalize_mod_algs(KVs,false)} || {Op,KVs} <- M]}; +check_modify_algorithms(_) -> + error_in_check(modify_algorithms, "Bad option value. List expected."). + + + + +normalize_mod_algs(KVs, UseDefaultAlgs) -> + normalize_mod_algs(ssh_transport:algo_classes(), KVs, [], UseDefaultAlgs). + +normalize_mod_algs([K|Ks], KVs0, Acc, UseDefaultAlgs) -> + %% Pick the expected keys in order and check if they are in the user's list + {Vs1, KVs} = + case lists:keytake(K, 1, KVs0) of + {value, {K,Vs0}, KVs1} -> + {Vs0, KVs1}; + false -> + {[], KVs0} + end, + Vs = normalize_mod_alg_list(K, Vs1, UseDefaultAlgs), + normalize_mod_algs(Ks, KVs, [{K,Vs} | Acc], UseDefaultAlgs); +normalize_mod_algs([], [], Acc, _) -> + %% No values left in the key-value list after removing the expected entries + %% (thats good) + lists:reverse(Acc); +normalize_mod_algs([], [{K,_}|_], _, _) -> + %% Some values left in the key-value list after removing the expected entries + %% (thats bad) + case ssh_transport:algo_class(K) of + true -> error_in_check(K, "Duplicate key"); + false -> error_in_check(K, "Unknown key") + end; +normalize_mod_algs([], [X|_], _, _) -> + error_in_check(X, "Bad list element"). + + + +%%% Handle the algorithms list +normalize_mod_alg_list(K, Vs, UseDefaultAlgs) -> + normalize_mod_alg_list(K, + ssh_transport:algo_two_spec_class(K), + Vs, + def_alg(K,UseDefaultAlgs)). + + +normalize_mod_alg_list(_K, _, [], Default) -> + Default; + +normalize_mod_alg_list(K, true, [{client2server,L1}], [_,{server2client,L2}]) -> + [nml1(K,{client2server,L1}), + {server2client,L2}]; + +normalize_mod_alg_list(K, true, [{server2client,L2}], [{client2server,L1},_]) -> + [{client2server,L1}, + nml1(K,{server2client,L2})]; + +normalize_mod_alg_list(K, true, [{server2client,L2},{client2server,L1}], _) -> + [nml1(K,{client2server,L1}), + nml1(K,{server2client,L2})]; + +normalize_mod_alg_list(K, true, [{client2server,L1},{server2client,L2}], _) -> + [nml1(K,{client2server,L1}), + nml1(K,{server2client,L2})]; + +normalize_mod_alg_list(K, true, L0, _) -> + L = nml(K,L0), % Throws errors + [{client2server,L}, + {server2client,L}]; + +normalize_mod_alg_list(K, false, L, _) -> + nml(K,L). + + +nml1(K, {T,V}) when T==client2server ; T==server2client -> + {T, nml({K,T}, V)}. + +nml(K, L) -> + [error_in_check(K, "Bad value for this key") % This is a throw + || V <- L, + not is_atom(V) + ], + case L -- lists:usort(L) of + [] -> ok; + Dups -> error_in_check({K,Dups}, "Duplicates") % This is a throw + end, + L. - try alg_duplicates(Algs, [], []) - of - [] -> - {true, - [case proplists:get_value(Key, Algs) of - undefined -> - {Key,DefAlgs}; - Vals -> - handle_pref_alg(Key,Vals,SupAlgs) - end - || {{Key,DefAlgs}, {Key,SupAlgs}} <- lists:zip(ssh:default_algorithms(), - ssh_transport:supported_algorithms()) - ] - }; - - Dups -> - error_in_check(Dups, "Duplicates") - catch - _:_ -> - false - end. -alg_duplicates([{K,V}|KVs], Ks, Dups0) -> - Dups = - case lists:member(K,Ks) of - true -> [K|Dups0]; - false -> Dups0 - end, - case V--lists:usort(V) of - [] -> alg_duplicates(KVs, [K|Ks], Dups); - Ds -> alg_duplicates(KVs, [K|Ks], Dups++Ds) +def_alg(K, false) -> + case ssh_transport:algo_two_spec_class(K) of + false -> []; + true -> [{client2server,[]}, {server2client,[]}] end; -alg_duplicates([], _Ks, Dups) -> - Dups. - -handle_pref_alg(Key, - Vs=[{client2server,C2Ss=[_|_]},{server2client,S2Cs=[_|_]}], - [{client2server,Sup_C2Ss},{server2client,Sup_S2Cs}] - ) -> - chk_alg_vs(Key, C2Ss, Sup_C2Ss), - chk_alg_vs(Key, S2Cs, Sup_S2Cs), - {Key, Vs}; - -handle_pref_alg(Key, - Vs=[{server2client,[_|_]},{client2server,[_|_]}], - Sup=[{client2server,_},{server2client,_}] - ) -> - handle_pref_alg(Key, lists:reverse(Vs), Sup); - -handle_pref_alg(Key, - Vs=[V|_], - Sup=[{client2server,_},{server2client,_}] - ) when is_atom(V) -> - handle_pref_alg(Key, [{client2server,Vs},{server2client,Vs}], Sup); - -handle_pref_alg(Key, - Vs=[V|_], - Sup=[S|_] - ) when is_atom(V), is_atom(S) -> - chk_alg_vs(Key, Vs, Sup), - {Key, Vs}; - -handle_pref_alg(Key, Vs, _) -> - error_in_check({Key,Vs}, "Badly formed list"). - -chk_alg_vs(OptKey, Values, SupportedValues) -> - case (Values -- SupportedValues) of - [] -> Values; - [none] -> [none]; % for testing only - Bad -> error_in_check({OptKey,Bad}, "Unsupported value(s) found") +def_alg(K, true) -> + ssh_transport:default_algorithms(K). + + + +check_preferred_algorithms(Algs) when is_list(Algs) -> + check_input_ok(Algs), + {true, normalize_mod_algs(Algs, true)}; + +check_preferred_algorithms(Algs) when is_list(Algs) -> + check_preferred_algorithms({false,Algs}); + +check_preferred_algorithms(_) -> + error_in_check(modify_algorithms, "Bad option value. List expected."). + + +check_input_ok(Algs) -> + [error_in_check(KVs, "Bad preferred_algorithms") + || KVs <- Algs, + not is_tuple(KVs) + orelse (size(KVs) =/= 2)]. + +%%%---------------------------------------------------------------- +final_preferred_algorithms(Options) -> + Result = + case ?GET_OPT(modify_algorithms, Options) of + undefined -> + rm_non_supported(true, + ?GET_OPT(preferred_algorithms, Options)); + ModAlgs -> + rm_non_supported(false, + eval_ops(?GET_OPT(preferred_algorithms, Options), + ModAlgs)) + end, + error_if_empty(Result), % Throws errors if any value list is empty + ?PUT_OPT({preferred_algorithms,Result}, Options). + +eval_ops(PrefAlgs, ModAlgs) -> + lists:foldl(fun eval_op/2, PrefAlgs, ModAlgs). + +eval_op({Op,AlgKVs}, PrefAlgs) -> + eval_op(Op, AlgKVs, PrefAlgs, []). + +eval_op(Op, [{C,L1}|T1], [{C,L2}|T2], Acc) -> + eval_op(Op, T1, T2, [{C,eval_op(Op,L1,L2,[])} | Acc]); + +eval_op(_, [], [], Acc) -> lists:reverse(Acc); +eval_op(rm, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> Pref -- Opt; +eval_op(append, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> (Pref--Opt) ++ Opt; +eval_op(prepend, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> Opt ++ (Pref--Opt). + + +rm_non_supported(UnsupIsErrorFlg, KVs) -> + [{K,rmns(K,Vs, UnsupIsErrorFlg)} || {K,Vs} <- KVs]. + +rmns(K, Vs, UnsupIsErrorFlg) -> + case ssh_transport:algo_two_spec_class(K) of + false -> + rm_unsup(Vs, ssh_transport:supported_algorithms(K), UnsupIsErrorFlg, K); + true -> + [{C, rm_unsup(Vsx, Sup, UnsupIsErrorFlg, {K,C})} + || {{C,Vsx},{C,Sup}} <- lists:zip(Vs,ssh_transport:supported_algorithms(K)) + ] end. +rm_unsup(A, B, Flg, ErrInf) -> + case A--B of + Unsup=[_|_] when Flg==true -> error({eoptions, + {preferred_algorithms,{ErrInf,Unsup}}, + "Unsupported value(s) found" + }); + Unsup -> A -- Unsup + end. + + +error_if_empty([{K,[]}|_]) -> + error({eoptions, K, "Empty resulting algorithm list"}); +error_if_empty([{K,[{client2server,[]}, {server2client,[]}]}]) -> + error({eoptions, K, "Empty resulting algorithm list"}); +error_if_empty([{K,[{client2server,[]}|_]} | _]) -> + error({eoptions, {K,client2server}, "Empty resulting algorithm list"}); +error_if_empty([{K,[_,{server2client,[]}|_]} | _]) -> + error({eoptions, {K,server2client}, "Empty resulting algorithm list"}); +error_if_empty([_|T]) -> + error_if_empty(T); +error_if_empty([]) -> + ok. + %%%---------------------------------------------------------------- forbidden_option(K,V) -> Txt = io_lib:format("The option '~s' is used internally. The " diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 412f5de9de..c48c0800e4 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -34,6 +34,8 @@ -export([next_seqnum/1, supported_algorithms/0, supported_algorithms/1, default_algorithms/0, default_algorithms/1, + algo_classes/0, algo_class/1, + algo_two_spec_classes/0, algo_two_spec_class/1, handle_packet_part/4, handle_hello_version/1, key_exchange_init_msg/1, @@ -81,6 +83,23 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. +algo_class(kex) -> true; +algo_class(public_key) -> true; +algo_class(cipher) -> true; +algo_class(mac) -> true; +algo_class(compression) -> true; +algo_class(_) -> false. + + +algo_two_spec_classes() -> [cipher, mac, compression]. + +algo_two_spec_class(cipher) -> true; +algo_two_spec_class(mac) -> true; +algo_two_spec_class(compression) -> true; +algo_two_spec_class(_) -> false. + + + default_algorithms(kex) -> supported_algorithms(kex, [ 'diffie-hellman-group1-sha1' % Gone in OpenSSH 7.3.p1 -- cgit v1.2.3 From fdb4455125776076b72dc1e31f2909c5ea819651 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 31 Aug 2017 17:53:45 +0200 Subject: ssh: ssh:chk_algos_opts/1 This function is intended primarily for users who want to experiment with the options preferred_algorithms and modify_algorithms. --- lib/ssh/src/ssh.erl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 5ebab43c30..1a5d48baca 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -35,6 +35,7 @@ daemon/1, daemon/2, daemon/3, daemon_info/1, default_algorithms/0, + chk_algos_opts/1, stop_listener/1, stop_listener/2, stop_listener/3, stop_daemon/1, stop_daemon/2, stop_daemon/3, shell/1, shell/2, shell/3 @@ -380,6 +381,27 @@ start_shell(Error) -> default_algorithms() -> ssh_transport:default_algorithms(). +%%-------------------------------------------------------------------- +-spec chk_algos_opts(list(any())) -> algs_list() . +%%-------------------------------------------------------------------- +chk_algos_opts(Opts) -> + case lists:foldl( + fun({preferred_algorithms,_}, Acc) -> Acc; + ({modify_algorithms,_}, Acc) -> Acc; + (KV, Acc) -> [KV|Acc] + end, [], Opts) + of + [] -> + case ssh_options:handle_options(client, Opts) of + M when is_map(M) -> + maps:get(preferred_algorithms, M); + Others -> + Others + end; + OtherOps -> + {error, {non_algo_opts_found,OtherOps}} + end. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -- cgit v1.2.3 From b3cb129a5518d0018340eea088acd409b616836a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 28 Aug 2017 12:51:23 +0200 Subject: ssh: test cases for modify_algorithms --- lib/ssh/test/ssh_protocol_SUITE.erl | 140 ++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 5 deletions(-) diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 0837fe7eaf..7da921adb2 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -34,8 +34,8 @@ -define(NEWLINE, <<"\r\n">>). -define(REKEY_DATA_TMO, 65000). -%%-define(DEFAULT_KEX, 'diffie-hellman-group1-sha1'). -define(DEFAULT_KEX, 'diffie-hellman-group14-sha256'). +-define(EXTRA_KEX, 'diffie-hellman-group1-sha1'). -define(CIPHERS, ['aes256-ctr','aes192-ctr','aes128-ctr','aes128-cbc','3des-cbc']). -define(DEFAULT_CIPHERS, [{client2server,?CIPHERS}, {server2client,?CIPHERS}]). @@ -60,7 +60,8 @@ all() -> {group,authentication}, {group,packet_size_error}, {group,field_size_error}, - {group,ext_info} + {group,ext_info}, + {group,preferred_algorithms} ]. groups() -> @@ -96,7 +97,13 @@ groups() -> no_ext_info_s2, ext_info_s, ext_info_c - ]} + ]}, + {preferred_algorithms, [], [preferred_algorithms, + modify_append, + modify_prepend, + modify_rm, + modify_combo + ]} ]. @@ -701,8 +708,6 @@ ext_info_s(Config) -> %%%-------------------------------------------------------------------- %%% The client sends the extension ext_info_c(Config) -> - {User,_Pwd} = server_user_password(Config), - %% Create a listening socket as server socket: {ok,InitialState} = ssh_trpt_test_lib:exec(listen), HostPort = ssh_trpt_test_lib:server_host_port(InitialState), @@ -757,10 +762,135 @@ ext_info_c(Config) -> {result, Pid, Error} -> ct:fail("Error: ~p",[Error]) end. + +%%%---------------------------------------------------------------- +%%% +preferred_algorithms(Config) -> + Ciphers = filter_supported(cipher, ?CIPHERS), + {error,{eoptions,{{preferred_algorithms,{kex,[some_unknown_algo]}}, + "Unsupported value(s) found"}}} = + chk_pref_algs(Config, + [?DEFAULT_KEX], + Ciphers, + [{preferred_algorithms, [{kex,[some_unknown_algo,?DEFAULT_KEX]}, + {cipher,Ciphers} + ]} + ]). + +%%%---------------------------------------------------------------- +%%% +modify_append(Config) -> + Ciphers = filter_supported(cipher, ?CIPHERS), + {ok,_} = + chk_pref_algs(Config, + [?DEFAULT_KEX, ?EXTRA_KEX], + Ciphers, + [{preferred_algorithms, [{kex,[?DEFAULT_KEX]}, + {cipher,Ciphers} + ]}, + {modify_algorithms, [{append,[{kex,[some_unknown_algo,?EXTRA_KEX]}]}]} + ]). + +%%%---------------------------------------------------------------- +%%% +modify_prepend(Config) -> + Ciphers = filter_supported(cipher, ?CIPHERS), + {ok,_} = + chk_pref_algs(Config, + [?EXTRA_KEX, ?DEFAULT_KEX], + Ciphers, + [{preferred_algorithms, [{kex,[?DEFAULT_KEX]}, + {cipher,Ciphers} + ]}, + {modify_algorithms, [{prepend,[{kex,[some_unknown_algo,?EXTRA_KEX]}]}]} + ]). + +%%%---------------------------------------------------------------- +%%% +modify_rm(Config) -> + Ciphers = filter_supported(cipher, ?CIPHERS), + {ok,_} = + chk_pref_algs(Config, + [?DEFAULT_KEX], + tl(Ciphers), + [{preferred_algorithms, [{kex,[?DEFAULT_KEX,?EXTRA_KEX]}, + {cipher,Ciphers} + ]}, + {modify_algorithms, [{rm,[{kex,[some_unknown_algo,?EXTRA_KEX]}, + {cipher,[hd(Ciphers)]} + ]} + ]} + ]). + + +%%%---------------------------------------------------------------- +%%% +modify_combo(Config) -> + Ciphers = filter_supported(cipher, ?CIPHERS), + LastC = lists:last(Ciphers), + {ok,_} = + chk_pref_algs(Config, + [?DEFAULT_KEX], + [LastC] ++ (tl(Ciphers)--[LastC]) ++ [hd(Ciphers)], + [{preferred_algorithms, [{kex,[?DEFAULT_KEX,?EXTRA_KEX]}, + {cipher,Ciphers} + ]}, + {modify_algorithms, [{rm,[{kex,[some_unknown_algo,?EXTRA_KEX]} + ]}, + {prepend,[{cipher,[{server2client,[LastC]}]} + ]}, + {append,[{cipher,[a,hd(Ciphers),b]} + ]} + ]} + ]). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ +chk_pref_algs(Config, + ExpectedKex, + ExpectedCiphers, + ServerPrefOpts) -> + %% Start the dameon + case ssh_test_lib:daemon( + [{send_ext_info,false}, + {recv_ext_info,false}, + {system_dir, system_dir(Config)} + | ServerPrefOpts]) + of + {_,Host,Port} -> + %% Check the Kex part + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, {print_messages,detail}]}, + {connect, Host, Port, + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false} + ]}, + {send, hello}, + receive_hello, + {match, + #ssh_msg_kexinit{ + kex_algorithms = to_lists(ExpectedKex), + encryption_algorithms_server_to_client = to_lists(ExpectedCiphers), + _ = '_'}, + receive_msg} + ]); + Error -> + Error + end. + + +filter_supported(K, Algs) -> Algs -- (Algs--supported(K)). + +supported(K) -> proplists:get_value( + server2client, + ssh_transport:supported_algorithms(cipher)). + +to_lists(L) -> lists:map(fun erlang:atom_to_list/1, L). + + %%%---- init_suite and end_suite --------------------------------------- start_apps(Config) -> catch ssh:stop(), -- cgit v1.2.3 From c657c2133913412f02442b2366c5580d0bc4beef Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 28 Aug 2017 15:32:08 +0200 Subject: ssh: Document the option modify_algorithms and a User's Guide chapter --- lib/ssh/doc/src/Makefile | 3 +- lib/ssh/doc/src/configure_algos.xml | 457 ++++++++++++++++++++++++++++++++++++ lib/ssh/doc/src/ssh.xml | 80 ++++++- lib/ssh/doc/src/ssh_app.xml | 4 +- lib/ssh/doc/src/usersguide.xml | 1 + 5 files changed, 541 insertions(+), 4 deletions(-) create mode 100644 lib/ssh/doc/src/configure_algos.xml diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index a759854da4..adbda5a030 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -53,7 +53,8 @@ XML_PART_FILES = part_notes.xml \ XML_CHAPTER_FILES = notes.xml \ introduction.xml \ ssh_protocol.xml \ - using_ssh.xml + using_ssh.xml \ + configure_algos.xml BOOK_FILES = book.xml diff --git a/lib/ssh/doc/src/configure_algos.xml b/lib/ssh/doc/src/configure_algos.xml new file mode 100644 index 0000000000..ebd128c097 --- /dev/null +++ b/lib/ssh/doc/src/configure_algos.xml @@ -0,0 +1,457 @@ + + + + +
+ + 2017 + 2017 + Ericsson AB. All Rights Reserved. + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + Configuring algorithms in SSH + + + + + + configure_algos.xml +
+ +
+ + Introduction +

To fully understand how to configure the algorithms, we must understand partly both how the ssh protocol + works and how the OTP SSH app handles the corresponding items

+ +

The first subsection will give a short background about the ssh protocol while later sections describes + the implementation and provides many examples

+ +
+ Basics of the ssh protocol's algorithms handling + +

SSH uses different sets of algorithms in different phases of a session. Which + algorithms to use is negotiated by the client and the server at the beginning of a session. + See RFC 4253, + "The Secure Shell (SSH) Transport Layer Protocol" for details. +

+ +

The negotiation is simple: both peers sends their list of supported alghorithms to the other part. + The first algorithm on the client's list that also in on the server's list is selected. So it is the + client's orderering of the list that gives the priority for the algorithms.

+ +

There are five lists exchanged in the connection setup. Three of them are also divided in two + directions, to and from the server.

+ +

The lists are (named as in the SSH application's options):

+ + kex + +

Key exchange.

+

An algorithm is selected for computing a secret encryption key. Among examples are: + the old nowadays week 'diffie-hellman-group-exchange-sha1' and the very strong and modern + 'ecdh-sha2-nistp512'.

+
+ + public_key + +

Server host key

+

The asymetric encryption algorithm used in the server's private-public host key pair. + Examples include the well-known RSA 'ssh-rsa' and elliptic curve 'ecdsa-sha2-nistp521'. +

+
+ + cipher + +

Symetric cipher algorithm used for the message encryption. This algorithm will use the key calculated + in the kex phase (together with other info) to genereate the actual key used. Examples are + tripple-DES '3des-cbc' and one of many AES variants 'aes192-ctr'. +

+

This list is actually two - one for each direction server-to-client and client-to-server. Therefore it + is possible but rare to have different algorithms in the two directions in one connection.

+
+ + mac + +

Message authentication code

+

"Check sum" of each message sent between the peers. Examples are SHA 'hmac-sha1' and + SHA2 'hmac-sha2-512'.

+

This list is also divided into two for the both directions

+
+ + compression + +

If and how to compress the message. Examples are none, that is, no compression and + zlib.

+

This list is also divided into two for the both directions

+
+ +
+
+ +
+ The SSH app's mechanism +

The set of algorithms that the SSH app uses by default depends on the algoritms supported by the:

+ +

crypto app,

+
+

The cryptolib OTP is linked with, usally the one the OS uses, probably OpenSSL,

+
+

and finaly what the SSH app implements

+
+
+

Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.

+

There is an important commands to list the actual algorithms and their ordering: + ssh:default_algorithms/0.

+ +0> ssh:default_algorithms(). +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521', + 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256', + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes256-gcm@openssh.com', + 'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com', + 'aes128-ctr','aes128-cbc','3des-cbc']}, + {server2client,['aes256-gcm@openssh.com','aes256-ctr', + 'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr', + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}] + + +

To change this listing, there are two options which can be used in + ssh:default_algorithms/2,3,4 + and + ssh:daemon/2,3. The options could of course + be used in all other functions that initiates connections.

+ +

The options are preferred_algorithms and modify_algorithms. The first one + replaces the default set, while the latter modifies the default set.

+
+
+ +
+ Replacing the default set: preferred_algorithms +

See the Reference Manual for details

+ +

Here follows a series of examples ranging from simple to more complex.

+ +

The experimental function ssh:chk_algos_opts(Opts) mangles the options preferred_algorithms + and modify_algorithms as ssh:dameon, ssh:connect and others does.

+ +
+ Example 1 +

Replace the kex algorithms list with the single algorithm 'diffie-hellman-group14-sha256':

+ +1> ssh:chk_algos_opts( + [{preferred_algorithms, + [{kex, ['diffie-hellman-group14-sha256']} + ] + } + ]). +[{kex,['diffie-hellman-group14-sha256']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256', + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes256-gcm@openssh.com', + 'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com', + 'aes128-ctr','aes128-cbc','3des-cbc']}, + {server2client,['aes256-gcm@openssh.com','aes256-ctr', + 'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr', + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}] + +

Note that the unmentioned lists (public_key, cipher, mac and compression) + are un-changed.

+
+ +
+ Example 2 +

In the lists that are divided in two for the two directions (c.f cipher) it is possible + to change both directions at once:

+ +2> ssh:chk_algos_opts( + [{preferred_algorithms, + [{cipher,['aes128-ctr']} + ] + } + ]). +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521', + 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256', + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes128-ctr']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}] + +

Note that both lists in cipher has been changed to the provided value ('aes128-ctr').

+
+ +
+ Example 3 +

In the lists that are divided in two for the two directions (c.f cipher) it is possible + to change only one of the directions:

+ +3> ssh:chk_algos_opts( + [{preferred_algorithms, + [{cipher,[{client2server,['aes128-ctr']}]} + ] + } + ]). +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521', + 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256', + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes256-gcm@openssh.com','aes256-ctr', + 'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr', + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}] + +
+ +
+ Example 4 +

It is of course possible to change more than one list:

+ +4> ssh:chk_algos_opts( + [{preferred_algorithms, + [{cipher,['aes128-ctr']}, + {mac,['hmac-sha2-256']}, + {kex,['ecdh-sha2-nistp384']}, + {public_key,['ssh-rsa']}, + {compression,[{server2client,[none]}, + {client2server,[zlib]}]} + ] + } + ]). +[{kex,['ecdh-sha2-nistp384']}, + {public_key,['ssh-rsa']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes128-ctr']}]}, + {mac,[{client2server,['hmac-sha2-256']}, + {server2client,['hmac-sha2-256']}]}, + {compression,[{client2server,[zlib]}, + {server2client,[none]}]}] + + +

Note that the ordering of the tuples in the lists didn't matter.

+
+
+ +
+ Modifying the default set: modify_algorithms +

The option preferred_algorithms is complicated to use for adding or removing single algorithms. One has + to first list them with ssh:default_algorithms() and then do substitutions in the lists. A situation + when it might be useful to add an algorithm is when one need to use a supported but disabled one. An example + is the kex 'diffie-hellman-group1-sha1' which nowadays is very unsecure and therefore disabled. It is + however still supported and might be used.

+ +

To facilitate addition or removal of algorithms the option modify_algorithms is available. + See the Reference Manual for details.

+ +

The option takes a list with instructions to append, prepend or remove algorithms:

+ +{modify_algorithms, [{append, ...}, + {prepend, ...}, + {rm, ...} + ]} + +

Each of the ... can be a algs_list() as the argument to the preferred_algorithms option.

+
+ Example 5 +

As an example let's add the Diffie-Hellman Group1 first in the kex list. It is supported according to + Supported algoritms.

+ +5> ssh:chk_algos_opts( + [{modify_algorithms, + [{prepend, + [{kex,['diffie-hellman-group1-sha1']}] + } + ] + } + ]). +[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384', + 'ecdh-sha2-nistp521','ecdh-sha2-nistp256', + 'diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256', + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes256-gcm@openssh.com', + 'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com', + 'aes128-ctr','aes128-cbc','3des-cbc']}, + {server2client,['aes256-gcm@openssh.com','aes256-ctr', + 'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr', + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}] + + +

And the result shows that the Diffie-Hellman Group1 is added at the head of the kex list

+
+ +
+ Example 6 +

In next example, we also move the 'ecdh-sha2-nistp521' to the end in the kex + list, that is, append.

+ +6> ssh:chk_algos_opts( + [{modify_algorithms, + [{prepend, + [{kex, ['diffie-hellman-group1-sha1']} + ]}, + {append, + [{kex, ['ecdh-sha2-nistp521']} + ]} + ] + } + ]). +[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384', + 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + ..... +] + +

Note that the appended algorithm is removed from its original place and then appended.

+
+ +
+ Example 7 +

In next example, we also move the 'ecdh-sha2-nistp521' to the end in the kex + list, that is, append.

+ +7> ssh:chk_algos_opts( + [{modify_algorithms, + [{prepend, + [{kex, ['diffie-hellman-group1-sha1']} + ]}, + {append, + [{kex, ['ecdh-sha2-nistp521']} + ]} + ] + } + ]). +[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384', + 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group18-sha512', + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group14-sha1', + 'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']}, + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', + ..... +] + +

Note that the appended algorithm first is removed from its original place and then appended.

+
+ + +
+ Example 8 +

In this example, we use both options (preferred_algorithms and modify_algorithms) and + also try to prepend an unsupported algorithm. Any unsupported algorithm is quietly removed.

+ +8> ssh:chk_algos_opts( + [{preferred_algorithms, + [{cipher,['aes128-ctr']}, + {mac,['hmac-sha2-256']}, + {kex,['ecdh-sha2-nistp384']}, + {public_key,['ssh-rsa']}, + {compression,[{server2client,[none]}, + {client2server,[zlib]}]} + ] + }, + {modify_algorithms, + [{prepend, + [{kex, ['some unsupported algorithm']} + ]}, + {append, + [{kex, ['diffie-hellman-group1-sha1']} + ]} + ] + } + ]). +[{kex,['ecdh-sha2-nistp384','diffie-hellman-group1-sha1']}, + {public_key,['ssh-rsa']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes128-ctr']}]}, + {mac,[{client2server,['hmac-sha2-256']}, + {server2client,['hmac-sha2-256']}]}, + {compression,[{client2server,[zlib]}, + {server2client,[none]}]}] + + +

It is of course questionable why anyone would like to use the both options together, but it is possible + if the needed.

+
+ + + +
+ +
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index ea7e975ef5..48553bf503 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -108,6 +108,9 @@ double_algs() =

[{client2serverlist,simple_algs()},{server2client,simple_algs()}] | simple_algs()

+ + modify_algs_list() = +

list( {append,algs_list()} | {prepend,algs_list()} | {rm,algs_list()} )

@@ -254,7 +257,8 @@

- + +

List of algorithms to use in the algorithm negotiation. The default algs_list() can be obtained from default_algorithms/0. @@ -275,6 +279,8 @@ for cipher but specifies the same algorithms for mac and compression in both directions. The kex (key exchange) is implicit but public_key is set explicitly.

+

For background and more examples see the User's Guide.

+

Changing the values can make a connection less secure. Do not change unless you know exactly what you are doing. If you do not understand the values then you @@ -282,6 +288,41 @@ + + + +

Modifies the list of algorithms to use in the algorithm negotiation. The modifications are + applied after the option preferred_algorithms is applied (if existing)

+

The possible modifications are to:

+ +

Append or prepend supported but not enabled algorithm(s) to the list of + algorithms.

If the wanted algorithms already are in the list of algorithms, they will first + be removed and then appended or prepended. +

+
+

Remove (rm) one or more algorithms from the list of algorithms.

+
+

If an unsupported algorithm is in the list, it will be silently ignored

+ +

Here is an example of this option:

+ +{modify_algorithms, + [{prepend, [{kex, ['diffie-hellman-group1-sha1']}], + {rm, [{compression, [none]}]} + ] +} + +

The example specifies that:

+ +

the old key exchange algorithm 'diffie-hellman-group1-sha1' should be + the main alternative. It will be the main alternative since it is prepened to the list

+
+

The compression algorithm none (= no compression) is removed so compression is enforced

+
+
+

For background and more examples see the User's Guide.

+
+

Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group. @@ -555,6 +596,8 @@ for cipher but specifies the same algorithms for mac and compression in both directions. The kex (key exchange) is implicit but public_key is set explicitly.

+

For background and more examples see the User's Guide.

+

Changing the values can make a connection less secure. Do not change unless you know exactly what you are doing. If you do not understand the values then you @@ -562,6 +605,41 @@ + + + +

Modifies the list of algorithms to use in the algorithm negotiation. The modifications are + applied after the option preferred_algorithms is applied (if existing)

+

The possible modifications are to:

+ +

Append or prepend supported but not enabled algorithm(s) to the list of + algorithms.

If the wanted algorithms already are in the list of algorithms, they will first + be removed and then appended or prepended. +

+
+

Remove (rm) one or more algorithms from the list of algorithms.

+
+

If an unsupported algorithm is in the list, it will be silently ignored

+ +

Here is an example of this option:

+ +{modify_algorithms, + [{prepend, [{kex, ['diffie-hellman-group1-sha1']}], + {rm, [{compression, [none]}]} + ] +} + +

The example specifies that:

+ +

the old key exchange algorithm 'diffie-hellman-group1-sha1' should be + the main alternative. It will be the main alternative since it is prepened to the list

+
+

The compression algorithm none (= no compression) is removed so compression is enforced

+
+
+

For background and more examples see the User's Guide.

+
+

Defines the groups the server may choose among when diffie-hellman-group-exchange is negotiated. diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 33ec7aaee0..1cbbdfcf38 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -97,7 +97,7 @@

The known_hosts file contains a list of approved servers and their public keys. Once a server is listed, it can be verified without user interaction. -

+

Authorized Keys @@ -135,7 +135,7 @@

Supported algorithms are:

- + Key exchange algorithms diff --git a/lib/ssh/doc/src/usersguide.xml b/lib/ssh/doc/src/usersguide.xml index 70051ba771..d902df6848 100644 --- a/lib/ssh/doc/src/usersguide.xml +++ b/lib/ssh/doc/src/usersguide.xml @@ -36,4 +36,5 @@ + -- cgit v1.2.3 From 8182596a52b95edb78542bf854aa7b8ff93cc245 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 5 Sep 2017 16:10:36 +0200 Subject: ssh: fix dialyzer error --- lib/ssh/src/ssh_options.erl | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl index d8931da774..6939094401 100644 --- a/lib/ssh/src/ssh_options.erl +++ b/lib/ssh/src/ssh_options.erl @@ -938,9 +938,6 @@ check_preferred_algorithms(Algs) when is_list(Algs) -> check_input_ok(Algs), {true, normalize_mod_algs(Algs, true)}; -check_preferred_algorithms(Algs) when is_list(Algs) -> - check_preferred_algorithms({false,Algs}); - check_preferred_algorithms(_) -> error_in_check(modify_algorithms, "Bad option value. List expected."). -- cgit v1.2.3 From 10dd3321f37175b0adb4c8a31371419d45bf94d0 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 8 Sep 2017 18:16:24 +0200 Subject: ssh: Doc modified after comments --- lib/ssh/doc/src/configure_algos.xml | 73 +++++++++++-------------------------- lib/ssh/doc/src/ssh.xml | 39 +++++++++++++++----- 2 files changed, 52 insertions(+), 60 deletions(-) diff --git a/lib/ssh/doc/src/configure_algos.xml b/lib/ssh/doc/src/configure_algos.xml index ebd128c097..dd60324851 100644 --- a/lib/ssh/doc/src/configure_algos.xml +++ b/lib/ssh/doc/src/configure_algos.xml @@ -35,11 +35,11 @@
Introduction -

To fully understand how to configure the algorithms, we must understand partly both how the ssh protocol - works and how the OTP SSH app handles the corresponding items

+

To fully understand how to configure the algorithms, it is essential to have a basic understanding of the SSH protocol + and how OTP SSH app handles the corresponding items

-

The first subsection will give a short background about the ssh protocol while later sections describes - the implementation and provides many examples

+

The first subsection will give a short background of the SSH protocol while later sections describes + the implementation and provides some examples

Basics of the ssh protocol's algorithms handling @@ -77,7 +77,7 @@ cipher -

Symetric cipher algorithm used for the message encryption. This algorithm will use the key calculated +

Symetric cipher algorithm used for the payload encryption. This algorithm will use the key calculated in the kex phase (together with other info) to genereate the actual key used. Examples are tripple-DES '3des-cbc' and one of many AES variants 'aes192-ctr'.

@@ -115,7 +115,7 @@

Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.

-

There is an important commands to list the actual algorithms and their ordering: +

There is an important command to list the actual algorithms and their ordering: ssh:default_algorithms/0.

0> ssh:default_algorithms(). @@ -143,8 +143,8 @@ {server2client,[none,'zlib@openssh.com',zlib]}]}] -

To change this listing, there are two options which can be used in - ssh:default_algorithms/2,3,4 +

To change the algorithm list, there are two options which can be used in + ssh:connect/2,3,4 and ssh:daemon/2,3. The options could of course be used in all other functions that initiates connections.

@@ -160,8 +160,9 @@

Here follows a series of examples ranging from simple to more complex.

-

The experimental function ssh:chk_algos_opts(Opts) mangles the options preferred_algorithms - and modify_algorithms as ssh:dameon, ssh:connect and others does.

+

To forsee the effect of an option there is an experimental function ssh:chk_algos_opts(Opts). + It mangles the options preferred_algorithms + and modify_algorithms in the same way as ssh:dameon, ssh:connect and their friends does.

Example 1 @@ -292,11 +293,12 @@
Modifying the default set: modify_algorithms -

The option preferred_algorithms is complicated to use for adding or removing single algorithms. One has - to first list them with ssh:default_algorithms() and then do substitutions in the lists. A situation - when it might be useful to add an algorithm is when one need to use a supported but disabled one. An example - is the kex 'diffie-hellman-group1-sha1' which nowadays is very unsecure and therefore disabled. It is +

A situation where it might be useful to add an algorithm is when one need to use a supported but disabled one. + An example is the 'diffie-hellman-group1-sha1' which nowadays is very unsecure and therefore disabled. It is however still supported and might be used.

+ +

The option preferred_algorithms may be complicated to use for adding or removing single algorithms. + First one has to list them with ssh:default_algorithms() and then do changes in the lists.

To facilitate addition or removal of algorithms the option modify_algorithms is available. See the Reference Manual for details.

@@ -352,8 +354,8 @@
Example 6 -

In next example, we also move the 'ecdh-sha2-nistp521' to the end in the kex - list, that is, append.

+

In this example, we in put the 'diffie-hellman-group1-sha1' first and also move the + 'ecdh-sha2-nistp521' to the end in the kex list, that is, append it.

6> ssh:chk_algos_opts( [{modify_algorithms, @@ -377,46 +379,15 @@ ..... ] -

Note that the appended algorithm is removed from its original place and then appended.

+

Note that the appended algorithm is removed from its original place and then appended to the same list.

Example 7 -

In next example, we also move the 'ecdh-sha2-nistp521' to the end in the kex - list, that is, append.

- -7> ssh:chk_algos_opts( - [{modify_algorithms, - [{prepend, - [{kex, ['diffie-hellman-group1-sha1']} - ]}, - {append, - [{kex, ['ecdh-sha2-nistp521']} - ]} - ] - } - ]). -[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384', - 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256', - 'diffie-hellman-group16-sha512', - 'diffie-hellman-group18-sha512', - 'diffie-hellman-group14-sha256', - 'diffie-hellman-group14-sha1', - 'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']}, - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521', - ..... -] - -

Note that the appended algorithm first is removed from its original place and then appended.

-
- - -
- Example 8

In this example, we use both options (preferred_algorithms and modify_algorithms) and also try to prepend an unsupported algorithm. Any unsupported algorithm is quietly removed.

-8> ssh:chk_algos_opts( +7> ssh:chk_algos_opts( [{preferred_algorithms, [{cipher,['aes128-ctr']}, {mac,['hmac-sha2-256']}, @@ -446,8 +417,8 @@ {server2client,[none]}]}] -

It is of course questionable why anyone would like to use the both options together, but it is possible - if the needed.

+

It is of course questionable why anyone would like to use the both these options together, + but it is possible if an unforeseen need should arise.

diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 48553bf503..d9516fff12 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -292,18 +292,39 @@

Modifies the list of algorithms to use in the algorithm negotiation. The modifications are - applied after the option preferred_algorithms is applied (if existing)

-

The possible modifications are to:

+ applied after the option preferred_algorithms (if existing) is applied.

+

The algoritm for modifications works like this:

-

Append or prepend supported but not enabled algorithm(s) to the list of - algorithms.

If the wanted algorithms already are in the list of algorithms, they will first - be removed and then appended or prepended. -

+ +

Input is the modify_algs_list() and a set of algorithms A + obtained from the preferred_algorithms option if existing, or else from the + ssh:default_algorithms/0. +

+
+ +

The head of the modify_algs_list() modifies A giving the result A'.

+

The possible modifications are:

+ + +

Append or prepend supported but not enabled algorithm(s) to the list of + algorithms. If the wanted algorithms already are in A they will first + be removed and then appended or prepended, +

+
+ +

Remove (rm) one or more algorithms from A. +

+
+
+
+ +

Repeat the modification step with the tail of modify_algs_list() and the resulting + A'. +

-

Remove (rm) one or more algorithms from the list of algorithms.

-

If an unsupported algorithm is in the list, it will be silently ignored

- +

If an unsupported algorithm is in the modify_algs_list(), it will be silently ignored

+

If there are more than one modify_algorithms options, the result is undefined.

Here is an example of this option:

{modify_algorithms, -- cgit v1.2.3