Apache HTTPD
mod_access_compat.c
Go to the documentation of this file.
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/*
18 * Security options etc.
19 *
20 * Module derived from code originally written by Rob McCool
21 *
22 */
23
24#include "apr_strings.h"
25#include "apr_network_io.h"
26#include "apr_md5.h"
27
28#define APR_WANT_STRFUNC
29#define APR_WANT_BYTEFUNC
30#include "apr_want.h"
31
32#include "ap_config.h"
33#include "httpd.h"
34#include "http_core.h"
35#include "http_config.h"
36#include "http_log.h"
37#include "http_protocol.h"
38#include "http_request.h"
39
40#include "mod_auth.h"
41
42#if APR_HAVE_NETINET_IN_H
43#include <netinet/in.h>
44#endif
45
54
55typedef struct {
56 apr_int64_t limited;
57 union {
58 char *from;
60 } x;
62} allowdeny;
63
64/* things in the 'order' array */
65#define DENY_THEN_ALLOW 0
66#define ALLOW_THEN_DENY 1
67#define MUTUAL_FAILURE 2
68
69typedef struct {
73 int *satisfy; /* for every method one */
75
76module AP_MODULE_DECLARE_DATA access_compat_module;
77
79{
80 int i;
83
84 for (i = 0; i < METHODS; ++i) {
85 conf->order[i] = DENY_THEN_ALLOW;
86 }
87 conf->allows = apr_array_make(p, 1, sizeof(allowdeny));
88 conf->denys = apr_array_make(p, 1, sizeof(allowdeny));
89 conf->satisfy = apr_palloc(p, sizeof(*conf->satisfy) * METHODS);
90 for (i = 0; i < METHODS; ++i) {
91 conf->satisfy[i] = SATISFY_NOSPEC;
92 }
93
94 return (void *)conf;
95}
96
97static const char *order(cmd_parms *cmd, void *dv, const char *arg)
98{
100 int i, o;
101
102 if (!strcasecmp(arg, "allow,deny"))
103 o = ALLOW_THEN_DENY;
104 else if (!strcasecmp(arg, "deny,allow"))
105 o = DENY_THEN_ALLOW;
106 else if (!strcasecmp(arg, "mutual-failure"))
107 o = MUTUAL_FAILURE;
108 else
109 return "unknown order";
110
111 for (i = 0; i < METHODS; ++i)
112 if (cmd->limited & (AP_METHOD_BIT << i))
113 d->order[i] = o;
114
115 return NULL;
116}
117
118static const char *satisfy(cmd_parms *cmd, void *dv, const char *arg)
119{
122 int i;
123
124 if (!strcasecmp(arg, "all")) {
126 }
127 else if (!strcasecmp(arg, "any")) {
129 }
130 else {
131 return "Satisfy either 'any' or 'all'.";
132 }
133
134 for (i = 0; i < METHODS; ++i) {
135 if (cmd->limited & (AP_METHOD_BIT << i)) {
136 d->satisfy[i] = satisfy;
137 }
138 }
139
140 return NULL;
141}
142
143static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from,
144 const char *where_c)
145{
147 allowdeny *a;
148 char *where = apr_pstrdup(cmd->pool, where_c);
149 char *s;
150 apr_status_t rv;
151
152 if (strcasecmp(from, "from"))
153 return "allow and deny must be followed by 'from'";
154
155 a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys);
156 a->x.from = where;
157 a->limited = cmd->limited;
158
159 if (!strncasecmp(where, "env=!", 5)) {
160 a->type = T_NENV;
161 a->x.from += 5;
162
163 }
164 else if (!strncasecmp(where, "env=", 4)) {
165 a->type = T_ENV;
166 a->x.from += 4;
167
168 }
169 else if (!strcasecmp(where, "all")) {
170 a->type = T_ALL;
171 }
172 else if ((s = ap_strchr(where, '/'))) {
173 *s++ = '\0';
174 rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool);
175 if(APR_STATUS_IS_EINVAL(rv)) {
176 /* looked nothing like an IP address */
177 return "An IP address was expected";
178 }
179 else if (rv != APR_SUCCESS) {
180 return apr_psprintf(cmd->pool, "%pm", &rv);
181 }
182 a->type = T_IP;
183 }
184 else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where,
185 NULL, cmd->pool))) {
186 if (rv != APR_SUCCESS)
187 return apr_psprintf(cmd->pool, "%pm", &rv);
188 a->type = T_IP;
189 }
190 else if (ap_strchr(where, '#')) {
191 return "No comments are allowed here";
192 }
193 else { /* no slash, didn't look like an IP address => must be a host */
194 a->type = T_HOST;
195 }
196
197 return NULL;
198}
199
200static char its_an_allow;
201
203{
204 AP_INIT_TAKE1("order", order, NULL, OR_LIMIT,
205 "'allow,deny', 'deny,allow', or 'mutual-failure'"),
207 "'from' followed by hostnames or IP-address wildcards"),
209 "'from' followed by hostnames or IP-address wildcards"),
211 "access policy if both allow and require used ('all' or 'any')"),
212 {NULL}
213};
214
215static int in_domain(const char *domain, const char *what)
216{
217 int dl = strlen(domain);
218 int wl = strlen(what);
219
220 if ((wl - dl) >= 0) {
221 if (strcasecmp(domain, &what[wl - dl]) != 0) {
222 return 0;
223 }
224
225 /* Make sure we matched an *entire* subdomain --- if the user
226 * said 'allow from good.com', we don't want people from nogood.com
227 * to be able to get in.
228 */
229
230 if (wl == dl) {
231 return 1; /* matched whole thing */
232 }
233 else {
234 return (domain[0] == '.' || what[wl - dl - 1] == '.');
235 }
236 }
237 else {
238 return 0;
239 }
240}
241
243{
244
245 allowdeny *ap = (allowdeny *) a->elts;
246 apr_int64_t mmask = (AP_METHOD_BIT << method);
247 int i;
248 int gothost = 0;
249 const char *remotehost = NULL;
250
251 for (i = 0; i < a->nelts; ++i) {
252 if (!(mmask & ap[i].limited)) {
253 continue;
254 }
255
256 switch (ap[i].type) {
257 case T_ENV:
258 if (apr_table_get(r->subprocess_env, ap[i].x.from)) {
259 return 1;
260 }
261 break;
262
263 case T_NENV:
264 if (!apr_table_get(r->subprocess_env, ap[i].x.from)) {
265 return 1;
266 }
267 break;
268
269 case T_ALL:
270 return 1;
271
272 case T_IP:
273 if (apr_ipsubnet_test(ap[i].x.ip, r->useragent_addr)) {
274 return 1;
275 }
276 break;
277
278 case T_HOST:
279 if (!gothost) {
280 int remotehost_is_ip;
281
283 &remotehost_is_ip);
284
285 if ((remotehost == NULL) || remotehost_is_ip) {
286 gothost = 1;
287 }
288 else {
289 gothost = 2;
290 }
291 }
292
293 if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) {
294 return 1;
295 }
296 break;
297
298 case T_FAIL:
299 /* do nothing? */
300 break;
301 }
302 }
303
304 return 0;
305}
306
308{
310 ap_get_module_config(r->per_dir_config, &access_compat_module);
311
312 return conf->satisfy[r->method_number];
313}
314
316{
317 int method = r->method_number;
318 int ret = OK;
320 ap_get_module_config(r->per_dir_config, &access_compat_module);
321
322 if (a->order[method] == ALLOW_THEN_DENY) {
323 ret = HTTP_FORBIDDEN;
324 if (find_allowdeny(r, a->allows, method)) {
325 ret = OK;
326 }
327 if (find_allowdeny(r, a->denys, method)) {
328 ret = HTTP_FORBIDDEN;
329 }
330 }
331 else if (a->order[method] == DENY_THEN_ALLOW) {
332 if (find_allowdeny(r, a->denys, method)) {
333 ret = HTTP_FORBIDDEN;
334 }
335 if (find_allowdeny(r, a->allows, method)) {
336 ret = OK;
337 }
338 }
339 else {
340 if (find_allowdeny(r, a->allows, method)
341 && !find_allowdeny(r, a->denys, method)) {
342 ret = OK;
343 }
344 else {
345 ret = HTTP_FORBIDDEN;
346 }
347 }
348
349 if (ret == HTTP_FORBIDDEN) {
351 "client denied by server configuration: %s%s",
352 r->filename ? "" : "uri ",
353 r->filename ? r->filename : r->uri);
354 }
355
356 return ret;
357}
358
360{
362
363 /* This can be access checker since we don't require r->user to be set. */
366}
367
368AP_DECLARE_MODULE(access_compat) =
369{
371 create_access_compat_dir_config, /* dir config creater */
372 NULL, /* dir merger --- default is to override */
373 NULL, /* server config */
374 NULL, /* merge server config */
376 register_hooks /* register hooks */
377};
Symbol export macros and hook functions.
APR MD5 Routines.
APR Network library.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
static apr_OFN_access_compat_ap_satisfies_t * access_compat_ap_satisfies
Definition core.c:819
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_INIT_ITERATE2(directive, func, mconfig, where, help)
#define AP_DECLARE_MODULE(foo)
request_rec * r
#define OK
Definition httpd.h:456
#define SATISFY_ANY
Definition http_core.h:125
#define SATISFY_NOSPEC
Definition http_core.h:127
#define SATISFY_ALL
Definition http_core.h:123
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
#define AP_AUTH_INTERNAL_PER_CONF
void ap_hook_check_access(ap_HOOK_access_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder, int type)
Definition request.c:2194
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define APR_STATUS_IS_EINVAL(s)
Definition apr_errno.h:1266
apr_bucket apr_bucket_brigade * a
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_REGISTER_OPTIONAL_FN(name)
#define OR_LIMIT
#define OR_AUTHCFG
#define HTTP_FORBIDDEN
Definition httpd.h:511
#define AP_METHOD_BIT
Definition httpd.h:629
#define METHODS
Definition httpd.h:624
#define STANDARD20_MODULE_STUFF
#define ap_strchr(s, c)
Definition httpd.h:2351
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_seek_where_t where
int type
int strcasecmp(const char *a, const char *b)
int strncasecmp(const char *a, const char *b, size_t n)
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_uint32_t apr_pool_t apr_uint32_t apr_pollset_method_e method
Definition apr_poll.h:195
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
apr_cmdtype_e cmd
const char * ap_get_useragent_host(request_rec *req, int type, int *str_is_ip)
Definition core.c:1036
#define REMOTE_DOUBLE_REV
Definition http_core.h:118
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method)
static int in_domain(const char *domain, const char *what)
static void * create_access_compat_dir_config(apr_pool_t *p, char *dummy)
#define DENY_THEN_ALLOW
static const command_rec access_compat_cmds[]
static int check_dir_access(request_rec *r)
static const char * satisfy(cmd_parms *cmd, void *dv, const char *arg)
#define MUTUAL_FAILURE
static void register_hooks(apr_pool_t *p)
static const char * allow_cmd(cmd_parms *cmd, void *dv, const char *from, const char *where_c)
#define ALLOW_THEN_DENY
static char its_an_allow
allowdeny_type
@ T_FAIL
@ T_HOST
@ T_ENV
@ T_ALL
@ T_NENV
static const char * order(cmd_parms *cmd, void *dv, const char *arg)
Authentication and Authorization Extension for Apache.
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
apr_array_header_t * allows
apr_array_header_t * denys
apr_int64_t limited
apr_ipsubnet_t * ip
enum allowdeny_type type
const apr_bucket_type_t * type
A structure that represents the current request.
Definition httpd.h:845
char * uri
Definition httpd.h:1016
int method_number
Definition httpd.h:898
apr_sockaddr_t * useragent_addr
Definition httpd.h:1100
char * filename
Definition httpd.h:1018
apr_table_t * subprocess_env
Definition httpd.h:983
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047