[Exim] LDAP and exim

Top Page
Delete this message
Reply to this message
Author: Lawrence Walton
Date:  
To: exim
Subject: [Exim] LDAP and exim
This is a from Lindell Alderman, forwarded from me.
Mr Hazel:

I tried to send this email to your email address but it bounced
so I am posting this to the exim-users email list. Lawrence Walton has
been in contact with you over the past several days regarding a bug in Exim
that we have been struggling with. I have been working with him on this
project. Finally, I think that I have identified the source of the bug.

The problem we were having is that our LDAP lookup for UIDs did not
work correctly in our local delivery transport. I could lookup the
value for other fields in the transport just fine. But when I tried
to set the "user" string like this:

-- from exim.conf
user = ${lookup ldap{ldap:///ou=people,ou=business,dc=${domain},o=top?uidNumber?sub?(mail=${local_part}@${domain})}{$value}}
--

I kept getting LDAP errors like this:

-- from exim mainlog --
2002-04-03 04:39:34 16scR1-0006dT-00 == seth.ohare@??? <seth.ohare@???
> T=ldap_delivery defer (-30): Failed to expand user string "${extract{3}{/}{${l

ookup ldap{ldap:///ou=people,ou=business,dc=$domain,o=top?homeDirectory?sub?(mai
l=$local_part@$domain)}{$value}fail}}}" from the ldap_delivery transport: lookup
of "ldap:///ou=people,ou=business,dc=otak.com,o=top?homeDirectory?sub?(mail=set
h.ohare@???)" gave DEFER: ldap search initiation failed
--

I spent a lot of time fiddling with the lookup and discovered that it failed
with two ldap fields in particular: "uid" and "uidNumber".
I could lookup other fields and set the user string just fine. In that
case, exim would give me an error that it could "find the user." I thought
that perhaps the problem was the field itself, but then I discovered that if
I appended some string to the end of the lookup, then the lookup itself
would work.

-- from exim mainlog --
2002-04-03 02:43:48 16sacC-0006Nj-00 Failed to find user "setho1" from expanded
string "${local_part:${lookup ldap{ldap:///mailAlias=$local_part,ou=mailingLists
,ou=business,dc=otak.com,o=top?mailAliasedName?sub?(objectclass=*)}{$value}{nobo
dy}}}1" from the ldap_delivery transport
--

However, if I removed the appended string, the the same ldap lookup fails.
After trying unsuccessfully to make the transport lookup work, I tried moving
the user ldap lookup from the transport to a director. When I did this the
same ldap lookup worked perfectly!

This leads me to suspect that there is a very subtle bug in the way that
the transport code interacts with ldap lookups.


Finally, I discovered a bug in the ldap error handling code. When
Lawrence and I were first testing our ldap lookups we found that
ldap queries kept failing part way through. It turned out that
the ldap_err2string call was crashing the ldap library because
the was passing in a NULL result. The openldap library contains
an assert statement in ldap_err2string that "result != NULL".
So whenever ldap_err2string is called with a NULL it crashes.

Here is the code that I believe is causing the problem. This code is
from perform_ldap_search

-- from ldap.c
/* Annoyingly, the different implementations of LDAP have gone for different
methods of handling error codes and generating error messages. */

if (rc == -1)
  {
    DEBUG(9) debug_printf("ldap_result failed\n");


      #if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2
        *errmsg = string_sprintf("ldap_result failed: %s",
           ldap_err2string(ldap_result2error(lcp->ld, result, 0)));
--


As a quick hack to fix the problem, I changed the code as follows:
(I used C++ // instead of /* */ so this isn't as portable as it should be)

-- from ldap.c
/* Annoyingly, the different implementations of LDAP have gone for different
methods of handling error codes and generating error messages. */

if (rc == -1)
  {
    DEBUG(9) debug_printf("ldap_result failed\n");


      #if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2
        // *errmsg = string_sprintf("ldap_result failed: %s",
        // ldap_err2string(ldap_result2error(lcp->ld, result, 0)));
        *errmsg = string_sprintf("ldap_result faildd");
--


I've attached a diff patch for ldap.c that you can use to debug
the problem.

Lindell Alderman

--LZvS9be/3tNcYl/X
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ldap.c.patch"

--- ldap.c.bak    Tue Apr  2 11:21:49 2002
+++ ldap.c    Tue Apr  2 12:29:34 2002
@@ -467,9 +467,9 @@
   DEBUG(9) debug_printf("ldap_result failed\n");


   #if defined LDAP_LIB_SOLARIS || defined LDAP_LIB_OPENLDAP2
-    *errmsg = string_sprintf("ldap_result failed: %s",
-      ldap_err2string(ldap_result2error(lcp->ld, result, 0)));
-
+    // *errmsg = string_sprintf("ldap_result failed: %s",
+    // ldap_err2string(ldap_result2error(lcp->ld, result, 0)));
+    *errmsg = string_sprintf("ldap_result faildd");
   #elif defined LDAP_LIB_NETSCAPE
     {
     char *error, *matched;


--LZvS9be/3tNcYl/X--


--
*--* Mail: lawrence@???
*--* Voice: 425.739.4247
*--* Fax: 425.827.9577
*--* HTTP://www.otak-k.com/~lawrence/
--------------------------------------
- - - - - - O t a k i n c . - - - - -