Bug #2846
closedLDAP authentication vs. AD: problems with referrals
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);
Files
Updated by bjornfor almost 7 years 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.)
Updated by bjornfor almost 7 years 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.)
Updated by gstrauss almost 7 years ago
- Target version changed from 1.4.49 to 1.4.x
Updated by gstrauss almost 7 years ago
- Related to Feature #2294: add ldap referrals support added
Updated by gstrauss almost 7 years ago
- Related to Bug #2464: patch for intermittent ldap failures added
Updated by gstrauss almost 7 years 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
Updated by gstrauss almost 7 years 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);
Updated by gstrauss almost 7 years ago
- Status changed from New to Patch Pending
- Target version changed from 1.4.x to 1.4.49
Updated by gstrauss almost 7 years ago
- Status changed from Patch Pending to Fixed
- % Done changed from 0 to 100
Applied in changeset d5f37803ddaec9bd21f7dc23145047d5b12a9c28.
Also available in: Atom