From 2d122b4e5560c8cc40478cec12bb44dbe97c3415 Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Tue, 28 Aug 2001 23:16:12 +0000 Subject: [PATCH] Add specified user attributes to the environment when using mod_auth_ldap. This allows you to use mod_include to embed specified user attributes in a page like so: Hello , how are you? PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90775 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 ++++ include/util_ldap.h | 10 ++++--- modules/aaa/mod_auth_ldap.c | 37 +++++++++++++++++++++++-- modules/ldap/util_ldap.c | 36 ++++++++++++++++++++---- modules/ldap/util_ldap_cache.c | 44 +++++++++++++++++++++++++++--- modules/ldap/util_ldap_cache.h | 7 +++-- modules/ldap/util_ldap_cache_mgr.c | 15 ++++++---- 7 files changed, 131 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index 5f5c03732a..651c286bb3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ Changes with Apache 2.0.25-dev + *) Add specified user attributes to the environment when using + mod_auth_ldap. This allows you to use mod_include to embed specified + user attributes in a page like so: + Hello , how are you? + [Graham Leggett] + *) Fix a performance problem with the worker MPM. We now create transaction pools once, and re-use them for each connection. [Aaron Bannert ] diff --git a/include/util_ldap.h b/include/util_ldap.h index bd9327e26f..a0182724cf 100644 --- a/include/util_ldap.h +++ b/include/util_ldap.h @@ -232,19 +232,21 @@ int util_ldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc, * @param url The URL of the LDAP connection - used for deciding which cache to use. * @param basedn The Base DN to search for the user in. * @param scope LDAP scope of the search. + * @param attrs LDAP attributes to return in search. * @param filter The user to search for in the form of an LDAP filter. This filter must return * exactly one user for the check to be successful. * @param bindpw The user password to bind as. * @param binddn The DN of the user will be returned in this variable. + * @param retvals The values corresponding to the attributes requested in the attrs array. * @tip The filter supplied will be searched for. If a single entry is returned, an attempt * is made to bind as that user. If this bind succeeds, the user is not validated. * @deffunc int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, - * char *url, const char *basedn, int scope, - * char *filter, char *bindpw, char **binddn) + * char *url, const char *basedn, int scope, char **attrs, + * char *filter, char *bindpw, char **binddn, char ***retvals) */ int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, - const char *url, const char *basedn, int scope, - const char *filter, const char *bindpw, const char **binddn); + const char *url, const char *basedn, int scope, char **attrs, + const char *filter, const char *bindpw, const char **binddn, const char ***retvals); /* from apr_ldap_cache.c */ diff --git a/modules/aaa/mod_auth_ldap.c b/modules/aaa/mod_auth_ldap.c index c23cffcd9b..6be891cf17 100644 --- a/modules/aaa/mod_auth_ldap.c +++ b/modules/aaa/mod_auth_ldap.c @@ -68,6 +68,8 @@ /* for getpid() */ #include #endif +#include + #include "httpd.h" #include "http_config.h" #include "http_core.h" @@ -90,6 +92,7 @@ typedef struct { int port; /* Port of the LDAP server */ char *basedn; /* Base DN to do all searches from */ char *attribute; /* Attribute to search for */ + char **attributes; /* Array of all the attributes to return */ int scope; /* Scope of the search */ char *filter; /* Filter to further limit the search */ deref_options deref; /* how to handle alias dereferening */ @@ -202,6 +205,7 @@ void mod_auth_ldap_build_filter(char *filtbuf, */ int mod_auth_ldap_check_user_id(request_rec *r) { + const char **vals = NULL; char filtbuf[FILTER_LENGTH]; mod_auth_ldap_config_t *sec = (mod_auth_ldap_config_t *)ap_get_module_config(r->per_dir_config, &auth_ldap_module); @@ -254,7 +258,8 @@ int mod_auth_ldap_check_user_id(request_rec *r) mod_auth_ldap_build_filter(filtbuf, r, sec); /* do the user search */ - result = util_ldap_cache_checkuserid(r, ldc, sec->url, sec->basedn, sec->scope, filtbuf, sent_pw, &dn); + result = util_ldap_cache_checkuserid(r, ldc, sec->url, sec->basedn, sec->scope, + sec->attributes, filtbuf, sent_pw, &dn, &vals); util_ldap_connection_close(ldc); if (result != LDAP_SUCCESS) { @@ -278,6 +283,24 @@ int mod_auth_ldap_check_user_id(request_rec *r) r->user = req->dn; } + /* add environment variables */ + if (sec->attributes && vals) { + apr_table_t *e = r->subprocess_env; + int i = 0; + while (sec->attributes[i]) { + char *str = apr_pstrcat(r->pool, "AUTHENTICATE_", sec->attributes[i], NULL); + int j = 13; + while (str[j]) { + if (str[j] >= 'a' && str[j] <= 'z') { + str[j] = str[j] - ('a' - 'A'); + } + j++; + } + apr_table_setn(e, str, vals[i]); + i++; + } + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[%d] auth_ldap authenticate: accepting %s", getpid(), r->user); @@ -639,7 +662,17 @@ static const char *mod_auth_ldap_parse_url(cmd_parms *cmd, } sec->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; if (urld->lud_attrs && urld->lud_attrs[0]) { - sec->attribute = apr_pstrdup(cmd->pool, urld->lud_attrs[0]); + int i = 1; + while (urld->lud_attrs[i]) { + i++; + } + sec->attributes = apr_pcalloc(cmd->pool, sizeof(char *) * (i+1)); + i = 0; + while (urld->lud_attrs[i]) { + sec->attributes[i] = apr_pstrdup(cmd->pool, urld->lud_attrs[i]); + i++; + } + sec->attribute = sec->attributes[0]; } else { sec->attribute = "uid"; diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c index 433ea097e3..4e9ca0e501 100644 --- a/modules/ldap/util_ldap.c +++ b/modules/ldap/util_ldap.c @@ -720,9 +720,11 @@ start_over: } int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, - const char *url, const char *basedn, int scope, - const char *filter, const char *bindpw, const char **binddn) + const char *url, const char *basedn, int scope, char **attrs, + const char *filter, const char *bindpw, const char **binddn, + const char ***retvals) { + const char **vals = NULL; int result = 0; LDAPMessage *res, *entry; char *dn; @@ -738,7 +740,6 @@ int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module); - /* read lock this function */ if (!util_ldap_cache_lock) { apr_lock_create(&util_ldap_cache_lock, APR_READWRITE, APR_INTRAPROCESS, NULL, st->pool); @@ -776,6 +777,7 @@ int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, else { /* ...and entry is valid */ *binddn = search_nodep->dn; + *retvals = search_nodep->vals; apr_lock_release(util_ldap_cache_lock); ldc->reason = "Authentication successful (cached)"; return LDAP_SUCCESS; @@ -803,7 +805,7 @@ start_over: /* try do the search */ if ((result = ldap_search_ext_s(ldc->ldap, basedn, scope, - filter, NULL, 1, + 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; @@ -864,7 +866,29 @@ start_over: return result; } - ldap_msgfree(res); + /* + * 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++; + } + vals[i] = str; + i++; + } + *retvals = vals; + } /* * Add the new username to the search cache. @@ -874,7 +898,9 @@ start_over: the_search_node.dn = *binddn; the_search_node.bindpw = bindpw; the_search_node.lastbind = apr_time_now(); + the_search_node.vals = vals; util_ald_cache_insert(curl->search_cache, &the_search_node); + ldap_msgfree(res); apr_lock_release(util_ldap_cache_lock); ldc->reason = "Authentication successful"; diff --git a/modules/ldap/util_ldap_cache.c b/modules/ldap/util_ldap_cache.c index cd4888676e..f8d4a4dc08 100644 --- a/modules/ldap/util_ldap_cache.c +++ b/modules/ldap/util_ldap_cache.c @@ -127,16 +127,52 @@ void *util_ldap_search_node_copy(void *c) { util_search_node_t *node = (util_search_node_t *)c; util_search_node_t *newnode = util_ald_alloc(sizeof(util_search_node_t)); - newnode->username = util_ald_strdup(node->username); - newnode->dn = util_ald_strdup(node->dn); - newnode->bindpw = util_ald_strdup(node->bindpw); - newnode->lastbind = node->lastbind; + + /* safety check */ + if (newnode) { + + /* copy vals */ + if (node->vals) { + int k = 0; + int i = 0; + while (node->vals[k++]); + if (!(newnode->vals = util_ald_alloc(sizeof(char *) * (k+1)))) { + util_ldap_search_node_free(newnode); + return NULL; + } + while (node->vals[i]) { + if (!(newnode->vals[i] = util_ald_strdup(node->vals[i]))) { + util_ldap_search_node_free(newnode); + return NULL; + } + i++; + } + } + else { + newnode->vals = NULL; + } + if (!(newnode->username = util_ald_strdup(node->username)) || + !(newnode->dn = util_ald_strdup(node->dn)) || + !(newnode->bindpw = util_ald_strdup(node->bindpw)) ) { + util_ldap_search_node_free(newnode); + return NULL; + } + newnode->lastbind = node->lastbind; + + } return (void *)newnode; } void util_ldap_search_node_free(void *n) { + int i = 0; util_search_node_t *node = (util_search_node_t *)n; + if (node->vals) { + while (node->vals[i]) { + util_ald_free(node->vals[i++]); + } + util_ald_free(node->vals); + } util_ald_free(node->username); util_ald_free(node->dn); util_ald_free(node->bindpw); diff --git a/modules/ldap/util_ldap_cache.h b/modules/ldap/util_ldap_cache.h index 2cedb2f45b..ea0709887a 100644 --- a/modules/ldap/util_ldap_cache.h +++ b/modules/ldap/util_ldap_cache.h @@ -139,9 +139,10 @@ typedef struct util_url_node_t { typedef struct util_search_node_t { const char *username; /* Cache key */ const char *dn; /* DN returned from search */ - const char *bindpw; /* The most recently used bind password; - NULL if the bind failed */ - apr_time_t lastbind; /* Time of last successful bind */ + const char *bindpw; /* The most recently used bind password; + NULL if the bind failed */ + apr_time_t lastbind; /* Time of last successful bind */ + const char **vals; /* Values of queried attributes */ } util_search_node_t; /* diff --git a/modules/ldap/util_ldap_cache_mgr.c b/modules/ldap/util_ldap_cache_mgr.c index c35c4612e9..5921f5fd40 100644 --- a/modules/ldap/util_ldap_cache_mgr.c +++ b/modules/ldap/util_ldap_cache_mgr.c @@ -116,12 +116,15 @@ void util_ald_free(const void *ptr) { #if APR_HAS_SHARED_MEMORY if (util_ldap_shm) { - apr_shm_free(util_ldap_shm, (void *)ptr); + if (ptr) + apr_shm_free(util_ldap_shm, (void *)ptr); } else { - free((void *)ptr); + if (ptr) + free((void *)ptr); } #else - free((void *)ptr); + if (ptr) + free((void *)ptr); #endif } @@ -129,12 +132,12 @@ void *util_ald_alloc(int size) { #if APR_HAS_SHARED_MEMORY if (util_ldap_shm) { - return (void *)apr_shm_malloc(util_ldap_shm, size); + return (void *)apr_shm_calloc(util_ldap_shm, size); } else { - return (void *)malloc(size); + return (void *)calloc(sizeof(char), size); } #else - return (void *)malloc(size); + return (void *)calloc(size); #endif } -- 2.50.1