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