From 8757505b5e4e85fd8039412b3ebc2df0326ef325 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 23 Sep 2016 16:00:00 +0200 Subject: ssl: Avoid event reordering Several handshake events may be received in the same TLS packet. Then there will be several events pushed to the gen_statems internal queue. New events already in the socket-buffer should not be processed if there are more unprocessed handshake events in next_event queue. We need to handle this in the next_record/1 function. --- lib/ssl/src/ssl_connection.hrl | 1 + lib/ssl/src/tls_connection.erl | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index f1e612a41b..d1ed62829c 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -48,6 +48,7 @@ socket_options :: #socket_options{}, connection_states :: ssl_record:connection_states() | secret_printout(), protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl + unprocessed_handshake_events = 0 :: integer(), tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout() | 'undefined', cert_db :: reference() | 'undefined', diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 9b9031473a..763f1c7253 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -421,7 +421,7 @@ handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data}, connection -> ssl_connection:hibernate_after(StateName, State, Events); _ -> - {next_state, StateName, State, Events} + {next_state, StateName, State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events} end catch throw:#alert{} = Alert -> ssl_connection:handle_own_alert(Alert, Version, StateName, State0) @@ -537,7 +537,9 @@ next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buf #alert{} = Alert -> Alert end. - +next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 -> + {no_record, State#state{unprocessed_handshake_events = N-1}}; + next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]} = Buffers, @@ -712,3 +714,10 @@ gen_info(Event, StateName, #state{negotiated_version = Version} = State) -> Version, StateName, State) end. +unprocessed_events(Events) -> + %% The first handshake event will be processed immediately + %% as it is entered first in the event queue and + %% when it is processed there will be length(Events)-1 + %% handshake events left to process before we should + %% process more TLS-records received on the socket. + erlang:length(Events)-1. -- cgit v1.2.3