~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/aaa/mod_authz_owner.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
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.
 
15
 */
 
16
 
 
17
#include "apr_strings.h"
 
18
#include "apr_file_info.h"
 
19
#include "apr_user.h"
 
20
 
 
21
#include "ap_config.h"
 
22
#include "httpd.h"
 
23
#include "http_config.h"
 
24
#include "http_core.h"
 
25
#include "http_log.h"
 
26
#include "http_protocol.h"
 
27
#include "http_request.h"
 
28
 
 
29
#include "mod_auth.h"     /* for AUTHZ_GROUP_NOTE */
 
30
 
 
31
typedef struct {
 
32
    int authoritative;
 
33
} authz_owner_config_rec;
 
34
 
 
35
static void *create_authz_owner_dir_config(apr_pool_t *p, char *d)
 
36
{
 
37
    authz_owner_config_rec *conf = apr_palloc(p, sizeof(*conf));
 
38
 
 
39
    conf->authoritative = 1; /* keep the fortress secure by default */
 
40
    return conf;
 
41
}
 
42
 
 
43
static const command_rec authz_owner_cmds[] =
 
44
{
 
45
    AP_INIT_FLAG("AuthzOwnerAuthoritative", ap_set_flag_slot,
 
46
                 (void *)APR_OFFSETOF(authz_owner_config_rec, authoritative),
 
47
                 OR_AUTHCFG,
 
48
                 "Set to 'Off' to allow access control to be passed along to "
 
49
                 "lower modules. (default is On.)"),
 
50
    {NULL}
 
51
};
 
52
 
 
53
module AP_MODULE_DECLARE_DATA authz_owner_module;
 
54
 
 
55
static int check_file_owner(request_rec *r)
 
56
{
 
57
    authz_owner_config_rec *conf = ap_get_module_config(r->per_dir_config,
 
58
                                                        &authz_owner_module);
 
59
    int m = r->method_number;
 
60
    register int x;
 
61
    const char *t, *w;
 
62
    const apr_array_header_t *reqs_arr = ap_requires(r);
 
63
    require_line *reqs;
 
64
    int required_owner = 0;
 
65
    apr_status_t status = 0;
 
66
    char *reason = NULL;
 
67
 
 
68
    if (!reqs_arr) {
 
69
        return DECLINED;
 
70
    }
 
71
 
 
72
    reqs = (require_line *)reqs_arr->elts;
 
73
    for (x = 0; x < reqs_arr->nelts; x++) {
 
74
 
 
75
        /* if authoritative = On then break if a require already failed. */
 
76
        if (reason && conf->authoritative) {
 
77
            break;
 
78
        }
 
79
 
 
80
        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
 
81
            continue;
 
82
        }
 
83
 
 
84
        t = reqs[x].requirement;
 
85
        w = ap_getword_white(r->pool, &t);
 
86
 
 
87
        if (!strcmp(w, "file-owner")) {
 
88
#if !APR_HAS_USER
 
89
            if ((required_owner & ~1) && conf->authoritative) {
 
90
                break;
 
91
            }
 
92
 
 
93
            required_owner |= 1; /* remember the requirement */
 
94
            reason = "'Require file-owner' is not supported on this platform.";
 
95
            continue;
 
96
#else  /* APR_HAS_USER */
 
97
            char *owner = NULL;
 
98
            apr_finfo_t finfo;
 
99
 
 
100
            if ((required_owner & ~1) && conf->authoritative) {
 
101
                break;
 
102
            }
 
103
 
 
104
            required_owner |= 1; /* remember the requirement */
 
105
 
 
106
            if (!r->filename) {
 
107
                reason = "no filename available";
 
108
                continue;
 
109
            }
 
110
 
 
111
            status = apr_stat(&finfo, r->filename, APR_FINFO_USER, r->pool);
 
112
            if (status != APR_SUCCESS) {
 
113
                reason = apr_pstrcat(r->pool, "could not stat file ",
 
114
                                     r->filename, NULL);
 
115
                continue;
 
116
            }
 
117
 
 
118
            if (!(finfo.valid & APR_FINFO_USER)) {
 
119
                reason = "no file owner information available";
 
120
                continue;
 
121
            }
 
122
 
 
123
            status = apr_uid_name_get(&owner, finfo.user, r->pool);
 
124
            if (status != APR_SUCCESS || !owner) {
 
125
                reason = "could not get name of file owner";
 
126
                continue;
 
127
            }
 
128
 
 
129
            if (strcmp(owner, r->user)) {
 
130
                reason = apr_psprintf(r->pool, "file owner %s does not match.",
 
131
                                      owner);
 
132
                continue;
 
133
            }
 
134
 
 
135
            /* this user is authorized */
 
136
            return OK;
 
137
#endif /* APR_HAS_USER */
 
138
        }
 
139
 
 
140
        /* file-group only figures out the file's group and lets
 
141
         * other modules do the actual authorization (against a group file/db).
 
142
         * Thus, these modules have to hook themselves after
 
143
         * mod_authz_owner and of course recognize 'file-group', too.
 
144
         */
 
145
        if (!strcmp(w, "file-group")) {
 
146
#if !APR_HAS_USER
 
147
            if ((required_owner & ~6) && conf->authoritative) {
 
148
                break;
 
149
            }
 
150
 
 
151
            required_owner |= 2; /* remember the requirement */
 
152
            reason = "'Require file-group' is not supported on this platform.";
 
153
            continue;
 
154
#else  /* APR_HAS_USER */
 
155
            char *group = NULL;
 
156
            apr_finfo_t finfo;
 
157
 
 
158
            if ((required_owner & ~6) && conf->authoritative) {
 
159
                break;
 
160
            }
 
161
 
 
162
            required_owner |= 2; /* remember the requirement */
 
163
 
 
164
            if (!r->filename) {
 
165
                reason = "no filename available";
 
166
                continue;
 
167
            }
 
168
 
 
169
            status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool);
 
170
            if (status != APR_SUCCESS) {
 
171
                reason = apr_pstrcat(r->pool, "could not stat file ",
 
172
                                     r->filename, NULL);
 
173
                continue;
 
174
            }
 
175
 
 
176
            if (!(finfo.valid & APR_FINFO_GROUP)) {
 
177
                reason = "no file group information available";
 
178
                continue;
 
179
            }
 
180
 
 
181
            status = apr_gid_name_get(&group, finfo.group, r->pool);
 
182
            if (status != APR_SUCCESS || !group) {
 
183
                reason = "could not get name of file group";
 
184
                continue;
 
185
            }
 
186
 
 
187
            /* store group name in a note and let others decide... */
 
188
            apr_table_setn(r->notes, AUTHZ_GROUP_NOTE, group);
 
189
            required_owner |= 4;
 
190
            continue;
 
191
#endif /* APR_HAS_USER */
 
192
        }
 
193
    }
 
194
 
 
195
    if (!required_owner || !conf->authoritative) {
 
196
        return DECLINED;
 
197
    }
 
198
 
 
199
    /* allow file-group passed to group db modules either if this is the
 
200
     * only applicable requirement here or if a file-owner failed but we're
 
201
     * not authoritative.
 
202
     * This allows configurations like:
 
203
     *
 
204
     * AuthzOwnerAuthoritative Off
 
205
     * require file-owner
 
206
     * require file-group
 
207
     *
 
208
     * with the semantical meaning of "either owner or group must match"
 
209
     * (inclusive or)
 
210
     *
 
211
     * [ 6 == 2 | 4; 7 == 1 | 2 | 4 ] should I use #defines instead?
 
212
     */
 
213
    if (required_owner == 6 || (required_owner == 7 && !conf->authoritative)) {
 
214
        return DECLINED;
 
215
    }
 
216
 
 
217
    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
 
218
                  "Authorization of user %s to access %s failed, reason: %s",
 
219
                  r->user, r->uri, reason ? reason : "unknown");
 
220
 
 
221
    ap_note_auth_failure(r);
 
222
    return HTTP_UNAUTHORIZED;
 
223
}
 
224
 
 
225
static void register_hooks(apr_pool_t *p)
 
226
{
 
227
    ap_hook_auth_checker(check_file_owner, NULL, NULL, APR_HOOK_MIDDLE);
 
228
}
 
229
 
 
230
module AP_MODULE_DECLARE_DATA authz_owner_module =
 
231
{
 
232
    STANDARD20_MODULE_STUFF,
 
233
    create_authz_owner_dir_config, /* dir config creater */
 
234
    NULL,                          /* dir merger --- default is to override */
 
235
    NULL,                          /* server config */
 
236
    NULL,                          /* merge server config */
 
237
    authz_owner_cmds,              /* command apr_table_t */
 
238
    register_hooks                 /* register hooks */
 
239
};