Blame ext/mod_op_strstr.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 "httpd.h"
Packit 284210
#include "http_core.h"
Packit 284210
#include "http_config.h"
Packit 284210
#include "http_log.h"
Packit 284210
#include "http_protocol.h"
Packit 284210
#include "ap_config.h"
Packit 284210
#include "apr_optional.h"
Packit 284210
Packit 284210
#include "modsecurity.h"
Packit 284210
Packit 284210
#define ALPHABET_SIZE       256
Packit 284210
#define MAX_PATTERN_SIZE    64
Packit 284210
Packit 284210
static void initBoyerMooreHorspool(const char *pattern, int patlength,
Packit 284210
    int *bm_badcharacter_array);
Packit 284210
Packit 284210
static int BoyerMooreHorspool(const char *pattern, int patlength,
Packit 284210
    const char *text, int textlen, int *bm_badcharacter_array);
Packit 284210
Packit 284210
/**
Packit 284210
 * Operator parameter initialisation entry point.
Packit 284210
 */
Packit 284210
static int op_strstr_init(msre_rule *rule, char **error_msg) {
Packit 284210
    /* Operator initialisation function will be called once per
Packit 284210
     * statement where operator is used. It is meant to be used
Packit 284210
     * to check the parameters to see whether they are present
Packit 284210
     * and if they are in the correct format.
Packit 284210
     */
Packit 284210
Packit 284210
    /* In this example we just look for a simple non-empty parameter. */
Packit 284210
    if ((rule->op_param == NULL)||(strlen(rule->op_param) == 0)) {
Packit 284210
        *error_msg = apr_psprintf(rule->ruleset->mp, "Missing parameter for operator 'strstr'.");
Packit 284210
        return 0; /* ERROR */
Packit 284210
    }
Packit 284210
Packit 284210
    /* If you need to transform the data in the parameter into something
Packit 284210
     * else you should do that here. Simply create a new structure to hold
Packit 284210
     * the transformed data and place the pointer to it into rule->op_param_data.
Packit 284210
     * You will have access to this pointer later on.
Packit 284210
     */
Packit 284210
    rule->op_param_data = apr_pcalloc(rule->ruleset->mp, ALPHABET_SIZE * sizeof(int));
Packit 284210
    initBoyerMooreHorspool(rule->op_param, strlen(rule->op_param), (int *)rule->op_param_data);
Packit 284210
Packit 284210
    /* OK */
Packit 284210
    return 1;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Operator execution entry point.
Packit 284210
 */
Packit 284210
static int op_strstr_exec(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
Packit 284210
    /* Here we need to inspect the contents of the supplied variable. */
Packit 284210
Packit 284210
    /* In a general case it is possible for the value
Packit 284210
     * to be NULL. What you need to do in this case
Packit 284210
     * depends on your operator. In this example we return
Packit 284210
     * a "no match" response.
Packit 284210
     */
Packit 284210
    if (var->value == NULL) return 0; /* No match. */
Packit 284210
Packit 284210
    /* Another thing to note is that variables are not C strings,
Packit 284210
     * meaning the NULL byte is not used to determine the end
Packit 284210
     * of the string. Variable length var->value_len should be
Packit 284210
     * used for this purpose.
Packit 284210
     */
Packit 284210
Packit 284210
    if (BoyerMooreHorspool(rule->op_param, strlen(rule->op_param),
Packit 284210
        var->value, var->value_len, (int *)rule->op_param_data) >= 0)
Packit 284210
    {
Packit 284210
        return 1; /* Match. */
Packit 284210
    }
Packit 284210
    
Packit 284210
    return 0; /* No match. */
Packit 284210
}
Packit 284210
Packit 284210
static int hook_pre_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_temp) {
Packit 284210
    void (*fn)(const char *name, void *fn_init, void *fn_exec);
Packit 284210
Packit 284210
    /* Look for the registration function
Packit 284210
     * exported by ModSecurity.
Packit 284210
     */
Packit 284210
    fn = APR_RETRIEVE_OPTIONAL_FN(modsec_register_operator);
Packit 284210
    if (fn) {
Packit 284210
        /* Use it to register our new
Packit 284210
         * transformation function under the
Packit 284210
         * name "reverse".
Packit 284210
         */
Packit 284210
        fn("strstr", (void *)op_strstr_init, (void *)op_strstr_exec);
Packit 284210
    } else {
Packit 284210
        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
Packit 284210
            "mod_op_strstr: Unable to find modsec_register_operator.");
Packit 284210
    }
Packit 284210
Packit 284210
    return OK;
Packit 284210
}
Packit 284210
Packit 284210
static void register_hooks(apr_pool_t *p) {
Packit 284210
    ap_hook_pre_config(hook_pre_config, NULL, NULL, APR_HOOK_LAST);
Packit 284210
}
Packit 284210
Packit 284210
/* Dispatch list for API hooks */
Packit 284210
module AP_MODULE_DECLARE_DATA op_strstr_module = {
Packit 284210
    STANDARD20_MODULE_STUFF, 
Packit 284210
    NULL,                  /* create per-dir    config structures */
Packit 284210
    NULL,                  /* merge  per-dir    config structures */
Packit 284210
    NULL,                  /* create per-server config structures */
Packit 284210
    NULL,                  /* merge  per-server config structures */
Packit 284210
    NULL,                  /* table of config file commands       */
Packit 284210
    register_hooks         /* register hooks                      */
Packit 284210
};
Packit 284210
Packit 284210
/*
Packit 284210
Packit 284210
This example uses an implementation Boyer-Moore-Horspool
Packit 284210
matching algorithm as implemented in Streamline (http://ffpf.sourceforge.net).
Packit 284210
Packit 284210
Copyright (c) 2004-2006, Vrije Universiteit Amsterdam
Packit 284210
All rights reserved.
Packit 284210
Packit 284210
Redistribution and use in source and binary forms, with or without modification, 
Packit 284210
are permitted provided that the following conditions are met:
Packit 284210
Packit 284210
Redistributions of source code must retain the above copyright notice, 
Packit 284210
this list of conditions and the following disclaimer.
Packit 284210
Packit 284210
Redistributions in binary form must reproduce the above copyright notice, 
Packit 284210
this list of conditions and the following disclaimer in the documentation 
Packit 284210
and/or other materials provided with the distribution.
Packit 284210
Packit 284210
Neither the name of the Vrije Universiteit nor the names of its contributors 
Packit 284210
may be used to endorse or promote products derived from this software without 
Packit 284210
specific prior written permission.
Packit 284210
Packit 284210
*/
Packit 284210
Packit 284210
static void precompute_badcharacter(const char *pattern, int patlength,
Packit 284210
    int bm_badcharacter_array[])
Packit 284210
{
Packit 284210
    int i;
Packit 284210
 
Packit 284210
    for (i = 0; i < ALPHABET_SIZE; ++i) {
Packit 284210
        bm_badcharacter_array[i] = patlength;
Packit 284210
    }
Packit 284210
Packit 284210
    for (i = 0; i < patlength - 1; ++i){
Packit 284210
        bm_badcharacter_array[(uint8_t)pattern[i]] = patlength - i - 1;
Packit 284210
	}
Packit 284210
}
Packit 284210
Packit 284210
static void initBoyerMooreHorspool(const char *pattern, int patlength,
Packit 284210
    int *bm_badcharacter_array)
Packit 284210
{
Packit 284210
    precompute_badcharacter(pattern,
Packit 284210
        (patlength < MAX_PATTERN_SIZE ? patlength : MAX_PATTERN_SIZE), bm_badcharacter_array);
Packit 284210
}
Packit 284210
Packit 284210
static int BoyerMooreHorspool(const char *pattern, int patlength,
Packit 284210
    const char *text, int textlen, int *bm_badcharacter_array)
Packit 284210
{
Packit 284210
    int j;
Packit 284210
    char c;
Packit 284210
Packit 284210
    j = 0;
Packit 284210
    while (j <= textlen - patlength) {
Packit 284210
        c = text[j + patlength - 1];
Packit 284210
        if (pattern[patlength - 1] == c && memcmp(pattern, text + j, patlength - 1) == 0) {
Packit 284210
            return j;
Packit 284210
        }
Packit 284210
        j += bm_badcharacter_array[(uint8_t)c];
Packit 284210
    }
Packit 284210
Packit 284210
    return -1;
Packit 284210
}