request.c revision 85bb5b92490e4f095aae394118fc588a8f4c486f
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* ====================================================================
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * The Apache Software License, Version 1.1
5f5d1b4cc970b7f06ff8ef6526128e9a27303d88nd * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * Redistribution and use in source and binary forms, with or without
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * modification, are permitted provided that the following conditions
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * 1. Redistributions of source code must retain the above copyright
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * notice, this list of conditions and the following disclaimer.
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * 2. Redistributions in binary form must reproduce the above copyright
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * notice, this list of conditions and the following disclaimer in
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * the documentation and/or other materials provided with the
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * distribution.
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * 3. The end-user documentation included with the redistribution,
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * if any, must include the following acknowledgment:
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * "This product includes software developed by the
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * Apache Software Foundation (http://www.apache.org/)."
7db9f691a00ead175b03335457ca296a33ddf31bnd * Alternately, this acknowledgment may appear in the software itself,
3577f1d38e53397f6b431c02011f875316b2f070nd * if and wherever such third-party acknowledgments normally appear.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * 4. The names "Apache" and "Apache Software Foundation" must
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * not be used to endorse or promote products derived from this
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * software without prior written permission. For written
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * permission, please contact apache@apache.org.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * 5. Products derived from this software may not be called "Apache",
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * nor may "Apache" appear in their name, without prior written
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * permission of the Apache Software Foundation.
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * SUCH DAMAGE.
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * ====================================================================
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * This software consists of voluntary contributions made by many
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * individuals on behalf of the Apache Software Foundation. For more
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * information on the Apache Software Foundation, please see
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * Portions of this software are based upon public domain software
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * originally written at the National Center for Supercomputing Applications,
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * University of Illinois, Urbana-Champaign.
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * http_request.c: functions to get and process requests
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * Rob McCool 3/21/93
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * Thoroughly revamped by rst for Apache. NB this file reads
c6f41bc69d643835804e7e831776d3d46c6f5962slive * best from the bottom up.
d7604f90897d9b08b227c127ff5392393178911crpluemAP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))
d7604f90897d9b08b227c127ff5392393178911crpluemAP_IMPLEMENT_HOOK_RUN_ALL(int,create_request,(request_rec *r),(r),OK,DECLINED)
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slivestatic int decl_die(int status, char *phase, request_rec *r)
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, r,
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive "configuration error: couldn't %s: %s", phase, r->uri);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* This is the master logic for processing requests. Do NOT duplicate
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * this logic elsewhere, or the security model will be broken by future
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * API changes. Each phase must be individually optimized to pick up
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * redundant/duplicate calls by subrequests, and redirects.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabeleAP_DECLARE(int) ap_process_request_internal(request_rec *r)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Ignore embedded %2F's in path for proxy requests */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele access_status = ap_unescape_url(r->parsed_uri.path);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_getparents(r->uri); /* OK --- shrinking transformations... */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* File-specific requests with no 'true' URI are a huge pain... they
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * cannot bubble through the next several steps. Only subrequests may
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * have an empty uri, otherwise let translate_name kill the request.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Reset to the server default config prior to running map_to_storage
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd /* This request wasn't in storage (e.g. TRACE) */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Excluding file-specific requests with no 'true' URI...
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Rerun the location walk, which overrides any map_to_storage config.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Only on the main request! */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Skip authn/authz if the parent or prior request passed the authn/authz,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * and that configuration didn't change (this requires optimized _walk()
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * functions in map_to_storage that use the same merge results given
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * identical input.) If the config changes, we must re-auth.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((access_status = ap_run_access_checker(r)) != 0) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele return decl_die(access_status, "check access", r);
00e3a194016a8be92daa1d4a360ed41dec1786d0rbowen if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ? "check user. No user file?"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele : "perform authentication. AuthType not set!", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ? "check access. No groups file?"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele : "perform authentication. AuthType not set!", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (((access_status = ap_run_access_checker(r)) != 0) || !ap_auth_type(r)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ? "check access"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele : "perform authentication. AuthType not set!", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ? "check user. No user file?"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele : "perform authentication. AuthType not set!", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ? "check access. No groups file?"
a3388213b2b4d46b356be205e38204e67b4304d8rbowen : "perform authentication. AuthType not set!", r);
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive /* XXX Must make certain the ap_run_type_checker short circuits mime
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * in mod-proxy for r->proxyreq && r->parsed_uri.scheme
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * && !strcmp(r->parsed_uri.scheme, "http")
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((access_status = ap_run_type_checker(r)) != 0) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* The new insert_filter stage makes sense here IMHO. We are sure that
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * we are going to run the request now, so we may as well insert filters
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * if any are available. Since the goal of this phase is to allow all
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * modules to insert a filter if they want to, this filter returns
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * void. I just can't see any way that this filter can reasonably
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * fail, either your modules inserts something or it doesn't. rbb
a3388213b2b4d46b356be205e38204e67b4304d8rbowen/* Useful caching structures to repeat _walk/merge sequences as required
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * when a subrequest or redirect reuses substantially the same config.
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * Directive order in the httpd.conf file and its Includes significantly
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * impact this optimization. Grouping common blocks at the front of the
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * config that are less likely to change between a request and
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * its subrequests, or between a request and its redirects reduced
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * the work of these functions significantly.
d94fadc8231669a4e710869f290ed57a8232a61drbowentypedef struct walk_walked_t {
a3388213b2b4d46b356be205e38204e67b4304d8rbowen ap_conf_vector_t *matched; /* A dir_conf sections we matched */
d94fadc8231669a4e710869f290ed57a8232a61drbowen ap_conf_vector_t *merged; /* The dir_conf merged result */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabeletypedef struct walk_cache_t {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele const char *cached; /* The identifier we matched */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_conf_vector_t **dir_conf_tested;/* The sections we matched against */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_conf_vector_t *dir_conf_merged;/* Base per_dir_config */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_conf_vector_t *per_dir_result; /* per_dir_config += walked result */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele apr_array_header_t *walked; /* The list of walk_walked_t results */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic walk_cache_t *prep_walk_cache(const char *cache_name, request_rec *r)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Find the most relevant, recent entry to work from. That would be
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * this request (on the second call), or the parent request of a
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * subrequest, or the prior request of an internal redirect. Provide
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * this _walk()er with a copy it is allowed to munge. If there is no
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * parent or prior cached request, then create a new walk cache.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((r->main && (apr_pool_userdata_get((void **)&cache,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele || (r->prev && (apr_pool_userdata_get((void **)&cache,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele cache = apr_pmemdup(r->pool, cache, sizeof(*cache));
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele cache->walked = apr_array_copy(r->pool, cache->walked);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t));
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/*****************************************************************
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Getting and checking directory configuration. Also checks the
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * FollowSymlinks and FollowSymOwner stuff, since this is really the
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * only place that can happen (barring a new mid_dir_walk callout).
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * We can't do it as an access_checker module function which gets
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * called with the final per_dir_config, since we could have a directory
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * with FollowSymLinks disabled, which contains a symlink to another
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * with a .htaccess file which turns FollowSymLinks back on --- and
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * access in such a case must be denied. So, whatever it is that
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * checks FollowSymLinks needs to know the state of the options as
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * they change, all the way down.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * We don't want people able to serve up pipes, or unix sockets, or other
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * scary things. Note that symlink tests are performed later.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "object is not a file, directory or symlink: %s",
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * resolve_symlink must _always_ be called on an APR_LNK file type!
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * It will resolve the actual target file type, modification date, etc,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * and provide any processing required for symlink evaluation.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Path must already be cleaned, no trailing slash, no multi-slashes,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * and don't call this on the root!
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Simply, the number of times we deref a symlink are minimal compared
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * to the number of times we had an extra lstat() since we 'weren't sure'.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * To optimize, we stat() anything when given (opts & OPT_SYM_LINKS), otherwise
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * we start off with an lstat(). Every lstat() must be dereferenced in case
cb8fcd00b37e588874a63102677d42687aab7b19trawick * it points at a 'nasty' - we must always rerun check_safe_file (or similar.)
2c44e52ec852d7d8392068fd13a1d8d8a4e830c1kessstatic int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((res = apr_stat(&fi, d, lfi->valid, p)) != APR_SUCCESS)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Give back the target */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* OPT_SYM_OWNER only works if we can get the owner of
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * both the file and symlink. First fill in a missing
cb8fcd00b37e588874a63102677d42687aab7b19trawick * owner of the symlink, then get the info of the target.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((res = apr_lstat(&fi, d, lfi->valid | APR_FINFO_OWNER, p))
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if ((res = apr_stat(&fi, d, lfi->valid, p)) != APR_SUCCESS)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (apr_compare_users(fi.user, lfi->user) != APR_SUCCESS)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Give back the target */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/*****************************************************************
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Getting and checking directory configuration. Also checks the
&core_module);
char *entry_dir;
return OK;
!= APR_SUCCESS) {
return OK;
* Otherwise (as is the case with most dir_merged/file_merged requests)
return OK;
return OK;
int sec_idx;
char *buf;
if (r->path_info)
r->path_info);
(const char **)&r->path_info,
sec_idx = 0;
int res;
char *seg_name;
char *delim;
if (matches) {
++last_walk;
--matches;
goto minimerge;
matches = 0;
if (now_merged)
* See core.c::merge_core_dir_configs() for explanation.
if (!this_dir)
if (res)
return res;
if (htaccess_conf) {
if (matches) {
++last_walk;
--matches;
goto minimerge2;
matches = 0;
if (now_merged)
* See core.c::merge_core_dir_configs() for explanation.
if (this_dir)
if (delim) {
++seg_name;
if (!*seg_name)
return res;
r->filename);
++seg;
if (!entry_core->r)
if (matches) {
++last_walk;
--matches;
goto minimerge;
matches = 0;
if (now_merged)
if (matches)
x * APR_DIR test. But if you accessed /symlink/index.html, for example,
if (now_merged)
r->per_dir_config,
return OK;
&core_module);
const char *entry_uri;
if (!num_sec) {
return OK;
/* Location and LocationMatch differ on their behaviour w.r.t. multiple
* Otherwise (as is the case with most dir_merged/file_merged requests)
return OK;
return OK;
if (entry_core->r
if (matches) {
++last_walk;
--matches;
matches = 0;
if (now_merged)
if (matches)
if (now_merged)
r->per_dir_config,
return OK;
&core_module);
const char *test_file;
return OK;
if (!num_sec) {
return OK;
return OK;
return OK;
int sec_idx;
if (entry_core->r
if (matches) {
++last_walk;
--matches;
matches = 0;
if (now_merged)
if (matches)
if (now_merged)
r->per_dir_config,
return OK;
return rr;
if (next_filter) {
if (APR_BUCKET_IS_EOS(e)) {
return APR_SUCCESS;
if (!reqs_arr)
const char *new_file,
const request_rec *r,
int res;
char *udir;
return rnew;
const request_rec *r,
const request_rec *r,
int res;
char *fdir;
char *udir;
return rnew;
return rnew;
const request_rec *r,
int res;
char *fdir;
return rnew;
return rnew;
int retval;
return retval;