diff options
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/dtls_connection.erl | 23 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 9 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/tls_connection.erl | 88 |
4 files changed, 68 insertions, 56 deletions
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index 2c6b71c97a..721689da8b 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -50,7 +50,7 @@ -export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states @@ -434,12 +434,12 @@ init({call, From}, {start, Timeout}, HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}), - State3 = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion + State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion session = Session0#session{session_id = Hello#client_hello.session_id}, start_or_recv_from = From}, - {Record, State} = next_record(State3), - next_event(hello, Record, State, [{{timeout, handshake}, Timeout, close} | Actions]); + + next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close} | Actions]); init({call, _} = Type, Event, #state{static_env = #static_env{role = server}, protocol_specific = PS} = State) -> Result = gen_handshake(?FUNCTION_NAME, Type, Event, @@ -497,9 +497,8 @@ hello(internal, #client_hello{cookie = <<>>, %% negotiated. VerifyRequest = dtls_handshake:hello_verify_request(Cookie, ?HELLO_VERIFY_REQUEST_VERSION), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), - {State2, Actions} = send_handshake(VerifyRequest, State1), - {Record, State} = next_record(State2), - next_event(?FUNCTION_NAME, Record, + {State, Actions} = send_handshake(VerifyRequest, State1), + next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{ tls_handshake_history = ssl_handshake:init_handshake_history()}}, @@ -701,12 +700,10 @@ connection(internal, #hello_request{}, #state{static_env = #static_env{host = Ho HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions), State1 = prepare_flight(State0), {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}), - {Record, State} = - next_record( - State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)}, - session = Session0#session{session_id - = Hello#client_hello.session_id}}), - next_event(hello, Record, State, Actions); + State = State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)}, + session = Session0#session{session_id + = Hello#client_hello.session_id}}, + next_event(hello, no_record, State, Actions); connection(internal, #client_hello{} = Hello, #state{static_env = #static_env{role = server}, handshake_env = #handshake_env{allow_renegotiate = true} = HsEnv} = State) -> %% Mitigate Computational DoS attack diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index fbbe0a49c8..12038a8527 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -442,8 +442,7 @@ handle_alert(#alert{level = ?WARNING} = Alert, StateName, passive_receive(State0 = #state{user_data_buffer = {_,BufferSize,_}}, StateName, Connection, StartTimerAction) -> case BufferSize of 0 -> - {Record, State} = Connection:next_record(State0), - Connection:next_event(StateName, Record, State, StartTimerAction); + Connection:next_event(StateName, no_record, State0, StartTimerAction); _ -> case read_application_data(<<>>, State0) of {stop, _, _} = ShutdownError -> @@ -1188,10 +1187,8 @@ cipher(internal, #finished{verify_data = Data} = Finished, cipher(internal, #next_protocol{selected_protocol = SelectedProtocol}, #state{static_env = #static_env{role = server}, handshake_env = #handshake_env{expecting_finished = true, - expecting_next_protocol_negotiation = true} = HsEnv} = State0, Connection) -> - {Record, State} = - Connection:next_record(State0), - Connection:next_event(?FUNCTION_NAME, Record, + expecting_next_protocol_negotiation = true} = HsEnv} = State, Connection) -> + Connection:next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol, expecting_next_protocol_negotiation = false}}); cipher(internal, #change_cipher_spec{type = <<1>>}, #state{handshake_env = HsEnv, connection_states = ConnectionStates0} = diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 29db1b07c4..9e7f6851c9 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -92,8 +92,8 @@ hello_request() -> #hello_request{}. %%-------------------------------------------------------------------- --spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), - Extension::map()) -> #server_hello{}. +%%-spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), +%% Extension::map()) -> #server_hello{}. %% %% Description: Creates a server hello message. %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 52e5db731a..b88c7292a7 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -60,7 +60,7 @@ close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states @@ -142,33 +142,59 @@ pids(#state{protocol_specific = #{sender := Sender}}) -> %%==================================================================== %% State transition handling %%==================================================================== -next_record(#state{handshake_env = +next_record(_, #state{handshake_env = #handshake_env{unprocessed_handshake_events = N} = HsEnv} = State) when N > 0 -> {no_record, State#state{handshake_env = HsEnv#handshake_env{unprocessed_handshake_events = N-1}}}; -next_record(#state{protocol_buffers = - #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, - connection_states = ConnectionStates, - ssl_options = #ssl_options{padding_check = Check}} = State) -> +next_record(_, #state{protocol_buffers = + #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, + connection_states = ConnectionStates, + ssl_options = #ssl_options{padding_check = Check}} = State) -> next_record(State, CipherTexts, ConnectionStates, Check); -next_record(#state{user_data_buffer = {_,0,_}, - protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, - protocol_specific = #{active_n_toggle := true, - active_n := N} = ProtocolSpec, - static_env = #static_env{socket = Socket, - close_tag = CloseTag, - transport_cb = Transport} - } = State) -> +next_record(connection, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + %% If ssl application user is not reading data wait to activate socket + flow_ctrl(State); + +next_record(_, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + activate_socket(State); +next_record(_, State) -> + {no_record, State}. + + +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = undefined} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = 0} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = BytesToRead} = State) when (Size >= BytesToRead) andalso + (BytesToRead > 0) -> + {no_record, State}; +flow_ctrl(State) -> + activate_socket(State). + + +activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec, + static_env = #static_env{socket = Socket, + close_tag = CloseTag, + transport_cb = Transport} + } = State) -> case tls_socket:setopts(Transport, Socket, [{active, N}]) of - ok -> + ok -> {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; - _ -> + _ -> self() ! {CloseTag, Socket}, {no_record, State} - end; -next_record(State) -> - {no_record, State}. + end. %% Decipher next record and concatenate consecutive ?APPLICATION_DATA records into one %% @@ -200,28 +226,20 @@ next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, Connec State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts}, connection_states = ConnectionStates}}. - next_event(StateName, Record, State) -> next_event(StateName, Record, State, []). %% next_event(StateName, no_record, State0, Actions) -> - case next_record(State0) of + case next_record(StateName, State0) of {no_record, State} -> {next_state, StateName, State, Actions}; - {#ssl_tls{} = Record, State} -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - {next_state, StateName, State0, [{next_event, internal, Alert} | Actions]} + {Record, State} -> + next_event(StateName, Record, State, Actions) end; -next_event(StateName, Record, State, Actions) -> - case Record of - no_record -> - {next_state, StateName, State, Actions}; - #ssl_tls{} = Record -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - {next_state, StateName, State, [{next_event, internal, Alert} | Actions]} - end. +next_event(StateName, #ssl_tls{} = Record, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; +next_event(StateName, #alert{} = Alert, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}. %%% TLS record protocol level application data messages @@ -871,7 +889,7 @@ next_tls_record(Data, StateName, case tls_record:get_tls_records(Data, Versions, Buf0) of {Records, Buf1} -> CT1 = CT0 ++ Records, - next_record(State0#state{protocol_buffers = + next_record(StateName, State0#state{protocol_buffers = Buffers#protocol_buffers{tls_record_buffer = Buf1, tls_cipher_texts = CT1}}); #alert{} = Alert -> |