diff --git a/CHANGES b/CHANGES index 776ea39b..9a0c6565 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +23 Jul 2012 - 2.6.7 +------------------- + + * Fixed PCRE mismtach version warning message (Thanks Victor Julien). + + * Fixed explicit target replacement using SecUpdateTargetById was broken. + + * The ctl:updateTargetById is deprecated and will be removed for future versions since + there is no safe way to use it per-request. + + * Added ctl:RemoveTargetById that can be used to exclude targets to be processed per-request. + 08 Jun 2012 - 2.6.6 ------------------- diff --git a/apache2/modsecurity.c b/apache2/modsecurity.c index 11615c29..7b9fff4d 100644 --- a/apache2/modsecurity.c +++ b/apache2/modsecurity.c @@ -368,6 +368,8 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) { if (msr->response_headers_to_sanitize == NULL) return -1; msr->pattern_to_sanitize = apr_table_make(msr->mp, 32); if (msr->pattern_to_sanitize == NULL) return -1; + msr->removed_targets = apr_table_make(msr->mp, 16); + if (msr->removed_targets == NULL) return -1; /* Initialise cookies */ msr->request_cookies = apr_table_make(msr->mp, 16); diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index cead25d3..1ed9b4c5 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -280,6 +280,7 @@ struct modsec_rec { apr_table_t *response_headers_to_sanitize; apr_table_t *request_cookies; apr_table_t *pattern_to_sanitize; + apr_table_t *removed_targets; unsigned int urlencoded_error; unsigned int inbound_error; diff --git a/apache2/re.c b/apache2/re.c index 907bb089..9a8224ec 100644 --- a/apache2/re.c +++ b/apache2/re.c @@ -32,6 +32,7 @@ static const char *const severities[] = { NULL, }; +static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, const char *full_varname); static apr_status_t msre_parse_targets(msre_ruleset *ruleset, const char *text, apr_array_header_t *arr, char **error_msg); static char *msre_generate_target_string(apr_pool_t *pool, msre_rule *rule); @@ -43,6 +44,53 @@ static apr_status_t msre_rule_process(msre_rule *rule, modsec_rec *msr); /* -- Actions, variables, functions and operator functions ----------------- */ +static int fetch_target_exception(msre_rule *rule, modsec_rec *msr, const char *full_varname) { + const char *targets = NULL, *exceptions = NULL; + char *savedptr = NULL, *target = NULL; + + if(msr == NULL) + return 0; + + if(rule == NULL) + return 0; + + if(rule->actionset == NULL) + return 0; + + if(rule->actionset->id !=NULL) { + + exceptions = (const char *)apr_table_get(msr->removed_targets, rule->actionset->id); + + targets = apr_pstrdup(msr->mp, exceptions); + + if(targets != NULL) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "fetch_target_exception: Found exception target list [%s] for rule id %s", targets, rule->actionset->id); + } + + target = apr_strtok((char *)targets, ",", &savedptr); + + while(target != NULL) { + if(strncasecmp(target, full_varname, strlen(target)) == 0) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "fetch_target_exception: Target %s will not be processed.", target); + } + return 1; + } + target = apr_strtok(NULL, ",", &savedptr); + } + } else { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "fetch_target_exception: No exception target found for rule id %s.", rule->actionset->id); + + } + } + + } + + return 0; +} + char *update_rule_target(cmd_parms *cmd, directory_config *dcfg, msre_ruleset *rset, const char *p1, const char *p2, const char *p3) { @@ -2161,10 +2209,24 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr, full_varname = var->name; } + rc = fetch_target_exception(rule, msr, full_varname); + + if(rc > 0) { + + if (msr->txcfg->debuglog_level >= 4) { + msr_log(msr, 4, "Executing operator \"%s%s\" with param \"%s\" against %s skipped.", + (rule->op_negated ? "!" : ""), rule->op_name, + log_escape(msr->mp, rule->op_param), full_varname); + } + + return RULE_NO_MATCH; + + } + if (msr->txcfg->debuglog_level >= 4) { msr_log(msr, 4, "Executing operator \"%s%s\" with param \"%s\" against %s.", - (rule->op_negated ? "!" : ""), rule->op_name, - log_escape(msr->mp, rule->op_param), full_varname); + (rule->op_negated ? "!" : ""), rule->op_name, + log_escape(msr->mp, rule->op_param), full_varname); } if (msr->txcfg->debuglog_level >= 9) { diff --git a/apache2/re_actions.c b/apache2/re_actions.c index 280452b9..8879a733 100644 --- a/apache2/re_actions.c +++ b/apache2/re_actions.c @@ -818,6 +818,17 @@ static char *msre_action_ctl_validate(msre_engine *engine, msre_action *action) } return NULL; + } else + if (strcasecmp(name, "ruleRemoveTargetById") == 0) { + char *parm = NULL; + char *savedptr = NULL; + + parm = apr_strtok(value,";",&savedptr); + + if(parm == NULL && savedptr == NULL) + return apr_psprintf(engine->mp, "ruleRemoveTargetById must has at least id;target1,targets2...targetN"); + + return NULL; } else if (strcasecmp(name, "ruleUpdateTargetById") == 0) { char *parm = NULL; @@ -1046,6 +1057,23 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp, return 1; } else + if (strcasecmp(name, "ruleRemoveTargetById") == 0) { + msre_rule *updated_rule = NULL; + char *p1 = NULL, *p2 = NULL; + char *savedptr = NULL; + + p1 = apr_strtok(value,";",&savedptr); + + p2 = apr_strtok(NULL,";",&savedptr); + + if (msr->txcfg->debuglog_level >= 4) { + msr_log(msr, 4, "Ctl: ruleRemoveTargetById id=%s targets=%s", p1, p2); + } + + apr_table_setn(msr->removed_targets, p1, (const char *)apr_pstrdup(msr->mp, p2)); + + return 1; + } else if (strcasecmp(name, "ruleUpdateTargetById") == 0) { char *p1 = NULL, *p2 = NULL, *p3 = NULL; char *savedptr = NULL;