From 7e14b2d46a2209afcd5d17b363ffb541466618ed Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 13 Jul 2011 15:40:27 +1000 Subject: [PATCH] Add ldap_tls_cacertfile and ldap_tls_depth options (EJAB-1299) --- src/ejabberd_auth_ldap.erl | 6 +++- src/eldap/eldap.erl | 53 ++++++++++++++++++++++++---------- src/mod_shared_roster_ldap.erl | 15 +++++++++- src/mod_vcard_ldap.erl | 15 +++++++++- 4 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 7470dbb0f..88486f175 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -374,6 +374,8 @@ parse_options(Host) -> end, LDAPEncrypt = ejabberd_config:get_local_option({ldap_encrypt, Host}), LDAPTLSVerify = ejabberd_config:get_local_option({ldap_tls_verify, Host}), + LDAPTLSCAFile = ejabberd_config:get_local_option({ldap_tls_cacertfile, Host}), + LDAPTLSDepth = ejabberd_config:get_local_option({ldap_tls_depth, Host}), LDAPPort = case ejabberd_config:get_local_option({ldap_port, Host}) of undefined -> case LDAPEncrypt of tls -> ?LDAPS_PORT; @@ -422,7 +424,9 @@ parse_options(Host) -> backups = LDAPBackups, port = LDAPPort, tls_options = [{encrypt, LDAPEncrypt}, - {tls_verify, LDAPTLSVerify}], + {tls_verify, LDAPTLSVerify}, + {tls_cacertfile, LDAPTLSCAFile}, + {tls_depth, LDAPTLSDepth}], dn = RootDN, password = Password, base = LDAPBase, diff --git a/src/eldap/eldap.erl b/src/eldap/eldap.erl index 9e6081687..c438626fa 100644 --- a/src/eldap/eldap.erl +++ b/src/eldap/eldap.erl @@ -448,14 +448,29 @@ init({Hosts, Port, Rootdn, Passwd, Opts}) -> end; PT -> PT end, - TLSOpts = case proplists:get_value(tls_verify, Opts) of - soft -> - [{verify, 1}]; - hard -> - [{verify, 2}]; - _ -> - [{verify, 0}] - end, + CacertOpts = case proplists:get_value(tls_cacertfile, Opts) of + [_|_] = Path -> [{cacertfile, Path}]; + _ -> [] + end, + DepthOpts = case proplists:get_value(tls_depth, Opts) of + Depth when is_integer(Depth), Depth >= 0 -> + [{depth, Depth}]; + _ -> [] + end, + Verify = proplists:get_value(tls_verify, Opts), + TLSOpts = if (Verify == hard orelse Verify == soft) + andalso CacertOpts == [] -> + ?WARNING_MSG("TLS verification is enabled " + "but no CA certfiles configured, so " + "verification is disabled.", []), + []; + Verify == soft -> + [{verify, 1}] ++ CacertOpts ++ DepthOpts; + Verify == hard -> + [{verify, 2}] ++ CacertOpts ++ DepthOpts; + true -> + [] + end, {ok, connecting, #eldap{hosts = Hosts, port = PortTemp, rootdn = Rootdn, @@ -965,18 +980,21 @@ polish([], Res, Ref) -> connect_bind(S) -> Host = next_host(S#eldap.host, S#eldap.hosts), ?INFO_MSG("LDAP connection on ~s:~p", [Host, S#eldap.port]), + Opts = if S#eldap.tls == tls -> + [{packet, asn1}, {active, true}, {keepalive, true}, + binary | S#eldap.tls_options]; + true -> + [{packet, asn1}, {active, true}, {keepalive, true}, + {send_timeout, ?SEND_TIMEOUT}, binary] + end, SocketData = case S#eldap.tls of tls -> SockMod = ssl, - SslOpts = [{packet, asn1}, {active, true}, {keepalive, true}, - binary | S#eldap.tls_options], - ssl:connect(Host, S#eldap.port, SslOpts); + ssl:connect(Host, S#eldap.port, Opts); %% starttls -> %% TODO: Implement STARTTLS; _ -> SockMod = gen_tcp, - TcpOpts = [{packet, asn1}, {active, true}, {keepalive, true}, - {send_timeout, ?SEND_TIMEOUT}, binary], - gen_tcp:connect(Host, S#eldap.port, TcpOpts) + gen_tcp:connect(Host, S#eldap.port, Opts) end, case SocketData of {ok, Socket} -> @@ -994,8 +1012,11 @@ connect_bind(S) -> {ok, connecting, NewS#eldap{host = Host}} end; {error, Reason} -> - ?ERROR_MSG("LDAP connection failed on ~s:~p~nReason: ~p", - [Host, S#eldap.port, Reason]), + ?ERROR_MSG("LDAP connection failed:~n" + "** Server: ~s:~p~n" + "** Reason: ~p~n" + "** Socket options: ~p", + [Host, S#eldap.port, Reason, Opts]), NewS = close_and_retry(S), {ok, connecting, NewS#eldap{host = Host}} end. diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 613371922..0e1143d4a 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -483,6 +483,17 @@ parse_options(Host, Opts) -> ejabberd_config:get_local_option({ldap_tls_verify, Host}); Verify -> Verify end, + LDAPTLSCAFile = case gen_mod:get_opt(ldap_tls_cacertfile, Opts, undefined) of + undefined -> + ejabberd_config:get_local_option({ldap_tls_cacertfile, Host}); + CAFile -> CAFile + end, + LDAPTLSDepth = case gen_mod:get_opt(ldap_tls_depth, Opts, undefined) of + undefined -> + ejabberd_config:get_local_option({ldap_tls_depth, Host}); + Depth -> + Depth + end, LDAPPort = case gen_mod:get_opt(ldap_port, Opts, undefined) of undefined -> case ejabberd_config:get_local_option({ldap_port, Host}) of @@ -654,7 +665,9 @@ parse_options(Host, Opts) -> backups = LDAPBackups, port = LDAPPort, tls_options = [{encrypt, LDAPEncrypt}, - {tls_verify, LDAPTLSVerify}], + {tls_verify, LDAPTLSVerify}, + {tls_cacertfile, LDAPTLSCAFile}, + {tls_depth, LDAPTLSDepth}], dn = RootDN, base = LDAPBase, password = Password, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 7afd1f210..56ba9eb4d 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -691,6 +691,17 @@ parse_options(Host, Opts) -> ejabberd_config:get_local_option({ldap_tls_verify, Host}); Verify -> Verify end, + LDAPTLSCAFile = case gen_mod:get_opt(ldap_tls_cacertfile, Opts, undefined) of + undefined -> + ejabberd_config:get_local_option({ldap_tls_cacertfile, Host}); + CAFile -> CAFile + end, + LDAPTLSDepth = case gen_mod:get_opt(ldap_tls_depth, Opts, undefined) of + undefined -> + ejabberd_config:get_local_option({ldap_tls_depth, Host}); + Depth -> + Depth + end, LDAPPortTemp = case gen_mod:get_opt(ldap_port, Opts, undefined) of undefined -> ejabberd_config:get_local_option({ldap_port, Host}); @@ -776,7 +787,9 @@ parse_options(Host, Opts) -> backups = LDAPBackups, port = LDAPPort, tls_options = [{encrypt, LDAPEncrypt}, - {tls_verify, LDAPTLSVerify}], + {tls_verify, LDAPTLSVerify}, + {tls_cacertfile, LDAPTLSCAFile}, + {tls_depth, LDAPTLSDepth}], dn = RootDN, base = LDAPBase, password = Password,