aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2014-10-15 20:33:25 +0200
committerHans Nilsson <[email protected]>2014-10-16 15:21:09 +0200
commita4cd7efbbbf174ae283cfac60a8e5492e340e3a6 (patch)
treeebc48d4df688aadf16d7f4b1ae2f042e38d91fba
parent5d49d05c3604f764736b10cfb287818d4b41efda (diff)
downloadotp-a4cd7efbbbf174ae283cfac60a8e5492e340e3a6.tar.gz
otp-a4cd7efbbbf174ae283cfac60a8e5492e340e3a6.tar.bz2
otp-a4cd7efbbbf174ae283cfac60a8e5492e340e3a6.zip
ssh: Fix port scanner problems
-rw-r--r--lib/ssh/src/ssh_auth.erl24
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl17
-rw-r--r--lib/ssh/src/ssh_message.erl5
3 files changed, 43 insertions, 3 deletions
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index b4d406ba8d..45c4d52d7e 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -184,9 +184,8 @@ handle_userauth_request(#ssh_msg_service_request{name =
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
method = "password",
- data = Data}, _,
+ data = <<?FALSE, ?UINT32(Sz), BinPwd:Sz/binary>>}, _,
#ssh{opts = Opts} = Ssh) ->
- <<_:8, ?UINT32(Sz), BinPwd:Sz/binary>> = Data,
Password = unicode:characters_to_list(BinPwd),
case check_password(User, Password, Opts) of
true ->
@@ -201,6 +200,27 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
+ method = "password",
+ data = <<?TRUE,
+ _/binary
+ %% ?UINT32(Sz1), OldBinPwd:Sz1/binary,
+ %% ?UINT32(Sz2), NewBinPwd:Sz2/binary
+ >>
+ }, _,
+ Ssh) ->
+ %% Password change without us having sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ (because we never do)
+ %% RFC 4252 says:
+ %% SSH_MSG_USERAUTH_FAILURE without partial success - The password
+ %% has not been changed. Either password changing was not supported,
+ %% or the old password was bad.
+
+ {not_authorized, {User, {error,"Password change not supported"}},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications = "",
+ partial_success = false}, Ssh)};
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
method = "none"}, _,
#ssh{userauth_supported_methods = Methods} = Ssh) ->
{not_authorized, {User, undefined},
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 4fbc5d0ae2..e9d35c4c4c 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -45,7 +45,8 @@
%% gen_fsm callbacks
-export([hello/2, kexinit/2, key_exchange/2, new_keys/2,
- userauth/2, connected/2]).
+ userauth/2, connected/2,
+ error/2]).
-export([init/1, handle_event/3,
handle_sync_event/4, handle_info/3, terminate/3, format_status/2, code_change/4]).
@@ -174,6 +175,13 @@ init([Role, Socket, SshOpts]) ->
gen_fsm:enter_loop(?MODULE, [], error, {Error, State0})
end.
+%% Temporary fix for the Nessus error. SYN-> <-SYNACK ACK-> RST-> ?
+error(_Event, {Error, %%={badmatch,{error,enotconn}},
+ State=#state{socket=Socket,
+ transport_cb=Transport}}) ->
+ (catch Transport:close(Socket)),
+ {stop, {shutdown,init,Error}, State}.
+
%%--------------------------------------------------------------------
-spec open_channel(pid(), string(), iodata(), integer(), integer(),
timeout()) -> {open, channel_id()} | {error, term()}.
@@ -951,8 +959,14 @@ terminate({shutdown, #ssh_msg_disconnect{} = Msg}, StateName,
{SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
send_msg(SshPacket, State),
terminate(normal, StateName, State#state{ssh_params = Ssh});
+
terminate({shutdown, _}, StateName, State) ->
terminate(normal, StateName, State);
+
+terminate({shutdown,init,Reason}, StateName, State) ->
+ error_logger:info_report(io_lib:format("Erlang ssh in connection handler init: ~p~n",[Reason])),
+ terminate(normal, StateName, State);
+
terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid,
connection_state = Connection} = State) ->
terminate_subsytem(Connection),
@@ -965,6 +979,7 @@ terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid,
send_msg(SshPacket, State),
terminate(normal, StateName, State#state{ssh_params = Ssh}).
+
terminate_subsytem(#connection{system_supervisor = SysSup,
sub_system_supervisor = SubSysSup}) when is_pid(SubSysSup) ->
ssh_system_sup:stop_subsystem(SysSup, SubSysSup);
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 891ccec24c..66e7717095 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -505,6 +505,11 @@ erl_boolean(1) ->
decode_kex_init(<<?BYTE(Bool), ?UINT32(X)>>, Acc, 0) ->
list_to_tuple(lists:reverse([X, erl_boolean(Bool) | Acc]));
+decode_kex_init(<<?BYTE(Bool)>>, Acc, 0) ->
+ %% The mandatory trailing UINT32 is missing. Assume the value it anyhow must have
+ %% See rfc 4253 7.1
+ X = 0,
+ list_to_tuple(lists:reverse([X, erl_boolean(Bool) | Acc]));
decode_kex_init(<<?UINT32(Len), Data:Len/binary, Rest/binary>>, Acc, N) ->
Names = string:tokens(unicode:characters_to_list(Data), ","),
decode_kex_init(Rest, [Names | Acc], N -1).