[Exim] Using LDAP for SMTP Authentication

Top Page
Delete this message
Reply to this message
Author: Jeffrey C. Ollie
Date:  
To: exim-users
Subject: [Exim] Using LDAP for SMTP Authentication
I've developed a patch against Exim 3.33 that adds a lookup type
called 'ldapauth'. It's similar to the other LDAP lookups except
this one returns a "yes" or a "no" depending on if the connection
to the LDAP server sucessfully completes a non-anonymous bind.

Here's an example of how I use it:

login:
driver = plaintext
public_name = LOGIN
server_prompts = "Username:: : Password::"
server_condition = ${lookup ldapauth {user="uid=${quote_ldap:$1},ou=people,o=example.org" pass="$2" ldap://ldap.example.org/}{$value} fail}
server_set_id = uid=$1,ou=people,o=example.org

The code has been minimally tested so far, but I'm fairly confident in it.

Here's the patch:

--- src/lookups/ldap.c.orig    Wed Oct  3 07:34:12 2001
+++ src/lookups/ldap.c    Thu Oct  4 08:46:51 2001
@@ -77,7 +77,7 @@
 #define SEARCH_LDAP_MULTIPLE 0       /* Get attributes from multiple entries */
 #define SEARCH_LDAP_SINGLE 1         /* Get attributes from one entry only */
 #define SEARCH_LDAP_DN 2             /* Get DN from one entry */
-
+#define SEARCH_LDAP_AUTH 3           /* Just checking for authentication */


/* Structure and anchor for caching connections. */

@@ -157,9 +157,16 @@
   debug_printf("perform_ldap_search: ldap%s URL =\"%s\" server=%s port=%d "
     "sizelimit=%d timelimit=%d\n",
     (search_type == SEARCH_LDAP_MULTIPLE)? "m" :
-    (search_type == SEARCH_LDAP_DN)? "dn" : "",
+    (search_type == SEARCH_LDAP_DN)? "dn" :
+    (search_type == SEARCH_LDAP_AUTH)? "auth" : "",
     ldap_url, server, s_port, sizelimit, timelimit);


+if (search_type == SEARCH_LDAP_AUTH && (user == NULL || password == NULL))
+ {
+ *errmsg = string_copy_malloc("ldapauth lookups must specify the username and password");
+ goto RETURN_ERROR;
+ }
+
/* Check if LDAP thinks the URL is a valid LDAP URL */

 if (!ldap_is_ldap_url(ldap_url))
@@ -233,6 +240,8 @@
   lcp = store_malloc(sizeof(LDAP_CONNECTION));
   lcp->host = (host == NULL)? NULL : string_copy_malloc(host);
   lcp->bound = FALSE;
+  lcp->user = NULL;
+  lcp->password = NULL;
   lcp->port = port;
   lcp->ld = ld;
   lcp->next = ldap_connections;
@@ -263,6 +272,11 @@
   if ((rc = ldap_bind_s(lcp->ld, user, password, LDAP_AUTH_SIMPLE))
        != LDAP_SUCCESS)
     {
+    if (search_type == SEARCH_LDAP_AUTH)
+      {
+      data = string_copy_malloc("no");
+      goto RETURN_OK;
+      }
     *errmsg = string_sprintf("failed to bind the LDAP connection to server "
       "%s:%d - LDAP error %d: %s", host, port, rc, ldap_err2string(rc));
     goto RETURN_ERROR;
@@ -272,6 +286,15 @@
   lcp->password = (password == NULL)? NULL : string_copy_malloc(password);
   }


+if (search_type == SEARCH_LDAP_AUTH)
+  {
+  if (lcp->bound && lcp->user != NULL && lcp->password != NULL)
+    data = string_copy_malloc("yes");
+  else
+    data = string_copy_malloc("no");
+  goto RETURN_OK;
+  }
+
 /* Before doing the search, set the time and size limits (if given). Here again
 the different implementations of LDAP have chosen to do things differently. */


@@ -515,7 +538,7 @@
}

/* Otherwise, it's all worked */
-
+RETURN_OK:
DEBUG(9) debug_printf("LDAP search: returning: %s\n", data);
*res = data;
ldap_free_urldesc(ludp);
@@ -672,6 +695,13 @@
return(control_ldap_search(ldap_url, SEARCH_LDAP_DN, result, errmsg));
}

+int
+eldapauth_find(void *handle, char *filename, char *ldap_url, int length,
+ char **result, char **errmsg)
+{
+return(control_ldap_search(ldap_url, SEARCH_LDAP_AUTH, result, errmsg));
+}
+


 /*************************************************
@@ -705,6 +735,8 @@
   ldap_unbind(lcp->ld);
   ldap_connections = lcp->next;
   if (lcp->host != NULL) store_free(lcp->host);
+  if (lcp->user != NULL) store_free(lcp->user);
+  if (lcp->password != NULL) store_free(lcp->password);
   store_free(lcp);
   }
 }
--- src/lookups/ldap.h.orig    Wed Oct  3 07:34:21 2001
+++ src/lookups/ldap.h    Wed Oct  3 08:06:19 2001
@@ -11,6 +11,7 @@
 extern int   eldap_find(void *, char *, char *, int, char **, char **);
 extern int   eldapdn_find(void *, char *, char *, int, char **, char **);
 extern int   eldapm_find(void *, char *, char *, int, char **, char **);
+extern int   eldapauth_find(void *, char *, char *, int, char **, char **);
 extern void  eldap_tidy(void);
 extern char *eldap_quote(char *);


--- src/drtables.c.orig    Wed Aug 15 06:09:08 2001
+++ src/drtables.c    Wed Oct  3 08:05:01 2001
@@ -174,6 +174,23 @@
 #endif
   },


+/* LDAP lookup, just checking for authentication */
+
+  {
+  "ldapauth",                       /* lookup name */
+  lookup_querystyle,             /* query-style lookup */
+#ifdef LOOKUP_LDAP
+  eldap_open,       /* sic */    /* open function */
+  NULL,                          /* check function */
+  eldapauth_find,                  /* find function */
+  NULL,                          /* no close function */
+  eldap_tidy,       /* sic */    /* tidy function */
+  eldap_quote       /* sic */    /* quoting function */
+#else
+  NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
+#endif
+  },
+
 /* LDAP lookup, allowing data from more than one entry to be returned */


{