4
#include "http_config.h"
6
#include "http_protocol.h"
8
#include "apr_optional.h"
10
#include "modsecurity.h"
12
#define ALPHABET_SIZE 256
13
#define MAX_PATTERN_SIZE 64
15
static void initBoyerMooreHorspool(const char *pattern, int patlength,
16
int *bm_badcharacter_array);
18
static int BoyerMooreHorspool(const char *pattern, int patlength,
19
const char *text, int textlen, int *bm_badcharacter_array);
22
* Operator parameter initialisation entry point.
24
static int op_strstr_init(msre_rule *rule, char **error_msg) {
25
/* Operator initialisation function will be called once per
26
* statement where operator is used. It is meant to be used
27
* to check the parameters to see whether they are present
28
* and if they are in the correct format.
31
/* In this example we just look for a simple non-empty parameter. */
32
if ((rule->op_param == NULL)||(strlen(rule->op_param) == 0)) {
33
*error_msg = apr_psprintf(rule->ruleset->mp, "Missing parameter for operator 'strstr'.");
37
/* If you need to transform the data in the parameter into something
38
* else you should do that here. Simply create a new structure to hold
39
* the transformed data and place the pointer to it into rule->op_param_data.
40
* You will have access to this pointer later on.
42
rule->op_param_data = apr_pcalloc(rule->ruleset->mp, ALPHABET_SIZE * sizeof(int));
43
initBoyerMooreHorspool(rule->op_param, strlen(rule->op_param), (int *)rule->op_param_data);
50
* Operator execution entry point.
52
static int op_strstr_exec(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
53
/* Here we need to inspect the contents of the supplied variable. */
55
/* In a general case it is possible for the value
56
* to be NULL. What you need to do in this case
57
* depends on your operator. In this example we return
58
* a "no match" response.
60
if (var->value == NULL) return 0; /* No match. */
62
/* Another thing to note is that variables are not C strings,
63
* meaning the NULL byte is not used to determine the end
64
* of the string. Variable length var->value_len should be
65
* used for this purpose.
68
if (BoyerMooreHorspool(rule->op_param, strlen(rule->op_param),
69
var->value, var->value_len, (int *)rule->op_param_data) >= 0)
71
return 1; /* Match. */
74
return 0; /* No match. */
77
static int hook_pre_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_temp) {
78
void (*fn)(const char *name, void *fn_init, void *fn_exec);
80
/* Look for the registration function
81
* exported by ModSecurity.
83
fn = APR_RETRIEVE_OPTIONAL_FN(modsec_register_operator);
85
/* Use it to register our new
86
* transformation function under the
89
fn("strstr", (void *)op_strstr_init, (void *)op_strstr_exec);
95
static void register_hooks(apr_pool_t *p) {
96
ap_hook_pre_config(hook_pre_config, NULL, NULL, APR_HOOK_LAST);
99
/* Dispatch list for API hooks */
100
module AP_MODULE_DECLARE_DATA op_strstr_module = {
101
STANDARD20_MODULE_STUFF,
102
NULL, /* create per-dir config structures */
103
NULL, /* merge per-dir config structures */
104
NULL, /* create per-server config structures */
105
NULL, /* merge per-server config structures */
106
NULL, /* table of config file commands */
107
register_hooks /* register hooks */
112
This example uses an implementation Boyer-Moore-Horspool
113
matching algorithm as implemented in Streamline (http://ffpf.sourceforge.net).
115
Copyright (c) 2004-2006, Vrije Universiteit Amsterdam
118
Redistribution and use in source and binary forms, with or without modification,
119
are permitted provided that the following conditions are met:
121
Redistributions of source code must retain the above copyright notice,
122
this list of conditions and the following disclaimer.
124
Redistributions in binary form must reproduce the above copyright notice,
125
this list of conditions and the following disclaimer in the documentation
126
and/or other materials provided with the distribution.
128
Neither the name of the Vrije Universiteit nor the names of its contributors
129
may be used to endorse or promote products derived from this software without
130
specific prior written permission.
134
static void precompute_badcharacter(const char *pattern, int patlength,
135
int bm_badcharacter_array[])
139
for (i = 0; i < ALPHABET_SIZE; ++i) {
140
bm_badcharacter_array[i] = patlength;
143
for (i = 0; i < patlength - 1; ++i){
144
bm_badcharacter_array[(uint8_t)pattern[i]] = patlength - i - 1;
148
static void initBoyerMooreHorspool(const char *pattern, int patlength,
149
int *bm_badcharacter_array)
151
precompute_badcharacter(pattern,
152
(patlength < MAX_PATTERN_SIZE ? patlength : MAX_PATTERN_SIZE), bm_badcharacter_array);
155
static int BoyerMooreHorspool(const char *pattern, int patlength,
156
const char *text, int textlen, int *bm_badcharacter_array)
162
while (j <= textlen - patlength) {
163
c = text[j + patlength - 1];
164
if (pattern[patlength - 1] == c && memcmp(pattern, text + j, patlength - 1) == 0) {
167
j += bm_badcharacter_array[(uint8_t)c];