Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc23097c

Browse files
Ulisses AlbuquerqueFelipe Zimmerle
Ulisses Albuquerque
authored and
Felipe Zimmerle
committed
Added support for JSON body processor
1 parent410aca9 commitc23097c

File tree

9 files changed

+421
-7
lines changed

9 files changed

+421
-7
lines changed

‎apache2/Makefile.am‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod_security2_la_SOURCES = acmp.c \
1212
msc_crypt.c\
1313
msc_geo.c\
1414
msc_gsb.c\
15+
msc_json.c\
1516
msc_logging.c\
1617
msc_lua.c\
1718
msc_multipart.c\

‎apache2/modsecurity.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include"modsecurity.h"
2020
#include"msc_parsers.h"
2121
#include"msc_util.h"
22+
#include"msc_json.h"
2223
#include"msc_xml.h"
2324
#include"apr_version.h"
2425

@@ -255,6 +256,9 @@ static apr_status_t modsecurity_tx_cleanup(void *data) {
255256
/* XML processor cleanup. */
256257
if (msr->xml!=NULL)xml_cleanup(msr);
257258

259+
/* JSON processor cleanup. */
260+
if (msr->json!=NULL)json_cleanup(msr);
261+
258262
// TODO: Why do we ignore return code here?
259263
modsecurity_request_body_clear(msr,&my_error_msg);
260264
if (my_error_msg!=NULL) {

‎apache2/modsecurity.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef struct msc_parm msc_parm;
3838
#include"msc_multipart.h"
3939
#include"msc_pcre.h"
4040
#include"msc_util.h"
41+
#include"msc_json.h"
4142
#include"msc_xml.h"
4243
#include"msc_geo.h"
4344
#include"msc_gsb.h"
@@ -368,6 +369,7 @@ struct modsec_rec {
368369
multipart_data*mpd;/* MULTIPART processor data structure */
369370

370371
xml_data*xml;/* XML processor data structure */
372+
json_data*json;/* JSON processor data structure */
371373

372374
/* audit logging */
373375
char*new_auditlog_boundary;

‎apache2/modules.mk‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
MOD_SECURITY2 = mod_security2 apache2_config apache2_io apache2_util\
2-
re re_operators re_actions re_tfns re_variables\
2+
re re_operators re_actions re_tfns re_variablesmsc_json\
33
msc_logging msc_xml msc_multipart modsecurity msc_parsers msc_util msc_pcre\
44
persist_dbm msc_reqbody pdf_protect msc_geo msc_gsb msc_crypt msc_tree msc_unicode acmp msc_lua
55

6-
H = re.h modsecurity.h msc_logging.h msc_multipart.h msc_parsers.h\
6+
H = re.h modsecurity.h msc_logging.h msc_multipart.h msc_parsers.hmsc_json.h\
77
msc_pcre.h msc_util.h msc_xml.h persist_dbm.h apache2.h pdf_protect.h\
88
msc_geo.h msc_gsb.h msc_crypt.h msc_tree.h msc_unicode.h acmp.h utf8tables.h msc_lua.h
99

‎apache2/msc_json.c‎

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/*
2+
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
3+
* Copyright (c) 2004-2011 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License.  You may obtain a copy of the License at
7+
*
8+
*     http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*/
14+
15+
#include"msc_json.h"
16+
17+
intjson_add_argument(modsec_rec*msr,constchar*value,unsignedlength)
18+
{
19+
msc_arg*arg= (msc_arg*)NULL;
20+
21+
/**
22+
* If we do not have a prefix, we cannot create a variable name
23+
* to reference this argument; for now we simply ignore these
24+
*/
25+
if (!msr->json->current_key) {
26+
msr_log(msr,3,"Cannot add scalar value without an associated key");
27+
return1;
28+
}
29+
30+
arg= (msc_arg*)apr_pcalloc(msr->mp,sizeof(msc_arg));
31+
32+
/**
33+
* Argument name is 'prefix + current_key'
34+
*/
35+
if (msr->json->prefix) {
36+
arg->name=apr_psprintf(msr->mp,"%s.%s",msr->json->prefix,
37+
msr->json->current_key);
38+
}
39+
else {
40+
arg->name=apr_psprintf(msr->mp,"%s",msr->json->current_key);
41+
}
42+
arg->name_len=strlen(arg->name);
43+
44+
/**
45+
* Argument value is copied from the provided string
46+
*/
47+
arg->value=apr_pstrmemdup(msr->mp,value,length);
48+
arg->value_len=length;
49+
50+
if (msr->txcfg->debuglog_level >=9) {
51+
msr_log(msr,9,"Adding JSON argument '%s' with value '%s'",
52+
arg->name,arg->value);
53+
}
54+
55+
apr_table_addn(msr->arguments,
56+
log_escape_nq_ex(msr->mp,arg->name,arg->name_len), (void*)arg);
57+
58+
return1;
59+
}
60+
61+
/**
62+
* yajl callback functions
63+
* For more information on the function signatures and order, check
64+
* http://lloyd.github.com/yajl/yajl-1.0.12/structyajl__callbacks.html
65+
*/
66+
67+
/**
68+
* Callback for hash key values; we use those to define the variable names
69+
* under ARGS. Whenever we reach a new key, we update the current key value.
70+
*/
71+
staticintyajl_map_key(void*ctx,constunsignedchar*key,unsignedintlength)
72+
{
73+
modsec_rec*msr= (modsec_rec*)ctx;
74+
unsignedchar*safe_key= (unsignedchar*)NULL;
75+
76+
/**
77+
* yajl does not provide us with null-terminated strings, but
78+
* rather expects us to copy the data from the key up to the
79+
* length informed; we create a standalone null-termined copy
80+
* in safe_key
81+
*/
82+
safe_key=apr_pstrndup(msr->mp,key,length);
83+
84+
if (msr->txcfg->debuglog_level >=9) {
85+
msr_log(msr,9,"New JSON hash key '%s'",safe_key);
86+
}
87+
88+
/**
89+
* TODO: How do we free the previously string value stored here?
90+
*/
91+
msr->json->current_key=safe_key;
92+
93+
return1;
94+
}
95+
96+
/**
97+
* Callback for null values
98+
*
99+
* TODO: Is there a way to define true null parameter values instead of
100+
* empty values?
101+
*/
102+
staticintyajl_null(void*ctx)
103+
{
104+
modsec_rec*msr= (modsec_rec*)ctx;
105+
106+
returnjson_add_argument(msr,"",0);
107+
}
108+
109+
/**
110+
* Callback for boolean values
111+
*/
112+
staticintyajl_boolean(void*ctx,intvalue)
113+
{
114+
modsec_rec*msr= (modsec_rec*)ctx;
115+
116+
if (value) {
117+
returnjson_add_argument(msr,"true",strlen("true"));
118+
}
119+
else {
120+
returnjson_add_argument(msr,"false",strlen("false"));
121+
}
122+
}
123+
124+
/**
125+
* Callback for string values
126+
*/
127+
staticintyajl_string(void*ctx,constunsignedchar*value,unsignedintlength)
128+
{
129+
modsec_rec*msr= (modsec_rec*)ctx;
130+
131+
returnjson_add_argument(msr,value,length);
132+
}
133+
134+
/**
135+
* Callback for numbers; YAJL can use separate callbacks for integers/longs and
136+
* float/double values, but since we are not interested in using the numeric
137+
* values here, we use a generic handler which uses numeric strings
138+
*/
139+
staticintyajl_number(void*ctx,constunsignedchar*value,unsignedintlength)
140+
{
141+
modsec_rec*msr= (modsec_rec*)ctx;
142+
143+
returnjson_add_argument(msr,value,length);
144+
}
145+
146+
/**
147+
* Callback for a new hash, which indicates a new subtree, labeled as the current
148+
* argument name, is being created
149+
*/
150+
staticintyajl_start_map(void*ctx)
151+
{
152+
modsec_rec*msr= (modsec_rec*)ctx;
153+
154+
/**
155+
* If we do not have a current_key, this is a top-level hash, so we do not
156+
* need to do anything
157+
*/
158+
if (!msr->json->current_key)return1;
159+
160+
/**
161+
* Check if we are already inside a hash context, and append or create the
162+
* current key name accordingly
163+
*/
164+
if (msr->json->prefix) {
165+
msr->json->prefix=apr_psprintf(msr->mp,"%s.%s",msr->json->prefix,
166+
msr->json->current_key);
167+
}
168+
else {
169+
msr->json->prefix=apr_pstrdup(msr->mp,msr->json->current_key);
170+
}
171+
172+
if (msr->txcfg->debuglog_level >=9) {
173+
msr_log(msr,9,"New JSON hash context (prefix '%s')",msr->json->prefix);
174+
}
175+
176+
return1;
177+
}
178+
179+
/**
180+
* Callback for end hash, meaning the current subtree is being closed, and that
181+
* we should go back to the parent variable label
182+
*/
183+
staticintyajl_end_map(void*ctx)
184+
{
185+
modsec_rec*msr= (modsec_rec*)ctx;
186+
unsignedchar*separator= (unsignedchar*)NULL;
187+
188+
/**
189+
* If we have no prefix, then this is the end of a top-level hash and
190+
* we don't do anything
191+
*/
192+
if (msr->json->prefix==NULL)return1;
193+
194+
/**
195+
* Current prefix might or not include a separator character; top-level
196+
* hash keys do not have separators in the variable name
197+
*/
198+
separator=strrchr(msr->json->prefix,'.');
199+
200+
if (separator) {
201+
msr->json->prefix=apr_pstrmemdup(msr->mp,msr->json->prefix,
202+
separator-msr->json->prefix);
203+
msr->json->current_key=apr_psprintf(msr->mp,"%s",separator+1);
204+
}
205+
else {
206+
/**
207+
* TODO: Check if it is safe to do this kind of pointer tricks
208+
*/
209+
msr->json->current_key=msr->json->prefix;
210+
msr->json->prefix= (unsignedchar*)NULL;
211+
}
212+
213+
return1;
214+
}
215+
216+
/**
217+
* Initialise JSON parser.
218+
*/
219+
intjson_init(modsec_rec*msr,char**error_msg) {
220+
/**
221+
* yajl configuration and callbacks
222+
*/
223+
staticyajl_parser_configconfig= {0,1 };
224+
staticyajl_callbackscallbacks= {
225+
yajl_null,
226+
yajl_boolean,
227+
NULL/* yajl_integer */,
228+
NULL/* yajl_double */,
229+
yajl_number,
230+
yajl_string,
231+
yajl_start_map,
232+
yajl_map_key,
233+
yajl_end_map,
234+
NULL/* yajl_start_array */,
235+
NULL/* yajl_end_array */
236+
};
237+
238+
if (error_msg==NULL)return-1;
239+
*error_msg=NULL;
240+
241+
msr_log(msr,4,"JSON parser initialization");
242+
msr->json=apr_pcalloc(msr->mp,sizeof(json_data));
243+
if (msr->json==NULL)return-1;
244+
245+
/**
246+
* Prefix and current key are initially empty
247+
*/
248+
msr->json->prefix= (unsignedchar*)NULL;
249+
msr->json->current_key= (unsignedchar*)NULL;
250+
251+
/**
252+
* yajl initialization
253+
*
254+
* yajl_parser_config definition:
255+
* http://lloyd.github.com/yajl/yajl-1.0.12/structyajl__parser__config.html
256+
*
257+
* TODO: make UTF8 validation optional, as it depends on Content-Encoding
258+
*/
259+
if (msr->txcfg->debuglog_level >=9) {
260+
msr_log(msr,9,"yajl JSON parsing callback initialization");
261+
}
262+
msr->json->handle=yajl_alloc(&callbacks,&config,NULL,msr);
263+
264+
return1;
265+
}
266+
267+
/**
268+
* Feed one chunk of data to the JSON parser.
269+
*/
270+
intjson_process_chunk(modsec_rec*msr,constchar*buf,unsignedintsize,char**error_msg) {
271+
if (error_msg==NULL)return-1;
272+
*error_msg=NULL;
273+
274+
/* Feed our parser and catch any errors */
275+
msr->json->status=yajl_parse(msr->json->handle,buf,size);
276+
if (msr->json->status!=yajl_status_ok&&
277+
msr->json->status!=yajl_status_insufficient_data) {
278+
/* We need to free the yajl error message later, how to do this? */
279+
*error_msg=yajl_get_error(msr->json->handle,0,buf,size);
280+
}
281+
282+
return1;
283+
}
284+
285+
/**
286+
* Finalise JSON parsing.
287+
*/
288+
intjson_complete(modsec_rec*msr,char**error_msg) {
289+
char*json_data= (char*)NULL;
290+
291+
if (error_msg==NULL)return-1;
292+
*error_msg=NULL;
293+
294+
/* Wrap up the parsing process */
295+
msr->json->status=yajl_parse_complete(msr->json->handle);
296+
if (msr->json->status!=yajl_status_ok&&
297+
msr->json->status!=yajl_status_insufficient_data) {
298+
/* We need to free the yajl error message later, how to do this? */
299+
*error_msg=yajl_get_error(msr->json->handle,0,NULL,0);
300+
}
301+
302+
return1;
303+
}
304+
305+
/**
306+
* Frees the resources used for XML parsing.
307+
*/
308+
apr_status_tjson_cleanup(modsec_rec*msr) {
309+
msr_log(msr,4,"JSON: Cleaning up JSON results");
310+
311+
return1;
312+
}
313+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp