mod_authz_groupfile.c revision 33bdcae1f7a1a65e351dda2a766a0cf28b1e695d
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor/* ====================================================================
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * The Apache Software License, Version 1.1
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * reserved.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * Redistribution and use in source and binary forms, with or without
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * modification, are permitted provided that the following conditions
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * are met:
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * 1. Redistributions of source code must retain the above copyright
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * notice, this list of conditions and the following disclaimer.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * 2. Redistributions in binary form must reproduce the above copyright
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * notice, this list of conditions and the following disclaimer in
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * the documentation and/or other materials provided with the
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * distribution.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * 3. The end-user documentation included with the redistribution,
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * if any, must include the following acknowledgment:
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * "This product includes software developed by the
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * Apache Software Foundation (http://www.apache.org/)."
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * Alternately, this acknowledgment may appear in the software itself,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * if and wherever such third-party acknowledgments normally appear.
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * 4. The names "Apache" and "Apache Software Foundation" must
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * not be used to endorse or promote products derived from this
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * software without prior written permission. For written
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * permission, please contact apache@apache.org.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * 5. Products derived from this software may not be called "Apache",
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * nor may "Apache" appear in their name, without prior written
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * permission of the Apache Software Foundation.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * SUCH DAMAGE.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * ====================================================================
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * This software consists of voluntary contributions made by many
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * individuals on behalf of the Apache Software Foundation. For more
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * information on the Apache Software Foundation, please see
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf * <http://www.apache.org/>.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * Portions of this software are based upon public domain software
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * originally written at the National Center for Supercomputing Applications,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * University of Illinois, Urbana-Champaign.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor */
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor/* This module is triggered by an
ffb01336be79c64046b636e59fa8ddca8ec029edsf *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * AuthGroupFile standard /path/to/file
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * and the presense of a
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * require group <list-of-groups>
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * In an applicable limit/directory block for that method.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * If there are no AuthGroupFile directives valid for
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * the request; we DECLINED.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * If the AuthGroupFile is defined; but somehow not
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * accessible: we SERVER_ERROR (was DECLINED).
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * If there are no 'require ' directives defined for
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * this request then we DECLINED (was OK).
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * If there are no 'require ' directives valid for
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * this request method then we DECLINED. (was OK)
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * If there are any 'require group' blocks and we
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * are not in any group - we HTTP_UNAUTHORIZE
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * unless we are non-authoritative; in which
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor * case we DECLINED.
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor *
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor */
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
48c64aeceef385e19025b384bd719b2a9789592dnd#include "apr_strings.h"
48c64aeceef385e19025b384bd719b2a9789592dnd
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor#include "ap_config.h"
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor#include "httpd.h"
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor#include "http_config.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen#include "http_core.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen#include "http_log.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen#include "http_protocol.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen#include "http_request.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen#include "mod_auth.h"
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowentypedef struct {
1462ff536f1b939bb337766b2056109c29664c4erbowen char *groupfile;
1462ff536f1b939bb337766b2056109c29664c4erbowen int authoritative;
1462ff536f1b939bb337766b2056109c29664c4erbowen} authz_groupfile_config_rec;
1462ff536f1b939bb337766b2056109c29664c4erbowen
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzorstatic void *create_authz_groupfile_dir_config(apr_pool_t *p, char *d)
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor{
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor authz_groupfile_config_rec *conf = apr_palloc(p, sizeof(*conf));
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor conf->groupfile = NULL;
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor conf->authoritative = 1; /* keep the fortress secure by default */
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor return conf;
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor}
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzorstatic const char *set_authz_groupfile_slot(cmd_parms *cmd, void *offset, const char *f,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor const char *t)
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor{
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor if (t && strcmp(t, "standard")) {
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor return apr_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor }
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor return ap_set_file_slot(cmd, offset, f);
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor}
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzorstatic const command_rec authz_groupfile_cmds[] =
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor{
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor AP_INIT_TAKE12("AuthGroupFile", set_authz_groupfile_slot,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor (void *)APR_OFFSETOF(authz_groupfile_config_rec, groupfile),
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor OR_AUTHCFG,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor "text file containing group names and member user IDs"),
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor AP_INIT_FLAG("AuthzGroupFileAuthoritative", ap_set_flag_slot,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor (void *)APR_OFFSETOF(authz_groupfile_config_rec,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor authoritative),
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor OR_AUTHCFG,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor "Set to 'Off' to allow access control to be passed along to "
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor "lower modules if the 'require group' fails. (default is "
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor "On)."),
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor {NULL}
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor};
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzormodule AP_MODULE_DECLARE_DATA authz_groupfile_module;
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzorstatic apr_status_t groups_for_user(apr_pool_t *p, char *user, char *grpfile,
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor apr_table_t ** out)
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor{
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor ap_configfile_t *f;
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor apr_table_t *grps = apr_table_make(p, 15);
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor apr_pool_t *sp;
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf char l[MAX_STRING_LEN];
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf const char *group_name, *ll, *w;
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf apr_status_t status;
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen if ((status = ap_pcfg_openfile(&f, p, grpfile)) != APR_SUCCESS) {
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf return status ;
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf }
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf
e40d2af13fd7ff120eda49cd327c68fbc16443e8sf apr_pool_create(&sp, p);
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
1462ff536f1b939bb337766b2056109c29664c4erbowen if ((l[0] == '#') || (!l[0])) {
1462ff536f1b939bb337766b2056109c29664c4erbowen continue;
1462ff536f1b939bb337766b2056109c29664c4erbowen }
1462ff536f1b939bb337766b2056109c29664c4erbowen ll = l;
1462ff536f1b939bb337766b2056109c29664c4erbowen apr_pool_clear(sp);
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen group_name = ap_getword(sp, &ll, ':');
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen while (ll[0]) {
1462ff536f1b939bb337766b2056109c29664c4erbowen w = ap_getword_conf(sp, &ll);
1462ff536f1b939bb337766b2056109c29664c4erbowen if (!strcmp(w, user)) {
1462ff536f1b939bb337766b2056109c29664c4erbowen apr_table_setn(grps, apr_pstrdup(p, group_name), "in");
1462ff536f1b939bb337766b2056109c29664c4erbowen break;
1462ff536f1b939bb337766b2056109c29664c4erbowen }
1462ff536f1b939bb337766b2056109c29664c4erbowen }
1462ff536f1b939bb337766b2056109c29664c4erbowen }
1462ff536f1b939bb337766b2056109c29664c4erbowen ap_cfg_closefile(f);
1462ff536f1b939bb337766b2056109c29664c4erbowen apr_pool_destroy(sp);
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen *out = grps;
1462ff536f1b939bb337766b2056109c29664c4erbowen return APR_SUCCESS;
1462ff536f1b939bb337766b2056109c29664c4erbowen}
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen/* Checking ID */
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowenstatic int check_user_access(request_rec *r)
1462ff536f1b939bb337766b2056109c29664c4erbowen{
1462ff536f1b939bb337766b2056109c29664c4erbowen authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config,
1462ff536f1b939bb337766b2056109c29664c4erbowen &authz_groupfile_module);
1462ff536f1b939bb337766b2056109c29664c4erbowen char *user = r->user;
1462ff536f1b939bb337766b2056109c29664c4erbowen int m = r->method_number;
1462ff536f1b939bb337766b2056109c29664c4erbowen int required_group = 0;
1462ff536f1b939bb337766b2056109c29664c4erbowen register int x;
1462ff536f1b939bb337766b2056109c29664c4erbowen const char *t, *w;
1462ff536f1b939bb337766b2056109c29664c4erbowen apr_table_t *grpstatus = NULL;
1462ff536f1b939bb337766b2056109c29664c4erbowen const apr_array_header_t *reqs_arr = ap_requires(r);
1462ff536f1b939bb337766b2056109c29664c4erbowen require_line *reqs;
1462ff536f1b939bb337766b2056109c29664c4erbowen const char *filegroup = NULL;
1462ff536f1b939bb337766b2056109c29664c4erbowen char *reason = NULL;
1462ff536f1b939bb337766b2056109c29664c4erbowen
1462ff536f1b939bb337766b2056109c29664c4erbowen /* If there is no group file - then we are not
1462ff536f1b939bb337766b2056109c29664c4erbowen * configured. So decline.
1462ff536f1b939bb337766b2056109c29664c4erbowen */
1462ff536f1b939bb337766b2056109c29664c4erbowen if (!(conf->groupfile)) {
1462ff536f1b939bb337766b2056109c29664c4erbowen return DECLINED;
1462ff536f1b939bb337766b2056109c29664c4erbowen }
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor if (!reqs_arr) {
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor return DECLINED; /* XXX change from legacy */
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung }
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
9c1260efa52c82c2a58e5b5f20cd6902563d95f5rbowen reqs = (require_line *)reqs_arr->elts;
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor
cc8190433d13f5e9de618c5d7f10c824c0c1919cgryzor for (x = 0; x < reqs_arr->nelts; x++) {
if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
continue;
}
t = reqs[x].requirement;
w = ap_getword_white(r->pool, &t);
/* needs mod_authz_owner to be present */
if (!strcmp(w, "file-group")) {
filegroup = apr_table_get(r->notes, AUTHZ_GROUP_NOTE);
if (!filegroup) {
/* mod_authz_owner is not present or not
* authoritative. We are just a helper module for testing
* group membership, so we don't care and decline.
*/
continue;
}
}
if (!strcmp(w, "group") || filegroup) {
required_group = 1; /* remember the requirement */
/* create group table only if actually needed. */
if (!grpstatus) {
apr_status_t status;
status = groups_for_user(r->pool, user, conf->groupfile,
&grpstatus);
if (status != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
"Could not open group file: %s",
conf->groupfile);
return HTTP_INTERNAL_SERVER_ERROR;
}
if (apr_table_elts(grpstatus)->nelts == 0) {
/* no groups available, so exit immediately */
reason = apr_psprintf(r->pool,
"user doesn't appear in group file "
"(%s).", conf->groupfile);
break;
}
}
if (filegroup) {
if (apr_table_get(grpstatus, filegroup)) {
return OK;
}
if (conf->authoritative) {
reason = apr_psprintf(r->pool,
"file group '%s' does not match.",
filegroup);
break;
}
/* now forget the filegroup, thus alternatively require'd
groups get a real chance */
filegroup = NULL;
}
else {
while (t[0]) {
w = ap_getword_conf(r->pool, &t);
if (apr_table_get(grpstatus, w)) {
return OK;
}
}
}
}
}
/* No applicable "require group" for this method seen */
if (!required_group || !conf->authoritative) {
return DECLINED;
}
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Authorization of user %s to access %s failed, reason: %s",
r->user, r->uri,
reason ? reason : "user is not part of the "
"'require'ed group(s).");
ap_note_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
static void register_hooks(apr_pool_t *p)
{
static const char * const aszPre[]={ "mod_authz_owner.c", NULL };
ap_hook_auth_checker(check_user_access, aszPre, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA authz_groupfile_module =
{
STANDARD20_MODULE_STUFF,
create_authz_groupfile_dir_config,/* dir config creater */
NULL, /* dir merger -- default is to override */
NULL, /* server config */
NULL, /* merge server config */
authz_groupfile_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};