14
14
15
15
#include "msc_xml.h"
16
16
17
+ static void msc_xml_on_start_elementns (
18
+ void * ctx ,
19
+ const xmlChar * localname ,
20
+ const xmlChar * prefix ,
21
+ const xmlChar * URI ,
22
+ int nb_namespaces ,
23
+ const xmlChar * * namespaces ,
24
+ int nb_attributes ,
25
+ int nb_defaulted ,
26
+ const xmlChar * * attributes
27
+ ) {
28
+
29
+ // get the length of XML tag (localname)
30
+ size_t taglen = strlen ((const char * )localname );
31
+ modsec_rec * msr = (modsec_rec * )ctx ;
32
+ msc_xml_parser_state * xml_parser_state = msr -> xml -> xml_parser_state ;
33
+
34
+ // pathlen contains the concatenated strings of tags with '.'
35
+ // eg xml.root.level1.leaf
36
+ xml_parser_state -> pathlen += (taglen + 1 );
37
+ char * newpath = apr_pstrcat (msr -> mp , xml_parser_state -> currpath , "." , (char * )localname , NULL );
38
+ xml_parser_state -> currpath = newpath ;
39
+
40
+ int * new_stack_item = (int * )apr_array_push (xml_parser_state -> has_child_stack );
41
+ * new_stack_item = 0 ;
42
+ xml_parser_state -> depth ++ ;
43
+
44
+ // if there is an item before the current one we set that has a child
45
+ if (xml_parser_state -> depth > 1 ) {
46
+ int * parent_stack_item = & ((int * )xml_parser_state -> has_child_stack -> elts )[xml_parser_state -> has_child_stack -> nelts - 2 ];
47
+ * parent_stack_item = 1 ;
48
+ }
49
+
50
+ }
51
+
52
+ static void msc_xml_on_end_elementns (
53
+ void * ctx ,
54
+ const xmlChar * localname ,
55
+ const xmlChar * prefix ,
56
+ const xmlChar * URI
57
+ ) {
58
+
59
+ size_t taglen = strlen ((const char * )localname );
60
+ modsec_rec * msr = (modsec_rec * )ctx ;
61
+ msc_xml_parser_state * xml_parser_state = msr -> xml -> xml_parser_state ;
62
+
63
+ // if the node is a leaf we add it as argument
64
+ // get the top item from the stack which tells this info
65
+ int * top_stack_item = apr_array_pop (xml_parser_state -> has_child_stack );
66
+ if (* top_stack_item == 0 ) {
67
+
68
+ if (apr_table_elts (msr -> arguments )-> nelts >= msr -> txcfg -> arguments_limit ) {
69
+ if (msr -> txcfg -> debuglog_level >= 4 ) {
70
+ msr_log (msr , 4 , "Skipping request argument, over limit (XML): name \"%s\", value \"%s\"" ,
71
+ log_escape_ex (msr -> mp , xml_parser_state -> currpath , strlen (xml_parser_state -> currpath )),
72
+ log_escape_ex (msr -> mp , xml_parser_state -> currval , strlen (xml_parser_state -> currval )));
73
+ }
74
+ msr -> msc_reqbody_error = 1 ;
75
+ msr -> xml -> xml_error = apr_psprintf (msr -> mp , "More than %ld XML keys" , msr -> txcfg -> arguments_limit );
76
+ xmlStopParser ((xmlParserCtxtPtr )msr -> xml -> parsing_ctx_arg );
77
+ }
78
+ else {
79
+
80
+ msc_arg * arg = (msc_arg * ) apr_pcalloc (msr -> mp , sizeof (msc_arg ));
81
+
82
+ arg -> name = xml_parser_state -> currpath ;
83
+ arg -> name_len = strlen (arg -> name );
84
+ arg -> value = xml_parser_state -> currval ;
85
+ arg -> value_len = strlen (xml_parser_state -> currval );
86
+ arg -> value_origin_len = arg -> value_len ;
87
+ //arg->value_origin_offset = value-base_offset;
88
+ arg -> origin = "XML" ;
89
+
90
+ if (msr -> txcfg -> debuglog_level >= 9 ) {
91
+ msr_log (msr , 9 , "Adding XML argument '%s' with value '%s'" ,
92
+ xml_parser_state -> currpath , xml_parser_state -> currval );
93
+ }
94
+
95
+ apr_table_addn (msr -> arguments ,
96
+ log_escape_nq_ex (msr -> mp , arg -> name , arg -> name_len ), (void * ) arg );
97
+ } // end else
98
+ } // end top_stack_item == 0
99
+
100
+ // decrease the length of current path length - +1 because of the '\0'
101
+ xml_parser_state -> pathlen -= (taglen + 1 );
102
+
103
+ // -1 need because we don't need the '.'
104
+ char * newpath = apr_pstrndup (msr -> mp , xml_parser_state -> currpath , xml_parser_state -> pathlen - 1 );
105
+ xml_parser_state -> currpath = newpath ;
106
+
107
+ xml_parser_state -> depth -- ;
108
+ }
109
+
110
+ static void msc_xml_on_characters (void * ctx , const xmlChar * ch , int len ) {
111
+
112
+ modsec_rec * msr = (modsec_rec * )ctx ;
113
+ msc_xml_parser_state * xml_parser_state = msr -> xml -> xml_parser_state ;
114
+
115
+ xml_parser_state -> currval = apr_pstrndup (msr -> mp , (const char * )ch , len );
116
+ }
117
+
118
+
17
119
static xmlParserInputBufferPtr
18
120
xml_unload_external_entity (const char * URI , xmlCharEncoding enc ) {
19
121
return NULL ;
@@ -37,6 +139,33 @@ int xml_init(modsec_rec *msr, char **error_msg) {
37
139
entity = xmlParserInputBufferCreateFilenameDefault (xml_unload_external_entity );
38
140
}
39
141
142
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_OFF ) {
143
+
144
+ msr -> xml -> sax_handler = (xmlSAXHandler * )apr_pcalloc (msr -> mp , sizeof (xmlSAXHandler ));
145
+ memset (msr -> xml -> sax_handler , 0 , sizeof (xmlSAXHandler ));
146
+ if (msr -> xml -> sax_handler == NULL ) {
147
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed to create SAX handler." );
148
+ return -1 ;
149
+ }
150
+
151
+ msr -> xml -> sax_handler -> initialized = XML_SAX2_MAGIC ;
152
+ msr -> xml -> sax_handler -> startElementNs = msc_xml_on_start_elementns ;
153
+ msr -> xml -> sax_handler -> endElementNs = msc_xml_on_end_elementns ;
154
+ msr -> xml -> sax_handler -> characters = msc_xml_on_characters ;
155
+
156
+ // set the parser state struct
157
+ msr -> xml -> xml_parser_state = apr_pcalloc (msr -> mp , sizeof (msc_xml_parser_state ));
158
+ msr -> xml -> xml_parser_state -> depth = 0 ;
159
+ msr -> xml -> xml_parser_state -> pathlen = 4 ; // "xml\0"
160
+ msr -> xml -> xml_parser_state -> currpath = apr_pstrdup (msr -> mp , "xml" );
161
+ msr -> xml -> xml_parser_state -> currval = NULL ;
162
+ msr -> xml -> xml_parser_state -> currpathbufflen = 4 ;
163
+ // initialize the stack with item of 10
164
+ // this will store the information about nodes
165
+ // 10 is just an initial value, it can be automatically incremented
166
+ msr -> xml -> xml_parser_state -> has_child_stack = apr_array_make (msr -> mp , 10 , sizeof (int ));
167
+ }
168
+
40
169
return 1 ;
41
170
}
42
171
@@ -68,7 +197,7 @@ int xml_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char
68
197
* enable us to pass it the first chunk of data so that
69
198
* it can attempt to auto-detect the encoding.
70
199
*/
71
- if (msr -> xml -> parsing_ctx == NULL ) {
200
+ if (msr -> xml -> parsing_ctx == NULL && msr -> xml -> parsing_ctx_arg == NULL ) {
72
201
73
202
/* First invocation. */
74
203
@@ -86,18 +215,50 @@ int xml_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char
86
215
87
216
*/
88
217
89
- msr -> xml -> parsing_ctx = xmlCreatePushParserCtxt (NULL , NULL , buf , size , "body.xml" );
90
- if (msr -> xml -> parsing_ctx == NULL ) {
91
- * error_msg = apr_psprintf (msr -> mp , "XML: Failed to create parsing context." );
92
- return -1 ;
218
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_ONLYARGS ) {
219
+ msr -> xml -> parsing_ctx = xmlCreatePushParserCtxt (NULL , NULL , buf , size , "body.xml" );
220
+ if (msr -> xml -> parsing_ctx == NULL ) {
221
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed to create parsing context." );
222
+ return -1 ;
223
+ }
224
+ }
225
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_OFF ) {
226
+ msr -> xml -> parsing_ctx_arg = xmlCreatePushParserCtxt (
227
+ msr -> xml -> sax_handler ,
228
+ msr ,
229
+ buf ,
230
+ size ,
231
+ NULL );
232
+ if (msr -> xml -> parsing_ctx_arg == NULL ) {
233
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed to create parsing context for ARGS." );
234
+ return -1 ;
235
+ }
93
236
}
94
237
} else {
95
238
96
239
/* Not a first invocation. */
240
+ msr_log (msr , 4 , "XML: Continue parsing." );
241
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_ONLYARGS ) {
242
+ xmlParseChunk (msr -> xml -> parsing_ctx , buf , size , 0 );
243
+ if (msr -> xml -> parsing_ctx -> wellFormed != 1 ) {
244
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document." );
245
+ return -1 ;
246
+ }
247
+ }
97
248
98
- xmlParseChunk (msr -> xml -> parsing_ctx , buf , size , 0 );
99
- if (msr -> xml -> parsing_ctx -> wellFormed != 1 ) {
100
- * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document." );
249
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_OFF ) {
250
+ if (xmlParseChunk (msr -> xml -> parsing_ctx_arg , buf , size , 0 ) != 0 ) {
251
+ if (msr -> xml -> xml_error ) {
252
+ * error_msg = msr -> xml -> xml_error ;
253
+ }
254
+ else {
255
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document for ARGS." );
256
+ }
257
+ return -1 ;
258
+ }
259
+ }
260
+ if (msr -> xml -> xml_error ) {
261
+ * error_msg = msr -> xml -> xml_error ;
101
262
return -1 ;
102
263
}
103
264
}
@@ -114,23 +275,42 @@ int xml_complete(modsec_rec *msr, char **error_msg) {
114
275
* error_msg = NULL ;
115
276
116
277
/* Only if we have a context, meaning we've done some work. */
117
- if (msr -> xml -> parsing_ctx != NULL ) {
118
- /* This is how we signalise the end of parsing to libxml. */
119
- xmlParseChunk (msr -> xml -> parsing_ctx , NULL , 0 , 1 );
278
+ if (msr -> xml -> parsing_ctx != NULL || msr -> xml -> parsing_ctx_arg != NULL ) {
279
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_ONLYARGS ) {
280
+ /* This is how we signalise the end of parsing to libxml. */
281
+ xmlParseChunk (msr -> xml -> parsing_ctx , NULL , 0 , 1 );
120
282
121
- /* Preserve the results for our reference. */
122
- msr -> xml -> well_formed = msr -> xml -> parsing_ctx -> wellFormed ;
123
- msr -> xml -> doc = msr -> xml -> parsing_ctx -> myDoc ;
283
+ /* Preserve the results for our reference. */
284
+ msr -> xml -> well_formed = msr -> xml -> parsing_ctx -> wellFormed ;
285
+ msr -> xml -> doc = msr -> xml -> parsing_ctx -> myDoc ;
124
286
125
- /* Clean up everything else. */
126
- xmlFreeParserCtxt (msr -> xml -> parsing_ctx );
127
- msr -> xml -> parsing_ctx = NULL ;
128
- msr_log (msr , 4 , "XML: Parsing complete (well_formed %u)." , msr -> xml -> well_formed );
287
+ /* Clean up everything else. */
288
+ xmlFreeParserCtxt (msr -> xml -> parsing_ctx );
289
+ msr -> xml -> parsing_ctx = NULL ;
290
+ msr_log (msr , 4 , "XML: Parsing complete (well_formed %u)." , msr -> xml -> well_formed );
129
291
130
- if (msr -> xml -> well_formed != 1 ) {
131
- * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document." );
132
- return -1 ;
292
+ if (msr -> xml -> well_formed != 1 ) {
293
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document." );
294
+ return -1 ;
295
+ }
296
+ }
297
+
298
+ if (msr -> txcfg -> parse_xml_into_args != MSC_XML_ARGS_OFF ) {
299
+ if (xmlParseChunk (msr -> xml -> parsing_ctx_arg , NULL , 0 , 1 ) != 0 ) {
300
+ if (msr -> xml -> xml_error ) {
301
+ * error_msg = msr -> xml -> xml_error ;
302
+ }
303
+ else {
304
+ * error_msg = apr_psprintf (msr -> mp , "XML: Failed parsing document for ARGS." );
305
+ }
306
+ xmlFreeParserCtxt (msr -> xml -> parsing_ctx_arg );
307
+ msr -> xml -> parsing_ctx_arg = NULL ;
308
+ return -1 ;
309
+ }
310
+ xmlFreeParserCtxt (msr -> xml -> parsing_ctx_arg );
311
+ msr -> xml -> parsing_ctx_arg = NULL ;
133
312
}
313
+
134
314
}
135
315
136
316
return 1 ;
@@ -152,6 +332,15 @@ apr_status_t xml_cleanup(modsec_rec *msr) {
152
332
xmlFreeParserCtxt (msr -> xml -> parsing_ctx );
153
333
msr -> xml -> parsing_ctx = NULL ;
154
334
}
335
+ if (msr -> xml -> parsing_ctx_arg != NULL ) {
336
+
337
+ if (msr -> xml -> parsing_ctx_arg -> myDoc ) {
338
+ xmlFreeDoc (msr -> xml -> parsing_ctx_arg -> myDoc );
339
+ }
340
+
341
+ xmlFreeParserCtxt (msr -> xml -> parsing_ctx_arg );
342
+ msr -> xml -> parsing_ctx_arg = NULL ;
343
+ }
155
344
if (msr -> xml -> doc != NULL ) {
156
345
xmlFreeDoc (msr -> xml -> doc );
157
346
msr -> xml -> doc = NULL ;
0 commit comments