Blame ext/mod_op_strstr.c

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