fix(tls): fix incompatible tls options and issue with tls version gap
This commit is contained in:
parent
267053cc35
commit
6d88cd7a20
|
@ -478,7 +478,7 @@ to_server_opts(Type, Opts) ->
|
|||
Versions = integral_versions(Type, maps:get(versions, Opts, undefined)),
|
||||
Ciphers = integral_ciphers(Versions, maps:get(ciphers, Opts, undefined)),
|
||||
Path = fun(Key) -> resolve_cert_path_for_read_strict(maps:get(Key, Opts, undefined)) end,
|
||||
filter(
|
||||
ensure_valid_options(
|
||||
maps:to_list(Opts#{
|
||||
keyfile => Path(keyfile),
|
||||
certfile => Path(certfile),
|
||||
|
@ -511,7 +511,7 @@ to_client_opts(Type, Opts) ->
|
|||
SNI = ensure_sni(Get(server_name_indication)),
|
||||
Versions = integral_versions(Type, Get(versions)),
|
||||
Ciphers = integral_ciphers(Versions, Get(ciphers)),
|
||||
filter(
|
||||
ensure_valid_options(
|
||||
[
|
||||
{keyfile, KeyFile},
|
||||
{certfile, CertFile},
|
||||
|
@ -556,33 +556,96 @@ resolve_cert_path_for_read_strict(Path) ->
|
|||
resolve_cert_path_for_read(Path) ->
|
||||
emqx_schema:naive_env_interpolation(Path).
|
||||
|
||||
filter([], _) ->
|
||||
[];
|
||||
filter([{_, undefined} | T], Versions) ->
|
||||
filter(T, Versions);
|
||||
filter([{_, ""} | T], Versions) ->
|
||||
filter(T, Versions);
|
||||
filter([{K, V} | T], Versions) ->
|
||||
ensure_valid_options(Options, Versions0) ->
|
||||
Versions = validate_version_gap(Versions0),
|
||||
ensure_valid_options(Options, Versions, []).
|
||||
|
||||
%% See also lib/ssl/src/ssl.erl#L2617.
|
||||
%% Do not allow configuration of TLS 1.3 with a gap where TLS 1.2 is not supported
|
||||
%% as that configuration can trigger the built in version downgrade protection
|
||||
%% mechanism and the handshake can fail with an Illegal Parameter alert.
|
||||
validate_version_gap(Versions) ->
|
||||
case lists:member('tlsv1.3', Versions) of
|
||||
true when length(Versions) >= 2 ->
|
||||
case lists:member('tlsv1.2', Versions) of
|
||||
true ->
|
||||
Versions;
|
||||
false ->
|
||||
NewVersions = ['tlsv1.3'],
|
||||
?SLOG(warning, #{
|
||||
msg => "tlsv13_version_gap",
|
||||
versions => Versions,
|
||||
new_versions => NewVersions
|
||||
}),
|
||||
NewVersions
|
||||
end;
|
||||
_ ->
|
||||
Versions
|
||||
end.
|
||||
|
||||
ensure_valid_options([], _, Acc) ->
|
||||
lists:reverse(Acc);
|
||||
ensure_valid_options([{_, undefined} | T], Versions, Acc) ->
|
||||
ensure_valid_options(T, Versions, Acc);
|
||||
ensure_valid_options([{_, ""} | T], Versions, Acc) ->
|
||||
ensure_valid_options(T, Versions, Acc);
|
||||
ensure_valid_options([{K, V} | T], Versions, Acc) ->
|
||||
case tls_option_compatible_versions(K) of
|
||||
all ->
|
||||
[{K, V} | filter(T, Versions)];
|
||||
ensure_valid_options(T, Versions, [{K, V} | Acc]);
|
||||
CompatibleVersions ->
|
||||
case CompatibleVersions -- (CompatibleVersions -- Versions) of
|
||||
[] ->
|
||||
filter(T, Versions);
|
||||
_ ->
|
||||
[{K, V} | filter(T, Versions)]
|
||||
Enabled = sets:from_list(Versions),
|
||||
Compatible = sets:from_list(CompatibleVersions),
|
||||
case sets:size(sets:intersection(Enabled, Compatible)) > 0 of
|
||||
true ->
|
||||
ensure_valid_options(T, Versions, [{K, V} | Acc]);
|
||||
false ->
|
||||
?SLOG(warning, #{
|
||||
msg => "drop_incompatible_tls_option", option => K, versions => Versions
|
||||
}),
|
||||
ensure_valid_options(T, Versions, Acc)
|
||||
end
|
||||
end.
|
||||
|
||||
%% see lib/ssl/src/ssl.erl, assert_option_dependency/4
|
||||
tls_option_compatible_versions(beast_mitigation) ->
|
||||
[dtlsv1, 'tlsv1'];
|
||||
tls_option_compatible_versions(padding_check) ->
|
||||
[dtlsv1, 'tlsv1'];
|
||||
tls_option_compatible_versions(client_renegotiation) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(reuse_session) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(reuse_sessions) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(secure_renegotiate) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(next_protocol_advertised) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(client_preferred_next_protocols) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(psk_identity) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(srp_identity) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(user_lookup_fun) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(client_renegotiation) ->
|
||||
[dtlsv1, 'dtlsv1.2', 'tlsv1', 'tlsv1.1', 'tlsv1.2'];
|
||||
tls_option_compatible_versions(early_data) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(certificate_authorities) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(cookie) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(key_update_at) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(anti_replay) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(session_tickets) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(supported_groups) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(use_ticket) ->
|
||||
['tlsv1.3'];
|
||||
tls_option_compatible_versions(_) ->
|
||||
all.
|
||||
|
||||
|
|
Loading…
Reference in New Issue