You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by bn...@apache.org on 2004/11/02 00:43:24 UTC
cvs commit: httpd-2.0/modules/ldap NWGNUmakefile util_ldap.c
bnicholes 2004/11/01 15:43:24
Modified: modules/ldap NWGNUmakefile util_ldap.c
Log:
Implement the util_ldap_cache_getuserdn() API so that the ldap authorization only modules have access to the util_ldap user cache without have to require ldap authentication as well. Also required by mod_authnz_ldap so that it's authorization functionality can be used independant from the authentication functionality. [PR 31898]
Submitted by: Jari Ahonen [jah progress.com]
Reviewed by: Brad Nicholes
Revision Changes Path
1.2 +1 -0 httpd-2.0/modules/ldap/NWGNUmakefile
Index: NWGNUmakefile
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/ldap/NWGNUmakefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- NWGNUmakefile 18 Aug 2004 22:18:39 -0000 1.1
+++ NWGNUmakefile 1 Nov 2004 23:43:24 -0000 1.2
@@ -226,6 +226,7 @@
util_ldap_connection_unbind \
util_ldap_connection_cleanup \
util_ldap_cache_checkuserid \
+ util_ldap_cache_getuserdn \
util_ldap_cache_compare \
util_ldap_cache_comparedn \
util_ldap_ssl_supported \
1.18 +191 -10 httpd-2.0/modules/ldap/util_ldap.c
Index: util_ldap.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/ldap/util_ldap.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- util_ldap.c 25 Oct 2004 18:32:58 -0000 1.17
+++ util_ldap.c 1 Nov 2004 23:43:24 -0000 1.18
@@ -745,24 +745,22 @@
LDAP_CACHE_LOCK();
the_search_node.username = filter;
search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node);
- if (search_nodep != NULL && search_nodep->bindpw) {
+ if (search_nodep != NULL) {
/* found entry in search cache... */
curtime = apr_time_now();
/*
- * Remove this item from the cache if its expired, or if the
- * sent password doesn't match the storepassword.
+ * Remove this item from the cache if its expired. If the sent password
+ * doesn't match the storepassword, the entry will be removed and readded
+ * later if the credentials pass authentication.
*/
if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) {
/* ...but entry is too old */
util_ald_cache_remove(curl->search_cache, search_nodep);
}
- else if (strcmp(search_nodep->bindpw, bindpw) != 0) {
- /* ...but cached password doesn't match sent password */
- util_ald_cache_remove(curl->search_cache, search_nodep);
- }
- else {
+ else if ((search_nodep->bindpw) && (search_nodep->bindpw[0] != '\0') &&
+ (strcmp(search_nodep->bindpw, bindpw) == 0)) {
/* ...and entry is valid */
*binddn = search_nodep->dn;
*retvals = search_nodep->vals;
@@ -835,7 +833,7 @@
* able to authenticate with this module. I don't see this as a big
* problem.
*/
- if (strlen(bindpw) <= 0) {
+ if (!bindpw || strlen(bindpw) <= 0) {
ldap_msgfree(res);
ldc->reason = "Empty password not allowed";
return LDAP_INVALID_CREDENTIALS;
@@ -912,11 +910,20 @@
into the cache before we got here. If it does exist then update the lastbind */
search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node);
if ((search_nodep == NULL) ||
- (strcmp(*binddn, search_nodep->dn) != 0) || (strcmp(bindpw, search_nodep->bindpw) != 0)) {
+ (strcmp(*binddn, search_nodep->dn) != 0)) {
+ /* Nothing in cache, insert new entry */
+ util_ald_cache_insert(curl->search_cache, &the_search_node);
+ }
+ else if ((!search_nodep->bindpw) ||
+ (strcmp(bindpw, search_nodep->bindpw) != 0)) {
+
+ /* Entry in cache is invalid, remove it and insert new one */
+ util_ald_cache_remove(curl->search_cache, search_nodep);
util_ald_cache_insert(curl->search_cache, &the_search_node);
}
else {
+ /* Cache entry is valid, update lastbind */
search_nodep->lastbind = the_search_node.lastbind;
}
LDAP_CACHE_UNLOCK();
@@ -927,6 +934,180 @@
return LDAP_SUCCESS;
}
+ /*
+ * This function will return the DN of the entry matching userid.
+ * It is used to get the DN in case some other module than mod_auth_ldap
+ * has authenticated the user.
+ * The function is basically a copy of util_ldap_cache_checkuserid
+ * with password checking removed.
+ */
+LDAP_DECLARE(int) util_ldap_cache_getuserdn(request_rec *r, util_ldap_connection_t *ldc,
+ const char *url, const char *basedn, int scope, char **attrs,
+ const char *filter, const char **binddn,
+ const char ***retvals)
+{
+ const char **vals = NULL;
+ int result = 0;
+ LDAPMessage *res, *entry;
+ char *dn;
+ int count;
+ int failures = 0;
+ util_url_node_t *curl; /* Cached URL node */
+ util_url_node_t curnode;
+ util_search_node_t *search_nodep; /* Cached search node */
+ util_search_node_t the_search_node;
+ apr_time_t curtime;
+
+ util_ldap_state_t *st =
+ (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
+ &ldap_module);
+
+ /* Get the cache node for this url */
+ LDAP_CACHE_LOCK();
+ 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();
+
+ if (curl) {
+ LDAP_CACHE_LOCK();
+ the_search_node.username = filter;
+ search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node);
+ if (search_nodep != NULL) {
+
+ /* found entry in search cache... */
+ curtime = apr_time_now();
+
+ /*
+ * Remove this item from the cache if its expired.
+ */
+ if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) {
+ /* ...but entry is too old */
+ util_ald_cache_remove(curl->search_cache, search_nodep);
+ }
+ else {
+ /* ...and entry is valid */
+ *binddn = search_nodep->dn;
+ *retvals = search_nodep->vals;
+ LDAP_CACHE_UNLOCK();
+ ldc->reason = "Search successful (cached)";
+ return LDAP_SUCCESS;
+ }
+ }
+ /* unlock this read lock */
+ LDAP_CACHE_UNLOCK();
+ }
+
+ /*
+ * At this point, there is no valid cached search, so lets do the search.
+ */
+
+ /*
+ * If any LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
+ */
+start_over:
+ if (failures++ > 10) {
+ return result;
+ }
+ if (LDAP_SUCCESS != (result = util_ldap_connection_open(r, ldc))) {
+ return result;
+ }
+
+ /* try do the search */
+ if ((result = ldap_search_ext_s(ldc->ldap,
+ basedn, scope, filter, attrs, 0,
+ NULL, NULL, NULL, -1, &res)) == LDAP_SERVER_DOWN) {
+ ldc->reason = "ldap_search_ext_s() for user failed with server down";
+ goto start_over;
+ }
+
+ /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
+ if (result != LDAP_SUCCESS) {
+ ldc->reason = "ldap_search_ext_s() for user failed";
+ return result;
+ }
+
+ /*
+ * We should have found exactly one entry; to find a different
+ * number is an error.
+ */
+ count = ldap_count_entries(ldc->ldap, res);
+ if (count != 1)
+ {
+ if (count == 0 )
+ ldc->reason = "User not found";
+ else
+ ldc->reason = "User is not unique (search found two or more matches)";
+ ldap_msgfree(res);
+ return LDAP_NO_SUCH_OBJECT;
+ }
+
+ entry = ldap_first_entry(ldc->ldap, res);
+
+ /* Grab the dn, copy it into the pool, and free it again */
+ dn = ldap_get_dn(ldc->ldap, entry);
+ *binddn = apr_pstrdup(st->pool, dn);
+ ldap_memfree(dn);
+
+ /*
+ * Get values for the provided attributes.
+ */
+ if (attrs) {
+ int k = 0;
+ int i = 0;
+ while (attrs[k++]);
+ vals = apr_pcalloc(r->pool, sizeof(char *) * (k+1));
+ while (attrs[i]) {
+ char **values;
+ int j = 0;
+ char *str = NULL;
+ /* get values */
+ values = ldap_get_values(ldc->ldap, entry, attrs[i]);
+ while (values && values[j]) {
+ str = str ? apr_pstrcat(r->pool, str, "; ", values[j], NULL) : apr_pstrdup(r->pool, values[j]);
+ j++;
+ }
+ ldap_value_free(values);
+ vals[i] = str;
+ i++;
+ }
+ *retvals = vals;
+ }
+
+ /*
+ * Add the new username to the search cache.
+ */
+ if (curl) {
+ LDAP_CACHE_LOCK();
+ the_search_node.username = filter;
+ the_search_node.dn = *binddn;
+ the_search_node.bindpw = NULL;
+ the_search_node.lastbind = apr_time_now();
+ the_search_node.vals = vals;
+
+ /* Search again to make sure that another thread didn't ready insert this node
+ into the cache before we got here. If it does exist then update the lastbind */
+ search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node);
+ if ((search_nodep == NULL) ||
+ (strcmp(*binddn, search_nodep->dn) != 0)) {
+
+ /* Nothing in cache, insert new entry */
+ util_ald_cache_insert(curl->search_cache, &the_search_node);
+ }
+ else {
+ /* Cache entry is valid, update lastbind */
+ search_nodep->lastbind = the_search_node.lastbind;
+ }
+ LDAP_CACHE_UNLOCK();
+ }
+
+ ldap_msgfree(res);
+
+ ldc->reason = "Search successful";
+ return LDAP_SUCCESS;
+}
/*
* Reports if ssl support is enabled