core.c revision af8dee354a287249dd9f3f77bbe850108e5afe43
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* Copyright 2001-2004 The Apache Software Foundation
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * Licensed under the Apache License, Version 2.0 (the "License");
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * you may not use this file except in compliance with the License.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * You may obtain a copy of the License at
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * http://www.apache.org/licenses/LICENSE-2.0
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * Unless required by applicable law or agreed to in writing, software
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * distributed under the License is distributed on an "AS IS" BASIS,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * See the License for the specific language governing permissions and
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * limitations under the License.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#include "apr_thread_proc.h" /* for RLIMIT stuff */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#include "http_protocol.h" /* For index_of_response(). Grump. */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#include "http_main.h" /* For the default_handler below... */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* LimitXMLRequestBody handling */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#define AP_DEFAULT_LIMIT_XML_BODY ((size_t)1000000)
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae BungiuAP_IMPLEMENT_HOOK_RUN_ALL(int, get_mgmt_items,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu (apr_pool_t *p, const char *val, apr_hash_t *ht),
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* Server core module... This module provides support for really basic
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * server operations, including options and commands which control the
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * operation of other modules. Consider this the bureaucracy module.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * The core module also defines handlers, etc., do handle just enough
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * to allow a server with the core module ONLY to actually serve documents
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * (though it slaps DefaultType on all of 'em); this was useful in testing,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * but may not be worth preserving.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * This file could almost be mod_core.c, except for the stuff which affects
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * the http_conf_globals.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* Handles for core filters */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae BungiuAP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae BungiuAP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle;
9475501a6acf48434052d9e6f4a05ed6681eaaabFrancisc Nicolae BungiuAP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae BungiuAP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae BungiuAP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic void *create_core_dir_config(apr_pool_t *a, char *dir)
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu /* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->opts_add = conf->opts_remove = OPT_NONE;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu for (i = 0; i < METHODS; ++i) {
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->limit_xml_body = AP_LIMIT_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->server_signature = srv_sig_unset;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu /* Overriding all negotiation
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * Flag for use of inodes in ETags.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->enable_mmap = ENABLE_MMAP_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu return (void *)conf;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * Overlay one hash table of ct_output_filters onto another
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic void *merge_ct_filters(apr_pool_t *p,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu new->name = apr_pstrdup(p, overlay_info->name);
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance /* We can't have dups. */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu if (!strcasecmp(base_info->name, f->name)) {
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu f->name = apr_pstrdup(p, base_info->name);
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu core_dir_config *base = (core_dir_config *)basev;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu core_dir_config *new = (core_dir_config *)newv;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu /* Create this conf by duplicating the base, replacing elements
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * (or creating copies for merging) where new-> values exist.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu memcpy(conf, base, sizeof(core_dir_config));
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->d_is_fnmatch = new->d_is_fnmatch;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->d_components = new->d_components;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu /* there was no explicit setting of new->opts, so we merge
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * preserve the invariant (opts_add & opts_remove) == 0
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance conf->opts_remove = (conf->opts_remove & ~new->opts_add)
2713ec15465bd1e643f6310d7048b5a30ad55c83Christian Maeder conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
2713ec15465bd1e643f6310d7048b5a30ad55c83Christian Maeder conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance /* otherwise we just copy, because an explicit opts setting
2713ec15465bd1e643f6310d7048b5a30ad55c83Christian Maeder * overrides all earlier +/- modifiers
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance conf->ap_default_type = new->ap_default_type;
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance if (conf->response_code_strings == NULL) {
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance conf->response_code_strings = new->response_code_strings;
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance else if (new->response_code_strings != NULL) {
2713ec15465bd1e643f6310d7048b5a30ad55c83Christian Maeder /* If we merge, the merge-result must have it's own array
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance conf->response_code_strings = apr_palloc(a,
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance sizeof(*conf->response_code_strings) * RESPONSE_CODES);
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance memcpy(conf->response_code_strings, base->response_code_strings,
2713ec15465bd1e643f6310d7048b5a30ad55c83Christian Maeder sizeof(*conf->response_code_strings) * RESPONSE_CODES);
86f318f607745d1f40cbf87048a13ac1c65100e6Felix Gabriel Mance for (i = 0; i < RESPONSE_CODES; ++i) {
#ifdef RLIMIT_CPU
#ifdef RLIMIT_NPROC
for (i = 0; i < METHODS; ++i) {
NULL);
return (void*)conf;
#ifdef GPROF
return (void *)conf;
return conf;
&core_module);
&core_module);
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;
for (i = 0; i < METHODS; ++i) {
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
#ifdef AP_MPM_WANT_SET_STACKSIZE
{ 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 (AP_BUCKET_IS_EOC(e)) {
else 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;