diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index 393b4144..5403bb32 100644 --- a/headers/modsecurity/rule.h +++ b/headers/modsecurity/rule.h @@ -140,7 +140,8 @@ class Rule { int m_phase; modsecurity::Variables::Variables *m_variables; operators::Operator *m_op; - Rule *m_chainedRule; + Rule *m_chainedRuleChild; + Rule *m_chainedRuleParent; std::string m_fileName; std::string m_marker; std::string m_rev; diff --git a/src/parser/driver.cc b/src/parser/driver.cc index 8bd2129b..e942939b 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -78,9 +78,10 @@ int Driver::addSecRule(Rule *rule) { } if (lastRule && lastRule->m_chained) { - if (lastRule->m_chainedRule == NULL) { + if (lastRule->m_chainedRuleChild == NULL) { rule->m_phase = lastRule->m_phase; - lastRule->m_chainedRule = rule; + lastRule->m_chainedRuleChild = rule; + rule->m_chainedRuleParent = lastRule; if (rule->m_theDisruptiveAction) { m_parserError << "Disruptive actions can only be specified by"; m_parserError << " chain starter rules."; @@ -88,12 +89,13 @@ int Driver::addSecRule(Rule *rule) { } return true; } else { - Rule *a = lastRule->m_chainedRule; - while (a->m_chained && a->m_chainedRule != NULL) { - a = a->m_chainedRule; + Rule *a = lastRule->m_chainedRuleChild; + while (a->m_chained && a->m_chainedRuleChild != NULL) { + a = a->m_chainedRuleChild; } - if (a->m_chained && a->m_chainedRule == NULL) { - a->m_chainedRule = rule; + if (a->m_chained && a->m_chainedRuleChild == NULL) { + a->m_chainedRuleChild = rule; + rule->m_chainedRuleParent = a; if (a->m_theDisruptiveAction) { m_parserError << "Disruptive actions can only be "; m_parserError << "specified by chain starter rules."; diff --git a/src/rule.cc b/src/rule.cc index 42b42862..df48b45a 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -57,7 +57,7 @@ Rule::Rule(std::string marker) m_actionsSetVar(), m_actionsTag(), m_chained(false), - m_chainedRule(NULL), + m_chainedRuleChild(NULL), m_fileName(""), m_lineNumber(0), m_marker(marker), @@ -91,7 +91,8 @@ Rule::Rule(Operator *_op, m_actionsSetVar(), m_actionsTag(), m_chained(false), - m_chainedRule(NULL), + m_chainedRuleChild(NULL), + m_chainedRuleParent(NULL), m_fileName(fileName), m_lineNumber(lineNumber), m_marker(""), @@ -146,8 +147,8 @@ Rule::~Rule() { delete m_variables; } - if (m_chainedRule != NULL) { - delete m_chainedRule; + if (m_chainedRuleChild != NULL) { + delete m_chainedRuleChild; } } @@ -793,7 +794,7 @@ bool Rule::evaluate(Transaction *trans, goto end_exec; } - if (this->m_chainedRule == NULL) { + if (this->m_chainedRuleChild == NULL) { #ifndef NO_LOGS trans->debug(4, "Rule is marked as chained but there " \ "isn't a subsequent rule."); @@ -804,7 +805,7 @@ bool Rule::evaluate(Transaction *trans, #ifndef NO_LOGS trans->debug(4, "Executing chained rule."); #endif - recursiveGlobalRet = this->m_chainedRule->evaluate(trans, ruleMessage); + recursiveGlobalRet = this->m_chainedRuleChild->evaluate(trans, ruleMessage); if (recursiveGlobalRet == true) { goto end_exec; diff --git a/src/variables/rule.h b/src/variables/rule.h index 018e8579..4947a190 100644 --- a/src/variables/rule.h +++ b/src/variables/rule.h @@ -40,11 +40,17 @@ class Rule_DictElement : public VariableDictElement { \ static void id(Transaction *t, Rule *rule, std::vector *l) { - if (!rule) { + Rule *r = rule; + + while (r && r->m_ruleId == 0) { + r = r->m_chainedRuleParent; + } + + if (!r || r->m_ruleId == 0) { return; } std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(rule->m_ruleId)); + std::string *a = new std::string(std::to_string(r->m_ruleId)); VariableValue *var = new VariableValue( std::make_shared("RULE:id"), a @@ -60,11 +66,18 @@ class Rule_DictElement : public VariableDictElement { \ static void rev(Transaction *t, Rule *rule, std::vector *l) { - if (!rule) { + Rule *r = rule; + + while (r && r->m_rev.empty()) { + r = r->m_chainedRuleParent; + } + + if (!r) { return; } + std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(rule->m_rev); + std::string *a = new std::string(r->m_rev); VariableValue *var = new VariableValue( std::make_shared("RULE:rev"), a @@ -80,9 +93,15 @@ class Rule_DictElement : public VariableDictElement { \ static void severity(Transaction *t, Rule *rule, std::vector *l) { - if (rule && rule->m_severity) { + Rule *r = rule; + + while (r && !r->m_severity) { + r = r->m_chainedRuleParent; + } + + if (r && r->m_severity) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(rule->m_severity->m_severity)); + std::string *a = new std::string(std::to_string(r->m_severity->m_severity)); VariableValue *var = new VariableValue( std::make_shared("RULE:severity"), a @@ -99,9 +118,15 @@ class Rule_DictElement : public VariableDictElement { \ static void logData(Transaction *t, Rule *rule, std::vector *l) { - if (rule && rule->m_logData) { + Rule *r = rule; + + while (r && !r->m_logData) { + r = r->m_chainedRuleParent; + } + + if (r && r->m_logData) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(rule->m_logData->data(t)); + std::string *a = new std::string(r->m_logData->data(t)); VariableValue *var = new VariableValue( std::make_shared("RULE:logdata"), a @@ -117,9 +142,15 @@ class Rule_DictElement : public VariableDictElement { \ static void msg(Transaction *t, Rule *rule, std::vector *l) { - if (rule && rule->m_msg) { + Rule *r = rule; + + while (r && !r->m_msg) { + r = r->m_chainedRuleParent; + } + + if (r && r->m_msg) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(rule->m_msg->data(t)); + std::string *a = new std::string(r->m_msg->data(t)); VariableValue *var = new VariableValue( std::make_shared("RULE:msg"), a