summaryrefslogtreecommitdiffstats
path: root/modules/ldap/util_ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ldap/util_ldap.c')
-rw-r--r--modules/ldap/util_ldap.c162
1 files changed, 108 insertions, 54 deletions
diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c
index 08f986c..aa0bad1 100644
--- a/modules/ldap/util_ldap.c
+++ b/modules/ldap/util_ldap.c
@@ -75,15 +75,61 @@ module AP_MODULE_DECLARE_DATA ldap_module;
static const char *ldap_cache_mutex_type = "ldap-cache";
static apr_status_t uldap_connection_unbind(void *param);
-#define LDAP_CACHE_LOCK() do { \
- if (st->util_ldap_cache_lock) \
- apr_global_mutex_lock(st->util_ldap_cache_lock); \
-} while (0)
+/* For OpenLDAP with the 3-arg version of ldap_set_rebind_proc(), use
+ * a simpler rebind callback than the implementation in APR-util.
+ * Testing for API version >= 3001 appears safe although OpenLDAP
+ * 2.1.x (API version = 2004) also has the 3-arg API. */
+#if APR_HAS_OPENLDAP_LDAPSDK && defined(LDAP_API_VERSION) && LDAP_API_VERSION >= 3001
-#define LDAP_CACHE_UNLOCK() do { \
- if (st->util_ldap_cache_lock) \
- apr_global_mutex_unlock(st->util_ldap_cache_lock); \
-} while (0)
+#define uldap_rebind_init(p) APR_SUCCESS /* noop */
+
+static int uldap_rebind_proc(LDAP *ld, const char *url, ber_tag_t request,
+ ber_int_t msgid, void *params)
+{
+ util_ldap_connection_t *ldc = params;
+
+ return ldap_bind_s(ld, ldc->binddn, ldc->bindpw, LDAP_AUTH_SIMPLE);
+}
+
+static apr_status_t uldap_rebind_add(util_ldap_connection_t *ldc)
+{
+ ldap_set_rebind_proc(ldc->ldap, uldap_rebind_proc, ldc);
+ return APR_SUCCESS;
+}
+
+#else /* !APR_HAS_OPENLDAP_LDAPSDK */
+
+#define USE_APR_LDAP_REBIND
+#include <apr_ldap_rebind.h>
+
+#define uldap_rebind_init(p) apr_ldap_rebind_init(p)
+#define uldap_rebind_add(ldc) apr_ldap_rebind_add((ldc)->rebind_pool, \
+ (ldc)->ldap, (ldc)->binddn, \
+ (ldc)->bindpw)
+#endif
+
+static APR_INLINE apr_status_t ldap_cache_lock(util_ldap_state_t *st, request_rec *r) {
+ apr_status_t rv = APR_SUCCESS;
+ if (st->util_ldap_cache_lock) {
+ apr_status_t rv = apr_global_mutex_lock(st->util_ldap_cache_lock);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, rv, r, APLOGNO(10134) "LDAP cache lock failed");
+ ap_assert(0);
+ }
+ }
+ return rv;
+}
+static APR_INLINE apr_status_t ldap_cache_unlock(util_ldap_state_t *st, request_rec *r) {
+ apr_status_t rv = APR_SUCCESS;
+ if (st->util_ldap_cache_lock) {
+ apr_status_t rv = apr_global_mutex_unlock(st->util_ldap_cache_lock);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, rv, r, APLOGNO(10135) "LDAP cache lock failed");
+ ap_assert(0);
+ }
+ }
+ return rv;
+}
static void util_ldap_strdup (char **str, const char *newstr)
{
@@ -181,6 +227,13 @@ static apr_status_t uldap_connection_unbind(void *param)
util_ldap_connection_t *ldc = param;
if (ldc) {
+#ifdef USE_APR_LDAP_REBIND
+ /* forget the rebind info for this conn */
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ apr_pool_clear(ldc->rebind_pool);
+ }
+#endif
+
if (ldc->ldap) {
if (ldc->r) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, ldc->r, "LDC %pp unbind", ldc);
@@ -189,12 +242,6 @@ static apr_status_t uldap_connection_unbind(void *param)
ldc->ldap = NULL;
}
ldc->bound = 0;
-
- /* forget the rebind info for this conn */
- if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
- apr_ldap_rebind_remove(ldc->ldap);
- apr_pool_clear(ldc->rebind_pool);
- }
}
return APR_SUCCESS;
@@ -250,7 +297,7 @@ static apr_status_t util_ldap_connection_remove (void *param)
apr_thread_mutex_unlock(st->mutex);
#endif
- /* Destory the pool associated with this connection */
+ /* Destroy the pool associated with this connection */
apr_pool_destroy(ldc->pool);
@@ -330,7 +377,7 @@ static int uldap_connection_init(request_rec *r,
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);
+ rc = uldap_rebind_add(ldc);
if (rc != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, APLOGNO(01277)
"LDAP: Unable to add rebind cross reference entry. Out of memory?");
@@ -817,6 +864,7 @@ static util_ldap_connection_t *
#endif
return NULL;
}
+ apr_pool_tag(newpool, "util_ldap_connection");
/*
* Add the new connection entry to the linked list. Note that we
@@ -855,6 +903,7 @@ static util_ldap_connection_t *
/* whether or not to keep this connection in the pool when it's returned */
l->keep = (st->connection_pool_ttl == 0) ? 0 : 1;
+#ifdef USE_APR_LDAP_REBIND
if (l->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
if (apr_pool_create(&(l->rebind_pool), l->pool) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01286)
@@ -864,7 +913,9 @@ static util_ldap_connection_t *
#endif
return NULL;
}
+ apr_pool_tag(l->rebind_pool, "util_ldap_rebind");
}
+#endif
if (p) {
p->next = l;
@@ -910,14 +961,14 @@ static int uldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc,
&ldap_module);
/* get cache entry (or create one) */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curnode.url = url;
curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
if (curl == NULL) {
curl = util_ald_create_caches(st, url);
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
/* a simple compare? */
if (!compare_dn_on_server) {
@@ -934,7 +985,7 @@ static int uldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc,
if (curl) {
/* no - it's a server side compare */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
/* is it in the compare cache? */
newnode.reqdn = (char *)reqdn;
@@ -942,13 +993,13 @@ static int uldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc,
if (node != NULL) {
/* If it's in the cache, it's good */
/* unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
ldc->reason = "DN Comparison TRUE (cached)";
return LDAP_COMPARE_TRUE;
}
/* unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
start_over:
@@ -1010,7 +1061,7 @@ start_over:
else {
if (curl) {
/* compare successful - add to the compare cache */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
newnode.reqdn = (char *)reqdn;
newnode.dn = (char *)dn;
@@ -1021,7 +1072,7 @@ start_over:
{
util_ald_cache_insert(curl->dn_compare_cache, &newnode);
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
ldc->reason = "DN Comparison TRUE (checked on server)";
result = LDAP_COMPARE_TRUE;
@@ -1056,17 +1107,17 @@ static int uldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
&ldap_module);
/* get cache entry (or create one) */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curnode.url = url;
curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
if (curl == NULL) {
curl = util_ald_create_caches(st, url);
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
if (curl) {
/* make a comparison to the cache */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curtime = apr_time_now();
the_compare_node.dn = (char *)dn;
@@ -1105,7 +1156,7 @@ static int uldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
/* record the result code to return with the reason... */
result = compare_nodep->result;
/* and unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r,
"ldap_compare_s(%pp, %s, %s, %s) = %s (cached)",
@@ -1114,7 +1165,7 @@ static int uldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
}
}
/* unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
start_over:
@@ -1162,7 +1213,7 @@ start_over:
(LDAP_NO_SUCH_ATTRIBUTE == result)) {
if (curl) {
/* compare completed; caching result */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_compare_node.lastcompare = curtime;
the_compare_node.result = result;
the_compare_node.sgl_processed = 0;
@@ -1191,7 +1242,7 @@ start_over:
compare_nodep->lastcompare = curtime;
compare_nodep->result = result;
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
if (LDAP_COMPARE_TRUE == result) {
@@ -1456,14 +1507,14 @@ static int uldap_cache_check_subgroups(request_rec *r,
* 2. Find previously created cache entry and check if there is already a
* subgrouplist.
*/
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curnode.url = url;
curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
if (curl && curl->compare_cache) {
/* make a comparison to the cache */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_compare_node.dn = (char *)dn;
the_compare_node.attrib = (char *)"objectClass";
@@ -1505,7 +1556,7 @@ static int uldap_cache_check_subgroups(request_rec *r,
}
}
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
if (!tmp_local_sgl && !sgl_cached_empty) {
@@ -1524,7 +1575,7 @@ static int uldap_cache_check_subgroups(request_rec *r,
/*
* Find the generic group cache entry and add the sgl we just retrieved.
*/
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_compare_node.dn = (char *)dn;
the_compare_node.attrib = (char *)"objectClass";
@@ -1589,7 +1640,7 @@ static int uldap_cache_check_subgroups(request_rec *r,
}
}
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
}
@@ -1667,17 +1718,17 @@ static int uldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc,
&ldap_module);
/* Get the cache node for this url */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curnode.url = url;
curl = (util_url_node_t *)util_ald_cache_fetch(st->util_ldap_cache,
&curnode);
if (curl == NULL) {
curl = util_ald_create_caches(st, url);
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
if (curl) {
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_search_node.username = filter;
search_nodep = util_ald_cache_fetch(curl->search_cache,
&the_search_node);
@@ -1709,13 +1760,13 @@ static int uldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc,
(*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
}
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
ldc->reason = "Authentication successful (cached)";
return LDAP_SUCCESS;
}
}
/* unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
/*
@@ -1874,7 +1925,7 @@ start_over:
* Add the new username to the search cache.
*/
if (curl) {
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_search_node.username = filter;
the_search_node.dn = *binddn;
the_search_node.bindpw = bindpw;
@@ -1905,7 +1956,7 @@ start_over:
/* Cache entry is valid, update lastbind */
search_nodep->lastbind = the_search_node.lastbind;
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
ldap_msgfree(res);
@@ -1943,17 +1994,17 @@ static int uldap_cache_getuserdn(request_rec *r, util_ldap_connection_t *ldc,
&ldap_module);
/* Get the cache node for this url */
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
curnode.url = url;
curl = (util_url_node_t *)util_ald_cache_fetch(st->util_ldap_cache,
&curnode);
if (curl == NULL) {
curl = util_ald_create_caches(st, url);
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
if (curl) {
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_search_node.username = filter;
search_nodep = util_ald_cache_fetch(curl->search_cache,
&the_search_node);
@@ -1979,13 +2030,13 @@ static int uldap_cache_getuserdn(request_rec *r, util_ldap_connection_t *ldc,
(*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
}
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
ldc->reason = "Search successful (cached)";
return LDAP_SUCCESS;
}
}
/* unlock this read lock */
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
/*
@@ -2083,7 +2134,7 @@ start_over:
* Add the new username to the search cache.
*/
if (curl) {
- LDAP_CACHE_LOCK();
+ ldap_cache_lock(st, r);
the_search_node.username = filter;
the_search_node.dn = *binddn;
the_search_node.bindpw = NULL;
@@ -2112,7 +2163,7 @@ start_over:
/* Cache entry is valid, update lastbind */
search_nodep->lastbind = the_search_node.lastbind;
}
- LDAP_CACHE_UNLOCK();
+ ldap_cache_unlock(st, r);
}
ldap_msgfree(res);
@@ -2736,12 +2787,14 @@ static const char *util_ldap_set_conn_ttl(cmd_parms *cmd,
void *dummy,
const char *val)
{
- apr_interval_time_t timeout;
+ apr_interval_time_t timeout = -1;
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
- if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) {
+ /* Negative values mean AP_LDAP_CONNPOOL_INFINITE */
+ if (val[0] != '-' &&
+ ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) {
return "LDAPConnectionPoolTTL has wrong format";
}
@@ -2810,6 +2863,7 @@ static void *util_ldap_create_config(apr_pool_t *p, server_rec *s)
* no shared memory managed by either.
*/
apr_pool_create(&st->pool, p);
+ apr_pool_tag(st->pool, "util_ldap_state");
#if APR_HAS_THREADS
apr_thread_mutex_create(&st->mutex, APR_THREAD_MUTEX_DEFAULT, st->pool);
#endif
@@ -2874,7 +2928,7 @@ static void *util_ldap_merge_config(apr_pool_t *p, void *basev,
able to handle the connection timeout per-connection
but the Novell SDK cannot. Allowing the timeout to
be set by each vhost is of little value so rather than
- trying to make special expections for one LDAP SDK, GLOBAL_ONLY
+ trying to make special exceptions for one LDAP SDK, GLOBAL_ONLY
is being enforced on this setting as well. */
st->connectionTimeout = base->connectionTimeout;
st->opTimeout = base->opTimeout;
@@ -3051,7 +3105,7 @@ static int util_ldap_post_config(apr_pool_t *p, apr_pool_t *plog,
}
/* Initialize the rebind callback's cross reference list. */
- apr_ldap_rebind_init (p);
+ (void) uldap_rebind_init(p);
#ifdef AP_LDAP_OPT_DEBUG
if (st->debug_level > 0) {