Re: [Exim] Using LDAP for SMTP Authentication

Top Page
Delete this message
Reply to this message
Author: John Dalbec
Date:  
To: Jeffrey C. Ollie, Exim Users Mailing List
Subject: Re: [Exim] Using LDAP for SMTP Authentication

"Jeffrey C. Ollie" wrote:
>
> 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}


The combination of the above server condition and the patch below is an open
relay. If the password is a null string ("", not NULL), then the LDAP bind is
treated as an explicit anonymous bind and succeeds. The user does not have to
be defined in the LDAP database.

From openldap-software:
> This behavior is defined by the design of ldap
>
> It is described in RFC2829, but most clearly stated in
> draft-ietf-ldapbis-authmeth
>
>    An LDAP client MAY also choose to explicitly bind anonymously. A
>    client that wishes to do so MUST choose the simple authentication
>    option in the Bind Request (see section 4.1) and set the password to
>    be of zero length. (This is often done by LDAPv2 clients.) Typically
>    the name is also of zero length.


This can be fixed by changing either the server condition or the patch.
Example:

server_condition = ${if eq {$2}{}{no}{${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)


The patch may be fixed by changing the above line to:

+ if (lcp->bound && lcp->user != NULL && lcp->password != NULL &&
*(lcp->password) != '\0')

> +    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 */

>
>    {

>
> --
> ## List details at http://www.exim.org/mailman/listinfo/exim-users Exim details at http://www.exim.org/ ##