From eb884c80d0cbe1dbdf8a2716fcf1b4d0325faa7c Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 8 Dec 2010 20:02:31 +0100 Subject: [PATCH] Add option to require encryption in S2S connections (EJAB-495) --- doc/guide.tex | 13 +++++++------ src/ejabberd.cfg.example | 4 ++-- src/ejabberd_s2s_out.erl | 22 +++++++++++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index d3db10338..bccbe586d 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -962,9 +962,10 @@ This is a detailed description of each option allowed by the listening modules: There are some additional global options that can be specified in the ejabberd configuration file (outside \term{listen}): \begin{description} - \titem{\{s2s\_use\_starttls, true|false\}} - \ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines whether to - use STARTTLS for s2s connections. + \titem{\{s2s\_use\_starttls, false|optional|required\}} + \ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines if + s2s connections can optionally use STARTTLS encryption, or if it must be required. + The default value is to not use STARTTLS: \term{false}. \titem{\{s2s\_certfile, Path\}} \ind{options!s2s\_certificate}Full path to a file containing a SSL certificate. \titem{\{domain\_certfile, Domain, Path\}} \ind{options!domain\_certfile} @@ -1057,7 +1058,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi ]} ] }. -{s2s_use_starttls, true}. +{s2s_use_starttls, optional}. {s2s_certfile, "/etc/ejabberd/server.pem"}. {domain_certfile, "example.com", "/etc/ejabberd/example_com.pem"}. {outgoing_s2s_options, [ipv4, ipv6], 10000}. @@ -1069,7 +1070,7 @@ In this example, the following configuration defines that: on port 5223 (SSL, IP 192.168.0.1 and fdca:8ab6:a243:75ef::1) and denied for the user called `\term{bad}'. \item s2s connections are listened for on port 5269 (all IPv4 addresses) - with STARTTLS for secured traffic enabled. + with STARTTLS for secured traffic required. Incoming and outgoing connections of remote XMPP servers are denied, only two servers can connect: "jabber.example.org" and "example.com". \item Port 5280 is serving the Web Admin and the HTTP Polling service @@ -1150,7 +1151,7 @@ In this example, the following configuration defines that: {service_check_from, false}]} ] }. -{s2s_use_starttls, true}. +{s2s_use_starttls, required}. {s2s_certfile, "/path/to/ssl.pem"}. {s2s_default_policy, deny}. {{s2s_host,"jabber.example.org"}, allow}. diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index 6dd9e0962..45cdfb4d0 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -170,10 +170,10 @@ %% %% s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections. -%% Allowed values are: true or false. +%% Allowed values are: false optional required %% You must specify a certificate file. %% -%%{s2s_use_starttls, true}. +%%{s2s_use_starttls, optional}. %% %% s2s_certfile: Specify a certificate file. diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index d33fc9718..b8d35ddad 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -154,11 +154,13 @@ stop_connection(Pid) -> init([From, Server, Type]) -> process_flag(trap_exit, true), ?DEBUG("started: ~p", [{From, Server, Type}]), - TLS = case ejabberd_config:get_local_option(s2s_use_starttls) of - undefined -> - false; - UseStartTLS -> - UseStartTLS + {TLS, TLSRequired} = case ejabberd_config:get_local_option(s2s_use_starttls) of + UseTls when (UseTls==undefined) or (UseTls==false) -> + {false, false}; + UseTls when (UseTls==true) or (UseTls==optional) -> + {true, false}; + required -> + {true, true} end, UseV10 = TLS, TLSOpts = case ejabberd_config:get_local_option(s2s_certfile) of @@ -177,6 +179,7 @@ init([From, Server, Type]) -> Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, open_socket, #state{use_v10 = UseV10, tls = TLS, + tls_required = TLSRequired, tls_options = TLSOpts, queue = queue:new(), myname = From, @@ -351,8 +354,8 @@ wait_for_validation({xmlstreamelement, El}, StateData) -> case is_verify_res(El) of {result, To, From, Id, Type} -> ?DEBUG("recv result: ~p", [{From, To, Id, Type}]), - case Type of - "valid" -> + case {Type, StateData#state.tls_enabled, StateData#state.tls_required} of + {"valid", Enabled, Required} when (Enabled==true) or (Required==false) -> send_queue(StateData, StateData#state.queue), ?INFO_MSG("Connection established: ~s -> ~s with TLS=~p", [StateData#state.myname, StateData#state.server, StateData#state.tls_enabled]), @@ -361,6 +364,11 @@ wait_for_validation({xmlstreamelement, El}, StateData) -> StateData#state.server]), {next_state, stream_established, StateData#state{queue = queue:new()}}; + {"valid", Enabled, Required} when (Enabled==false) and (Required==true) -> + %% TODO: bounce packets + ?INFO_MSG("Closing s2s connection: ~s -> ~s (TLS is required but unavailable)", + [StateData#state.myname, StateData#state.server]), + {stop, normal, StateData}; _ -> %% TODO: bounce packets ?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid dialback key)",