diff -ur clean/httpd-2.2.15/modules/ldap/util_ldap.c apache/httpd-2.2.15/modules/ldap/util_ldap.c --- clean/httpd-2.2.15/modules/ldap/util_ldap.c 2009-12-18 16:09:40.000000000 +0200 +++ apache/httpd-2.2.15/modules/ldap/util_ldap.c 2011-03-24 12:45:23.000000000 +0200 @@ -32,6 +32,7 @@ #include "util_ldap_cache.h" #include +#include #if APR_HAVE_UNISTD_H #include @@ -73,6 +74,15 @@ apr_global_mutex_unlock(st->util_ldap_cache_lock); \ } while (0) +#ifdef SASL_H +typedef struct { + const char *passwd; + const char *realm; + const char *authzid; + request_rec *request; +} uldap_sasl_ctx; +#endif + static void util_ldap_strdup (char **str, const char *newstr) { if (*str) { @@ -330,6 +340,57 @@ return(rc); } +#ifdef SASL_H +static int uldap_sasl_interact(LDAP *ldap, unsigned flags, void *defaults, void *in) +{ + sasl_interact_t *interact = in; + uldap_sasl_ctx *ctx = defaults; + const char *p; + + for (;interact->id != SASL_CB_LIST_END;interact++) { + p = NULL; + switch(interact->id) { + case SASL_CB_GETREALM: + p = ctx->realm; + break; + case SASL_CB_AUTHNAME: + p = ctx->request->user; + break; + case SASL_CB_USER: + p = ctx->authzid; + break; + case SASL_CB_PASS: + p = ctx->passwd; + break; + } + if (p) { + interact->result = p; + interact->len = strlen(interact->result); + } + } + return LDAP_SUCCESS; +} + +static int uldap_sasl_bind(request_rec *r, util_ldap_connection_t *ldc, const char *bindpw, const char *binddn) +{ + int rc; + uldap_sasl_ctx ctx; + + ctx.passwd=bindpw; + ctx.realm=NULL; + ctx.authzid=NULL; + ctx.request=r; + + rc = ldap_sasl_interactive_bind_s(ldc->ldap, binddn, "PLAIN", NULL, NULL, LDAP_SASL_QUIET, uldap_sasl_interact, &ctx); + + if (rc != LDAP_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "LDAP: SASL Failed %s", ldap_err2string(rc)); + rc = ldap_simple_bind_s(ldc->ldap, binddn, bindpw); + } + return rc; +} +#endif + /* * Connect to the LDAP server and binds. Does not connect if already * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound. @@ -1023,9 +1084,7 @@ * fails, it means that the password is wrong (the dn obviously * exists, since we just retrieved it) */ - result = ldap_simple_bind_s(ldc->ldap, - (char *)*binddn, - (char *)bindpw); + result = uldap_sasl_bind(r, ldc, bindpw, *binddn); if (AP_LDAP_IS_SERVER_DOWN(result)) { ldc->reason = "ldap_simple_bind_s() to check user credentials " "failed with server down";