From 10713fbd378f27023bbff8840447ad0b0d965088 Mon Sep 17 00:00:00 2001 From: brectanus Date: Thu, 31 Jul 2008 22:36:24 +0000 Subject: [PATCH] Sync up branches/2.5.x and trunk. --- CHANGES | 58 +++- README.TXT | 8 +- apache2/acmp.c | 19 +- apache2/acmp.h | 16 +- apache2/apache2.h | 16 +- apache2/apache2_config.c | 60 +++- apache2/apache2_io.c | 16 +- apache2/apache2_util.c | 30 +- apache2/configure | 26 +- apache2/configure.in | 23 +- apache2/mod_security2.c | 21 +- apache2/modsecurity.c | 81 ++++- apache2/modsecurity.h | 23 +- apache2/msc_geo.c | 16 +- apache2/msc_geo.h | 16 +- apache2/msc_logging.c | 16 +- apache2/msc_logging.h | 16 +- apache2/msc_lua.c | 16 +- apache2/msc_lua.h | 16 +- apache2/msc_multipart.c | 16 +- apache2/msc_multipart.h | 16 +- apache2/msc_parsers.c | 50 ++- apache2/msc_parsers.h | 16 +- apache2/msc_pcre.c | 16 +- apache2/msc_pcre.h | 16 +- apache2/msc_reqbody.c | 16 +- apache2/msc_test.c | 16 +- apache2/msc_util.c | 16 +- apache2/msc_util.h | 16 +- apache2/msc_xml.c | 16 +- apache2/msc_xml.h | 16 +- apache2/pdf_protect.c | 16 +- apache2/pdf_protect.h | 17 +- apache2/persist_dbm.c | 16 +- apache2/persist_dbm.h | 16 +- apache2/re.c | 297 +++++++++++------- apache2/re.h | 16 +- apache2/re_actions.c | 16 +- apache2/re_operators.c | 16 +- apache2/re_tfns.c | 16 +- apache2/re_variables.c | 124 ++++---- .../action/10-detectiononly-actions.t | 8 +- apache2/t/regression/misc/10-tfn-cache.t | 189 +++++++++++ apache2/t/run-regression-tests.pl.in | 133 +++++--- apache2/utf8tables.h | 18 +- doc/modsecurity2-apache-reference.xml | 188 +++++++---- 46 files changed, 1318 insertions(+), 487 deletions(-) create mode 100644 apache2/t/regression/misc/10-tfn-cache.t diff --git a/CHANGES b/CHANGES index f9ce7d87..25868aa8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,33 +1,61 @@ +31 Jul 2008 - trunk +======= -16 Jul 2008 - trunk + * Implement cssDecode. + + * Persistent counter updates are now atomic. + + +31 Jul 2008 - 2.5.6 ------------------- + + * Transformation caching has been deprecated, and is now off by default. We + now advise against using transformation caching in production. + + * Fixed two separate transformation caching issues that could cause incorrect + content inspection in some circumstances. + + * Fixed an issue with the transformation cache using too much RAM, potentially + crashing Apache with a large number of cache entries. Two new configuration + options have been added to allow for a finer control of caching: + + maxitems: Max number of items to cache (default 1024) + incremental: Whether to cache incrementally (default off) -* Implement cssDecode. + * Added an experimental regression testing suite. The regression suite may + be executed via "make test-regression", however it is strongly advised + to only be executed on a non-production machine as it will startup the + Apache web server that ModSecurity is compiled against with various + configurations in which it will run tests. -* Persistent counter updates are now atomic. + * Added a licensing exception so that ModSecurity can be used in a derivative + work when that derivative is also under an approved open source license. + + * Updated mlogc to version 1.4.5 which adds a LockFile directive and fixes an + issue in which the configuration file may be deleted. 05 Jun 2008 - 2.5.5 ------------------- -* Fixed an issue where an alert was not logged in the error log - unless "auditlog" was used. + * Fixed an issue where an alert was not logged in the error log + unless "auditlog" was used. -* Enable the "auditlog" action by default to help prevent a misconfiguration. - The new default is now: "phase:2,log,auditlog,pass" + * Enable the "auditlog" action by default to help prevent a misconfiguration. + The new default is now: "phase:2,log,auditlog,pass" -* Improve request body processing error messages. + * Improve request body processing error messages. -* Handle lack of a new line after the final boundary in a multipart request. - This fixes the reported WordPress Flash file uploader problem. + * Handle lack of a new line after the final boundary in a multipart request. + This fixes the reported WordPress Flash file uploader problem. -* Fixed issue with multithreaded servers where concurrent XML processing - could crash the web server (at least under Windows). + * Fixed issue with multithreaded servers where concurrent XML processing + could crash the web server (at least under Windows). -* Fixed blocking in phase 3. + * Fixed blocking in phase 3. -* Force modules "mod_rpaf-2.0.c" and "mod_custom_header.c" to run before - ModSecurity so that the correct IP is used. + * Force modules "mod_rpaf-2.0.c" and "mod_custom_header.c" to run before + ModSecurity so that the correct IP is used. 07 May 2008 - 2.5.4 diff --git a/README.TXT b/README.TXT index f0ac7445..791e9497 100644 --- a/README.TXT +++ b/README.TXT @@ -5,9 +5,11 @@ ModSecurity for Apache is an open source product, released under terms of the General Public Licence, Version 2 (GPLv2). Please refer to the file LICENSE, which contains the complete text of the licence. -Additionally, certain software may be granted further rights via -a licensing exception. Please refer to the file MODSECURITY_LICENSE_EXCEPTION, -which contains the complete exception. +There are special exceptions to the terms and conditions of the GPL +as it is applied to this software. View the full text of the exception in +file MODSECURITY_LICENSING_EXCEPTION in the directory of this software +distribution. + DOCUMENTATION diff --git a/apache2/acmp.c b/apache2/acmp.c index 734c6666..5ca6d5c1 100644 --- a/apache2/acmp.c +++ b/apache2/acmp.c @@ -2,12 +2,23 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ + +/* Aho-Corasick Matching */ + #include "acmp.h" #ifdef ACMP_USE_UTF8 diff --git a/apache2/acmp.h b/apache2/acmp.h index f79a44cd..bad3bd9e 100644 --- a/apache2/acmp.h +++ b/apache2/acmp.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef ACMP_H_ diff --git a/apache2/apache2.h b/apache2/apache2.h index 7dc623b4..f82438e8 100644 --- a/apache2/apache2.h +++ b/apache2/apache2.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _APACHE2_H_ diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index 6de2223a..7e54f409 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include @@ -102,8 +110,10 @@ void *create_directory_config(apr_pool_t *mp, char *path) { /* Cache */ dcfg->cache_trans = NOT_SET; + dcfg->cache_trans_incremental = NOT_SET; dcfg->cache_trans_min = NOT_SET; dcfg->cache_trans_max = NOT_SET; + dcfg->cache_trans_maxitems = NOT_SET; dcfg->component_signatures = apr_array_make(mp, 16, sizeof(char *)); @@ -439,10 +449,14 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) { /* Cache */ merged->cache_trans = (child->cache_trans == NOT_SET ? parent->cache_trans : child->cache_trans); + merged->cache_trans_incremental = (child->cache_trans_incremental == NOT_SET + ? parent->cache_trans_incremental : child->cache_trans_incremental); merged->cache_trans_min = (child->cache_trans_min == (apr_size_t)NOT_SET ? parent->cache_trans_min : child->cache_trans_min); merged->cache_trans_max = (child->cache_trans_max == (apr_size_t)NOT_SET ? parent->cache_trans_max : child->cache_trans_max); + merged->cache_trans_maxitems = (child->cache_trans_maxitems == (apr_size_t)NOT_SET + ? parent->cache_trans_maxitems : child->cache_trans_maxitems); /* Merge component signatures. */ merged->component_signatures = apr_array_append(mp, parent->component_signatures, @@ -528,9 +542,11 @@ void init_directory_config(directory_config *dcfg) { if (dcfg->geo == NOT_SET_P) dcfg->geo = NULL; /* Cache */ - if (dcfg->cache_trans == NOT_SET) dcfg->cache_trans = MODSEC_CACHE_ENABLED; - if (dcfg->cache_trans_min == (apr_size_t)NOT_SET) dcfg->cache_trans_min = 15; - if (dcfg->cache_trans_max == (apr_size_t)NOT_SET) dcfg->cache_trans_max = 0; + if (dcfg->cache_trans == NOT_SET) dcfg->cache_trans = MODSEC_CACHE_DISABLED; + if (dcfg->cache_trans_incremental == NOT_SET) dcfg->cache_trans_incremental = 0; + if (dcfg->cache_trans_min == (apr_size_t)NOT_SET) dcfg->cache_trans_min = 32; + if (dcfg->cache_trans_max == (apr_size_t)NOT_SET) dcfg->cache_trans_max = 1024; + if (dcfg->cache_trans_maxitems == (apr_size_t)NOT_SET) dcfg->cache_trans_maxitems = 512; if (dcfg->request_encoding == NOT_SET_P) dcfg->request_encoding = NULL; } @@ -1650,7 +1666,7 @@ static const char *cmd_cache_transformations(cmd_parms *cmd, void *_dcfg, const /* Process options */ if (p2 != NULL) { - apr_table_t *vartable = apr_table_make(cmd->pool, 10); + apr_table_t *vartable = apr_table_make(cmd->pool, 4); apr_status_t rc; char *error_msg = NULL; const char *charval = NULL; @@ -1664,7 +1680,18 @@ static const char *cmd_cache_transformations(cmd_parms *cmd, void *_dcfg, const return apr_psprintf(cmd->pool, "ModSecurity: Unable to parse options for SecCacheTransformations: %s", error_msg); } - /* minval */ + /* incremental */ + charval = apr_table_get(vartable, "incremental"); + if (charval != NULL) { + if (strcasecmp(charval, "on") == 0) + dcfg->cache_trans_incremental = 1; + else if (strcasecmp(charval, "off") == 0) + dcfg->cache_trans_incremental = 0; + else + return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations invalid incremental value: %s", charval); + } + + /* minlen */ charval = apr_table_get(vartable, "minlen"); if (charval != NULL) { intval = apr_atoi64(charval); @@ -1684,7 +1711,7 @@ static const char *cmd_cache_transformations(cmd_parms *cmd, void *_dcfg, const dcfg->cache_trans_min = (apr_size_t)intval; } - /* maxval */ + /* maxlen */ charval = apr_table_get(vartable, "maxlen"); if (charval != NULL) { intval = apr_atoi64(charval); @@ -1707,6 +1734,19 @@ static const char *cmd_cache_transformations(cmd_parms *cmd, void *_dcfg, const dcfg->cache_trans_max = (apr_size_t)intval; } + + /* maxitems */ + charval = apr_table_get(vartable, "maxitems"); + if (charval != NULL) { + intval = apr_atoi64(charval); + if (errno == ERANGE) { + return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxitems out of range: %s", charval); + } + if (intval < 0) { + return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxitems must be positive: %s", charval); + } + dcfg->cache_trans_maxitems = (apr_size_t)intval; + } } return NULL; diff --git a/apache2/apache2_io.c b/apache2/apache2_io.c index b2ceda4e..457ee6cc 100644 --- a/apache2/apache2_io.c +++ b/apache2/apache2_io.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "modsecurity.h" diff --git a/apache2/apache2_util.c b/apache2/apache2_util.c index 9ebf34e6..19c7de84 100644 --- a/apache2/apache2_util.c +++ b/apache2/apache2_util.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "modsecurity.h" @@ -105,6 +113,10 @@ int apache2_exec(modsec_rec *msr, const char *command, const char **argv, char * apr_procattr_io_set(procattr, APR_NO_PIPE, APR_FULL_BLOCK, APR_NO_PIPE); apr_procattr_cmdtype_set(procattr, APR_SHELLCMD); + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Exec: %s", log_escape_nq(r->pool, command)); + } + rc = apr_proc_create(procnew, command, argv, env, procattr, r->pool); if (rc != APR_SUCCESS) { msr_log(msr, 1, "Exec: Execution failed: %s (%s)", log_escape_nq(r->pool, command), @@ -139,8 +151,10 @@ int apache2_exec(modsec_rec *msr, const char *command, const char **argv, char * p++; } - msr_log(msr, 4, "Exec: First line from script output: \"%s\"", - log_escape(r->pool, buf)); + if (msr->txcfg->debuglog_level >= 4) { + msr_log(msr, 4, "Exec: First line from script output: \"%s\"", + log_escape(r->pool, buf)); + } if (output != NULL) *output = apr_pstrdup(r->pool, buf); @@ -189,7 +203,9 @@ void record_time_checkpoint(modsec_rec *msr, int checkpoint_no) { apr_snprintf(note_name, 99, "mod_security-time%d", checkpoint_no); apr_table_set(msr->r->notes, note_name, note); - msr_log(msr, 4, "Time #%d: %s", checkpoint_no, note); + if (msr->txcfg->debuglog_level >= 4) { + msr_log(msr, 4, "Time #%d: %s", checkpoint_no, note); + } } /** diff --git a/apache2/configure b/apache2/configure index cc1071dd..eb397c48 100755 --- a/apache2/configure +++ b/apache2/configure @@ -1299,6 +1299,7 @@ Optional Features: --enable-debug-conf Enable debug during configuration. --enable-debug-cache Enable debug for transformation caching. --enable-debug-acmp Enable debugging acmp code. + --enable-debug-mem Enable debug during configuration. --enable-performance-measurement Enable performance-measurement stats. --disable-modsec-api Disable the API; compiling against some older Apache @@ -5257,6 +5258,23 @@ else fi +# DEBUG_MEM +# Check whether --enable-debug-mem was given. +if test "${enable_debug_mem+set}" = set; then + enableval=$enable_debug_mem; + if test "$enableval" != "no"; then + debug_mem="-DDEBUG_MEM" + else + debug_mem= + fi + +else + + debug_mem= + +fi + + # PERFORMANCE_MEASUREMENT # Check whether --enable-performance-measurement was given. if test "${enable_performance_measurement+set}" = set; then @@ -5293,8 +5311,12 @@ fi ### Build *EXTRA_CFLAGS vars -EXTRA_CFLAGS="-O2 -g -Wall $strict_compile" -MODSEC_EXTRA_CFLAGS="$debug_conf $debug_cache $debug_acmp $perf_meas $modsec_api" +if test -n "$debug_mem"; then + EXTRA_CFLAGS="-O0 -g -Wall" +else + EXTRA_CFLAGS="-O2 -g -Wall $strict_compile" +fi +MODSEC_EXTRA_CFLAGS="$debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api" APXS_WRAPPER=build/apxs-wrapper APXS_EXTRA_CFLAGS="" diff --git a/apache2/configure.in b/apache2/configure.in index 717221d6..2825c8b4 100644 --- a/apache2/configure.in +++ b/apache2/configure.in @@ -225,6 +225,21 @@ AC_ARG_ENABLE(debug-acmp, debug_acmp= ]) +# DEBUG_MEM +AC_ARG_ENABLE(debug-mem, + AS_HELP_STRING([--enable-debug-mem], + [Enable debug during configuration.]), +[ + if test "$enableval" != "no"; then + debug_mem="-DDEBUG_MEM" + else + debug_mem= + fi +], +[ + debug_mem= +]) + # PERFORMANCE_MEASUREMENT AC_ARG_ENABLE(performance-measurement, AS_HELP_STRING([--enable-performance-measurement], @@ -257,8 +272,12 @@ AC_ARG_ENABLE(modsec-api, ### Build *EXTRA_CFLAGS vars -EXTRA_CFLAGS="-O2 -g -Wall $strict_compile" -MODSEC_EXTRA_CFLAGS="$debug_conf $debug_cache $debug_acmp $perf_meas $modsec_api" +if test -n "$debug_mem"; then + EXTRA_CFLAGS="-O0 -g -Wall" +else + EXTRA_CFLAGS="-O2 -g -Wall $strict_compile" +fi +MODSEC_EXTRA_CFLAGS="$debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api" APXS_WRAPPER=build/apxs-wrapper APXS_EXTRA_CFLAGS="" diff --git a/apache2/mod_security2.c b/apache2/mod_security2.c index 903884c3..fe405407 100644 --- a/apache2/mod_security2.c +++ b/apache2/mod_security2.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include @@ -962,6 +970,8 @@ static void hook_insert_filter(request_rec *r) { } } +// TODO: Holding off on this for now (needs more testing) +#if 0 /** * Invoked whenever Apache starts processing an error. A chance * to insert ourselves into the output filter chain. @@ -1003,6 +1013,7 @@ static void hook_insert_error_filter(request_rec *r) { } } } +#endif #if (!defined(NO_MODSEC_API)) /** @@ -1106,7 +1117,9 @@ static void register_hooks(apr_pool_t *mp) { /* Filter hooks */ ap_hook_insert_filter(hook_insert_filter, NULL, NULL, APR_HOOK_FIRST); +#if 0 ap_hook_insert_error_filter(hook_insert_error_filter, NULL, NULL, APR_HOOK_FIRST); +#endif ap_register_input_filter("MODSECURITY_IN", input_filter, NULL, AP_FTYPE_CONTENT_SET); diff --git a/apache2/modsecurity.c b/apache2/modsecurity.c index f3139b16..fd8236ea 100644 --- a/apache2/modsecurity.c +++ b/apache2/modsecurity.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include @@ -314,8 +322,8 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) { if (msr->collections_dirty == NULL) return -1; /* Other */ - msr->tcache = apr_hash_make(msr->mp); - if (msr->tcache == NULL) return -1; + msr->tcache = NULL; + msr->tcache_items = 0; msr->matched_rules = apr_array_make(msr->mp, 16, sizeof(void *)); if (msr->matched_rules == NULL) return -1; @@ -497,19 +505,76 @@ static apr_status_t modsecurity_process_phase_logging(modsec_rec *msr) { apr_status_t modsecurity_process_phase(modsec_rec *msr, unsigned int phase) { /* Check if we should run. */ if ((msr->was_intercepted)&&(phase != PHASE_LOGGING)) { - msr_log(msr, 4, "Skipping phase %i as request was already intercepted.", phase); + msr_log(msr, 4, "Skipping phase %d as request was already intercepted.", phase); return 0; } /* Do not process the same phase twice. */ if (msr->phase >= phase) { - msr_log(msr, 4, "Skipping phase %i because it was previously run (at %i now).", + msr_log(msr, 4, "Skipping phase %d because it was previously run (at %d now).", phase, msr->phase); return 0; } msr->phase = phase; + /* Clear out the transformation cache at the start of each phase */ + if (msr->txcfg->cache_trans == MODSEC_CACHE_ENABLED) { + if (msr->tcache) { + apr_hash_index_t *hi; + void *dummy; + apr_table_t *tab; + const void *key; + apr_ssize_t klen; + #ifdef CACHE_DEBUG + apr_pool_t *mp = msr->msc_rule_mptmp; + const apr_array_header_t *ctarr; + const apr_table_entry_t *ctelts; + msre_cache_rec *rec; + int cn = 0; + int ri; + #else + apr_pool_t *mp = msr->mp; + #endif + + for (hi = apr_hash_first(mp, msr->tcache); hi; hi = apr_hash_next(hi)) { + apr_hash_this(hi, &key, &klen, &dummy); + tab = (apr_table_t *)dummy; + + if (tab == NULL) continue; + + #ifdef CACHE_DEBUG + /* Dump the cache out as we clear */ + ctarr = apr_table_elts(tab); + ctelts = (const apr_table_entry_t*)ctarr->elts; + for (ri = 0; ri < ctarr->nelts; ri++) { + cn++; + rec = (msre_cache_rec *)ctelts[ri].val; + if (rec->changed) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "CACHE: %5d) hits=%d key=%pp %x;%s=\"%s\" (%pp - %pp)", cn, rec->hits, key, rec->num, rec->path, log_escape_nq_ex(mp, rec->val, rec->val_len), rec->val, rec->val + rec->val_len); + } + } + else { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "CACHE: %5d) hits=%d key=%pp %x;%s=", cn, rec->hits, key, rec->num, rec->path); + } + } + } + #endif + + apr_table_clear(tab); + apr_hash_set(msr->tcache, key, klen, NULL); + } + + msr_log(msr, 9, "Cleared transformation cache for phase %d", msr->phase); + } + + msr->tcache_items = 0; + msr->tcache = apr_hash_make(msr->mp); + if (msr->tcache == NULL) return -1; + } + switch(phase) { case 1 : return modsecurity_process_phase_request_headers(msr); diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index 15fd2866..5d840df6 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MODSECURITY_H_ @@ -30,6 +38,10 @@ typedef struct msc_string msc_string; #define DSOLOCAL #endif +#if defined(DEBUG_MEM) +/* Nothing Yet */ +#endif + /* For GNU C, tell the compiler to check printf like formatters */ #if (defined(__GNUC__) && !defined(SOLARIS2)) #define PRINTF_ATTRIBUTE(a,b) __attribute__((format (printf, a, b))) @@ -366,6 +378,7 @@ struct modsec_rec { /* data cache */ apr_hash_t *tcache; + apr_size_t tcache_items; /* removed rules */ apr_array_header_t *removed_rules; @@ -475,8 +488,10 @@ struct directory_config { /* Cache */ int cache_trans; + int cache_trans_incremental; apr_size_t cache_trans_min; apr_size_t cache_trans_max; + apr_size_t cache_trans_maxitems; /* Array to hold signatures of components, which will * appear in the ModSecurity signature in the audit log. diff --git a/apache2/msc_geo.c b/apache2/msc_geo.c index 3269ba3d..639bbe07 100644 --- a/apache2/msc_geo.c +++ b/apache2/msc_geo.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "msc_geo.h" diff --git a/apache2/msc_geo.h b/apache2/msc_geo.h index 9c6b5326..e00236cc 100644 --- a/apache2/msc_geo.h +++ b/apache2/msc_geo.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_GEO_H_ diff --git a/apache2/msc_logging.c b/apache2/msc_logging.c index 24e940a1..68435870 100644 --- a/apache2/msc_logging.c +++ b/apache2/msc_logging.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "re.h" diff --git a/apache2/msc_logging.h b/apache2/msc_logging.h index 5b5cb92d..e568ca24 100644 --- a/apache2/msc_logging.h +++ b/apache2/msc_logging.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_LOGGING_H_ diff --git a/apache2/msc_lua.c b/apache2/msc_lua.c index 6eaae2bc..c5a9c56d 100644 --- a/apache2/msc_lua.c +++ b/apache2/msc_lua.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #if defined(WITH_LUA) diff --git a/apache2/msc_lua.h b/apache2/msc_lua.h index 4f9ba937..83f6f540 100644 --- a/apache2/msc_lua.h +++ b/apache2/msc_lua.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #if defined(WITH_LUA) diff --git a/apache2/msc_multipart.c b/apache2/msc_multipart.c index bcf100f2..b8b56e68 100644 --- a/apache2/msc_multipart.c +++ b/apache2/msc_multipart.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include diff --git a/apache2/msc_multipart.h b/apache2/msc_multipart.h index 0b06ce89..b55dd337 100644 --- a/apache2/msc_multipart.h +++ b/apache2/msc_multipart.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_MULTIPART_H_ diff --git a/apache2/msc_parsers.c b/apache2/msc_parsers.c index dfe7dfc8..ed57c361 100644 --- a/apache2/msc_parsers.c +++ b/apache2/msc_parsers.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "msc_parsers.h" @@ -49,10 +57,18 @@ int parse_cookies_v0(modsec_rec *msr, char *_cookie_header, apr_table_t *cookies /* we ignore cookies with empty names */ if ((attr_name != NULL)&&(strlen(attr_name) != 0)) { if (attr_value != NULL) { - msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"", log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value)); + if (msr->txcfg->debuglog_level >= 5) { + msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"", + log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value)); + } + apr_table_add(cookies, attr_name, attr_value); } else { - msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty", log_escape(msr->mp, attr_name)); + if (msr->txcfg->debuglog_level >= 5) { + msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty", + log_escape(msr->mp, attr_name)); + } + apr_table_add(cookies, attr_name, ""); } @@ -169,12 +185,18 @@ int parse_cookies_v1(modsec_rec *msr, char *_cookie_header, apr_table_t *cookies } if (attr_value != NULL) { - msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"", - log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value)); + if (msr->txcfg->debuglog_level >= 5) { + msr_log(msr, 5, "Adding request cookie: name \"%s\", value \"%s\"", + log_escape(msr->mp, attr_name), log_escape(msr->mp, attr_value)); + } + apr_table_add(cookies, attr_name, attr_value); } else { - msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty", - log_escape(msr->mp, attr_name)); + if (msr->txcfg->debuglog_level >= 5) { + msr_log(msr, 5, "Adding request cookie: name \"%s\", value empty", + log_escape(msr->mp, attr_name)); + } + apr_table_add(cookies, attr_name, ""); } @@ -301,9 +323,11 @@ int parse_arguments(modsec_rec *msr, const char *s, apr_size_t inputlength, * */ void add_argument(modsec_rec *msr, apr_table_t *arguments, msc_arg *arg) { - msr_log(msr, 5, "Adding request argument (%s): name \"%s\", value \"%s\"", - arg->origin, log_escape_ex(msr->mp, arg->name, arg->name_len), - log_escape_ex(msr->mp, arg->value, arg->value_len)); + if (msr->txcfg->debuglog_level >= 5) { + msr_log(msr, 5, "Adding request argument (%s): name \"%s\", value \"%s\"", + arg->origin, log_escape_ex(msr->mp, arg->name, arg->name_len), + log_escape_ex(msr->mp, arg->value, arg->value_len)); + } apr_table_addn(arguments, log_escape_nq_ex(msr->mp, arg->name, arg->name_len), (void *)arg); } diff --git a/apache2/msc_parsers.h b/apache2/msc_parsers.h index 8aad1faa..563ee9d5 100644 --- a/apache2/msc_parsers.h +++ b/apache2/msc_parsers.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_PARSERS_H_ diff --git a/apache2/msc_pcre.c b/apache2/msc_pcre.c index cd007e7a..f8b32152 100644 --- a/apache2/msc_pcre.c +++ b/apache2/msc_pcre.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "msc_pcre.h" diff --git a/apache2/msc_pcre.h b/apache2/msc_pcre.h index 8f41bf5a..67b6f9aa 100644 --- a/apache2/msc_pcre.h +++ b/apache2/msc_pcre.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_PCRE_H_ diff --git a/apache2/msc_reqbody.c b/apache2/msc_reqbody.c index c88dde9e..26aed3a3 100644 --- a/apache2/msc_reqbody.c +++ b/apache2/msc_reqbody.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "modsecurity.h" diff --git a/apache2/msc_test.c b/apache2/msc_test.c index d41281a5..df73d63a 100644 --- a/apache2/msc_test.c +++ b/apache2/msc_test.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include diff --git a/apache2/msc_util.c b/apache2/msc_util.c index 2006cb89..414d48eb 100644 --- a/apache2/msc_util.c +++ b/apache2/msc_util.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "msc_util.h" diff --git a/apache2/msc_util.h b/apache2/msc_util.h index 265bae31..40f225c0 100644 --- a/apache2/msc_util.h +++ b/apache2/msc_util.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _UTIL_H_ diff --git a/apache2/msc_xml.c b/apache2/msc_xml.c index 3b5c133a..4dd212f3 100644 --- a/apache2/msc_xml.c +++ b/apache2/msc_xml.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "msc_xml.h" diff --git a/apache2/msc_xml.h b/apache2/msc_xml.h index 389d2996..ad6d0241 100644 --- a/apache2/msc_xml.h +++ b/apache2/msc_xml.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_XML_H_ diff --git a/apache2/pdf_protect.c b/apache2/pdf_protect.c index ed401f33..d5c26482 100644 --- a/apache2/pdf_protect.c +++ b/apache2/pdf_protect.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "modsecurity.h" diff --git a/apache2/pdf_protect.h b/apache2/pdf_protect.h index 8613193a..df0bd2b6 100644 --- a/apache2/pdf_protect.h +++ b/apache2/pdf_protect.h @@ -2,13 +2,20 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ - #ifndef _PDF_PROTECT_H_ #define _PDF_PROTECT_H_ diff --git a/apache2/persist_dbm.c b/apache2/persist_dbm.c index 3d667675..5d2b68a5 100644 --- a/apache2/persist_dbm.c +++ b/apache2/persist_dbm.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "persist_dbm.h" diff --git a/apache2/persist_dbm.h b/apache2/persist_dbm.h index 4bf2d0a9..8651240b 100644 --- a/apache2/persist_dbm.h +++ b/apache2/persist_dbm.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _PERSIST_DBM_H_ diff --git a/apache2/re.c b/apache2/re.c index f8ef7189..eb8cadf2 100644 --- a/apache2/re.c +++ b/apache2/re.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include @@ -1774,7 +1782,7 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { apr_pool_t *mptmp = msr->msc_rule_mptmp; apr_table_t *tartab = NULL; apr_table_t *vartab = NULL; - int i, rc, match_count = 0; + int i, rc = 0, match_count = 0; int invocations = 0; int multi_match = 0; @@ -1789,6 +1797,7 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { multi_match = 1; } + /* ENH: What is a good initial size? */ tartab = apr_table_make(mptmp, 24); if (tartab == NULL) return -1; vartab = apr_table_make(mptmp, 24); @@ -1857,28 +1866,48 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { for (i = 0; i < arr->nelts; i++) { int changed; int usecache = 0; - apr_table_t **carr = NULL; apr_table_t *cachetab = NULL; apr_time_t time_before_trans = 0; + msre_var *var; /* Take one target. */ - msre_var *var = (msre_var *)te[i].val; + var = (msre_var *)te[i].val; /* Is this var cacheable? */ if (msr->txcfg->cache_trans != MODSEC_CACHE_DISABLED) { usecache = 1; + /* Counting vars are not cacheable due to them being created + * in a local per-rule pool. + */ + if (var->is_counting) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "CACHE: Disabled - &%s is dynamic", var->name); + } + + usecache = 0; + } + /* Only cache if if the variable is available in this phase */ + else if (msr->phase < var->metadata->availability) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "CACHE: Disabled - %s is not yet available in phase %d (requires phase %d or later)", var->name, msr->phase, var->metadata->availability); + } + + usecache = 0; + } /* check the cache options */ - if (var->value_len < msr->txcfg->cache_trans_min) { + else if (var->value_len < msr->txcfg->cache_trans_min) { if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "CACHE: Disabled - %s value length=%u, smaller than minlen=%" APR_SIZE_T_FMT, var->name, var->value_len, msr->txcfg->cache_trans_min); } + usecache = 0; } - if ((msr->txcfg->cache_trans_max != 0) && (var->value_len > msr->txcfg->cache_trans_max)) { + else if ((msr->txcfg->cache_trans_max != 0) && (var->value_len > msr->txcfg->cache_trans_max)) { if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "CACHE: Disabled - %s value length=%u, larger than maxlen=%" APR_SIZE_T_FMT, var->name, var->value_len, msr->txcfg->cache_trans_max); } + usecache = 0; } @@ -1889,26 +1918,44 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { msr_log(msr, 9, "CACHE: Enabled"); } + #ifdef CACHE_DEBUG + msr_log(msr, 9, "CACHE: Fetching cache entry from hash=%pp: %pp=%s", msr->tcache, var, var->name); + #endif + /* Fetch cache table for this target */ - carr = (apr_table_t **)apr_hash_get(msr->tcache, var->name, APR_HASH_KEY_STRING); - if (carr != NULL) { - cachetab = carr[msr->phase]; - } - else { - /* Create an array of cache tables (one table per phase) */ - carr = (apr_table_t **)apr_pcalloc(msr->mp, (sizeof(apr_table_t *) * (PHASE_LAST + 1))); - if (carr == NULL) return -1; - memset(carr, 0, (sizeof(apr_table_t *) * (PHASE_LAST + 1))); - apr_hash_set(msr->tcache, var->name, APR_HASH_KEY_STRING, carr); - } + cachetab = (apr_table_t *)apr_hash_get(msr->tcache, var->value, sizeof(var->value)); /* Create an empty cache table if this is the first time */ - if (cachetab == NULL) { - cachetab = carr[msr->phase] = apr_table_make(msr->mp, 5); + #ifdef CACHE_DEBUG + if (cachetab) { + msr_log(msr, 9, "CACHE: Using cache table %pp", cachetab); } + else + #else + if (cachetab == NULL) + #endif + { + /* NOTE: We use the pointer to the var value as a hash + * key as it is unique. This pointer *must* + * remain valid through the entire phase. If + * it does not, then we will not receive a cache + * hit and just wasted RAM. So, it is important + * that any such vars be marked as VAR_DONT_CACHE. + * + * ENH: Only use pointer for non-scalar vars + */ + cachetab = apr_table_make(msr->mp, 3); + apr_hash_set(msr->tcache, var->value, sizeof(var->value), cachetab); + + #ifdef CACHE_DEBUG + msr_log(msr, 9, "CACHE: Created a new cache table %pp for %pp", cachetab, var->value); + #endif + } + } else { usecache = 0; + if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "CACHE: %s transformations are not cacheable", var->name); } @@ -1936,7 +1983,10 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { msre_action *action; msre_tfn_metadata *metadata; apr_table_t *normtab; + const char *lastvarval = NULL; + apr_size_t lastvarlen = 0; + changed = 0; normtab = apr_table_make(mptmp, 10); if (normtab == NULL) return -1; tarr = apr_table_elts(rule->actionset->actions); @@ -1945,6 +1995,7 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { /* Build the final list of transformation functions. */ for (k = 0; k < tarr->nelts; k++) { action = (msre_action *)telts[k].val; + if (strcmp(telts[k].key, "t") == 0) { if (strcmp(action->param, "none") == 0) { apr_table_clear(normtab); @@ -1968,9 +2019,14 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { * starting point */ if (usecache) { - tfnspath = apr_psprintf(msr->mp, "%s%s%s", (tfnspath?tfnspath:""), (tfnspath?",":""), action->param); - tfnskey = apr_psprintf(msr->mp, "%x;%s", tfnscount, tfnspath); + tfnspath = apr_psprintf(mptmp, "%s%s%s", (tfnspath?tfnspath:""), (tfnspath?",":""), action->param); + tfnskey = apr_psprintf(mptmp, "%x;%s", tfnscount, tfnspath); crec = (msre_cache_rec *)apr_table_get(cachetab, tfnskey); + + #ifdef CACHE_DEBUG + msr_log(msr, 9, "CACHE: %s %s cached=%d", var->name, tfnskey, (crec ? 1 : 0)); + #endif + if (crec != NULL) { last_crec = crec; last_cached_tfn = tfnscount; @@ -1983,15 +2039,19 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { /* If the last cached tfn is the last in the list * then we can stop here and just execute the action immediatly */ - if (usecache && !multi_match && (crec != NULL) && (crec == last_crec)) { + if (usecache && !multi_match && + (crec != NULL) && (crec == last_crec)) + { crec->hits++; + if (crec->changed) { - var->value = apr_pmemdup(msr->mp, crec->val, crec->val_len); + var->value = apr_pmemdup(mptmp, crec->val, crec->val_len); var->value_len = crec->val_len; } if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "T (%d) %s: \"%s\" [cached hits=%d]", crec->changed, crec->path, log_escape_nq_ex(mptmp, var->value, var->value_len), crec->hits); + msr_log(msr, 9, "T (%d) %s: \"%s\" [fully cached hits=%d]", crec->changed, crec->path, + log_escape_nq_ex(mptmp, var->value, var->value_len), crec->hits); } #if !defined(PERFORMANCE_MEASUREMENT) @@ -1999,9 +2059,11 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { #endif { apr_time_t t1 = apr_time_now(); + #if defined(PERFORMANCE_MEASUREMENT) rule->trans_time += (t1 - time_before_trans); #endif + msr_log(msr, 4, "Transformation completed in %" APR_TIME_T_FMT " usec.", (t1 - time_before_trans)); } @@ -2030,14 +2092,6 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { tarr = apr_table_elts(normtab); - /* Make a copy of the variable value so that - * we can change it in-place. - */ - if (tarr->nelts) { - var->value = apr_pstrmemdup(mptmp, var->value, var->value_len); - /* var->value_len remains the same */ - } - /* Execute transformations in a loop. */ /* Start after the last known cached transformation if we can */ @@ -2046,32 +2100,39 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { tfnspath = last_crec->path; last_crec->hits++; - if ((changed = last_crec->changed) == 1) { - var->value = apr_pmemdup(msr->mp, last_crec->val, last_crec->val_len); + if ((changed = last_crec->changed) > 0) { + var->value = last_crec->val; var->value_len = last_crec->val_len; } if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "T (%d) %s: \"%s\" [partially cached hits=%d]", last_crec->changed, tfnspath, log_escape_nq_ex(mptmp, var->value, var->value_len), last_crec->hits); + msr_log(msr, 9, "T (%d) %s: \"%s\" [partially cached hits=%d]", last_crec->changed, + tfnspath, log_escape_nq_ex(mptmp, var->value, var->value_len), last_crec->hits); } } else { - changed = 1; tfnspath = NULL; k = 0; } + /* Make a copy of the value so that we can change it in-place. */ + if (tarr->nelts) { + var->value = apr_pstrmemdup(mptmp, var->value, var->value_len); + /* var->value_len remains the same */ + } + telts = (const apr_table_entry_t*)tarr->elts; for (; k < tarr->nelts; k++) { char *rval = NULL; long int rval_length = -1; + int tfnchanged = 0; /* In multi-match mode we execute the operator * once at the beginning and then once every * time the variable is changed by the transformation * function. */ - if (multi_match && changed) { + if (multi_match && (k == 0 || tfnchanged)) { invocations++; #if !defined(PERFORMANCE_MEASUREMENT) @@ -2079,9 +2140,11 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { #endif { apr_time_t t1 = apr_time_now(); + #if defined(PERFORMANCE_MEASUREMENT) rule->trans_time += (t1 - time_before_trans); #endif + msr_log(msr, 4, "Transformation completed in %" APR_TIME_T_FMT " usec.", (t1 - time_before_trans)); } @@ -2108,60 +2171,88 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { /* Perform one transformation. */ action = (msre_action *)telts[k].val; metadata = (msre_tfn_metadata *)action->param_data; - - /* Try to use the cache */ - if (usecache) { - /* Generate the cache key */ - tfnspath = apr_psprintf(msr->mp, "%s%s%s", (tfnspath?tfnspath:""), (tfnspath?",":""), action->param); - tfnskey = apr_psprintf(msr->mp, "%x;%s", (k + 1), tfnspath); - - /* Try to fetch this transformation from cache */ - #ifdef CACHE_DEBUG - msr_log(msr, 9, "CACHE: Fetching %s %s ", var->name, tfnskey); - #endif - crec = (msre_cache_rec *)apr_table_get(cachetab, tfnskey); - if (crec != NULL) { - crec->hits++; - - if ((changed = crec->changed) == 1) { - var->value = apr_pmemdup(msr->mp, crec->val, crec->val_len); - var->value_len = crec->val_len; - } - - if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "T (%d) %s: \"%s\" [cached hits=%d]", crec->changed, metadata->name, log_escape_nq_ex(mptmp, var->value, var->value_len), crec->hits); - } - continue; - } - } - - rc = metadata->execute(mptmp, (unsigned char *)var->value, var->value_len, + tfnchanged = metadata->execute(mptmp, + (unsigned char *)var->value, var->value_len, &rval, &rval_length); - if (rc < 0) { + + if (tfnchanged < 0) { return -1; } - changed = rc; + if (tfnchanged) { + changed++; + } + /* Use the new values */ var->value = rval; var->value_len = rval_length; /* Cache the transformation */ if (usecache) { - /* ENH1: Add flag to vars to tell which ones can change across phases store the rest in a global cache */ - crec = (msre_cache_rec *)apr_pcalloc(msr->mp, sizeof(msre_cache_rec)); - if (crec == NULL) return -1; + int tfnsnum = k + 1; - crec->hits = 0; - crec->changed = changed; - crec->num = k + 1; - crec->path = tfnspath; - crec->val = changed ? apr_pmemdup(msr->mp, var->value, var->value_len) : NULL; - crec->val_len = changed ? var->value_len : 0; - #ifdef CACHE_DEBUG - msr_log(msr, 9, "CACHE: Caching %s=\"%.*s\"", tfnskey, var->value_len, log_escape_nq_ex(mptmp, var->value, var->value_len)); - #endif - apr_table_setn(cachetab, tfnskey, (void *)crec); + /* Generate the cache key */ + tfnspath = apr_psprintf(msr->mp, "%s%s%s", (tfnspath ? tfnspath : ""), + (tfnspath ? "," : ""), action->param); + tfnskey = apr_psprintf(msr->mp, "%x;%s", tfnsnum, tfnspath); + + if ((msr->txcfg->cache_trans_maxitems != 0) && + (msr->tcache_items >= msr->txcfg->cache_trans_maxitems)) + { + /* Warn only once if we attempt to go over the cache limit. */ + if (msr->tcache_items == msr->txcfg->cache_trans_maxitems) { + msr->tcache_items++; + msr_log(msr, 4, "CACHE: Disabled - phase=%d" + " maxitems=%" APR_SIZE_T_FMT + " limit reached.", + msr->phase, + msr->txcfg->cache_trans_maxitems); + } + } + else if (msr->txcfg->cache_trans_incremental || + (tfnsnum == tarr->nelts)) + { + /* ENH1: Add flag to vars to tell which ones can change across phases store the rest in a global cache */ + crec = (msre_cache_rec *)apr_pcalloc(msr->mp, sizeof(msre_cache_rec)); + if (crec == NULL) return -1; + + crec->hits = 0; + crec->changed = changed; + crec->num = k + 1; + crec->path = tfnspath; + + /* We want to cache a copy if it changed otherwise + * we just want to use a pointer to the last changed value. + */ + crec->val = (!lastvarval || tfnchanged) ? apr_pmemdup(msr->mp, var->value, var->value_len) : lastvarval; + crec->val_len = changed ? ((!lastvarval || tfnchanged) ? var->value_len : lastvarlen) : 0; + + /* Keep track of the last changed var value */ + if (tfnchanged) { + lastvarval = crec->val; + lastvarlen = crec->val_len; + } + + #ifdef CACHE_DEBUG + if (changed) { + msr_log(msr, 9, "CACHE: Caching %s=\"%s\" (%pp)", + tfnskey, + log_escape_nq_ex(mptmp, + crec->val, + crec->val_len), + var); + } + else { + msr_log(msr, 9, "CACHE: Caching %s= (%pp)", + tfnskey, + var); + } + #endif + + msr->tcache_items++; + + apr_table_setn(cachetab, tfnskey, (void *)crec); + } } if (msr->txcfg->debuglog_level >= 9) { @@ -2183,9 +2274,11 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { #endif { apr_time_t t1 = apr_time_now(); + #if defined(PERFORMANCE_MEASUREMENT) rule->trans_time += (t1 - time_before_trans); #endif + msr_log(msr, 4, "Transformation completed in %" APR_TIME_T_FMT " usec.", (t1 - time_before_trans)); } @@ -2210,44 +2303,6 @@ static apr_status_t msre_rule_process_normal(msre_rule *rule, modsec_rec *msr) { } } - #ifdef CACHE_DEBUG - if (msr->txcfg->debuglog_level >= 9) { - apr_hash_index_t *hi; - void *dummy; - apr_table_t **tab; - const apr_array_header_t *ctarr; - const apr_table_entry_t *ctelts; - msre_cache_rec *rec; - int cn = 0; - int ti, ri; - - for (hi = apr_hash_first(msr->mp, msr->tcache); hi; hi = apr_hash_next(hi)) { - apr_hash_this(hi, NULL, NULL, &dummy); - tab = (apr_table_t **)dummy; - if (tab == NULL) continue; - - for (ti = PHASE_FIRST; ti <= PHASE_LAST; ti++) { - if (tab[ti] == NULL) continue; - ctarr = apr_table_elts(tab[ti]); - ctelts = (const apr_table_entry_t*)ctarr->elts; - for (ri = 0; ri < ctarr->nelts; ri++) { - cn++; - rec = (msre_cache_rec *)ctelts[ri].val; - if (rec->changed) { - if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "CACHE: %5d) phase=%d hits=%d %x;%s=\"%s\"", cn, msr->phase, rec->hits, rec->num, rec->path, log_escape_nq_ex(mptmp, rec->val, rec->val_len)); - } - } - else { - if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "CACHE: %5d) phase=%d hits=%d %x;%s=", cn, msr->phase, rec->hits, rec->num, rec->path); - } - } - } - } - } - } - #endif return (match_count ? RULE_MATCH : RULE_NO_MATCH); } diff --git a/apache2/re.h b/apache2/re.h index 002f48e8..bcf256ad 100644 --- a/apache2/re.h +++ b/apache2/re.h @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef _MSC_RE_H_ diff --git a/apache2/re_actions.c b/apache2/re_actions.c index 2de11d05..d753e50c 100644 --- a/apache2/re_actions.c +++ b/apache2/re_actions.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "re.h" diff --git a/apache2/re_operators.c b/apache2/re_operators.c index 5eacf863..528968f9 100644 --- a/apache2/re_operators.c +++ b/apache2/re_operators.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "re.h" diff --git a/apache2/re_tfns.c b/apache2/re_tfns.c index 98faa382..b4a4b32b 100644 --- a/apache2/re_tfns.c +++ b/apache2/re_tfns.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include diff --git a/apache2/re_variables.c b/apache2/re_variables.c index 91bf97e6..2225cba5 100644 --- a/apache2/re_variables.c +++ b/apache2/re_variables.c @@ -2,10 +2,18 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #include "http_core.h" @@ -450,7 +458,7 @@ static int var_request_uri_raw_generate(modsec_rec *msr, msre_var *var, msre_rul /* REQUEST_URI */ static int var_request_uri_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, - apr_table_t *vartab, apr_pool_t *mptmp) + apr_table_t *vartab, apr_pool_t *mptmp) /* dynamic */ { char *value = NULL; @@ -2134,7 +2142,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_args_combined_size_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2233,7 +2241,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_files_combined_size_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2255,7 +2263,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 1, var_generic_list_validate, var_files_sizes_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2277,7 +2285,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_geo_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2288,7 +2296,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_global_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2299,7 +2307,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_highest_severity_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2310,7 +2318,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_ip_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2321,7 +2329,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_matched_var_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2332,7 +2340,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_matched_var_name_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2354,7 +2362,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_boundary_quoted_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2365,7 +2373,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_boundary_whitespace_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2376,7 +2384,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_data_after_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2387,7 +2395,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_data_before_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2398,7 +2406,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_header_folding_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2409,7 +2417,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_crlf_line_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2420,7 +2428,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_crlf_lf_lines_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2431,7 +2439,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_lf_line_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2442,7 +2450,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_missing_semicolon_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2453,7 +2461,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_strict_error_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2464,7 +2472,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_multipart_unmatched_boundary_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); @@ -2519,7 +2527,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_remote_port_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2541,7 +2549,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_resource_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2552,7 +2560,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_reqbody_processor_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); @@ -2563,7 +2571,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_reqbody_processor_error_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); @@ -2574,7 +2582,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_reqbody_processor_error_msg_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); @@ -2585,7 +2593,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_request_basename_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); @@ -2695,7 +2703,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_request_uri_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); @@ -2728,7 +2736,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_response_content_length, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_RESPONSE_HEADERS ); @@ -2783,7 +2791,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_response_status_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_RESPONSE_HEADERS ); @@ -2794,7 +2802,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, NULL, var_rule_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); @@ -2805,7 +2813,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_gid_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2816,7 +2824,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_basename_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2838,7 +2846,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_groupname_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2849,7 +2857,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_mode_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2860,7 +2868,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_uid_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2871,7 +2879,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_script_username_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); @@ -2904,7 +2912,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_server_port_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); @@ -2915,7 +2923,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_session_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2926,7 +2934,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_sessionid_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); @@ -2948,7 +2956,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_user_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2959,7 +2967,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_userid_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); @@ -2970,7 +2978,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2981,7 +2989,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_day_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -2992,7 +3000,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_epoch_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3003,7 +3011,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_hour_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3014,7 +3022,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_min_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3025,7 +3033,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_mon_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3036,7 +3044,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_sec_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3047,7 +3055,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_wday_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3058,7 +3066,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_time_year_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3069,7 +3077,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 1, 1, var_generic_list_validate, var_tx_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3091,7 +3099,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 0, NULL, var_webserver_error_log_generate, - VAR_DONT_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); @@ -3102,7 +3110,7 @@ void msre_engine_register_default_variables(msre_engine *engine) { 0, 1, var_xml_validate, var_xml_generate, - VAR_CACHE, + VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); } diff --git a/apache2/t/regression/action/10-detectiononly-actions.t b/apache2/t/regression/action/10-detectiononly-actions.t index 74d71456..238972c7 100644 --- a/apache2/t/regression/action/10-detectiononly-actions.t +++ b/apache2/t/regression/action/10-detectiononly-actions.t @@ -107,7 +107,7 @@ match_log => { error => [ qr/ModSecurity: Warning. Unconditional match in SecAction.*ALLOWED/, 1 ], -error => [ qr/Access allowed/, 1 ], -# TODO: Allow should probably rule stop execution +# TODO: Allow should probably stop rule execution # -error => [ qr/DENIED/, 1 ], }, match_response => { @@ -131,7 +131,7 @@ match_log => { error => [ qr/ModSecurity: Warning. Unconditional match in SecAction.*ALLOWED/, 1 ], -error => [ qr/Access allowed/, 1 ], -# TODO: Allow should probably rule stop execution +# TODO: Allow should probably stop rule execution # -error => [ qr/DENIED/, 1 ], }, match_response => { @@ -155,7 +155,7 @@ match_log => { error => [ qr/ModSecurity: Warning. Unconditional match in SecAction.*ALLOWED/, 1 ], -error => [ qr/Access allowed/, 1 ], -# TODO: Allow should probably rule stop execution +# TODO: Allow should probably stop rule execution # -error => [ qr/DENIED/, 1 ], }, match_response => { @@ -179,7 +179,7 @@ match_log => { error => [ qr/ModSecurity: Warning. Unconditional match in SecAction.*ALLOWED/, 1 ], -error => [ qr/Access allowed/, 1 ], -# TODO: Allow should probably rule stop execution +# TODO: Allow should probably stop rule execution # -error => [ qr/DENIED/, 1 ], }, match_response => { diff --git a/apache2/t/regression/misc/10-tfn-cache.t b/apache2/t/regression/misc/10-tfn-cache.t new file mode 100644 index 00000000..271834db --- /dev/null +++ b/apache2/t/regression/misc/10-tfn-cache.t @@ -0,0 +1,189 @@ +### Transformation Caching + +{ + type => "misc", + comment => "tfncache (simple fully cached)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0" + + # This should cache it + SecRule ARGS_GET "WillNotMatch" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + + # This should use the cached value + SecRule ARGS_GET:test "foobar" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,deny" + ), + match_log => { + debug => [ qr/removeWhiteSpace,lowercase: "foobar" .*cached/, 1 ], + -debug => [ qr/partially cached/, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html?test=Foo+Bar", + ), +}, +{ + type => "misc", + comment => "tfncache (simple partially cached)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0,incremental:off,maxitems:0" + + # This should cache it + SecRule ARGS_GET "WillNotMatch" "phase:1,t:none,t:removeWhiteSpace,pass,nolog" + + # This should use the partially cached value + SecRule ARGS_GET:test "foobar" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,deny" + ), + match_log => { + debug => [ qr/removeWhiteSpace: "FooBar" .*partially cached/, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html?test=Foo+Bar", + ), +}, +{ + type => "misc", + comment => "tfncache (separate phases)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0" + + # This should cache it + SecRule ARGS_GET "WillNotMatch" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + + # This should use the cached value + SecRule ARGS_GET:test "foobar" "phase:2,t:none,t:removeWhiteSpace,t:lowercase,deny" + ), + match_log => { + -debug => [ qr/removeWhiteSpace,lowercase: "foobar" .*cached/, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html?test=Foo+Bar", + ), +}, +{ + type => "misc", + comment => "tfncache (non-modifying tfns cached)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0" + + # This should cache it + SecRule ARGS_GET "WillNotMatch" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + + # This should use the cached value + SecRule ARGS_GET:test "foobar" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,deny" + ), + match_log => { + debug => [ qr/removeWhiteSpace,lowercase: "foobar" .*cached/, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html?test=foo+bar", + ), +}, +{ + type => "misc", + comment => "tfncache (unique keys)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + SecRequestBodyAccess On + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0" + + # This should cache it + SecRule ARGS "WillNotMatch" "phase:2,t:none,t:removeWhiteSpace,t:lowercase,pass" + + # This should see cached versions of *both* ARGS_GET + SecRule ARGS:test "queryval" "phase:2,t:none,t:removeWhiteSpace,t:lowercase,deny,chain" + SecRule ARGS:test "firstval" "t:none,t:removeWhiteSpace,t:lowercase,chain" + SecRule ARGS:test "secondval" "t:none,t:removeWhiteSpace,t:lowercase" + ), + match_log => { + debug => [ qr/removeWhiteSpace,lowercase: "queryval" .*removeWhiteSpace,lowercase: "firstval" .*cached.*removeWhiteSpace,lowercase: "secondval" .*cached/s, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html?test=Query+Val", + [ + "Content-Type" => "application/x-www-form-urlencoded", + ], + # Args + "test=First+Val&test=Second+Val", + ), +}, +{ + type => "misc", + comment => "tfncache (large cache)", + conf => qq( + SecRuleEngine On + SecDebugLog $ENV{DEBUG_LOG} + SecDebugLogLevel 9 + SecRequestBodyAccess On + + + SecRequestBodyNoFilesLimit 1048576 + + SecRequestBodyInMemoryLimit 131072 + SecResponseBodyLimit 1048576 + + # We need to make this work no matter what the defaults may change to + SecCacheTransformations On "minlen:1,maxlen:0,maxitems:0" + + # This should cache it in all phases + SecRule ARGS "WillNotMatch" "phase:1,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + SecRule ARGS "WillNotMatch" "phase:2,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + SecRule ARGS "WillNotMatch" "phase:3,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + SecRule ARGS "WillNotMatch" "phase:4,t:none,t:removeWhiteSpace,t:lowercase,pass,nolog" + + # This should use the cached value + SecRule ARGS "foobar" "phase:4,t:none,t:removeWhiteSpace,t:lowercase,deny" + ), + match_log => { + debug => [ qr/Adding request argument \(BODY\): name "test", value "Foo Bar"/, 60, "Waiting for httpd to process request: "], + -error => [ qr/segmentation fault/i, 60 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/index.html", + [ + "Content-Type" => "application/x-www-form-urlencoded", + ], + # 1000 Args + join("&", map { sprintf "arg%08d=0123456789abcdef+0123456789ABCDEF+0123456789abcdef", $_ } (1 .. 1000))."&test=Foo+Bar", + ), +}, diff --git a/apache2/t/run-regression-tests.pl.in b/apache2/t/run-regression-tests.pl.in index 6ddfbb8a..69243227 100755 --- a/apache2/t/run-regression-tests.pl.in +++ b/apache2/t/run-regression-tests.pl.in @@ -35,6 +35,7 @@ my $PID_FILE = "$FILES_DIR/httpd.pid"; my $HTTPD = q(@APXS_HTTPD@); my $PASSED = 0; my $TOTAL = 0; +my $BUFSIZ = 32768; my %C = (); my %FILE = (); my $UA_NAME = "ModSecurity Regression Tests/1.2.3"; @@ -49,9 +50,9 @@ if ($HTTPD eq "\@APXS_HTTPD\@") { $SIG{TERM} = $SIG{INT} = \&handle_interrupt; my %opt; -getopts('A:E:D:C:T:H:a:p:dh', \%opt); +getopts('A:E:D:C:T:H:a:p:dvh', \%opt); -if ($opt{D}) { +if ($opt{d}) { $Data::Dumper::Indent = 1; $Data::Dumper::Terse = 1; $Data::Dumper::Pad = ""; @@ -72,7 +73,8 @@ Usage: $SCRIPT [options] [file [N]] -S path Specify Apache httpd server root path. -a file Specify Apache httpd binary (default: httpd) -p port Specify Apache httpd port (default: 8088) - -d Enable debugging. + -v Enable verbose output (details on failure). + -d Enable debugging output. -h This help. EOT @@ -98,6 +100,7 @@ $opt{E} = "$FILES_DIR/error.log" unless (defined $opt{E}); $opt{C} = "$CONF_DIR/httpd.conf" unless (defined $opt{C}); $opt{H} = "$SROOT_DIR/htdocs" unless (defined $opt{H}); $opt{p} = 8088 unless (defined $opt{p}); +$opt{v} = 1 if ($opt{d}); unless (defined $opt{S}) { my $httpd_root = `$HTTPD -V`; @@ -194,7 +197,7 @@ sub runfile { if (exists $t{conf} and defined $t{conf}) { $conf_fn = sprintf "%s/%s_%s_%06d.conf", $CONF_DIR, $t{type}, $cfg, $n; -# dbg("Writing test config to: $conf_fn"); + #dbg("Writing test config to: $conf_fn"); open(CONF, ">$conf_fn") or die "Failed to open conf \"$conf_fn\": $!\n"; print CONF (ref $t{conf} eq "CODE" ? eval { &{$t{conf}} } : $t{conf}); msg("$@") if ($@); @@ -207,9 +210,9 @@ sub runfile { # Run any prerun setup if ($rc == 0 and exists $t{prerun} and defined $t{prerun}) { - dbg("Executing perl prerun..."); + vrb("Executing perl prerun..."); $rc = &{$t{prerun}}; - dbg("Perl prerun returned: $rc"); + vrb("Perl prerun returned: $rc"); } if ($httpd_up) { @@ -218,7 +221,7 @@ sub runfile { my $resp = do_request($t{request}); if (!$resp) { msg("invalid response"); - dbg("RESPONSE: ", $resp); + vrb("RESPONSE: ", $resp); $rc = 1; } else { @@ -229,14 +232,13 @@ sub runfile { if ($neg and defined $match) { $rc = 1; msg("response $mtype matched: $m"); - dbg($resp); - + vrb($resp); last; } elsif (!$neg and !defined $match) { $rc = 1; msg("response $mtype failed to match: $m"); - dbg($resp); + vrb($resp); last; } } @@ -245,13 +247,13 @@ sub runfile { # Run any arbitrary perl tests if ($rc == 0 and exists $t{test} and defined $t{test}) { - #dbg("Executing perl test(s)..."); + dbg("Executing perl test(s)..."); $rc = eval { &{$t{test}} }; if (! defined $rc) { msg("Error running test: $@"); $rc = -1; } - #dbg("Perl tests returned: $rc"); + dbg("Perl tests returned: $rc"); } # Search for all log matches @@ -263,15 +265,11 @@ sub runfile { if ($neg and defined $match) { $rc = 1; msg("$mtype log matched: $m->[0]"); - msg("Log: $FILE{$mtype}{fn}"); - dbg(escape("$FILE{$mtype}{buf}")); last; } elsif (!$neg and !defined $match) { $rc = 1; msg("$mtype log failed to match: $m->[0]"); - msg("Log: $FILE{$mtype}{fn}"); - dbg(escape("$FILE{$mtype}{buf}")); last; } } @@ -287,13 +285,11 @@ sub runfile { if ($neg and defined $match) { $rc = 1; msg("$fn file matched: $m"); - dbg(escape("$FILE{$fn}{buf}")); last; } elsif (!$neg and !defined $match) { $rc = 1; msg("$fn file failed match: $m"); - dbg(escape("$FILE{$fn}{buf}")); last; } } @@ -308,7 +304,11 @@ sub runfile { $pass++; } else { - dbg("Test config: $conf_fn"); + vrb("Test Config: $conf_fn"); + vrb("Debug Log: $FILE{debug}{fn}"); + dbg(escape("$FILE{debug}{buf}")); + vrb("Error Log: $FILE{error}{fn}"); + dbg(escape("$FILE{error}{buf}")); } msg(sprintf("%s) %s%s: %s%s", $id, $t{type}, (exists($t{comment}) ? " - $t{comment}" : ""), ($rc ? "failed" : "passed"), ((defined($out) && $out ne "")? " ($out)" : ""))); @@ -375,15 +375,11 @@ sub do_request { } if (ref $r eq "HTTP::Request") { -# dbg("REQUEST: ", $r); my $resp = $UA->request($r); - if ($opt{d}) { - dbg($resp->request()->as_string()); - } + dbg($resp->request()->as_string()) if ($opt{d}); return $resp } else { -# dbg("REQUEST:\n", $r); return do_raw_request($r); } @@ -409,13 +405,17 @@ sub match_response { return; } +sub read_log { + my($name, $timeout, $graph) = @_; + return match_log($name, undef, $timeout, $graph); +} + sub match_log { - my($name, $re, $timeout) = @_; + my($name, $re, $timeout, $graph) = @_; my $t0 = gettimeofday; my($fh,$rbuf) = ($FILE{$name}{fd}, \$FILE{$name}{buf}); my $n = length($$rbuf); - - msg("Warning: Empty regular expression.") if (!defined $re or $re eq ""); + my $rc = undef; unless (defined $fh) { msg("Error: File \"$name\" is not opened for matching."); @@ -424,15 +424,45 @@ sub match_log { $timeout = 0 unless (defined $timeout); - do { - $n += $fh->sysread($$rbuf, 1024, $n); -# dbg("Match \"$re\" in $name \"$$rbuf\" ($n)"); - return $& if ($$rbuf =~ m/$re/m); - # TODO: Use select()/poll() - sleep 0.1; - } while (gettimeofday - $t0 < $timeout); + my $i = 0; + my $graphed = 0; + READ: { + do { + my $nbytes = $fh->sysread($$rbuf, $BUFSIZ, $n); + if (!defined($nbytes)) { + msg("Error: Could not read \"$name\" log: $!"); + last; + } + elsif (!defined($re) and $nbytes == 0) { + last; + } - return; + # Remove APR pool debugging + $$rbuf =~ s/POOL DEBUG:[^\n]+PALLOC[^\n]+\n//sg; + + $n = length($$rbuf); + + #dbg("Match \"$re\" in $name \"$$rbuf\" ($n)"); + if ($$rbuf =~ m/$re/m) { + $rc = $&; + last; + } + # TODO: Use select()/poll() + sleep 0.1 unless ($nbytes == $BUFSIZ); + if ($graph and $opt{d}) { + $i++; + if ($i == 10) { + $graphed++; + $i=0; + print STDERR $graph if ($graphed == 1); + print STDERR "." + } + } + } while (gettimeofday - $t0 < $timeout); + } + print STDERR "\n" if ($graphed); + + return $rc; } sub match_file { @@ -477,6 +507,11 @@ sub dbg { print STDOUT "$out\n"; } +sub vrb { + return unless(@_ and $opt{v}); + msg(@_); +} + sub msg { return unless(@_); my $out = join "", map { @@ -524,14 +559,14 @@ sub httpd_start { my $httpd_out; my $httpd_pid = open3(undef, $httpd_out, undef, @p) or quit(1); - my $out = join("\\n", split(/\n/, <$httpd_out>)); + my $out = join("\\n", grep(!/POOL DEBUG/, (<$httpd_out>))); close $httpd_out; waitpid($httpd_pid, 0); my $rc = $?; if ( WIFEXITED($rc) ) { $rc = WEXITSTATUS($rc); - dbg("Httpd start returned with $rc.") if ($rc); + vrb("Httpd start returned with $rc.") if ($rc); } elsif( WIFSIGNALED($rc) ) { msg("Httpd start failed with signal " . WTERMSIG($rc) . "."); @@ -543,15 +578,15 @@ sub httpd_start { } if (defined $out and $out ne "") { - dbg(join(" ", map { quote_shell($_) } @p)); + vrb(join(" ", map { quote_shell($_) } @p)); msg("Httpd start failed with error messages:\n$out"); return -1 } # Look for startup msg - unless (defined match_log("error", qr/resuming normal operations/, 10)) { - dbg(join(" ", map { quote_shell($_) } @p)); - dbg(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10)); + unless (defined match_log("error", qr/resuming normal operations/, 60, "Waiting on httpd to start: ")) { + vrb(join(" ", map { quote_shell($_) } @p)); + vrb(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10)); msg("Httpd server failed to start."); return -1; } @@ -571,7 +606,7 @@ sub httpd_stop { my $httpd_out; my $httpd_pid = open3(undef, $httpd_out, undef, @p) or quit(1); - my $out = join("\\n", split(/\n/, <$httpd_out>)); + my $out = join("\\n", grep(!/POOL DEBUG/, (<$httpd_out>))); close $httpd_out; waitpid($httpd_pid, 0); @@ -583,7 +618,7 @@ sub httpd_stop { my $rc = $?; if ( WIFEXITED($rc) ) { $rc = WEXITSTATUS($rc); - dbg("Httpd stop returned with $rc.") if ($rc); + vrb("Httpd stop returned with $rc.") if ($rc); } elsif( WIFSIGNALED($rc) ) { msg("Httpd stop failed with signal " . WTERMSIG($rc) . "."); @@ -595,8 +630,8 @@ sub httpd_stop { } # Look for startup msg - unless (defined match_log("error", qr/caught SIG[A-Z]+, shutting down/, 10)) { - dbg(join(" ", map { quote_shell($_) } @p)); + unless (defined match_log("error", qr/caught SIG[A-Z]+, shutting down/, 60, "Waiting on httpd to stop: ")) { + vrb(join(" ", map { quote_shell($_) } @p)); msg("Httpd server failed to shutdown."); return -1; } @@ -617,7 +652,7 @@ sub httpd_reload { my $httpd_out; my $httpd_pid = open3(undef, $httpd_out, undef, @p) or quit(1); - my $out = join("\\n", split(/\n/, <$httpd_out>)); + my $out = join("\\n", grep(!/POOL DEBUG/, (<$httpd_out>))); close $httpd_out; waitpid($httpd_pid, 0); @@ -629,7 +664,7 @@ sub httpd_reload { my $rc = $?; if ( WIFEXITED($rc) ) { $rc = WEXITSTATUS($rc); - dbg("Httpd reload returned with $rc.") if ($rc); + vrb("Httpd reload returned with $rc.") if ($rc); } elsif( WIFSIGNALED($rc) ) { msg("Httpd reload failed with signal " . WTERMSIG($rc) . "."); @@ -641,8 +676,8 @@ sub httpd_reload { } # Look for startup msg - unless (defined match_log("error", qr/resuming normal operations/, 10)) { - dbg(join(" ", map { quote_shell($_) } @p)); + unless (defined match_log("error", qr/resuming normal operations/, 60, "Waiting on httpd to restart: ")) { + vrb(join(" ", map { quote_shell($_) } @p)); msg("Httpd server failed to reload."); return -1; } diff --git a/apache2/utf8tables.h b/apache2/utf8tables.h index 5bd74253..75b6554f 100644 --- a/apache2/utf8tables.h +++ b/apache2/utf8tables.h @@ -2,17 +2,25 @@ * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) * - * You should have received a copy of the licence along with this - * program (stored in the file "LICENSE"). If the file is missing, - * or if you have any other questions related to the licence, please - * write to Breach Security, Inc. at support@breach.com. + * This product is released under the terms of the General Public Licence, + * version 2 (GPLv2). Please refer to the file LICENSE (included with this + * distribution) which contains the complete text of the licence. + * + * There are special exceptions to the terms and conditions of the GPL + * as it is applied to this software. View the full text of the exception in + * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software + * distribution. + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Breach Security, Inc. + * directly using the email address support@breach.com. * */ #ifndef UTF8TABLES_H_ #define UTF8TABLES_H_ /** - * This include file is used by acmp.c only, it's not included anywhere else + * This include file is used by acmp.c only; it's not included anywhere else. */ typedef long acmp_utf8_char_t; diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml index 523ba44e..55d6c0dd 100644 --- a/doc/modsecurity2-apache-reference.xml +++ b/doc/modsecurity2-apache-reference.xml @@ -4,7 +4,7 @@ Manual - Version 2.6.0-trunk (July 16, 2008) + Version 2.6.0-trunk (July 31, 2008) 2004-2008 @@ -182,15 +182,15 @@ Security. - ModSecurity, mod_security, and ModSecurity Pro are trademarks or - registered trademarks of Breach Security, Inc. + ModSecurity, mod_security, ModSecurity Pro, and ModSecurity Core + Rules are trademarks or registered trademarks of Breach Security, + Inc.
- <trademark class="registered">ModSecurity</trademark> Core - Rules + <trademark>ModSecurity Core Rules</trademark>
Overview @@ -858,10 +858,12 @@ SecAuditLogStorageDir logs/audit
- <literal>SecCacheTransformations</literal> + <literal>SecCacheTransformations</literal> + (Deprecated/Experimental) Description: Controls caching of - transformations. + transformations. Caching is off by default starting with 2.5.6, when it + was deprecated and downgraded back to experimental. Syntax: SecCacheTransformations On|Off @@ -898,16 +900,30 @@ SecAuditLogStorageDir logs/audit The following options are allowed (comma separated): + + incremental:on|off - + enabling this option will cache every transformation instead of just + the final transformation. (default: off) + + + + maxitems:N - do not allow + more than N transformations to be cached. The cache will then be + disabled. A zero value is interpreted as "unlimited". This option + may be useful to limit caching for a form with a large number of + ARGS. (default: 512) + + minlen:N - do not cache the transformation if the value's length is less than N bytes. (default: - 15) + 32) maxlen:N - do not cache the transformation if the value's length is more than N bytes. A zero - value is interpreted as "unlimited". (default: 0) + value is interpreted as "unlimited". (default: 1024)
@@ -1284,7 +1300,8 @@ SecAuditLogStorageDir logs/audit Dependencies/Notes: None - SecRule REQUEST_URI "^/$" "chain,skipAfter:99" + SecRule REQUEST_URI "^/$" \ + "chain,t:none,t:urlDecode,t:lowercase,t:normalisePath,skipAfter:99" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent \ "^Apache \(internal dummy connection\)$" "t:none" @@ -1452,10 +1469,11 @@ SecRule &REQUEST_HEADERS:Accept "@eq 0" \ Version: 2.0.0 Dependencies/Notes: This directive is - required if you plan to inspect POST_PAYLOADS of requests. This + required if you plan to inspect POST_PAYLOAD. This directive must be used along with the "phase:2" processing phase action - and REQUEST_BODY variable/location. If any of these 3 parts are not - configured, you will not be able to inspect the request bodies. + and REQUEST_BODY variable/location. If any of these 3 + parts are not configured, you will not be able to inspect the request + bodies. Possible values are: @@ -1724,7 +1742,10 @@ SecResponseBodyLimit 524288 VARIABLES OPERATOR [ACTIONS] Example Usage: SecRule REQUEST_URI "attack" + moreinfo="none">SecRule REQUEST_URI "attack" \ + + + "phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath" Processing Phase: Any @@ -1752,11 +1773,11 @@ SecResponseBodyLimit 524288 following rule will reject a transaction that has the word dirty in the URI: - SecRule REQUEST_URI dirty + SecRule ARGS dirty Each rule can specify one or more variables: - SecRule REQUEST_URI|QUERY_STRING dirty + SecRule ARGS|REQUEST_HEADERS:User-Agent dirty There is a third format supported by the selection operator - XPath expression. XPath expressions can only used against the special @@ -1783,7 +1804,7 @@ SecResponseBodyLimit 524288 moreinfo="none">@ as the first character in the second rule parameter: - SecRule REQUEST_URI "@rx dirty" + SecRule ARGS "@rx dirty" Note how we had to use double quotes to delimit the second rule parameter. This is because the second parameter now has a whitespace @@ -2019,7 +2040,7 @@ function main() -- Retrieve one variable, applying one transformation function. -- The second parameter is a string. - local var2 = m.getvar("REQUEST_URI", "normalisePath"); + local var2 = m.getvar("ARGS", "lowercase"); -- Retrieve one variable, applying several transformation functions. -- The second parameter is now a list. You should note that m.getvar() @@ -2537,7 +2558,8 @@ SecRule REQUEST_HEADERS:Host "!^$" "deny,phase:1" - SecRule REQUEST_FILENAME "^/cgi-bin/login\.php$" "chain,log,deny,phase:2" + SecRule REQUEST_FILENAME "^/cgi-bin/login\.php" \ + "chain,log,deny,phase:2,t:none,t:lowercase,t:normalisePath" SecRule ARGS_COMBINED_SIZE "@gt 25"
@@ -2551,8 +2573,9 @@ SecRule ARGS_COMBINED_SIZE "@gt 25" allow 2 argument names - p and a. If any other argument names are injected, it will be blocked. - SecRule REQUEST_FILENAME "/index.php" "chain,log,deny,status:403,phase:2" -SecRule ARGS_NAMES "!^(p|a)$" + SecRule REQUEST_FILENAME "/index.php" \ + "chain,log,deny,status:403,phase:2,t:none,t:lowercase,t:normalisePath" +SecRule ARGS_NAMES "!^(p|a)$" "t:none,t:lowercase"
@@ -2605,9 +2628,9 @@ SecRule ARGS_NAMES "!^(p|a)$"
<literal moreinfo="none">ENV</literal> - Collection, requires a single parameter (after a colon character). - The ENV variable is set with setenv and does not give access to the CGI - environment variables. Example: + Collection, requires a single parameter (after colon). The + ENV variable is set with setenv and does not give + access to the CGI environment variables. Example: SecRule REQUEST_FILENAME "printenv" pass,setenv:tag=suspicious SecRule ENV:tag "suspicious" @@ -2988,10 +3011,17 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd" <literal moreinfo="none">REQUEST_BASENAME</literal> This variable holds just the filename part of - REQUEST_FILENAME (e.g. index.php). Warning: not URL - decoded. Example: + REQUEST_FILENAME (e.g. index.php). - SecRule REQUEST_BASENAME "^login\.php$" + Example: + + SecRule REQUEST_BASENAME "^login\.php$" phase:2,t:none,t:lowercase + + + Please note that anti-evasion transformations are not applied to + this variable by default. REQUEST_BASENAME will + recognise both / and \ as path separators. +
@@ -3007,7 +3037,7 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd" Note This variable is only available if the content type is - application/x-www-form-urlencoded. + application/x-www-form-urlencoded.
@@ -3034,25 +3064,32 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
<literal moreinfo="none">REQUEST_FILENAME</literal> - This variable holds the relative REQUEST_URI minus the - QUERY_STRING part (e.g. /index.php). Example: + This variable holds the relative REQUEST_URI + minus the QUERY_STRING part (e.g. /index.php). + Example: - SecRule REQUEST_FILENAME "^/cgi-bin/login\.php$" + SecRule REQUEST_FILENAME "^/cgi-bin/login\.php$" phase:2,t:none,t:normalisePath + + + Please note that anti-evasion transformations are not used on + REQUEST_FILENAME by default. +
<literal moreinfo="none">REQUEST_HEADERS</literal> This variable can be used as either a collection of all of the - Request Headers or can be used to specify individual headers (by using + request headers or can be used to specify individual headers (by using REQUEST_HEADERS:Header-Name). Example: the first - example uses REQUEST_HEADERS as a collection and is applying the - validateUrlEncoding operator against all headers. + example uses REQUEST_HEADERS as a collection and is + applying the validateUrlEncoding operator against all + headers. SecRule REQUEST_HEADERS "@validateUrlEncoding" - Example: the second example is targeting only the Host - header. + Example: the second example is targeting only the + Host header. SecRule REQUEST_HEADERS:Host "^[\d\.]+$" \ "deny,log,status:400,msg:'Host header is a numeric IP address'" @@ -3061,8 +3098,8 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
<literal moreinfo="none">REQUEST_HEADERS_NAMES</literal> - This variable is a collection of the names of all of the Request - Headers. Example: + This variable is a collection of the names of all of the request + headers. Example: SecRule REQUEST_HEADERS_NAMES "^x-forwarded-for" \ "log,deny,status:403,t:lowercase,msg:'Proxy Server Used'" @@ -3083,9 +3120,10 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
<literal moreinfo="none">REQUEST_METHOD</literal> - This variable holds the Request Method used by the client. - Example: the following example will trigger if the Request Method is - either CONNECT or TRACE. + This variable holds the request method used by the client. + + The following example will trigger if the request method is either + CONNECT or TRACE. SecRule REQUEST_METHOD "^((?:connect|trace))$" t:none,t:lowercase
@@ -3093,7 +3131,7 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
<literal moreinfo="none">REQUEST_PROTOCOL</literal> - This variable holds the Request Protocol Version information. + This variable holds the request protocol version information. Example: SecRule REQUEST_PROTOCOL "!^http/(0\.9|1\.0|1\.1)$" t:none,t:lowercase @@ -3102,31 +3140,45 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
<literal moreinfo="none">REQUEST_URI</literal> - This variable holds the full URL including the QUERY_STRING data - (e.g. /index.php?p=X), however it will never contain a domain name, even - if it was provided on the request line. Warning: not URL decoded. It - also does not include either the REQUEST_METHOD or the HTTP version - info. Example: + This variable holds the full URL including the + QUERY_STRING data (e.g. /index.php?p=X), however it + will never contain a domain name, even if it was provided on the request + line. It also does not include either the + REQUEST_METHOD or the HTTP version info. - SecRule REQUEST_URI "attack" + Example: + + SecRule REQUEST_URI "attack" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath + + + Please note that anti-evasion transformations are not used on + REQUEST_URI by default. +
<literal moreinfo="none">REQUEST_URI_RAW</literal> - Same as REQUEST_URI but will contain the domain name if it was - provided on the request line (e.g. - http://www.example.com/index.php?p=X). Warning: not URL decoded. - Example: + Same as REQUEST_URI but will contain the domain + name if it was provided on the request line (e.g. + http://www.example.com/index.php?p=X). - SecRule REQUEST_URI_RAW "http:/" + Example: + + SecRule REQUEST_URI_RAW "http:/" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath + + + Please note that anti-evasion transformations are not used on + REQUEST_URI_RAW by default. +
<literal moreinfo="none">RESPONSE_BODY</literal> - This variable holds the data for the response payload. - Example: + This variable holds the data for the response payload. + + Example: SecRule RESPONSE_BODY "ODBC Error Code"
@@ -3361,7 +3413,8 @@ SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd" SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass SecAction setsid:%{REQUEST_COOKIES.PHPSESSID} -SecRule REQUEST_URI "^/cgi-bin/finger$" "pass,log,setvar:session.score=+10" +SecRule REQUEST_URI "^/cgi-bin/finger$" \ + "phase:2,t:none,t:lowercase,t:normalisePath,pass,log,setvar:session.score=+10" SecRule SESSION:SCORE "@gt 50" "pass,log,setvar:session.blocked=1" SecRule SESSION:BLOCKED "@eq 1" "log,deny,status:403"
@@ -4113,9 +4166,11 @@ SecRule TX:1 "(?:(?:a(dmin|nonymous)))" Example: # Refuse to accept POST requests that do -# not specify request body length -SecRule REQUEST_METHOD ^POST$ chain -SecRule REQUEST_HEADER:Content-Length ^$ +# not specify request body length. Do note that +# this rule should be preceeded by a rule that verifies +# only valid request methods (e.g. GET, HEAD and POST) are used. +SecRule REQUEST_METHOD ^POST$ chain,t:none +SecRule REQUEST_HEADER:Content-Length ^$ t:none Note @@ -4294,7 +4349,7 @@ SecRule IP:AUTH_ATTEMPT "@gt 25" \ # The following is going to execute /usr/local/apache/bin/test.sh # as a shell script on rule match. SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ - "log,exec:/usr/local/apache/bin/test.sh" + "phase:2,t:none,t:lowercase,t:normalisePath,log,exec:/usr/local/apache/bin/test.sh" # The following is going to process /usr/local/apache/conf/exec.lua # internally as a Lua script on rule match. @@ -4328,7 +4383,8 @@ SecRule ARGS:p attack log,exec:/usr/local/apache/conf/exec.luaSecRule REQUEST_COOKIES:JSESSIONID "!^$" nolog,phase:1,pass,chain SecAction setsid:%{REQUEST_COOKIES:JSESSIONID} SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ - "log,allow,setvar:session.suspicious=1,expirevar:session.suspicious=3600,phase:1" + "phase:2,t:none,t:lowercase,t:normalisePath,log,allow,\ +setvar:session.suspicious=1,expirevar:session.suspicious=3600,phase:1" Note @@ -4946,7 +5002,8 @@ SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}Example: - SecRule REQUEST_URI "^/$" "chain,skip:2" + SecRule REQUEST_URI "^/$" \ +"phase:2,chain,t:none,skip:2" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none" SecRule &REQUEST_HEADERS:Host "@eq 0" \ @@ -4975,7 +5032,7 @@ SecRule &REQUEST_HEADERS:Accept "@eq 0" \ Example: - SecRule REQUEST_URI "^/$" "chain,skipAfter:960015" + SecRule REQUEST_URI "^/$" "chain,t:none,skipAfter:960015" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none" SecRule &REQUEST_HEADERS:Host "@eq 0" \ @@ -5050,7 +5107,8 @@ SecRule REQUEST_COOKIES:SESSIONID "47414e81cbbef3cf8366e84eeacba091" \ Example: SecRule REQUEST_FILENAME "\b(?:n(?:map|et|c)|w(?:guest|sh)|cmd(?:32)?|telnet|rcmd|ftp)\.exe\b" \ - "deny,msg:'System Command Access',id:'950002',tag:'WEB_ATTACK/FILE_INJECTION',tag:'OWASP/A2',severity:'2'" + "t:none,t:lowercase,deny,msg:'System Command Access',id:'950002',\ +tag:'WEB_ATTACK/FILE_INJECTION',tag:'OWASP/A2',severity:'2'" Note @@ -6123,4 +6181,4 @@ Server: Apache/2.x.x
- \ No newline at end of file +