Blame standalone/filters.c

Packit 284210
/*
Packit 284210
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
Packit 284210
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Packit 284210
*
Packit 284210
* You may not use this file except in compliance with
Packit 284210
* the License.  You may obtain a copy of the License at
Packit 284210
*
Packit 284210
*     http://www.apache.org/licenses/LICENSE-2.0
Packit 284210
*
Packit 284210
* If any of the files related to licensing are missing or if you have any
Packit 284210
* other questions related to licensing please contact Trustwave Holdings, Inc.
Packit 284210
* directly using the email address security@modsecurity.org.
Packit 284210
*/
Packit 284210

Packit 284210
#include <limits.h>
Packit 284210

Packit 284210
#include "http_core.h"
Packit 284210
#include "http_request.h"
Packit 284210

Packit 284210
#include "modsecurity.h"
Packit 284210
#include "apache2.h"
Packit 284210
#include "http_main.h"
Packit 284210
#include "http_connection.h"
Packit 284210

Packit 284210
#include "apr_optional.h"
Packit 284210
#include "mod_log_config.h"
Packit 284210

Packit 284210
#include "msc_logging.h"
Packit 284210
#include "msc_util.h"
Packit 284210

Packit 284210
#include "ap_mpm.h"
Packit 284210
#include "scoreboard.h"
Packit 284210

Packit 284210
#include "apr_version.h"
Packit 284210

Packit 284210
#include "apr_lib.h"
Packit 284210
#include "ap_config.h"
Packit 284210
#include "http_config.h"
Packit 284210

Packit 284210
#define	FILTER_POOL	apr_hook_global_pool
Packit 284210
#include "apr_hooks.h"
Packit 284210

Packit 284210
/*
Packit 284210
** This macro returns true/false if a given filter should be inserted BEFORE
Packit 284210
** another filter. This will happen when one of: 1) there isn't another
Packit 284210
** filter; 2) that filter has a higher filter type (class); 3) that filter
Packit 284210
** corresponds to a different request.
Packit 284210
*/
Packit 284210
#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
Packit 284210
                           || (before_this)->frec->ftype > (f)->frec->ftype \
Packit 284210
                           || (before_this)->r != (f)->r)
Packit 284210

Packit 284210

Packit 284210
apr_table_t *ms_input_filters = NULL;
Packit 284210
apr_table_t *ms_output_filters = NULL;
Packit 284210

Packit 284210
void init_filter_tables()
Packit 284210
{
Packit 284210
	if(ms_input_filters == NULL)
Packit 284210
	{
Packit 284210
		ms_input_filters = apr_table_make(FILTER_POOL, 10);
Packit 284210
		ms_output_filters = apr_table_make(FILTER_POOL, 10);
Packit 284210
	}
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
Packit 284210
                                          ap_in_filter_func filter_func,
Packit 284210
                                          ap_init_filter_func filter_init,
Packit 284210
                                          ap_filter_type ftype)
Packit 284210
{
Packit 284210
	ap_filter_rec_t *f;
Packit 284210

Packit 284210
	init_filter_tables();
Packit 284210
	
Packit 284210
	f = apr_palloc(FILTER_POOL, sizeof(ap_filter_rec_t));
Packit 284210

Packit 284210
	f->filter_func.in_func = filter_func;
Packit 284210
	f->filter_init_func = filter_init;
Packit 284210
	f->ftype = ftype;
Packit 284210
	f->name = name;
Packit 284210

Packit 284210
	apr_table_setn(ms_input_filters, name, (const char *)f);
Packit 284210

Packit 284210
	return f;
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
Packit 284210
                                            ap_out_filter_func filter_func,
Packit 284210
                                            ap_init_filter_func filter_init,
Packit 284210
                                            ap_filter_type ftype)
Packit 284210
{
Packit 284210
	ap_filter_rec_t *f;
Packit 284210
	
Packit 284210
	init_filter_tables();
Packit 284210
	
Packit 284210
	f = apr_palloc(FILTER_POOL, sizeof(ap_filter_rec_t));
Packit 284210

Packit 284210
	f->filter_func.out_func = filter_func;
Packit 284210
	f->filter_init_func = filter_init;
Packit 284210
	f->ftype = ftype;
Packit 284210
	f->name = name;
Packit 284210

Packit 284210
	apr_table_setn(ms_output_filters, name, (const char *)f);
Packit 284210

Packit 284210
	return f;
Packit 284210
}
Packit 284210

Packit 284210
static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
Packit 284210
                                          request_rec *r, conn_rec *c,
Packit 284210
                                          ap_filter_t **r_filters,
Packit 284210
                                          ap_filter_t **p_filters,
Packit 284210
                                          ap_filter_t **c_filters)
Packit 284210
{
Packit 284210
    apr_pool_t* p = r ? r->pool : c->pool;
Packit 284210
    ap_filter_t *f = apr_palloc(p, sizeof(*f));
Packit 284210
    ap_filter_t **outf;
Packit 284210

Packit 284210
    if (frec->ftype < AP_FTYPE_PROTOCOL) {
Packit 284210
        if (r) {
Packit 284210
            outf = r_filters;
Packit 284210
        }
Packit 284210
        else {
Packit 284210
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
Packit 284210
                      "a content filter was added without a request: %s", frec->name);
Packit 284210
            return NULL;
Packit 284210
        }
Packit 284210
    }
Packit 284210
    else if (frec->ftype < AP_FTYPE_CONNECTION) {
Packit 284210
        if (r) {
Packit 284210
            outf = p_filters;
Packit 284210
        }
Packit 284210
        else {
Packit 284210
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
Packit 284210
                         "a protocol filter was added without a request: %s", frec->name);
Packit 284210
            return NULL;
Packit 284210
        }
Packit 284210
    }
Packit 284210
    else {
Packit 284210
        outf = c_filters;
Packit 284210
    }
Packit 284210

Packit 284210
    f->frec = frec;
Packit 284210
    f->ctx = ctx;
Packit 284210
    f->r = r;
Packit 284210
    f->c = c;
Packit 284210
    f->next = NULL;
Packit 284210

Packit 284210
    if (INSERT_BEFORE(f, *outf)) {
Packit 284210
        f->next = *outf;
Packit 284210

Packit 284210
        if (*outf) {
Packit 284210
            ap_filter_t *first = NULL;
Packit 284210

Packit 284210
            if (r) {
Packit 284210
                /* If we are adding our first non-connection filter,
Packit 284210
                 * Then don't try to find the right location, it is
Packit 284210
                 * automatically first.
Packit 284210
                 */
Packit 284210
                if (*r_filters != *c_filters) {
Packit 284210
                    first = *r_filters;
Packit 284210
                    while (first && (first->next != (*outf))) {
Packit 284210
                        first = first->next;
Packit 284210
                    }
Packit 284210
                }
Packit 284210
            }
Packit 284210
            if (first && first != (*outf)) {
Packit 284210
                first->next = f;
Packit 284210
            }
Packit 284210
        }
Packit 284210
        *outf = f;
Packit 284210
    }
Packit 284210
    else {
Packit 284210
        ap_filter_t *fscan = *outf;
Packit 284210
        while (!INSERT_BEFORE(f, fscan->next))
Packit 284210
            fscan = fscan->next;
Packit 284210

Packit 284210
        f->next = fscan->next;
Packit 284210
        fscan->next = f;
Packit 284210
    }
Packit 284210

Packit 284210
    if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
Packit 284210
        *r_filters = *p_filters;
Packit 284210
    }
Packit 284210
    return f;
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
Packit 284210
                                              request_rec *r, conn_rec *c)
Packit 284210
{
Packit 284210
	ap_filter_rec_t *f = (ap_filter_rec_t *)apr_table_get(ms_input_filters, name);
Packit 284210

Packit 284210
	if(f == NULL)
Packit 284210
		return NULL;
Packit 284210

Packit 284210
	return add_any_filter_handle(f, ctx, r, c,
Packit 284210
                          r ? &r->input_filters : NULL,
Packit 284210
                          r ? &r->proto_input_filters : NULL, &c->input_filters);
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx, 
Packit 284210
                                               request_rec *r, conn_rec *c)
Packit 284210
{
Packit 284210
	ap_filter_rec_t *f = (ap_filter_rec_t *)apr_table_get(ms_output_filters, name);
Packit 284210

Packit 284210
	if(f == NULL)
Packit 284210
		return NULL;
Packit 284210

Packit 284210
    return add_any_filter_handle(f, ctx, r, c,
Packit 284210
                          r ? &r->output_filters : NULL,
Packit 284210
                          r ? &r->proto_output_filters : NULL, &c->output_filters);
Packit 284210
}
Packit 284210

Packit 284210
static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
Packit 284210
                              ap_filter_t **c_filt)
Packit 284210
{
Packit 284210
    ap_filter_t **curr = r_filt ? r_filt : c_filt;
Packit 284210
    ap_filter_t *fscan = *curr;
Packit 284210

Packit 284210
    if (p_filt && *p_filt == f)
Packit 284210
        *p_filt = (*p_filt)->next;
Packit 284210

Packit 284210
    if (*curr == f) {
Packit 284210
        *curr = (*curr)->next;
Packit 284210
        return;
Packit 284210
    }
Packit 284210

Packit 284210
    while (fscan->next != f) {
Packit 284210
        if (!(fscan = fscan->next)) {
Packit 284210
            return;
Packit 284210
        }
Packit 284210
    }
Packit 284210

Packit 284210
    fscan->next = f->next;
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
Packit 284210
{
Packit 284210
    remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
Packit 284210
                      f->r ? &f->r->proto_input_filters : NULL,
Packit 284210
                      &f->c->input_filters);
Packit 284210
}
Packit 284210

Packit 284210
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
Packit 284210
{
Packit 284210
    remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
Packit 284210
                      f->r ? &f->r->proto_output_filters : NULL,
Packit 284210
                      &f->c->output_filters);
Packit 284210
}