aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/src/ssh_auth.erl
diff options
context:
space:
mode:
authorHenrik Nord <[email protected]>2015-06-02 09:00:04 +0200
committerHenrik Nord <[email protected]>2015-06-02 09:00:04 +0200
commit21b8941d83516e381000387c47758bc7f040ae8b (patch)
tree2499b8b04c15a5ba2777a54921af7e4f9916676d /lib/ssh/src/ssh_auth.erl
parentf3fefbae24a2569a13b538d80d0e99129963ebef (diff)
parentc1df511623b9a2a98d4d3862ae612c1ca9837da7 (diff)
downloadotp-21b8941d83516e381000387c47758bc7f040ae8b.tar.gz
otp-21b8941d83516e381000387c47758bc7f040ae8b.tar.bz2
otp-21b8941d83516e381000387c47758bc7f040ae8b.zip
Merge tag 'OTP-17.5.6' into maint
=== OTP-17.5.6 === Changed Applications: - inets-5.10.9 - ssh-3.2.4 - ssl-6.0.1 Unchanged Applications: - asn1-3.0.4 - common_test-1.10.1 - compiler-5.0.4 - cosEvent-2.1.15 - cosEventDomain-1.1.14 - cosFileTransfer-1.1.16 - cosNotification-1.1.21 - cosProperty-1.1.17 - cosTime-1.1.14 - cosTransactions-1.2.14 - crypto-3.5 - debugger-4.0.3 - dialyzer-2.7.4 - diameter-1.9.2 - edoc-0.7.16 - eldap-1.1.1 - erl_docgen-0.3.7 - erl_interface-3.7.20 - erts-6.4.1 - et-1.5 - eunit-2.2.9 - gs-1.5.16 - hipe-3.11.3 - ic-4.3.6 - jinterface-1.5.12 - kernel-3.2 - megaco-3.17.3 - mnesia-4.12.5 - observer-2.0.4 - odbc-2.10.22 - orber-3.7.1 - os_mon-2.3.1 - ose-1.0.2 - otp_mibs-1.0.10 - parsetools-2.0.12 - percept-0.8.10 - public_key-0.23 - reltool-0.6.6 - runtime_tools-1.8.16 - sasl-2.4.1 - snmp-5.1.2 - stdlib-2.4 - syntax_tools-1.6.18 - test_server-3.8.1 - tools-2.7.2 - typer-0.9.8 - webtool-0.8.10 - wx-1.3.3 - xmerl-1.3.7
Diffstat (limited to 'lib/ssh/src/ssh_auth.erl')
-rw-r--r--lib/ssh/src/ssh_auth.erl80
1 files changed, 80 insertions, 0 deletions
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 45c4d52d7e..9d1ab14ce9 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -259,6 +259,54 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
+ method = "keyboard-interactive",
+ data = _},
+ _, #ssh{opts = Opts} = Ssh) ->
+ %% RFC4256
+ %% The data field contains:
+ %% - language tag (deprecated). If =/=[] SHOULD use it however. We skip
+ %% it for simplicity.
+ %% - submethods. "... the user can give a hint of which actual methods
+ %% he wants to use. ...". It's a "MAY use" so we skip
+ %% it. It also needs an understanding between the client
+ %% and the server.
+ %%
+ %% "The server MUST reply with an SSH_MSG_USERAUTH_SUCCESS,
+ %% SSH_MSG_USERAUTH_FAILURE, or SSH_MSG_USERAUTH_INFO_REQUEST message."
+ Default = {"SSH server",
+ "Enter password for \""++User++"\"",
+ "pwd: ",
+ false},
+
+ {Name, Instruction, Prompt, Echo} =
+ case proplists:get_value(auth_method_kb_interactive_data, Opts) of
+ undefined ->
+ Default;
+ {_,_,_,_}=V ->
+ V;
+ F when is_function(F) ->
+ {_,PeerName} = Ssh#ssh.peer,
+ F(PeerName, User, "ssh-connection")
+ end,
+ EchoEnc = case Echo of
+ true -> <<?TRUE>>;
+ false -> <<?FALSE>>
+ end,
+ Msg = #ssh_msg_userauth_info_request{name = unicode:characters_to_list(Name),
+ instruction = unicode:characters_to_list(Instruction),
+ language_tag = "",
+ num_prompts = 1,
+ data = <<?STRING(unicode:characters_to_binary(Prompt)),
+ EchoEnc/binary
+ >>
+ },
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
+ opts = [{max_kb_tries,3},{kb_userauth_info_msg,Msg}|Opts]
+ })};
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
method = Other}, _,
#ssh{userauth_supported_methods = Methods} = Ssh) ->
{not_authorized, {User, {authmethod, Other}},
@@ -280,6 +328,38 @@ handle_userauth_info_request(
#ssh_msg_userauth_info_response{num_responses = NumPrompts,
data = Responses}, Ssh)}.
+handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1,
+ data = <<?UINT32(Sz), Password:Sz/binary>>},
+ #ssh{opts = Opts0,
+ user = User} = Ssh) ->
+ NumTriesLeft = proplists:get_value(max_kb_tries, Opts0, 0) - 1,
+ Opts = lists:keydelete(max_kb_tries,1,Opts0),
+ case check_password(User, unicode:characters_to_list(Password), Opts) of
+ true ->
+ {authorized, User,
+ ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)};
+ false when NumTriesLeft > 0 ->
+ UserAuthInfoMsg =
+ (proplists:get_value(kb_userauth_info_msg,Opts))
+ #ssh_msg_userauth_info_request{name = "",
+ instruction =
+ lists:concat(
+ ["Bad user or password, try again. ",
+ integer_to_list(NumTriesLeft),
+ " tries left."])},
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(UserAuthInfoMsg,
+ Ssh#ssh{opts = [{max_kb_tries,NumTriesLeft}|Opts]})};
+
+ false ->
+ {not_authorized, {User, {error,"Bad user or password"}},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications = "",
+ partial_success = false},
+ Ssh#ssh{opts = lists:keydelete(kb_userauth_info_msg,1,Opts)}
+ )}
+ end;
+
handle_userauth_info_response(#ssh_msg_userauth_info_response{},
_Auth) ->
throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,