--- mod_authnz_ldap.c.orig 2006-07-26 09:31:38.000000000 -0400 +++ mod_authnz_ldap.c 2006-11-27 14:52:34.000000000 -0500 @@ -73,6 +73,7 @@ it's the exact string passed by the HTTP client */ int secure; /* True if SSL connections are requested */ + int require_dn; /* Off means it's OK if the user has no DN */ } authn_ldap_config_t; typedef struct { @@ -85,6 +86,7 @@ struct mod_auth_ldap_groupattr_entry_t { char *name; + char *type; }; module AP_MODULE_DECLARE_DATA authnz_ldap_module; @@ -295,6 +297,7 @@ sec->deref = always; sec->group_attrib_is_dn = 1; sec->auth_authoritative = 1; + sec->require_dn = 1; /* sec->frontpage_hack = 0; @@ -414,13 +417,13 @@ #ifdef LDAP_SECURITY_ERROR : (LDAP_SECURITY_ERROR(result)) ? AUTH_DENIED #else - : (LDAP_INAPPROPRIATE_AUTH == result) ? AUTH_DENIED - : (LDAP_INVALID_CREDENTIALS == result) ? AUTH_DENIED + : (LDAP_INAPPROPRIATE_AUTH == result) ? AUTH_DENIED + : (LDAP_INVALID_CREDENTIALS == result) ? AUTH_DENIED #ifdef LDAP_INSUFFICIENT_ACCESS : (LDAP_INSUFFICIENT_ACCESS == result) ? AUTH_DENIED #endif #ifdef LDAP_INSUFFICIENT_RIGHTS - : (LDAP_INSUFFICIENT_RIGHTS == result) ? AUTH_DENIED + : (LDAP_INSUFFICIENT_RIGHTS == result) ? AUTH_DENIED #endif #endif : AUTH_GENERAL_ERROR; @@ -531,8 +534,10 @@ #endif grp = apr_array_push(sec->groupattr); grp->name = "member"; + grp->type = NULL; grp = apr_array_push(sec->groupattr); grp->name = "uniquemember"; + grp->type = NULL; #if APR_HAS_THREADS apr_thread_mutex_unlock(sec->lock); #endif @@ -569,7 +574,7 @@ sec->scope, sec->attributes, filtbuf, &dn, &vals); /* Search failed, log error and return failure */ - if(result != LDAP_SUCCESS) { + if((result != LDAP_SUCCESS) && (sec->require_dn)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "auth_ldap authorise: User DN not found, %s", ldc->reason); return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; @@ -694,13 +699,22 @@ getpid(), t); for (i = 0; i < sec->groupattr->nelts; i++) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: " - "testing for %s: %s (%s)", getpid(), - ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t); + result = 0; - result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, - sec->group_attrib_is_dn ? req->dn : req->user); + if (ent[i].type == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: " + "testing for %s: %s (%s)", getpid(), + ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t); + result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, + sec->group_attrib_is_dn ? req->dn : req->user); + } else if (req->dn != NULL && strlen(req->dn) != 0 && strcasecmp(ent[i].type, "dn") == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: " + "testing for %s: %s (%s)", getpid(), + ent[i].name, req->dn, t); + result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, req->dn); + } switch(result) { case LDAP_COMPARE_TRUE: { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, @@ -990,6 +1004,23 @@ new = apr_array_push(sec->groupattr); new->name = apr_pstrdup(cmd->pool, arg); + new->type = NULL; + + return NULL; +} + +static const char *mod_auth_ldap_add_group_attribute_dn(cmd_parms *cmd, void *config, const char *arg) +{ + struct mod_auth_ldap_groupattr_entry_t *new; + + authn_ldap_config_t *sec = config; + + if (sec->groupattr->nelts > GROUPATTR_MAX_ELTS) + return "Too many AuthLDAPGroupAttribute directives"; + + new = apr_array_push(sec->groupattr); + new->name = apr_pstrdup(cmd->pool, arg); + new->type = apr_pstrdup( "dn" ); return NULL; } @@ -1057,12 +1088,21 @@ "A list of attributes used to define group membership - defaults to " "member and uniquemember"), + AP_INIT_ITERATE("AuthLDAPGroupAttributeDN", mod_auth_ldap_add_group_attribute_dn, NULL, OR_AUTHCFG, + "A list of attributes used to define group membership as DNs - defaults to " + "nothing"), + AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot, (void *)APR_OFFSETOF(authn_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG, "If set to 'on', auth_ldap uses the DN that is retrieved from the server for" "subsequent group comparisons. If set to 'off', auth_ldap uses the string" "provided by the client directly. Defaults to 'on'."), + AP_INIT_FLAG("AuthzLDAPRequireDN", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, require_dn), OR_AUTHCFG, + "If set to 'on', auth_ldap requires a user to have a DN. If set to 'off' " + "the user does not need to have an entry in LDAP. Defaults to 'on'."), + AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG, "Determines how aliases are handled during a search. Can bo one of the" "values \"never\", \"searching\", \"finding\", or \"always\". "