diff options
author | Hans Nilsson <hans@erlang.org> | 2022-08-01 15:44:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-01 15:44:59 +0200 |
commit | d9ad79c0c37310670ca07259c8127bd670ebb485 (patch) | |
tree | f20dac9d2e035d9e74ad762380186294d31122b1 | |
parent | ee9db140a9fae78912278275360f562d257cb2cd (diff) | |
parent | 787b5ee2fa5694db81c19314b75f0343395d96dd (diff) | |
download | erlang-d9ad79c0c37310670ca07259c8127bd670ebb485.tar.gz |
Merge pull request #6066 from HansN/hans/ssh/authentication-none/GH-6021/OTP-18134
Option to skip SSH authentication for some niche cases
-rw-r--r-- | lib/ssh/doc/src/ssh.xml | 13 | ||||
-rw-r--r-- | lib/ssh/src/ssh.hrl | 4 | ||||
-rw-r--r-- | lib/ssh/src/ssh_auth.erl | 20 | ||||
-rw-r--r-- | lib/ssh/src/ssh_fsm_userauth_server.erl | 13 | ||||
-rw-r--r-- | lib/ssh/src/ssh_options.erl | 6 | ||||
-rw-r--r-- | lib/ssh/test/ssh_options_SUITE.erl | 26 |
6 files changed, 72 insertions, 10 deletions
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index c549fc38fa..94f3815943 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -648,6 +648,19 @@ </p> <p>This variant is kept for compatibility.</p> </item> + + <tag><marker id="option-no_auth_needed"/><c>no_auth_needed</c></tag> + <item> + <p>If <c>true</c>, a client is authenticated without any need of + providing any password or key. + </p> + <p>This option is only intended for very special applications due + to the high risk of accepting any connecting client. + </p> + <p>The default value is <c>false</c>. + </p> + </item> + </taglist> </desc> </datatype> diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 206c5feb9b..796a35bbb8 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() 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 69ede2c10b..4351782247 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, diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index c5269eb2be..02294af37c 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, @@ -576,6 +578,30 @@ amkid(Config, {ExpectName,ExpectInstr,ExpectPrompts,ExpectEcho}, OptVal) -> {"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), FileRead = proplists:get_value(readable_file,Config), |