Commit dbbf9bcd authored by Bradley Nicholes's avatar Bradley Nicholes
Browse files

Backing out the AuthLDAPAllowDNAuth patch from r168016. Because of LDAP...

Backing out the AuthLDAPAllowDNAuth patch from r168016.  Because of LDAP filter issues this patch still can't guarantee unique results.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@168644 13f79535-47bb-0310-9956-ffa450edef68
parent 6934ed75
Loading
Loading
Loading
Loading
+5 −40
Original line number Diff line number Diff line
@@ -819,38 +819,6 @@ 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>
@@ -906,16 +874,13 @@ user name.</description>

<dt>attribute</dt>

        <dd>The attribute to search for as well as additional attribute
        values to extract from the authenticated user object.
        <dd>The attribute to search for.
        Although RFC 2255 allows a comma-separated list of
        attributes, only the first attribute will be used, no
        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>
        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>

<dt>scope</dt>

+53 −102
Original line number Diff line number Diff line
@@ -73,7 +73,6 @@ 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 {
@@ -151,61 +150,6 @@ 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
@@ -224,23 +168,20 @@ static char* cat_escape_dn_element(char *filtbuf, char *user)
 *
 * 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);
@@ -269,50 +210,66 @@ static void authn_ldap_build_filter(char *filtbuf,
        }
    }

    apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(&", filter);

    /* 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); 
    }

	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);

    /* 
     * 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;
            }
    ldap_value_free (dnbuf); 
        }
    }
#endif
    *q = '\0';

    /* 
     * Append the closing parens of the filter, unless doing so would 
     * overrun the buffer.
     */
    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);
    if (q + 2 <= filtbuf_end)
        strcat(filtbuf, "))");
}

static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d)
@@ -338,7 +295,6 @@ 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;
@@ -1097,11 +1053,6 @@ 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}
};