At 11:13 PM 3/2/2005, William A. Rowe, Jr. wrote:
>x>>No - simply create a per-dir config, and use dirconfig to represent;
>>>
>>>> <AuthConfig>
>>>>     AuthFile users1
>>>> </AuthConfig>
>>
>>How does that work?  The issue here is that we want to use the same module 
>>multiple times in the same location/directory/file.  So, there'd only be one 
>>per-dir-config instance.  -- justin
>
>I found an hour to hack it, but it will take two more to wrap it.

And attached is the module for comment.  I have no time till this
weekend if then, so I've got the build system changes and will
commit if we like.

Bill 
/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
 * applicable.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "httpd.h"
#include "http_request.h"
#include "apr_strings.h"

#define CORE_PRIVATE
#include "http_config.h"


module AP_MODULE_DECLARE_DATA auth_config_module;

typedef struct auth_dir_conf {
    apr_array_header_t *sec_auth;
} auth_dir_conf;


static void *create_auth_dir_config(apr_pool_t *p, char *dummy)
{
    auth_dir_conf *conf =
        (auth_dir_conf *) apr_palloc(p, sizeof(auth_dir_conf));

    /* Created in authsection, when invoked */
    conf->sec_auth = NULL;

    return (void *) conf;
}

static void *merge_auth_dir_config(apr_pool_t *p, void *basev, void *addv)
{
    auth_dir_conf *conf = (auth_dir_conf *) apr_palloc(p, 
sizeof(auth_dir_conf));
    auth_dir_conf *base = (auth_dir_conf *) basev;
    auth_dir_conf *add = (auth_dir_conf *) addv;

    if (add->sec_auth) {
        conf->sec_auth = add->sec_auth;
    }
    else {
        conf->sec_auth = base->sec_auth;
    }
    /* The logic; 
     * conf->auth_dir_conf = apr_array_append(p, base->sec_auth, add->sec_auth);
     * would be useful, if we had a way to distinguish when <AuthConfig > should
     * override <AuthConfig> from a lower scope.
     */

    return conf;
}

static const char *authsection(cmd_parms *cmd, void *confv, const char *arg)
{
    int old_overrides = cmd->override;
    auth_dir_conf *conf = (auth_dir_conf *)confv;
    ap_conf_vector_t *new_auth_config = ap_create_per_dir_config(cmd->pool);
    const char *endp = ap_strrchr_c(arg, '>');
    const char *errmsg = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    if (errmsg != NULL) 
        return errmsg;

    if (endp == NULL)
        return apr_pstrcat(cmd->pool, cmd->cmd->name,
                           "> directive missing closing '>'", NULL);

    if (arg)
        return apr_pstrcat(cmd->pool, "<AuthConfig> takes no options, ", arg, 
                           " is invalid", NULL);

    /* Create the sec_auth array on demand */
    if (!conf->sec_auth)
        conf->sec_auth = apr_array_make(cmd->pool, 2, sizeof(ap_conf_vector_t 
*));

    cmd->override = ACCESS_CONF;

    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_auth_config);

    *((void **)apr_array_push(conf->sec_auth)) = new_auth_config;
    cmd->override = old_overrides;

    /* Hopefully NULL */
    return errmsg;
}


static int auth_check_user_id(request_rec *r)
{
    int access_status;
    void *recurse;
    auth_dir_conf *conf = ap_get_module_config(r->per_dir_config, 
                                               &auth_config_module);
    ap_conf_vector_t *orig_dir_config = r->per_dir_config;
    ap_conf_vector_t **auth_elt;
    int auth_nelt;

    if (!conf->sec_auth)
        return DECLINED;

    if ((apr_pool_userdata_get((void**)&recurse, "mod_auth_config::recurse",
                               r->pool) != APR_SUCCESS) && recurse) 
        return DONE;

    auth_elt = (ap_conf_vector_t **)conf->sec_auth->elts;
    auth_nelt = conf->sec_auth->nelts;

    apr_pool_userdata_setn((void*) -1, "mod_auth_config::recurse", 
                           apr_pool_cleanup_null, r->pool);

    while (auth_nelt && *auth_elt) {

        r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config, 
                                                              *auth_elt);
        access_status = ap_run_check_user_id(r);

        /* We contine on DONE, only auth_config returns it */
        if ((access_status != DONE)  && (access_status != DECLINED)) {
            apr_pool_userdata_setn(NULL, "mod_auth_config::recurse", 
                                   apr_pool_cleanup_null, r->pool);
            return access_status;
        }

        --auth_nelt;
        ++auth_elt;
    }

    apr_pool_userdata_setn(NULL, "mod_auth_config::recurse", 
                           apr_pool_cleanup_null, r->pool);
    r->per_dir_config = orig_dir_config;
    return access_status;
}

static const command_rec auth_config_cmds[] =
{
    AP_INIT_RAW_ARGS("<AuthConfig", authsection, NULL, RSRC_CONF, 
    "Container for directives offering alternately acceptable auth"),
    {NULL}
};

static void register_hooks(apr_pool_t *p)
{
    /* Priority immediately before anon */
    ap_hook_check_user_id(auth_check_user_id,NULL,NULL,APR_HOOK_LAST+1);
}

module AP_MODULE_DECLARE_DATA auth_config_module =
{
    STANDARD20_MODULE_STUFF,
    create_auth_dir_config,        /* dir config creater */
    merge_auth_dir_config,         /* dir merger --- default is to override */
    NULL,                          /* server config */
    NULL,                          /* merge server config */
    auth_config_cmds,              /* command apr_table_t */
    register_hooks                 /* register hooks */
};

Reply via email to