summaryrefslogtreecommitdiff
path: root/lib/ssl/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src')
-rw-r--r--lib/ssl/src/dtls_connection.erl56
-rw-r--r--lib/ssl/src/dtls_handshake.erl29
-rw-r--r--lib/ssl/src/dtls_record.erl20
-rw-r--r--lib/ssl/src/ssl.erl438
-rw-r--r--lib/ssl/src/ssl_config.erl26
-rw-r--r--lib/ssl/src/ssl_connection.erl174
-rw-r--r--lib/ssl/src/ssl_connection.hrl2
-rw-r--r--lib/ssl/src/ssl_handshake.erl70
-rw-r--r--lib/ssl/src/ssl_internal.hrl2
-rw-r--r--lib/ssl/src/ssl_session.erl16
-rw-r--r--lib/ssl/src/tls_connection.erl63
-rw-r--r--lib/ssl/src/tls_handshake.erl38
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl79
-rw-r--r--lib/ssl/src/tls_record.erl8
-rw-r--r--lib/ssl/src/tls_socket.erl4
15 files changed, 553 insertions, 472 deletions
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index b220691e79..f8fd42e36d 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -66,7 +66,7 @@
%%====================================================================
%% Setup
%%====================================================================
-start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
+start_fsm(Role, Host, Port, Socket, {#{erl_dist := false},_, Tracker} = Opts,
User, {CbModule, _, _, _, _} = CbInfo,
Timeout) ->
try
@@ -316,10 +316,10 @@ queue_handshake(Handshake0, #state{handshake_env = #handshake_env{tls_handshake_
flight_buffer = #{handshakes := HsBuffer0,
change_cipher_spec := undefined,
next_sequence := Seq} = Flight0,
- ssl_options = SslOpts} = State) ->
+ ssl_options = #{log_level := LogLevel}} = State) ->
Handshake = dtls_handshake:encode_handshake(Handshake0, Version, Seq),
Hist = update_handshake_history(Handshake0, Handshake, Hist0),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'handshake', Handshake0),
+ ssl_logger:debug(LogLevel, outbound, 'handshake', Handshake0),
State#state{flight_buffer = Flight0#{handshakes => [Handshake | HsBuffer0],
next_sequence => Seq +1},
@@ -329,10 +329,10 @@ queue_handshake(Handshake0, #state{handshake_env = #handshake_env{tls_handshake_
connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes_after_change_cipher_spec := Buffer0,
next_sequence := Seq} = Flight0,
- ssl_options = SslOpts} = State) ->
+ ssl_options = #{log_level := LogLevel}} = State) ->
Handshake = dtls_handshake:encode_handshake(Handshake0, Version, Seq),
Hist = update_handshake_history(Handshake0, Handshake, Hist0),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'handshake', Handshake0),
+ ssl_logger:debug(LogLevel, outbound, 'handshake', Handshake0),
State#state{flight_buffer = Flight0#{handshakes_after_change_cipher_spec => [Handshake | Buffer0],
next_sequence => Seq +1},
@@ -384,11 +384,11 @@ send_alert(Alert, #state{static_env = #static_env{socket = Socket,
connection_env = #connection_env{negotiated_version = Version},
connection_states = ConnectionStates0,
- ssl_options = SslOpts} = State0) ->
+ ssl_options = #{log_level := LogLevel}} = State0) ->
{BinMsg, ConnectionStates} =
encode_alert(Alert, Version, ConnectionStates0),
send(Transport, Socket, BinMsg),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinMsg),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinMsg),
State0#state{connection_states = ConnectionStates}.
send_alert_in_connection(Alert, State) ->
@@ -440,7 +440,7 @@ init({call, From}, {start, Timeout},
session_cache_cb = CacheCb},
handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
connection_env = CEnv,
- ssl_options = SslOpts,
+ ssl_options = #{versions := Versions} = SslOpts,
session = #session{own_certificate = Cert} = Session0,
connection_states = ConnectionStates0
} = State0) ->
@@ -448,7 +448,7 @@ init({call, From}, {start, Timeout},
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
- HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
+ HelloVersion = dtls_record:hello_version(Version, 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}}),
State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion
@@ -547,14 +547,14 @@ hello(internal, #hello_verify_request{cookie = Cookie}, #state{static_env = #sta
Hello#client_hello.session_id}},
next_event(?FUNCTION_NAME, no_record, State, Actions);
hello(internal, #client_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #ssl_options{handshake = hello},
+ #state{ssl_options = #{handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, Extensions}}]};
hello(internal, #server_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #ssl_options{handshake = hello},
+ #state{ssl_options = #{handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
@@ -705,7 +705,7 @@ connection(internal, #hello_request{}, #state{static_env = #static_env{host = Ho
handshake_env = #handshake_env{ renegotiation = {Renegotiation, _}},
connection_env = CEnv,
session = #session{own_certificate = Cert} = Session0,
- ssl_options = SslOpts,
+ ssl_options = #{versions := Versions} = SslOpts,
connection_states = ConnectionStates0,
protocol_specific = PS
} = State0) ->
@@ -713,7 +713,7 @@ connection(internal, #hello_request{}, #state{static_env = #static_env{host = Ho
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
- HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
+ HelloVersion = dtls_record:hello_version(Version, Versions),
State1 = prepare_flight(State0),
{State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}),
State = State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
@@ -774,9 +774,10 @@ format_status(Type, Data) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
+initial_state(Role, Host, Port, Socket,
+ {#{client_renegotiation := ClientRenegotiation} = SSLOptions, SocketOptions, _}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
- #ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
+ #{beast_mitigation := BeastMitigation} = SSLOptions,
ConnectionStates = dtls_record:init_connection_states(Role, BeastMitigation),
SessionCacheCb = case application:get_env(ssl, session_cb) of
@@ -810,13 +811,13 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
handshake_env = #handshake_env{
tls_handshake_history = ssl_handshake:init_handshake_history(),
renegotiation = {false, first},
- allow_renegotiate = SSLOptions#ssl_options.client_renegotiation
+ allow_renegotiate = ClientRenegotiation
},
connection_env = #connection_env{user_application = {Monitor, User}},
socket_options = SocketOptions,
%% We do not want to save the password in the state so that
%% could be written in the clear into error logs.
- ssl_options = SSLOptions#ssl_options{password = undefined},
+ ssl_options = SSLOptions#{password => undefined},
session = #session{is_resumable = new},
connection_states = ConnectionStates,
protocol_buffers = #protocol_buffers{},
@@ -989,12 +990,13 @@ handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
-handle_own_alert(Alert, Version, StateName, #state{static_env = #static_env{data_tag = udp,
- role = Role},
- ssl_options = Options} = State0) ->
+handle_own_alert(Alert, Version, StateName,
+ #state{static_env = #static_env{data_tag = udp,
+ role = Role},
+ ssl_options = #{log_level := LogLevel}} = State0) ->
case ignore_alert(Alert, State0) of
{true, State} ->
- log_ignore_alert(Options#ssl_options.log_level, StateName, Alert, Role),
+ log_ignore_alert(LogLevel, StateName, Alert, Role),
{next_state, StateName, State};
{false, State} ->
ssl_connection:handle_own_alert(Alert, Version, StateName, State)
@@ -1105,7 +1107,7 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
flight_buffer = #{handshakes := Flight,
change_cipher_spec := undefined},
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{log_level = LogLevel}} = State0,
+ ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
%% TODO remove hardcoded Max size
{Encoded, ConnectionStates} =
@@ -1121,7 +1123,7 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := []},
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{log_level = LogLevel}} = State0,
+ ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch, ConnectionStates0),
@@ -1139,7 +1141,7 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := Flight1},
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{log_level = LogLevel}} = State0,
+ ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch-1, ConnectionStates0),
@@ -1160,7 +1162,7 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := Flight1},
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{log_level = LogLevel}} = State0,
+ ssl_options = #{log_level := LogLevel}} = State0,
Epoch) ->
{EncChangeCipher, ConnectionStates1} =
encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates0),
@@ -1220,8 +1222,8 @@ send_application_data(Data, From, _StateName,
connection_env = #connection_env{negotiated_version = Version},
handshake_env = HsEnv,
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt,
- log_level = LogLevel}} = State0) ->
+ ssl_options = #{renegotiate_at := RenegotiateAt,
+ log_level := LogLevel}} = State0) ->
case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
true ->
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 4a381745d4..b2a5fcfa66 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -47,7 +47,7 @@
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(ssl:host(), inet:port_number(), ssl_record:connection_states(),
- #ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
+ ssl_options(), integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
%% Description: Creates a client hello message.
@@ -60,16 +60,15 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
%%--------------------------------------------------------------------
-spec client_hello(ssl:host(), inet:port_number(), term(), ssl_record:connection_states(),
- #ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
+ ssl_options(), integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
%% Description: Creates a client hello message.
%%--------------------------------------------------------------------
client_hello(Host, Port, Cookie, ConnectionStates,
- #ssl_options{versions = Versions,
- ciphers = UserSuites,
- fallback = Fallback
- } = SslOpts,
+ #{versions := Versions,
+ ciphers := UserSuites,
+ fallback := Fallback} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = dtls_record:highest_protocol_version(Versions),
Pending = ssl_record:pending_connection_state(ConnectionStates, read),
@@ -97,7 +96,7 @@ hello(#server_hello{server_version = Version, random = Random,
cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId, extensions = HelloExt},
- #ssl_options{versions = SupportedVersions} = SslOpt,
+ #{versions := SupportedVersions} = SslOpt,
ConnectionStates0, Renegotiation) ->
case dtls_record:is_acceptable_version(Version, SupportedVersions) of
true ->
@@ -108,7 +107,7 @@ hello(#server_hello{server_version = Version, random = Random,
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
end;
hello(#client_hello{client_version = ClientVersion} = Hello,
- #ssl_options{versions = Versions} = SslOpts,
+ #{versions := Versions} = SslOpts,
Info, Renegotiation) ->
Version = ssl_handshake:select_version(dtls_record, ClientVersion, Versions),
handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation).
@@ -151,7 +150,7 @@ encode_handshake(Handshake, Version, Seq) ->
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
--spec get_dtls_handshake(ssl_record:ssl_version(), binary(), #protocol_buffers{}, #ssl_options{}) ->
+-spec get_dtls_handshake(ssl_record:ssl_version(), binary(), #protocol_buffers{}, ssl_options()) ->
{[dtls_handshake()], #protocol_buffers{}}.
%%
%% Description: Given buffered and new data from dtls_record, collects
@@ -170,10 +169,10 @@ handle_client_hello(Version,
compression_methods = Compressions,
random = Random,
extensions = HelloExt},
- #ssl_options{versions = Versions,
- signature_algs = SupportedHashSigns,
- eccs = SupportedECCs,
- honor_ecc_order = ECCOrder} = SslOpts,
+ #{versions := Versions,
+ signature_algs := SupportedHashSigns,
+ eccs := SupportedECCs,
+ honor_ecc_order := ECCOrder} = SslOpts,
{Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _},
Renegotiation) ->
case dtls_record:is_acceptable_version(Version, Versions) of
@@ -317,14 +316,14 @@ handle_fragments(Version, FragmentData, Buffers0, Options, Acc) ->
do_handle_fragments(_, [], Buffers, _Options, Acc) ->
{lists:reverse(Acc), Buffers};
-do_handle_fragments(Version, [Fragment | Fragments], Buffers0, Options, Acc) ->
+do_handle_fragments(Version, [Fragment | Fragments], Buffers0, #{log_level := LogLevel} = Options, Acc) ->
case reassemble(Version, Fragment, Buffers0) of
{more_data, Buffers} when Fragments == [] ->
{lists:reverse(Acc), Buffers};
{more_data, Buffers} ->
do_handle_fragments(Version, Fragments, Buffers, Options, Acc);
{{Handshake, _} = HsPacket, Buffers} ->
- ssl_logger:debug(Options#ssl_options.log_level, inbound, 'handshake', Handshake),
+ ssl_logger:debug(LogLevel, inbound, 'handshake', Handshake),
do_handle_fragments(Version, Fragments, Buffers, Options, [HsPacket | Acc])
end.
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 8b8db7b2de..ee0ce2d22a 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -163,7 +163,7 @@ current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
%%--------------------------------------------------------------------
-spec get_dtls_records(binary(), {atom(), atom(), ssl_record:ssl_version(), [ssl_record:ssl_version()]}, binary(),
- #ssl_options{}) -> {[binary()], binary()} | #alert{}.
+ ssl_options()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from UDP/SCTP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
@@ -399,13 +399,13 @@ initial_connection_state(ConnectionEnd, BeastMitigation) ->
get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Epoch), ?UINT48(SequenceNumber),
?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
- Acc, SslOpts) when ((StateName == hello) orelse
- ((StateName == certify) andalso (DataTag == udp)) orelse
- ((StateName == abbreviated) andalso(DataTag == udp)))
- andalso
- ((Type == ?HANDSHAKE) orelse
- (Type == ?ALERT)) ->
- ssl_logger:debug(SslOpts#ssl_options.log_level, inbound, 'record', [RawDTLSRecord]),
+ Acc, #{log_level := LogLevel} = SslOpts)
+ when ((StateName == hello)
+ orelse ((StateName == certify) andalso (DataTag == udp))
+ orelse ((StateName == abbreviated) andalso (DataTag == udp))) andalso ((Type == ?HANDSHAKE)
+ orelse
+ (Type == ?ALERT)) ->
+ ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
case is_acceptable_version({MajVer, MinVer}, Versions) of
true ->
get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
@@ -418,11 +418,11 @@ get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo, <<?BYTE(Type),?B
get_dtls_records_aux({_, _, Version, _} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Epoch), ?UINT48(SequenceNumber),
?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
- Acc, SslOpts) when (Type == ?APPLICATION_DATA) orelse
+ Acc, #{log_level := LogLevel} = SslOpts) when (Type == ?APPLICATION_DATA) orelse
(Type == ?HANDSHAKE) orelse
(Type == ?ALERT) orelse
(Type == ?CHANGE_CIPHER_SPEC) ->
- ssl_logger:debug(SslOpts#ssl_options.log_level, inbound, 'record', [RawDTLSRecord]),
+ ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
case {MajVer, MinVer} of
Version ->
get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 7ff9aed8ea..0d6501b5ee 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -97,7 +97,8 @@
new_ssl_options/3,
suite_to_str/1,
suite_to_openssl_str/1,
- str_to_suite/1]).
+ str_to_suite/1,
+ options_to_map/1]).
-deprecated({ssl_accept, 1, eventually}).
-deprecated({ssl_accept, 2, eventually}).
@@ -438,6 +439,7 @@
elliptic_curves => [public_key:oid()],
sni => hostname()}. % exported
%% -------------------------------------------------------------------------------------------------------
+-define(SSL_OPTIONS, record_info(fields, ssl_options)).
%%%--------------------------------------------------------------------
%%% API
@@ -784,7 +786,13 @@ close(#sslsocket{pid = [TLSPid|_]},
{Pid, Timeout} = DownGrade) when is_pid(TLSPid),
is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
- ssl_connection:close(TLSPid, {close, DownGrade});
+ case ssl_connection:close(TLSPid, {close, DownGrade}) of
+ ok -> %% In normal close {error, closed} is regarded as ok, as it is not interesting which side
+ %% that got to do the actual close. But in the downgrade case only {ok, Port} is a sucess.
+ {error, closed};
+ Other ->
+ Other
+ end;
close(#sslsocket{pid = [TLSPid|_]}, Timeout) when is_pid(TLSPid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, Timeout});
@@ -1452,15 +1460,18 @@ do_listen(Port, #config{transport_info = {Transport, _, _, _,_}} = Config, tls_c
do_listen(Port, Config, dtls_connection) ->
dtls_socket:listen(Port, Config).
-%% Handle extra ssl options given to ssl_accept
--spec handle_options([any()], #ssl_options{}) -> #ssl_options{}
- ; ([any()], client | server) -> {ok, #config{}}.
+
+-spec handle_options([any()], client | server) -> {ok, #config{}};
+ ([any()], ssl_options()) -> ssl_options().
+
handle_options(Opts, Role) ->
handle_options(Opts, Role, undefined).
-handle_options(Opts0, #ssl_options{protocol = Protocol, cacerts = CaCerts0,
- cacertfile = CaCertFile0} = InheritedSslOpts, _) ->
+%% Handle ssl options at handshake_continue
+handle_options(Opts0, #{protocol := Protocol,
+ cacerts := CaCerts0,
+ cacertfile := CaCertFile0} = InheritedSslOpts, _) ->
RecordCB = record_cb(Protocol),
CaCerts = handle_option(cacerts, Opts0, CaCerts0),
{Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun, PartialChainHanlder,
@@ -1472,13 +1483,13 @@ handle_options(Opts0, #ssl_options{protocol = Protocol, cacerts = CaCerts0,
CAFile
end,
- NewVerifyOpts = InheritedSslOpts#ssl_options{cacerts = CaCerts,
- cacertfile = CaCertFile,
- verify = Verify,
- verify_fun = VerifyFun,
- partial_chain = PartialChainHanlder,
- fail_if_no_peer_cert = FailIfNoPeerCert,
- verify_client_once = VerifyClientOnce},
+ NewVerifyOpts = InheritedSslOpts#{cacerts => CaCerts,
+ cacertfile => CaCertFile,
+ verify => Verify,
+ verify_fun => VerifyFun,
+ partial_chain => PartialChainHanlder,
+ fail_if_no_peer_cert => FailIfNoPeerCert,
+ verify_client_once => VerifyClientOnce},
SslOpts1 = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
end, Opts0, [cacerts, cacertfile, verify, verify_fun, partial_chain,
@@ -1490,10 +1501,10 @@ handle_options(Opts0, #ssl_options{protocol = Protocol, cacerts = CaCerts0,
Versions0 = [RecordCB:protocol_version(Vsn) || Vsn <- Value],
Versions1 = lists:sort(fun RecordCB:is_higher/2, Versions0),
new_ssl_options(proplists:delete(versions, SslOpts1),
- NewVerifyOpts#ssl_options{versions = Versions1}, record_cb(Protocol))
+ NewVerifyOpts#{versions => Versions1}, record_cb(Protocol))
end;
-%% Handle all options in listen and connect
+%% Handle all options in listen, connect and handshake
handle_options(Opts0, Role, Host) ->
Opts = proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Opts0),
@@ -1544,36 +1555,21 @@ handle_options(Opts0, Role, Host) ->
user_lookup_fun = handle_option(user_lookup_fun, Opts, undefined),
psk_identity = handle_option(psk_identity, Opts, undefined),
srp_identity = handle_option(srp_identity, Opts, undefined),
- ciphers = handle_cipher_option(proplists:get_value(ciphers, Opts, []),
- HighestVersion),
- eccs = handle_eccs_option(proplists:get_value(eccs, Opts, eccs()),
- HighestVersion),
- supported_groups = handle_supported_groups_option(
- proplists:get_value(supported_groups, Opts, groups(default)),
- HighestVersion),
- signature_algs =
- handle_hashsigns_option(
- proplists:get_value(
- signature_algs,
- Opts,
- default_option_role_sign_algs(server,
- tls_v1:default_signature_algs(HighestVersion),
- Role,
- HighestVersion)),
- tls_version(HighestVersion)),
- signature_algs_cert =
- handle_signature_algorithms_option(
- proplists:get_value(
- signature_algs_cert,
- Opts,
- undefined), %% Do not send by default
- tls_version(HighestVersion)),
- reuse_sessions = handle_reuse_sessions_option(reuse_sessions, Opts, Role),
- reuse_session = handle_reuse_session_option(reuse_session, Opts, Role),
+ ciphers = handle_option(ciphers, Opts, undefined, undefined, undefined, HighestVersion),
+
+ eccs = handle_option(eccs, Opts, undefined, undefined, undefined, HighestVersion),
+
+ supported_groups = handle_option(supported_groups, Opts, undefined, undefined, undefined,
+ HighestVersion),
+ signature_algs = handle_option(signature_algs, Opts, undefined, Role, undefined, HighestVersion),
+ signature_algs_cert = handle_option(signature_algs_cert, Opts, undefined, undefined, undefined,
+ HighestVersion),
+ reuse_sessions = handle_option(reuse_sessions, Opts, undefined, Role),
+
+ reuse_session = handle_option(reuse_session, Opts, undefined, Role),
+
secure_renegotiate = handle_option(secure_renegotiate, Opts, true),
- client_renegotiation = handle_option(client_renegotiation, Opts,
- default_option_role(server, true, Role),
- server, Role),
+ client_renegotiation = handle_option(client_renegotiation, Opts, undefined, Role),
renegotiate_at = handle_option(renegotiate_at, Opts, ?DEFAULT_RENEGOTIATE_AT),
hibernate_after = handle_option(hibernate_after, Opts, infinity),
erl_dist = handle_option(erl_dist, Opts, false),
@@ -1584,71 +1580,61 @@ handle_options(Opts0, Role, Host) ->
next_protocols_advertised =
handle_option(next_protocols_advertised, Opts, undefined),
next_protocol_selector =
- make_next_protocol_selector(
- handle_option(client_preferred_next_protocols, Opts, undefined)),
- server_name_indication = handle_option(server_name_indication, Opts,
- default_option_role(client,
- server_name_indication_default(Host), Role)),
+ handle_option(next_protocol_selector, Opts, undefined),
+ server_name_indication =
+ handle_option(server_name_indication, Opts, undefined, Role, Host),
sni_hosts = handle_option(sni_hosts, Opts, []),
sni_fun = handle_option(sni_fun, Opts, undefined),
- honor_cipher_order = handle_option(honor_cipher_order, Opts,
- default_option_role(server, false, Role),
- server, Role),
- honor_ecc_order = handle_option(honor_ecc_order, Opts,
- default_option_role(server, false, Role),
- server, Role),
+ honor_cipher_order = handle_option(honor_cipher_order, Opts, undefined, Role),
+ honor_ecc_order = handle_option(honor_ecc_order, Opts, undefined, Role),
protocol = Protocol,
padding_check = proplists:get_value(padding_check, Opts, true),
- beast_mitigation = handle_option(beast_mitigation, Opts, one_n_minus_one),
- fallback = handle_option(fallback, Opts,
- proplists:get_value(fallback, Opts,
- default_option_role(client,
- false, Role)),
- client, Role),
+ beast_mitigation = handle_option(beast_mitigation, Opts, one_n_minus_one),
+ fallback = handle_option(fallback, Opts, undefined, Role),
+
crl_check = handle_option(crl_check, Opts, false),
crl_cache = handle_option(crl_cache, Opts, {ssl_crl_cache, {internal, []}}),
max_handshake_size = handle_option(max_handshake_size, Opts, ?DEFAULT_MAX_HANDSHAKE_SIZE),
handshake = handle_option(handshake, Opts, full),
- customize_hostname_check = handle_option(customize_hostname_check, Opts, [])
+ customize_hostname_check = handle_option(customize_hostname_check, Opts, [])
},
LogLevel = handle_option(log_alert, Opts, true),
- SSLOptions = SSLOptions0#ssl_options{
+ SSLOptions1 = SSLOptions0#ssl_options{
log_level = handle_option(log_level, Opts, LogLevel)
},
CbInfo = handle_option(cb_info, Opts, default_cb_info(Protocol)),
- SslOptions = [protocol, versions, verify, verify_fun, partial_chain,
- fail_if_no_peer_cert, verify_client_once,
- depth, cert, certfile, key, keyfile,
- password, cacerts, cacertfile, dh, dhfile,
- user_lookup_fun, psk_identity, srp_identity, ciphers,
- reuse_session, reuse_sessions, ssl_imp, client_renegotiation,
- cb_info, renegotiate_at, secure_renegotiate, hibernate_after,
- erl_dist, alpn_advertised_protocols, sni_hosts, sni_fun,
- alpn_preferred_protocols, next_protocols_advertised,
- client_preferred_next_protocols, log_alert, log_level,
- server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache,
- fallback, signature_algs, signature_algs_cert, eccs, honor_ecc_order,
- beast_mitigation, max_handshake_size, handshake, customize_hostname_check,
- supported_groups],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
- end, Opts, SslOptions),
+ end, Opts, ?SSL_OPTIONS ++
+ [ssl_imp, %% TODO: remove ssl_imp
+ client_preferred_next_protocols, %% next_protocol_selector
+ log_alert,
+ cb_info]),
{Sock, Emulated} = emulated_options(Protocol, SockOpts),
ConnetionCb = connection_cb(Opts),
-
+ SSLOptions = options_to_map(SSLOptions1),
{ok, #config{ssl = SSLOptions, emulated = Emulated, inet_ssl = Sock,
inet_user = Sock, transport_info = CbInfo, connection_cb = ConnetionCb
}}.
-handle_option(OptionName, Opts, Default, Role, Role) ->
- handle_option(OptionName, Opts, Default);
-handle_option(_, _, undefined = Value, _, _) ->
- Value.
+%% handle_option(OptionName, Opts, Default, Role, Role) ->
+%% handle_option(OptionName, Opts, Default);
+%% handle_option(_, _, undefined = Value, _, _) ->
+%% Value.
-handle_option(sni_fun, Opts, Default) ->
+handle_option(OptionName, Opts, Default) ->
+ handle_option(OptionName, Opts, Default, undefined, undefined, undefined).
+%%
+handle_option(OptionName, Opts, Default, Role) ->
+ handle_option(OptionName, Opts, Default, Role, undefined, undefined).
+%%
+handle_option(OptionName, Opts, Default, Role, Host) ->
+ handle_option(OptionName, Opts, Default, Role, Host, undefined).
+%%
+handle_option(sni_fun, Opts, Default, _Role, _Host, _Version) ->
OptFun = validate_option(sni_fun,
proplists:get_value(sni_fun, Opts, Default)),
OptHosts = proplists:get_value(sni_hosts, Opts, undefined),
@@ -1660,14 +1646,91 @@ handle_option(sni_fun, Opts, Default) ->
_ ->
throw({error, {conflict_options, [sni_fun, sni_hosts]}})
end;
-handle_option(cb_info, Opts, Default) ->
+handle_option(cb_info, Opts, Default, _Role, _Host, _Version) ->
CbInfo = proplists:get_value(cb_info, Opts, Default),
true = validate_option(cb_info, CbInfo),
handle_cb_info(CbInfo, Default);
-handle_option(OptionName, Opts, Default) ->
+handle_option(ciphers = Key, Opts, _Default, _Role, _Host, HighestVersion) ->
+ handle_cipher_option(proplists:get_value(Key, Opts, []),
+ HighestVersion);
+handle_option(eccs = Key, Opts, _Default, _Role, _Host, HighestVersion) ->
+ handle_eccs_option(proplists:get_value(Key, Opts, eccs()),
+ HighestVersion);
+handle_option(supported_groups = Key, Opts, _Default, _Role, _Host, HighestVersion) ->
+ handle_supported_groups_option(proplists:get_value(Key, Opts, groups(default)),
+ HighestVersion);
+handle_option(signature_algs = Key, Opts, _Default, Role, _Host, HighestVersion) ->
+ handle_hashsigns_option(
+ proplists:get_value(Key,
+ Opts,
+ default_option_role_sign_algs(server,
+ tls_v1:default_signature_algs(HighestVersion),
+ Role,
+ HighestVersion)),
+ tls_version(HighestVersion));
+handle_option(signature_algs_cert = Key, Opts, _Default, _Role, _Host, HighestVersion) ->
+ handle_signature_algorithms_option(
+ proplists:get_value(Key,
+ Opts,
+ undefined), %% Do not send by default
+ tls_version(HighestVersion));
+handle_option(reuse_sessions = Key, Opts, _Default, client, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, true),
+ validate_option(Key, Value),
+ Value;
+handle_option(reuse_sessions = Key, Opts0, _Default, server, _Host, _Version) ->
+ Opts = proplists:delete({Key, save}, Opts0),
+ Value = proplists:get_value(Key, Opts, true),
+ validate_option(Key, Value),
+ Value;
+handle_option(reuse_session = Key, Opts, _Default, client, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, undefined),
+ validate_option(Key, Value),
+ Value;
+handle_option(reuse_session = Key, Opts, _Default, server, _Host, _Version) ->
+ ReuseSessionFun = fun(_, _, _, _) -> true end,
+ Value = proplists:get_value(Key, Opts, ReuseSessionFun),
+ validate_option(Key, Value),
+ Value;
+handle_option(fallback = Key, Opts, _Default, Role, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, default_option_role(client, false, Role)),
+ assert_role(client_only, Role, Key, Value),
+ validate_option(Key, Value);
+handle_option(client_renegotiation = Key, Opts, _Default, Role, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, default_option_role(server, true, Role)),
+ assert_role(server_only, Role, Key, Value),
+ validate_option(Key, Value);
+handle_option(honor_cipher_order = Key, Opts, _Default, Role, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, default_option_role(server, false, Role)),
+ assert_role(server_only, Role, Key, Value),
+ validate_option(Key, Value);
+handle_option(honor_ecc_order = Key, Opts, _Default, Role, _Host, _Version) ->
+ Value = proplists:get_value(Key, Opts, default_option_role(server, false, Role)),
+ assert_role(server_only, Role, Key, Value),
+ validate_option(Key, Value);
+handle_option(next_protocol_selector = _Key, Opts, _Default, _Role, _Host, _Version) ->
+ make_next_protocol_selector(
+ handle_option(client_preferred_next_protocols, Opts, undefined, undefined, undefined, undefined));
+handle_option(server_name_indication = Key, Opts, _Default, Role, Host, _Version) ->
+ Default = default_option_role(client, server_name_indication_default(Host), Role),
+ validate_option(Key, proplists:get_value(Key, Opts, Default));
+handle_option(OptionName, Opts, Default, _Role, _Host, _Version) ->
validate_option(OptionName,
proplists:get_value(OptionName, Opts, Default)).
+
+assert_role(client_only, client, _, _) ->
+ ok;
+assert_role(server_only, server, _, _) ->
+ ok;
+assert_role(client_only, _, _, undefined) ->
+ ok;
+assert_role(server_only, _, _, undefined) ->
+ ok;
+assert_role(Type, _, Key, _) ->
+ throw({error, {option, Type, Key}}).
+
+
validate_option(versions, Versions) ->
validate_versions(Versions, Versions);
validate_option(verify, Value)
@@ -1913,6 +1976,13 @@ validate_option(cb_info, {V1, V2, V3, V4, V5}) when is_atom(V1),
true;
validate_option(cb_info, _) ->
false;
+validate_option(Opt, undefined = Value) ->
+ case lists:member(Opt, ?SSL_OPTIONS) of
+ true ->
+ Value;
+ false ->
+ throw({error, {options, {Opt, Value}}})
+ end;
validate_option(Opt, Value) ->
throw({error, {options, {Opt, Value}}}).
@@ -1957,26 +2027,6 @@ handle_signature_algorithms_option(Value, Version) when is_list(Value)
handle_signature_algorithms_option(_, _Version) ->
undefined.
-handle_reuse_sessions_option(Key, Opts, client) ->
- Value = proplists:get_value(Key, Opts, true),
- validate_option(Key, Value),
- Value;
-handle_reuse_sessions_option(Key, Opts0, server) ->
- Opts = proplists:delete({Key, save}, Opts0),
- Value = proplists:get_value(Key, Opts, true),
- validate_option(Key, Value),
- Value.
-
-handle_reuse_session_option(Key, Opts, client) ->
- Value = proplists:get_value(Key, Opts, undefined),
- validate_option(Key, Value),
- Value;
-handle_reuse_session_option(Key, Opts, server) ->
- ReuseSessionFun = fun(_, _, _, _) -> true end,
- Value = proplists:get_value(Key, Opts, ReuseSessionFun),
- validate_option(Key, Value),
- Value.
-
validate_options([]) ->
[];
validate_options([{Opt, Value} | Tail]) ->
@@ -2225,101 +2275,104 @@ assert_proplist([inet6 | Rest]) ->
assert_proplist([Value | _]) ->
throw({option_not_a_key_value_tuple, Value}).
-new_ssl_options([], #ssl_options{} = Opts, _) ->
+new_ssl_options([], #{} = Opts, _) ->
Opts;
-new_ssl_options([{verify_client_once, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{verify_client_once =
- validate_option(verify_client_once, Value)}, RecordCB);
-new_ssl_options([{depth, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{depth = validate_option(depth, Value)}, RecordCB);
-new_ssl_options([{cert, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{cert = validate_option(cert, Value)}, RecordCB);
-new_ssl_options([{certfile, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{certfile = validate_option(certfile, Value)}, RecordCB);
-new_ssl_options([{key, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{key = validate_option(key, Value)}, RecordCB);
-new_ssl_options([{keyfile, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{keyfile = validate_option(keyfile, Value)}, RecordCB);
-new_ssl_options([{password, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{password = validate_option(password, Value)}, RecordCB);
-new_ssl_options([{dh, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{dh = validate_option(dh, Value)}, RecordCB);
-new_ssl_options([{dhfile, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{dhfile = validate_option(dhfile, Value)}, RecordCB);
-new_ssl_options([{user_lookup_fun, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{user_lookup_fun = validate_option(user_lookup_fun, Value)}, RecordCB);
-new_ssl_options([{psk_identity, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{psk_identity = validate_option(psk_identity, Value)}, RecordCB);
-new_ssl_options([{srp_identity, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{srp_identity = validate_option(srp_identity, Value)}, RecordCB);
-new_ssl_options([{ciphers, Value} | Rest], #ssl_options{versions = Versions} = Opts, RecordCB) ->
+new_ssl_options([{verify_client_once, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{verify_client_once =>
+ validate_option(verify_client_once, Value)}, RecordCB);
+new_ssl_options([{depth, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{depth => validate_option(depth, Value)}, RecordCB);
+new_ssl_options([{cert, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{cert => validate_option(cert, Value)}, RecordCB);
+new_ssl_options([{certfile, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{certfile => validate_option(certfile, Value)}, RecordCB);
+new_ssl_options([{key, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{key => validate_option(key, Value)}, RecordCB);
+new_ssl_options([{keyfile, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{keyfile => validate_option(keyfile, Value)}, RecordCB);
+new_ssl_options([{password, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{password => validate_option(password, Value)}, RecordCB);
+new_ssl_options([{dh, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{dh => validate_option(dh, Value)}, RecordCB);
+new_ssl_options([{dhfile, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{dhfile => validate_option(dhfile, Value)}, RecordCB);
+new_ssl_options([{user_lookup_fun, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{user_lookup_fun => validate_option(user_lookup_fun, Value)}, RecordCB);
+new_ssl_options([{psk_identity, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{psk_identity => validate_option(psk_identity, Value)}, RecordCB);
+new_ssl_options([{srp_identity, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{srp_identity => validate_option(srp_identity, Value)}, RecordCB);
+new_ssl_options([{ciphers, Value} | Rest], #{versions := Versions} = Opts, RecordCB) ->
Ciphers = handle_cipher_option(Value, RecordCB:highest_protocol_version(Versions)),
- new_ssl_options(Rest,
- Opts#ssl_options{ciphers = Ciphers}, RecordCB);
-new_ssl_options([{reuse_session, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{reuse_session = validate_option(reuse_session, Value)}, RecordCB);
-new_ssl_options([{reuse_sessions, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{reuse_sessions = validate_option(reuse_sessions, Value)}, RecordCB);
-new_ssl_options([{ssl_imp, _Value} | Rest], #ssl_options{} = Opts, RecordCB) -> %% Not used backwards compatibility
+ new_ssl_options(Rest, Opts#{ciphers => Ciphers}, RecordCB);
+new_ssl_options([{reuse_session, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{reuse_session => validate_option(reuse_session, Value)}, RecordCB);
+new_ssl_options([{reuse_sessions, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{reuse_sessions => validate_option(reuse_sessions, Value)}, RecordCB);
+new_ssl_options([{ssl_imp, _Value} | Rest], #{} = Opts, RecordCB) -> %% Not used backwards compatibility
new_ssl_options(Rest, Opts, RecordCB);
-new_ssl_options([{renegotiate_at, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{ renegotiate_at = validate_option(renegotiate_at, Value)}, RecordCB);
-new_ssl_options([{secure_renegotiate, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{secure_renegotiate = validate_option(secure_renegotiate, Value)}, RecordCB);
-new_ssl_options([{client_renegotiation, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{client_renegotiation = validate_option(client_renegotiation, Value)}, RecordCB);
-new_ssl_options([{hibernate_after, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{hibernate_after = validate_option(hibernate_after, Value)}, RecordCB);
-new_ssl_options([{alpn_advertised_protocols, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{alpn_advertised_protocols = validate_option(alpn_advertised_protocols, Value)}, RecordCB);
-new_ssl_options([{alpn_preferred_protocols, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{alpn_preferred_protocols = validate_option(alpn_preferred_protocols, Value)}, RecordCB);
-new_ssl_options([{next_protocols_advertised, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{next_protocols_advertised = validate_option(next_protocols_advertised, Value)}, RecordCB);
-new_ssl_options([{client_preferred_next_protocols, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{next_protocol_selector =
- make_next_protocol_selector(validate_option(client_preferred_next_protocols, Value))}, RecordCB);
-new_ssl_options([{log_alert, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{log_level = validate_option(log_alert, Value)}, RecordCB);
-new_ssl_options([{log_level, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{log_level = validate_option(log_level, Value)}, RecordCB);
-new_ssl_options([{server_name_indication, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{server_name_indication = validate_option(server_name_indication, Value)}, RecordCB);
-new_ssl_options([{honor_cipher_order, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{honor_cipher_order = validate_option(honor_cipher_order, Value)}, RecordCB);
-new_ssl_options([{honor_ecc_order, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{honor_ecc_order = validate_option(honor_ecc_order, Value)}, RecordCB);
-new_ssl_options([{eccs, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+new_ssl_options([{renegotiate_at, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{renegotiate_at => validate_option(renegotiate_at, Value)}, RecordCB);
+new_ssl_options([{secure_renegotiate, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{secure_renegotiate => validate_option(secure_renegotiate, Value)}, RecordCB);
+new_ssl_options([{client_renegotiation, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{client_renegotiation => validate_option(client_renegotiation, Value)}, RecordCB);
+new_ssl_options([{hibernate_after, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{hibernate_after => validate_option(hibernate_after, Value)}, RecordCB);
+new_ssl_options([{alpn_advertised_protocols, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{alpn_advertised_protocols => validate_option(alpn_advertised_protocols, Value)},
+ RecordCB);
+new_ssl_options([{alpn_preferred_protocols, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{alpn_preferred_protocols => validate_option(alpn_preferred_protocols, Value)},
+ RecordCB);
+new_ssl_options([{next_protocols_advertised, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{next_protocols_advertised => validate_option(next_protocols_advertised, Value)},
+ RecordCB);
+new_ssl_options([{client_preferred_next_protocols, Value} | Rest], #{} = Opts, RecordCB) ->
new_ssl_options(Rest,
- Opts#ssl_options{eccs =
- handle_eccs_option(Value, RecordCB:highest_protocol_version())
+ Opts#{next_protocol_selector =>
+ make_next_protocol_selector(validate_option(client_preferred_next_protocols, Value))},
+ RecordCB);
+new_ssl_options([{log_alert, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{log_level => validate_option(log_alert, Value)}, RecordCB);
+new_ssl_options([{log_level, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{log_level => validate_option(log_level, Value)}, RecordCB);
+new_ssl_options([{server_name_indication, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{server_name_indication => validate_option(server_name_indication, Value)}, RecordCB);
+new_ssl_options([{honor_cipher_order, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{honor_cipher_order => validate_option(honor_cipher_order, Value)}, RecordCB);
+new_ssl_options([{honor_ecc_order, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#{honor_ecc_order => validate_option(honor_ecc_order, Value)}, RecordCB);
+new_ssl_options([{eccs, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest,
+ Opts#{eccs => handle_eccs_option(Value, RecordCB:highest_protocol_version())
},
RecordCB);
-new_ssl_options([{supported_groups, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+new_ssl_options([{supported_groups, Value} | Rest], #{} = Opts, RecordCB) ->
new_ssl_options(Rest,
- Opts#ssl_options{supported_groups =
- handle_supported_groups_option(Value, RecordCB:highest_protocol_version())
+ Opts#{supported_groups =>
+ handle_supported_groups_option(Value, RecordCB:highest_protocol_version())
},
RecordCB);
-new_ssl_options([{signature_algs, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest,
- Opts#ssl_options{signature_algs =
- handle_hashsigns_option(Value,
- tls_version(RecordCB:highest_protocol_version()))},
+new_ssl_options([{signature_algs, Value} | Rest], #{} = Opts, RecordCB) ->
+ new_ssl_options(Rest,
+ Opts#{signature_algs =>
+ handle_hashsigns_option(Value,
+ tls_version(RecordCB:highest_protocol_version()))},
RecordCB);
-new_ssl_options([{signature_algs_cert, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+new_ssl_options([{signature_algs_cert, Value} | Rest], #{} = Opts, RecordCB) ->
new_ssl_options(
Rest,
- Opts#ssl_options{signature_algs_cert =
- handle_signature_algorithms_option(
- Value,
- tls_version(RecordCB:highest_protocol_version()))},
+ Opts#{signature_algs_cert =>
+ handle_signature_algorithms_option(
+ Value,
+ tls_version(RecordCB:highest_protocol_version()))},
RecordCB);
-new_ssl_options([{protocol, dtls = Value} | Rest], #ssl_options{} = Opts, dtls_record = RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{protocol = Value}, RecordCB);
-new_ssl_options([{protocol, tls = Value} | Rest], #ssl_options{} = Opts, tls_record = RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{protocol = Value}, RecordCB);
-new_ssl_options([{Key, Value} | _Rest], #ssl_options{}, _) ->
+new_ssl_options([{protocol, dtls = Value} | Rest], #{} = Opts, dtls_record = RecordCB) ->
+ new_ssl_options(Rest, Opts#{protocol => Value}, RecordCB);
+new_ssl_options([{protocol, tls = Value} | Rest], #{} = Opts, tls_record = RecordCB) ->
+ new_ssl_options(Rest, Opts#{protocol => Value}, RecordCB);
+new_ssl_options([{Key, Value} | _Rest], #{}, _) ->
throw({error, {options, {Key, Value}}}).
@@ -2433,3 +2486,10 @@ add_filter(undefined, Filters) ->
Filters;
add_filter(Filter, Filters) ->
[Filter | Filters].
+
+%% Convert the record #ssl_options{} into a map for internal usage
+options_to_map(Options) ->
+ Fields = record_info(fields, ssl_options),
+ [_Tag| Values] = tuple_to_list(Options),
+ L = lists:zip(Fields, Values),
+ maps:from_list(L).
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index 1e6dab9276..7d1e80c1cc 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -28,16 +28,20 @@
-export([init/2]).
-init(SslOpts, Role) ->
+init(#{erl_dist := ErlDist,
+ key := Key,
+ keyfile := KeyFile,
+ password := Password,
+ dh := DH,
+ dhfile := DHFile} = SslOpts, Role) ->
- init_manager_name(SslOpts#ssl_options.erl_dist),
+ init_manager_name(ErlDist),
{ok, #{pem_cache := PemCache} = Config}
= init_certificates(SslOpts, Role),
PrivateKey =
- init_private_key(PemCache, SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
- SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(PemCache, SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
+ init_private_key(PemCache, Key, KeyFile, Password, Role),
+ DHParams = init_diffie_hellman(PemCache, DH, DHFile, Role),
{ok, Config#{private_key => PrivateKey, dh_params => DHParams}}.
init_manager_name(false) ->
@@ -47,12 +51,12 @@ init_manager_name(true) ->
put(ssl_manager, ssl_manager:name(dist)),
put(ssl_pem_cache, ssl_pem_cache:name(dist)).
-init_certificates(#ssl_options{cacerts = CaCerts,
- cacertfile = CACertFile,
- certfile = CertFile,
- cert = Cert,
- crl_cache = CRLCache
- }, Role) ->
+init_certificates(#{cacerts := CaCerts,
+ cacertfile := CACertFile,
+ certfile := CertFile,
+ cert := Cert,
+ crl_cache := CRLCache
+ }, Role) ->
{ok, Config} =
try
Certs = case CaCerts of
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 2483509228..6789c2c23f 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -80,7 +80,7 @@
-spec connect(tls_connection | dtls_connection,
ssl:host(), inet:port_number(),
port() | {tuple(), port()}, %% TLS | DTLS
- {#ssl_options{}, #socket_options{},
+ {ssl_options(), #socket_options{},
%% Tracker only needed on server side
undefined},
pid(), tuple(), timeout()) ->
@@ -98,7 +98,7 @@ connect(Connection, Host, Port, Socket, Options, User, CbInfo, Timeout) ->
%%--------------------------------------------------------------------
-spec handshake(tls_connection | dtls_connection,
inet:port_number(), port(),
- {#ssl_options{}, #socket_options{}, undefined | pid()},
+ {ssl_options(), #socket_options{}, undefined | pid()},
pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
@@ -130,7 +130,7 @@ handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) ->
end.
%%--------------------------------------------------------------------
--spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}}, timeout()) ->
+-spec handshake(#sslsocket{}, {ssl_options(),#socket_options{}}, timeout()) ->
{ok, #sslsocket{}} | {ok, #sslsocket{}, map()} | {error, reason()}.
%%
%% Description: Starts ssl handshake with some new options
@@ -331,7 +331,7 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
handle_own_alert(Alert0, _, StateName,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
- ssl_options = SslOpts} = State) ->
+ ssl_options = #{log_level := LogLevel}} = State) ->
try %% Try to tell the other side
send_alert(Alert0, StateName, State)
catch _:_ -> %% Can crash if we are in a uninitialized state
@@ -339,7 +339,7 @@ handle_own_alert(Alert0, _, StateName,
end,
try %% Try to tell the local user
Alert = Alert0#alert{role = Role},
- log_alert(SslOpts#ssl_options.log_level, Role, Connection:protocol_name(), StateName, Alert),
+ log_alert(LogLevel, Role, Connection:protocol_name(), StateName, Alert),
handle_normal_shutdown(Alert,StateName, State)
catch _:_ ->
ok
@@ -376,13 +376,13 @@ handle_alert(#alert{level = ?FATAL} = Alert0, StateName,
transport_cb = Transport,
protocol_cb = Connection},
connection_env = #connection_env{user_application = {_Mon, Pid}},
- ssl_options = SslOpts,
+ ssl_options = #{log_level := LogLevel},
start_or_recv_from = From,
session = Session,
socket_options = Opts} = State) ->
invalidate_session(Role, Host, Port, Session),
Alert = Alert0#alert{role = opposite_role(Role)},
- log_alert(SslOpts#ssl_options.log_level, Role, Connection:protocol_name(),
+ log_alert(LogLevel, Role, Connection:protocol_name(),
StateName, Alert),
Pids = Connection:pids(State),
alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, StateName, Connection),
@@ -399,9 +399,9 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert0,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
handshake_env = #handshake_env{renegotiation = {true, internal}},
- ssl_options = SslOpts} = State) ->
+ ssl_options = #{log_level := LogLevel}} = State) ->
Alert = Alert0#alert{role = opposite_role(Role)},
- log_alert(SslOpts#ssl_options.log_level, Role,
+ log_alert(LogLevel, Role,
Connection:protocol_name(), StateName, Alert),
handle_normal_shutdown(Alert, StateName, State),
{stop,{shutdown, peer_close}, State};
@@ -410,9 +410,9 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv,
- ssl_options = SslOpts
+ ssl_options = #{log_level := LogLevel}
} = State0) ->
- log_alert(SslOpts#ssl_options.log_level, Role,
+ log_alert(LogLevel, Role,
Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
gen_statem:reply(From, {error, renegotiation_rejected}),
State = Connection:reinit_handshake_data(State0),
@@ -422,9 +422,9 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv,
- ssl_options = SslOpts
+ ssl_options = #{log_level := LogLevel}
} = State0) ->
- log_alert(SslOpts#ssl_options.log_level, Role,
+ log_alert(LogLevel, Role,
Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
gen_statem:reply(From, {error, renegotiation_rejected}),
%% Go back to connection!
@@ -435,8 +435,8 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
handle_alert(#alert{level = ?WARNING} = Alert, StateName,
#state{static_env = #static_env{role = Role,
protocol_cb = Connection},
- ssl_options = SslOpts} = State) ->
- log_alert(SslOpts#ssl_options.log_level, Role,
+ ssl_options = #{log_level := LogLevel}} = State) ->
+ log_alert(LogLevel, Role,
Connection:protocol_name(), StateName,
Alert#alert{role = opposite_role(Role)}),
Connection:next_event(StateName, no_record, State).
@@ -773,7 +773,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
end.
%%--------------------------------------------------------------------
--spec ssl_config(#ssl_options{}, client | server, #state{}) -> #state{}.
+-spec ssl_config(ssl_options(), client | server, #state{}) -> #state{}.
%%--------------------------------------------------------------------
ssl_config(Opts, Role, #state{static_env = InitStatEnv0,
handshake_env = HsEnv,
@@ -870,7 +870,7 @@ user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
#state{static_env = #static_env{role = Role},
handshake_env = #handshake_env{hello = Hello},
ssl_options = Options0} = State0, _Connection) ->
- Options = ssl:handle_options(NewOptions, Options0#ssl_options{handshake = full}),
+ Options = ssl:handle_options(NewOptions, Options0#{handshake => full}),
State = ssl_config(Options, Role, State0),
{next_state, hello, State#state{start_or_recv_from = From},
[{next_event, internal, Hello}, {{timeout, handshake}, Timeout, close}]};
@@ -962,21 +962,21 @@ certify(info, Msg, State, _) ->
certify(internal, #certificate{asn1_certificates = []},
#state{static_env = #static_env{role = server},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #ssl_options{verify = verify_peer,
- fail_if_no_peer_cert = true}} =
+ ssl_options = #{verify := verify_peer,
+ fail_if_no_peer_cert := true}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE),
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{verify = verify_peer,
- fail_if_no_peer_cert = false}} =
+ ssl_options = #{verify := verify_peer,
+ fail_if_no_peer_cert := false}} =
State0, Connection) ->
Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false});
certify(internal, #certificate{},
#state{static_env = #static_env{role = server},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #ssl_options{verify = verify_none}} =
+ ssl_options = #{verify := verify_none}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate),
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
@@ -1067,7 +1067,7 @@ certify(internal, #certificate_request{} = CertRequest,
handshake_env = HsEnv,
connection_env = #connection_env{negotiated_version = Version},
session = #session{own_certificate = Cert},
- ssl_options = #ssl_options{signature_algs = SupportedHashSigns}} = State, Connection) ->
+ ssl_options = #{signature_algs := SupportedHashSigns}} = State, Connection) ->
case ssl_handshake:select_hashsign(CertRequest, Cert,
SupportedHashSigns, ssl:tls_version(Version)) of
#alert {} = Alert ->
@@ -1085,7 +1085,7 @@ certify(internal, #server_hello_done{},
handshake_env = #handshake_env{kex_algorithm = KexAlg,
premaster_secret = undefined,
server_psk_identity = PSKIdentity} = HsEnv,
- ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection)
+ ssl_options = #{user_lookup_fun := PSKLookup}} = State0, Connection)
when KexAlg == psk ->
case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup) of
#alert{} = Alert ->
@@ -1103,7 +1103,7 @@ certify(internal, #server_hello_done{},
premaster_secret = undefined,
server_psk_identity = PSKIdentity} = HsEnv,
session = #session{master_secret = undefined},
- ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection)
+ ssl_options = #{user_lookup_fun := PSKLookup}} = State0, Connection)
when KexAlg == rsa_psk ->
Rand = ssl_cipher:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2),
RSAPremasterSecret = <<?BYTE(Major), ?BYTE(Minor), Rand/binary>>,
@@ -1152,7 +1152,7 @@ certify(internal, #server_hello_done{},
certify(internal = Type, #client_key_exchange{} = Msg,
#state{static_env = #static_env{role = server},
client_certificate_requested = true,
- ssl_options = #ssl_options{fail_if_no_peer_cert = true}} = State,
+ ssl_options = #{fail_if_no_peer_cert := true}} = State,
Connection) ->
%% We expect a certificate here
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection);
@@ -1297,7 +1297,7 @@ connection(cast, {internal_renegotiate, WriteState}, #state{static_env = #static
Connection:renegotiate(State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, internal}},
connection_states = ConnectionStates#{current_write => WriteState}}, []);
connection(cast, {dist_handshake_complete, DHandle},
- #state{ssl_options = #ssl_options{erl_dist = true},
+ #state{ssl_options = #{erl_dist := true},
connection_env = CEnv,
socket_options = SockOpts} = State0, Connection) ->
process_flag(priority, normal),
@@ -1506,7 +1506,7 @@ handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_e
handle_info({'DOWN', MonitorRef, _, _, Reason}, _,
#state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}},
- ssl_options = #ssl_options{erl_dist = true}}) ->
+ ssl_options = #{erl_dist := true}}) ->
{stop, {shutdown, Reason}};
handle_info({'DOWN', MonitorRef, _, _, _}, _,
#state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}}}) ->
@@ -1572,7 +1572,7 @@ terminate(Reason, connection, #state{static_env = #static_env{
transport_cb = Transport,
socket = Socket},
connection_states = ConnectionStates,
- ssl_options = #ssl_options{padding_check = Check}
+ ssl_options = #{padding_check := Check}
} = State) ->
handle_trusted_certs_db(State),
Alert = terminate_alert(Reason),
@@ -1590,13 +1590,13 @@ format_status(normal, [_, StateName, State]) ->
[{data, [{"State", {StateName, State}}]}];
format_status(terminate, [_, StateName, State]) ->
SslOptions = (State#state.ssl_options),
- NewOptions = SslOptions#ssl_options{password = ?SECRET_PRINTOUT,
- cert = ?SECRET_PRINTOUT,
- cacerts = ?SECRET_PRINTOUT,
- key = ?SECRET_PRINTOUT,
- dh = ?SECRET_PRINTOUT,
- psk_identity = ?SECRET_PRINTOUT,
- srp_identity = ?SECRET_PRINTOUT},
+ NewOptions = SslOptions#{password => ?SECRET_PRINTOUT,
+ cert => ?SECRET_PRINTOUT,
+ cacerts => ?SECRET_PRINTOUT,
+ key => ?SECRET_PRINTOUT,
+ dh => ?SECRET_PRINTOUT,
+ psk_identity => ?SECRET_PRINTOUT,
+ srp_identity => ?SECRET_PRINTOUT},
[{data, [{"State", {StateName, State#state{connection_states = ?SECRET_PRINTOUT,
protocol_buffers = ?SECRET_PRINTOUT,
user_data_buffer = ?SECRET_PRINTOUT,
@@ -1651,7 +1651,7 @@ do_server_hello(Type, #{next_protocol_negotiation := NextProtocols} =
handshake_env = HsEnv,
session = #session{session_id = SessId},
connection_states = ConnectionStates0,
- ssl_options = #ssl_options{versions = [HighestVersion|_]}}
+ ssl_options = #{versions := [HighestVersion|_]}}
= State0, Connection) when is_atom(Type) ->
%% TLS 1.3 - Section 4.1.3
%% Override server random values for TLS 1.3 downgrade protection mechanism.
@@ -1885,7 +1885,7 @@ certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientP
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_psk_identity{} = ClientKey,
#state{ssl_options =
- #ssl_options{user_lookup_fun = PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
@@ -1893,7 +1893,7 @@ certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
kex_keys = {_, ServerDhPrivateKey}},
ssl_options =
- #ssl_options{user_lookup_fun = PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}} = State0,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup),
@@ -1901,7 +1901,7 @@ certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{kex_keys = ServerEcDhPrivateKey},
ssl_options =
- #ssl_options{user_lookup_fun = PSKLookup}} = State,
+ #{user_lookup_fun := PSKLookup}} = State,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup),
@@ -1909,7 +1909,7 @@ certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
#state{connection_env = #connection_env{private_key = Key},
ssl_options =
- #ssl_options{user_lookup_fun = PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
@@ -1995,10 +1995,10 @@ key_exchange(#state{static_env = #static_env{role = server},
State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}};
key_exchange(#state{static_env = #static_env{role = server},
handshake_env = #handshake_env{kex_algorithm = psk},
- ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
+ ssl_options = #{psk_identity := undefined}} = State, _) ->
State;
key_exchange(#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{psk_identity = PskIdentityHint},
+ ssl_options = #{psk_identity := PskIdentityHint},
handshake_env = #handshake_env{kex_algorithm = psk,
hashsign_algorithm = HashSignAlgo},
connection_env = #connection_env{negotiated_version = Version,
@@ -2015,7 +2015,7 @@ key_exchange(#state{static_env = #static_env{role = server},
PrivateKey}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{psk_identity = PskIdentityHint},
+ ssl_options = #{psk_identity := PskIdentityHint},
handshake_env = #handshake_env{kex_algorithm = dhe_psk,
diffie_hellman_params = #'DHParameter'{} = Params,
hashsign_algorithm = HashSignAlgo},
@@ -2037,7 +2037,7 @@ key_exchange(#state{static_env = #static_env{role = server},
#state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
State#state{handshake_env = HsEnv#handshake_env{kex_keys = DHKeys}};
key_exchange(#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{psk_identity = PskIdentityHint},
+ ssl_options = #{psk_identity := PskIdentityHint},
handshake_env = #handshake_env{kex_algorithm = ecdhe_psk,
hashsign_algorithm = HashSignAlgo},
connection_env = #connection_env{negotiated_version = Version,
@@ -2060,10 +2060,10 @@ key_exchange(#state{static_env = #static_env{role = server},
State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}};
key_exchange(#state{static_env = #static_env{role = server},
handshake_env = #handshake_env{kex_algorithm = rsa_psk},
- ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
+ ssl_options = #{psk_identity := undefined}} = State, _) ->
State;
key_exchange(#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{psk_identity = PskIdentityHint},
+ ssl_options = #{psk_identity := PskIdentityHint},
handshake_env = #handshake_env{kex_algorithm = rsa_psk,
hashsign_algorithm = HashSignAlgo},
connection_env = #connection_env{negotiated_version = Version,
@@ -2081,7 +2081,7 @@ key_exchange(#state{static_env = #static_env{role = server},
PrivateKey}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = server},
- ssl_options = #ssl_options{user_lookup_fun = LookupFun},
+ ssl_options = #{user_lookup_fun := LookupFun},
handshake_env = #handshake_env{kex_algorithm = KexAlg,
hashsign_algorithm = HashSignAlgo},
connection_env = #connection_env{negotiated_version = Version,
@@ -2146,28 +2146,28 @@ key_exchange(#state{static_env = #static_env{role = client},
key_exchange(#state{static_env = #static_env{role = client},
handshake_env = #handshake_env{kex_algorithm = psk},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = SslOpts} = State0, Connection) ->
+ ssl_options = #{psk_identity := PSKIdentity}} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
- {psk, SslOpts#ssl_options.psk_identity}),
+ {psk, PSKIdentity}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = client},
handshake_env = #handshake_env{kex_algorithm = dhe_psk,
kex_keys = {DhPubKey, _}},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = SslOpts} = State0, Connection) ->
+ ssl_options = #{psk_identity := PSKIdentity}} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{dhe_psk,
- SslOpts#ssl_options.psk_identity, DhPubKey}),
+ PSKIdentity, DhPubKey}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = client},
handshake_env = #handshake_env{kex_algorithm = ecdhe_psk,
kex_keys = ECDHKeys},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = SslOpts} = State0, Connection) ->
+ ssl_options = #{psk_identity := PSKIdentity}} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{ecdhe_psk,
- SslOpts#ssl_options.psk_identity, ECDHKeys}),
+ PSKIdentity, ECDHKeys}),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = client},
@@ -2175,9 +2175,9 @@ key_exchange(#state{static_env = #static_env{role = client},
public_key_info = PublicKeyInfo,
premaster_secret = PremasterSecret},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = SslOpts}
+ ssl_options = #{psk_identity := PSKIdentity}}
= State0, Connection) ->
- Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity,
+ Msg = rsa_psk_key_exchange(ssl:tls_version(Version), PSKIdentity,
PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
key_exchange(#state{static_env = #static_env{role = client},
@@ -2239,8 +2239,8 @@ request_client_cert(#state{handshake_env = #handshake_env{kex_algorithm = Alg}}
request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle,
cert_db_ref = CertDbRef},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #ssl_options{verify = verify_peer,
- signature_algs = SupportedHashSigns},
+ ssl_options = #{verify := verify_peer,
+ signature_algs := SupportedHashSigns},
connection_states = ConnectionStates0} = State0, Connection) ->
#{security_parameters :=
#security_parameters{cipher_suite = CipherSuite}} =
@@ -2253,7 +2253,7 @@ request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle,
State = Connection:queue_handshake(Msg, State0),
State#state{client_certificate_requested = true};
-request_client_cert(#state{ssl_options = #ssl_options{verify = verify_none}} =
+request_client_cert(#state{ssl_options = #{verify := verify_none}} =
State, _) ->
State.
@@ -2353,7 +2353,7 @@ calculate_secret(#server_psk_params{
calculate_secret(#server_dhe_psk_params{
dh_params = #server_dh_params{dh_p = Prime, dh_g = Base}} = ServerKey,
#state{handshake_env = HsEnv,
- ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
+ ssl_options = #{user_lookup_fun := PSKLookup}} =
State, Connection) ->
Keys = {_, PrivateDhKey} =
crypto:generate_key(dh, [Prime, Base]),
@@ -2363,7 +2363,7 @@ calculate_secret(#server_dhe_psk_params{
calculate_secret(#server_ecdhe_psk_params{
dh_params = #server_ecdh_params{curve = ECCurve}} = ServerKey,
- #state{ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
+ #state{ssl_options = #{user_lookup_fun := PSKLookup}} =
#state{handshake_env = HsEnv,
session = Session} = State, Connection) ->
ECDHKeys = public_key:generate_key(ECCurve),
@@ -2376,7 +2376,7 @@ calculate_secret(#server_ecdhe_psk_params{
calculate_secret(#server_srp_params{srp_n = Prime, srp_g = Generator} = ServerKey,
#state{handshake_env = HsEnv,
- ssl_options = #ssl_options{srp_identity = SRPId}} = State,
+ ssl_options = #{srp_identity := SRPId}} = State,
Connection) ->
Keys = generate_srp_client_keys(Generator, Prime, 0),
PremasterSecret = ssl_handshake:premaster_secret(ServerKey, Keys, SRPId),
@@ -2610,7 +2610,7 @@ set_socket_opts(ConnectionCb, Transport, Socket, [Opt | Opts], SockOpts, Other)
hibernate_after(connection = StateName,
- #state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}} = State,
+ #state{ssl_options= #{hibernate_after := HibernateAfter}} = State,
Actions) ->
{next_state, StateName, State, [{timeout, HibernateAfter, hibernate} | Actions]};
hibernate_after(StateName, State, Actions) ->
@@ -2626,12 +2626,12 @@ terminate_alert(_) ->
?ALERT_REC(?FATAL, ?INTERNAL_ERROR).
handle_trusted_certs_db(#state{ssl_options =
- #ssl_options{cacertfile = <<>>, cacerts = []}}) ->
+ #{cacertfile := <<>>, cacerts := []}}) ->
%% No trusted certs specified
ok;
handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref,
cert_db = CertDb},
- ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
+ ssl_options = #{cacertfile := <<>>}}) when CertDb =/= undefined ->
%% Certs provided as DER directly can not be shared
%% with other connections and it is safe to delete them when the connection ends.
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
@@ -2641,7 +2641,7 @@ handle_trusted_certs_db(#state{static_env = #static_env{file_ref_db = undefined}
ok;
handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref,
file_ref_db = RefDb},
- ssl_options = #ssl_options{cacertfile = File}}) ->
+ ssl_options = #{cacertfile := File}}) ->
case ssl_pkix_db:ref_count(Ref, RefDb, -1) of
0 ->
ssl_manager:clean_cert_db(Ref, File);
@@ -2678,11 +2678,11 @@ session_handle_params(#server_ecdh_params{curve = ECCurve}, Session) ->
session_handle_params(_, Session) ->
Session.
-handle_session(Role = server, #ssl_options{reuse_sessions = true} = SslOpts,
+handle_session(Role = server, #{reuse_sessions := true} = SslOpts,
Host, Port, Session0) ->
register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, true);
-handle_session(Role = client, #ssl_options{verify = verify_peer,
- reuse_sessions = Reuse} = SslOpts,
+handle_session(Role = client, #{verify := verify_peer,
+ reuse_sessions := Reuse} = SslOpts,
Host, Port, Session0) when Reuse =/= false ->
register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, reg_type(Reuse));
handle_session(server, _, Host, Port, Session) ->
@@ -2709,7 +2709,7 @@ register_session(server, _, Port, #session{is_resumable = new} = Session0, _) ->
register_session(_, _, _, Session, _) ->
Session. %% Already registered
-host_id(client, _Host, #ssl_options{server_name_indication = Hostname}) when is_list(Hostname) ->
+host_id(client, _Host, #{server_name_indication := Hostname}) when is_list(Hostname) ->
Hostname;
host_id(_, Host, _) ->
Host.
@@ -2760,28 +2760,27 @@ negotiated_hashsign(HashSign = {_, _}, _, _, _) ->
HashSign.
ssl_options_list(SslOptions) ->
- Fileds = record_info(fields, ssl_options),
- Values = tl(tuple_to_list(SslOptions)),
- ssl_options_list(Fileds, Values, []).
+ L = maps:to_list(SslOptions),
+ ssl_options_list(L, []).
-ssl_options_list([],[], Acc) ->
+ssl_options_list([], Acc) ->
lists:reverse(Acc);
%% Skip internal options, only return user options
-ssl_options_list([protocol | Keys], [_ | Values], Acc) ->
- ssl_options_list(Keys, Values, Acc);
-ssl_options_list([erl_dist | Keys], [_ | Values], Acc) ->
- ssl_options_list(Keys, Values, Acc);
-ssl_options_list([renegotiate_at | Keys], [_ | Values], Acc) ->
- ssl_options_list(Keys, Values, Acc);
-ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
- ssl_options_list(Keys, Values,
+ssl_options_list([{protocol, _}| T], Acc) ->
+ ssl_options_list(T, Acc);
+ssl_options_list([{erl_dist, _}|T], Acc) ->
+ ssl_options_list(T, Acc);
+ssl_options_list([{renegotiate_at, _}|T], Acc) ->
+ ssl_options_list(T, Acc);
+ssl_options_list([{ciphers = Key, Value}|T], Acc) ->
+ ssl_options_list(T,
[{Key, lists:map(
fun(Suite) ->
ssl_cipher_format:suite_bin_to_map(Suite)
end, Value)}
| Acc]);
-ssl_options_list([Key | Keys], [Value | Values], Acc) ->
- ssl_options_list(Keys, Values, [{Key, Value} | Acc]).
+ssl_options_list([{Key, Value}|T], Acc) ->
+ ssl_options_list(T, [{Key, Value} | Acc]).
handle_active_option(false, connection = StateName, To, Reply, State) ->
hibernate_after(StateName, State, [{reply, To, Reply}]);
@@ -3029,12 +3028,13 @@ handle_sni_extension(#sni{hostname = Hostname}, #state{static_env = #static_env{
}
end.
-update_ssl_options_from_sni(OrigSSLOptions, SNIHostname) ->
+update_ssl_options_from_sni(#{sni_fun := SNIFun,
+ sni_hosts := SNIHosts} = OrigSSLOptions, SNIHostname) ->
SSLOption =
- case OrigSSLOptions#ssl_options.sni_fun of
+ case SNIFun of
undefined ->
proplists:get_value(SNIHostname,
- OrigSSLOptions#ssl_options.sni_hosts);
+ SNIHosts);
SNIFun ->
SNIFun(SNIHostname)
end,
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 844368c761..be94fd05bb 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -92,7 +92,7 @@
-record(state, {
static_env :: #static_env{},
connection_env :: #connection_env{} | secret_printout(),
- ssl_options :: #ssl_options{},
+ ssl_options :: ssl_options(),
socket_options :: #socket_options{},
%% Hanshake %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index bd2efa9fbb..1c8a2ca452 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -336,25 +336,30 @@ next_protocol(SelectedProtocol) ->
%% Handle handshake messages
%%====================================================================
%%--------------------------------------------------------------------
--spec certify(#certificate{}, db_handle(), certdb_ref(), #ssl_options{}, term(),
+-spec certify(#certificate{}, db_handle(), certdb_ref(), ssl_options(), term(),
client | server, inet:hostname() | inet:ip_address()) -> {der_cert(), public_key_info()} | #alert{}.
%%
%% Description: Handles a certificate handshake message
%%--------------------------------------------------------------------
certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
- Opts, CRLDbHandle, Role, Host) ->
-
- ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
+ #{server_name_indication := ServerNameIndication,
+ partial_chain := PartialChain,
+ verify_fun := VerifyFun,
+ customize_hostname_check := CustomizeHostnameCheck,
+ crl_check := CrlCheck,
+ depth := Depth} = Opts, CRLDbHandle, Role, Host) ->
+
+ ServerName = server_name(ServerNameIndication, Host, Role),
[PeerCert | ChainCerts ] = ASN1Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
- Opts#ssl_options.partial_chain),
- ValidationFunAndState = validation_fun_and_state(Opts#ssl_options.verify_fun, Role,
+ PartialChain),
+ ValidationFunAndState = validation_fun_and_state(VerifyFun, Role,
CertDbHandle, CertDbRef, ServerName,
- Opts#ssl_options.customize_hostname_check,
- Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
- Options = [{max_path_length, Opts#ssl_options.depth},
+ CustomizeHostnameCheck,
+ CrlCheck, CRLDbHandle, CertPath),
+ Options = [{max_path_length, Depth},
{verify_fun, ValidationFunAndState}],
case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of
{ok, {PublicKeyInfo,_}} ->
@@ -945,7 +950,7 @@ prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) ->
select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, Port, #session{ecc = ECCCurve0} =
Session, Version,
- #ssl_options{ciphers = UserSuites, honor_cipher_order = HonorCipherOrder} = SslOpts,
+ #{ciphers := UserSuites, honor_cipher_order := HonorCipherOrder} = SslOpts,
Cache, CacheCb, Cert) ->
{SessionId, Resumed} = ssl_session:server_id(Port, SuggestedSessionId,
SslOpts, Cert,
@@ -1071,27 +1076,29 @@ client_hello_extensions(Version, CipherSuites, SslOpts, ConnectionStates, Renego
add_tls12_extensions(_Version,
- SslOpts,
+ #{alpn_advertised_protocols := AlpnAdvertisedProtocols,
+ next_protocol_selector := NextProtocolSelector,
+ server_name_indication := ServerNameIndication} = SslOpts,
ConnectionStates,
Renegotiation) ->
SRP = srp_user(SslOpts),
#{renegotiation_info => renegotiation_info(tls_record, client,
ConnectionStates, Renegotiation),
srp => SRP,
- alpn => encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
+ alpn => encode_alpn(AlpnAdvertisedProtocols, Renegotiation),
next_protocol_negotiation =>
- encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
+ encode_client_protocol_negotiation(NextProtocolSelector,
Renegotiation),
- sni => sni(SslOpts#ssl_options.server_name_indication)
+ sni => sni(ServerNameIndication)
}.
add_common_extensions({3,4},
HelloExtensions,
_CipherSuites,
- #ssl_options{eccs = SupportedECCs,
- supported_groups = Groups,
- signature_algs = SignatureSchemes}) ->
+ #{eccs := SupportedECCs,
+ supported_groups := Groups,
+ signature_algs := SignatureSchemes}) ->
{EcPointFormats, _} =
client_ecc_extensions(SupportedECCs),
HelloExtensions#{ec_point_formats => EcPointFormats,
@@ -1101,8 +1108,8 @@ add_common_extensions({3,4},
add_common_extensions(Version,
HelloExtensions,
CipherSuites,
- #ssl_options{eccs = SupportedECCs,
- signature_algs = SupportedHashSigns}) ->
+ #{eccs := SupportedECCs,
+ signature_algs := SupportedHashSigns}) ->
{EcPointFormats, EllipticCurves} =
case advertises_ec_ciphers(
@@ -1120,8 +1127,8 @@ add_common_extensions(Version,
maybe_add_tls13_extensions({3,4},
HelloExtensions0,
- #ssl_options{signature_algs_cert = SignatureSchemes,
- versions = SupportedVersions},
+ #{signature_algs_cert := SignatureSchemes,
+ versions := SupportedVersions},
KeyShare) ->
HelloExtensions =
HelloExtensions0#{client_hello_versions =>
@@ -1223,8 +1230,8 @@ signature_algs_cert(SignatureSchemes) ->
handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
Exts, Version,
- #ssl_options{secure_renegotiate = SecureRenegotation,
- alpn_preferred_protocols = ALPNPreferredProtocols} = Opts,
+ #{secure_renegotiate := SecureRenegotation,
+ alpn_preferred_protocols := ALPNPreferredProtocols} = Opts,
#session{cipher_suite = NegotiatedCipherSuite,
compression_method = Compression} = Session0,
ConnectionStates0, Renegotiation) ->
@@ -1259,8 +1266,8 @@ handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
Exts, Version,
- #ssl_options{secure_renegotiate = SecureRenegotation,
- next_protocol_selector = NextProtoSelector},
+ #{secure_renegotiate := SecureRenegotation,
+ next_protocol_selector := NextProtoSelector},
ConnectionStates0, Renegotiation) ->
ConnectionStates = handle_renegotiation_extension(client, RecordCB, Version,
maps:get(renegotiation_info, Exts, undefined), Random,
@@ -1477,7 +1484,7 @@ select_hashsign_algs(undefined, ?rsaEncryption, _) ->
select_hashsign_algs(undefined, ?'id-dsa', _) ->
{sha, dsa}.
-srp_user(#ssl_options{srp_identity = {UserName, _}}) ->
+srp_user(#{srp_identity := {UserName, _}}) ->
#srp{username = UserName};
srp_user(_) ->
undefined.
@@ -1644,12 +1651,12 @@ handle_path_validation_error({bad_cert, unknown_ca} = Reason, PeerCert, Chain,
Opts, Options, CertDbHandle, CertsDbRef) ->
handle_incomplete_chain(PeerCert, Chain, Opts, Options, CertDbHandle, CertsDbRef, Reason);
handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chain0,
- Opts, Options, CertDbHandle, CertsDbRef) ->
+ #{partial_chain := PartialChain} = Opts, Options, CertDbHandle, CertsDbRef) ->
case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef, Chain0) of
{ok, _, [PeerCert | Chain] = OrdedChain} when Chain =/= Chain0 -> %% Chain appaears to be unorded
{Trusted, Path} = ssl_certificate:trusted_cert_and_path(OrdedChain,
CertDbHandle, CertsDbRef,
- Opts#ssl_options.partial_chain),
+ PartialChain),
case public_key:pkix_path_validation(Trusted, Path, Options) of
{ok, {PublicKeyInfo,_}} ->
{PeerCert, PublicKeyInfo};
@@ -1663,12 +1670,13 @@ handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chai
handle_path_validation_error(Reason, _, _, _, _,_, _) ->
path_validation_alert(Reason).
-handle_incomplete_chain(PeerCert, Chain0, Opts, Options, CertDbHandle, CertsDbRef, PathError0) ->
+handle_incomplete_chain(PeerCert, Chain0,
+ #{partial_chain := PartialChain}, Options, CertDbHandle, CertsDbRef, PathError0) ->
case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef) of
{ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found
{Trusted, Path} = ssl_certificate:trusted_cert_and_path(Chain,
CertDbHandle, CertsDbRef,
- Opts#ssl_options.partial_chain),
+ PartialChain),
case public_key:pkix_path_validation(Trusted, Path, Options) of
{ok, {PublicKeyInfo,_}} ->
{PeerCert, PublicKeyInfo};
@@ -2834,7 +2842,7 @@ handle_next_protocol_on_server(undefined, _Renegotiation, _SslOpts) ->
undefined;
handle_next_protocol_on_server(#next_protocol_negotiation{extension_data = <<>>},
- false, #ssl_options{next_protocols_advertised = Protocols}) ->
+ false, #{next_protocols_advertised := Protocols}) ->
Protocols;
handle_next_protocol_on_server(_Hello, _Renegotiation, _SSLOpts) ->
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 06c3ccae45..fc9f16a189 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -202,7 +202,7 @@
-type gen_fsm_state_return() :: {next_state, state_name(), any()} |
{next_state, state_name(), any(), timeout()} |
{stop, any(), any()}.
--type ssl_options() :: #ssl_options{}.
+-type ssl_options() :: map().
-endif. % -ifdef(ssl_internal).
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 44305c65fe..fd012acd5e 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -48,13 +48,13 @@ is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec client_id({ssl:host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
+-spec client_id({ssl:host(), inet:port_number(), ssl_options()}, db_handle(), atom(),
undefined | binary()) -> binary().
%%
%% Description: Should be called by the client side to get an id
%% for the client hello message.
%%--------------------------------------------------------------------
-client_id({Host, Port, #ssl_options{reuse_session = SessionId}}, Cache, CacheCb, _) when is_binary(SessionId)->
+client_id({Host, Port, #{reuse_session := SessionId}}, Cache, CacheCb, _) when is_binary(SessionId)->
case CacheCb:lookup(Cache, {{Host, Port}, SessionId}) of
undefined ->
<<>>;
@@ -99,7 +99,7 @@ server_id(Port, SuggestedId, Options, Cert, Cache, CacheCb) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-select_session({_, _, #ssl_options{reuse_sessions = Reuse}}, _Cache, _CacheCb, _OwnCert) when Reuse =/= true ->
+select_session({_, _, #{reuse_sessions := Reuse}}, _Cache, _CacheCb, _OwnCert) when Reuse =/= true ->
%% If reuse_sessions == true | save a new session should be created
no_session;
select_session({HostIP, Port, SslOpts}, Cache, CacheCb, OwnCert) ->
@@ -108,7 +108,7 @@ select_session({HostIP, Port, SslOpts}, Cache, CacheCb, OwnCert) ->
select_session([], _, _) ->
no_session;
-select_session(Sessions, #ssl_options{ciphers = Ciphers}, OwnCert) ->
+select_session(Sessions, #{ciphers := Ciphers}, OwnCert) ->
IsNotResumable =
fun(Session) ->
not (resumable(Session#session.is_resumable) andalso
@@ -120,9 +120,9 @@ select_session(Sessions, #ssl_options{ciphers = Ciphers}, OwnCert) ->
[Session | _] -> Session#session.session_id
end.
-is_resumable(_, _, #ssl_options{reuse_sessions = false}, _, _, _, _) ->
+is_resumable(_, _, #{reuse_sessions := false}, _, _, _, _) ->
{false, undefined};
-is_resumable(SuggestedSessionId, Port, #ssl_options{reuse_session = ReuseFun} = Options, Cache,
+is_resumable(SuggestedSessionId, Port, #{reuse_session := ReuseFun} = Options, Cache,
CacheCb, SecondLifeTime, OwnCert) ->
case CacheCb:lookup(Cache, {Port, SuggestedSessionId}) of
#session{cipher_suite = CipherSuite,
@@ -149,8 +149,8 @@ resumable(new) ->
resumable(IsResumable) ->
IsResumable.
-reusable_options(#ssl_options{fail_if_no_peer_cert = true,
- verify = verify_peer}, Session) ->
+reusable_options(#{fail_if_no_peer_cert := true,
+ verify := verify_peer}, Session) ->
(Session#session.peer_certificate =/= undefined);
reusable_options(_,_) ->
true.
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 3998f03519..cf104cd805 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -98,7 +98,7 @@
%%====================================================================
%% Setup
%%====================================================================
-start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
+start_fsm(Role, Host, Port, Socket, {#{erl_dist := false},_, Tracker} = Opts,
User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
@@ -112,7 +112,7 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
Error
end;
-start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} = Opts,
+start_fsm(Role, Host, Port, Socket, {#{erl_dist := true},_, Tracker} = Opts,
User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
@@ -136,10 +136,10 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} =
start_link(Role, Sender, Host, Port, Socket, Options, User, CbInfo) ->
{ok, proc_lib:spawn_link(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]])}.
-init([Role, Sender, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo]) ->
+init([Role, Sender, Host, Port, Socket, {#{erl_dist := ErlDist}, _, _} = Options, User, CbInfo]) ->
process_flag(trap_exit, true),
link(Sender),
- case SslOpts#ssl_options.erl_dist of
+ case ErlDist of
true ->
process_flag(priority, max);
_ ->
@@ -170,7 +170,7 @@ next_record(_, #state{handshake_env =
next_record(_, #state{protocol_buffers =
#protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts},
connection_states = ConnectionStates,
- ssl_options = #ssl_options{padding_check = Check}} = State) ->
+ ssl_options = #{padding_check := Check}} = State) ->
next_record(State, CipherTexts, ConnectionStates, Check);
next_record(connection, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []},
protocol_specific = #{active_n_toggle := true}
@@ -385,12 +385,12 @@ send_handshake(Handshake, State) ->
queue_handshake(Handshake, #state{handshake_env = #handshake_env{tls_handshake_history = Hist0} = HsEnv,
connection_env = #connection_env{negotiated_version = Version},
flight_buffer = Flight0,
- ssl_options = SslOpts,
+ ssl_options = #{log_level := LogLevel},
connection_states = ConnectionStates0} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'handshake', Handshake),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinHandshake),
+ ssl_logger:debug(LogLevel, outbound, 'handshake', Handshake),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinHandshake),
State0#state{connection_states = ConnectionStates,
handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist},
@@ -406,11 +406,11 @@ send_handshake_flight(#state{static_env = #static_env{socket = Socket,
queue_change_cipher(Msg, #state{connection_env = #connection_env{negotiated_version = Version},
flight_buffer = Flight0,
- ssl_options = SslOpts,
+ ssl_options = #{log_level := LogLevel},
connection_states = ConnectionStates0} = State0) ->
{BinChangeCipher, ConnectionStates} =
encode_change_cipher(Msg, Version, ConnectionStates0),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinChangeCipher),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinChangeCipher),
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
@@ -454,12 +454,12 @@ encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
send_alert(Alert, #state{static_env = #static_env{socket = Socket,
transport_cb = Transport},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = SslOpts,
+ ssl_options = #{log_level := LogLevel},
connection_states = ConnectionStates0} = StateData0) ->
{BinMsg, ConnectionStates} =
encode_alert(Alert, Version, ConnectionStates0),
tls_socket:send(Transport, Socket, BinMsg),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinMsg),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinMsg),
StateData0#state{connection_states = ConnectionStates}.
%% If an ALERT sent in the connection state, should cause the TLS
@@ -542,7 +542,8 @@ init({call, From}, {start, Timeout},
session_cache_cb = CacheCb},
handshake_env = #handshake_env{renegotiation = {Renegotiation, _}} = HsEnv,
connection_env = CEnv,
- ssl_options = SslOpts,
+ ssl_options = #{log_level := LogLevel,
+ versions := Versions} = SslOpts,
session = #session{own_certificate = Cert} = Session0,
connection_states = ConnectionStates0
} = State0) ->
@@ -550,13 +551,13 @@ init({call, From}, {start, Timeout},
Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert, KeyShare),
- HelloVersion = tls_record:hello_version(SslOpts#ssl_options.versions),
+ HelloVersion = tls_record:hello_version(Versions),
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
tls_socket:send(Transport, Socket, BinMsg),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'handshake', Hello),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinMsg),
+ ssl_logger:debug(LogLevel, outbound, 'handshake', Hello),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinMsg),
State = State0#state{connection_states = ConnectionStates,
connection_env = CEnv#connection_env{negotiated_version = HelloVersion}, %% Requested version
@@ -592,14 +593,14 @@ error(_, _, _) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
hello(internal, #client_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #ssl_options{handshake = hello},
+ #state{ssl_options = #{handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, Extensions}}]};
hello(internal, #server_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #ssl_options{handshake = hello},
+ #state{ssl_options = #{handshake := hello},
handshake_env = HsEnv,
start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
@@ -982,8 +983,9 @@ code_change(_OldVsn, StateName, State, _) ->
%%--------------------------------------------------------------------
initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
- #ssl_options{beast_mitigation = BeastMitigation,
- erl_dist = IsErlDist} = SSLOptions,
+ #{beast_mitigation := BeastMitigation,
+ erl_dist := IsErlDist,
+ client_renegotiation := ClientRenegotiation} = SSLOptions,
ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
SessionCacheCb = case application:get_env(ssl, session_cb) of
{ok, Cb} when is_atom(Cb) ->
@@ -1017,7 +1019,7 @@ initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trac
handshake_env = #handshake_env{
tls_handshake_history = ssl_handshake:init_handshake_history(),
renegotiation = {false, first},
- allow_renegotiate = SSLOptions#ssl_options.client_renegotiation
+ allow_renegotiate = ClientRenegotiation
},
connection_env = #connection_env{user_application = {UserMonitor, User}},
socket_options = SocketOptions,
@@ -1042,8 +1044,8 @@ initialize_tls_sender(#state{static_env = #static_env{
},
connection_env = #connection_env{negotiated_version = Version},
socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt,
- log_level = LogLevel},
+ ssl_options = #{renegotiate_at := RenegotiateAt,
+ log_level := LogLevel},
connection_states = #{current_write := ConnectionWriteState},
protocol_specific = #{sender := Sender}}) ->
Init = #{current_write => ConnectionWriteState,
@@ -1261,7 +1263,7 @@ unprocessed_events(Events) ->
assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,
- #ssl_options{max_handshake_size = Max}) when
+ #{max_handshake_size := Max}) when
Length =< Max ->
case size(Rest) of
N when N < Length ->
@@ -1295,18 +1297,17 @@ ensure_sender_terminate(_, #state{protocol_specific = #{sender := Sender}}) ->
end,
spawn(Kill).
-maybe_generate_client_shares(#ssl_options{
- versions = [Version|_],
- supported_groups =
- #supported_groups{
- supported_groups = [Group|_]}})
+maybe_generate_client_shares(#{versions := [Version|_],
+ supported_groups :=
+ #supported_groups{
+ supported_groups = [Group|_]}})
when Version =:= {3,4} ->
%% Generate only key_share entry for the most preferred group
ssl_cipher:generate_client_shares([Group]);
maybe_generate_client_shares(_) ->
undefined.
-choose_tls_version(#ssl_options{versions = Versions},
+choose_tls_version(#{versions := Versions},
#client_hello{
extensions = #{client_hello_versions :=
#client_hello_versions{versions = ClientVersions}
@@ -1322,7 +1323,7 @@ choose_tls_version(_, _) ->
'tls_v1.2'.
-effective_version(undefined, #ssl_options{versions = [Version|_]}) ->
+effective_version(undefined, #{versions := [Version|_]}) ->
Version;
effective_version(Version, _) ->
Version.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 37265e0759..203f89a0b8 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -51,17 +51,17 @@
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(ssl:host(), inet:port_number(), ssl_record:connection_states(),
- #ssl_options{}, integer(), atom(), boolean(), der_cert(),
+ ssl_options(), integer(), atom(), boolean(), der_cert(),
#key_share_client_hello{} | undefined) ->
#client_hello{}.
%%
%% Description: Creates a client hello message.
%%--------------------------------------------------------------------
client_hello(Host, Port, ConnectionStates,
- #ssl_options{versions = Versions,
- ciphers = UserSuites,
- fallback = Fallback
- } = SslOpts,
+ #{versions := Versions,
+ ciphers := UserSuites,
+ fallback := Fallback
+ } = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert, KeyShare) ->
Version = tls_record:highest_protocol_version(Versions),
@@ -95,7 +95,7 @@ client_hello(Host, Port, ConnectionStates,
}.
%%--------------------------------------------------------------------
--spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
+-spec hello(#server_hello{} | #client_hello{}, ssl_options(),
ssl_record:connection_states() | {inet:port_number(), #session{}, db_handle(),
atom(), ssl_record:connection_states(),
binary() | undefined, ssl:kex_algo()},
@@ -117,7 +117,7 @@ client_hello(Host, Port, ConnectionStates,
%% values.
hello(#server_hello{server_version = {Major, Minor},
random = <<_:24/binary,Down:8/binary>>},
- #ssl_options{versions = [{M,N}|_]}, _, _)
+ #{versions := [{M,N}|_]}, _, _)
when (M > 3 orelse M =:= 3 andalso N >= 4) andalso %% TLS 1.3 client
(Major =:= 3 andalso Minor =:= 3 andalso %% Negotiating TLS 1.2
Down =:= ?RANDOM_OVERRIDE_TLS12) orelse
@@ -131,7 +131,7 @@ hello(#server_hello{server_version = {Major, Minor},
%% equal to the second value if the ServerHello indicates TLS 1.1 or below.
hello(#server_hello{server_version = {Major, Minor},
random = <<_:24/binary,Down:8/binary>>},
- #ssl_options{versions = [{M,N}|_]}, _, _)
+ #{versions := [{M,N}|_]}, _, _)
when (M =:= 3 andalso N =:= 3) andalso %% TLS 1.2 client
(Major =:= 3 andalso Minor < 3 andalso %% Negotiating TLS 1.1 or prior
Down =:= ?RANDOM_OVERRIDE_TLS11) ->
@@ -156,7 +156,7 @@ hello(#server_hello{server_version = LegacyVersion,
extensions = #{server_hello_selected_version :=
#server_hello_selected_version{selected_version = Version} = HelloExt}
},
- #ssl_options{versions = SupportedVersions} = SslOpt,
+ #{versions := SupportedVersions} = SslOpt,
ConnectionStates0, Renegotiation) ->
%% In TLS 1.3, the TLS server indicates its version using the "supported_versions" extension
%% (Section 4.2.1), and the legacy_version field MUST be set to 0x0303, which is the version
@@ -190,7 +190,7 @@ hello(#server_hello{server_version = Version,
compression_method = Compression,
session_id = SessionId,
extensions = HelloExt},
- #ssl_options{versions = SupportedVersions} = SslOpt,
+ #{versions := SupportedVersions} = SslOpt,
ConnectionStates0, Renegotiation) ->
case tls_record:is_acceptable_version(Version, SupportedVersions) of
true ->
@@ -221,7 +221,7 @@ hello(#client_hello{client_version = _ClientVersion,
extensions = #{client_hello_versions :=
#client_hello_versions{versions = ClientVersions}
}} = Hello,
- #ssl_options{versions = Versions} = SslOpts,
+ #{versions := Versions} = SslOpts,
Info, Renegotiation) ->
try
Version = ssl_handshake:select_supported_version(ClientVersions, Versions),
@@ -233,7 +233,7 @@ hello(#client_hello{client_version = _ClientVersion,
hello(#client_hello{client_version = ClientVersion,
cipher_suites = CipherSuites} = Hello,
- #ssl_options{versions = Versions} = SslOpts,
+ #{versions := Versions} = SslOpts,
Info, Renegotiation) ->
try
Version = ssl_handshake:select_version(tls_record, ClientVersion, Versions),
@@ -269,7 +269,7 @@ encode_handshake(Package, Version) ->
%%--------------------------------------------------------------------
-spec get_tls_handshake(tls_record:tls_version(), binary(), binary() | iolist(),
- #ssl_options{}) ->
+ ssl_options()) ->
{[{tls_handshake(), binary()}], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
@@ -290,10 +290,10 @@ handle_client_hello(Version,
compression_methods = Compressions,
random = Random,
extensions = HelloExt},
- #ssl_options{versions = Versions,
- signature_algs = SupportedHashSigns,
- eccs = SupportedECCs,
- honor_ecc_order = ECCOrder} = SslOpts,
+ #{versions := Versions,
+ signature_algs := SupportedHashSigns,
+ eccs := SupportedECCs,
+ honor_ecc_order := ECCOrder} = SslOpts,
{Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _},
Renegotiation) ->
case tls_record:is_acceptable_version(Version, Versions) of
@@ -404,11 +404,11 @@ enc_handshake(HandshakeMsg, Version) ->
%%--------------------------------------------------------------------
get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>,
- Opts, Acc) ->
+ #{log_level := LogLevel} = Opts, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
try decode_handshake(Version, Type, Body) of
Handshake ->
- ssl_logger:debug(Opts#ssl_options.log_level, inbound, 'handshake', Handshake),
+ ssl_logger:debug(LogLevel, inbound, 'handshake', Handshake),
get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
catch
_:_ ->
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index c29366e717..5f4c0b9a4a 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -336,8 +336,9 @@ decode_handshake(?ENCRYPTED_EXTENSIONS, <<?UINT16(Size), EncExts:Size/binary>>)
extensions = decode_extensions(EncExts, encrypted_extensions)
};
decode_handshake(?NEW_SESSION_TICKET, <<?UINT32(LifeTime), ?UINT32(Age),
- ?BYTE(Nonce), ?UINT16(TicketSize), Ticket:TicketSize/binary,
- BinExts/binary>>) ->
+ ?BYTE(NonceSize), Nonce:NonceSize/binary,
+ ?UINT16(TicketSize), Ticket:TicketSize/binary,
+ ?UINT16(BinExtSize), BinExts:BinExtSize/binary>>) ->
Exts = decode_extensions(BinExts, encrypted_extensions),
#new_session_ticket{ticket_lifetime = LifeTime,
ticket_age_add = Age,
@@ -501,11 +502,11 @@ do_start(#client_hello{cipher_suites = ClientCiphers,
session_id = SessionId,
extensions = Extensions} = _Hello,
#state{connection_states = _ConnectionStates0,
- ssl_options = #ssl_options{ciphers = ServerCiphers,
- signature_algs = ServerSignAlgs,
- supported_groups = ServerGroups0,
- alpn_preferred_protocols = ALPNPreferredProtocols,
- honor_cipher_order = HonorCipherOrder},
+ ssl_options = #{ciphers := ServerCiphers,
+ signature_algs := ServerSignAlgs,
+ supported_groups := ServerGroups0,
+ alpn_preferred_protocols := ALPNPreferredProtocols,
+ honor_cipher_order := HonorCipherOrder},
session = #session{own_certificate = Cert}} = State0) ->
ClientGroups0 = maps:get(elliptic_curves, Extensions, undefined),
ClientGroups = get_supported_groups(ClientGroups0),
@@ -600,8 +601,10 @@ do_start(#server_hello{cipher_suite = SelectedCipherSuite,
handshake_env = #handshake_env{renegotiation = {Renegotiation, _},
tls_handshake_history = _HHistory} = HsEnv,
connection_env = CEnv,
- ssl_options = #ssl_options{ciphers = ClientCiphers,
- supported_groups = ClientGroups0} = SslOpts,
+ ssl_options = #{ciphers := ClientCiphers,
+ supported_groups := ClientGroups0,
+ versions := Versions,
+ log_level := LogLevel} = SslOpts,
session = #session{own_certificate = Cert} = Session0,
connection_states = ConnectionStates0
} = State0) ->
@@ -632,7 +635,7 @@ do_start(#server_hello{cipher_suite = SelectedCipherSuite,
Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert, ClientKeyShare),
- HelloVersion = tls_record:hello_version(SslOpts#ssl_options.versions),
+ HelloVersion = tls_record:hello_version(Versions),
%% Update state
State1 = update_start_state(State0,
@@ -648,8 +651,8 @@ do_start(#server_hello{cipher_suite = SelectedCipherSuite,
{BinMsg, ConnectionStates, Handshake} =
tls_connection:encode_handshake(Hello, HelloVersion, ConnectionStates0, HHistory),
tls_socket:send(Transport, Socket, BinMsg),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'handshake', Hello),
- ssl_logger:debug(SslOpts#ssl_options.log_level, outbound, 'record', BinMsg),
+ ssl_logger:debug(LogLevel, outbound, 'handshake', Hello),
+ ssl_logger:debug(LogLevel, outbound, 'record', BinMsg),
State = State2#state{
connection_states = ConnectionStates,
@@ -673,7 +676,7 @@ do_negotiated(start_handshake,
ecc = SelectedGroup,
sign_alg = SignatureScheme,
dh_public_value = ClientPublicKey},
- ssl_options = #ssl_options{} = SslOpts,
+ ssl_options = #{} = SslOpts,
key_share = KeyShare,
handshake_env = #handshake_env{tls_handshake_history = _HHistory0},
connection_env = #connection_env{private_key = CertPrivateKey},
@@ -831,8 +834,8 @@ do_wait_sh(#server_hello{cipher_suite = SelectedCipherSuite,
session_id = SessionId,
extensions = Extensions} = ServerHello,
#state{key_share = ClientKeyShare0,
- ssl_options = #ssl_options{ciphers = ClientCiphers,
- supported_groups = ClientGroups0}} = State0) ->
+ ssl_options = #{ciphers := ClientCiphers,
+ supported_groups := ClientGroups0}} = State0) ->
ClientGroups = get_supported_groups(ClientGroups0),
ServerKeyShare0 = maps:get(key_share, Extensions, undefined),
ClientKeyShare = get_key_shares(ClientKeyShare0),
@@ -976,7 +979,7 @@ maybe_queue_cert_cert_cv(#state{client_certificate_requested = false} = State) -
maybe_queue_cert_cert_cv(#state{connection_states = _ConnectionStates0,
session = #session{session_id = _SessionId,
own_certificate = OwnCert},
- ssl_options = #ssl_options{} = _SslOpts,
+ ssl_options = #{} = _SslOpts,
key_share = _KeyShare,
handshake_env = #handshake_env{tls_handshake_history = _HHistory0},
static_env = #static_env{
@@ -1063,12 +1066,11 @@ send_hello_retry_request(State0, _, _, _) ->
{ok, {State0, negotiated}}.
-maybe_send_certificate_request(State, #ssl_options{verify = verify_none}) ->
+maybe_send_certificate_request(State, #{verify := verify_none}) ->
{State, wait_finished};
-maybe_send_certificate_request(State, #ssl_options{
- verify = verify_peer,
- signature_algs = SignAlgs,
- signature_algs_cert = SignAlgsCert}) ->
+maybe_send_certificate_request(State, #{verify := verify_peer,
+ signature_algs := SignAlgs,
+ signature_algs_cert := SignAlgsCert}) ->
CertificateRequest = certificate_request(SignAlgs, SignAlgsCert),
{tls_connection:queue_handshake(CertificateRequest, State), wait_cert}.
@@ -1102,15 +1104,13 @@ process_certificate(#certificate_1_3{
certificate_request_context = <<>>,
certificate_list = []},
#state{ssl_options =
- #ssl_options{
- fail_if_no_peer_cert = false}} = State) ->
+ #{fail_if_no_peer_cert := false}} = State) ->
{ok, {State, wait_finished}};
process_certificate(#certificate_1_3{
certificate_request_context = <<>>,
certificate_list = []},
#state{ssl_options =
- #ssl_options{
- fail_if_no_peer_cert = true}} = State0) ->
+ #{fail_if_no_peer_cert := true}} = State0) ->
%% At this point the client believes that the connection is up and starts using
%% its traffic secrets. In order to be able send an proper Alert to the client
@@ -1121,8 +1121,8 @@ process_certificate(#certificate_1_3{
{error, {certificate_required, State}};
process_certificate(#certificate_1_3{certificate_list = Certs0},
#state{ssl_options =
- #ssl_options{signature_algs = SignAlgs,
- signature_algs_cert = SignAlgsCert} = SslOptions,
+ #{signature_algs := SignAlgs,
+ signature_algs_cert := SignAlgsCert} = SslOptions,
static_env =
#static_env{
role = Role,
@@ -1180,19 +1180,26 @@ update_encryption_state(client, State) ->
State.
-validate_certificate_chain(Certs, CertDbHandle, CertDbRef, SslOptions, CRLDbHandle, Role, Host) ->
- ServerName = ssl_handshake:server_name(SslOptions#ssl_options.server_name_indication, Host, Role),
+validate_certificate_chain(Certs, CertDbHandle, CertDbRef,
+ #{server_name_indication := ServerNameIndication,
+ partial_chain := PartialChain,
+ verify_fun := VerifyFun,
+ customize_hostname_check := CustomizeHostnameCheck,
+ crl_check := CrlCheck,
+ depth := Depth} = SslOptions,
+ CRLDbHandle, Role, Host) ->
+ ServerName = ssl_handshake:server_name(ServerNameIndication, Host, Role),
[PeerCert | ChainCerts ] = Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(Certs, CertDbHandle, CertDbRef,
- SslOptions#ssl_options.partial_chain),
+ PartialChain),
ValidationFunAndState =
- ssl_handshake:validation_fun_and_state(SslOptions#ssl_options.verify_fun, Role,
+ ssl_handshake:validation_fun_and_state(VerifyFun, Role,
CertDbHandle, CertDbRef, ServerName,
- SslOptions#ssl_options.customize_hostname_check,
- SslOptions#ssl_options.crl_check, CRLDbHandle, CertPath),
- Options = [{max_path_length, SslOptions#ssl_options.depth},
+ CustomizeHostnameCheck,
+ CrlCheck, CRLDbHandle, CertPath),
+ Options = [{max_path_length, Depth},
{verify_fun, ValidationFunAndState}],
%% TODO: Validate if Certificate is using a supported signature algorithm
%% (signature_algs_cert)!
@@ -1531,9 +1538,7 @@ get_handshake_context_client(L) ->
%% CertificateRequest message.
verify_signature_algorithm(#state{
static_env = #static_env{role = Role},
- ssl_options =
- #ssl_options{
- signature_algs = LocalSignAlgs}} = State0,
+ ssl_options = #{signature_algs := LocalSignAlgs}} = State0,
#certificate_verify_1_3{algorithm = PeerSignAlg}) ->
case lists:member(PeerSignAlg, LocalSignAlgs) of
true ->
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 2aeab98929..cfd75076b3 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -83,7 +83,7 @@ init_connection_states(Role, BeastMitigation) ->
binary(),
[tls_version()] | tls_version(),
Buffer0 :: binary() | {'undefined' | #ssl_tls{}, {[binary()],non_neg_integer(),[binary()]}},
- #ssl_options{}) ->
+ ssl_options()) ->
{Records :: [#ssl_tls{}],
Buffer :: {'undefined' | #ssl_tls{}, {[binary()],non_neg_integer(),[binary()]}}} |
#alert{}.
@@ -495,7 +495,9 @@ validate_tls_record_version(Versions, Q, SslOpts, Acc, Type, Version, Length) ->
validate_tls_record_length(_Versions, Q, _SslOpts, Acc, Type, Version, undefined) ->
{lists:reverse(Acc),
{#ssl_tls{type = Type, version = Version, fragment = undefined}, Q}};
-validate_tls_record_length(Versions, {_,Size0,_} = Q0, SslOpts, Acc, Type, Version, Length) ->
+validate_tls_record_length(Versions, {_,Size0,_} = Q0,
+ #{log_level := LogLevel} = SslOpts,
+ Acc, Type, Version, Length) ->
if
Length =< ?MAX_CIPHER_TEXT_LENGTH ->
if
@@ -503,7 +505,7 @@ validate_tls_record_length(Versions, {_,Size0,_} = Q0, SslOpts, Acc, Type, Versi
%% Complete record
{Fragment, Q} = binary_from_front(Length, Q0),
Record = #ssl_tls{type = Type, version = Version, fragment = Fragment},
- ssl_logger:debug(SslOpts#ssl_options.log_level, inbound, 'record', Record),
+ ssl_logger:debug(LogLevel, inbound, 'record', Record),
decode_tls_records(Versions, Q, SslOpts, [Record|Acc], undefined, undefined, undefined);
true ->
{lists:reverse(Acc),
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 6c32e6fa04..acd907905c 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -210,9 +210,9 @@ internal_inet_values() ->
default_inet_values() ->
[{packet_size, 0}, {packet,0}, {header, 0}, {active, true}, {mode, list}].
-inherit_tracker(ListenSocket, EmOpts, #ssl_options{erl_dist = false} = SslOpts) ->
+inherit_tracker(ListenSocket, EmOpts, #{erl_dist := false} = SslOpts) ->
ssl_listen_tracker_sup:start_child([ListenSocket, EmOpts, SslOpts]);
-inherit_tracker(ListenSocket, EmOpts, #ssl_options{erl_dist = true} = SslOpts) ->
+inherit_tracker(ListenSocket, EmOpts, #{erl_dist := true} = SslOpts) ->
ssl_listen_tracker_sup:start_child_dist([ListenSocket, EmOpts, SslOpts]).
get_emulated_opts(TrackerPid) ->