aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2014-03-27 11:08:06 +0100
committerHans Nilsson <[email protected]>2014-03-27 11:08:06 +0100
commitd6b30f44ea610355dab47024acdcb9fc597f96cb (patch)
treee92d281c5501e87b8916f2133931b103d39e5cbc /lib
parentbe5ad8be918b803d4224e8d6b17a508d2559b8a1 (diff)
parentfb908b7ceccaef70a46bb14db8da3e6e373a9810 (diff)
downloadotp-d6b30f44ea610355dab47024acdcb9fc597f96cb.tar.gz
otp-d6b30f44ea610355dab47024acdcb9fc597f96cb.tar.bz2
otp-d6b30f44ea610355dab47024acdcb9fc597f96cb.zip
Merge branch 'hans/ssh/login_hangs/OTP-11823'
Diffstat (limited to 'lib')
-rw-r--r--lib/ssh/doc/src/ssh.xml17
-rw-r--r--lib/ssh/src/ssh.erl12
-rw-r--r--lib/ssh/src/ssh_acceptor.erl5
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl12
4 files changed, 42 insertions, 4 deletions
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index eaf96d0230..7fbd70c87e 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -304,6 +304,23 @@
<c><![CDATA[true]]></c> if the password is valid and
<c><![CDATA[false]]></c> otherwise.</p>
</item>
+
+ <tag><c><![CDATA[{negotiation_timeout, integer()}]]></c></tag>
+ <item>
+ <p>Max time in milliseconds for the authentication negotiation. The default value is 2 minutes.
+ </p>
+ </item>
+
+ <tag><c><![CDATA[{parallel_login, boolean()}]]></c></tag>
+ <item>
+ <p>If set to false (the default value), only one login is handled a time. If set to true, an unlimited logins will be allowed simultanously. Note that this affects only the connections with authentication in progress, not the already authenticated connections.
+ </p>
+ <warning>
+ <p>Do not enable parallel_logins without protecting the server by other means like a firewall. If set to true, there is no protection against dos attacs.</p>
+ </warning>
+
+ </item>
+
<tag><c><![CDATA[{key_cb, atom()}]]></c></tag>
<item>
<p>Module implementing the behaviour <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index d50d5a0cb3..de6e8cc421 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,4 +1,4 @@
-%%
+%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
@@ -332,6 +332,12 @@ handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{rekey_limit, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{negotiation_timeout, _} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([parallel_login|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]);
handle_option([Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
@@ -360,6 +366,10 @@ handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), leng
end;
handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
Opt;
+handle_ssh_option({negotiation_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
+ Opt;
+handle_ssh_option({parallel_login, Value} = Opt) when Value==true ; Value==false ->
+ Opt;
handle_ssh_option({user, Value} = Opt) when is_list(Value) ->
Opt;
handle_ssh_option({dsa_pass_phrase, Value} = Opt) when is_list(Value) ->
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index 91905b2eaf..e57b07cee8 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -84,11 +84,14 @@ handle_connection(_Callback, Address, Port, Options, Socket) ->
SystemSup = ssh_system_sup:system_supervisor(Address, Port),
{ok, SubSysSup} = ssh_system_sup:start_subsystem(SystemSup, Options),
ConnectionSup = ssh_subsystem_sup:connection_supervisor(SubSysSup),
+ Timeout = proplists:get_value(negotiation_timeout,
+ proplists:get_value(ssh_opts, Options, []),
+ 2*60*1000),
ssh_connection_handler:start_connection(server, Socket,
[{supervisors, [{system_sup, SystemSup},
{subsystem_sup, SubSysSup},
{connection_sup, ConnectionSup}]}
- | Options], infinity).
+ | Options], Timeout).
handle_error(timeout) ->
ok;
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index d7fff14f92..322da50f21 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -110,8 +110,16 @@ start_connection(server = Role, Socket, Options, Timeout) ->
{ok, Pid} = ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Opts]),
{_, Callback, _} = proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}),
socket_control(Socket, Pid, Callback),
- Ref = erlang:monitor(process, Pid),
- handshake(Pid, Ref, Timeout)
+ case proplists:get_value(parallel_login, Opts, false) of
+ true ->
+ spawn(fun() ->
+ Ref = erlang:monitor(process, Pid),
+ handshake(Pid, Ref, Timeout)
+ end);
+ false ->
+ Ref = erlang:monitor(process, Pid),
+ handshake(Pid, Ref, Timeout)
+ end
catch
exit:{noproc, _} ->
{error, ssh_not_started};