* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Many thanks to Stuart Lynne for contributing the original code for this
*/
static int
-perform_ldap_search(uschar *ldap_url, uschar *server, int s_port, int search_type,
- uschar **res, uschar **errmsg, BOOL *defer_break, uschar *user, uschar *password,
- int sizelimit, int timelimit, int tcplimit, int dereference, void *referrals)
+perform_ldap_search(const uschar *ldap_url, uschar *server, int s_port,
+ int search_type, uschar **res, uschar **errmsg, BOOL *defer_break,
+ uschar *user, uschar *password, int sizelimit, int timelimit, int tcplimit,
+ int dereference, void *referrals)
{
LDAPURLDesc *ludp = NULL;
LDAPMessage *result = NULL;
{
LDAP *ld;
+ #ifdef LDAP_OPT_X_TLS_NEWCTX
+ int am_server = 0;
+ LDAP *ldsetctx;
+ #else
+ LDAP *ldsetctx = NULL;
+ #endif
+
/* --------------------------- OpenLDAP ------------------------ */
goto RETURN_ERROR;
}
+ #ifdef LDAP_OPT_X_TLS_NEWCTX
+ ldsetctx = ld;
+ #endif
+
/* Set the TCP connect time limit if available. This is something that is
in Netscape SDK v4.1; I don't know about other libraries. */
#ifdef LDAP_OPT_X_TLS_CACERTFILE
if (eldap_ca_cert_file != NULL)
{
- ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTFILE, eldap_ca_cert_file);
+ ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_CACERTFILE, eldap_ca_cert_file);
}
#endif
#ifdef LDAP_OPT_X_TLS_CACERTDIR
if (eldap_ca_cert_dir != NULL)
{
- ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTDIR, eldap_ca_cert_dir);
+ ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_CACERTDIR, eldap_ca_cert_dir);
}
#endif
#ifdef LDAP_OPT_X_TLS_CERTFILE
if (eldap_cert_file != NULL)
{
- ldap_set_option(ld, LDAP_OPT_X_TLS_CERTFILE, eldap_cert_file);
+ ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_CERTFILE, eldap_cert_file);
}
#endif
#ifdef LDAP_OPT_X_TLS_KEYFILE
if (eldap_cert_key != NULL)
{
- ldap_set_option(ld, LDAP_OPT_X_TLS_KEYFILE, eldap_cert_key);
+ ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_KEYFILE, eldap_cert_key);
}
#endif
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
if (eldap_cipher_suite != NULL)
{
- ldap_set_option(ld, LDAP_OPT_X_TLS_CIPHER_SUITE, eldap_cipher_suite);
+ ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_CIPHER_SUITE, eldap_cipher_suite);
}
#endif
#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
{
cert_option = LDAP_OPT_X_TLS_TRY;
}
- /* Use NULL ldap handle because is a global option */
- ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert_option);
+ /* This ldap handle is set at compile time based on client libs. Older
+ * versions want it to be global and newer versions can force a reload
+ * of the TLS context (to reload these settings we are changing from the
+ * default that loaded at instantiation). */
+ rc = ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert_option);
+ if (rc)
+ {
+ DEBUG(D_lookup)
+ debug_printf("Unable to set TLS require cert_option(%d) globally: %s\n",
+ cert_option, ldap_err2string(rc));
+ }
+ }
+ #endif
+ #ifdef LDAP_OPT_X_TLS_NEWCTX
+ rc = ldap_set_option(ldsetctx, LDAP_OPT_X_TLS_NEWCTX, &am_server);
+ if (rc)
+ {
+ DEBUG(D_lookup)
+ debug_printf("Unable to reload TLS context %d: %s\n",
+ rc, ldap_err2string(rc));
}
#endif
DEBUG(D_lookup) debug_printf("LDAP attr loop %s:%s\n", attr, value);
- if (values != firstval)
+ /* In case we requested one attribute only but got
+ * several times into that attr loop, we need to append
+ * the additional values. (This may happen if you derive
+ * attributeTypes B and C from A and then query for A.)
+ * In all other cases we detect the different attribute
+ * and append only every non first value. */
+ if ((attr_count == 1 && data) || (values != firstval))
data = string_cat(data, &size, &ptr, US",", 1);
/* For multiple attributes, the data is in quotes. We must escape
*/
static int
-control_ldap_search(uschar *ldap_url, int search_type, uschar **res,
+control_ldap_search(const uschar *ldap_url, int search_type, uschar **res,
uschar **errmsg)
{
BOOL defer_break = FALSE;
int sep = 0;
int dereference = LDAP_DEREF_NEVER;
void* referrals = LDAP_OPT_ON;
-uschar *url = ldap_url;
-uschar *p;
+const uschar *url = ldap_url;
+const uschar *p;
uschar *user = NULL;
uschar *password = NULL;
-uschar *server, *list;
+uschar *local_servers = NULL;
+uschar *server;
+const uschar *list;
uschar buffer[512];
while (isspace(*url)) url++;
while (strncmpic(url, US"ldap", 4) != 0)
{
- uschar *name = url;
+ const uschar *name = url;
while (*url != 0 && *url != '=') url++;
if (*url == '=')
{
else if (strncmpic(name, US"TIME=", namelen) == 0) timelimit = Uatoi(value);
else if (strncmpic(name, US"CONNECT=", namelen) == 0) tcplimit = Uatoi(value);
else if (strncmpic(name, US"NETTIME=", namelen) == 0) tcplimit = Uatoi(value);
+ else if (strncmpic(name, US"SERVERS=", namelen) == 0) local_servers = value;
/* Don't know if all LDAP libraries have LDAP_OPT_DEREF */
/* No default servers, or URL contains a server name: just one attempt */
-if (eldap_default_servers == NULL || p[3] != '/')
+if ((eldap_default_servers == NULL && local_servers == NULL) || p[3] != '/')
{
return perform_ldap_search(url, NULL, 0, search_type, res, errmsg,
&defer_break, user, password, sizelimit, timelimit, tcplimit, dereference,
referrals);
}
-/* Loop through the default servers until OK or FAIL */
-
-list = eldap_default_servers;
+/* Loop through the default servers until OK or FAIL. Use local_servers list
+ * if defined in the lookup, otherwise use the global default list */
+list = (local_servers == NULL) ? eldap_default_servers : local_servers;
while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
{
int rc;
The handle and filename arguments are not used. */
static int
-eldap_find(void *handle, uschar *filename, uschar *ldap_url, int length,
+eldap_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
/* Keep picky compilers happy */
}
static int
-eldapm_find(void *handle, uschar *filename, uschar *ldap_url, int length,
+eldapm_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
/* Keep picky compilers happy */
}
static int
-eldapdn_find(void *handle, uschar *filename, uschar *ldap_url, int length,
+eldapdn_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
/* Keep picky compilers happy */
}
int
-eldapauth_find(void *handle, uschar *filename, uschar *ldap_url, int length,
+eldapauth_find(void *handle, uschar *filename, const uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
/* Keep picky compilers happy */