/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* * Security options etc. * * Module derived from code originally written by Rob McCool *
*/
struct authz_section_conf { constchar *provider_name; constchar *provider_args; constvoid *provider_parsed_args; const authz_provider *provider;
apr_int64_t limited;
authz_logic_op op; int negate; /** true if this is not a real container but produced by AuthMerging;
* only used for logging */ int is_merged;
authz_section_conf *first;
authz_section_conf *next;
};
/* Only per-server directive we have is GLOBAL_ONLY */ staticvoid *merge_authz_core_svr_config(apr_pool_t *p, void *basev, void *newv)
{ return basev;
}
/* This is a fake authz provider that really merges various authz alias * configurations and then invokes them.
*/ static authz_status authz_alias_check_authorization(request_rec *r, constchar *require_args, constvoid *parsed_require_args)
{ constchar *provider_name;
/* Look up the provider alias in the alias list. * Get the dir_config and call ap_merge_per_dir_configs() * Call the real provider->check_authorization() function * Return the result of the above function call
*/
/* If we found the alias provider in the list, then merge the directory
configurations and call the real provider */ if (prvdraliasrec) {
ap_conf_vector_t *orig_dir_config = r->per_dir_config;
authz_status ret;
/* Pull the real provider name and the alias name from the block header */
provider_name = ap_getword_conf(cmd->pool, &args);
provider_alias = ap_getword_conf(cmd->pool, &args);
provider_args = ap_getword_conf(cmd->pool, &args);
extra_args = ap_getword_conf(cmd->pool, &args);
/* We only handle one "Require-Parameters" parameter. If several parameters
are needed, they must be enclosed between quotes */ if (extra_args && *extra_args) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(10142) "When several arguments (%s %s...) are passed to a %s directive, " "they must be enclosed in quotation marks. Otherwise, only the " "first one is taken into account",
provider_args, extra_args, cmd->cmd->name);
}
/* Walk the subsection configuration to get the per_dir config that we will * merge just before the real provider is called.
*/
cmd->override = OR_AUTHCFG | ACCESS_CONF;
errmsg = ap_walk_config(cmd->directive->first_child, cmd,
new_authz_config);
cmd->override = old_overrides;
if (!errmsg) {
provider_alias_rec *prvdraliasrec;
authz_core_srv_conf *authcfg;
/* Save off the new directory config along with the original * provider name and function pointer data
*/
prvdraliasrec->provider_name = provider_name;
prvdraliasrec->provider_alias = provider_alias;
prvdraliasrec->provider_args = provider_args;
prvdraliasrec->sec_auth = new_authz_config;
prvdraliasrec->provider =
ap_lookup_provider(AUTHZ_PROVIDER_GROUP, provider_name,
AUTHZ_PROVIDER_VERSION);
/* by the time the config file is used, the provider should be loaded * and registered with us.
*/ if (!prvdraliasrec->provider) { return apr_psprintf(cmd->pool, "Unknown Authz provider: %s",
provider_name);
} if (prvdraliasrec->provider->parse_require_line) {
err = prvdraliasrec->provider->parse_require_line(cmd,
provider_args, &prvdraliasrec->provider_parsed_args); if (err) return apr_psprintf(cmd->pool, "Can't parse 'Require %s %s': %s",
provider_name, provider_args, err);
}
/* Register the fake provider so that we get called first */
ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP,
provider_alias, AUTHZ_PROVIDER_VERSION,
&authz_alias_provider,
AP_AUTH_INTERNAL_PER_CONF);
}
/* lookup and cache the actual provider now */
section->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
section->provider_name,
AUTHZ_PROVIDER_VERSION);
/* by the time the config file is used, the provider should be loaded * and registered with us.
*/ if (!section->provider) { return apr_psprintf(cmd->pool, "Unknown Authz provider: %s",
section->provider_name);
}
/* if the provider doesn't provide the appropriate function, reject it */ if (!section->provider->check_authorization) { return apr_psprintf(cmd->pool, "The '%s' Authz provider is not supported by any " "of the loaded authorization modules",
section->provider_name);
}
while (conf) { if (conf->section) { if (authz_core_check_section(p, s, conf->section, 1) != OK) { return !OK;
}
}
conf = conf->next;
}
return OK;
}
staticconst command_rec authz_cmds[] =
{
AP_INIT_RAW_ARGS(", authz_require_alias_section,
NULL, RSRC_CONF, "container for grouping an authorization provider's " "directives under a provider alias"),
AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG, "specifies authorization directives " "which one must pass (or not) for a request to suceeed"),
AP_INIT_RAW_ARGS(", add_authz_section, NULL, OR_AUTHCFG, "container for grouping authorization directives " "of which none must fail and at least one must pass " "for a request to succeed"),
AP_INIT_RAW_ARGS(", add_authz_section, NULL, OR_AUTHCFG, "container for grouping authorization directives " "of which one must pass " "for a request to succeed"), #ifdef AUTHZ_EXTRA_CONFIGS
AP_INIT_RAW_ARGS(", add_authz_section, NULL, OR_AUTHCFG, "container for grouping authorization directives " "of which some must fail or none must pass " "for a request to succeed"), #endif
AP_INIT_RAW_ARGS(", add_authz_section, NULL, OR_AUTHCFG, "container for grouping authorization directives " "of which none must pass " "for a request to succeed"),
AP_INIT_TAKE1("AuthMerging", authz_merge_sections, NULL, OR_AUTHCFG, "controls how a , , or similar " "directive's authorization directives are combined with " "those of its predecessor"),
AP_INIT_FLAG("AuthzSendForbiddenOnFailure", ap_set_flag_slot_char,
(void *)APR_OFFSETOF(authz_core_dir_conf, authz_forbidden_on_fail),
OR_AUTHCFG, "Controls if an authorization failure should result in a " "'403 FORBIDDEN' response instead of the HTTP-conforming " "'401 UNAUTHORIZED'"),
{NULL}
};
/* check to make sure that the request method requires authorization */ if (!(section->limited & (AP_METHOD_BIT << r->method_number))) {
auth_result =
(parent_op == AUTHZ_LOGIC_AND) ? AUTHZ_GRANTED : AUTHZ_NEUTRAL;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01625) "authorization result of %s: %s " "(directive limited to other methods)",
format_authz_command(r->pool, section),
format_authz_result(auth_result));
return auth_result;
}
if (section->provider) {
apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE,
section->provider_name);
if (child_result == AUTHZ_GENERAL_ERROR) { return AUTHZ_GENERAL_ERROR;
}
if (child_result != AUTHZ_NEUTRAL) { /* * Handling of AUTHZ_DENIED/AUTHZ_DENIED_NO_USER: Return * AUTHZ_DENIED_NO_USER if providing a user may change the * result, AUTHZ_DENIED otherwise.
*/ if (section->op == AUTHZ_LOGIC_AND) { if (child_result == AUTHZ_DENIED) {
auth_result = child_result; break;
} if ((child_result == AUTHZ_DENIED_NO_USER
&& auth_result != AUTHZ_DENIED)
|| (auth_result == AUTHZ_NEUTRAL)) {
auth_result = child_result;
}
} else { /* AUTHZ_LOGIC_OR */ if (child_result == AUTHZ_GRANTED) {
auth_result = child_result; break;
} if ((child_result == AUTHZ_DENIED_NO_USER
&& auth_result == AUTHZ_DENIED)
|| (auth_result == AUTHZ_NEUTRAL)) {
auth_result = child_result;
}
}
}
child = child->next;
}
}
if (section->negate) { if (auth_result == AUTHZ_GRANTED) {
auth_result = AUTHZ_DENIED;
} elseif (auth_result == AUTHZ_DENIED ||
auth_result == AUTHZ_DENIED_NO_USER) { /* For negated directives, if the original result was denied * then the new result is neutral since we can not grant * access simply because authorization was not rejected.
*/
auth_result = AUTHZ_NEUTRAL;
}
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01626) "authorization result of %s: %s",
format_authz_command(r->pool, section),
format_authz_result(auth_result));
return auth_result;
}
staticint authorize_user_core(request_rec *r, int after_authn)
{
authz_core_dir_conf *conf;
authz_status auth_result;
if (auth_result == AUTHZ_GRANTED) { return OK;
} elseif (auth_result == AUTHZ_DENIED_NO_USER) { if (after_authn) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01629) "authorization failure (no authenticated user): %s",
r->uri); /* * If we're returning 401 to an authenticated user, tell them to * try again. If unauthenticated, note_auth_failure has already * been called during auth.
*/ if (r->user)
ap_note_auth_failure(r);
return HTTP_UNAUTHORIZED;
} else { /* * We need a user before we can decide what to do. * Get out of the way and proceed with authentication.
*/ return DECLINED;
}
} elseif (auth_result == AUTHZ_DENIED || auth_result == AUTHZ_NEUTRAL) { if (!after_authn || ap_auth_type(r) == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01630) "client denied by server configuration: %s%s",
r->filename ? "" : "uri ",
r->filename ? r->filename : r->uri);
if (conf->authz_forbidden_on_fail > 0) { return HTTP_FORBIDDEN;
} else { /* * If we're returning 401 to an authenticated user, tell them to * try again. If unauthenticated, note_auth_failure has already * been called during auth.
*/ if (r->user)
ap_note_auth_failure(r); return HTTP_UNAUTHORIZED;
}
}
} else { /* We'll assume that the module has already said what its * error was in the logs.
*/ return HTTP_INTERNAL_SERVER_ERROR;
}
}
/* The 'env' provider will allow the configuration to specify a list of env variables to check rather than a single variable. This is different
from the previous host based syntax. */
t = require_line; while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { if (apr_table_get(r->subprocess_env, w)) { return AUTHZ_GRANTED;
}
}
staticconstchar *all_parse_config(cmd_parms *cmd, constchar *require_line, constvoid **parsed_require_line)
{ /* * If the argument to the 'all' provider is 'granted' then just let * everybody in. This would be equivalent to the previous syntax of * 'allow from all'. If the argument is 'denied' we reject everybody, * which is equivalent to 'deny from all'.
*/ if (strcasecmp(require_line, "granted") == 0) {
*parsed_require_line = (void *)1; return NULL;
} elseif (strcasecmp(require_line, "denied") == 0) { /* *parsed_require_line is already NULL */ return NULL;
} else { return"Argument for 'Require all' must be 'granted' or 'denied'";
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.