diff --git a/rebar.config b/rebar.config index 42eab79c6..857133829 100644 --- a/rebar.config +++ b/rebar.config @@ -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"}}, diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index f997877d4..9bf7efcfe 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -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; diff --git a/src/ejabberd_pkix.erl b/src/ejabberd_pkix.erl index 7fd7e6286..9b9c51287 100644 --- a/src/ejabberd_pkix.erl +++ b/src/ejabberd_pkix.erl @@ -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", []), diff --git a/src/ejabberd_sip.erl b/src/ejabberd_sip.erl index 01bb7ffcc..ffd5c059a 100644 --- a/src/ejabberd_sip.erl +++ b/src/ejabberd_sip.erl @@ -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; diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 8228a2577..25a55ae90 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -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;