diff --git a/CHANGES b/CHANGES index 8bf9b084cf..516cf225b6 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,14 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) core, authn/z: Avoid calling access control hooks for internal requests + with configurations which match those of initial request. Revert to + original behaviour (call access control hooks for internal requests + with URIs different from initial request) if any access control hooks or + providers are not registered as permitting this optimization. + Introduce wrappers for access control hook and provider registration + which can accept additional mode and flag data. [Chris Darroch] + *) http_filters: Don't spin if get an error when reading the next chunk. PR 44381 [Ruediger Pluem] diff --git a/include/http_request.h b/include/http_request.h index edad37087e..ce491da76c 100644 --- a/include/http_request.h +++ b/include/http_request.h @@ -18,6 +18,12 @@ * @file http_request.h * @brief Apache Request library * + * @defgroup APACHE_CORE_REQ Apache Request Processing + * @ingroup APACHE_CORE + * @{ + */ + +/* * request.c is the code which handles the main line of request * processing, once a request has been read in (finding the right per- * directory configuration, building it if necessary, and calling all @@ -42,6 +48,7 @@ #define APACHE_HTTP_REQUEST_H #include "apr_hooks.h" +#include "apr_optional.h" #include "util_filter.h" #ifdef __cplusplus @@ -181,7 +188,73 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *sub_req, request_rec *r) * @return 1 if authentication is required, 0 otherwise */ AP_DECLARE(int) ap_some_auth_required(request_rec *r); - + +/** + * @defgroup APACHE_CORE_REQ_AUTH Access Control for Sub-Requests and + * Internal Redirects + * @ingroup APACHE_CORE_REQ + * @{ + */ + +#define AP_AUTH_INTERNAL_PER_URI 0 /**< Run access control hooks on all + internal requests with URIs + distinct from that of initial + request */ +#define AP_AUTH_INTERNAL_PER_CONF 1 /**< Run access control hooks only on + internal requests with + configurations distinct from + that of initial request */ +#define AP_AUTH_INTERNAL_MASK 0x000F /**< mask to extract internal request + processing mode */ + +/** + * Clear flag which determines when access control hooks will be run for + * internal requests. + */ +AP_DECLARE(void) ap_clear_auth_internal(); + +/** + * Determine whether access control hooks will be run for all internal + * requests with URIs distinct from that of the initial request, or only + * those for which different configurations apply than those which applied + * to the initial request. To accomodate legacy external modules which + * may expect access control hooks to be run for all internal requests + * with distinct URIs, this is the default behaviour unless all access + * control hooks and authentication and authorization providers are + * registered with AP_AUTH_INTERNAL_PER_CONF. + * @param ptemp Pool used for temporary allocations + */ +AP_DECLARE(void) ap_setup_auth_internal(apr_pool_t *ptemp); + +/** + * Register an authentication or authorization provider with the global + * provider pool. + * @param pool The pool to create any storage from + * @param provider_group The group to store the provider in + * @param provider_name The name for this provider + * @param provider_version The version for this provider + * @param provider Opaque structure for this provider + * @param type Internal request processing mode, either + * AP_AUTH_INTERNAL_PER_URI or AP_AUTH_INTERNAL_PER_CONF + * @return APR_SUCCESS if all went well + */ +AP_DECLARE(apr_status_t) ap_register_auth_provider(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + const void *provider, + int type); + +/** @} */ + +/* Optional functions coming from mod_authn_core and mod_authz_core + * that list all registered authn/z providers. + */ +APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, authn_ap_list_provider_names, + (apr_pool_t *ptemp)); +APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, authz_ap_list_provider_names, + (apr_pool_t *ptemp)); + /** * Determine if the current request is the main request or a subrequest * @param r The current request @@ -300,11 +373,13 @@ AP_DECLARE_HOOK(int,map_to_storage,(request_rec *r)) * r->ap_auth_type). This hook is only run when Apache determines that * authentication/authorization is required for this resource (as determined * by the 'Require' directive). It runs after the access_checker hook, and - * before the auth_checker hook. + * before the auth_checker hook. This hook should be registered with + * ap_hook_check_authn(). * * @param r The current request * @return OK, DECLINED, or HTTP_... * @ingroup hooks + * @see ap_hook_check_authn */ AP_DECLARE_HOOK(int,check_user_id,(request_rec *r)) @@ -331,11 +406,13 @@ AP_DECLARE_HOOK(int,type_checker,(request_rec *r)) * This hook is used to apply additional access control to this resource. * It runs *before* a user is authenticated, so this hook is really to * apply additional restrictions independent of a user. It also runs - * independent of 'Require' directive usage. + * independent of 'Require' directive usage. This hook should be registered + * with ap_hook_check_access(). * * @param r the current request * @return OK, DECLINED, or HTTP_... * @ingroup hooks + * @see ap_hook_check_access */ AP_DECLARE_HOOK(int,access_checker,(request_rec *r)) @@ -344,14 +421,70 @@ AP_DECLARE_HOOK(int,access_checker,(request_rec *r)) * is available for the authenticated user (r->user and r->ap_auth_type). * It runs after the access_checker and check_user_id hooks. Note that * it will *only* be called if Apache determines that access control has - * been applied to this resource (through a 'Require' directive). + * been applied to this resource (through a 'Require' directive). This + * hook should be registered with ap_hook_check_authz(). * * @param r the current request * @return OK, DECLINED, or HTTP_... * @ingroup hooks + * @see ap_hook_check_authz */ AP_DECLARE_HOOK(int,auth_checker,(request_rec *r)) +/** + * Register a hook function that will apply additional access control to + * the current request. + * @param pf An access_checker hook function + * @param aszPre A NULL-terminated array of strings that name modules whose + * hooks should precede this one + * @param aszSucc A NULL-terminated array of strings that name modules whose + * hooks should succeed this one + * @param nOrder An integer determining order before honouring aszPre and + * aszSucc (for example, HOOK_MIDDLE) + * @param type Internal request processing mode, either + * AP_AUTH_INTERNAL_PER_URI or AP_AUTH_INTERNAL_PER_CONF + */ +AP_DECLARE(void) ap_hook_check_access(ap_HOOK_access_checker_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type); + +/** + * Register a hook function that will analyze the request headers, + * authenticate the user, and set the user information in the request record. + * @param pf A check_user_id hook function + * @param aszPre A NULL-terminated array of strings that name modules whose + * hooks should precede this one + * @param aszSucc A NULL-terminated array of strings that name modules whose + * hooks should succeed this one + * @param nOrder An integer determining order before honouring aszPre and + * aszSucc (for example, HOOK_MIDDLE) + * @param type Internal request processing mode, either + * AP_AUTH_INTERNAL_PER_URI or AP_AUTH_INTERNAL_PER_CONF + */ +AP_DECLARE(void) ap_hook_check_authn(ap_HOOK_check_user_id_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type); + +/** + * Register a hook function that determine if the resource being requested + * is available for the currently authenticated user. + * @param pf An auth_checker hook function + * @param aszPre A NULL-terminated array of strings that name modules whose + * hooks should precede this one + * @param aszSucc A NULL-terminated array of strings that name modules whose + * hooks should succeed this one + * @param nOrder An integer determining order before honouring aszPre and + * aszSucc (for example, HOOK_MIDDLE) + * @param type Internal request processing mode, either + * AP_AUTH_INTERNAL_PER_URI or AP_AUTH_INTERNAL_PER_CONF + */ +AP_DECLARE(void) ap_hook_check_authz(ap_HOOK_auth_checker_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type); + /** * This hook allows modules to insert filters for the current request * @param r the current request @@ -398,3 +531,4 @@ AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list, #endif #endif /* !APACHE_HTTP_REQUEST_H */ +/** @} */ diff --git a/modules/aaa/mod_access_compat.c b/modules/aaa/mod_access_compat.c index b93e9fcac9..bd56c8ed2c 100644 --- a/modules/aaa/mod_access_compat.c +++ b/modules/aaa/mod_access_compat.c @@ -364,7 +364,8 @@ static void register_hooks(apr_pool_t *p) APR_REGISTER_OPTIONAL_FN(access_compat_ap_satisfies); /* This can be access checker since we don't require r->user to be set. */ - ap_hook_access_checker(check_dir_access,NULL,NULL,APR_HOOK_MIDDLE); + ap_hook_check_access(check_dir_access, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA access_compat_module = diff --git a/modules/aaa/mod_auth_basic.c b/modules/aaa/mod_auth_basic.c index 4ae1c4665c..628e7a2dd4 100644 --- a/modules/aaa/mod_auth_basic.c +++ b/modules/aaa/mod_auth_basic.c @@ -286,7 +286,8 @@ static int authenticate_basic_user(request_rec *r) static void register_hooks(apr_pool_t *p) { - ap_hook_check_user_id(authenticate_basic_user,NULL,NULL,APR_HOOK_MIDDLE); + ap_hook_check_authn(authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA auth_basic_module = diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index fc2b684cca..ad2e0e9159 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -1970,7 +1970,8 @@ static void register_hooks(apr_pool_t *p) ap_hook_post_config(initialize_module, NULL, cfgPost, APR_HOOK_MIDDLE); ap_hook_child_init(initialize_child, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request(parse_hdr_and_update_nc, parsePre, NULL, APR_HOOK_MIDDLE); - ap_hook_check_user_id(authenticate_digest_user, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_authn(authenticate_digest_user, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_fixups(add_auth_info, NULL, NULL, APR_HOOK_MIDDLE); } diff --git a/modules/aaa/mod_authn_anon.c b/modules/aaa/mod_authn_anon.c index 07f48b35b3..ce8510f605 100644 --- a/modules/aaa/mod_authn_anon.c +++ b/modules/aaa/mod_authn_anon.c @@ -198,8 +198,8 @@ static const authn_provider authn_anon_provider = static void register_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHN_PROVIDER_GROUP, "anon", "0", - &authn_anon_provider); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "anon", "0", + &authn_anon_provider, AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authn_anon_module = diff --git a/modules/aaa/mod_authn_core.c b/modules/aaa/mod_authn_core.c index e421e1375d..66e204e0d0 100644 --- a/modules/aaa/mod_authn_core.c +++ b/modules/aaa/mod_authn_core.c @@ -253,8 +253,9 @@ static const char *authaliassection(cmd_parms *cmd, void *mconfig, const char *a apr_hash_set(authcfg->alias_rec, provider_alias, APR_HASH_KEY_STRING, prvdraliasrec); /* Register the fake provider so that we get called first */ - ap_register_provider(cmd->pool, AUTHN_PROVIDER_GROUP, provider_alias, "0", - &authn_alias_provider); + ap_register_auth_provider(cmd->pool, AUTHN_PROVIDER_GROUP, + provider_alias, "0", &authn_alias_provider, + AP_AUTH_INTERNAL_PER_CONF); } cmd->override = old_overrides; @@ -296,6 +297,11 @@ static const char *authn_ap_auth_name(request_rec *r) return apr_pstrdup(r->pool, conf->ap_auth_name); } +static apr_array_header_t *authn_ap_list_provider_names(apr_pool_t *ptemp) +{ + return ap_list_provider_names(ptemp, AUTHN_PROVIDER_GROUP, "0"); +} + static const command_rec authn_cmds[] = { AP_INIT_TAKE1("AuthType", ap_set_string_slot, @@ -313,6 +319,7 @@ static void register_hooks(apr_pool_t *p) { APR_REGISTER_OPTIONAL_FN(authn_ap_auth_type); APR_REGISTER_OPTIONAL_FN(authn_ap_auth_name); + APR_REGISTER_OPTIONAL_FN(authn_ap_list_provider_names); } module AP_MODULE_DECLARE_DATA authn_core_module = diff --git a/modules/aaa/mod_authn_dbd.c b/modules/aaa/mod_authn_dbd.c index 3341171e67..47ce2aa49c 100644 --- a/modules/aaa/mod_authn_dbd.c +++ b/modules/aaa/mod_authn_dbd.c @@ -18,6 +18,7 @@ #include "httpd.h" #include "http_config.h" #include "http_log.h" +#include "http_request.h" #include "apr_lib.h" #include "apr_dbd.h" #include "mod_dbd.h" @@ -268,7 +269,8 @@ static void authn_dbd_hooks(apr_pool_t *p) &authn_dbd_realm }; - ap_register_provider(p, AUTHN_PROVIDER_GROUP, "dbd", "0", &authn_dbd_provider); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "dbd", "0", + &authn_dbd_provider, AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authn_dbd_module = { diff --git a/modules/aaa/mod_authn_dbm.c b/modules/aaa/mod_authn_dbm.c index 9221752fa2..abb8df482a 100644 --- a/modules/aaa/mod_authn_dbm.c +++ b/modules/aaa/mod_authn_dbm.c @@ -189,8 +189,8 @@ static const authn_provider authn_dbm_provider = static void register_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHN_PROVIDER_GROUP, "dbm", "0", - &authn_dbm_provider); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "dbm", "0", + &authn_dbm_provider, AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authn_dbm_module = diff --git a/modules/aaa/mod_authn_default.c b/modules/aaa/mod_authn_default.c index 46c78cd79a..0155c6e298 100644 --- a/modules/aaa/mod_authn_default.c +++ b/modules/aaa/mod_authn_default.c @@ -90,7 +90,8 @@ static int authenticate_no_user(request_rec *r) static void register_hooks(apr_pool_t *p) { - ap_hook_check_user_id(authenticate_no_user,NULL,NULL,APR_HOOK_LAST); + ap_hook_check_authn(authenticate_no_user, NULL, NULL, APR_HOOK_LAST, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authn_default_module = diff --git a/modules/aaa/mod_authn_file.c b/modules/aaa/mod_authn_file.c index 018733e1ea..2cab61ca90 100644 --- a/modules/aaa/mod_authn_file.c +++ b/modules/aaa/mod_authn_file.c @@ -163,8 +163,8 @@ static const authn_provider authn_file_provider = static void register_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHN_PROVIDER_GROUP, "file", "0", - &authn_file_provider); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "file", "0", + &authn_file_provider, AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authn_file_module = diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c index 4034f5efb8..9c6ac6f600 100644 --- a/modules/aaa/mod_authnz_ldap.c +++ b/modules/aaa/mod_authnz_ldap.c @@ -1582,20 +1582,25 @@ static void ImportULDAPOptFn(void) static void register_hooks(apr_pool_t *p) { /* Register authn provider */ - ap_register_provider(p, AUTHN_PROVIDER_GROUP, "ldap", "0", - &authn_ldap_provider); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "ldap", "0", + &authn_ldap_provider, AP_AUTH_INTERNAL_PER_CONF); /* Register authz providers */ - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-user", "0", - &authz_ldapuser_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-group", "0", - &authz_ldapgroup_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-dn", "0", - &authz_ldapdn_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-attribute", "0", - &authz_ldapattribute_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-filter", "0", - &authz_ldapfilter_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-user", "0", + &authz_ldapuser_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-group", "0", + &authz_ldapgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-dn", "0", + &authz_ldapdn_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-attribute", "0", + &authz_ldapattribute_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-filter", "0", + &authz_ldapfilter_provider, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_post_config(authnz_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE); diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c index 15557f4e4b..5b7c409861 100644 --- a/modules/aaa/mod_authz_core.c +++ b/modules/aaa/mod_authz_core.c @@ -483,8 +483,9 @@ static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig, APR_HASH_KEY_STRING, prvdraliasrec); /* Register the fake provider so that we get called first */ - ap_register_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, provider_alias, "0", - &authz_alias_provider); + ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, + provider_alias, "0", &authz_alias_provider, + AP_AUTH_INTERNAL_PER_CONF); } cmd->override = old_overrides; @@ -802,11 +803,18 @@ static int authz_some_auth_required(request_rec *r) return req_authz; } +static apr_array_header_t *authz_ap_list_provider_names(apr_pool_t *ptemp) +{ + return ap_list_provider_names(ptemp, AUTHZ_PROVIDER_GROUP, "0"); +} + static void register_hooks(apr_pool_t *p) { APR_REGISTER_OPTIONAL_FN(authz_some_auth_required); + APR_REGISTER_OPTIONAL_FN(authz_ap_list_provider_names); - ap_hook_auth_checker(authorize_user, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_authz(authorize_user, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_core_module = diff --git a/modules/aaa/mod_authz_dbd.c b/modules/aaa/mod_authz_dbd.c index d01d83bd67..8164a5eeac 100644 --- a/modules/aaa/mod_authz_dbd.c +++ b/modules/aaa/mod_authz_dbd.c @@ -310,12 +310,15 @@ static const authz_provider authz_dbdlogout_provider = static void authz_dbd_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-group", "0", - &authz_dbdgroup_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-login", "0", - &authz_dbdlogin_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-logout", "0", - &authz_dbdlogout_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-group", "0", + &authz_dbdgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-login", "0", + &authz_dbdlogin_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-logout", "0", + &authz_dbdlogout_provider, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_dbd_module = diff --git a/modules/aaa/mod_authz_dbm.c b/modules/aaa/mod_authz_dbm.c index c71e4a338c..e67f699594 100644 --- a/modules/aaa/mod_authz_dbm.c +++ b/modules/aaa/mod_authz_dbm.c @@ -272,10 +272,12 @@ static void register_hooks(apr_pool_t *p) { authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-group", "0", - &authz_dbmgroup_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-file-group", "0", - &authz_dbmfilegroup_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-group", "0", + &authz_dbmgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-file-group", "0", + &authz_dbmfilegroup_provider, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_dbm_module = diff --git a/modules/aaa/mod_authz_default.c b/modules/aaa/mod_authz_default.c index 8a234f9795..82588ea0f5 100644 --- a/modules/aaa/mod_authz_default.c +++ b/modules/aaa/mod_authz_default.c @@ -89,7 +89,8 @@ static int check_user_access(request_rec *r) static void register_hooks(apr_pool_t *p) { - ap_hook_auth_checker(check_user_access,NULL,NULL,APR_HOOK_LAST); + ap_hook_check_authz(check_user_access, NULL, NULL, APR_HOOK_LAST, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_default_module = diff --git a/modules/aaa/mod_authz_groupfile.c b/modules/aaa/mod_authz_groupfile.c index 6ff3e17832..fabf6cdd25 100644 --- a/modules/aaa/mod_authz_groupfile.c +++ b/modules/aaa/mod_authz_groupfile.c @@ -266,10 +266,12 @@ static void register_hooks(apr_pool_t *p) { authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "group", "0", - &authz_group_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "file-group", "0", - &authz_filegroup_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "group", "0", + &authz_group_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "file-group", "0", + &authz_filegroup_provider, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_groupfile_module = diff --git a/modules/aaa/mod_authz_host.c b/modules/aaa/mod_authz_host.c index 77af896568..e6d6ec79d3 100644 --- a/modules/aaa/mod_authz_host.c +++ b/modules/aaa/mod_authz_host.c @@ -241,14 +241,14 @@ static const authz_provider authz_all_provider = static void register_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "env", "0", - &authz_env_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ip", "0", - &authz_ip_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "host", "0", - &authz_host_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "all", "0", - &authz_all_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "env", "0", + &authz_env_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ip", "0", + &authz_ip_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "host", "0", + &authz_host_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "all", "0", + &authz_all_provider, AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_host_module = diff --git a/modules/aaa/mod_authz_owner.c b/modules/aaa/mod_authz_owner.c index 26eec14289..50cbbcae56 100644 --- a/modules/aaa/mod_authz_owner.c +++ b/modules/aaa/mod_authz_owner.c @@ -167,8 +167,9 @@ static void register_hooks(apr_pool_t *p) { APR_REGISTER_OPTIONAL_FN(authz_owner_get_file_group); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "file-owner", "0", - &authz_fileowner_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "file-owner", "0", + &authz_fileowner_provider, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_owner_module = diff --git a/modules/aaa/mod_authz_user.c b/modules/aaa/mod_authz_user.c index 8607a033d1..75c21589b0 100644 --- a/modules/aaa/mod_authz_user.c +++ b/modules/aaa/mod_authz_user.c @@ -81,10 +81,11 @@ static const authz_provider authz_validuser_provider = static void register_hooks(apr_pool_t *p) { - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "user", "0", - &authz_user_provider); - ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "valid-user", "0", - &authz_validuser_provider); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "user", "0", + &authz_user_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "valid-user", "0", + &authz_validuser_provider, + AP_AUTH_INTERNAL_PER_CONF); } module AP_MODULE_DECLARE_DATA authz_user_module = diff --git a/modules/examples/mod_example_hooks.c b/modules/examples/mod_example_hooks.c index 824de41dd7..30ea60fe78 100644 --- a/modules/examples/mod_example_hooks.c +++ b/modules/examples/mod_example_hooks.c @@ -324,6 +324,7 @@ static x_cfg *our_cconfig(const conn_rec *c) #define EXAMPLE_LOG_EACH 0 #endif +#if EXAMPLE_LOG_EACH static void example_log_each(apr_pool_t *p, server_rec *s, const char *note) { if (s != NULL) { @@ -336,7 +337,7 @@ static void example_log_each(apr_pool_t *p, server_rec *s, const char *note) "context: %s\n", note); } } - +#endif /* * This utility routine traces the hooks called when the server starts up. @@ -564,8 +565,8 @@ static void *x_create_dir_config(apr_pool_t *p, char *dirspec) */ dname = (dname != NULL) ? dname : ""; cfg->loc = apr_pstrcat(p, "DIR(", dname, ")", NULL); - note = apr_psprintf(p, "x_create_dir_config(p == 0x%x, dirspec == %s)", - p, dirspec); + note = apr_psprintf(p, "x_create_dir_config(p == %pp, dirspec == %s)", + (void*) p, dirspec); trace_startup(p, NULL, cfg, note); return (void *) cfg; } @@ -617,9 +618,9 @@ static void *x_merge_dir_config(apr_pool_t *p, void *parent_conf, * Now just record our being called in the trace list. Include the * locations we were asked to merge. */ - note = apr_psprintf(p, "x_merge_dir_config(p == 0x%x, parent_conf == " - "0x%x, newloc_conf == 0x%x)", p, parent_conf, - newloc_conf); + note = apr_psprintf(p, "x_merge_dir_config(p == %pp, parent_conf == " + "%pp, newloc_conf == %pp)", (void*) p, + (void*) parent_conf, (void*) newloc_conf); trace_startup(p, NULL, merged_config, note); return (void *) merged_config; } @@ -1120,8 +1121,8 @@ static int x_pre_connection(conn_rec *c, void *csd) /* * Log the call and exit. */ - note = apr_psprintf(c->pool, "x_pre_connection(c = %x, p = %x)", - c, c->pool); + note = apr_psprintf(c->pool, "x_pre_connection(c = %pp, p = %pp)", + (void*) c, (void*) c->pool); trace_connection(c, note); return OK; @@ -1218,6 +1219,20 @@ static int x_header_parser(request_rec *r) } +/* + * This routine is called to check for any module-specific restrictions placed + * upon the requested resource. (See the mod_access_compat module for an + * example.) + * + * This is a RUN_ALL hook. The first handler to return a status other than OK + * or DECLINED (for instance, HTTP_FORBIDDEN) aborts the callback chain. + */ +static int x_check_access(request_rec *r) +{ + trace_request(r, "x_check_access()"); + return DECLINED; +} + /* * This routine is called to check the authentication information sent with * the request (such as looking up the user in a database and verifying that @@ -1226,12 +1241,12 @@ static int x_header_parser(request_rec *r) * This is a RUN_FIRST hook. The return value is OK, DECLINED, or some * HTTP_mumble error (typically HTTP_UNAUTHORIZED). */ -static int x_check_user_id(request_rec *r) +static int x_check_authn(request_rec *r) { /* * Don't do anything except log the call. */ - trace_request(r, "x_check_user_id()"); + trace_request(r, "x_check_authn()"); return DECLINED; } @@ -1246,26 +1261,13 @@ static int x_check_user_id(request_rec *r) * If *all* modules return DECLINED, the request is aborted with a server * error. */ -static int x_auth_checker(request_rec *r) +static int x_check_authz(request_rec *r) { /* * Log the call and return OK, or access will be denied (even though we * didn't actually do anything). */ - trace_request(r, "x_auth_checker()"); - return DECLINED; -} - -/* - * This routine is called to check for any module-specific restrictions placed - * upon the requested resource. (See the mod_access module for an example.) - * - * This is a RUN_ALL hook. The first handler to return a status other than OK - * or DECLINED (for instance, HTTP_FORBIDDEN) aborts the callback chain. - */ -static int x_access_checker(request_rec *r) -{ - trace_request(r, "x_access_checker()"); + trace_request(r, "x_check_authz()"); return DECLINED; } @@ -1456,11 +1458,14 @@ static void x_register_hooks(apr_pool_t *p) ap_hook_translate_name(x_translate_name, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_map_to_storage(x_map_to_storage, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_header_parser(x_header_parser, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_check_user_id(x_check_user_id, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_fixups(x_fixups, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_type_checker(x_type_checker, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_access_checker(x_access_checker, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_auth_checker(x_auth_checker, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_access(x_check_access, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_check_authn(x_check_authn, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_check_authz(x_check_authz, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_insert_filter(x_insert_filter, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_insert_error_filter(x_insert_error_filter, NULL, NULL, APR_HOOK_MIDDLE); #ifdef HAVE_UNIX_SUEXEC diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 573255d2a8..379c827471 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -501,10 +501,13 @@ static void ssl_register_hooks(apr_pool_t *p) ap_hook_default_port (ssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_pre_config (ssl_hook_pre_config, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_child_init (ssl_init_Child, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_check_user_id (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST); + ap_hook_check_authn (ssl_hook_UserCheck, NULL,NULL, APR_HOOK_FIRST, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_fixups (ssl_hook_Fixup, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_access_checker(ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE); - ap_hook_auth_checker (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE); + ap_hook_check_access (ssl_hook_Access, NULL,NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_check_authz (ssl_hook_Auth, NULL,NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE); ssl_var_register(p); diff --git a/server/core.c b/server/core.c index cfa9fc4ad6..f6c987643c 100644 --- a/server/core.c +++ b/server/core.c @@ -2002,7 +2002,6 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg) int old_overrides = cmd->override; char *old_path = cmd->path; core_dir_config *conf; - ap_regex_t *r = NULL; const command_rec *thiscmd = cmd->cmd; core_dir_config *c = mconfig; ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool); @@ -3753,6 +3752,7 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte set_banner(pconf); ap_setup_make_content_type(pconf); + ap_setup_auth_internal(ptemp); return OK; } @@ -3963,7 +3963,6 @@ static void register_hooks(apr_pool_t *p) /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */ ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST); ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST); - ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST); ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE); APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL, APR_HOOK_MIDDLE); diff --git a/server/main.c b/server/main.c index e758211375..0f3e6a09fb 100644 --- a/server/main.c +++ b/server/main.c @@ -35,6 +35,7 @@ #include "http_log.h" #include "http_config.h" #include "http_core.h" +#include "http_request.h" #include "http_vhost.h" #include "apr_uri.h" #include "util_ebcdic.h" @@ -713,6 +714,7 @@ int main(int argc, const char * const argv[]) for (;;) { apr_hook_deregister_all(); apr_pool_clear(pconf); + ap_clear_auth_internal(server_conf); for (mod = ap_prelinked_modules; *mod != NULL; mod++) { ap_register_hooks(*mod, pconf); diff --git a/server/request.c b/server/request.c index d3eecbb688..bec1343733 100644 --- a/server/request.c +++ b/server/request.c @@ -34,6 +34,7 @@ #define CORE_PRIVATE #include "ap_config.h" +#include "ap_provider.h" #include "httpd.h" #include "http_config.h" #include "http_request.h" @@ -82,6 +83,10 @@ AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r)) AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request, (request_rec *r), (r), OK, DECLINED) +static int auth_internal_per_conf = 0; +static int auth_internal_per_conf_hooks = 0; +static int auth_internal_per_conf_providers = 0; + static int decl_die(int status, char *phase, request_rec *r) { @@ -171,14 +176,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) * functions in map_to_storage that use the same merge results given * identical input.) If the config changes, we must re-auth. */ - if (r->main && (r->main->per_dir_config == r->per_dir_config)) { - r->user = r->main->user; - r->ap_auth_type = r->main->ap_auth_type; - } - else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) { + if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) { r->user = r->prev->user; r->ap_auth_type = r->prev->ap_auth_type; } + else if (r->main && (r->main->per_dir_config == r->per_dir_config)) { + r->user = r->main->user; + r->ap_auth_type = r->main->ap_auth_type; + } else { switch (ap_satisfies(r)) { case SATISFY_ALL: @@ -248,44 +253,61 @@ typedef struct walk_cache_t { ap_conf_vector_t *dir_conf_merged; /* Base per_dir_config */ ap_conf_vector_t *per_dir_result; /* per_dir_config += walked result */ apr_array_header_t *walked; /* The list of walk_walked_t results */ + struct walk_cache_t *prev; /* Prev cache of same call in this (sub)req */ + int count; /* Number of prev invocations of same call in this (sub)req */ } walk_cache_t; static walk_cache_t *prep_walk_cache(apr_size_t t, request_rec *r) { - walk_cache_t *cache; - void **note; + void **note, **inherit_note; + walk_cache_t *cache, *prev_cache, *copy_cache; + int count; - /* Find the most relevant, recent entry to work from. That would be - * this request (on the second call), or the parent request of a - * subrequest, or the prior request of an internal redirect. Provide - * this _walk()er with a copy it is allowed to munge. If there is no - * parent or prior cached request, then create a new walk cache. + /* Find the most relevant, recent walk cache to work from and provide + * a copy the caller is allowed to munge. In the case of a sub-request + * or internal redirect, this is the cache corresponding to the equivalent + * invocation of the same function call in the "parent" request, if such + * a cache exists. Otherwise it is the walk cache of the previous + * invocation of the same function call in the current request, if + * that exists; if not, then create a new walk cache. */ note = ap_get_request_note(r, t); if (!note) { return NULL; } - if (!(cache = *note)) { - void **inherit_note; + copy_cache = prev_cache = *note; + count = prev_cache ? (prev_cache->count + 1) : 0; - if ((r->main - && ((inherit_note = ap_get_request_note(r->main, t))) - && *inherit_note) - || (r->prev - && ((inherit_note = ap_get_request_note(r->prev, t))) - && *inherit_note)) { - cache = apr_pmemdup(r->pool, *inherit_note, - sizeof(*cache)); - cache->walked = apr_array_copy(r->pool, cache->walked); - } - else { - cache = apr_pcalloc(r->pool, sizeof(*cache)); - cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t)); - } + if ((r->prev + && (inherit_note = ap_get_request_note(r->prev, t)) + && *inherit_note) + || (r->main + && (inherit_note = ap_get_request_note(r->main, t)) + && *inherit_note)) { + walk_cache_t *inherit_cache = *inherit_note; - *note = cache; + while (inherit_cache->count > count) { + inherit_cache = inherit_cache->prev; + } + if (inherit_cache->count == count) { + copy_cache = inherit_cache; + } } + + if (copy_cache) { + cache = apr_pmemdup(r->pool, copy_cache, sizeof(*cache)); + cache->walked = apr_array_copy(r->pool, cache->walked); + cache->prev = prev_cache; + cache->count = count; + } + else { + cache = apr_pcalloc(r->pool, sizeof(*cache)); + cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t)); + } + + *note = cache; + return cache; } @@ -454,6 +476,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) walk_cache_t *cache; char *entry_dir; apr_status_t rv; + int cached; /* XXX: Better (faster) tests needed!!! * @@ -491,6 +514,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) r->filename = entry_dir; cache = prep_walk_cache(AP_NOTE_DIRECTORY_WALK, r); + cached = (cache->cached != NULL); /* If this is not a dirent subrequest with a preconstructed * r->finfo value, then we can simply stat the filename to @@ -534,7 +558,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) * and the vhost's list of directory sections hasn't changed, * we can skip rewalking the directory_walk entries. */ - if (cache->cached + if (cached && ((r->finfo.filetype == APR_REG) || ((r->finfo.filetype == APR_DIR) && (!r->path_info || !*r->path_info))) @@ -619,6 +643,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ int sec_idx; int matches = cache->walked->nelts; + int cached_matches = matches; walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts; core_dir_config *this_dir; core_opts_t opts; @@ -628,6 +653,8 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) char *buf; unsigned int seg, startseg; + cached &= auth_internal_per_conf; + /* Invariant: from the first time filename_len is set until * it goes out of scope, filename_len==strlen(r->filename) */ @@ -827,6 +854,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ cache->walked->nelts -= matches; matches = 0; + cached = 0; } if (now_merged) { @@ -894,6 +922,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ cache->walked->nelts -= matches; matches = 0; + cached = 0; } if (now_merged) { @@ -1106,6 +1135,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ cache->walked->nelts -= matches; matches = 0; + cached = 0; } if (now_merged) { @@ -1122,11 +1152,16 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) last_walk->merged = now_merged; } - /* Whoops - everything matched in sequence, but the original walk - * found some additional matches. Truncate them. + /* Whoops - everything matched in sequence, but either the original + * walk found some additional matches (which we need to truncate), or + * this walk found some additional matches. */ if (matches) { cache->walked->nelts -= matches; + cached = 0; + } + else if (cache->walked->nelts > cached_matches) { + cached = 0; } } @@ -1166,6 +1201,12 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) cache->cached = ap_make_dirstr_parent(r->pool, r->filename); } + if (cached + && r->per_dir_config == cache->dir_conf_merged) { + r->per_dir_config = cache->per_dir_result; + return OK; + } + cache->dir_conf_tested = sec_ent; cache->dir_conf_merged = r->per_dir_config; @@ -1192,6 +1233,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) int num_sec = sconf->sec_url->nelts; walk_cache_t *cache; const char *entry_uri; + int cached; /* No tricks here, there are no to parse in this vhost. * We won't destroy the cache, just in case _this_ redirect is later @@ -1202,6 +1244,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) } cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); + cached = (cache->cached != NULL); /* Location and LocationMatch differ on their behaviour w.r.t. multiple * slashes. Location matches multiple slashes with a single slash, @@ -1221,7 +1264,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) * and the vhost's list of locations hasn't changed, we can skip * rewalking the location_walk entries. */ - if (cache->cached + if (cached && (cache->dir_conf_tested == sec_ent) && (strcmp(entry_uri, cache->cached) == 0)) { /* Well this looks really familiar! If our end-result (per_dir_result) @@ -1233,11 +1276,6 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) return OK; } - if (r->per_dir_config == cache->dir_conf_merged) { - r->per_dir_config = cache->per_dir_result; - return OK; - } - if (cache->walked->nelts) { now_merged = ((walk_walked_t*)cache->walked->elts) [cache->walked->nelts - 1].merged; @@ -1249,7 +1287,10 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) */ int len, sec_idx; int matches = cache->walked->nelts; + int cached_matches = matches; walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts; + + cached &= auth_internal_per_conf; cache->cached = entry_uri; /* Go through the location entries, and check for matches. @@ -1295,6 +1336,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) */ cache->walked->nelts -= matches; matches = 0; + cached = 0; } if (now_merged) { @@ -1311,12 +1353,23 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) last_walk->merged = now_merged; } - /* Whoops - everything matched in sequence, but the original walk - * found some additional matches. Truncate them. + /* Whoops - everything matched in sequence, but either the original + * walk found some additional matches (which we need to truncate), or + * this walk found some additional matches. */ if (matches) { cache->walked->nelts -= matches; + cached = 0; } + else if (cache->walked->nelts > cached_matches) { + cached = 0; + } + } + + if (cached + && r->per_dir_config == cache->dir_conf_merged) { + r->per_dir_config = cache->per_dir_result; + return OK; } cache->dir_conf_tested = sec_ent; @@ -1344,6 +1397,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) int num_sec = dconf->sec_file->nelts; walk_cache_t *cache; const char *test_file; + int cached; /* To allow broken modules to proceed, we allow missing filenames to pass. * We will catch it later if it's heading for the core handler. @@ -1354,6 +1408,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) } cache = prep_walk_cache(AP_NOTE_FILE_WALK, r); + cached = (cache->cached != NULL); /* No tricks here, there are just no to parse in this context. * We won't destroy the cache, just in case _this_ redirect is later @@ -1378,7 +1433,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) * and the directory's list of file sections hasn't changed, we * can skip rewalking the file_walk entries. */ - if (cache->cached + if (cached && (cache->dir_conf_tested == sec_ent) && (strcmp(test_file, cache->cached) == 0)) { /* Well this looks really familiar! If our end-result (per_dir_result) @@ -1390,11 +1445,6 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) return OK; } - if (r->per_dir_config == cache->dir_conf_merged) { - r->per_dir_config = cache->per_dir_result; - return OK; - } - if (cache->walked->nelts) { now_merged = ((walk_walked_t*)cache->walked->elts) [cache->walked->nelts - 1].merged; @@ -1406,7 +1456,10 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) */ int sec_idx; int matches = cache->walked->nelts; + int cached_matches = matches; walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts; + + cached &= auth_internal_per_conf; cache->cached = test_file; /* Go through the location entries, and check for matches. @@ -1449,6 +1502,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) */ cache->walked->nelts -= matches; matches = 0; + cached = 0; } if (now_merged) { @@ -1465,12 +1519,23 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) last_walk->merged = now_merged; } - /* Whoops - everything matched in sequence, but the original walk - * found some additional matches. Truncate them. + /* Whoops - everything matched in sequence, but either the original + * walk found some additional matches (which we need to truncate), or + * this walk found some additional matches. */ if (matches) { cache->walked->nelts -= matches; + cached = 0; } + else if (cache->walked->nelts > cached_matches) { + cached = 0; + } + } + + if (cached + && r->per_dir_config == cache->dir_conf_merged) { + r->per_dir_config = cache->per_dir_result; + return OK; } cache->dir_conf_tested = sec_ent; @@ -1618,6 +1683,107 @@ AP_DECLARE(int) ap_some_auth_required(request_rec *r) return 0; } +AP_DECLARE(void) ap_clear_auth_internal(void) +{ + auth_internal_per_conf_hooks = 0; + auth_internal_per_conf_providers = 0; +} + +AP_DECLARE(void) ap_setup_auth_internal(apr_pool_t *ptemp) +{ + APR_OPTIONAL_FN_TYPE(authn_ap_list_provider_names) + *authn_ap_list_provider_names; + APR_OPTIONAL_FN_TYPE(authz_ap_list_provider_names) + *authz_ap_list_provider_names; + int total_auth_hooks = 0; + int total_auth_providers = 0; + + auth_internal_per_conf = 0; + + if (_hooks.link_access_checker) { + total_auth_hooks += _hooks.link_access_checker->nelts; + } + if (_hooks.link_check_user_id) { + total_auth_hooks += _hooks.link_check_user_id->nelts; + } + if (_hooks.link_auth_checker) { + total_auth_hooks += _hooks.link_auth_checker->nelts; + } + + if (total_auth_hooks > auth_internal_per_conf_hooks) { + return; + } + + authn_ap_list_provider_names = + APR_RETRIEVE_OPTIONAL_FN(authn_ap_list_provider_names); + authz_ap_list_provider_names = + APR_RETRIEVE_OPTIONAL_FN(authz_ap_list_provider_names); + + if (authn_ap_list_provider_names) { + total_auth_providers += authn_ap_list_provider_names(ptemp)->nelts; + } + + if (authz_ap_list_provider_names) { + total_auth_providers += authz_ap_list_provider_names(ptemp)->nelts; + } + + if (total_auth_providers > auth_internal_per_conf_providers) { + return; + } + + auth_internal_per_conf = 1; +} + +AP_DECLARE(apr_status_t) ap_register_auth_provider(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + const void *provider, + int type) +{ + if ((type & AP_AUTH_INTERNAL_MASK) == AP_AUTH_INTERNAL_PER_CONF) { + ++auth_internal_per_conf_providers; + } + + return ap_register_provider(pool, provider_group, provider_name, + provider_version, provider); +} + +AP_DECLARE(void) ap_hook_check_access(ap_HOOK_access_checker_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type) +{ + if ((type & AP_AUTH_INTERNAL_MASK) == AP_AUTH_INTERNAL_PER_CONF) { + ++auth_internal_per_conf_hooks; + } + + ap_hook_access_checker(pf, aszPre, aszSucc, nOrder); +} + +AP_DECLARE(void) ap_hook_check_authn(ap_HOOK_check_user_id_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type) +{ + if ((type & AP_AUTH_INTERNAL_MASK) == AP_AUTH_INTERNAL_PER_CONF) { + ++auth_internal_per_conf_hooks; + } + + ap_hook_check_user_id(pf, aszPre, aszSucc, nOrder); +} + +AP_DECLARE(void) ap_hook_check_authz(ap_HOOK_auth_checker_t *pf, + const char * const *aszPre, + const char * const *aszSucc, + int nOrder, int type) +{ + if ((type & AP_AUTH_INTERNAL_MASK) == AP_AUTH_INTERNAL_PER_CONF) { + ++auth_internal_per_conf_hooks; + } + + ap_hook_auth_checker(pf, aszPre, aszSucc, nOrder); +} AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method, const char *new_uri, @@ -1949,3 +2115,4 @@ AP_DECLARE(int) ap_is_initial_req(request_rec *r) return (r->main == NULL) /* otherwise, this is a sub-request */ && (r->prev == NULL); /* otherwise, this is an internal redirect */ } +