|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
|
Packit Service |
384592 |
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* You may not use this file except in compliance with
|
|
Packit Service |
384592 |
* the License. You may obtain a copy of the License at
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* If any of the files related to licensing are missing or if you have any
|
|
Packit Service |
384592 |
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
Packit Service |
384592 |
* directly using the email address security@modsecurity.org.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include <limits.h>
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "http_core.h"
|
|
Packit Service |
384592 |
#include "http_request.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "modsecurity.h"
|
|
Packit Service |
384592 |
#include "apache2.h"
|
|
Packit Service |
384592 |
#include "http_main.h"
|
|
Packit Service |
384592 |
#include "http_connection.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "apr_optional.h"
|
|
Packit Service |
384592 |
#include "mod_log_config.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "msc_logging.h"
|
|
Packit Service |
384592 |
#include "msc_util.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "ap_mpm.h"
|
|
Packit Service |
384592 |
#include "scoreboard.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "apr_version.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "apr_lib.h"
|
|
Packit Service |
384592 |
#include "ap_config.h"
|
|
Packit Service |
384592 |
#include "http_config.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#define FILTER_POOL apr_hook_global_pool
|
|
Packit Service |
384592 |
#include "apr_hooks.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
** This macro returns true/false if a given filter should be inserted BEFORE
|
|
Packit Service |
384592 |
** another filter. This will happen when one of: 1) there isn't another
|
|
Packit Service |
384592 |
** filter; 2) that filter has a higher filter type (class); 3) that filter
|
|
Packit Service |
384592 |
** corresponds to a different request.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
|
|
Packit Service |
384592 |
|| (before_this)->frec->ftype > (f)->frec->ftype \
|
|
Packit Service |
384592 |
|| (before_this)->r != (f)->r)
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_table_t *ms_input_filters = NULL;
|
|
Packit Service |
384592 |
apr_table_t *ms_output_filters = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
void init_filter_tables()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if(ms_input_filters == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ms_input_filters = apr_table_make(FILTER_POOL, 10);
|
|
Packit Service |
384592 |
ms_output_filters = apr_table_make(FILTER_POOL, 10);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
|
|
Packit Service |
384592 |
ap_in_filter_func filter_func,
|
|
Packit Service |
384592 |
ap_init_filter_func filter_init,
|
|
Packit Service |
384592 |
ap_filter_type ftype)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_filter_rec_t *f;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
init_filter_tables();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f = apr_palloc(FILTER_POOL, sizeof(ap_filter_rec_t));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f->filter_func.in_func = filter_func;
|
|
Packit Service |
384592 |
f->filter_init_func = filter_init;
|
|
Packit Service |
384592 |
f->ftype = ftype;
|
|
Packit Service |
384592 |
f->name = name;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_table_setn(ms_input_filters, name, (const char *)f);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
|
|
Packit Service |
384592 |
ap_out_filter_func filter_func,
|
|
Packit Service |
384592 |
ap_init_filter_func filter_init,
|
|
Packit Service |
384592 |
ap_filter_type ftype)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_filter_rec_t *f;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
init_filter_tables();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f = apr_palloc(FILTER_POOL, sizeof(ap_filter_rec_t));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f->filter_func.out_func = filter_func;
|
|
Packit Service |
384592 |
f->filter_init_func = filter_init;
|
|
Packit Service |
384592 |
f->ftype = ftype;
|
|
Packit Service |
384592 |
f->name = name;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_table_setn(ms_output_filters, name, (const char *)f);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
|
|
Packit Service |
384592 |
request_rec *r, conn_rec *c,
|
|
Packit Service |
384592 |
ap_filter_t **r_filters,
|
|
Packit Service |
384592 |
ap_filter_t **p_filters,
|
|
Packit Service |
384592 |
ap_filter_t **c_filters)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
apr_pool_t* p = r ? r->pool : c->pool;
|
|
Packit Service |
384592 |
ap_filter_t *f = apr_palloc(p, sizeof(*f));
|
|
Packit Service |
384592 |
ap_filter_t **outf;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (frec->ftype < AP_FTYPE_PROTOCOL) {
|
|
Packit Service |
384592 |
if (r) {
|
|
Packit Service |
384592 |
outf = r_filters;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
Packit Service |
384592 |
"a content filter was added without a request: %s", frec->name);
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else if (frec->ftype < AP_FTYPE_CONNECTION) {
|
|
Packit Service |
384592 |
if (r) {
|
|
Packit Service |
384592 |
outf = p_filters;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
Packit Service |
384592 |
"a protocol filter was added without a request: %s", frec->name);
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
outf = c_filters;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f->frec = frec;
|
|
Packit Service |
384592 |
f->ctx = ctx;
|
|
Packit Service |
384592 |
f->r = r;
|
|
Packit Service |
384592 |
f->c = c;
|
|
Packit Service |
384592 |
f->next = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (INSERT_BEFORE(f, *outf)) {
|
|
Packit Service |
384592 |
f->next = *outf;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (*outf) {
|
|
Packit Service |
384592 |
ap_filter_t *first = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (r) {
|
|
Packit Service |
384592 |
/* If we are adding our first non-connection filter,
|
|
Packit Service |
384592 |
* Then don't try to find the right location, it is
|
|
Packit Service |
384592 |
* automatically first.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
if (*r_filters != *c_filters) {
|
|
Packit Service |
384592 |
first = *r_filters;
|
|
Packit Service |
384592 |
while (first && (first->next != (*outf))) {
|
|
Packit Service |
384592 |
first = first->next;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
if (first && first != (*outf)) {
|
|
Packit Service |
384592 |
first->next = f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
*outf = f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else {
|
|
Packit Service |
384592 |
ap_filter_t *fscan = *outf;
|
|
Packit Service |
384592 |
while (!INSERT_BEFORE(f, fscan->next))
|
|
Packit Service |
384592 |
fscan = fscan->next;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
f->next = fscan->next;
|
|
Packit Service |
384592 |
fscan->next = f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
|
|
Packit Service |
384592 |
*r_filters = *p_filters;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return f;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
|
|
Packit Service |
384592 |
request_rec *r, conn_rec *c)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_filter_rec_t *f = (ap_filter_rec_t *)apr_table_get(ms_input_filters, name);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(f == NULL)
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return add_any_filter_handle(f, ctx, r, c,
|
|
Packit Service |
384592 |
r ? &r->input_filters : NULL,
|
|
Packit Service |
384592 |
r ? &r->proto_input_filters : NULL, &c->input_filters);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
|
|
Packit Service |
384592 |
request_rec *r, conn_rec *c)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_filter_rec_t *f = (ap_filter_rec_t *)apr_table_get(ms_output_filters, name);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(f == NULL)
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return add_any_filter_handle(f, ctx, r, c,
|
|
Packit Service |
384592 |
r ? &r->output_filters : NULL,
|
|
Packit Service |
384592 |
r ? &r->proto_output_filters : NULL, &c->output_filters);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
|
|
Packit Service |
384592 |
ap_filter_t **c_filt)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
ap_filter_t **curr = r_filt ? r_filt : c_filt;
|
|
Packit Service |
384592 |
ap_filter_t *fscan = *curr;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (p_filt && *p_filt == f)
|
|
Packit Service |
384592 |
*p_filt = (*p_filt)->next;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (*curr == f) {
|
|
Packit Service |
384592 |
*curr = (*curr)->next;
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
while (fscan->next != f) {
|
|
Packit Service |
384592 |
if (!(fscan = fscan->next)) {
|
|
Packit Service |
384592 |
return;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
fscan->next = f->next;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
|
|
Packit Service |
384592 |
f->r ? &f->r->proto_input_filters : NULL,
|
|
Packit Service |
384592 |
&f->c->input_filters);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
|
|
Packit Service |
384592 |
f->r ? &f->r->proto_output_filters : NULL,
|
|
Packit Service |
384592 |
&f->c->output_filters);
|
|
Packit Service |
384592 |
}
|