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.
18 * Security options etc.
20 * Module derived from code originally written by Rob McCool
24 #include "apr_strings.h"
25 #include "apr_network_io.h"
28 #define APR_WANT_STRFUNC
29 #define APR_WANT_BYTEFUNC
32 #include "ap_config.h"
34 #include "http_config.h"
35 #include "http_core.h"
37 #include "http_request.h"
38 #include "http_protocol.h"
39 #include "ap_provider.h"
43 #if APR_HAVE_NETINET_IN_H
44 #include <netinet/in.h>
49 X- Convert all of the authz modules to providers
50 X- Remove the ap_requires field from the core_dir_config structure
51 X- Remove the ap_requires field from authz_dir_conf
52 X- Remove the function ap_requires() and authz_ap_requires()
53 since their functionality is no longer supported
54 or necessary in the refactoring
55 X- Remove the calls to ap_some_auth_required() in the
56 core request handling to allow the hooks to be called
57 in all cases. Is this function even necessary
59 X- Determine of merge_authz_dir_config is even
60 necessary and remove if not
61 X- Split the authz type from the arguments when the
62 authz provider is registered and store the type
63 in ->provider_name and the arguments in ->requirement
64 X- Move the check for METHOD_MASK out of the authz
65 providers and into the provider vector
66 X- Change the status code to AUTHZ_DENIED, AUTHZ_GRANTED
67 and AUTHZ_GENERAL_ERROR
68 - Determine if setting the AUTHZ_PROVIDER_NAME_NOTE note
69 is even necessary. This was used in authn to support
70 authn_alias. Is there a need for an authz_alias?
71 X- Remove the Satisfy directive functionality and replace it with the
72 <SatisfyAll>, <SatisfyOne> directives
73 X- Remove the Satisfy directive
74 X- Implement the <SatisfyAll> <SatisfyOne> block directives
75 to handle the 'and' and 'or' logic for authorization.
76 X- Remove the AuthzXXXAuthoritative directives from all of
78 X- Implement the Reject directive that will deny authorization
79 if the argument is true
80 X- Fold the Reject directive into the <SatisfyAll> <SatisfyOne>
82 X- Reimplement the host based authorization 'allow', 'deny'
83 and 'order' as authz providers
84 X- Remove the 'allow', 'deny' and 'order' directives
85 - Merge mod_authn_alias into mod_authn_core
86 X- Remove all of the references to the authzxxxAuthoritative
87 directives from the documentation
88 X- Remove the Satisfy directive from the documentation
91 typedef struct provider_alias_rec {
95 ap_conf_vector_t *sec_auth;
96 const authz_provider *provider;
100 authz_provider_list *providers;
101 authz_request_state req_state;
104 } authz_core_dir_conf;
106 typedef struct authz_core_srv_conf {
107 apr_hash_t *alias_rec;
108 } authz_core_srv_conf;
110 module AP_MODULE_DECLARE_DATA authz_core_module;
111 static const char *merge_authz_provider(authz_core_dir_conf *conf, authz_provider_list *newp);
112 static void walk_merge_provider_list(apr_pool_t *a, authz_core_dir_conf *conf, authz_provider_list *providers);
114 #define BASE_REQ_STATE AUTHZ_REQSTATE_ALL
115 #define BASE_REQ_LEVEL 0
117 static void *create_authz_core_dir_config(apr_pool_t *p, char *dummy)
119 authz_core_dir_conf *conf =
120 (authz_core_dir_conf *)apr_pcalloc(p, sizeof(authz_core_dir_conf));
122 conf->req_state = BASE_REQ_STATE;
123 conf->req_state_level = BASE_REQ_LEVEL;
124 conf->merge_rules = 1;
128 static void *merge_authz_core_dir_config(apr_pool_t *a, void *basev, void *newv)
130 authz_core_dir_conf *base = (authz_core_dir_conf *)basev;
131 authz_core_dir_conf *new = (authz_core_dir_conf *)newv;
132 authz_core_dir_conf *conf;
134 /* Create this conf by duplicating the base, replacing elements
135 * (or creating copies for merging) where new-> values exist.
137 conf = (authz_core_dir_conf *)apr_pmemdup(a, base, sizeof(authz_core_dir_conf));
139 /* Wipe out the providers and rejects lists so that
140 they can be recreated by the merge process. */
141 conf->providers = NULL;
143 /* Only merge the base providers in if the merge_rules
144 directive has been set. */
145 if (base->providers && new->merge_rules) {
146 walk_merge_provider_list (a, conf, base->providers);
148 if (new->providers) {
149 walk_merge_provider_list (a, conf, new->providers);
155 static void *create_authz_core_svr_config(apr_pool_t *p, server_rec *s)
158 authz_core_srv_conf *authcfg;
160 authcfg = (authz_core_srv_conf *) apr_pcalloc(p, sizeof(authz_core_srv_conf));
161 authcfg->alias_rec = apr_hash_make(p);
163 return (void *) authcfg;
166 static void walk_merge_provider_list(apr_pool_t *a, authz_core_dir_conf *conf, authz_provider_list *providers)
168 authz_provider_list *newp = (authz_provider_list *)apr_palloc(a, sizeof(authz_provider_list));
169 memcpy(newp, providers, sizeof(authz_provider_list));
171 /* Since the merge is being done at a later time rather than
172 at configuration time, we need to fake the current
173 state of the list so that the new element get merged
174 into the correct location. The current state is
175 derived from the state of the object to be merged. */
176 conf->req_state = newp->req_state;
177 conf->req_state_level = newp->req_state_level;
178 newp->one_next = NULL;
179 newp->all_next = NULL;
181 /* Merge it into the existing provider logic. */
182 merge_authz_provider(conf, newp);
184 /* Walk all of the elements recursively to allow each existing
185 element to be copied and merged into the final configuration.*/
186 if (BASE_REQ_STATE == AUTHZ_REQSTATE_ONE) {
187 if (providers->one_next) {
188 walk_merge_provider_list (a, conf, providers->one_next);
190 if (providers->all_next) {
191 walk_merge_provider_list (a, conf, providers->all_next);
195 if (providers->all_next) {
196 walk_merge_provider_list (a, conf, providers->all_next);
198 if (providers->one_next) {
199 walk_merge_provider_list (a, conf, providers->one_next);
206 static const char *merge_authz_provider(authz_core_dir_conf *conf, authz_provider_list *newp)
208 /* Add it to the list now. */
209 if (!conf->providers) {
210 conf->providers = newp;
213 authz_provider_list *last = conf->providers;
214 int level = conf->req_state_level;
216 /* if the level is the base level then take care of the implicit
217 * operation at this level.
219 if (level == BASE_REQ_LEVEL) {
220 if (conf->req_state == AUTHZ_REQSTATE_ONE) {
221 /* Just run through the Require_one list and add the
224 while (last->one_next) {
225 last = last->one_next;
227 last->one_next = newp;
230 /* Just run through the Require_all list and add the
233 while (last->all_next) {
234 last = last->all_next;
236 last->all_next = newp;
240 /* if the last nodes level is greater than the new nodes
241 * level, then we need to insert the new node at this
242 * point. The req_state of the new node determine
243 * how it is inserted into the list.
245 else if (last->req_state_level > newp->req_state_level) {
246 if (newp->req_state == AUTHZ_REQSTATE_ONE)
247 newp->one_next = last;
249 newp->all_next = last;
250 conf->providers = newp;
253 /* Traverse the list to find the last entry.Each level
254 * indicates a transition in the logic.
256 for (;level;level--) {
257 /* if we are in a Require_all block then run through
258 * all of the Require_all nodes to the end of the list.
259 * Stop if we run into a node whose level is greater than
260 * the level of the node that is being inserted.
262 if (last->req_state == AUTHZ_REQSTATE_ALL) {
263 while ((last->all_next) && (last->all_next->req_state_level <= conf->req_state_level)) {
264 last = last->all_next;
266 /* If the end of the list contains a node state
267 * change then run through all of the Require_one
268 * nodes to the end of that list
270 if (level >= last->req_state_level) {
271 while (last->one_next) {
272 last = last->one_next;
277 /* if we are in a Require_one block then run through
278 * all of the Require_one nodes to the end of the list
280 if (last->req_state == AUTHZ_REQSTATE_ONE) {
281 while (last->one_next) {
282 last = last->one_next;
284 /* If the end of the list contains a node state
285 * change then run through all of the Require_all
286 * nodes to the end of that list
288 if (level >= last->req_state_level) {
289 while (last->all_next) {
290 last = last->all_next;
297 /* The current state flag indicates which way the transition should
298 * go. If ALL then take the all_next path, otherwise one_next
300 if (last->req_state == AUTHZ_REQSTATE_ALL) {
301 /* If we already have an all_next node, then
302 * we must have dropped back a level so assign
303 * the node to one_next
305 if (!last->all_next) {
306 last->all_next = newp;
308 /* If the level of the new node is greater than the
309 * last node, then insert the new node at this point.
310 * The req_state of the new node will determine
311 * how the node is added to the list.
313 else if (last->req_state_level <= newp->req_state_level) {
314 if (newp->req_state == AUTHZ_REQSTATE_ONE)
315 newp->one_next = last->all_next;
317 newp->all_next = last->all_next;
318 last->all_next = newp;
321 last->one_next = newp;
325 /* If we already have a one_next node, then
326 * we must have dropped back a level so assign
327 * the node to all_next
329 if (!last->one_next) {
330 last->one_next = newp;
332 /* If the level of the new node is greater than the
333 * last node, then insert the new node at this point.
334 * The req_state of the new node will determine
335 * how the node is added to the list.
337 else if (last->req_state_level <= newp->req_state_level) {
338 if (newp->req_state == AUTHZ_REQSTATE_ONE)
339 newp->one_next = last->one_next;
341 newp->all_next = last->one_next;
342 last->one_next = newp;
345 last->all_next = newp;
354 static const char *add_authz_provider(cmd_parms *cmd, void *config,
357 authz_core_dir_conf *conf = (authz_core_dir_conf*)config;
358 authz_provider_list *newp;
361 newp = apr_pcalloc(cmd->pool, sizeof(authz_provider_list));
364 w = ap_getword_white(cmd->pool, &t);
367 newp->provider_name = apr_pstrdup(cmd->pool, w);
369 newp->requirement = apr_pstrdup(cmd->pool, t);
370 newp->method_mask = cmd->limited;
372 /* lookup and cache the actual provider now */
373 newp->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
375 AUTHZ_PROVIDER_VERSION);
376 newp->req_state = conf->req_state;
377 newp->req_state_level = conf->req_state_level;
378 newp->is_reject = (cmd->info != NULL);
380 /* by the time the config file is used, the provider should be loaded
381 * and registered with us.
383 if (newp->provider == NULL) {
384 return apr_psprintf(cmd->pool,
385 "Unknown Authz provider: %s",
386 newp->provider_name);
389 /* if the provider doesn't provide the appropriate function, reject it */
390 if (!newp->provider->check_authorization) {
391 return apr_psprintf(cmd->pool,
392 "The '%s' Authz provider is not supported by any "
393 "of the loaded authorization modules ",
394 newp->provider_name);
397 /* Add the element to the list. */
398 return merge_authz_provider(conf, newp);
401 /* This is a fake authz provider that really merges various authz alias
402 * configurations and then envokes them.
404 static authz_status authz_alias_check_authorization(request_rec *r,
405 const char *require_args)
407 /* Look up the provider alias in the alias list.
408 * Get the the dir_config and call ap_Merge_per_dir_configs()
409 * Call the real provider->check_authorization() function
410 * return the result of the above function call
413 const char *provider_name = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
414 authz_status ret = AUTHZ_DENIED;
415 authz_core_srv_conf *authcfg =
416 (authz_core_srv_conf *)ap_get_module_config(r->server->module_config,
420 provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec,
422 APR_HASH_KEY_STRING);
423 ap_conf_vector_t *orig_dir_config = r->per_dir_config;
425 /* If we found the alias provider in the list, then merge the directory
426 configurations and call the real provider */
428 r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config,
429 prvdraliasrec->sec_auth);
430 ret = prvdraliasrec->provider->check_authorization(r,
431 prvdraliasrec->provider_args);
432 r->per_dir_config = orig_dir_config;
439 static const authz_provider authz_alias_provider =
441 &authz_alias_check_authorization,
444 static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig,
447 int old_overrides = cmd->override;
448 const char *endp = ap_strrchr_c(arg, '>');
450 char *provider_alias;
454 ap_conf_vector_t *new_authz_config = ap_create_per_dir_config(cmd->pool);
455 authz_core_srv_conf *authcfg =
456 (authz_core_srv_conf *)ap_get_module_config(cmd->server->module_config,
459 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
465 return apr_pstrcat(cmd->pool, cmd->cmd->name,
466 "> directive missing closing '>'", NULL);
469 args = apr_pstrndup(cmd->pool, arg, endp - arg);
472 return apr_pstrcat(cmd->pool, cmd->cmd->name,
473 "> directive requires additional arguments", NULL);
476 /* Pull the real provider name and the alias name from the block header */
477 provider_name = ap_getword_conf(cmd->pool, &args);
478 provider_alias = ap_getword_conf(cmd->pool, &args);
479 provider_args = ap_getword_conf(cmd->pool, &args);
481 if (!provider_name[0] || !provider_alias[0]) {
482 return apr_pstrcat(cmd->pool, cmd->cmd->name,
483 "> directive requires additional arguments", NULL);
486 /* walk the subsection configuration to get the per_dir config that we will
487 * merge just before the real provider is called.
489 cmd->override = OR_ALL|ACCESS_CONF;
490 errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_authz_config);
493 provider_alias_rec *prvdraliasrec = apr_pcalloc(cmd->pool,
494 sizeof(provider_alias_rec));
495 const authz_provider *provider =
496 ap_lookup_provider(AUTHZ_PROVIDER_GROUP, provider_name,
497 AUTHZ_PROVIDER_VERSION);
499 /* Save off the new directory config along with the original provider name
500 * and function pointer data
502 prvdraliasrec->sec_auth = new_authz_config;
503 prvdraliasrec->provider_name = provider_name;
504 prvdraliasrec->provider_alias = provider_alias;
505 prvdraliasrec->provider_args = provider_args;
506 prvdraliasrec->provider = provider;
508 apr_hash_set(authcfg->alias_rec, provider_alias,
509 APR_HASH_KEY_STRING, prvdraliasrec);
511 /* Register the fake provider so that we get called first */
512 ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP,
513 provider_alias, AUTHZ_PROVIDER_VERSION,
514 &authz_alias_provider,
515 AP_AUTH_INTERNAL_PER_CONF);
518 cmd->override = old_overrides;
523 static const char *authz_require_section(cmd_parms *cmd, void *mconfig, const char *arg)
525 int old_overrides = cmd->override;
526 const char *endp = ap_strrchr_c(arg, '>');
529 authz_request_state old_reqstate;
530 authz_core_dir_conf *conf = (authz_core_dir_conf*)mconfig;
533 return apr_pstrcat(cmd->pool, cmd->cmd->name,
534 "> directive missing closing '>'", NULL);
537 args = apr_pstrndup(cmd->pool, arg, endp - arg);
540 return apr_pstrcat(cmd->pool, cmd->cmd->name,
541 "> directive doesn't take additional arguments", NULL);
544 /* Save off the current request state so that we can go back to it after walking
545 * the subsection. Indicate a transition in the logic incrementing the level.
546 * After the subsection walk the level will be decremented to indicate the
547 * path to follow. As the require directives are read by the configuration
548 * the req_state and the level will allow it to traverse the list to find
549 * the last element in the provider calling list.
551 old_reqstate = conf->req_state;
552 if (strcasecmp (cmd->directive->directive, "<SatisfyAll") == 0) {
553 conf->req_state = AUTHZ_REQSTATE_ALL;
556 conf->req_state = AUTHZ_REQSTATE_ONE;
558 conf->req_state_level++;
559 cmd->override = OR_ALL|ACCESS_CONF;
561 /* Walk the subsection configuration to get the per_dir config that we will
562 * merge just before the real provider is called.
564 errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
566 conf->req_state_level--;
567 conf->req_state = old_reqstate;
568 cmd->override = old_overrides;
573 static const command_rec authz_cmds[] =
575 AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG,
576 "Selects which authenticated users or groups may access "
577 "a protected space"),
578 AP_INIT_RAW_ARGS("Reject", add_authz_provider, (void*)1, OR_AUTHCFG,
579 "Rejects the specified authenticated users groups or "
580 "host based requests from accessing a protected space"),
581 AP_INIT_RAW_ARGS("<RequireAlias", authz_require_alias_section, NULL, RSRC_CONF,
582 "Container for authorization directives grouped under "
583 "an authz provider alias"),
584 AP_INIT_RAW_ARGS("<SatisfyAll", authz_require_section, NULL, OR_AUTHCFG,
585 "Container for grouping require statements that must all "
586 "succeed for authorization to be granted"),
587 AP_INIT_RAW_ARGS("<SatisfyOne", authz_require_section, NULL, OR_AUTHCFG,
588 "Container for grouping require statements of which one "
589 "must succeed for authorization to be granted"),
590 AP_INIT_FLAG("AuthzMergeRules", ap_set_flag_slot,
591 (void *)APR_OFFSETOF(authz_core_dir_conf, merge_rules), OR_AUTHCFG,
592 "Set to 'on' to allow the parent's <Directory> or <Location> authz rules "
593 "to be merged into the current <Directory> or <Location>. Set to 'off' "
594 "to disable merging. If set to 'off', only the authz rules defined in "
595 "the current <Directory> or <Location> block will apply. The default is 'on'."),
599 #define RESOLVE_NEUTRAL(orig,new) (new == AUTHZ_NEUTRAL) ? orig : new;
601 static authz_status check_provider_list (request_rec *r, authz_provider_list *current_provider, int prev_level)
603 authz_status auth_result = AUTHZ_DENIED;
605 const authz_provider *provider;
607 provider = current_provider->provider;
608 apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE,
609 current_provider->provider_name);
611 /* check to make sure that the request method requires
612 * authorization before calling the provider
614 if (!(current_provider->method_mask &
615 (AP_METHOD_BIT << r->method_number))) {
619 auth_result = provider->check_authorization(r,
620 current_provider->requirement);
622 if (auth_result == AUTHZ_GENERAL_ERROR) {
626 if (current_provider->is_reject) {
627 /* If the provider was called through a reject directive, then
628 alter the result accordingly. If the original result was
629 Denied then the new result is Neutral since we can not grant
630 access simply because authorization was not rejected. */
631 auth_result = auth_result == AUTHZ_DENIED ? AUTHZ_NEUTRAL : AUTHZ_DENIED;
634 apr_table_unset(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
636 /* If the current node is a Require_One type */
637 if (current_provider->req_state == AUTHZ_REQSTATE_ONE) {
638 /* If the auth_result of *this* node was GRANTED and we are
639 * embedded in a Require_all block then look to see if there
640 * is another Require_all node that needs to be satisfied
642 if ((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL)) {
643 if ((current_provider->all_next) &&
644 (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
645 authz_status temp_result = check_provider_list (r, current_provider->all_next,
646 current_provider->req_state_level);
647 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
653 /* Traverse forward to the next Require_one node it one exists
654 * otherwise just return the auth_result
656 if (current_provider->one_next) {
657 authz_status temp_result = check_provider_list (r, current_provider->one_next,
658 current_provider->req_state_level);
659 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
664 /* If the *last* auth_result was GRANTED and we are embedded in
665 * a Require_all block then look to see if there is another
666 * Require_all node that needs to be satisfied
668 if (((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL))
669 && (current_provider->all_next)
670 && (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
671 authz_status temp_result = check_provider_list (r, current_provider->all_next,
672 current_provider->req_state_level);
673 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
675 /* If the *last* auth_result was DENIED and we are inside of a
676 * Require_one block then look to see if there is another
677 * Require_one node that can be satisfied
679 else if ((auth_result == AUTHZ_DENIED)
680 && (current_provider->one_next)
681 && (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
688 /* If the current node is a Require_All type */
689 if (current_provider->req_state == AUTHZ_REQSTATE_ALL) {
690 /* if the auth_result of *this* node was DENIED and we are
691 * embedded in a Require_one block then look to see if there
692 * is another Require_one node that can be satisfied
694 if (auth_result == AUTHZ_DENIED) {
695 if ((current_provider->one_next) &&
696 (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
697 authz_status temp_result = check_provider_list (r, current_provider->one_next,
698 current_provider->req_state_level);
699 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
705 /* Traverse forward to the next Require_all node it one exists
706 * otherwise just return the auth_result
708 if (current_provider->all_next) {
709 authz_status temp_result = check_provider_list (r, current_provider->all_next,
710 current_provider->req_state_level);
711 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
716 /* if the *last* auth_result was DENIED and we are embedded
717 * in a Require_one block then look to see if there is another
718 * Require_one node that can be satisfied
720 if ((auth_result == AUTHZ_DENIED)
721 && (current_provider->one_next)
722 && (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
723 authz_status temp_result = check_provider_list (r, current_provider->one_next,
724 current_provider->req_state_level);
725 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
727 /* If the *last* auth_result was GRANTED and we are inside of a
728 * Require_all block then look to see if there is another
729 * Require_all node that needs to be satisfied
731 else if (((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL))
732 && (current_provider->all_next)
733 && (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
741 static int authorize_user(request_rec *r)
743 authz_core_dir_conf *conf = ap_get_module_config(r->per_dir_config,
745 authz_status auth_result;
746 authz_provider_list *current_provider;
747 const char *note = apr_table_get(r->notes, AUTHZ_ACCESS_PASSED_NOTE);
749 /* If we're not really configured for providers, stop now. */
750 if (!conf->providers) {
751 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
752 "no authorization providers configured");
756 /* run through the require logic. */
757 current_provider = conf->providers;
758 auth_result = check_provider_list (r, current_provider, 0);
760 if (auth_result != AUTHZ_GRANTED) {
763 switch (auth_result) {
766 /* XXX If the deprecated Satisfy directive is set to anything
767 but ANY a failure in access control or authz will cause
768 an HTTP_UNAUTHORIZED. Just the if statement
769 should be removed in 3.0 when the Satisfy directive
771 if (!note || (ap_satisfies(r) != SATISFY_ANY) || (note[0] == 'N')) {
772 if (r->ap_auth_type == NULL) {
773 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
774 "client denied by server configuration: %s%s",
775 r->filename ? "" : "uri ",
776 r->filename ? r->filename : r->uri);
777 return_code = HTTP_FORBIDDEN;
780 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
781 "user %s: authorization failure for \"%s\": ",
783 return_code = HTTP_UNAUTHORIZED;
787 return_code = DECLINED;
790 case AUTHZ_GENERAL_ERROR:
792 /* We'll assume that the module has already said what its
793 * error was in the logs.
795 return_code = HTTP_INTERNAL_SERVER_ERROR;
799 /* If we're returning 403, tell them to try again. */
800 if (return_code == HTTP_UNAUTHORIZED) {
801 ap_note_auth_failure (r);
809 static int authz_some_auth_required(request_rec *r)
811 authz_core_dir_conf *conf = ap_get_module_config(r->per_dir_config,
813 authz_provider_list *current_provider;
816 current_provider = conf->providers;
818 while (current_provider) {
820 /* Does this provider config apply for this method */
821 if (current_provider->method_mask &
822 (AP_METHOD_BIT << r->method_number)) {
827 current_provider = current_provider->one_next;
833 static void register_hooks(apr_pool_t *p)
835 APR_REGISTER_OPTIONAL_FN(authz_some_auth_required);
837 ap_hook_check_authz(authorize_user, NULL, NULL, APR_HOOK_MIDDLE,
838 AP_AUTH_INTERNAL_PER_CONF);
841 module AP_MODULE_DECLARE_DATA authz_core_module =
843 STANDARD20_MODULE_STUFF,
844 create_authz_core_dir_config, /* dir config creater */
845 merge_authz_core_dir_config, /* dir merger */
846 create_authz_core_svr_config, /* server config */
847 NULL, /* merge server config */
849 register_hooks /* register hooks */