1 /*
2 * ModSecurity for Apache 2.x, http://www.modsecurity.org/
3 * Copyright (c) 2004-2013 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 <ctype.h>
16
17 #include "apr_md5.h"
18 #include "apr_sha1.h"
19 #include "apr_base64.h"
20
21 #include "msc_unicode.h"
22 #include "re.h"
23 #include "msc_util.h"
24
25 /* cmdline */
26
27 /**
28 * \brief cmdline transformation function
29 *
30 * \param mptmp Pointer to resource pool
31 * \param input Pointer to input data
32 * \param input_len Input data length
33 * \param rval Pointer to decoded buffer
34 * \param rval_len Decoded buffer length
35 *
36 * \retval 0 On failure
37 * \retval 1 On Success
38 */
msre_fn_cmdline_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)39 static int msre_fn_cmdline_execute(apr_pool_t *mptmp, unsigned char *input,
40 long int input_len, char **rval, long int *rval_len)
41 {
42 int space = 0;
43 unsigned char *s = input;
44
45 if (rval == NULL) return -1;
46
47 *rval = (char *)input;
48 /* Check characters */
49 for ( ; *input; input++ ) {
50 switch(*input) {
51 /* remove some characters */
52 case '"':
53 case '\'':
54 case '\\':
55 case '^':
56 continue;
57 /* replace some characters to space (only one) */
58 case ' ':
59 case ',':
60 case ';':
61 case '\t':
62 case '\r':
63 case '\n':
64 if (!space) {
65 *s++ = ' ';
66 space++;
67 }
68 break;
69 case '/':
70 case '(':
71 /* remove space before / or ( */
72 if (space) s--;
73 space = 0;
74 *s++ = *input;
75 break;
76 /* copy normal characters */
77 default :
78 *s++ = tolower(*input);
79 space = 0;
80 }
81 }
82
83 *s = 0;
84 *rval_len = strlen(*rval);
85 return 1;
86 }
87
88 /* lowercase */
89
msre_fn_lowercase_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)90 static int msre_fn_lowercase_execute(apr_pool_t *mptmp, unsigned char *input,
91 long int input_len, char **rval, long int *rval_len)
92 {
93 long int i;
94 int changed = 0;
95
96 if (rval == NULL) return -1;
97 *rval = NULL;
98
99 i = 0;
100 while(i < input_len) {
101 int x = input[i];
102 input[i] = tolower(x);
103 if (x != input[i]) changed = 1;
104 i++;
105 }
106
107 *rval = (char *)input;
108 *rval_len = input_len;
109
110 return changed;
111 }
112
113 /* trimLeft */
114
msre_fn_trimLeft_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)115 static int msre_fn_trimLeft_execute(apr_pool_t *mptmp, unsigned char *input,
116 long int input_len, char **rval, long int *rval_len)
117 {
118 long int i;
119
120 *rval = (char *)input;
121 for (i = 0; i < input_len; i++) {
122 if (isspace(**rval) == 0) {
123 break;
124 }
125 (*rval)++;
126 }
127
128 *rval_len = input_len - i;
129
130 return (*rval_len == input_len ? 0 : 1);
131 }
132
133 /* trimRight */
134
msre_fn_trimRight_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)135 static int msre_fn_trimRight_execute(apr_pool_t *mptmp, unsigned char *input,
136 long int input_len, char **rval, long int *rval_len)
137 {
138 long int i;
139
140 *rval = (char *)input;
141 for (i = input_len - 1; i >= 0; i--) {
142 if (isspace((*rval)[i]) == 0) {
143 break;
144 }
145 (*rval)[i] = '\0';
146 }
147
148 *rval_len = i + 1;
149
150 return (*rval_len == input_len ? 0 : 1);
151 }
152
153 /* trim */
154
msre_fn_trim_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)155 static int msre_fn_trim_execute(apr_pool_t *mptmp, unsigned char *input,
156 long int input_len, char **rval, long int *rval_len)
157 {
158 int rc = 0;
159
160 rc = msre_fn_trimLeft_execute(mptmp, input, input_len, rval, rval_len);
161 if (rc == 1) {
162 rc = msre_fn_trimRight_execute(mptmp, (unsigned char *)*rval, *rval_len, rval, rval_len);
163 }
164 else {
165 rc = msre_fn_trimRight_execute(mptmp, input, input_len, rval, rval_len);
166 }
167
168 return (*rval_len == input_len ? 0 : 1);
169 }
170
171 /* removeNulls */
172
msre_fn_removeNulls_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)173 static int msre_fn_removeNulls_execute(apr_pool_t *mptmp, unsigned char *input,
174 long int input_len, char **rval, long int *rval_len)
175 {
176 long int i, j;
177 int changed = 0;
178
179 i = j = 0;
180 while(i < input_len) {
181 if (input[i] == '\0') {
182 changed = 1;
183 } else {
184 input[j] = input[i];
185 j++;
186 }
187 i++;
188 }
189
190 *rval = (char *)input;
191 *rval_len = j;
192
193 return changed;
194 }
195
196 /* replaceNulls */
197
msre_fn_replaceNulls_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)198 static int msre_fn_replaceNulls_execute(apr_pool_t *mptmp, unsigned char *input,
199 long int input_len, char **rval, long int *rval_len)
200 {
201 long int i;
202 int changed = 0;
203
204 if (rval == NULL) return -1;
205 *rval = NULL;
206
207 i = 0;
208 while(i < input_len) {
209 if (input[i] == '\0') {
210 changed = 1;
211 input[i] = ' ';
212 }
213 i++;
214 }
215
216 *rval = (char *)input;
217 *rval_len = input_len;
218
219 return changed;
220 }
221
222 /* compressWhitespace */
223
msre_fn_compressWhitespace_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)224 static int msre_fn_compressWhitespace_execute(apr_pool_t *mptmp, unsigned char *input,
225 long int input_len, char **rval, long int *rval_len)
226 {
227 long int i, j, count;
228 int changed = 0;
229 int inwhitespace = 0;
230
231 i = j = count = 0;
232 while(i < input_len) {
233 if (isspace(input[i])||(input[i] == NBSP)) {
234 if (inwhitespace) changed = 1;
235 inwhitespace = 1;
236 count++;
237 } else {
238 inwhitespace = 0;
239 if (count) {
240 input[j] = ' ';
241 count = 0;
242 j++;
243 }
244 input[j] = input[i];
245 j++;
246 }
247 i++;
248 }
249
250 if (count) {
251 input[j] = ' ';
252 j++;
253 }
254
255 *rval = (char *)input;
256 *rval_len = j;
257
258 return changed;
259 }
260
261 /* cssDecode */
262
msre_fn_cssDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)263 static int msre_fn_cssDecode_execute(apr_pool_t *mptmp, unsigned char *input,
264 long int input_len, char **rval, long int *rval_len)
265 {
266 long int length;
267
268 length = css_decode_inplace(input, input_len);
269 *rval = (char *)input;
270 *rval_len = length;
271
272 return (*rval_len == input_len ? 0 : 1);
273 }
274
275 /* removeWhitespace */
276
msre_fn_removeWhitespace_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)277 static int msre_fn_removeWhitespace_execute(apr_pool_t *mptmp, unsigned char *input,
278 long int input_len, char **rval, long int *rval_len)
279 {
280 long int i, j;
281 int changed = 0;
282
283 i = j = 0;
284 while(i < input_len) {
285 if (isspace(input[i])||(input[i] == NBSP)) {
286 /* do nothing */
287 changed = 1;
288 } else {
289 input[j] = input[i];
290 j++;
291 }
292 i++;
293 }
294
295 *rval = (char *)input;
296 *rval_len = j;
297
298 return changed;
299 }
300
301 /* removeCommentsChar */
302
msre_fn_removeCommentsChar_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)303 static int msre_fn_removeCommentsChar_execute(apr_pool_t *mptmp, unsigned char *input,
304 long int input_len, char **rval, long int *rval_len)
305 {
306 long int i, j;
307 int changed = 0;
308
309 i = j = 0;
310 while(i < input_len) {
311 if ((input[i] == '/')&&(i + 1 < input_len)&&(input[i + 1] == '*')) {
312 changed = 1;
313 i += 2;
314 } else if ((input[i] == '*')&&(i + 1 < input_len)&&(input[i + 1] == '/')) {
315 changed = 1;
316 i += 2;
317 } else if ((input[i] == '<')&&(i + 1 < input_len)&&(input[i + 1] == '!')&&
318 (i + 2 < input_len)&&(input[i+2] == '-')&&(i + 3 < input_len)&&
319 (input[i + 3] == '-')) {
320 changed = 1;
321 i += 4;
322 } else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')&&
323 (i + 2 < input_len)&&(input[i+2] == '>')) {
324 changed = 1;
325 i += 3;
326 } else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')) {
327 changed = 1;
328 i += 2;
329 } else if (input[i] == '#') {
330 changed = 1;
331 i++;
332 } else {
333 input[j] = input[i];
334 i++;
335 j++;
336 }
337 }
338 input[j] = '\0';
339
340 *rval = (char *)input;
341 *rval_len = j;
342
343 return changed;
344 }
345
346 /* removeComments */
347
msre_fn_removeComments_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)348 static int msre_fn_removeComments_execute(apr_pool_t *mptmp, unsigned char *input,
349 long int input_len, char **rval, long int *rval_len)
350 {
351 long int i, j, incomment;
352 int changed = 0;
353
354 i = j = incomment = 0;
355 while(i < input_len) {
356 if (incomment == 0) {
357 if ((input[i] == '/')&&(i + 1 < input_len)&&(input[i + 1] == '*')) {
358 changed = 1;
359 incomment = 1;
360 i += 2;
361 } else if ((input[i] == '<')&&(i + 1 < input_len)&&(input[i + 1] == '!')&&
362 (i + 2 < input_len)&&(input[i+2] == '-')&&(i + 3 < input_len)&&
363 (input[i + 3] == '-') && (incomment == 0)) {
364 incomment = 1;
365 changed = 1;
366 i += 4;
367 } else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')
368 && (incomment == 0)) {
369 changed = 1;
370 input[i] = ' ';
371 break;
372 } else if (input[i] == '#' && (incomment == 0)) {
373 changed = 1;
374 input[i] = ' ';
375 break;
376 } else {
377 input[j] = input[i];
378 i++;
379 j++;
380 }
381 } else {
382 if ((input[i] == '*')&&(i + 1 < input_len)&&(input[i + 1] == '/')) {
383 incomment = 0;
384 i += 2;
385 input[j] = input[i];
386 i++;
387 j++;
388 } else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')&&
389 (i + 2 < input_len)&&(input[i+2] == '>')) {
390 incomment = 0;
391 i += 3;
392 input[j] = input[i];
393 i++;
394 j++;
395 } else {
396 i++;
397 }
398 }
399 }
400
401 if (incomment) {
402 input[j++] = ' ';
403 }
404
405 *rval = (char *)input;
406 *rval_len = j;
407
408 return changed;
409 }
410
411 /* replaceComments */
412
msre_fn_replaceComments_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)413 static int msre_fn_replaceComments_execute(apr_pool_t *mptmp, unsigned char *input,
414 long int input_len, char **rval, long int *rval_len)
415 {
416 long int i, j, incomment;
417 int changed = 0;
418
419 i = j = incomment = 0;
420 while(i < input_len) {
421 if (incomment == 0) {
422 if ((input[i] == '/')&&(i + 1 < input_len)&&(input[i + 1] == '*')) {
423 changed = 1;
424 incomment = 1;
425 i += 2;
426 } else {
427 input[j] = input[i];
428 i++;
429 j++;
430 }
431 } else {
432 if ((input[i] == '*')&&(i + 1 < input_len)&&(input[i + 1] == '/')) {
433 incomment = 0;
434 i += 2;
435 input[j] = ' ';
436 j++;
437 } else {
438 i++;
439 }
440 }
441 }
442
443 if (incomment) {
444 input[j++] = ' ';
445 }
446
447 *rval = (char *)input;
448 *rval_len = j;
449
450 return changed;
451 }
452
453 /* jsDecode */
454
msre_fn_jsDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)455 static int msre_fn_jsDecode_execute(apr_pool_t *mptmp, unsigned char *input,
456 long int input_len, char **rval, long int *rval_len)
457 {
458 long int length;
459
460 length = js_decode_nonstrict_inplace(input, input_len);
461 *rval = (char *)input;
462 *rval_len = length;
463
464 return (*rval_len == input_len ? 0 : 1);
465 }
466
467 /* urlDecode */
468
msre_fn_urlDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)469 static int msre_fn_urlDecode_execute(apr_pool_t *mptmp, unsigned char *input,
470 long int input_len, char **rval, long int *rval_len)
471 {
472 long int length;
473 int invalid_count;
474 int changed;
475
476 length = urldecode_nonstrict_inplace_ex(input, input_len, &invalid_count, &changed);
477 *rval = (char *)input;
478 *rval_len = length;
479
480 return changed;
481 }
482
483 /* urlDecodeUni */
484
msre_fn_urlDecodeUni_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)485 static int msre_fn_urlDecodeUni_execute(apr_pool_t *mptmp, unsigned char *input,
486 long int input_len, char **rval, long int *rval_len)
487 {
488 long int length;
489 int changed;
490
491 length = urldecode_uni_nonstrict_inplace_ex(input, input_len, &changed);
492 *rval = (char *)input;
493 *rval_len = length;
494
495 return changed;
496 }
497
msre_fn_utf8Unicode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)498 static int msre_fn_utf8Unicode_execute(apr_pool_t *mptmp, unsigned char *input,
499 long int input_len, char **rval, long int *rval_len)
500 {
501 int changed = 0;
502
503 *rval = (char *)utf8_unicode_inplace_ex(mptmp, input, input_len, &changed);
504 *rval_len = strlen(*rval);
505
506 return changed;
507 }
508
509
510 /* urlEncode */
511
msre_fn_urlEncode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)512 static int msre_fn_urlEncode_execute(apr_pool_t *mptmp, unsigned char *input,
513 long int input_len, char **rval, long int *rval_len)
514 {
515 int changed;
516
517 *rval = url_encode(mptmp, (char *)input, input_len, &changed);
518 *rval_len = strlen(*rval);
519
520 return changed;
521 }
522
523 /* base64Encode */
524
msre_fn_base64Encode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)525 static int msre_fn_base64Encode_execute(apr_pool_t *mptmp, unsigned char *input,
526 long int input_len, char **rval, long int *rval_len)
527 {
528 *rval_len = apr_base64_encode_len(input_len); /* returns len with NULL byte included */
529 *rval = apr_palloc(mptmp, *rval_len);
530 apr_base64_encode(*rval, (const char *)input, input_len);
531 (*rval_len)--;
532
533 return *rval_len ? 1 : 0;
534 }
535
536 /* base64Decode */
537
msre_fn_base64Decode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)538 static int msre_fn_base64Decode_execute(apr_pool_t *mptmp, unsigned char *input,
539 long int input_len, char **rval, long int *rval_len)
540 {
541 *rval_len = apr_base64_decode_len((const char *)input); /* returns len with NULL byte included */
542 *rval = apr_palloc(mptmp, *rval_len);
543 *rval_len = apr_base64_decode(*rval, (const char *)input);
544
545 return *rval_len ? 1 : 0;
546 }
547
548 /* length */
549
msre_fn_length_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)550 static int msre_fn_length_execute(apr_pool_t *mptmp, unsigned char *input,
551 long int input_len, char **rval, long int *rval_len)
552 {
553 *rval = apr_psprintf(mptmp, "%ld", input_len);
554 *rval_len = strlen(*rval);
555
556 return 1;
557 }
558
559 /* md5 */
560
msre_fn_md5_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)561 static int msre_fn_md5_execute(apr_pool_t *mptmp, unsigned char *input,
562 long int input_len, char **rval, long int *rval_len)
563 {
564 unsigned char digest[APR_MD5_DIGESTSIZE];
565
566 apr_md5(digest, input, input_len);
567
568 *rval_len = APR_MD5_DIGESTSIZE;
569 *rval = apr_pstrmemdup(mptmp, (const char *)digest, APR_MD5_DIGESTSIZE);
570
571 return 1;
572 }
573
574 /* sha1 */
575
msre_fn_sha1_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)576 static int msre_fn_sha1_execute(apr_pool_t *mptmp, unsigned char *input,
577 long int input_len, char **rval, long int *rval_len)
578 {
579 unsigned char digest[APR_SHA1_DIGESTSIZE];
580 apr_sha1_ctx_t context;
581
582 apr_sha1_init(&context);
583 apr_sha1_update(&context, (const char *)input, input_len);
584 apr_sha1_final(digest, &context);
585
586 *rval_len = APR_SHA1_DIGESTSIZE;
587 *rval = apr_pstrmemdup(mptmp, (const char *)digest, APR_SHA1_DIGESTSIZE);
588
589 return 1;
590 }
591
592 /**
593 * \brief SqlHexDecode transformation function. Transform xNN data.
594 *
595 * \param mptmp Pointer to resource pool
596 * \param input Pointer to input data
597 * \param input_len Input data length
598 * \param rval Pointer to decoded buffer
599 * \param rval_len Decoded buffer length
600 *
601 * \retval 0 On failure
602 * \retval 1 On Success
603 */
msre_fn_sqlHexDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)604 static int msre_fn_sqlHexDecode_execute(apr_pool_t *mptmp, unsigned char *input,
605 long int input_len, char **rval, long int *rval_len)
606 {
607 *rval_len = sql_hex2bytes_inplace(input, input_len);
608 *rval = (char *)input;
609
610 return 1;
611 }
612
613 /* hexDecode */
614
msre_fn_hexDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)615 static int msre_fn_hexDecode_execute(apr_pool_t *mptmp, unsigned char *input,
616 long int input_len, char **rval, long int *rval_len)
617 {
618 *rval_len = hex2bytes_inplace(input, input_len);
619 *rval = (char *)input;
620
621 return 1;
622 }
623
624 /* hexEncode */
625
msre_fn_hexEncode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)626 static int msre_fn_hexEncode_execute(apr_pool_t *mptmp, unsigned char *input,
627 long int input_len, char **rval, long int *rval_len)
628 {
629 *rval = bytes2hex(mptmp, input, input_len);
630 *rval_len = strlen(*rval);
631
632 return 1;
633 }
634
635 /* htmlEntityDecode */
636
msre_fn_htmlEntityDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)637 static int msre_fn_htmlEntityDecode_execute(apr_pool_t *mptmp, unsigned char *input,
638 long int input_len, char **rval, long int *rval_len)
639 {
640 *rval_len = html_entities_decode_inplace(mptmp, input, input_len);
641 *rval = (char *)input;
642
643 return (*rval_len == input_len ? 0 : 1);
644 }
645
646 /* escapeSeqDecode */
647
msre_fn_escapeSeqDecode_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)648 static int msre_fn_escapeSeqDecode_execute(apr_pool_t *mptmp, unsigned char *input,
649 long int input_len, char **rval, long int *rval_len)
650 {
651 *rval_len = ansi_c_sequences_decode_inplace(input, input_len);
652 *rval = (char *)input;
653
654 return (*rval_len == input_len ? 0 : 1);
655 }
656
657 /* normalizePath */
658
msre_fn_normalizePath_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)659 static int msre_fn_normalizePath_execute(apr_pool_t *mptmp, unsigned char *input,
660 long int input_len, char **rval, long int *rval_len)
661 {
662 int changed;
663
664 *rval_len = normalize_path_inplace(input, input_len, 0, &changed);
665 *rval = (char *)input;
666
667 return changed;
668 }
669
670 /* normalizePathWin */
671
msre_fn_normalizePathWin_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)672 static int msre_fn_normalizePathWin_execute(apr_pool_t *mptmp, unsigned char *input,
673 long int input_len, char **rval, long int *rval_len)
674 {
675 int changed;
676
677 *rval_len = normalize_path_inplace(input, input_len, 1, &changed);
678 *rval = (char *)input;
679
680 return changed;
681 }
682
683 /* parityEven7bit */
684
msre_fn_parityEven7bit_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)685 static int msre_fn_parityEven7bit_execute(apr_pool_t *mptmp, unsigned char *input,
686 long int input_len, char **rval, long int *rval_len)
687 {
688 long int i;
689 int changed = 0;
690
691 if (rval == NULL) return -1;
692 *rval = NULL;
693
694 i = 0;
695 while(i < input_len) {
696 unsigned int x = input[i];
697
698 input[i] ^= input[i] >> 4;
699 input[i] &= 0xf;
700
701 if ((0x6996 >> input[i]) & 1) {
702 input[i] = x | 0x80;
703 }
704 else {
705 input[i] = x & 0x7f;
706 }
707
708 if (x != input[i]) changed = 1;
709 i++;
710 }
711
712 *rval = (char *)input;
713 *rval_len = input_len;
714
715 return changed;
716 }
717
718 /* parityZero7bit */
719
msre_fn_parityZero7bit_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)720 static int msre_fn_parityZero7bit_execute(apr_pool_t *mptmp, unsigned char *input,
721 long int input_len, char **rval, long int *rval_len)
722 {
723 long int i;
724 int changed = 0;
725
726 if (rval == NULL) return -1;
727 *rval = NULL;
728
729 i = 0;
730 while(i < input_len) {
731 unsigned char c = input[i];
732 input[i] &= 0x7f;
733 if (c != input[i]) changed = 1;
734 i++;
735 }
736
737 *rval = (char *)input;
738 *rval_len = input_len;
739
740 return changed;
741 }
742
743 /* parityOdd7bit */
744
msre_fn_parityOdd7bit_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)745 static int msre_fn_parityOdd7bit_execute(apr_pool_t *mptmp, unsigned char *input,
746 long int input_len, char **rval, long int *rval_len)
747 {
748 long int i;
749 int changed = 0;
750
751 if (rval == NULL) return -1;
752 *rval = NULL;
753
754 i = 0;
755 while(i < input_len) {
756 unsigned int x = input[i];
757
758 input[i] ^= input[i] >> 4;
759 input[i] &= 0xf;
760
761 if ((0x6996 >> input[i]) & 1) {
762 input[i] = x & 0x7f;
763 }
764 else {
765 input[i] = x | 0x80;
766 }
767
768 if (x != input[i]) changed = 1;
769 i++;
770 }
771
772 *rval = (char *)input;
773 *rval_len = input_len;
774
775 return changed;
776 }
777
778 /**
779 * \brief Base64 transformation function based on RFC2045
780 *
781 * \param mptmp Pointer to resource pool
782 * \param input Pointer to input data
783 * \param input_len Input data length
784 * \param rval Pointer to decoded buffer
785 * \param rval_len Decoded buffer length
786 *
787 * \retval 0 On failure
788 * \retval 1 On Success
789 */
msre_fn_base64DecodeExt_execute(apr_pool_t * mptmp,unsigned char * input,long int input_len,char ** rval,long int * rval_len)790 static int msre_fn_base64DecodeExt_execute(apr_pool_t *mptmp, unsigned char *input, long int input_len, char **rval, long int *rval_len)
791 {
792 *rval_len = input_len;
793 *rval = apr_palloc(mptmp, *rval_len);
794 *rval_len = decode_base64_ext(*rval, (const unsigned char *)input, input_len);
795
796 return *rval_len ? 1 : 0;
797 }
798
799
800 /* ------------------------------------------------------------------------------ */
801
802 /**
803 * Registers one transformation function with the engine.
804 */
msre_engine_tfn_register(msre_engine * engine,const char * name,fn_tfn_execute_t execute)805 void msre_engine_tfn_register(msre_engine *engine, const char *name,
806 fn_tfn_execute_t execute)
807 {
808 msre_tfn_metadata *metadata = (msre_tfn_metadata *)apr_pcalloc(engine->mp,
809 sizeof(msre_tfn_metadata));
810 if (metadata == NULL) return;
811
812 metadata->name = name;
813 metadata->execute = execute;
814
815 apr_table_setn(engine->tfns, name, (void *)metadata);
816 }
817
818 /**
819 * Returns transformation function metadata given a name.
820 */
msre_engine_tfn_resolve(msre_engine * engine,const char * name)821 msre_tfn_metadata *msre_engine_tfn_resolve(msre_engine *engine, const char *name) {
822 return (msre_tfn_metadata *)apr_table_get(engine->tfns, name);
823 }
824
825 /**
826 * Register the default transformation functions.
827 */
msre_engine_register_default_tfns(msre_engine * engine)828 void msre_engine_register_default_tfns(msre_engine *engine) {
829
830 /* none */
831 msre_engine_tfn_register(engine,
832 "none",
833 NULL
834 );
835
836 /* base64Decode */
837 msre_engine_tfn_register(engine,
838 "base64Decode",
839 msre_fn_base64Decode_execute
840 );
841
842 /* base64Encode */
843 msre_engine_tfn_register(engine,
844 "base64Encode",
845 msre_fn_base64Encode_execute
846 );
847
848 /* compressWhitespace */
849 msre_engine_tfn_register(engine,
850 "compressWhitespace",
851 msre_fn_compressWhitespace_execute
852 );
853
854 /* cssDecode */
855 msre_engine_tfn_register(engine,
856 "cssDecode",
857 msre_fn_cssDecode_execute
858 );
859
860 /* escapeSeqDecode */
861 msre_engine_tfn_register(engine,
862 "escapeSeqDecode",
863 msre_fn_escapeSeqDecode_execute
864 );
865
866 /* sqlHexDecode */
867 msre_engine_tfn_register(engine,
868 "sqlHexDecode",
869 msre_fn_sqlHexDecode_execute
870 );
871
872 /* hexDecode */
873 msre_engine_tfn_register(engine,
874 "hexDecode",
875 msre_fn_hexDecode_execute
876 );
877
878 /* hexEncode */
879 msre_engine_tfn_register(engine,
880 "hexEncode",
881 msre_fn_hexEncode_execute
882 );
883
884 /* htmlEntityDecode */
885 msre_engine_tfn_register(engine,
886 "htmlEntityDecode",
887 msre_fn_htmlEntityDecode_execute
888 );
889
890 /* jsDecode */
891 msre_engine_tfn_register(engine,
892 "jsDecode",
893 msre_fn_jsDecode_execute
894 );
895
896 /* length */
897 msre_engine_tfn_register(engine,
898 "length",
899 msre_fn_length_execute
900 );
901
902 /* lowercase */
903 msre_engine_tfn_register(engine,
904 "lowercase",
905 msre_fn_lowercase_execute
906 );
907
908 /* md5 */
909 msre_engine_tfn_register(engine,
910 "md5",
911 msre_fn_md5_execute
912 );
913
914 /* normalisePath */
915 msre_engine_tfn_register(engine,
916 "normalisePath",
917 msre_fn_normalizePath_execute
918 );
919
920 /* normalizePath */
921 msre_engine_tfn_register(engine,
922 "normalizePath",
923 msre_fn_normalizePath_execute
924 );
925
926 /* normalisePathWin */
927 msre_engine_tfn_register(engine,
928 "normalisePathWin",
929 msre_fn_normalizePathWin_execute
930 );
931
932 /* normalizePathWin */
933 msre_engine_tfn_register(engine,
934 "normalizePathWin",
935 msre_fn_normalizePathWin_execute
936 );
937
938 /* parityEven7bit */
939 msre_engine_tfn_register(engine,
940 "parityEven7bit",
941 msre_fn_parityEven7bit_execute
942 );
943
944 /* parityZero7bit */
945 msre_engine_tfn_register(engine,
946 "parityZero7bit",
947 msre_fn_parityZero7bit_execute
948 );
949
950 /* parityOdd7bit */
951 msre_engine_tfn_register(engine,
952 "parityOdd7bit",
953 msre_fn_parityOdd7bit_execute
954 );
955
956 /* removeWhitespace */
957 msre_engine_tfn_register(engine,
958 "removeWhitespace",
959 msre_fn_removeWhitespace_execute
960 );
961
962 /* removeNulls */
963 msre_engine_tfn_register(engine,
964 "removeNulls",
965 msre_fn_removeNulls_execute
966 );
967
968 /* replaceNulls */
969 msre_engine_tfn_register(engine,
970 "replaceNulls",
971 msre_fn_replaceNulls_execute
972 );
973
974 /* removeComments */
975 msre_engine_tfn_register(engine,
976 "removeComments",
977 msre_fn_removeComments_execute
978 );
979
980 /* removeCommentsChar */
981 msre_engine_tfn_register(engine,
982 "removeCommentsChar",
983 msre_fn_removeCommentsChar_execute
984 );
985
986 /* replaceComments */
987 msre_engine_tfn_register(engine,
988 "replaceComments",
989 msre_fn_replaceComments_execute
990 );
991
992 /* sha1 */
993 msre_engine_tfn_register(engine,
994 "sha1",
995 msre_fn_sha1_execute
996 );
997
998 /* trim */
999 msre_engine_tfn_register(engine,
1000 "trim",
1001 msre_fn_trim_execute
1002 );
1003
1004 /* trimLeft */
1005 msre_engine_tfn_register(engine,
1006 "trimLeft",
1007 msre_fn_trimLeft_execute
1008 );
1009
1010 msre_engine_tfn_register(engine,
1011 "cmdline",
1012 msre_fn_cmdline_execute
1013 );
1014
1015 /* trimRight */
1016 msre_engine_tfn_register(engine,
1017 "trimRight",
1018 msre_fn_trimRight_execute
1019 );
1020
1021 /* urlDecode */
1022 msre_engine_tfn_register(engine,
1023 "urlDecode",
1024 msre_fn_urlDecode_execute
1025 );
1026
1027 /* urlDecodeUni */
1028 msre_engine_tfn_register(engine,
1029 "urlDecodeUni",
1030 msre_fn_urlDecodeUni_execute
1031 );
1032
1033 /* Utf8Unicode */
1034 msre_engine_tfn_register(engine,
1035 "Utf8toUnicode",
1036 msre_fn_utf8Unicode_execute
1037 );
1038
1039 /* urlEncode */
1040 msre_engine_tfn_register(engine,
1041 "urlEncode",
1042 msre_fn_urlEncode_execute
1043 );
1044
1045 /* base64DecodeExt */
1046 msre_engine_tfn_register(engine,
1047 "base64DecodeExt",
1048 msre_fn_base64DecodeExt_execute
1049 );
1050
1051 }
1052