2 * ModSecurity for Apache 2.x, http://www.modsecurity.org/
3 * Copyright (c) 2004-2009 Breach Security, Inc. (http://www.breach.com/)
5 * This product is released under the terms of the General Public Licence,
6 * version 2 (GPLv2). Please refer to the file LICENSE (included with this
7 * distribution) which contains the complete text of the licence.
9 * There are special exceptions to the terms and conditions of the GPL
10 * as it is applied to this software. View the full text of the exception in
11 * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software
14 * If any of the files related to licensing are missing or if you have any
15 * other questions related to licensing please contact Breach Security, Inc.
16 * directly using the email address support@breach.com.
23 #include "apr_base64.h"
30 static int msre_fn_lowercase_execute(apr_pool_t *mptmp, unsigned char *input,
31 long int input_len, char **rval, long int *rval_len)
36 if (rval == NULL) return -1;
40 while(i < input_len) {
42 input[i] = tolower(x);
43 if (x != input[i]) changed = 1;
47 *rval = (char *)input;
48 *rval_len = input_len;
55 static int msre_fn_trimLeft_execute(apr_pool_t *mptmp, unsigned char *input,
56 long int input_len, char **rval, long int *rval_len)
60 *rval = (char *)input;
61 for (i = 0; i < input_len; i++) {
62 if (isspace(**rval) == 0) {
68 *rval_len = input_len - i;
70 return (*rval_len == input_len ? 0 : 1);
75 static int msre_fn_trimRight_execute(apr_pool_t *mptmp, unsigned char *input,
76 long int input_len, char **rval, long int *rval_len)
80 *rval = (char *)input;
81 for (i = input_len - 1; i >= 0; i--) {
82 if (isspace((*rval)[i]) == 0) {
90 return (*rval_len == input_len ? 0 : 1);
95 static int msre_fn_trim_execute(apr_pool_t *mptmp, unsigned char *input,
96 long int input_len, char **rval, long int *rval_len)
100 rc = msre_fn_trimLeft_execute(mptmp, input, input_len, rval, rval_len);
102 rc = msre_fn_trimRight_execute(mptmp, (unsigned char *)*rval, *rval_len, rval, rval_len);
105 rc = msre_fn_trimRight_execute(mptmp, input, input_len, rval, rval_len);
108 return (*rval_len == input_len ? 0 : 1);
113 static int msre_fn_removeNulls_execute(apr_pool_t *mptmp, unsigned char *input,
114 long int input_len, char **rval, long int *rval_len)
120 while(i < input_len) {
121 if (input[i] == '\0') {
130 *rval = (char *)input;
138 static int msre_fn_replaceNulls_execute(apr_pool_t *mptmp, unsigned char *input,
139 long int input_len, char **rval, long int *rval_len)
144 if (rval == NULL) return -1;
148 while(i < input_len) {
149 if (input[i] == '\0') {
156 *rval = (char *)input;
157 *rval_len = input_len;
162 /* compressWhitespace */
164 static int msre_fn_compressWhitespace_execute(apr_pool_t *mptmp, unsigned char *input,
165 long int input_len, char **rval, long int *rval_len)
167 long int i, j, count;
169 int inwhitespace = 0;
172 while(i < input_len) {
173 if (isspace(input[i])||(input[i] == NBSP)) {
174 if (inwhitespace) changed = 1;
195 *rval = (char *)input;
203 static int msre_fn_cssDecode_execute(apr_pool_t *mptmp, unsigned char *input,
204 long int input_len, char **rval, long int *rval_len)
208 length = css_decode_inplace(input, input_len);
209 *rval = (char *)input;
212 return (*rval_len == input_len ? 0 : 1);
215 /* removeWhitespace */
217 static int msre_fn_removeWhitespace_execute(apr_pool_t *mptmp, unsigned char *input,
218 long int input_len, char **rval, long int *rval_len)
224 while(i < input_len) {
225 if (isspace(input[i])||(input[i] == NBSP)) {
235 *rval = (char *)input;
241 /* replaceComments */
243 static int msre_fn_replaceComments_execute(apr_pool_t *mptmp, unsigned char *input,
244 long int input_len, char **rval, long int *rval_len)
246 long int i, j, incomment;
249 i = j = incomment = 0;
250 while(i < input_len) {
251 if (incomment == 0) {
252 if ((input[i] == '/')&&(i + 1 < input_len)&&(input[i + 1] == '*')) {
262 if ((input[i] == '*')&&(i + 1 < input_len)&&(input[i + 1] == '/')) {
277 *rval = (char *)input;
285 static int msre_fn_jsDecode_execute(apr_pool_t *mptmp, unsigned char *input,
286 long int input_len, char **rval, long int *rval_len)
290 length = js_decode_nonstrict_inplace(input, input_len);
291 *rval = (char *)input;
294 return (*rval_len == input_len ? 0 : 1);
299 static int msre_fn_urlDecode_execute(apr_pool_t *mptmp, unsigned char *input,
300 long int input_len, char **rval, long int *rval_len)
306 length = urldecode_nonstrict_inplace_ex(input, input_len, &invalid_count, &changed);
307 *rval = (char *)input;
315 static int msre_fn_urlDecodeUni_execute(apr_pool_t *mptmp, unsigned char *input,
316 long int input_len, char **rval, long int *rval_len)
321 length = urldecode_uni_nonstrict_inplace_ex(input, input_len, &changed);
322 *rval = (char *)input;
330 static int msre_fn_urlEncode_execute(apr_pool_t *mptmp, unsigned char *input,
331 long int input_len, char **rval, long int *rval_len)
335 *rval = url_encode(mptmp, (char *)input, input_len, &changed);
336 *rval_len = strlen(*rval);
343 static int msre_fn_base64Encode_execute(apr_pool_t *mptmp, unsigned char *input,
344 long int input_len, char **rval, long int *rval_len)
346 *rval_len = apr_base64_encode_len(input_len); /* returns len with NULL byte included */
347 *rval = apr_palloc(mptmp, *rval_len);
348 apr_base64_encode(*rval, (const char *)input, input_len);
351 return *rval_len ? 1 : 0;
356 static int msre_fn_base64Decode_execute(apr_pool_t *mptmp, unsigned char *input,
357 long int input_len, char **rval, long int *rval_len)
359 *rval_len = apr_base64_decode_len((const char *)input); /* returns len with NULL byte included */
360 *rval = apr_palloc(mptmp, *rval_len);
361 *rval_len = apr_base64_decode(*rval, (const char *)input);
363 return *rval_len ? 1 : 0;
368 static int msre_fn_length_execute(apr_pool_t *mptmp, unsigned char *input,
369 long int input_len, char **rval, long int *rval_len)
371 *rval = apr_psprintf(mptmp, "%ld", input_len);
372 *rval_len = strlen(*rval);
379 static int msre_fn_md5_execute(apr_pool_t *mptmp, unsigned char *input,
380 long int input_len, char **rval, long int *rval_len)
382 unsigned char digest[APR_MD5_DIGESTSIZE];
384 apr_md5(digest, input, input_len);
386 *rval_len = APR_MD5_DIGESTSIZE;
387 *rval = apr_pstrmemdup(mptmp, (const char *)digest, APR_MD5_DIGESTSIZE);
394 static int msre_fn_sha1_execute(apr_pool_t *mptmp, unsigned char *input,
395 long int input_len, char **rval, long int *rval_len)
397 unsigned char digest[APR_SHA1_DIGESTSIZE];
398 apr_sha1_ctx_t context;
400 apr_sha1_init(&context);
401 apr_sha1_update(&context, (const char *)input, input_len);
402 apr_sha1_final(digest, &context);
404 *rval_len = APR_SHA1_DIGESTSIZE;
405 *rval = apr_pstrmemdup(mptmp, (const char *)digest, APR_SHA1_DIGESTSIZE);
412 static int msre_fn_hexDecode_execute(apr_pool_t *mptmp, unsigned char *input,
413 long int input_len, char **rval, long int *rval_len)
415 *rval_len = hex2bytes_inplace(input, input_len);
416 *rval = (char *)input;
423 static int msre_fn_hexEncode_execute(apr_pool_t *mptmp, unsigned char *input,
424 long int input_len, char **rval, long int *rval_len)
426 *rval = bytes2hex(mptmp, input, input_len);
427 *rval_len = strlen(*rval);
432 /* htmlEntityDecode */
434 static int msre_fn_htmlEntityDecode_execute(apr_pool_t *mptmp, unsigned char *input,
435 long int input_len, char **rval, long int *rval_len)
437 *rval_len = html_entities_decode_inplace(mptmp, input, input_len);
438 *rval = (char *)input;
440 return (*rval_len == input_len ? 0 : 1);
443 /* escapeSeqDecode */
445 static int msre_fn_escapeSeqDecode_execute(apr_pool_t *mptmp, unsigned char *input,
446 long int input_len, char **rval, long int *rval_len)
448 *rval_len = ansi_c_sequences_decode_inplace(input, input_len);
449 *rval = (char *)input;
451 return (*rval_len == input_len ? 0 : 1);
456 static int msre_fn_normalisePath_execute(apr_pool_t *mptmp, unsigned char *input,
457 long int input_len, char **rval, long int *rval_len)
461 *rval_len = normalise_path_inplace(input, input_len, 0, &changed);
462 *rval = (char *)input;
467 /* normalisePathWin */
469 static int msre_fn_normalisePathWin_execute(apr_pool_t *mptmp, unsigned char *input,
470 long int input_len, char **rval, long int *rval_len)
474 *rval_len = normalise_path_inplace(input, input_len, 1, &changed);
475 *rval = (char *)input;
482 static int msre_fn_parityEven7bit_execute(apr_pool_t *mptmp, unsigned char *input,
483 long int input_len, char **rval, long int *rval_len)
488 if (rval == NULL) return -1;
492 while(i < input_len) {
493 unsigned int x = input[i];
495 input[i] ^= input[i] >> 4;
498 if ((0x6996 >> input[i]) & 1) {
505 if (x != input[i]) changed = 1;
509 *rval = (char *)input;
510 *rval_len = input_len;
517 static int msre_fn_parityZero7bit_execute(apr_pool_t *mptmp, unsigned char *input,
518 long int input_len, char **rval, long int *rval_len)
523 if (rval == NULL) return -1;
527 while(i < input_len) {
528 unsigned char c = input[i];
530 if (c != input[i]) changed = 1;
534 *rval = (char *)input;
535 *rval_len = input_len;
542 static int msre_fn_parityOdd7bit_execute(apr_pool_t *mptmp, unsigned char *input,
543 long int input_len, char **rval, long int *rval_len)
548 if (rval == NULL) return -1;
552 while(i < input_len) {
553 unsigned int x = input[i];
555 input[i] ^= input[i] >> 4;
558 if ((0x6996 >> input[i]) & 1) {
565 if (x != input[i]) changed = 1;
569 *rval = (char *)input;
570 *rval_len = input_len;
575 /* ------------------------------------------------------------------------------ */
578 * Registers one transformation function with the engine.
580 void msre_engine_tfn_register(msre_engine *engine, const char *name,
581 fn_tfn_execute_t execute)
583 msre_tfn_metadata *metadata = (msre_tfn_metadata *)apr_pcalloc(engine->mp,
584 sizeof(msre_tfn_metadata));
585 if (metadata == NULL) return;
587 metadata->name = name;
588 metadata->execute = execute;
590 apr_table_setn(engine->tfns, name, (void *)metadata);
594 * Returns transformation function metadata given a name.
596 msre_tfn_metadata *msre_engine_tfn_resolve(msre_engine *engine, const char *name) {
597 return (msre_tfn_metadata *)apr_table_get(engine->tfns, name);
601 * Register the default transformation functions.
603 void msre_engine_register_default_tfns(msre_engine *engine) {
606 msre_engine_tfn_register(engine,
612 msre_engine_tfn_register(engine,
614 msre_fn_base64Decode_execute
618 msre_engine_tfn_register(engine,
620 msre_fn_base64Encode_execute
623 /* compressWhitespace */
624 msre_engine_tfn_register(engine,
625 "compressWhitespace",
626 msre_fn_compressWhitespace_execute
630 msre_engine_tfn_register(engine,
632 msre_fn_cssDecode_execute
635 /* escapeSeqDecode */
636 msre_engine_tfn_register(engine,
638 msre_fn_escapeSeqDecode_execute
642 msre_engine_tfn_register(engine,
644 msre_fn_hexDecode_execute
648 msre_engine_tfn_register(engine,
650 msre_fn_hexEncode_execute
653 /* htmlEntityDecode */
654 msre_engine_tfn_register(engine,
656 msre_fn_htmlEntityDecode_execute
660 msre_engine_tfn_register(engine,
662 msre_fn_jsDecode_execute
666 msre_engine_tfn_register(engine,
668 msre_fn_length_execute
672 msre_engine_tfn_register(engine,
674 msre_fn_lowercase_execute
678 msre_engine_tfn_register(engine,
684 msre_engine_tfn_register(engine,
686 msre_fn_normalisePath_execute
689 /* normalisePathWin */
690 msre_engine_tfn_register(engine,
692 msre_fn_normalisePathWin_execute
696 msre_engine_tfn_register(engine,
698 msre_fn_parityEven7bit_execute
702 msre_engine_tfn_register(engine,
704 msre_fn_parityZero7bit_execute
708 msre_engine_tfn_register(engine,
710 msre_fn_parityOdd7bit_execute
713 /* removeWhitespace */
714 msre_engine_tfn_register(engine,
716 msre_fn_removeWhitespace_execute
720 msre_engine_tfn_register(engine,
722 msre_fn_removeNulls_execute
726 msre_engine_tfn_register(engine,
728 msre_fn_replaceNulls_execute
731 /* replaceComments */
732 msre_engine_tfn_register(engine,
734 msre_fn_replaceComments_execute
738 msre_engine_tfn_register(engine,
744 msre_engine_tfn_register(engine,
750 msre_engine_tfn_register(engine,
752 msre_fn_trimLeft_execute
756 msre_engine_tfn_register(engine,
758 msre_fn_trimRight_execute
762 msre_engine_tfn_register(engine,
764 msre_fn_urlDecode_execute
768 msre_engine_tfn_register(engine,
770 msre_fn_urlDecodeUni_execute
774 msre_engine_tfn_register(engine,
776 msre_fn_urlEncode_execute