1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#define APR_WANT_STRFUNC
19
#include "apr_strings.h"
24
#include "http_config.h"
25
#include "http_core.h"
27
#include "http_protocol.h"
28
#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/
36
} authz_dbm_config_rec;
38
/* This should go into APR; perhaps with some nice
39
* caching/locking/flocking of the open dbm file.
41
static char *get_dbm_entry_as_str(apr_pool_t *pool, apr_dbm_t *f, char *key)
46
#ifndef NETSCAPE_DBM_COMPAT
47
q.dsize = strlen(q.dptr);
49
q.dsize = strlen(q.dptr) + 1;
52
if (apr_dbm_fetch(f, q, &d) == APR_SUCCESS && d.dptr) {
53
return apr_pstrmemdup(pool, d.dptr, d.dsize);
59
static void *create_authz_dbm_dir_config(apr_pool_t *p, char *d)
61
authz_dbm_config_rec *conf = apr_palloc(p, sizeof(*conf));
64
conf->dbmtype = "default";
65
conf->authoritative = 1; /* fortress is secure by default */
70
static const command_rec authz_dbm_cmds[] =
72
AP_INIT_TAKE1("AuthDBMGroupFile", ap_set_file_slot,
73
(void *)APR_OFFSETOF(authz_dbm_config_rec, grpfile),
74
OR_AUTHCFG, "database file containing group names and member user IDs"),
75
AP_INIT_TAKE1("AuthzDBMType", ap_set_string_slot,
76
(void *)APR_OFFSETOF(authz_dbm_config_rec, dbmtype),
77
OR_AUTHCFG, "what type of DBM file the group file is"),
78
AP_INIT_FLAG("AuthzDBMAuthoritative", ap_set_flag_slot,
79
(void *)APR_OFFSETOF(authz_dbm_config_rec, authoritative),
80
OR_AUTHCFG, "Set to 'Off' to allow access control to be passed along to "
81
"lower modules, if the group required is not found or empty, or the user "
82
" is not in the required groups. (default is On.)"),
86
module AP_MODULE_DECLARE_DATA authz_dbm_module;
88
/* We do something strange with the group file. If the group file
89
* contains any : we assume the format is
90
* key=username value=":"groupname [":"anything here is ignored]
91
* otherwise we now (0.8.14+) assume that the format is
92
* key=username value=groupname
93
* The first allows the password and group files to be the same
94
* physical DBM file; key=username value=password":"groupname[":"anything]
96
* mark@telescope.org, 22Sep95
99
static apr_status_t get_dbm_grp(request_rec *r, char *key1, char *key2,
100
char *dbmgrpfile, char *dbtype,
103
char *grp_colon, *val;
107
retval = apr_dbm_open_ex(&f, dbtype, dbmgrpfile, APR_DBM_READONLY,
108
APR_OS_DEFAULT, r->pool);
110
if (retval != APR_SUCCESS) {
114
/* Try key2 only if key1 failed */
115
if (!(val = get_dbm_entry_as_str(r->pool, f, key1))) {
116
val = get_dbm_entry_as_str(r->pool, f, key2);
121
if (val && (grp_colon = ap_strchr(val, ':')) != NULL) {
122
char *grp_colon2 = ap_strchr(++grp_colon, ':');
137
static int dbm_check_auth(request_rec *r)
139
authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
141
char *user = r->user;
142
int m = r->method_number;
143
const apr_array_header_t *reqs_arr = ap_requires(r);
144
require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
148
int required_group = 0;
149
const char *filegroup = NULL;
150
const char *orig_groups = NULL;
153
if (!conf->grpfile) {
161
for (x = 0; x < reqs_arr->nelts; x++) {
163
if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
167
t = reqs[x].requirement;
168
w = ap_getword_white(r->pool, &t);
170
if (!strcasecmp(w, "file-group")) {
171
filegroup = apr_table_get(r->notes, AUTHZ_GROUP_NOTE);
174
/* mod_authz_owner is not present or not
175
* authoritative. We are just a helper module for testing
176
* group membership, so we don't care and decline.
182
if (!strcasecmp(w, "group") || filegroup) {
183
const char *realm = ap_auth_name(r);
187
/* remember that actually a group is required */
190
/* fetch group data from dbm file only once. */
194
status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm,
197
conf->grpfile, conf->dbmtype, &groups);
199
if (status != APR_SUCCESS) {
200
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
201
"could not open dbm (type %s) group access "
202
"file: %s", conf->dbmtype, conf->grpfile);
203
return HTTP_INTERNAL_SERVER_ERROR;
206
if (groups == NULL) {
207
/* no groups available, so exit immediately */
208
reason = apr_psprintf(r->pool,
209
"user doesn't appear in DBM group "
210
"file (%s).", conf->grpfile);
214
orig_groups = groups;
218
groups = orig_groups;
220
v = ap_getword(r->pool, &groups, ',');
221
if (!strcmp(v, filegroup)) {
226
if (conf->authoritative) {
227
reason = apr_psprintf(r->pool,
228
"file group '%s' does not match.",
233
/* now forget the filegroup, thus alternatively require'd
234
groups get a real chance */
239
w = ap_getword_white(r->pool, &t);
240
groups = orig_groups;
242
v = ap_getword(r->pool, &groups, ',');
252
/* No applicable "require group" for this method seen */
253
if (!required_group || !conf->authoritative) {
257
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
258
"Authorization of user %s to access %s failed, reason: %s",
260
reason ? reason : "user is not part of the "
261
"'require'ed group(s).");
263
ap_note_auth_failure(r);
264
return HTTP_UNAUTHORIZED;
267
static void register_hooks(apr_pool_t *p)
269
static const char * const aszPre[]={ "mod_authz_owner.c", NULL };
271
ap_hook_auth_checker(dbm_check_auth, aszPre, NULL, APR_HOOK_MIDDLE);
274
module AP_MODULE_DECLARE_DATA authz_dbm_module =
276
STANDARD20_MODULE_STUFF,
277
create_authz_dbm_dir_config, /* dir config creater */
278
NULL, /* dir merger --- default is to override */
279
NULL, /* server config */
280
NULL, /* merge server config */
281
authz_dbm_cmds, /* command apr_table_t */
282
register_hooks /* register hooks */