Make ldap_require_cert work (not segfault).
[exim.git] / src / src / lookups / ldap.c
index b0a4cc2e95045362376d416cd4092b12a19fa1b4..06b74946912ff5d9ecc25930103f519d0f56db64 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/lookups/ldap.c,v 1.13 2006/12/19 14:51:34 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/ldap.c,v 1.15 2009/11/16 19:50:38 nm4 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Many thanks to Stuart Lynne for contributing the original code for this
@@ -15,20 +15,6 @@ researching how to handle the different kinds of error. */
 
 #include "../exim.h"
 #include "lf_functions.h"
-#include "ldap.h"
-
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the LDAP headers
-available for compiling. Therefore, compile these functions only if LOOKUP_LDAP
-is defined. However, some compilers don't like compiling empty modules, so keep
-them happy with a dummy when skipping the rest. Make it reference itself to
-stop picky compilers complaining that it is unused, and put in a dummy argument
-to stop even pickier compilers complaining about infinite loops. */
-
-#ifndef LOOKUP_LDAP
-static void dummy(int x) { dummy(x-1); }
-#else
 
 
 /* Include LDAP headers. The code below uses some "old" LDAP interfaces that
@@ -445,6 +431,60 @@ if (lcp == NULL)
     }
   #endif  /* LDAP_OPT_X_TLS */
 
+  #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);
+    }
+  #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);
+    }
+  #endif
+  #ifdef LDAP_OPT_X_TLS_CERTFILE
+  if (eldap_cert_file != NULL)
+    {
+    ldap_set_option(ld, 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);
+    }
+  #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);
+    }
+  #endif
+  #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
+  if (eldap_require_cert != NULL)
+    {
+    int cert_option = LDAP_OPT_X_TLS_NEVER;
+    if (Ustrcmp(eldap_require_cert, "hard") == 0)
+      {
+      cert_option = LDAP_OPT_X_TLS_HARD;
+      }
+    else if (Ustrcmp(eldap_require_cert, "demand") == 0)
+      {
+      cert_option = LDAP_OPT_X_TLS_DEMAND;
+      }
+    else if (Ustrcmp(eldap_require_cert, "allow") == 0)
+      {
+      cert_option = LDAP_OPT_X_TLS_ALLOW;
+      }
+    else if (Ustrcmp(eldap_require_cert, "try") == 0)
+      {
+      cert_option = LDAP_OPT_X_TLS_TRY;
+      }
+    ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert_option);
+    }
+  #endif
+
   /* Now add this connection to the chain of cached connections */
 
   lcp = store_get(sizeof(LDAP_CONNECTION));
@@ -481,6 +521,10 @@ if (!lcp->bound ||
   {
   DEBUG(D_lookup) debug_printf("%sbinding with user=%s password=%s\n",
     (lcp->bound)? "re-" : "", user, password);
+  if (eldap_start_tls)
+    {
+    ldap_start_tls_s(lcp->ld, NULL, NULL);
+    }
   if ((msgid = ldap_bind(lcp->ld, CS user, CS password, LDAP_AUTH_SIMPLE))
        == -1)
     {
@@ -1196,7 +1240,7 @@ return DEFER;
 are handled by a common function, with a flag to differentiate between them.
 The handle and filename arguments are not used. */
 
-int
+static int
 eldap_find(void *handle, uschar *filename, uschar *ldap_url, int length,
   uschar **result, uschar **errmsg, BOOL *do_cache)
 {
@@ -1205,7 +1249,7 @@ do_cache = do_cache;
 return(control_ldap_search(ldap_url, SEARCH_LDAP_SINGLE, result, errmsg));
 }
 
-int
+static int
 eldapm_find(void *handle, uschar *filename, uschar *ldap_url, int length,
   uschar **result, uschar **errmsg, BOOL *do_cache)
 {
@@ -1214,7 +1258,7 @@ do_cache = do_cache;
 return(control_ldap_search(ldap_url, SEARCH_LDAP_MULTIPLE, result, errmsg));
 }
 
-int
+static int
 eldapdn_find(void *handle, uschar *filename, uschar *ldap_url, int length,
   uschar **result, uschar **errmsg, BOOL *do_cache)
 {
@@ -1240,7 +1284,7 @@ return(control_ldap_search(ldap_url, SEARCH_LDAP_AUTH, result, errmsg));
 
 /* See local README for interface description. */
 
-void *
+static void *
 eldap_open(uschar *filename, uschar **errmsg)
 {
 return (void *)(1);    /* Just return something non-null */
@@ -1255,7 +1299,7 @@ return (void *)(1);    /* Just return something non-null */
 /* See local README for interface description.
 Make sure that eldap_dn does not refer to reclaimed or worse, freed store */
 
-void
+static void
 eldap_tidy(void)
 {
 LDAP_CONNECTION *lcp = NULL;
@@ -1351,7 +1395,7 @@ quote_ldap_dn, respectively. */
 
 
 
-uschar *
+static uschar *
 eldap_quote(uschar *s, uschar *opt)
 {
 register int c;
@@ -1470,6 +1514,66 @@ else
 return quoted;
 }
 
-#endif  /* LOOKUP_LDAP */
+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+ldap_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: LDAP: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
+static lookup_info ldap_lookup_info = {
+  US"ldap",                      /* lookup name */
+  lookup_querystyle,             /* query-style lookup */
+  eldap_open,                    /* open function */
+  NULL,                          /* check function */
+  eldap_find,                    /* find function */
+  NULL,                          /* no close function */
+  eldap_tidy,                    /* tidy function */
+  eldap_quote,                   /* quoting function */
+  ldap_version_report            /* version reporting */
+};
+
+static lookup_info ldapdn_lookup_info = {
+  US"ldapdn",                     /* lookup name */
+  lookup_querystyle,             /* query-style lookup */
+  eldap_open,       /* sic */    /* open function */
+  NULL,                          /* check function */
+  eldapdn_find,                  /* find function */
+  NULL,                          /* no close function */
+  eldap_tidy,       /* sic */    /* tidy function */
+  eldap_quote,      /* sic */    /* quoting function */
+  NULL                           /* no version reporting (redundant) */
+};
+
+static lookup_info ldapm_lookup_info = {
+  US"ldapm",                     /* lookup name */
+  lookup_querystyle,             /* query-style lookup */
+  eldap_open,       /* sic */    /* open function */
+  NULL,                          /* check function */
+  eldapm_find,                   /* find function */
+  NULL,                          /* no close function */
+  eldap_tidy,       /* sic */    /* tidy function */
+  eldap_quote,      /* sic */    /* quoting function */
+  NULL                           /* no version reporting (redundant) */
+};
+
+#ifdef DYNLOOKUP
+#define ldap_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &ldap_lookup_info, &ldapdn_lookup_info, &ldapm_lookup_info };
+lookup_module_info ldap_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 3 };
 
 /* End of lookups/ldap.c */