Using environment variables in a 'require group' DN substantially increases flexibility of access control. %{varName} is substitued for the variable's value when determining authorisation. eg. the following can be used to authenticate against different LDAP groups for different directories, both the directory structure and authorisation being dynamically updateble: RewriteRule ^/baseDir/([^/]*)/? - [env=dn1:$1] Require group ou=%{dn1},cn=groups,dc=ricardo,dc=com The following is the diff on mod_auth_ldap.c from 2.0.51 required to implement this [expand_env() is based on do_expand() in mod_rewrite.c]: --- httpd-2.0.51/modules/experimental/mod_auth_ldap.c 2004-05-22 00:39:41.000000000 +0100 +++ httpd-2.0.51_var/modules/experimental/mod_auth_ldap.c 2004-09-20 16:09:24.000000000 +0100 @@ -103,6 +103,7 @@ int mod_auth_ldap_check_user_id(request_rec *r); int mod_auth_ldap_auth_checker(request_rec *r); void *mod_auth_ldap_create_dir_config(apr_pool_t *p, char *d); +static void expand_env(request_rec *r, const char *input, char *buffer, int nbuf); /* ---------------------------------------- */ @@ -582,6 +583,7 @@ else if (strcmp(w, "group") == 0) { struct mod_auth_ldap_groupattr_entry_t *ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts; int i; + char group[MAX_STRING_LEN]; if (sec->group_attrib_is_dn) { if (req->dn == NULL || strlen(req->dn) == 0) { @@ -599,6 +601,9 @@ } } + expand_env(r, t, group, sizeof(group)); + if (group[0]=='\0') return HTTP_UNAUTHORIZED; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[%d] auth_ldap authorise: require group: testing for group membership in \"%s\"", getpid(), t); @@ -606,9 +611,9 @@ for (i = 0; i < sec->groupattr->nelts; i++) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "[%d] auth_ldap authorise: require group: testing for %s: %s (%s)", getpid(), - ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t); + ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, group); - result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, + result = util_ldap_cache_compare(r, ldc, sec->url, group, ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user); switch(result) { case LDAP_COMPARE_TRUE: { @@ -649,6 +654,54 @@ return HTTP_UNAUTHORIZED; } +/* ---------------------------------------- */ +/* expand string with Apache environment variables */ +static void expand_env(request_rec *r, const char *input, char *buffer, int nbuf) { + const char *inp; + char *outp; + apr_size_t span, space; + + inp = input; + outp = buffer; + space = nbuf - 1; /* room for '\0' */ + + for (;;) { + span = strcspn(inp, "%"); + if (span > space) { + span = space; + } + memcpy(outp, inp, span); + inp += span; + outp += span; + space -= span; + if (space == 0 || *inp == '\0') { + break; + } + if (inp[1] == '{') { + char *endp, *var, *val; + endp = strchr(inp+2, '}'); + if (endp == NULL) { + goto skip; + } + var = apr_pstrndup(r->pool, inp+2, endp-inp-2); + val=(char *) apr_table_get(r->subprocess_env, var); + if (!val) { /* flag subs failed */ + buffer='\0'; + break; + } + span = apr_cpystrn(outp, val, space) - outp; + inp = endp+1; + outp += span; + space -= span; + continue; + } + skip: + *outp++ = *inp++; + space--; + } + *outp++ = '\0'; +} + /* ---------------------------------------- */ /* config directives */
Created attachment 12813 [details] mod_auth_ldap.c 2.0.51 patch to implement env var substitution
Would it be possible to create a patch for httpd v2.1? The LDAP support in httpd v2.1 is no longer experiemental, it would be great to include this feature in the mod_authnz_ldap module.
2.4.x interpolates arguments to Require using the expression parser.