core.c revision ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dc
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Copyright 2000-2004 Apache Software Foundation
842ae4bd224140319ae7feec1872b93dfd491143fielding * Licensed under the Apache License, Version 2.0 (the "License");
842ae4bd224140319ae7feec1872b93dfd491143fielding * you may not use this file except in compliance with the License.
842ae4bd224140319ae7feec1872b93dfd491143fielding * You may obtain a copy of the License at
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse#include "http_protocol.h" /* For index_of_response(). Grump. */
7933d4a963def02417113b6798d87a36395053b0rse#include "http_main.h" /* For the default_handler below... */
d1bb6e2664788e0437acc18e877562c9a796d7cerse/* LimitXMLRequestBody handling */
7933d4a963def02417113b6798d87a36395053b0rse/* Server core module... This module provides support for really basic
7933d4a963def02417113b6798d87a36395053b0rse * server operations, including options and commands which control the
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * operation of other modules. Consider this the bureaucracy module.
7933d4a963def02417113b6798d87a36395053b0rse * The core module also defines handlers, etc., do handle just enough
7933d4a963def02417113b6798d87a36395053b0rse * to allow a server with the core module ONLY to actually serve documents
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * (though it slaps DefaultType on all of 'em); this was useful in testing,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * but may not be worth preserving.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * This file could almost be mod_core.c, except for the stuff which affects
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe * the http_conf_globals.
7933d4a963def02417113b6798d87a36395053b0rse/* Handles for core filters */
7933d4a963def02417113b6798d87a36395053b0rseAP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle;
7933d4a963def02417113b6798d87a36395053b0rseAP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle;
7933d4a963def02417113b6798d87a36395053b0rseAP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle;
7933d4a963def02417113b6798d87a36395053b0rseAP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle;
7933d4a963def02417113b6798d87a36395053b0rseAP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle;
7933d4a963def02417113b6798d87a36395053b0rsestatic void *create_core_dir_config(apr_pool_t *a, char *dir)
7933d4a963def02417113b6798d87a36395053b0rse conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
e0c3fda9f782aee1140d83fbce32672ac299f2a4ben /* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
7933d4a963def02417113b6798d87a36395053b0rse#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
7933d4a963def02417113b6798d87a36395053b0rse conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
7933d4a963def02417113b6798d87a36395053b0rse conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
7efe7de73c89c26518714a504359244d03cfbbc5jorton /* Overriding all negotiation
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse * Flag for use of inodes in ETags.
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse return (void *)conf;
7933d4a963def02417113b6798d87a36395053b0rse * Overlay one hash table of ct_output_filters onto another
7933d4a963def02417113b6798d87a36395053b0rse const void *key,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse const void *overlay_val,
7933d4a963def02417113b6798d87a36395053b0rse const void *base_val,
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse const void *data)
a72de14bfdbf0be9d935be9bdc2df631ca5e032bdougm const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
a72de14bfdbf0be9d935be9bdc2df631ca5e032bdougm const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
cc003103e52ff9d5fe9bed567ef9438613ab4fbfrse /* We can't have dups. */
7933d4a963def02417113b6798d87a36395053b0rse while (f) {
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowestatic void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe /* Create this conf by duplicating the base, replacing elements
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe * (or creating copies for merging) where new-> values exist.
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
56bd16e394f49423a22aa82643eb27f26db2c748jorton /* there was no explicit setting of new->opts, so we merge
56bd16e394f49423a22aa82643eb27f26db2c748jorton * preserve the invariant (opts_add & opts_remove) == 0
56bd16e394f49423a22aa82643eb27f26db2c748jorton conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
56bd16e394f49423a22aa82643eb27f26db2c748jorton conf->opts_remove = (conf->opts_remove & ~new->opts_add)
e8f95a682820a599fe41b22977010636be5c2717jim conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
d1bb6e2664788e0437acc18e877562c9a796d7cerse /* otherwise we just copy, because an explicit opts setting
71c00f988beb28388702e14cb7fe06f08bd792bbdougm * overrides all earlier +/- modifiers
2b7078b0c4fd5b6054f6f2d4f626177844f5c6f7wrowe conf->response_code_strings = new->response_code_strings;
8dc154408549195c828b823e9dc7396f107f2512jorton /* If we merge, the merge-result must have it's own array
417f504d4d11631c0d062be85347f82a26c88677aaron sizeof(*conf->response_code_strings) * RESPONSE_CODES);
417f504d4d11631c0d062be85347f82a26c88677aaron memcpy(conf->response_code_strings, base->response_code_strings,
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm for (i = 0; i < RESPONSE_CODES; ++i) {
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm conf->response_code_strings[i] = new->response_code_strings[i];
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm /* Otherwise we simply use the base->response_code_strings array
cde1010d880fb6230f80c9d697842ea0b1cb79c7dougm if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm /* If we merge, the merge-result must have it's own array
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm conf->sec_file = apr_array_append(a, base->sec_file, new->sec_file);
a943533fd4d91d114af622731a405407990c4fb1rse /* Otherwise we simply use the base->sec_file array
a943533fd4d91d114af622731a405407990c4fb1rse if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
a943533fd4d91d114af622731a405407990c4fb1rse conf->add_default_charset_name = new->add_default_charset_name;
9cb81d96f6b556cec1aa456191f43f7932aabaaedougm /* Overriding all negotiation
2261f694ce2fc09f9df6c65bd8e1f4230313696bjorton if (conf->ct_output_filters && new->ct_output_filters) {
a943533fd4d91d114af622731a405407990c4fb1rse conf->ct_output_filters = apr_hash_copy(a, new->ct_output_filters);
931b4fd1cc9dd3da096c45f4bf7ddcc14e0985c1dougm /* That memcpy above isn't enough. */
a943533fd4d91d114af622731a405407990c4fb1rse conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
a943533fd4d91d114af622731a405407990c4fb1rse * Now merge the setting of the FileETag directive.
a943533fd4d91d114af622731a405407990c4fb1rse (conf->etag_add & (~ new->etag_remove)) | new->etag_add;
a943533fd4d91d114af622731a405407990c4fb1rse (conf->opts_remove & (~ new->etag_add)) | new->etag_remove;
7933d4a963def02417113b6798d87a36395053b0rse (conf->etag_bits & (~ conf->etag_remove)) | conf->etag_add;
71c00f988beb28388702e14cb7fe06f08bd792bbdougm conf->allow_encoded_slashes = new->allow_encoded_slashes;
7933d4a963def02417113b6798d87a36395053b0rse return (void*)conf;
e726f34f8da08c01ee8bc90904b26196b69c8587wrowestatic void *create_core_server_config(apr_pool_t *a, server_rec *s)
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe /* recursion stopper */
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe return (void *)conf;
e726f34f8da08c01ee8bc90904b26196b69c8587wrowestatic void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe core_server_config *base = (core_server_config *)basev;
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe core_server_config *virt = (core_server_config *)virtv;
2261f694ce2fc09f9df6c65bd8e1f4230313696bjorton conf = (core_server_config *)apr_palloc(p, sizeof(core_server_config));
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
ccbf65bf19ac58a396133923aee4597e0870ec47bnicholes conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
825479074daa2c65852666c4b26d771dff957507jorton/* Add per-directory configuration entry (for <directory> section);
825479074daa2c65852666c4b26d771dff957507jorton * these are part of the core server config.
a943533fd4d91d114af622731a405407990c4fb1rseAP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
a943533fd4d91d114af622731a405407990c4fb1rse core_server_config *sconf = ap_get_module_config(s->module_config,
a943533fd4d91d114af622731a405407990c4fb1rse void **new_space = (void **)apr_array_push(sconf->sec_dir);
a943533fd4d91d114af622731a405407990c4fb1rseAP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config)
825479074daa2c65852666c4b26d771dff957507jorton core_server_config *sconf = ap_get_module_config(s->module_config,
e726f34f8da08c01ee8bc90904b26196b69c8587wrowe void **new_space = (void **)apr_array_push(sconf->sec_url);
621bd763d2e4d32f19013ac8b76b375b5a01851fdougmAP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
7933d4a963def02417113b6798d87a36395053b0rse void **new_space = (void **)apr_array_push(conf->sec_file);
7933d4a963def02417113b6798d87a36395053b0rse/* We need to do a stable sort, qsort isn't stable. So to make it stable
7933d4a963def02417113b6798d87a36395053b0rse * we'll be maintaining the original index into the list, and using it
7933d4a963def02417113b6798d87a36395053b0rse * as the minor key during sorting. The major key is the number of
7933d4a963def02417113b6798d87a36395053b0rse * components (where the root component is zero).
struct reorder_sort_rec {
int orig_index;
int nelts;
if (!nelts) {
for (i = 0; i < nelts; ++i) {
for (i = 0; i < nelts; ++i) {
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
return NULL;
while (sa) {
int hostname_lookups;
int ignored_str_is_ip;
*str_is_ip = 0;
if (dir_config) {
== APR_SUCCESS) {
return NULL;
return NULL;
if (ident_lookup) {
return ident_lookup(r);
return NULL;
core_dir_config *d;
&core_module);
#if APR_HAVE_IPV6
return plain_server_name;
core_dir_config *d =
ap_default_port(r);
ap_default_port(r);
return port;
request_rec *r)
core_dir_config *d =
return d->limit_req_body;
* Commands... this module handles almost all of the NCSA httpd.conf
* commands, but most of the old srm.conf is in the the modules.
const char *what)
return dirp;
return NULL;
unsigned forbidden)
return NULL;
return NULL;
const char *arg)
return err;
return NULL;
#ifdef GPROF
return err;
return NULL;
return err;
return NULL;
const char *arg)
return err;
arg);
return NULL;
const char *string)
int idx;
return err;
* http_protocol.c relies on to distinguish between
return NULL;
return err;
return NULL;
char action;
action = *(w++);
else if (first) {
first = 0;
return NULL;
const char *args_p)
char action;
char *token;
const char *args;
int valid;
int first;
int explicit;
explicit = 0;
token++;
if (first) {
first = 0;
valid = 0;
valid = 0;
if (! valid) {
NULL);
if (explicit) {
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return NULL;
require_line *r;
if (!c->ap_requires) {
return NULL;
void *dummy,
const char *arg)
const char *limited_methods;
const char *errmsg;
return err;
while (limited_methods[0]) {
int methnum;
return errmsg;
#ifdef WIN32
#define USE_ICASE 0
const char *errmsg;
return err;
if (!arg) {
char *newpath;
return errmsg;
conf->r = r;
return NULL;
const char *errmsg;
return err;
return errmsg;
conf->r = r;
return NULL;
const char *errmsg;
return err;
if (!old_path) {
char *newpath;
return errmsg;
conf->r = r;
return NULL;
if (not) {
arg++;
const char *retval;
return retval;
char **defines;
const char *endp;
int not = 0;
arg++;
const char *retval;
return retval;
/* httpd.conf commands... beginning with the <VirtualHost> business */
const char *arg)
const char *errmsg;
return err;
if (errmsg) {
return errmsg;
s->lookup_defaults);
return errmsg;
const char *arg)
while (*arg) {
return NULL;
const char *arg)
return err;
return NULL;
const char *portstr;
int port;
return err;
if (portstr) {
portstr++;
port = 0;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
return NULL;
const char *arg)
return err;
return NULL;
const char *name)
if (!conffile) {
return NULL;
char *str;
return err;
return NULL;
&core_module);
const char *word1)
return NULL;
static int version_locked = 0;
enum server_token_type {
version_locked = 0;
return APR_SUCCESS;
if (! version_locked) {
const char *arg)
return err;
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
NULL);
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
NULL);
return NULL;
const char *arg)
char *errp;
return err;
* Instead we have an idiotic define in httpd.h that prevents
return NULL;
const char *arg)
return err;
return NULL;
return AP_DEFAULT_LIMIT_XML_BODY;
#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
return NULL;
#ifdef RLIMIT_CPU
return NULL;
#if defined(RLIMIT_AS)
return NULL;
#ifdef RLIMIT_NPROC
return NULL;
&core_module);
if (limit <= 0) {
if (arg2) {
if (limit <= 0) {
return NULL;
&core_module);
log_backtrace(r);
log_backtrace(r);
const char *filter_name;
if (old) {
while (*arg &&
if (old) {
if (!new) {
return NULL;
const char *ctype;
&core_module);
if (ctype) {
while (ct_filter) {
*nbytes = 0;
*nbytes += n;
bytes_written += n;
return rv;
if (n < cnt) {
return APR_SUCCESS;
#if APR_HAS_SENDFILE
#ifdef AP_DEBUG
== APR_SUCCESS)
*bytes_sent = 0;
flags);
tmplen = 0;
file_bytes_left = 0;
file_offset = 0;
tmplen = 0;
apr_int32_t i;
*nbytes = 0;
sendlen = 0;
return rv;
#ifdef GPROF
"Set to on or off for PATH_INFO to be accepted by handlers, or default for the per-handler preference"),
#ifdef RLIMIT_CPU
#ifdef RLIMIT_NPROC
* #defined them in mpm.h.
#ifdef AP_MPM_WANT_SET_PIDFILE
#ifdef AP_MPM_WANT_SET_SCOREBOARD
#ifdef AP_MPM_WANT_SET_LOCKFILE
#ifdef AP_MPM_WANT_SET_MAX_REQUESTS
#ifdef AP_MPM_WANT_SET_COREDUMPDIR
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
{ NULL }
if (r->proxyreq) {
return HTTP_FORBIDDEN;
return HTTP_BAD_REQUEST;
/* skip all leading /'s (e.g. http://localhost///foo)
++path;
!= APR_SUCCESS) {
return HTTP_FORBIDDEN;
/* skip all leading /'s (e.g. http://localhost///foo)
++path;
!= APR_SUCCESS) {
return HTTP_FORBIDDEN;
return OK;
int access_status;
return access_status;
return access_status;
return OK;
&core_module);
return OK;
apr_bucket *e;
core_dir_config *d;
int errstatus;
int bld_content_md5;
&core_module);
return errstatus;
return HTTP_NOT_FOUND;
return HTTP_NOT_FOUND;
return HTTP_NOT_FOUND;
r->method);
return HTTP_METHOD_NOT_ALLOWED;
#if APR_HAS_SENDFILE
? 0 : APR_SENDFILE_ENABLED)
return HTTP_FORBIDDEN;
ap_set_etag(r);
return errstatus;
if (bld_content_md5) {
#if APR_HAS_SENDFILE
c->bucket_alloc);
#if APR_HAS_MMAP
(void)apr_bucket_file_enable_mmap(e, 0);
return HTTP_NOT_IMPLEMENTED;
return ap_send_http_options(r);
return HTTP_METHOD_NOT_ALLOWED;
typedef struct net_time_filter_ctx {
int first_line;
if (!ctx) {
if (keptalive) {
#define BRIGADE_NORMALIZE(b) \
apr_bucket *d; \
d = APR_BUCKET_NEXT(e); \
apr_bucket_delete(e); \
e = APR_BUCKET_NEXT(e); \
apr_bucket *e;
const char *str;
return APR_SUCCESS;
if (!ctx)
return APR_EOF;
return APR_EOF;
return rv;
apr_bucket *e;
return APR_EOF;
return rv;
c = str;
if (*c == APR_ASCII_LF)
return APR_SUCCESS;
return APR_SUCCESS;
apr_bucket *e;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
apr_bucket *e;
return APR_SUCCESS;
return rv;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
return rv;
e = APR_BUCKET_NEXT(e))
return rv;
return APR_SUCCESS;
conn_rec *c = f->c;
if (ctx->b) {
b = ctx->b;
while (b && !APR_BRIGADE_EMPTY(b)) {
apr_bucket *e;
for (e = APR_BRIGADE_FIRST(b);
e != APR_BRIGADE_SENTINEL(b);
e = APR_BUCKET_NEXT(e))
last_e = e;
if (APR_BUCKET_IS_EOS(e)) {
if (APR_BUCKET_IS_FLUSH(e)) {
if (e != APR_BRIGADE_LAST(b)) {
else if (APR_BUCKET_IS_FILE(e)
if (fd) {
const char *str;
apr_size_t n;
if (!fd) {
if (last_merged_bucket) {
temp_brig = b;
b = bb;
f->c->bucket_alloc);
while (temp != e) {
apr_bucket *d;
d = temp;
nvec = 0;
nbytes = 0;
nvec++;
nvec++;
e = temp;
last_e = e;
nvec++;
nbytes += n;
int file_bucket_saved = 0;
const char *buf;
return HTTP_INTERNAL_SERVER_ERROR;
return APR_SUCCESS;
if (fd) {
#if APR_HAS_SENDFILE
if (nvec) {
if (nvec_trailers) {
#if APR_HAS_SENDFILE
&bytes_sent);
if (more)
return APR_SUCCESS;
b = more;
return APR_SUCCESS;
return OK;
&core_module);
if (filters) {
if (filters) {
return APR_SUCCESS;
return num_request_notes++;
return NULL;
if (!req_cfg) {
return NULL;
sizeof(void *) * num_request_notes);
if (r->main) {
if (!r->prev) {
return OK;
!= APR_SUCCESS) {
return NULL;
!= APR_SUCCESS) {
return NULL;
net->c = c;
return DONE;