Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions lib/ssl/src/dtls_packet_demux.erl
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ getstat(PacketSocket, Opts) ->
init([Owner, Port0, TransportInfo, EmOpts, DTLSOptions, Socket]) ->
InternalActiveN = get_internal_active_n(),
erlang:monitor(process, Owner),
{ok, SessionIdHandle} = session_id_tracker(Socket, DTLSOptions),
{ok, SessionIdHandle} = session_id_tracker(Socket),
proc_lib:set_label({dtls_server_packet_demultiplexer, Port0}),
{ok, #state{active_n = InternalActiveN,
port = Port0,
Expand All @@ -139,11 +139,11 @@ handle_call({accept, Accepter}, From, #state{active_n = N,
listener = Socket} = State0) ->
next_datagram(Socket, N),
State = State0#state{first = false,
accepters = queue:in({Accepter, From}, Accepters)},
accepters = queue:in({Accepter, From}, Accepters)},
{noreply, State};

handle_call({accept, Accepter}, From, #state{accepters = Accepters} = State0) ->
State = State0#state{accepters = queue:in({Accepter, From}, Accepters)},
State = State0#state{accepters = queue:in({Accepter, From}, Accepters)},
{noreply, State};
handle_call(sockname, _, #state{listener = Socket} = State) ->
Reply = inet:sockname(Socket),
Expand Down Expand Up @@ -348,8 +348,16 @@ setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
dtls_options = DTLSOpts,
port = Port,
listener = Socket,
session_id_tracker = Tracker,
session_id_tracker = Tracker0,
emulated_options = EmOpts} = State) ->
Tracker = case erlang:is_process_alive(Tracker0) of
true ->
Tracker0;
false ->
{ok, Tracker1} = session_id_tracker(Socket),
Tracker1
end,

ConnArgs = [server, "localhost", Port, {self(), {Client, Socket}},
{DTLSOpts,
emulated_opts_list(EmOpts, [mode, active], []),
Expand All @@ -360,11 +368,12 @@ setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
erlang:monitor(process, Pid),
gen_server:reply(From, {ok, Pid}),
Pid ! Msg,
State#state{dtls_msq_queues = kv_insert(Client, {Pid, queue:new()}, MsgQueues),
State#state{session_id_tracker = Tracker,
dtls_msq_queues = kv_insert(Client, {Pid, queue:new()}, MsgQueues),
dtls_processes = kv_insert(Pid, Client, Processes)};
{error, Reason} ->
gen_server:reply(From, {error, Reason}),
State
State#state{session_id_tracker = Tracker}
end.

kv_update(Key, Value, Store) ->
Expand Down Expand Up @@ -411,7 +420,7 @@ get_socket_opts(Socket, SocketOpts, Cb) ->
do_set_emulated_opts([], Opts) ->
Opts;
do_set_emulated_opts([{mode, Value} | Rest], Opts) ->
do_set_emulated_opts(Rest, Opts#socket_options{mode = Value});
do_set_emulated_opts(Rest, Opts#socket_options{mode = Value});
do_set_emulated_opts([{active, N0} | Rest], Opts=#socket_options{active = Active}) when is_integer(N0) ->
N = tls_socket:update_active_n(N0, Active),
do_set_emulated_opts(Rest, Opts#socket_options{active = N});
Expand All @@ -421,14 +430,14 @@ do_set_emulated_opts([{active, Value} | Rest], Opts) ->
emulated_opts_list(_,[], Acc) ->
Acc;
emulated_opts_list( Opts, [mode | Rest], Acc) ->
emulated_opts_list(Opts, Rest, [{mode, Opts#socket_options.mode} | Acc]);
emulated_opts_list(Opts, Rest, [{mode, Opts#socket_options.mode} | Acc]);
emulated_opts_list(Opts, [active | Rest], Acc) ->
emulated_opts_list(Opts, Rest, [{active, Opts#socket_options.active} | Acc]).

%% Regardless of the option reuse_sessions we need the session_id_tracker
%% to generate session ids, but no sessions will be stored unless
%% reuse_sessions = true.
session_id_tracker(Listener,_) ->
session_id_tracker(Listener) ->
dtls_server_session_cache_sup:start_child(Listener).

get_internal_active_n() ->
Expand Down
8 changes: 5 additions & 3 deletions lib/ssl/src/ssl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2519,9 +2519,11 @@ handshake(#sslsocket{connection_cb = tls_gen_connection,
when is_list(SslOpts), is_list(Trackers), ?IS_TIMEOUT(Timeout) ->
try
Tracker = proplists:get_value(option_tracker, Trackers),
{ok, EmOpts, _} = tls_socket:get_all_opts(Tracker),
ssl_gen_statem:handshake(Socket, {SslOpts,
tls_socket:emulated_socket_options(EmOpts, #socket_options{})}, Timeout)
{ok, EmOpts} = tls_socket:get_emulated_opts(Tracker),
ssl_gen_statem:handshake(Socket,
{SslOpts,
tls_socket:emulated_socket_options(EmOpts,
#socket_options{})}, Timeout)
catch
Error = {error, _Reason} -> Error
end;
Expand Down
3 changes: 2 additions & 1 deletion lib/ssl/src/ssl_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ get_ticket_store_size() ->
application_int(server_session_ticket_store_size, 1000).

get_max_early_data_size() ->
application_int(server_session_ticket_max_early_data, ?DEFAULT_MAX_EARLY_DATA_SIZE).
application_int(server_session_ticket_max_early_data,
?DEFAULT_MAX_EARLY_DATA_SIZE).

get_internal_active_n() ->
get_internal_active_n(false).
Expand Down
2 changes: 1 addition & 1 deletion lib/ssl/src/ssl_record.erl
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ nonce_seed(_,_, CipherState) ->
%%--------------------------------------------------------------------

empty_connection_state(ConnectionEnd) ->
MaxEarlyDataSize = ssl_config:get_max_early_data_size(),
MaxEarlyDataSize = 0, %% TLS-1.3 only, this is not called by TLS-1.3
empty_connection_state(ConnectionEnd, _Version = undefined, MaxEarlyDataSize).
%%
empty_connection_state(ConnectionEnd, Version, MaxEarlyDataSize) ->
Expand Down
1 change: 0 additions & 1 deletion lib/ssl/src/ssl_server_session_cache.erl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ reuse_session(Pid, SessionId) ->
register_session(Pid, Session) ->
gen_server:cast(Pid, {register_session, Session}).


%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
Expand Down
6 changes: 2 additions & 4 deletions lib/ssl/src/ssl_server_session_cache_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ start_child(Listener) ->
%%% Supervisor callback
%%%=========================================================================
init(_) ->
SupFlags = #{strategy => simple_one_for_one,
intensity => 3,
period => 3600
SupFlags = #{strategy => simple_one_for_one
},
ChildSpecs = [#{id => undefined,
start => {ssl_server_session_cache, start_link, []},
restart => transient,
restart => temporary,
shutdown => 4000,
modules => [ssl_server_session_cache],
type => worker
Expand Down
5 changes: 4 additions & 1 deletion lib/ssl/src/tls_dtls_gen_connection.erl
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ initial_state(Role, Sender, Tab, Host, Port, Socket, {SSLOptions, SocketOptions,
%% Use highest supported version for client/server random nonce generation
#{versions := [Version|_]} = SSLOptions,
BeastMitigation = maps:get(beast_mitigation, SSLOptions, disabled),
ConnectionStates = tls_record:init_connection_states(Role, Version, BeastMitigation),
MaxEarlyData =
tls_gen_connection_1_3:init_max_early_data_size(Role),
ConnectionStates = tls_record:init_connection_states(Role, Version,
BeastMitigation, MaxEarlyData),
#{session_cb := SessionCacheCb} = ssl_config:pre_1_3_session_opts(Role),
UserMonitor = erlang:monitor(process, User),

Expand Down
1 change: 1 addition & 0 deletions lib/ssl/src/tls_gen_connection_1_3.erl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
update_cipher_key/2,
maybe_traffic_keylog_1_3/4,
maybe_forget_hs_secrets/2,
init_max_early_data_size/1,
do_maybe/0]).

%%--------------------------------------------------------------------
Expand Down
11 changes: 10 additions & 1 deletion lib/ssl/src/tls_handshake_1_3.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,16 @@ handle_pre_shared_key(#state{ssl_options = #{session_tickets := Tickets},
OfferedPreSharedKeys}, Cipher) when Tickets =/= disabled ->
Tracker = proplists:get_value(session_tickets_tracker, Trackers),
#{prf := CipherHash} = ssl_cipher_format:suite_bin_to_map(Cipher),
tls_server_session_ticket:use(Tracker, OfferedPreSharedKeys, CipherHash, HHistory).
#offered_psks{
identities = Identities,
binders = Binders
} = OfferedPreSharedKeys,
case length(Identities) == length(Binders) of
true ->
tls_server_session_ticket:use(Tracker, OfferedPreSharedKeys, CipherHash, HHistory);
false ->
{error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, illegal_pre_shared_key)}
end.

%% If the handshake includes a HelloRetryRequest, the initial
%% ClientHello and HelloRetryRequest are included in the transcript
Expand Down
11 changes: 0 additions & 11 deletions lib/ssl/src/tls_record.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

%% Handling of incoming data
-export([get_tls_records/5,
init_connection_states/3,
init_connection_states/4]).

%% Encoding TLS records
Expand Down Expand Up @@ -69,20 +68,10 @@
%% Handling of incoming data
%%====================================================================
%%--------------------------------------------------------------------
-spec init_connection_states(Role, Version, BeastMitigation) ->
ssl_record:connection_states() when
Role :: client | server,
Version :: tls_version(),
BeastMitigation :: one_n_minus_one | zero_n | disabled.

%%
%% Description: Creates a connection_states record with appropriate
%% values for the initial SSL connection setup.
%%--------------------------------------------------------------------
init_connection_states(Role, Version, BeastMitigation) ->
MaxEarlyDataSize = ssl_config:get_max_early_data_size(),
init_connection_states(Role, Version, BeastMitigation, MaxEarlyDataSize).
%%
-spec init_connection_states(Role, Version, BeastMitigation,
MaxEarlyDataSize) ->
ssl_record:connection_states() when
Expand Down
14 changes: 9 additions & 5 deletions lib/ssl/src/tls_server_connection_1_3.erl
Original file line number Diff line number Diff line change
Expand Up @@ -665,16 +665,20 @@ maybe_send_session_ticket(State, 0) ->
State;
maybe_send_session_ticket(#state{connection_states = ConnectionStates,
static_env = #static_env{trackers = Trackers,
protocol_cb = Connection}
} = State0, N) ->
protocol_cb = Connection}}
= State0, N) ->
Tracker = proplists:get_value(session_tickets_tracker, Trackers),
#{security_parameters := SecParamsR} =
ssl_record:current_connection_state(ConnectionStates, read),
#security_parameters{prf_algorithm = HKDF,
resumption_master_secret = RMS} = SecParamsR,
Ticket = new_session_ticket(Tracker, HKDF, RMS, State0),
{State, _} = Connection:send_handshake(Ticket, State0),
maybe_send_session_ticket(State, N - 1).
case new_session_ticket(Tracker, HKDF, RMS, State0) of
no_ticket -> %% Continuous restarts of ticket handler (unlikely scenario)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is meant by this code comment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the ticket handler needed to be restarted by the server connection process and it already crashed again we would end up here. This would probably not be an intermediate bug that we did not discover while testing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code comment could be more clear if it is about to stay.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can improve it later. Remind me if I forget.

State0;
Ticket ->
{State, _} = Connection:send_handshake(Ticket, State0),
maybe_send_session_ticket(State, N - 1)
end.

new_session_ticket(Tracker, HKDF, RMS,
#state{ssl_options = #{session_tickets := stateful_with_cert},
Expand Down
29 changes: 22 additions & 7 deletions lib/ssl/src/tls_server_session_ticket.erl
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@
%% Tracing
-export([handle_trace/3]).

-define(SERVER, ?MODULE).

-record(state, {
stateless,
stateful,
Expand Down Expand Up @@ -77,16 +75,26 @@ start_link(Listener, Mode1, Lifetime, TicketStoreSize, MaxEarlyDataSize, AntiRep
MaxEarlyDataSize, AntiReplay, Seed], []).

new(Pid, Prf, MasterSecret, PeerCert) ->
gen_server:call(Pid, {new_session_ticket, Prf, MasterSecret, PeerCert}, infinity).
Request = {new_session_ticket, Prf, MasterSecret, PeerCert},
case call(Pid, Request) of
{error, closed} ->
no_ticket;
Result ->
Result
end.

use(Pid, Identifiers, Prf, HandshakeHist) ->
gen_server:call(Pid, {use_ticket, Identifiers, Prf, HandshakeHist},
infinity).

case call(Pid, {use_ticket, Identifiers, Prf, HandshakeHist}) of
{error, closed} ->
%% Server died, old tickets can not be used (state is lost)
%% new accept call will start new ticket handler
{ok, undefined};
Result ->
Result
end.
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

-spec init(Args :: term()) -> {ok, State :: term()}.
init([Listener | Args]) ->
process_flag(trap_exit, true),
Expand Down Expand Up @@ -167,6 +175,13 @@ format_status(_Opt, Status) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
call(Pid, Msg) ->
try gen_server:call(Pid, Msg, infinity)
catch
exit:{noproc, _} ->
{error, closed}
end.

initial_state([stateless, Lifetime, _, MaxEarlyDataSize, undefined, Seed]) ->
#state{nonce = 0,
stateless = #{seed => stateless_seed(Seed),
Expand Down
6 changes: 2 additions & 4 deletions lib/ssl/src/tls_server_session_ticket_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,11 @@ sup_name(dist) ->
%%% Supervisor callback
%%%=========================================================================
init(_) ->
SupFlags = #{strategy => simple_one_for_one,
intensity => 0,
period => 3600
SupFlags = #{strategy => simple_one_for_one
},
ChildSpecs = [#{id => undefined,
start => {tls_server_session_ticket, start_link, []},
restart => transient,
restart => temporary,
shutdown => 4000,
modules => [tls_server_session_ticket],
type => worker
Expand Down
Loading
Loading