]> granicus.if.org Git - apache/commitdiff
Add the directive AuthLDAPAllowDNAuth to allow a user to authenticate against an...
authorBradley Nicholes <bnicholes@apache.org>
Tue, 3 May 2005 23:07:43 +0000 (23:07 +0000)
committerBradley Nicholes <bnicholes@apache.org>
Tue, 3 May 2005 23:07:43 +0000 (23:07 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@168016 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_authnz_ldap.xml
modules/aaa/mod_authnz_ldap.c

index 526de29f98c5356b74ca17bb8fb0c79c9c904a71..9b46e639b9a3128703c7351cdae55e469be2b336 100644 (file)
@@ -819,6 +819,38 @@ environment variable</description>
     the username that was passed by the client. It is turned off by
     default.</p>
 </usage>
+<seealso><directive module="mod_authnz_ldap">AuthLDAPAllowDNAuth</directive></seealso>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthLDAPAllowDNAuth</name>
+<description>Allow the user to authenticate by passing a fully distinguished
+user name.</description>
+<syntax>AuthLDAPAllowDNAuth on|off</syntax>
+<default>AuthLDAPAllowDNAuth off</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>AuthConfig</override>
+
+<usage>
+    <p>If this directive is set to ON, users are allowed to pass a fully
+    distinguished user name as the user ID.  Regardless of this setting,
+    Auth_LDAP will still allow a contextless login. This directive is 
+    turned off by default.</p>
+
+    <note><title>Note</title>
+      <p>If a full user DN is allowed for authentication and the value of
+      <directive module="mod_authnz_ldap">AuthLDAPRemoteUserIsDN</directive> 
+      is set to OFF, the value of the REMOTE_USER environment variable
+      will contain the actual user name value passed in the request.  If 
+      this directive is set to ON, the REMOTE_USER environment variable 
+      will always be set to the user DN retrieved from the LDAP directory. 
+      If a contextless user ID is required in all cases instead of a 
+      full DN, it is possible to retrieve the desired attribute value 
+      from the user object by specifying an attribute list in the 
+      <directive module="mod_authnz_ldap">AuthLDAPUrl</directive> directive.</p>
+    </note>
+</usage>
 </directivesynopsis>
 
 <directivesynopsis>
@@ -874,13 +906,16 @@ environment variable</description>
 
 <dt>attribute</dt>
 
-        <dd>The attribute to search for.
+        <dd>The attribute to search for as well as additional attribute
+        values to extract from the authenticated user object.
         Although RFC 2255 allows a comma-separated list of
         attributes, only the first attribute will be used, no
-        matter how many are provided. If no attributes are
-        provided, the default is to use <code>uid</code>. It's a good
-        idea to choose an attribute that will be unique across all
-        entries in the subtree you will be using.</dd>
+        matter how many are provided. The values of all other listed 
+        attributes will be extracted from the user object and assigned
+        to environment variables (AUTHENTICATE_&lt;Attribute&gt;=value). 
+        If no attributes are provided, the default is to use <code>uid</code>. 
+        It's a good idea to choose an attribute that will be unique across 
+        all entries in the subtree you will be searching.</dd>
 
 <dt>scope</dt>
 
index a26e33712cbe6abc616842cfebf433f5ebaea07c..d38e6a9441c413704450498d58a0b3516a2209d1 100644 (file)
@@ -73,6 +73,7 @@ typedef struct {
                                         it's the exact string passed by the HTTP client */
 
     int secure;                     /* True if SSL connections are requested */
+    int allow_fdn_auth;             /* Set to True if user is allowed to authenticate using an FDN */
 } authn_ldap_config_t;
 
 typedef struct {
@@ -150,6 +151,61 @@ static apr_xlate_t* get_conv_set (request_rec *r)
     return NULL;
 }
 
+#define FILTER_LENGTH MAX_STRING_LEN
+static char* cat_escape_dn_element(char *filtbuf, char *user)
+{
+    char *p, *q, *filtbuf_end;
+
+    /* 
+     * Now add the client-supplied username to the filter, ensuring that any
+     * LDAP filter metachars are escaped.
+     */
+    filtbuf_end = filtbuf + FILTER_LENGTH - 1;
+#if APR_HAS_MICROSOFT_LDAPSDK
+    for (p = user, q=filtbuf + strlen(filtbuf);
+         *p && q < filtbuf_end; ) {
+        if (strchr("*()\\", *p) != NULL) {
+            if ( q + 3 >= filtbuf_end)
+              break;  /* Don't write part of escape sequence if we can't write all of it */
+            *q++ = '\\';
+            switch ( *p++ )
+            {
+              case '*':
+                *q++ = '2';
+                *q++ = 'a';
+                break;
+              case '(':
+                *q++ = '2';
+                *q++ = '8';
+                break;
+              case ')':
+                *q++ = '2';
+                *q++ = '9';
+                break;
+              case '\\':
+                *q++ = '5';
+                *q++ = 'c';
+                break;
+                       }
+        }
+        else
+            *q++ = *p++;
+    }
+#else
+    for (p = user, q=filtbuf + strlen(filtbuf);
+         *p && q < filtbuf_end; *q++ = *p++) {
+        if (strchr("*()\\", *p) != NULL) {
+            *q++ = '\\';
+            if (q >= filtbuf_end) {
+              break;
+            }
+        }
+    }
+#endif
+    *q = '\0';
+
+    return filtbuf;
+}
 
 /*
  * Build the search filter, or at least as much of the search filter that
@@ -168,20 +224,23 @@ static apr_xlate_t* get_conv_set (request_rec *r)
  *
  * Further, assume that the userid passed by the client was `userj'.  The
  * search filter will be (&(posixid=*)(uid=userj)).
+ *
+ * If a full DN is allowed for authentication, the a userid of 
+ * cn=userj,o=dev will result in the following search filter:
+ *  (&(objectclass=*)(&(cn:dn:=userj)(o:dn:=dev)))
  */
-#define FILTER_LENGTH MAX_STRING_LEN
 static void authn_ldap_build_filter(char *filtbuf, 
                              request_rec *r,
                              const char* sent_user,
                              const char* sent_filter,
                              authn_ldap_config_t *sec)
 {
-    char *p, *q, *filtbuf_end;
     char *user, *filter;
     apr_xlate_t *convset = NULL;
     apr_size_t inbytes;
     apr_size_t outbytes;
     char *outbuf;
+       char **dnbuf = NULL;
 
     if (sent_user != NULL) {
         user = apr_pstrdup (r->pool, sent_user);
@@ -210,66 +269,50 @@ static void authn_ldap_build_filter(char *filtbuf,
         }
     }
 
-    /* 
-     * Create the first part of the filter, which consists of the 
-     * config-supplied portions.
-     */
-    apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute);
+    apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(&", filter);
 
-    /* 
-     * Now add the client-supplied username to the filter, ensuring that any
-     * LDAP filter metachars are escaped.
-     */
-    filtbuf_end = filtbuf + FILTER_LENGTH - 1;
-#if APR_HAS_MICROSOFT_LDAPSDK
-    for (p = user, q=filtbuf + strlen(filtbuf);
-         *p && q < filtbuf_end; ) {
-        if (strchr("*()\\", *p) != NULL) {
-            if ( q + 3 >= filtbuf_end)
-              break;  /* Don't write part of escape sequence if we can't write all of it */
-            *q++ = '\\';
-            switch ( *p++ )
-            {
-              case '*':
-                *q++ = '2';
-                *q++ = 'a';
-                break;
-              case '(':
-                *q++ = '2';
-                *q++ = '8';
-                break;
-              case ')':
-                *q++ = '2';
-                *q++ = '9';
-                break;
-              case '\\':
-                *q++ = '5';
-                *q++ = 'c';
-                break;
-                       }
-        }
-        else
-            *q++ = *p++;
+    /* If FDN authentication is not allowed then don't attempt to explode
+        the user ID.  The result is that dnbuf well be NULL which will
+        bypass building a FDN unique filter. */
+    if (sec->allow_fdn_auth) {
+        dnbuf = ldap_explode_dn (user, 0); 
     }
-#else
-    for (p = user, q=filtbuf + strlen(filtbuf);
-         *p && q < filtbuf_end; *q++ = *p++) {
-        if (strchr("*()\\", *p) != NULL) {
-            *q++ = '\\';
-            if (q >= filtbuf_end) {
-              break;
+
+       if (dnbuf && (strchr(*dnbuf, '='))) {
+               char **buf;
+        char *dnfilter = "&";
+               for (buf = dnbuf; *buf; buf++) {
+            char *eq = strchr (*buf, '=');
+            char *newdn = *buf;
+
+            if (eq) {
+                newdn = apr_pstrcat (r->pool, apr_pstrndup (r->pool, *buf, eq-(*buf)),
+                                     ":dn:", eq, NULL);
             }
-        }
+
+            apr_snprintf(filtbuf, FILTER_LENGTH, "%s(", filtbuf);
+            cat_escape_dn_element(filtbuf, newdn);
+            apr_snprintf(filtbuf, FILTER_LENGTH, "%s)", filtbuf);
+               }
+       }
+    else {
+        /* 
+         * Create the first part of the filter, which consists of the 
+         * config-supplied portions.
+         */
+        apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute);
+        cat_escape_dn_element(filtbuf, user);
     }
-#endif
-    *q = '\0';
+    ldap_value_free (dnbuf); 
 
     /* 
      * Append the closing parens of the filter, unless doing so would 
      * overrun the buffer.
      */
-    if (q + 2 <= filtbuf_end)
-        strcat(filtbuf, "))");
+    apr_snprintf(filtbuf, FILTER_LENGTH, "%s))", filtbuf);
+
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+                  "[%d] auth_ldap authenticate: using filter %s", getpid(), filtbuf);
 }
 
 static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d)
@@ -295,6 +338,7 @@ static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d)
     sec->deref = always;
     sec->group_attrib_is_dn = 1;
     sec->auth_authoritative = 1;
+    sec->allow_fdn_auth = 0;
 
 /*
     sec->frontpage_hack = 0;
@@ -1053,6 +1097,11 @@ static const command_rec authnz_ldap_cmds[] =
                   "Character set conversion configuration file. If omitted, character set"
                   "conversion is disabled."),
 
+    AP_INIT_FLAG("AuthLDAPAllowDNAuth", ap_set_flag_slot,
+                 (void *)APR_OFFSETOF(authn_ldap_config_t, allow_fdn_auth), OR_AUTHCFG,
+                 "If set to 'on', auth_ldap allows the user to authenicate using a fully" 
+                 "distinguished user name. Defaults to 'off'."),
+
     {NULL}
 };