Rely on Server Name Indication for incoming Direct-TLS connections

This commit also deprecates `certfile` option for ejabberd_http
listener.
This commit is contained in:
Evgeniy Khramtsov 2017-12-24 12:27:51 +03:00
parent b54e1e49ba
commit 1698956f34
5 changed files with 73 additions and 9 deletions

View File

@ -22,7 +22,7 @@
{tag, {if_version_above, "17", "3.4.2", "3.2.1"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.10"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.12"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.17"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", "ac507f2"}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.10"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", "f22a56d"}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", "597d78b"}},

View File

@ -97,8 +97,7 @@ start_link(SockData, Opts) ->
init({SockMod, Socket}, Opts) ->
TLSEnabled = proplists:get_bool(tls, Opts),
TLSOpts1 = lists:filter(fun ({certfile, _}) -> true;
({ciphers, _}) -> true;
TLSOpts1 = lists:filter(fun ({ciphers, _}) -> true;
({dhfile, _}) -> true;
({protocol_options, _}) -> true;
(_) -> false
@ -108,7 +107,11 @@ init({SockMod, Socket}, Opts) ->
false -> [compression_none | TLSOpts1];
true -> TLSOpts1
end,
TLSOpts = [verify_none | TLSOpts2],
TLSOpts3 = case get_certfile(Opts) of
undefined -> TLSOpts2;
CertFile -> [{certfile, CertFile}|TLSOpts2]
end,
TLSOpts = [verify_none | TLSOpts3],
{SockMod1, Socket1} = if TLSEnabled ->
inet:setopts(Socket, [{recbuf, 8192}]),
{ok, TLSSocket} = fast_tls:tcp_to_tls(Socket,
@ -885,6 +888,20 @@ normalize_path([_Parent, <<"..">>|Path], Norm) ->
normalize_path([Part | Path], Norm) ->
normalize_path(Path, [Part|Norm]).
-spec get_certfile([proplists:property()]) -> binary() | undefined.
get_certfile(Opts) ->
case lists:keyfind(certfile, 1, Opts) of
{_, CertFile} ->
CertFile;
false ->
case ejabberd_pkix:get_certfile(?MYNAME) of
{ok, CertFile} ->
CertFile;
error ->
ejabberd_config:get_option({domain_certfile, ?MYNAME})
end
end.
transform_listen_option(captcha, Opts) ->
[{captcha, true}|Opts];
transform_listen_option(register, Opts) ->
@ -933,8 +950,10 @@ opt_type(_) -> [trusted_proxies].
(atom()) -> [atom()].
listen_opt_type(tls) ->
fun(B) when is_boolean(B) -> B end;
listen_opt_type(certfile) ->
listen_opt_type(certfile = Opt) ->
fun(S) ->
?WARNING_MSG("Listening option '~s' for ~s is deprecated, use "
"'certfiles' global option instead", [Opt, ?MODULE]),
ejabberd_pkix:add_certfile(S),
iolist_to_binary(S)
end;

View File

@ -390,6 +390,7 @@ build_chain_and_check(State) ->
ets:delete_all_objects(?MODULE),
lists:foreach(
fun({Path, Domain}) ->
fast_tls:add_certfile(Domain, Path),
ets:insert(?MODULE, {Domain, Path})
end, CertFilesWithDomains),
?DEBUG("Validating certificates", []),

View File

@ -44,12 +44,14 @@ start(_, _) ->
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2,
socket_type/0, listen_opt_type/1]).
-include("ejabberd.hrl").
%%%===================================================================
%%% API
%%%===================================================================
tcp_init(Socket, Opts) ->
ejabberd:start_app(esip),
esip_socket:tcp_init(Socket, Opts).
esip_socket:tcp_init(Socket, set_certfile(Opts)).
udp_init(Socket, Opts) ->
ejabberd:start_app(esip),
@ -64,8 +66,28 @@ start(Opaque, Opts) ->
socket_type() ->
raw.
set_certfile(Opts) ->
case lists:keymember(certfile, 1, Opts) of
true ->
Opts;
false ->
case ejabberd_pkix:get_certfile(?MYNAME) of
{ok, CertFile} ->
[{certfile, CertFile}|Opts];
error ->
case ejabberd_config:get_option({domain_certfile, ?MYNAME}) of
undefined ->
Opts;
CertFile ->
[{certfile, CertFile}|Opts]
end
end
end.
listen_opt_type(certfile) ->
fun(S) ->
%% We cannot deprecate the option for now:
%% I think STUN/TURN clients are too stupid to set SNI
ejabberd_pkix:add_certfile(S),
iolist_to_binary(S)
end;

View File

@ -77,7 +77,7 @@ prepare_turn_opts(Opts) ->
prepare_turn_opts(Opts, UseTurn).
prepare_turn_opts(Opts, _UseTurn = false) ->
Opts;
set_certfile(Opts);
prepare_turn_opts(Opts, _UseTurn = true) ->
NumberOfMyHosts = length(?MYHOSTS),
case proplists:get_value(turn_ip, Opts) of
@ -109,8 +109,28 @@ prepare_turn_opts(Opts, _UseTurn = true) ->
[]
end,
MaxRate = shaper:get_max_rate(Shaper),
Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
lists:keydelete(shaper, 1, Opts)].
Opts1 = Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
lists:keydelete(shaper, 1, Opts)],
set_certfile(Opts1).
set_certfile(Opts) ->
case lists:keymember(certfile, 1, Opts) of
true ->
Opts;
false ->
Realm = proplists:get_value(auth_realm, Opts, ?MYNAME),
case ejabberd_pkix:get_certfile(Realm) of
{ok, CertFile} ->
[{certfile, CertFile}|Opts];
error ->
case ejabberd_config:get_option({domain_certfile, Realm}) of
undefined ->
Opts;
CertFile ->
[{certfile, CertFile}|Opts]
end
end
end.
listen_opt_type(use_turn) ->
fun(B) when is_boolean(B) -> B end;
@ -131,6 +151,8 @@ listen_opt_type(tls) ->
fun(B) when is_boolean(B) -> B end;
listen_opt_type(certfile) ->
fun(S) ->
%% We cannot deprecate the option for now:
%% I think STUN/TURN clients are too stupid to set SNI
ejabberd_pkix:add_certfile(S),
iolist_to_binary(S)
end;