Project

General

Profile

Bug #2846

LDAP authentication vs. AD: problems with referrals

Added by nperraud 10 months ago. Updated 8 months ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
Category:
mod_auth
Target version:
Start date:
2017-12-07
Due date:
% Done:

100%

Estimated time:
Missing in 1.5.x:

Description

Hello,

I was having difficulties setting up Lighttpd to authenticate users against a Windows 2008 domain controler (LDAP). Anonymous browsing is not permitted, but I'm not sure if that changes anything.

By default, the ldap_search_ext_s function, which is used in mod_authn_ldap_search, will follow LDAP refferals. The referral queries seem to be done anonymously, regardless if the first bind was authenticated (ref. ldap_set_option(3)).

In my case, the first, authenticated ldap search will succeed in finding the one user object that is expected, but the subsequent binds initiated to follow referrals fail. Even if not because of the failed binding, there wouldn't be a matching object in the referral scopes, and I expect that would be the case for most configurations in this context.

Because of the way LDAP authentication is currently (as of 1.4.48) implemented in mod_authn_ldap, the last referral query, resulting in either an error or empty result, seems to take over the first successful reply.

I fail to see a good reason to enable the following of LDAP referrals here, so disabling referral tracking by setting the following in mod_authn_ldap_host_init seems to solve the issue:

ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);

mod_authn_ldap.patch (761 Bytes) mod_authn_ldap.patch nperraud, 2017-12-07 09:36

Related issues

Related to Feature #2294: add ldap referrals supportMissing Feedback2011-02-03

Actions
Related to Bug #2464: patch for intermittent ldap failuresFixed2012-12-19

Actions

Associated revisions

Revision d5f37803 (diff)
Added by gstrauss 8 months ago

[mod_authn_ldap] auth with ldap referrals (fixes #2846)

use ldap_set_rebind_proc() to provide auth when rebinding following
ldap referrals (instead of rebinding anonymously for ldap referrals)

x-ref:
"LDAP authentication vs. AD: problems with referrals"
https://redmine.lighttpd.net/issues/2846

History

#1

Updated by bjornfor 9 months ago

Same situation here. And I wrote a very similar patch today :-)

After testing the patch I got a tip from a co-worker that my base DN was too broad, i.e. "dc=example,dc=com", and with his help we changed it to something like "ou=users,dc=example,dc=com". With this more specific base DN, unpatched lighttpd works. (I use this now, but would prefer the broad base DN to work too. It seems e.g. Apache and Gogs can handle the broad base DN.)

#2

Updated by bjornfor 9 months ago

Observation: Apache has a runtime option whether to follow referrals called LDAPReferrals, https://httpd.apache.org/docs/2.4/mod/mod_ldap.html#ldapreferrals. It defaults to "on". That makes me wonder if Apache does re-authentication with user/pw when following the referral. I found this snippet in $APACHE_SRC/modules/ldap/util_ldap.c, which seems to support this idea:

     if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
        /* Now that we have an ldap struct, add it to the referral list for rebinds. */
        rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);

Gogs does not have any "referral" option (and no mention of "referral" in its documentation), but also works (unmodified) against our LDAP server. (I grepped for "referral" in its source code but didn't understand whether it followed them or not.)

#3

Updated by gstrauss 9 months ago

  • Target version changed from 1.4.49 to 1.4.x
#4

Updated by gstrauss 8 months ago

#5

Updated by gstrauss 8 months ago

  • Related to Bug #2464: patch for intermittent ldap failures added
#6

Updated by gstrauss 8 months ago

For those following this, please be aware there is a memory leak patch for mod_authn_ldap in git master, which will be part of lighttpd 1.4.49 (not yet released). See #2849

#7

Updated by gstrauss 8 months ago

Untested patch which follows referrals and rebinds using authentication (not anonymous) for ldap searches, but disables referrals when binding only to verify user auth. Feedback appreciated.

--- a/src/mod_authn_ldap.c
+++ b/src/mod_authn_ldap.c
@@ -12,6 +12,7 @@

 typedef struct {
     LDAP *ldap;
+    server *srv;

     buffer *auth_ldap_hostname;
     buffer *auth_ldap_basedn;
@@ -450,6 +451,18 @@ static int mod_authn_ldap_bind(server *srv, LDAP *ld, const
 char *dn, const char
     return ret;
 }

+static int mod_authn_ldap_rebind_proc (LDAP *ld, LDAP_CONST char *url, ber_tag_
t ldap_request, ber_int_t msgid, void *params) {
+    plugin_config *s = (plugin_config *)params;
+    UNUSED(url);
+    UNUSED(ldap_request);
+    UNUSED(msgid);
+    return !buffer_string_is_empty(s->auth_ldap_binddn)
+      ? mod_authn_ldap_bind(s->srv, ld,
+                            s->auth_ldap_binddn->ptr,
+                            s->auth_ldap_bindpw->ptr)
+      : mod_authn_ldap_bind(s->srv, ld, NULL, NULL);
+}
+
 static LDAPMessage * mod_authn_ldap_search(server *srv, plugin_config *s, char *base, char *filter) {
     LDAPMessage *lm = NULL;
     char *attrs[] = { LDAP_NO_ATTRS, NULL };
@@ -484,11 +497,8 @@ static LDAPMessage * mod_authn_ldap_search(server *srv, plugin_config *s, char *
         return NULL;
     }

-    ret = !buffer_string_is_empty(s->auth_ldap_binddn)
-      ? mod_authn_ldap_bind(srv, s->ldap,
-                            s->auth_ldap_binddn->ptr,
-                            s->auth_ldap_bindpw->ptr)
-      : mod_authn_ldap_bind(srv, s->ldap, NULL, NULL);
+    ldap_set_rebind_proc(s->ldap, mod_authn_ldap_rebind_proc, s);
+    ret = mod_authn_ldap_rebind_proc(s->ldap, NULL, 0, 0, s);
     if (LDAP_SUCCESS != ret) {
         ldap_destroy(s->ldap);
         s->ldap = NULL;
@@ -588,6 +598,8 @@ static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, c
     handler_t rc;

     mod_authn_ldap_patch_connection(srv, con, p);
+    p->anon_conf->srv = srv;
+    p->conf.srv = srv;

     if (pw[0] == '\0' && !p->conf.auth_ldap_allow_empty_pw)
         return HANDLER_ERROR;
@@ -634,6 +646,17 @@ static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, c
         return HANDLER_ERROR;
     }

+    /* Disable referral tracking.  Target user should be in provided scope */
+    {
+        int ret = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+        if (LDAP_OPT_SUCCESS != ret) {
+            mod_authn_ldap_err(srv,__FILE__,__LINE__,"ldap_set_option()",ret);
+            ldap_destroy(ld);
+            if (dn != p->ldap_filter->ptr) ldap_memfree(dn);
+            return HANDLER_ERROR;
+        }
+    }
+
     if (LDAP_SUCCESS != mod_authn_ldap_bind(srv, ld, dn, pw)) {
         ldap_destroy(ld);
         if (dn != p->ldap_filter->ptr) ldap_memfree(dn);

#8

Updated by gstrauss 8 months ago

  • Status changed from New to Patch Pending
  • Target version changed from 1.4.x to 1.4.49
#9

Updated by gstrauss 8 months ago

  • Status changed from Patch Pending to Fixed
  • % Done changed from 0 to 100

Also available in: Atom