mod_authnz_ldap.c revision 6733d943c9e8d0f27dd077a04037e8c49eb090ff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * contributor license agreements. See the NOTICE file distributed with
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * this work for additional information regarding copyright ownership.
b99dbaab171d91e1b664397cc40e039d0c087c65fielding * The ASF licenses this file to You under the Apache License, Version 2.0
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * (the "License"); you may not use this file except in compliance with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the License. You may obtain a copy of the License at
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Unless required by applicable law or agreed to in writing, software
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distributed under the License is distributed on an "AS IS" BASIS,
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * See the License for the specific language governing permissions and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * limitations under the License.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding/* for getpid() */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#error mod_authnz_ldap requires APR-util to have LDAP support built in. To fix add --with-ldap to ./configure.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffieldingstatic char *default_attributes[3] = { "member", "uniqueMember", NULL };
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingtypedef struct {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_t *pool; /* Pool that this config is allocated from */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding apr_thread_mutex_t *lock; /* Lock for this config */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* These parameters are all derived from the AuthLDAPURL directive */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding char *host; /* Name of the LDAP server (or space separated list) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *basedn; /* Base DN to do all searches from */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char **attributes; /* Array of all the attributes to return */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *filter; /* Filter to further limit the search */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding deref_options deref; /* how to handle alias dereferening */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein char *binddn; /* DN to bind to server (can be NULL) */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein char *bindpw; /* Password to bind to server (can be NULL) */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein int user_is_dn; /* If true, connection->user is DN instead of userid */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein char *remote_user_attribute; /* If set, connection->user is this attribute instead of userid */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein int compare_dn_on_server; /* If true, will use server to do DN compare */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int have_ldap_url; /* Set if we have found an LDAP url */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *groupattr; /* List of Group attributes identifying user members. Default:"member uniqueMember" */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int group_attrib_is_dn; /* If true, the group attribute is the DN, otherwise,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding it's the exact string passed by the HTTP client */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char **sgAttributes; /* Array of strings constructed (post-config) from subgroupattrs. Last entry is NULL. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *subgroupclasses; /* List of object classes of sub-groups. Default:"groupOfNames groupOfUniqueNames" */
51af95bb51b5084e883bad250b2afa2838e9ceebfielding int maxNestingDepth; /* Maximum recursive nesting depth permitted during subgroup processing. Default: 10 */
7fae9cc4639013f3c04c085547256c68814aee8ftrawick int secure; /* True if SSL connections are requested */
7fae9cc4639013f3c04c085547256c68814aee8ftrawicktypedef struct {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *dn; /* The saved dn from a successful search */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *user; /* The username provided by the client */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* maximum group elements supported */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic APR_OPTIONAL_FN_TYPE(uldap_cache_check_subgroups) *util_ldap_cache_check_subgroups;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *to_charset = NULL; /* UTF-8 identifier derived from the charset.conv file */
785be1b6298010956622771c870ab3cd8ca57a2faaron/* Derive a code page ID give a language name or ID */
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic char* derive_codepage_from_lang (apr_pool_t *p, char *language)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *lang_line = (char*)apr_table_get(r->headers_in, "accept-language");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding lang = derive_codepage_from_lang(r->pool, lang_line);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (lang && (apr_xlate_open(&convset, to_charset, lang, r->pool) == APR_SUCCESS)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Build the search filter, or at least as much of the search filter that
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * will fit in the buffer. We don't worry about the buffer not being able
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to hold the entire filter. If the buffer wasn't big enough to hold the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * filter, ldap_search_s will complain, but the only situation where this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * is likely to happen is if the client sent a really, really long
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * username, most likely as part of an attack.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * The search filter consists of the filter provided with the URL,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * combined with a filter made up of the attribute provided with the URL,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and the actual username passed by the HTTP client. For example, assume
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * that the LDAP URL is
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ldap://ldap.airius.com/ou=People, o=Airius?uid??(posixid=*)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Further, assume that the userid passed by the client was `userj'. The
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * search filter will be (&(posixid=*)(uid=userj)).
785be1b6298010956622771c870ab3cd8ca57a2faaron char *p, *q, *filtbuf_end;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* Convert the user name to UTF-8. This is only valid for LDAP v3 */
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (apr_xlate_conv_buffer(convset, user, &inbytes, outbuf, &outbytes) == APR_SUCCESS) {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * Create the first part of the filter, which consists of the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * config-supplied portions.
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute);
785be1b6298010956622771c870ab3cd8ca57a2faaron * Now add the client-supplied username to the filter, ensuring that any
785be1b6298010956622771c870ab3cd8ca57a2faaron * LDAP filter metachars are escaped.
785be1b6298010956622771c870ab3cd8ca57a2faaron *p && q < filtbuf_end; ) {
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick break; /* Don't write part of escape sequence if we can't write all of it */
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick *q++ = '\\';
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick switch ( *p++ )
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid *q++ = '2';
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid *q++ = 'a';
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick *q++ = '2';
d17890657bc529b3f9db20e5546511182b829565dreid *q++ = '8';
d17890657bc529b3f9db20e5546511182b829565dreid *q++ = '2';
d17890657bc529b3f9db20e5546511182b829565dreid *q++ = '9';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *q++ = '5';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *q++ = 'c';
785be1b6298010956622771c870ab3cd8ca57a2faaron *q++ = *p++;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *p && q < filtbuf_end; *q++ = *p++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *q++ = '\\';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Append the closing parens of the filter, unless doing so would
785be1b6298010956622771c870ab3cd8ca57a2faaron * overrun the buffer.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d)
785be1b6298010956622771c870ab3cd8ca57a2faaron (authn_ldap_config_t *)apr_pcalloc(p, sizeof(authn_ldap_config_t));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_thread_mutex_create(&sec->lock, APR_THREAD_MUTEX_DEFAULT, p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sec->authz_enabled = 1;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm sec->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sec->subgroupclasses = apr_array_make(p, GROUPATTR_MAX_ELTS,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sec->sgAttributes = apr_pcalloc(p, sizeof (char *) * GROUPATTR_MAX_ELTS + 1);
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic apr_status_t authnz_ldap_cleanup_connection_close(void *param)
785be1b6298010956622771c870ab3cd8ca57a2faaron * Authentication Phase
785be1b6298010956622771c870ab3cd8ca57a2faaron * --------------------
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This phase authenticates the credentials the user has sent with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the request (ie the username and password are checked). This is done
785be1b6298010956622771c870ab3cd8ca57a2faaron * by making an attempt to bind to the LDAP server using this user's
785be1b6298010956622771c870ab3cd8ca57a2faaron * DN and the supplied password.
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic authn_status authn_ldap_check_password(request_rec *r, const char *user,
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *password)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_set_module_config(r->request_config, &authnz_ldap_module, req);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!sec->enabled) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return AUTH_USER_NOT_FOUND;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Basic sanity checks before any LDAP operations even happen.
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick /* There is a good AuthLDAPURL, right? */
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick ldc = util_ldap_connection_find(r, sec->host, sec->port,
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authenticate: no sec->host - weird...?", getpid());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authenticate: using URL %s", getpid(), sec->url);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Get the password that the client sent */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authenticate: no password specified", getpid());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authenticate: no user specified", getpid());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* build the username filter */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding authn_ldap_build_filter(filtbuf, r, user, NULL, sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* do the user search */
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein result = util_ldap_cache_checkuserid(r, ldc, sec->url, sec->basedn, sec->scope,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* sanity check - if server is down, retry it up to 5 times */
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick /* handle bind failure */
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick "user %s authentication failed; URI %s [%s][%s]",
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick getpid(), user, r->uri, ldc->reason, ldap_err2string(result));
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return (LDAP_NO_SUCH_OBJECT == result) ? AUTH_USER_NOT_FOUND
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding : (LDAP_INAPPROPRIATE_AUTH == result) ? AUTH_DENIED
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding : (LDAP_INVALID_CREDENTIALS == result) ? AUTH_DENIED
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding : (LDAP_INSUFFICIENT_ACCESS == result) ? AUTH_DENIED
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding : (LDAP_INSUFFICIENT_RIGHTS == result) ? AUTH_DENIED
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* mark the user and DN */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* add environment variables */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf int i = 0;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick char *str = apr_pstrcat(r->pool, AUTHN_PREFIX, sec->attributes[i], NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick while (str[j]) {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* handle remote_user_attribute, if set */
785be1b6298010956622771c870ab3cd8ca57a2faaron !strcmp(sec->remote_user_attribute, sec->attributes[i])) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* sanity check */
785be1b6298010956622771c870ab3cd8ca57a2faaron if (sec->remote_user_attribute && !remote_user_attribute_set) {
785be1b6298010956622771c870ab3cd8ca57a2faaron "REMOTE_USER was to be set with attribute '%s', "
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf "but this attribute was not requested for in the "
066877f1a045103acfdd376d48cdd473c33f409bdougm "LDAP query for the user. REMOTE_USER will fall "
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authenticate: accepting %s", getpid(), user);
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic authz_status ldapuser_check_authorization(request_rec *r,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
066877f1a045103acfdd376d48cdd473c33f409bdougm const char *t;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf ldc = util_ldap_connection_find(r, sec->host, sec->port,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
785be1b6298010956622771c870ab3cd8ca57a2faaron * If we have been authenticated by some other module than mod_authnz_ldap,
785be1b6298010956622771c870ab3cd8ca57a2faaron * the req structure needed for authorization needs to be created
785be1b6298010956622771c870ab3cd8ca57a2faaron * and populated with the userid and DN of the account in LDAP
785be1b6298010956622771c870ab3cd8ca57a2faaron /* Check that we have a userid to start with */
785be1b6298010956622771c870ab3cd8ca57a2faaron "ldap authorize: Userid is blank, AuthType=%s",
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf "ldap authorize: Creating LDAP req structure");
785be1b6298010956622771c870ab3cd8ca57a2faaron /* Build the username filter */
785be1b6298010956622771c870ab3cd8ca57a2faaron authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* Search for the user DN */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* Search failed, log error and return failure */
785be1b6298010956622771c870ab3cd8ca57a2faaron "auth_ldap authorise: User DN not found, %s", ldc->reason);
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_set_module_config(r->request_config, &authnz_ldap_module, req);
785be1b6298010956622771c870ab3cd8ca57a2faaron "require user: user's DN has not been defined; failing authorization",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * First do a whole-line compare, in case it's something like
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * require user Babs Jensen
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require_args);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require user: authorization successful", getpid());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authorize: require user: "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Now break apart the line and compare each word on it
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w);
785be1b6298010956622771c870ab3cd8ca57a2faaron "require user: authorization failed [%s][%s]",
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authorize user: authorization denied for user %s to %s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic authz_status ldapgroup_check_authorization(request_rec *r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
900127764fb985c340ee4979cac97146a330c694trawick const char *t;
785be1b6298010956622771c870ab3cd8ca57a2faaron ldc = util_ldap_connection_find(r, sec->host, sec->port,
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
785be1b6298010956622771c870ab3cd8ca57a2faaron * If there are no elements in the group attribute array, the default should be
785be1b6298010956622771c870ab3cd8ca57a2faaron * member and uniquemember; populate the array now.
785be1b6298010956622771c870ab3cd8ca57a2faaron * If there are no elements in the sub group classes array, the default
785be1b6298010956622771c870ab3cd8ca57a2faaron * should be groupOfNames and groupOfUniqueNames; populate the array now.
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick * If we have been authenticated by some other module than mod_auth_ldap,
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick * the req structure needed for authorization needs to be created
785be1b6298010956622771c870ab3cd8ca57a2faaron * and populated with the userid and DN of the account in LDAP
785be1b6298010956622771c870ab3cd8ca57a2faaron /* Check that we have a userid to start with */
066877f1a045103acfdd376d48cdd473c33f409bdougm "ldap authorize: Userid is blank, AuthType=%s",
785be1b6298010956622771c870ab3cd8ca57a2faaron "ldap authorize: Creating LDAP req structure");
785be1b6298010956622771c870ab3cd8ca57a2faaron /* Build the username filter */
785be1b6298010956622771c870ab3cd8ca57a2faaron authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search for the user DN */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search failed, log error and return failure */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "auth_ldap authorise: User DN not found, %s", ldc->reason);
bbbf8f0e622ad5a37ccf70f35660fc755575278arbb ap_set_module_config(r->request_config, &authnz_ldap_module, req);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "user's DN has not been defined; failing authorization for user %s",
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf /* We weren't called in the authentication phase, so we didn't have a
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf * chance to set the user field. Do so now. */
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf "testing for group membership in \"%s\"",
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t);
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name,
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick "authorization successful (attribute %s) [%s][%d - %s]",
644be6f54749d2d9950d2c4d2ac448f7af016d26martin getpid(), ent[i].name, ldc->reason, result, ldap_err2string(result));
644be6f54749d2d9950d2c4d2ac448f7af016d26martin "[%" APR_PID_T_FMT "] auth_ldap authorise: require group \"%s\": "
644be6f54749d2d9950d2c4d2ac448f7af016d26martin "failed [%s][%d - %s], checking sub-groups",
644be6f54749d2d9950d2c4d2ac448f7af016d26martin getpid(), t, ldc->reason, result, ldap_err2string(result));
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick result = util_ldap_cache_check_subgroups(r, ldc, sec->url, t, ent[i].name,
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick sec->sgAttributes[0] ? sec->sgAttributes : default_attributes,
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authorise: require group (sub-group): "
785be1b6298010956622771c870ab3cd8ca57a2faaron "authorisation successful (attribute %s) [%s][%d - %s]",
785be1b6298010956622771c870ab3cd8ca57a2faaron getpid(), ent[i].name, ldc->reason, result, ldap_err2string(result));
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick "[%" APR_PID_T_FMT "] auth_ldap authorise: require group (sub-group) \"%s\": "
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick "authorisation failed [%s][%d - %s]",
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick getpid(), t, ldc->reason, result, ldap_err2string(result));
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf "[%" APR_PID_T_FMT "] auth_ldap authorize: require group \"%s\": "
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf "authorization failed [%s][%d - %s]",
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf getpid(), t, ldc->reason, result, ldap_err2string(result));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authorize group: authorization denied for user %s to %s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic authz_status ldapdn_check_authorization(request_rec *r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *t;
785be1b6298010956622771c870ab3cd8ca57a2faaron ldc = util_ldap_connection_find(r, sec->host, sec->port,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
3d96ee83babeec32482c9082c9426340cee8c44dwrowe * If we have been authenticated by some other module than mod_auth_ldap,
785be1b6298010956622771c870ab3cd8ca57a2faaron * the req structure needed for authorization needs to be created
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and populated with the userid and DN of the account in LDAP
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Check that we have a userid to start with */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "ldap authorize: Userid is blank, AuthType=%s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "ldap authorize: Creating LDAP req structure");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Build the username filter */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search for the user DN */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search failed, log error and return failure */
785be1b6298010956622771c870ab3cd8ca57a2faaron "auth_ldap authorise: User DN not found, %s", ldc->reason);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_set_module_config(r->request_config, &authnz_ldap_module, req);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require dn: user's DN has not been defined; failing authorization",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, t, sec->compare_dn_on_server);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require dn \"%s\": LDAP error [%s][%s]",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding getpid(), t, ldc->reason, ldap_err2string(result));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "[%" APR_PID_T_FMT "] auth_ldap authorize dn: authorization denied for user %s to %s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic authz_status ldapattribute_check_authorization(request_rec *r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *t;
785be1b6298010956622771c870ab3cd8ca57a2faaron ldc = util_ldap_connection_find(r, sec->host, sec->port,
785be1b6298010956622771c870ab3cd8ca57a2faaron "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If we have been authenticated by some other module than mod_auth_ldap,
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * the req structure needed for authorization needs to be created
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and populated with the userid and DN of the account in LDAP
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Check that we have a userid to start with */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "ldap authorize: Userid is blank, AuthType=%s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "ldap authorize: Creating LDAP req structure");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Build the username filter */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search for the user DN */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Search failed, log error and return failure */
785be1b6298010956622771c870ab3cd8ca57a2faaron "auth_ldap authorise: User DN not found, %s", ldc->reason);
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_set_module_config(r->request_config, &authnz_ldap_module, req);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require ldap-attribute: user's DN has not been defined; failing authorization",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (t[0]) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "[%" APR_PID_T_FMT "] auth_ldap authorize: checking attribute"
785be1b6298010956622771c870ab3cd8ca57a2faaron result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, w, value);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require attribute: authorization successful",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "require attribute: authorization failed [%s][%s]",
8f8ec0957334f50b7ac11359f90490ee467258eedreid "[%" APR_PID_T_FMT "] auth_ldap authorize attribute: authorization denied for user %s to %s",
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic authz_status ldapfilter_check_authorization(request_rec *r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb const char *t;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf ldc = util_ldap_connection_find(r, sec->host, sec->port,
return AUTHZ_DENIED;
r->ap_auth_type);
if(!req) {
return AUTHZ_DENIED;
sizeof(authn_ldap_request_t));
getpid());
return AUTHZ_DENIED;
t = require_args;
getpid(), t);
switch(result) {
case LDAP_COMPARE_TRUE: {
return AUTHZ_GRANTED;
case LDAP_FILTER_ERROR: {
return AUTHZ_DENIED;
void *config,
const char *url,
const char *mode)
int rc;
cmd->server, "[%" APR_PID_T_FMT "] auth_ldap url parse: attrib: %s", getpid(), urld->lud_attrs? urld->lud_attrs[0] : "(null)");
if (mode) {
return NULL;
return NULL;
static const char *mod_auth_ldap_add_subgroup_attribute(cmd_parms *cmd, void *config, const char *arg)
if (i == GROUPATTR_MAX_ELTS)
return NULL;
return NULL;
void *config,
const char *max_depth)
return NULL;
return NULL;
(void *)arg);
return NULL;
"LDAP URL is <b>ldap://ldap.airius.com/ou=People, o=Airius?uid?sub?(posixid=*)</b>. "
AP_INIT_ITERATE("AuthLDAPSubGroupAttribute", mod_auth_ldap_add_subgroup_attribute, NULL, OR_AUTHCFG,
{NULL}
static int authnz_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
ap_configfile_t *f;
char l[MAX_STRING_LEN];
return HTTP_INTERNAL_SERVER_ERROR;
if (!charset_confname) {
return OK;
if (!charset_confname) {
return HTTP_INTERNAL_SERVER_ERROR;
!= APR_SUCCESS) {
return HTTP_INTERNAL_SERVER_ERROR;
const char *ll = l;
char *lang;
if (ll[0]) {
ap_cfg_closefile(f);
return HTTP_INTERNAL_SERVER_ERROR;
return OK;
static void ImportULDAPOptFn(void)