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];