From fbf71f86f3f970c1c9d56c0c5d21b25a8c67d9ed Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Tue, 1 Apr 2014 21:57:33 +0200 Subject: [PATCH] Add option to specify openssl options --- doc/guide.tex | 12 ++++++++++-- ejabberd.yml.example | 12 ++++++++++++ src/ejabberd_c2s.erl | 17 +++++++++++++---- src/ejabberd_s2s_in.erl | 16 ++++++++++++++-- src/ejabberd_s2s_out.erl | 16 ++++++++++++++-- 5 files changed, 63 insertions(+), 10 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index dd4255725..b0657f814 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -332,7 +332,7 @@ To compile \ejabberd{} on a `Unix-like' operating system, you need: \makesubsection{download}{Download Source Code} \ind{install!download} -Released versions of \ejabberd{} are available in the ProcessOne \ejabberd{} downloads page: +Released versions of \ejabberd{} are available in the ProcessOne \ejabberd{} downloads page: \ahrefurl{http://www.process-one.net/en/ejabberd/downloads} \ind{Git repository} @@ -869,7 +869,7 @@ The available modules, their purpose and the options allowed by each one are: \begin{description} \titem{\texttt{ejabberd\_c2s}} Handles c2s connections.\\ - Options: \texttt{access}, \texttt{certfile}, \texttt{ciphers}, + Options: \texttt{access}, \texttt{certfile}, \texttt{ciphers}, \texttt{protocol\_options} \texttt{max\_fsm\_queue}, \texttt{max\_stanza\_size}, \texttt{shaper}, \texttt{starttls}, \texttt{starttls\_required}, \texttt{tls}, @@ -917,6 +917,10 @@ This is a detailed description of each option allowed by the listening modules: To define a certificate file specific for a given domain, use the global option \term{domain\_certfile}. \titem{ciphers: Ciphers} OpenSSL ciphers list in the same format accepted by `\verb|openssl ciphers|' command. + \titem{protocol\_options: ProtocolOpts} \ind{options!protocol\_options} + List of general options relating to SSL/TLS. These map to \verb|OpenSSL's set_options()|. + For a full list of options available in ejabberd, \verb|see the source|. + The default entry is: \verb|"no_sslv2"| \titem{default\_host: undefined|HostName\}} If the HTTP request received by ejabberd contains the HTTP header \term{Host} with an ambiguous virtual host that doesn't match any one defined in ejabberd (see \ref{hostnames}), @@ -1065,6 +1069,10 @@ There are some additional global options that can be specified in the ejabberd c Full path to the file containing the SSL certificate for a specific domain. \titem{s2s\_ciphers: Ciphers} \ind{options!s2s\_ciphers} OpenSSL ciphers list in the same format accepted by `\verb|openssl ciphers|' command. + \titem{s2s\_protocol\_options: ProtocolOpts} \ind{options!s2s\_protocol\_options} + List of general options relating to SSL/TLS. These map to \verb|OpenSSL's set_options()|. + For a full list of options available in ejabberd, \verb|see the source|. + The default enitry is: \verb|"no_sslv2"| \titem{outgoing\_s2s\_families: [Family, ...]} \ind{options!outgoing\_s2s\_families} Specify which address families to try, in what order. By default it first tries connecting with IPv4, if that fails it tries using IPv6. diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 28f61fdbe..2e744103f 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -86,6 +86,12 @@ listen: ## ## certfile: "/path/to/ssl.pem" ## starttls: true + ## + ## Custom OpenSSL options + ## + ## protocol_options: + ## - "no_sslv3" + ## - "no_tlsv1" max_stanza_size: 65536 shaper: c2s_shaper access: c2s @@ -144,6 +150,12 @@ listen: ## ## s2s_certfile: "/path/to/ssl.pem" +## Custom OpenSSL options +## +## s2s_protocol_options: +## - "no_sslv3" +## - "no_tlsv1" + ## ## domain_certfile: Specify a different certificate for each served hostname. ## diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 83dfd2f07..fa0eee8c5 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -245,11 +245,20 @@ init([{SockMod, Socket}, Opts]) -> (_) -> false end, Opts), - TLSOpts2 = case proplists:get_bool(tls_compression, Opts) of - false -> [compression_none | TLSOpts1]; - true -> TLSOpts1 + TLSOpts2 = case lists:keysearch(protocol_options, 1, Opts) of + {value, {_, O}} -> + [_|ProtocolOptions] = lists:foldl( + fun(X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] || Opt <- O, is_binary(Opt)] + ), + [{protocol_options, iolist_to_binary(ProtocolOptions)} | TLSOpts1]; + _ -> TLSOpts1 end, - TLSOpts = [verify_none | TLSOpts2], + TLSOpts3 = case proplists:get_bool(tls_compression, Opts) of + false -> [compression_none | TLSOpts2]; + true -> TLSOpts2 + end, + TLSOpts = [verify_none | TLSOpts3], IP = peerip(SockMod, Socket), %% Check if IP is blacklisted: case is_ip_blacklisted(IP) of diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 97c65af74..22a69b02c 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -182,9 +182,21 @@ init([{SockMod, Socket}, Opts]) -> undefined -> TLSOpts1; Ciphers -> [{ciphers, Ciphers} | TLSOpts1] end, + TLSOpts3 = case ejabberd_config:get_option( + s2s_protocol_options, + fun (Options) -> + [_|O] = lists:foldl( + fun(X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] || Opt <- Options, is_binary(Opt)] + ), + iolist_to_binary(O) + end) of + undefined -> TLSOpts2; + ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2] + end, TLSOpts = case proplists:get_bool(tls_compression, Opts) of - false -> [compression_none | TLSOpts2]; - true -> TLSOpts2 + false -> [compression_none | TLSOpts3]; + true -> TLSOpts3 end, Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, wait_for_stream, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 7222e43b1..1f86cf68f 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -196,13 +196,25 @@ init([From, Server, Type]) -> undefined -> TLSOpts1; Ciphers -> [{ciphers, Ciphers} | TLSOpts1] end, + TLSOpts3 = case ejabberd_config:get_option( + s2s_protocol_options, + fun (Options) -> + [_|O] = lists:foldl( + fun(X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] || Opt <- Options, is_binary(Opt)] + ), + iolist_to_binary(O) + end) of + undefined -> TLSOpts2; + ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2] + end, TLSOpts = case ejabberd_config:get_option( {s2s_tls_compression, From}, fun(true) -> true; (false) -> false end, true) of - false -> [compression_none | TLSOpts2]; - true -> TLSOpts2 + false -> [compression_none | TLSOpts3]; + true -> TLSOpts3 end, {New, Verify} = case Type of {new, Key} -> {Key, false};