diff options
| author | Fredrik Gustafsson <[email protected]> | 2012-11-15 14:32:52 +0100 | 
|---|---|---|
| committer | Fredrik Gustafsson <[email protected]> | 2012-11-15 14:32:52 +0100 | 
| commit | e9d46adb58b940a92874b2c4bcc833dfcf7375a3 (patch) | |
| tree | 181317a1a03d54bc335593e9627e5b7d67e0f228 | |
| parent | 55c2b0b6d55fe6a011671832b5529cb1c7b636a8 (diff) | |
| download | otp-e9d46adb58b940a92874b2c4bcc833dfcf7375a3.tar.gz otp-e9d46adb58b940a92874b2c4bcc833dfcf7375a3.tar.bz2 otp-e9d46adb58b940a92874b2c4bcc833dfcf7375a3.zip | |
Fixed user interaction ssh
| -rw-r--r-- | lib/ssh/src/ssh.erl | 51 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_auth.erl | 18 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_io.erl | 56 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_transport.erl | 2 | 
4 files changed, 73 insertions, 54 deletions
| diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index d09f6cf34b..7d68b1d7bd 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -79,7 +79,7 @@ connect(Host, Port, Options, Timeout) ->  	    DisableIpv6 =  proplists:get_value(ip_v6_disabled, SshOptions, false),  	    Inet = inetopt(DisableIpv6),  	    do_connect(Host, Port, [Inet | SocketOptions],  -		       [{host, Host} | SshOptions], Timeout, DisableIpv6) +		       [{user_pid, self()}, {host, Host} | SshOptions], Timeout, DisableIpv6)      end.  do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) -> @@ -91,30 +91,39 @@ do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) ->   	{ok, ConnectionSup} ->  	    {ok, Manager} =   		ssh_connection_sup:connection_manager(ConnectionSup), -	    receive  -		{Manager, is_connected} -> -		    {ok, Manager}; -		%% When the connection fails  -		%% ssh_connection_sup:connection_manager -		%% might return undefined as the connection manager -		%% could allready have terminated, so we will not -		%% match the Manager in this case -		{_, not_connected, {error, econnrefused}} when DisableIpv6 == false -> -		    do_connect(Host, Port, proplists:delete(inet6, SocketOptions),  -			    SshOptions, Timeout, true); -		{_, not_connected, {error, Reason}} -> -		    {error, Reason}; -		{_, not_connected, Other} -> -		    {error, Other} -	    after Timeout  -> -		    ssh_connection_manager:stop(Manager), -		    {error, timeout} -	    end +	    msg_loop(Manager, DisableIpv6, Host, Port, SocketOptions, SshOptions, Timeout)      catch   	exit:{noproc, _} ->   	    {error, ssh_not_started}      end. - +msg_loop(Manager, DisableIpv6, Host, Port, SocketOptions, SshOptions, Timeout) -> +    receive  +	{Manager, is_connected} -> +	    {ok, Manager}; +	%% When the connection fails  +	%% ssh_connection_sup:connection_manager +	%% might return undefined as the connection manager +	%% could allready have terminated, so we will not +	%% match the Manager in this case +	{_, not_connected, {error, econnrefused}} when DisableIpv6 == false -> +	    do_connect(Host, Port, proplists:delete(inet6, SocketOptions),  +		       SshOptions, Timeout, true); +	{_, not_connected, {error, Reason}} -> +	    {error, Reason}; +	{_, not_connected, Other} -> +	    {error, Other}; +	{From, user_password} -> +	    Pass = io:get_password(), +	    From ! Pass, +	    msg_loop(Manager, DisableIpv6, Host, Port, SocketOptions, SshOptions, Timeout); +	{From, question} -> +	    Answer = io:get_line(""), +	    From ! Answer, +	    msg_loop(Manager, DisableIpv6, Host, Port, SocketOptions, SshOptions, Timeout) +    after Timeout  -> +	    ssh_connection_manager:stop(Manager), +	    {error, timeout} +    end.  %%--------------------------------------------------------------------  %% Function: close(ConnectionRef) -> ok  %% diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 27e44df554..c436793dc4 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -71,7 +71,7 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,      ssh_bits:install_messages(userauth_passwd_messages()),      Password = case proplists:get_value(password, Opts) of  		   undefined ->  -		       user_interaction(IoCb); +		       user_interaction(IoCb, Ssh);  		   PW ->   		       PW  	       end, @@ -89,10 +89,10 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,  	      Ssh)      end. -user_interaction(ssh_no_io) -> +user_interaction(ssh_no_io, _) ->      not_ok; -user_interaction(IoCb) -> -    IoCb:read_password("ssh password: "). +user_interaction(IoCb, Ssh) -> +    IoCb:read_password("ssh password: ", Ssh).  %% See RFC 4256 for info on keyboard-interactive @@ -401,11 +401,11 @@ keyboard_interact_get_responses(IoCb, Opts, Name, Instr, PromptInfos) ->  	    %% Special case/fallback for just one prompt  	    %% (assumed to be the password prompt)  	    case proplists:get_value(password, Opts) of -		undefined -> keyboard_interact(IoCb, Name, Instr, PromptInfos); +		undefined -> keyboard_interact(IoCb, Name, Instr, PromptInfos, Opts);  		PW        -> [PW]  	    end;  	undefined -> -	    keyboard_interact(IoCb, Name, Instr, PromptInfos); +	    keyboard_interact(IoCb, Name, Instr, PromptInfos, Opts);  	KbdInteractFun ->  	    Prompts = lists:map(fun({Prompt, _Echo}) -> Prompt end,  				PromptInfos), @@ -419,15 +419,15 @@ keyboard_interact_get_responses(IoCb, Opts, Name, Instr, PromptInfos) ->  	    end      end. -keyboard_interact(IoCb, Name, Instr, Prompts) -> +keyboard_interact(IoCb, Name, Instr, Prompts, Opts) ->      if Name /= "" -> IoCb:format("~s", [Name]);         true       -> ok      end,      if Instr /= "" -> IoCb:format("~s", [Instr]);         true        -> ok      end, -    lists:map(fun({Prompt, true})  -> IoCb:read_line(Prompt); -		 ({Prompt, false}) -> IoCb:read_password(Prompt) +    lists:map(fun({Prompt, true})  -> IoCb:read_line(Prompt, Opts); +		 ({Prompt, false}) -> IoCb:read_password(Prompt, Opts)  	      end,  	      Prompts). diff --git a/lib/ssh/src/ssh_io.erl b/lib/ssh/src/ssh_io.erl index 1dbd097423..fc7a572f7c 100644 --- a/lib/ssh/src/ssh_io.erl +++ b/lib/ssh/src/ssh_io.erl @@ -23,37 +23,47 @@  -module(ssh_io). --export([yes_no/1, read_password/1, read_line/1, format/2]). +-export([yes_no/2, read_password/2, read_line/2, format/2]).  -import(lists, [reverse/1]). +-include("ssh.hrl"). +read_line(Prompt, Ssh) -> +    format("~s", [listify(Prompt)]), +    proplists:get_value(user_pid, Ssh) ! {self(), question}, +    receive +	Answer -> +	    Answer +    end. -read_line(Prompt) when is_list(Prompt) -> -    io:get_line(list_to_atom(Prompt)); -read_line(Prompt) when is_atom(Prompt) -> -    io:get_line(Prompt). - -read_ln(Prompt) -> -    trim(read_line(Prompt)). - -yes_no(Prompt) -> +yes_no(Prompt, Ssh) ->      io:format("~s [y/n]?", [Prompt]), -    case read_ln('') of -	"y" -> yes; -	"n" -> no; -	"Y" -> yes; -	"N" -> no; -	_ -> -	    io:format("please answer y or n\n"), -	    yes_no(Prompt) +    proplists:get_value(user_pid, Ssh#ssh.opts) ! {self(), question}, +    receive +	Answer -> +	    case trim(Answer) of +		"y" -> yes; +		"n" -> no; +		"Y" -> yes; +		"N" -> no; +		y -> yes; +		n -> no; +		_ -> +		    io:format("please answer y or n\n"), +		    yes_no(Prompt, Ssh) +	    end      end. -read_password(Prompt) -> +read_password(Prompt, Ssh) ->      format("~s", [listify(Prompt)]), -    case io:get_password() of -	"" -> -	    read_password(Prompt); -	Pass -> Pass +    proplists:get_value(user_pid, Ssh#ssh.opts) ! {self(), user_password}, +    receive +	Answer -> +	    case Answer of +		"" -> +		    read_password(Prompt, Ssh); +		Pass -> Pass +	    end      end.  listify(A) when is_atom(A) -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 1f912c9bdf..7f6e7d9946 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -133,7 +133,7 @@ kex_dh_gex_messages() ->      ].  yes_no(Ssh, Prompt)  -> -    (Ssh#ssh.io_cb):yes_no(Prompt). +    (Ssh#ssh.io_cb):yes_no(Prompt, Ssh).  connect(ConnectionSup, Address, Port, SocketOpts, Opts) ->          Timeout = proplists:get_value(connect_timeout, Opts, infinity), | 
