fix(emqx_schema): move tls version gap validation to emqx_schema
This commit is contained in:
parent
6d88cd7a20
commit
4425942030
|
@ -2679,10 +2679,30 @@ validate_ciphers(Ciphers) ->
|
||||||
validate_tls_versions(Collection, Versions) ->
|
validate_tls_versions(Collection, Versions) ->
|
||||||
AvailableVersions = available_tls_vsns(Collection),
|
AvailableVersions = available_tls_vsns(Collection),
|
||||||
case lists:filter(fun(V) -> not lists:member(V, AvailableVersions) end, Versions) of
|
case lists:filter(fun(V) -> not lists:member(V, AvailableVersions) end, Versions) of
|
||||||
[] -> ok;
|
[] -> validate_tls_version_gap(Versions);
|
||||||
Vs -> {error, {unsupported_tls_versions, Vs}}
|
Vs -> {error, {unsupported_tls_versions, Vs}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% See also `validate_version_gap/1` in OTP ssl.erl,
|
||||||
|
%% e.g: https://github.com/emqx/otp/blob/emqx-OTP-25.1.2/lib/ssl/src/ssl.erl#L2566.
|
||||||
|
%% 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_tls_version_gap(Versions) ->
|
||||||
|
case lists:member('tlsv1.3', Versions) of
|
||||||
|
true when length(Versions) >= 2 ->
|
||||||
|
case lists:member('tlsv1.2', Versions) of
|
||||||
|
true ->
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
{error,
|
||||||
|
"Using multiple versions that include tlsv1.3 but "
|
||||||
|
"exclude tlsv1.2 is not allowed"}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
validations() ->
|
validations() ->
|
||||||
[
|
[
|
||||||
{check_process_watermark, fun check_process_watermark/1},
|
{check_process_watermark, fun check_process_watermark/1},
|
||||||
|
|
|
@ -556,33 +556,9 @@ resolve_cert_path_for_read_strict(Path) ->
|
||||||
resolve_cert_path_for_read(Path) ->
|
resolve_cert_path_for_read(Path) ->
|
||||||
emqx_schema:naive_env_interpolation(Path).
|
emqx_schema:naive_env_interpolation(Path).
|
||||||
|
|
||||||
ensure_valid_options(Options, Versions0) ->
|
ensure_valid_options(Options, Versions) ->
|
||||||
Versions = validate_version_gap(Versions0),
|
|
||||||
ensure_valid_options(Options, Versions, []).
|
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) ->
|
ensure_valid_options([], _, Acc) ->
|
||||||
lists:reverse(Acc);
|
lists:reverse(Acc);
|
||||||
ensure_valid_options([{_, undefined} | T], Versions, Acc) ->
|
ensure_valid_options([{_, undefined} | T], Versions, Acc) ->
|
||||||
|
@ -607,7 +583,7 @@ ensure_valid_options([{K, V} | T], Versions, Acc) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% see lib/ssl/src/ssl.erl, assert_option_dependency/4
|
%% see otp/lib/ssl/src/ssl.erl, `assert_option_dependency/4`
|
||||||
tls_option_compatible_versions(beast_mitigation) ->
|
tls_option_compatible_versions(beast_mitigation) ->
|
||||||
[dtlsv1, 'tlsv1'];
|
[dtlsv1, 'tlsv1'];
|
||||||
tls_option_compatible_versions(padding_check) ->
|
tls_option_compatible_versions(padding_check) ->
|
||||||
|
|
|
@ -94,6 +94,18 @@ ssl_opts_tls_psk_test() ->
|
||||||
Checked = validate(Sc, #{<<"versions">> => [<<"tlsv1.2">>]}),
|
Checked = validate(Sc, #{<<"versions">> => [<<"tlsv1.2">>]}),
|
||||||
?assertMatch(#{versions := ['tlsv1.2']}, Checked).
|
?assertMatch(#{versions := ['tlsv1.2']}, Checked).
|
||||||
|
|
||||||
|
ssl_opts_version_gap_test_() ->
|
||||||
|
Sc = emqx_schema:server_ssl_opts_schema(#{}, false),
|
||||||
|
RanchSc = emqx_schema:server_ssl_opts_schema(#{}, true),
|
||||||
|
Reason = "Using multiple versions that include tlsv1.3 but exclude tlsv1.2 is not allowed",
|
||||||
|
[
|
||||||
|
?_assertThrow(
|
||||||
|
{_, [#{kind := validation_error, reason := Reason}]},
|
||||||
|
validate(S, #{<<"versions">> => [<<"tlsv1.1">>, <<"tlsv1.3">>]})
|
||||||
|
)
|
||||||
|
|| S <- [Sc, RanchSc]
|
||||||
|
].
|
||||||
|
|
||||||
bad_cipher_test() ->
|
bad_cipher_test() ->
|
||||||
Sc = emqx_schema:server_ssl_opts_schema(#{}, false),
|
Sc = emqx_schema:server_ssl_opts_schema(#{}, false),
|
||||||
Reason = {bad_ciphers, ["foo"]},
|
Reason = {bad_ciphers, ["foo"]},
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
Disallow using multiple TLS versions in the listener config that include tlsv1.3 but exclude tlsv1.2.
|
||||||
|
|
||||||
|
Using TLS configuration with such version gap caused connection errors.
|
||||||
|
Additionally, drop and log TLS options that are incompatible with the selected TLS version(s).
|
||||||
|
|
||||||
|
Note: any old listener configuration with the version gap described above will fail to load
|
||||||
|
after applying this fix and must be manually fixed.
|
Loading…
Reference in New Issue