diff options
Diffstat (limited to 'lib/ssh/src/ssh.erl')
-rw-r--r-- | lib/ssh/src/ssh.erl | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 3395f73884..719c97e940 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} | fix_idle_time(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 %% @@ -237,6 +246,13 @@ shell(Host, Port, Options) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +fix_idle_time(SshOptions) -> + case proplists:get_value(idle_time, SshOptions) of + undefined -> + [{idle_time, infinity}|SshOptions]; + _ -> + SshOptions + end. start_daemon(Host, Port, Options, Inet) -> case handle_options(Options) of {error, _Reason} = Error -> @@ -342,6 +358,12 @@ handle_option([{exec, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{auth_methods, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{pref_public_key_algs, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{quiet_mode, _} = Opt|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions). @@ -357,6 +379,13 @@ handle_ssh_option({user_interaction, Value} = Opt) when Value == true; Value == Opt; handle_ssh_option({public_key_alg, Value} = Opt) when Value == ssh_rsa; Value == ssh_dsa -> Opt; +handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), length(Value) >= 1 -> + case check_pref_algs(Value) of + true -> + Opt; + _ -> + throw({error, {eoptions, Opt}}) + end; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; handle_ssh_option({user, Value} = Opt) when is_list(Value) -> @@ -391,8 +420,7 @@ handle_ssh_option({disconnectfun , Value} = Opt) when is_function(Value) -> Opt; handle_ssh_option({failfun, Value} = Opt) when is_function(Value) -> Opt; -handle_ssh_option({ip_v6_disabled, Value} = Opt) when Value == true; - Value == false -> +handle_ssh_option({ip_v6_disabled, Value} = Opt) when is_boolean(Value) -> Opt; handle_ssh_option({transport, {Protocol, Cb, ClosTag}} = Opt) when is_atom(Protocol), is_atom(Cb), @@ -407,6 +435,11 @@ handle_ssh_option({shell, {Module, Function, _}} = Opt) when is_atom(Module), Opt; handle_ssh_option({shell, Value} = Opt) when is_function(Value) -> Opt; +handle_ssh_option({quiet_mode, Value} = Opt) when Value == true; + Value == false -> + Opt; +handle_ssh_option({idle_time, Value} = Opt) when is_integer(Value), Value > 0 -> + Opt; handle_ssh_option(Opt) -> throw({error, {eoptions, Opt}}). @@ -424,12 +457,23 @@ handle_inet_option({reuseaddr, _} = Opt) -> %% Option verified by inet handle_inet_option(Opt) -> Opt. - +%% Check preferred algs +check_pref_algs([]) -> + true; +check_pref_algs([H|T]) -> + case H of + ssh_dsa -> + check_pref_algs(T); + ssh_rsa -> + check_pref_algs(T); + _ -> + false + end. %% Has IPv6 been disabled? inetopt(true) -> inet; inetopt(false) -> - case gen_tcp:listen(0, [inet6, {ip, loopback}]) of + case gen_tcp:listen(0, [inet6]) of {ok, Dummyport} -> gen_tcp:close(Dummyport), inet6; |