From 8119b8c021c217b325d841b7ea0d8f156f389ce4 Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Thu, 2 Jun 2022 18:52:13 +0200
Subject: ssh: Option to skip initial authentication
---
lib/ssh/src/ssh_auth.erl | 20 +++++++++++++++-----
lib/ssh/src/ssh_fsm_userauth_server.erl | 13 +++++++++----
lib/ssh/src/ssh_options.erl | 6 ++++++
3 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index abf9e0d18a..efd1bbbabd 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -272,11 +272,21 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
method = "none"}, _,
- #ssh{userauth_supported_methods = Methods} = Ssh) ->
- {not_authorized, {User, undefined},
- {#ssh_msg_userauth_failure{authentications = Methods,
- partial_success = false}, Ssh}
- };
+ #ssh{userauth_supported_methods = Methods,
+ opts = Opts} = Ssh) ->
+ case ?GET_OPT(no_auth_needed, Opts) of
+ false ->
+ %% The normal case
+ {not_authorized, {User, undefined},
+ {#ssh_msg_userauth_failure{authentications = Methods,
+ partial_success = false}, Ssh}
+ };
+ true ->
+ %% RFC 4252 5.2
+ {authorized, User,
+ {#ssh_msg_userauth_success{}, Ssh}
+ }
+ end;
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
diff --git a/lib/ssh/src/ssh_fsm_userauth_server.erl b/lib/ssh/src/ssh_fsm_userauth_server.erl
index 77657b4d82..0d12cb43ec 100644
--- a/lib/ssh/src/ssh_fsm_userauth_server.erl
+++ b/lib/ssh/src/ssh_fsm_userauth_server.erl
@@ -64,10 +64,15 @@ handle_event(internal,
case {ServiceName, Ssh0#ssh.service, Method} of
{"ssh-connection", "ssh-connection", "none"} ->
%% Probably the very first userauth_request but we deny unauthorized login
- {not_authorized, _, {Reply,Ssh}} =
- ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0),
- D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
- {keep_state, D};
+ %% However, we *may* accept unauthorized login if instructed so
+ case ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0) of
+ {not_authorized, _, {Reply,Ssh}} ->
+ D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
+ {keep_state, D};
+ {authorized, User, {Reply, Ssh1}} ->
+ D = connected_state(Reply, Ssh1, User, Method, D0),
+ {next_state, {connected,server}, D, {change_callback_module,ssh_connection_handler}}
+ end;
{"ssh-connection", "ssh-connection", Method} ->
%% Userauth request with a method like "password" or so
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index 2ea1f8c8bb..817bf2e4e2 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -477,6 +477,12 @@ default(server) ->
class => user_option
},
+ no_auth_needed =>
+ #{default => false,
+ chk => fun(V) -> erlang:is_boolean(V) end,
+ class => user_option
+ },
+
pk_check_user =>
#{default => false,
chk => fun(V) -> erlang:is_boolean(V) end,
--
cgit v1.2.1
From 981139b30941442b95e309e75ee1ec3f9bf6276a Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Fri, 3 Jun 2022 13:53:53 +0200
Subject: ssh: Typing and doc
---
lib/ssh/doc/src/ssh.xml | 13 +++++++++++++
lib/ssh/src/ssh.hrl | 4 +++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index f5952aeae9..61cd02b365 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -648,6 +648,19 @@
This variant is kept for compatibility.
+
+ no_auth_needed
+ -
+
If true, a client is authenticated without any need of
+ providing any password or key.
+
+ This option is only intended for very special applications due
+ to the high risk of accepting any connecting client.
+
+ The default value is false.
+
+
+
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index e662122807..a8a5075a53 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -362,7 +362,9 @@
| {user_passwords, [{UserName::string(),Pwd::string()}]}
| {pk_check_user, boolean()}
| {password, string()}
- | {pwdfun, pwdfun_2() | pwdfun_4()} .
+ | {pwdfun, pwdfun_2() | pwdfun_4()}
+ | {no_auth_needed, boolean()}
+ .
-type prompt_texts() ::
kb_int_tuple()
--
cgit v1.2.1
From 787b5ee2fa5694db81c19314b75f0343395d96dd Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Tue, 7 Jun 2022 10:22:24 +0200
Subject: ssh: Testcase for option 'no_auth_needed'
---
lib/ssh/test/ssh_options_SUITE.erl | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index 425ed19265..d0066b823a 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -34,6 +34,7 @@
auth_method_kb_interactive_data_tuple/1,
auth_method_kb_interactive_data_fun3/1,
auth_method_kb_interactive_data_fun4/1,
+ auth_none/1,
connectfun_disconnectfun_client/1,
disconnectfun_option_client/1,
disconnectfun_option_server/1,
@@ -115,6 +116,7 @@ all() ->
auth_method_kb_interactive_data_tuple,
auth_method_kb_interactive_data_fun3,
auth_method_kb_interactive_data_fun4,
+ auth_none,
{group, dir_options},
ssh_connect_timeout,
ssh_connect_arg4_timeout,
@@ -575,6 +577,30 @@ amkid(Config, {ExpectName,ExpectInstr,ExpectPrompts,ExpectEcho}, OptVal) ->
{"Bad again",1},
{"bar",2}]).
+%%--------------------------------------------------------------------
+auth_none(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = proplists:get_value(data_dir, Config),
+ {DaemonRef, Host, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {auth_methods, "password"}, % to make even more sure we don't use public-key-auth
+ {user_passwords, [{"foo","somepwd"}]}, % Not to be used
+ {no_auth_needed, true} % we test this
+ ]),
+ ClientConnRef1 =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "some-other-user"},
+ {password, "wrong-pwd"},
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ "some-other-user" =
+ proplists:get_value(user, ssh:connection_info(ClientConnRef1, [user])),
+ ok = ssh:close(ClientConnRef1),
+ ok = ssh:stop_daemon(DaemonRef).
+
%%--------------------------------------------------------------------
system_dir_option(Config) ->
DirUnread = proplists:get_value(unreadable_dir,Config),
--
cgit v1.2.1