Skip to content

Commit

Permalink
WIP MIM-2314
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrzej Telezynski committed Nov 12, 2024
1 parent 6fdd662 commit 0b9d8b5
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 12 deletions.
1 change: 1 addition & 0 deletions rel/mim1.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
shaper = \"c2s_shaper\"
max_stanza_size = 65536
tls.certfile = \"priv/ssl/fake_server.pem\"
tls.cacertfile = \"priv/ssl/cacert.pem\"
tls.mode = \"tls\""}.
{listen_service,
"[[listen.service]]
Expand Down
1 change: 1 addition & 0 deletions rel/mim2.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
max_stanza_size = 65536
tls.cacertfile = \"priv/ssl/cacert.pem\"
tls.certfile = \"priv/ssl/fake_server.pem\"
tls.cacertfile = \"priv/ssl/cacert.pem\"
tls.mode = \"tls\"
tls.ciphers = \"ECDHE-RSA-AES256-GCM-SHA384\""}.
{listen_service,
Expand Down
55 changes: 52 additions & 3 deletions src/config/mongoose_config_spec.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
process_listener/2,
process_c2s_tls/1,
process_c2s_just_tls/1,
process_c2s_fast_tls/1,
process_just_tls/1,
process_fast_tls/1,
process_sasl_external/1,
Expand Down Expand Up @@ -701,7 +702,7 @@ tls(c2s, just_tls) ->
validate = filename}}},
process = fun ?MODULE:process_c2s_just_tls/1};
tls(c2s, fast_tls) ->
#section{}.
#section{process = fun ?MODULE:process_c2s_fast_tls/1}.

server_name_indication() ->
#section{items = #{<<"enabled">> => #option{type = boolean},
Expand Down Expand Up @@ -945,7 +946,7 @@ process_root(Items) ->
HTItems = lists:filter(fun(Item) -> is_host_type_item(Item, HostTypes) end, Items),
case {unsupported_auth_methods(HTItems), unsupported_modules(HTItems)} of
{[], []} ->
Items;
check_use_starttls(HTItems, Items);
{Methods, Modules} ->
error(#{what => dynamic_domains_not_supported,
text => ("Dynamic modules not supported by the specified authentication "
Expand All @@ -956,7 +957,7 @@ process_root(Items) ->
_ ->
Items
end.

unsupported_auth_methods(KVs) ->
[Method || Method <- extract_auth_methods(KVs),
not ejabberd_auth:does_method_support(Method, dynamic_domains)].
Expand All @@ -975,6 +976,43 @@ extract_modules(KVs) ->
(_) -> []
end, KVs)).

check_use_starttls(HTItems, Items) ->
%% Require `cacertfile` for s2s listeners
%% if s2s config specifies `use_starttls` as something other than `false`,
%% meaning the peer certificate is to be checked
case lists:all(fun classify_use_starttls/1, extract_use_starttls(HTItems)) of
true ->
Items;
_ ->
check_s2s_verify_mode_cacertfile(Items)

Check warning on line 987 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L987

Added line #L987 was not covered by tests
end.

classify_use_starttls(false) ->
true;
classify_use_starttls(_) ->
false.

Check warning on line 993 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L993

Added line #L993 was not covered by tests

extract_use_starttls(KVs) ->
lists:flatmap(fun({{s2s, _}, S2S}) -> [maps:get(use_starttls, S2S)];(_) -> [] end, KVs).

check_s2s_verify_mode_cacertfile(Items) ->
case lists:keyfind(listen, 1, Items) of

Check warning on line 999 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L999

Added line #L999 was not covered by tests
false ->
Items;

Check warning on line 1001 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1001

Added line #L1001 was not covered by tests
{_, ListenItems} ->
S2S = [Item || Item <- ListenItems, maps:get(module, Item) == ejabberd_s2s_in],
lists:foreach(fun verify_s2s_tls/1, S2S),
Items

Check warning on line 1005 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1003-L1005

Added lines #L1003 - L1005 were not covered by tests
end.

verify_s2s_tls(#{tls := #{cacertfile := _}}=Item) ->
Item;

Check warning on line 1009 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1009

Added line #L1009 was not covered by tests
verify_s2s_tls(#{tls := #{verify_mode := peer}}) ->
error(#{what => missing_cacertfile,

Check warning on line 1011 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1011

Added line #L1011 was not covered by tests
text => <<"You need to provide CA certificate (cacertfile) "
"or disable peer verification (verify_mode) "
"for ejabberd_s2s_in when s2s.use_starttls is not false">>}).

is_host_type_item({{_, HostType}, _}, HostTypes) ->
HostType =:= global orelse lists:member(HostType, HostTypes);
is_host_type_item(_, _) ->
Expand Down Expand Up @@ -1045,6 +1083,17 @@ fast_tls_defaults() ->
#{ciphers => mongoose_tls:default_ciphers(),
protocol_options => ["no_sslv2", "no_sslv3", "no_tlsv1", "no_tlsv1_1"]}.

process_c2s_fast_tls(M = #{module := just_tls}) ->
M;
process_c2s_fast_tls(M = #{cacertfile := _}) ->
M;
process_c2s_fast_tls(#{verify_mode := peer}) ->
error(#{what => missing_cacertfile,
text => <<"You need to provide CA certificate (cacertfile) "
"or disable peer verification (verify_mode)">>});
process_c2s_fast_tls(M) ->
M.

process_listener([item, Type | _], Opts) ->
mongoose_listener_config:ensure_ip_options(Opts#{module => listener_module(Type),
connection_type => connection_type(Type)}).
Expand Down
3 changes: 2 additions & 1 deletion test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ options("mongooseim-pgsql") ->
access => c2s,
shaper => c2s_shaper,
max_stanza_size => 65536,
tls => #{certfile => "priv/dc1.pem", dhfile => "priv/dh.pem"}
tls => #{certfile => "priv/dc1.pem", dhfile => "priv/dh.pem",
cacertfile => "priv/ca.pem"}
}),
config([listen, c2s],
#{port => 5223,
Expand Down
18 changes: 10 additions & 8 deletions test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,12 @@ listen_c2s_fast_tls(_Config) ->
T = fun(Opts) -> listen_raw(c2s, #{<<"port">> => 5222,
<<"tls">> => Opts}) end,
P = [listen, 1, tls],
?cfg(P, default_c2s_tls(fast_tls), T(#{})),
M = tls_ca_raw(),
?cfg(P, maps:merge(default_c2s_tls(fast_tls), tls_ca()), T(M)),
test_fast_tls_server(P, T),
?cfg(P ++ [mode], tls, T(#{<<"mode">> => <<"tls">>})),
?err(T(#{<<"mode">> => <<"stopttls">>})),
?err(T(#{<<"module">> => <<"slow_tls">>})).
?cfg(P ++ [mode], tls, T(M#{<<"mode">> => <<"tls">>})),
?err(T(M#{<<"mode">> => <<"stopttls">>})),
?err(T(M#{<<"module">> => <<"slow_tls">>})).

listen_c2s_just_tls(_Config) ->
T = fun(Opts) -> listen_raw(c2s, #{<<"port">> => 5222,
Expand Down Expand Up @@ -1197,12 +1198,13 @@ test_just_tls_client_sni(ParentP, ParentT) ->

test_fast_tls_server(P, T) ->
?cfg(P ++ [verify_mode], none, T(#{<<"verify_mode">> => <<"none">>})),
?cfg(P ++ [certfile], "priv/cert.pem", T(#{<<"certfile">> => <<"priv/cert.pem">>})),
M = tls_ca_raw(),
?cfg(P ++ [certfile], "priv/cert.pem", T(M#{<<"certfile">> => <<"priv/cert.pem">>})),
?cfg(P ++ [cacertfile], "priv/ca.pem", T(tls_ca_raw())),
?cfg(P ++ [ciphers], "TLS_AES_256_GCM_SHA384",
T(#{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>})),
?cfg(P ++ [dhfile], "priv/dh.pem", T(#{<<"dhfile">> => <<"priv/dh.pem">>})),
?cfg(P ++ [protocol_options], ["nosslv2"], T(#{<<"protocol_options">> => [<<"nosslv2">>]})),
T(M#{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>})),
?cfg(P ++ [dhfile], "priv/dh.pem", T(M#{<<"dhfile">> => <<"priv/dh.pem">>})),
?cfg(P ++ [protocol_options], ["nosslv2"], T(M#{<<"protocol_options">> => [<<"nosslv2">>]})),
?err(T(#{<<"verify_mode">> => <<"selfsigned_peer">>})), % value only for just_tls
?err(T(#{<<"crl_files">> => [<<"priv/cert.pem">>]})), % option only for just_tls
?err(T(#{<<"certfile">> => <<"no_such_file.pem">>})),
Expand Down
1 change: 1 addition & 0 deletions test/config_parser_SUITE_data/mongooseim-pgsql.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
tls.mode = "starttls"
tls.certfile = "priv/dc1.pem"
tls.dhfile = "priv/dh.pem"
tls.cacertfile = "priv/ca.pem"

[[listen.c2s]]
port = 5223
Expand Down

0 comments on commit 0b9d8b5

Please sign in to comment.