forked from owasp-modsecurity/ModSecurity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod_reqbody_example.c
164 lines (138 loc) · 5.28 KB
/
mod_reqbody_example.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address [email protected].
*/
/* This is just an example on how to make an extension to allow custom
* request body parsing. This just describes how to do this externally
* and you should look more at on e of the internal parsers to see
* the full potential.
*
* This module defines "EXAMPLE" and can be enabled with a rule like this:
*
* SecAction "phase:1,pass,nolog,ctl:requestBodyProcessor=EXAMPLE"
*
* See these for real parsers:
* msc_reqbody.c
* msc_multipart.c
* msc_xml.c
*/
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_config.h"
#include "apr_optional.h"
#include "modsecurity.h"
typedef struct example_ctx {
unsigned long length;
} example_ctx;
/**
* This function will be invoked to initialize the processor. This is
* probably only needed for streaming parsers that must create a context.
*/
static int example_init(modsec_rec *msr, char **error_msg)
{
if (error_msg == NULL) return -1;
*error_msg = NULL;
ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, NULL,
"mod_reqbody_example: init()");
msr->reqbody_processor_ctx = apr_pcalloc(msr->mp, sizeof(example_ctx));
if (msr->reqbody_processor_ctx == NULL) {
/* Set error message and return -1 if unsuccessful */
*error_msg = apr_pstrdup(msr->mp, "failed to create example requbody processor context");
return -1;
}
/* Return 1 on success */
return 1;
}
/**
* This function will be invoked whenever the ModSecurity has data to
* be processed. You probably at least need to increment the no_files
* length, but otherwise this is only useful for a streaming parser.
*/
static int example_process(modsec_rec *msr,
const char *buf, unsigned int size, char **error_msg)
{
example_ctx *ctx = (example_ctx *)msr->reqbody_processor_ctx;
if (error_msg == NULL) return -1;
*error_msg = NULL;
ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, NULL,
"mod_reqbody_example: process()");
/* Need to increment the no_files length if this is not an uploaded file.
* Failing to do this will mess up some other limit checks.
*/
msr->msc_reqbody_no_files_length += size;
/* Check for an existing context and do something interesting
* with the chunk of data we have been given.
*/
if (ctx != NULL) {
ctx->length += size;
}
/* Return 1 on success */
return 1;
}
/**
* This function is called to signal the parser that the request body is
* complete. Here you should do any final parsing. For non-streaming parsers
* you can parse the data in msr->msc_reqbody_buffer of length
* msr->msc_reqbody_length. See modsecurity_request_body_end_urlencoded() in
* msc_reqbody.c for an example of this.
*/
static int example_complete(modsec_rec *msr, char **error_msg)
{
example_ctx *ctx = (example_ctx *)msr->reqbody_processor_ctx;
if (error_msg == NULL) return -1;
*error_msg = NULL;
ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, NULL,
"mod_reqbody_example: complete()");
ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, NULL,
"mod_reqbody_example: request body length=%lu", ctx->length);
/* Return 1 on success */
return 1;
}
static int hook_pre_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_temp) {
void (*fn)(const char *name,
void *fn_init, void *fn_process, void *fn_complete);
/* Look for the registration function exported by ModSecurity. */
fn = APR_RETRIEVE_OPTIONAL_FN(modsec_register_reqbody_processor);
if (fn) {
/* Use it to register our new request body parser functions under
* the name "EXAMPLE".
*/
fn("EXAMPLE",
(void *)example_init,
(void *)example_process,
(void *)example_complete);
}
else {
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
"mod_reqbody_example: Unable to find modsec_register_reqbody_processor.");
}
return OK;
}
/* This is a function to register another function to be called during
* the Apache configuration process.
*/
static void register_hooks(apr_pool_t *p) {
ap_hook_pre_config(hook_pre_config, NULL, NULL, APR_HOOK_LAST);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA reqbody_example_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
NULL, /* table of config file commands */
register_hooks /* register hooks */
};