diff options
author | Hans Nilsson <[email protected]> | 2015-10-29 19:51:04 +0100 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2015-11-04 12:09:56 +0100 |
commit | c505918a86fb9ac8c19e47cd751a9db4e2d9efb2 (patch) | |
tree | d0f0c0c284b906a3c55d5951f301b8287da3fc93 /lib/ssh/src | |
parent | 4f085471fc4e1886bd7549cf135e7038a87e6a8e (diff) | |
download | otp-c505918a86fb9ac8c19e47cd751a9db4e2d9efb2.tar.gz otp-c505918a86fb9ac8c19e47cd751a9db4e2d9efb2.tar.bz2 otp-c505918a86fb9ac8c19e47cd751a9db4e2d9efb2.zip |
ssh: pwdfun/4 and simple tests
Also solves OTP-13053
Diffstat (limited to 'lib/ssh/src')
-rw-r--r-- | lib/ssh/src/ssh.erl | 4 | ||||
-rw-r--r-- | lib/ssh/src/ssh.hrl | 1 | ||||
-rw-r--r-- | lib/ssh/src/ssh_auth.erl | 49 |
3 files changed, 39 insertions, 15 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 049018b21c..6f79b48091 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -462,7 +462,9 @@ handle_ssh_option({password, Value} = Opt) when is_list(Value) -> Opt; handle_ssh_option({user_passwords, Value} = Opt) when is_list(Value)-> Opt; -handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value) -> +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,2) -> + Opt; +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) -> Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index fc9d60c500..4ad936f742 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -138,6 +138,7 @@ kb_tries_left = 0, % integer(), num tries left for "keyboard-interactive" userauth_preference, available_host_keys, + pwdfun_user_state, authenticated = false }). diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 04749fcf8e..4272eb3c52 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -174,15 +174,15 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, #ssh{opts = Opts, userauth_supported_methods = Methods} = Ssh) -> Password = unicode:characters_to_list(BinPwd), - case check_password(User, Password, Opts) of - true -> + case check_password(User, Password, Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, - partial_success = false}, Ssh)} + partial_success = false}, Ssh1)} end; handle_userauth_request(#ssh_msg_userauth_request{user = User, @@ -335,16 +335,16 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, kb_tries_left = KbTriesLeft, user = User, userauth_supported_methods = Methods} = Ssh) -> - case check_password(User, unicode:characters_to_list(Password), Opts) of - true -> + case check_password(User, unicode:characters_to_list(Password), Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, - Ssh#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} + Ssh1#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} )} end; @@ -387,13 +387,34 @@ user_name(Opts) -> {ok, User} end. -check_password(User, Password, Opts) -> +check_password(User, Password, Opts, Ssh) -> case proplists:get_value(pwdfun, Opts) of undefined -> Static = get_password_option(Opts, User), - Password == Static; - Cheker -> - Cheker(User, Password) + {Password == Static, Ssh}; + + Checker when is_function(Checker,2) -> + {Checker(User, Password), Ssh}; + + Checker when is_function(Checker,4) -> + #ssh{pwdfun_user_state = PrivateState, + peer = {_,PeerAddr={_,_}} + } = Ssh, + case Checker(User, Password, PeerAddr, PrivateState) of + true -> + {true,Ssh}; + false -> + {false,Ssh}; + {true,NewState} -> + {true, Ssh#ssh{pwdfun_user_state=NewState}}; + {false,NewState} -> + {false, Ssh#ssh{pwdfun_user_state=NewState}}; + disconnect -> + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, + description = + "Unable to connect using the available authentication methods", + language = ""}) + end end. get_password_option(Opts, User) -> |