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 = apr_pcalloc(p, sizeof(*conf));
121 conf->req_state = BASE_REQ_STATE;
122 conf->req_state_level = BASE_REQ_LEVEL;
123 conf->merge_rules = 1;
127 static void *merge_authz_core_dir_config(apr_pool_t *p,
128 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(p, 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 (p, conf, base->providers);
148 if (new->providers) {
149 walk_merge_provider_list (p, 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 = apr_pcalloc(p, sizeof(*authcfg));
161 authcfg->alias_rec = apr_hash_make(p);
163 return (void *)authcfg;
166 /* This is a fake authz provider that really merges various authz alias
167 * configurations and then invokes them.
169 static authz_status authz_alias_check_authorization(request_rec *r,
170 const char *require_args)
172 const char *provider_name;
173 authz_status ret = AUTHZ_DENIED;
175 /* Look up the provider alias in the alias list.
176 * Get the the dir_config and call ap_Merge_per_dir_configs()
177 * Call the real provider->check_authorization() function
178 * return the result of the above function call
181 provider_name = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
184 authz_core_srv_conf *authcfg;
185 provider_alias_rec *prvdraliasrec;
187 authcfg = ap_get_module_config(r->server->module_config,
190 prvdraliasrec = apr_hash_get(authcfg->alias_rec, provider_name,
191 APR_HASH_KEY_STRING);
193 /* If we found the alias provider in the list, then merge the directory
194 configurations and call the real provider */
196 ap_conf_vector_t *orig_dir_config = r->per_dir_config;
199 ap_merge_per_dir_configs(r->pool, orig_dir_config,
200 prvdraliasrec->sec_auth);
202 ret = prvdraliasrec->provider->
203 check_authorization(r, prvdraliasrec->provider_args);
205 r->per_dir_config = orig_dir_config;
212 static const authz_provider authz_alias_provider =
214 &authz_alias_check_authorization
217 static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig,
220 const char *endp = ap_strrchr_c(args, '>');
222 char *provider_alias;
224 ap_conf_vector_t *new_authz_config;
225 int old_overrides = cmd->override;
228 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
234 return apr_pstrcat(cmd->pool, cmd->cmd->name,
235 "> directive missing closing '>'", NULL);
238 args = apr_pstrndup(cmd->pool, args, endp - args);
241 return apr_pstrcat(cmd->pool, cmd->cmd->name,
242 "> directive requires additional arguments", NULL);
245 /* Pull the real provider name and the alias name from the block header */
246 provider_name = ap_getword_conf(cmd->pool, &args);
247 provider_alias = ap_getword_conf(cmd->pool, &args);
248 provider_args = ap_getword_conf(cmd->pool, &args);
250 if (!provider_name[0] || !provider_alias[0]) {
251 return apr_pstrcat(cmd->pool, cmd->cmd->name,
252 "> directive requires additional arguments", NULL);
255 new_authz_config = ap_create_per_dir_config(cmd->pool);
257 /* Walk the subsection configuration to get the per_dir config that we will
258 * merge just before the real provider is called.
260 cmd->override = OR_ALL|ACCESS_CONF;
261 errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_authz_config);
262 cmd->override = old_overrides;
265 provider_alias_rec *prvdraliasrec;
266 authz_core_srv_conf *authcfg;
268 prvdraliasrec = apr_pcalloc(cmd->pool, sizeof(*prvdraliasrec));
270 /* Save off the new directory config along with the original
271 * provider name and function pointer data
273 prvdraliasrec->provider_name = provider_name;
274 prvdraliasrec->provider_alias = provider_alias;
275 prvdraliasrec->provider_args = provider_args;
276 prvdraliasrec->sec_auth = new_authz_config;
277 prvdraliasrec->provider =
278 ap_lookup_provider(AUTHZ_PROVIDER_GROUP, provider_name,
279 AUTHZ_PROVIDER_VERSION);
281 /* by the time the config file is used, the provider should be loaded
282 * and registered with us.
284 if (!prvdraliasrec->provider) {
285 return apr_psprintf(cmd->pool,
286 "Unknown Authz provider: %s",
290 authcfg = ap_get_module_config(cmd->server->module_config,
293 apr_hash_set(authcfg->alias_rec, provider_alias,
294 APR_HASH_KEY_STRING, prvdraliasrec);
296 /* Register the fake provider so that we get called first */
297 ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP,
298 provider_alias, AUTHZ_PROVIDER_VERSION,
299 &authz_alias_provider,
300 AP_AUTH_INTERNAL_PER_CONF);
306 static void walk_merge_provider_list(apr_pool_t *a, authz_core_dir_conf *conf, authz_provider_list *providers)
308 authz_provider_list *newp = (authz_provider_list *)apr_palloc(a, sizeof(authz_provider_list));
309 memcpy(newp, providers, sizeof(authz_provider_list));
311 /* Since the merge is being done at a later time rather than
312 at configuration time, we need to fake the current
313 state of the list so that the new element get merged
314 into the correct location. The current state is
315 derived from the state of the object to be merged. */
316 conf->req_state = newp->req_state;
317 conf->req_state_level = newp->req_state_level;
318 newp->one_next = NULL;
319 newp->all_next = NULL;
321 /* Merge it into the existing provider logic. */
322 merge_authz_provider(conf, newp);
324 /* Walk all of the elements recursively to allow each existing
325 element to be copied and merged into the final configuration.*/
326 if (BASE_REQ_STATE == AUTHZ_REQSTATE_ONE) {
327 if (providers->one_next) {
328 walk_merge_provider_list (a, conf, providers->one_next);
330 if (providers->all_next) {
331 walk_merge_provider_list (a, conf, providers->all_next);
335 if (providers->all_next) {
336 walk_merge_provider_list (a, conf, providers->all_next);
338 if (providers->one_next) {
339 walk_merge_provider_list (a, conf, providers->one_next);
346 static const char *merge_authz_provider(authz_core_dir_conf *conf, authz_provider_list *newp)
348 /* Add it to the list now. */
349 if (!conf->providers) {
350 conf->providers = newp;
353 authz_provider_list *last = conf->providers;
354 int level = conf->req_state_level;
356 /* if the level is the base level then take care of the implicit
357 * operation at this level.
359 if (level == BASE_REQ_LEVEL) {
360 if (conf->req_state == AUTHZ_REQSTATE_ONE) {
361 /* Just run through the Require_one list and add the
364 while (last->one_next) {
365 last = last->one_next;
367 last->one_next = newp;
370 /* Just run through the Require_all list and add the
373 while (last->all_next) {
374 last = last->all_next;
376 last->all_next = newp;
380 /* if the last nodes level is greater than the new nodes
381 * level, then we need to insert the new node at this
382 * point. The req_state of the new node determine
383 * how it is inserted into the list.
385 else if (last->req_state_level > newp->req_state_level) {
386 if (newp->req_state == AUTHZ_REQSTATE_ONE)
387 newp->one_next = last;
389 newp->all_next = last;
390 conf->providers = newp;
393 /* Traverse the list to find the last entry.Each level
394 * indicates a transition in the logic.
396 for (;level;level--) {
397 /* if we are in a Require_all block then run through
398 * all of the Require_all nodes to the end of the list.
399 * Stop if we run into a node whose level is greater than
400 * the level of the node that is being inserted.
402 if (last->req_state == AUTHZ_REQSTATE_ALL) {
403 while ((last->all_next) && (last->all_next->req_state_level <= conf->req_state_level)) {
404 last = last->all_next;
406 /* If the end of the list contains a node state
407 * change then run through all of the Require_one
408 * nodes to the end of that list
410 if (level >= last->req_state_level) {
411 while (last->one_next) {
412 last = last->one_next;
417 /* if we are in a Require_one block then run through
418 * all of the Require_one nodes to the end of the list
420 if (last->req_state == AUTHZ_REQSTATE_ONE) {
421 while (last->one_next) {
422 last = last->one_next;
424 /* If the end of the list contains a node state
425 * change then run through all of the Require_all
426 * nodes to the end of that list
428 if (level >= last->req_state_level) {
429 while (last->all_next) {
430 last = last->all_next;
437 /* The current state flag indicates which way the transition should
438 * go. If ALL then take the all_next path, otherwise one_next
440 if (last->req_state == AUTHZ_REQSTATE_ALL) {
441 /* If we already have an all_next node, then
442 * we must have dropped back a level so assign
443 * the node to one_next
445 if (!last->all_next) {
446 last->all_next = newp;
448 /* If the level of the new node is greater than the
449 * last node, then insert the new node at this point.
450 * The req_state of the new node will determine
451 * how the node is added to the list.
453 else if (last->req_state_level <= newp->req_state_level) {
454 if (newp->req_state == AUTHZ_REQSTATE_ONE)
455 newp->one_next = last->all_next;
457 newp->all_next = last->all_next;
458 last->all_next = newp;
461 last->one_next = newp;
465 /* If we already have a one_next node, then
466 * we must have dropped back a level so assign
467 * the node to all_next
469 if (!last->one_next) {
470 last->one_next = newp;
472 /* If the level of the new node is greater than the
473 * last node, then insert the new node at this point.
474 * The req_state of the new node will determine
475 * how the node is added to the list.
477 else if (last->req_state_level <= newp->req_state_level) {
478 if (newp->req_state == AUTHZ_REQSTATE_ONE)
479 newp->one_next = last->one_next;
481 newp->all_next = last->one_next;
482 last->one_next = newp;
485 last->all_next = newp;
494 static const char *add_authz_provider(cmd_parms *cmd, void *config,
497 authz_core_dir_conf *conf = (authz_core_dir_conf*)config;
498 authz_provider_list *newp;
501 newp = apr_pcalloc(cmd->pool, sizeof(authz_provider_list));
504 w = ap_getword_white(cmd->pool, &t);
507 newp->provider_name = apr_pstrdup(cmd->pool, w);
509 newp->requirement = apr_pstrdup(cmd->pool, t);
510 newp->method_mask = cmd->limited;
512 /* lookup and cache the actual provider now */
513 newp->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
515 AUTHZ_PROVIDER_VERSION);
516 newp->req_state = conf->req_state;
517 newp->req_state_level = conf->req_state_level;
518 newp->is_reject = (cmd->info != NULL);
520 /* by the time the config file is used, the provider should be loaded
521 * and registered with us.
523 if (newp->provider == NULL) {
524 return apr_psprintf(cmd->pool,
525 "Unknown Authz provider: %s",
526 newp->provider_name);
529 /* if the provider doesn't provide the appropriate function, reject it */
530 if (!newp->provider->check_authorization) {
531 return apr_psprintf(cmd->pool,
532 "The '%s' Authz provider is not supported by any "
533 "of the loaded authorization modules ",
534 newp->provider_name);
537 /* Add the element to the list. */
538 return merge_authz_provider(conf, newp);
541 static const char *add_authz_section(cmd_parms *cmd, void *mconfig,
544 authz_core_dir_conf *conf = mconfig;
545 const char *endp = ap_strrchr_c(args, '>');
546 authz_request_state old_reqstate;
547 int old_overrides = cmd->override;
551 return apr_pstrcat(cmd->pool, cmd->cmd->name,
552 "> directive missing closing '>'", NULL);
555 args = apr_pstrndup(cmd->pool, args, endp - args);
558 return apr_pstrcat(cmd->pool, cmd->cmd->name,
559 "> directive doesn't take additional arguments", NULL);
562 /* Save off the current request state so that we can go back to it after walking
563 * the subsection. Indicate a transition in the logic incrementing the level.
564 * After the subsection walk the level will be decremented to indicate the
565 * path to follow. As the require directives are read by the configuration
566 * the req_state and the level will allow it to traverse the list to find
567 * the last element in the provider calling list.
569 old_reqstate = conf->req_state;
570 if (strcasecmp (cmd->directive->directive, "<SatisfyAll") == 0) {
571 conf->req_state = AUTHZ_REQSTATE_ALL;
574 conf->req_state = AUTHZ_REQSTATE_ONE;
576 conf->req_state_level++;
577 cmd->override = OR_ALL|ACCESS_CONF;
579 /* Walk the subsection configuration to get the per_dir config that we will
580 * merge just before the real provider is called.
582 errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
584 conf->req_state_level--;
585 conf->req_state = old_reqstate;
586 cmd->override = old_overrides;
591 static const command_rec authz_cmds[] =
593 AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG,
594 "Selects which authenticated users or groups may access "
595 "a protected space"),
596 AP_INIT_RAW_ARGS("Reject", add_authz_provider, (void*)1, OR_AUTHCFG,
597 "Rejects the specified authenticated users groups or "
598 "host based requests from accessing a protected space"),
599 AP_INIT_RAW_ARGS("<RequireAlias", authz_require_alias_section, NULL, RSRC_CONF,
600 "Container for authorization directives grouped under "
601 "an authz provider alias"),
602 AP_INIT_RAW_ARGS("<SatisfyAll", add_authz_section, NULL, OR_AUTHCFG,
603 "Container for grouping require statements that must all "
604 "succeed for authorization to be granted"),
605 AP_INIT_RAW_ARGS("<SatisfyOne", add_authz_section, NULL, OR_AUTHCFG,
606 "Container for grouping require statements of which one "
607 "must succeed for authorization to be granted"),
608 AP_INIT_FLAG("AuthzMergeRules", ap_set_flag_slot,
609 (void *)APR_OFFSETOF(authz_core_dir_conf, merge_rules), OR_AUTHCFG,
610 "Set to 'on' to allow the parent's <Directory> or <Location> authz rules "
611 "to be merged into the current <Directory> or <Location>. Set to 'off' "
612 "to disable merging. If set to 'off', only the authz rules defined in "
613 "the current <Directory> or <Location> block will apply. The default is 'on'."),
617 #define RESOLVE_NEUTRAL(orig,new) (new == AUTHZ_NEUTRAL) ? orig : new;
619 static authz_status check_provider_list (request_rec *r, authz_provider_list *current_provider, int prev_level)
621 authz_status auth_result = AUTHZ_DENIED;
623 const authz_provider *provider;
625 provider = current_provider->provider;
626 apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE,
627 current_provider->provider_name);
629 /* check to make sure that the request method requires
630 * authorization before calling the provider
632 if (!(current_provider->method_mask &
633 (AP_METHOD_BIT << r->method_number))) {
637 auth_result = provider->check_authorization(r,
638 current_provider->requirement);
640 if (auth_result == AUTHZ_GENERAL_ERROR) {
644 if (current_provider->is_reject) {
645 /* If the provider was called through a reject directive, then
646 alter the result accordingly. If the original result was
647 Denied then the new result is Neutral since we can not grant
648 access simply because authorization was not rejected. */
649 auth_result = auth_result == AUTHZ_DENIED ? AUTHZ_NEUTRAL : AUTHZ_DENIED;
652 apr_table_unset(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
654 /* If the current node is a Require_One type */
655 if (current_provider->req_state == AUTHZ_REQSTATE_ONE) {
656 /* If the auth_result of *this* node was GRANTED and we are
657 * embedded in a Require_all block then look to see if there
658 * is another Require_all node that needs to be satisfied
660 if ((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL)) {
661 if ((current_provider->all_next) &&
662 (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
663 authz_status temp_result = check_provider_list (r, current_provider->all_next,
664 current_provider->req_state_level);
665 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
671 /* Traverse forward to the next Require_one node it one exists
672 * otherwise just return the auth_result
674 if (current_provider->one_next) {
675 authz_status temp_result = check_provider_list (r, current_provider->one_next,
676 current_provider->req_state_level);
677 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
682 /* If the *last* auth_result was GRANTED and we are embedded in
683 * a Require_all block then look to see if there is another
684 * Require_all node that needs to be satisfied
686 if (((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL))
687 && (current_provider->all_next)
688 && (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
689 authz_status temp_result = check_provider_list (r, current_provider->all_next,
690 current_provider->req_state_level);
691 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
693 /* If the *last* auth_result was DENIED and we are inside of a
694 * Require_one block then look to see if there is another
695 * Require_one node that can be satisfied
697 else if ((auth_result == AUTHZ_DENIED)
698 && (current_provider->one_next)
699 && (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
706 /* If the current node is a Require_All type */
707 if (current_provider->req_state == AUTHZ_REQSTATE_ALL) {
708 /* if the auth_result of *this* node was DENIED and we are
709 * embedded in a Require_one block then look to see if there
710 * is another Require_one node that can be satisfied
712 if (auth_result == AUTHZ_DENIED) {
713 if ((current_provider->one_next) &&
714 (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
715 authz_status temp_result = check_provider_list (r, current_provider->one_next,
716 current_provider->req_state_level);
717 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
723 /* Traverse forward to the next Require_all node it one exists
724 * otherwise just return the auth_result
726 if (current_provider->all_next) {
727 authz_status temp_result = check_provider_list (r, current_provider->all_next,
728 current_provider->req_state_level);
729 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
734 /* if the *last* auth_result was DENIED and we are embedded
735 * in a Require_one block then look to see if there is another
736 * Require_one node that can be satisfied
738 if ((auth_result == AUTHZ_DENIED)
739 && (current_provider->one_next)
740 && (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
741 authz_status temp_result = check_provider_list (r, current_provider->one_next,
742 current_provider->req_state_level);
743 auth_result = RESOLVE_NEUTRAL(auth_result, temp_result);
745 /* If the *last* auth_result was GRANTED and we are inside of a
746 * Require_all block then look to see if there is another
747 * Require_all node that needs to be satisfied
749 else if (((auth_result == AUTHZ_GRANTED) || (auth_result == AUTHZ_NEUTRAL))
750 && (current_provider->all_next)
751 && (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
759 static int authorize_user(request_rec *r)
761 authz_core_dir_conf *conf;
762 authz_status auth_result;
763 authz_provider_list *current_provider;
764 const char *note = apr_table_get(r->notes, AUTHZ_ACCESS_PASSED_NOTE);
766 conf = ap_get_module_config(r->per_dir_config, &authz_core_module);
768 /* If we're not really configured for providers, stop now. */
769 if (!conf->providers) {
770 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
771 "no authorization providers configured");
775 /* run through the require logic. */
776 current_provider = conf->providers;
777 auth_result = check_provider_list (r, current_provider, 0);
779 if (auth_result != AUTHZ_GRANTED) {
782 switch (auth_result) {
785 /* XXX If the deprecated Satisfy directive is set to anything
786 but ANY a failure in access control or authz will cause
787 an HTTP_UNAUTHORIZED. Just the if statement
788 should be removed in 3.0 when the Satisfy directive
790 if (!note || (ap_satisfies(r) != SATISFY_ANY) || (note[0] == 'N')) {
791 if (r->ap_auth_type == NULL) {
792 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
793 "client denied by server configuration: %s%s",
794 r->filename ? "" : "uri ",
795 r->filename ? r->filename : r->uri);
796 return_code = HTTP_FORBIDDEN;
799 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
800 "user %s: authorization failure for \"%s\": ",
802 return_code = HTTP_UNAUTHORIZED;
806 return_code = DECLINED;
809 case AUTHZ_GENERAL_ERROR:
811 /* We'll assume that the module has already said what its
812 * error was in the logs.
814 return_code = HTTP_INTERNAL_SERVER_ERROR;
818 /* If we're returning 403, tell them to try again. */
819 if (return_code == HTTP_UNAUTHORIZED) {
820 ap_note_auth_failure (r);
828 static int authz_some_auth_required(request_rec *r)
830 authz_core_dir_conf *conf;
831 authz_provider_list *current_provider;
833 conf = ap_get_module_config(r->per_dir_config, &authz_core_module);
835 current_provider = conf->providers;
837 while (current_provider) {
839 /* Does this provider config apply for this method */
840 if (current_provider->method_mask &
841 (AP_METHOD_BIT << r->method_number)) {
845 current_provider = current_provider->one_next;
851 static void register_hooks(apr_pool_t *p)
853 APR_REGISTER_OPTIONAL_FN(authz_some_auth_required);
855 ap_hook_check_authz(authorize_user, NULL, NULL, APR_HOOK_MIDDLE,
856 AP_AUTH_INTERNAL_PER_CONF);
859 module AP_MODULE_DECLARE_DATA authz_core_module =
861 STANDARD20_MODULE_STUFF,
862 create_authz_core_dir_config, /* dir config creater */
863 merge_authz_core_dir_config, /* dir merger */
864 create_authz_core_svr_config, /* server config */
865 NULL, /* merge server config */
867 register_hooks /* register hooks */