diff options
author | Hans Nilsson <[email protected]> | 2015-12-08 11:54:21 +0100 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2015-12-08 11:54:21 +0100 |
commit | 45c940463b7fc16d81d023013c21eac36cd57939 (patch) | |
tree | 778673eaa6c8ecc2479991c2f04348ad867ff74f /lib/ssh | |
parent | 5fe8d649b1431d84d559e6c3730de25b54dbde31 (diff) | |
parent | bb1a28deb139c34e2425e08e11f55480f5de6526 (diff) | |
download | otp-45c940463b7fc16d81d023013c21eac36cd57939.tar.gz otp-45c940463b7fc16d81d023013c21eac36cd57939.tar.bz2 otp-45c940463b7fc16d81d023013c21eac36cd57939.zip |
Merge branch 'hans/ssh/defensics_errors' into maint
* hans/ssh/defensics_errors:
ssh: fix error for data fields errors
ssh: fix error for bad packet lengths found by Defensics
Diffstat (limited to 'lib/ssh')
-rw-r--r-- | lib/ssh/src/ssh_connection_handler.erl | 100 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 5 |
2 files changed, 64 insertions, 41 deletions
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 516a09bf6a..f082db136c 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -999,7 +999,8 @@ handle_info({Protocol, Socket, Data}, StateName, encoded_data_buffer = EncData0, undecoded_packet_length = RemainingSshPacketLen0} = State0) -> Encoded = <<EncData0/binary, Data/binary>>, - case ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0) of + try ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0) + of {get_more, DecBytes, EncDataRest, RemainingSshPacketLen, Ssh1} -> {next_state, StateName, next_packet(State0#state{encoded_data_buffer = EncDataRest, @@ -1021,7 +1022,22 @@ handle_info({Protocol, Socket, Data}, StateName, #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, description = "Bad mac", language = ""}, - handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1}) + handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1}); + + {error, {exceeds_max_size,PacketLen}} -> + DisconnectMsg = + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet length " + ++ integer_to_list(PacketLen), + language = ""}, + handle_disconnect(DisconnectMsg, State0) + catch + _:_ -> + DisconnectMsg = + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet", + language = ""}, + handle_disconnect(DisconnectMsg, State0) end; handle_info({CloseTag, _Socket}, _StateName, @@ -1392,44 +1408,54 @@ generate_event(<<?BYTE(Byte), _/binary>> = Msg, StateName, Byte == ?SSH_MSG_CHANNEL_REQUEST; Byte == ?SSH_MSG_CHANNEL_SUCCESS; Byte == ?SSH_MSG_CHANNEL_FAILURE -> - ConnectionMsg = ssh_message:decode(Msg), - State1 = generate_event_new_state(State0, EncData), - try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of - {{replies, Replies0}, Connection} -> - if StateName == connected -> - Replies = Replies0, - State2 = State1; - true -> - {ConnReplies, Replies} = - lists:splitwith(fun not_connected_filter/1, Replies0), - Q = State1#state.event_queue ++ ConnReplies, - State2 = State1#state{ event_queue = Q } - end, - State = send_replies(Replies, State2#state{connection_state = Connection}), - {next_state, StateName, next_packet(State)}; - {noreply, Connection} -> - {next_state, StateName, next_packet(State1#state{connection_state = Connection})}; - {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when - Role == client andalso ((StateName =/= connected) and (not Renegotiation)) -> - State = send_replies(Replies, State1#state{connection_state = Connection}), - User ! {self(), not_connected, Reason}, - {stop, {shutdown, normal}, - next_packet(State#state{connection_state = Connection})}; - {disconnect, _Reason, {{replies, Replies}, Connection}} -> - State = send_replies(Replies, State1#state{connection_state = Connection}), - {stop, {shutdown, normal}, State#state{connection_state = Connection}} + try + ssh_message:decode(Msg) + of + ConnectionMsg -> + State1 = generate_event_new_state(State0, EncData), + try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of + {{replies, Replies0}, Connection} -> + if StateName == connected -> + Replies = Replies0, + State2 = State1; + true -> + {ConnReplies, Replies} = + lists:splitwith(fun not_connected_filter/1, Replies0), + Q = State1#state.event_queue ++ ConnReplies, + State2 = State1#state{ event_queue = Q } + end, + State = send_replies(Replies, State2#state{connection_state = Connection}), + {next_state, StateName, next_packet(State)}; + {noreply, Connection} -> + {next_state, StateName, next_packet(State1#state{connection_state = Connection})}; + {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when + Role == client andalso ((StateName =/= connected) and (not Renegotiation)) -> + State = send_replies(Replies, State1#state{connection_state = Connection}), + User ! {self(), not_connected, Reason}, + {stop, {shutdown, normal}, + next_packet(State#state{connection_state = Connection})}; + {disconnect, _Reason, {{replies, Replies}, Connection}} -> + State = send_replies(Replies, State1#state{connection_state = Connection}), + {stop, {shutdown, normal}, State#state{connection_state = Connection}} + catch + _:Error -> + {disconnect, _Reason, {{replies, Replies}, Connection}} = + ssh_connection:handle_msg( + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, + description = "Internal error", + language = "en"}, Connection0, Role), + State = send_replies(Replies, State1#state{connection_state = Connection}), + {stop, {shutdown, Error}, State#state{connection_state = Connection}} + end + catch - _:Error -> - {disconnect, _Reason, {{replies, Replies}, Connection}} = - ssh_connection:handle_msg( - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, - description = "Internal error", - language = "en"}, Connection0, Role), - State = send_replies(Replies, State1#state{connection_state = Connection}), - {stop, {shutdown, Error}, State#state{connection_state = Connection}} + _:_ -> + handle_disconnect( + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet received", + language = ""}, State0) end; - generate_event(Msg, StateName, State0, EncData) -> try Event = ssh_message:decode(set_prefix_if_trouble(Msg,State0)), diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 67a0d29bb8..18037b8461 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1004,10 +1004,7 @@ handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0 {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE -> %% far too long message than expected - throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Bad packet length " - ++ integer_to_list(PacketLen), - language = ""}); + {error, {exceeds_max_size,PacketLen}}; {ok, PacketLen, Decrypted, Encrypted1, #ssh{recv_mac_size = MacSize} = Ssh1} -> |