mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-29 11:16:33 +03:00
Splits Rule class into: Rule, RuleBase, RuleMarker
This commit is contained in:
@@ -28,8 +28,8 @@ namespace actions {
|
||||
|
||||
|
||||
bool SkipAfter::evaluate(Rule *rule, Transaction *transaction) {
|
||||
ms_dbg_a(transaction, 5, "Setting skipAfter for: " + m_parser_payload);
|
||||
transaction->m_marker = m_parser_payload;
|
||||
ms_dbg_a(transaction, 5, "Setting skipAfter for: " + *m_skipName);
|
||||
transaction->addMarker(m_skipName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "modsecurity/actions/action.h"
|
||||
|
||||
@@ -30,9 +31,12 @@ namespace actions {
|
||||
class SkipAfter : public Action {
|
||||
public:
|
||||
explicit SkipAfter(const std::string &action)
|
||||
: Action(action, RunTimeOnlyIfMatchKind) { }
|
||||
: Action(action, RunTimeOnlyIfMatchKind),
|
||||
m_skipName(std::make_shared<std::string>(m_parser_payload)) { }
|
||||
|
||||
bool evaluate(Rule *rule, Transaction *transaction) override;
|
||||
private:
|
||||
std::shared_ptr<std::string> m_skipName;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -41,9 +41,11 @@ Driver::~Driver() {
|
||||
}
|
||||
|
||||
|
||||
int Driver::addSecMarker(std::string marker) {
|
||||
int Driver::addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber) {
|
||||
// FIXME: we might move this to the parser.
|
||||
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
std::unique_ptr<Rule> rule(new Rule(marker));
|
||||
RuleMarker *r = new RuleMarker(marker, std::move(fileName), lineNumber);
|
||||
std::unique_ptr<RuleMarker> rule(std::move(r));
|
||||
rule->setPhase(i);
|
||||
m_rulesSetPhases.insert(std::move(rule));
|
||||
}
|
||||
@@ -58,7 +60,6 @@ int Driver::addSecAction(std::unique_ptr<Rule> rule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_rulesSetPhases.insert(std::move(rule));
|
||||
|
||||
return true;
|
||||
@@ -99,15 +100,16 @@ int Driver::addSecRule(std::unique_ptr<Rule> r) {
|
||||
*/
|
||||
if (rule->m_ruleId == 0) {
|
||||
m_parserError << "Rules must have an ID. File: ";
|
||||
m_parserError << rule->m_fileName << " at line: ";
|
||||
m_parserError << std::to_string(rule->m_lineNumber) << std::endl;
|
||||
m_parserError << rule->getFileName() << " at line: ";
|
||||
m_parserError << std::to_string(rule->getLineNumber()) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
Rules *rules = m_rulesSetPhases[i];
|
||||
for (int j = 0; j < rules->size(); j++) {
|
||||
if (rules->at(j)->m_ruleId == rule->m_ruleId) {
|
||||
Rule *lr = dynamic_cast<Rule *>(rules->at(j).get());
|
||||
if (lr && lr->m_ruleId == rule->m_ruleId) {
|
||||
m_parserError << "Rule id: " << std::to_string(rule->m_ruleId) \
|
||||
<< " is duplicated" << std::endl;
|
||||
return false;
|
||||
|
@@ -68,7 +68,7 @@ class Driver : public RulesSetProperties {
|
||||
|
||||
int addSecRule(std::unique_ptr<Rule> rule);
|
||||
int addSecAction(std::unique_ptr<Rule> rule);
|
||||
int addSecMarker(std::string marker);
|
||||
int addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber);
|
||||
int addSecRuleScript(std::unique_ptr<RuleScript> rule);
|
||||
|
||||
bool scan_begin();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1221,7 +1221,10 @@ expression:
|
||||
}
|
||||
| CONFIG_DIR_SEC_MARKER
|
||||
{
|
||||
driver.addSecMarker(modsecurity::utils::string::removeBracketsIfNeeded($1));
|
||||
driver.addSecMarker(modsecurity::utils::string::removeBracketsIfNeeded($1),
|
||||
/* file name */ std::unique_ptr<std::string>(new std::string(*@1.end.filename)),
|
||||
/* line number */ @1.end.line
|
||||
);
|
||||
}
|
||||
| CONFIG_DIR_RULE_ENG CONFIG_VALUE_OFF
|
||||
{
|
||||
|
32
src/rule.cc
32
src/rule.cc
@@ -51,17 +51,18 @@ using variables::Variable;
|
||||
using actions::transformations::None;
|
||||
using actions::transformations::Transformation;
|
||||
|
||||
Rule::Rule(const std::string &marker)
|
||||
: m_ruleId(0),
|
||||
Rule::Rule(const std::string &marker,
|
||||
std::unique_ptr<std::string> fileName,
|
||||
int lineNumber)
|
||||
: RuleBase(std::move(fileName), lineNumber),
|
||||
m_ruleId(0),
|
||||
m_chainedRuleChild(nullptr),
|
||||
m_chainedRuleParent(NULL),
|
||||
/* m_fileName(""), */
|
||||
m_marker(marker),
|
||||
m_rev(""),
|
||||
m_ver(""),
|
||||
m_accuracy(0),
|
||||
m_maturity(0),
|
||||
m_lineNumber(0),
|
||||
m_variables(NULL),
|
||||
m_operator(NULL),
|
||||
m_disruptiveAction(nullptr),
|
||||
@@ -77,8 +78,7 @@ Rule::Rule(const std::string &marker)
|
||||
m_containsStaticBlockAction(false),
|
||||
m_isChained(false),
|
||||
m_isSecMarker(true),
|
||||
m_unconditional(false),
|
||||
m_phase(-1) { }
|
||||
m_unconditional(false) { }
|
||||
|
||||
Rule::Rule(Operator *op,
|
||||
variables::Variables *variables,
|
||||
@@ -86,16 +86,15 @@ Rule::Rule(Operator *op,
|
||||
Transformations *transformations,
|
||||
std::unique_ptr<std::string> fileName,
|
||||
int lineNumber)
|
||||
: m_ruleId(0),
|
||||
: RuleBase(std::move(fileName), lineNumber),
|
||||
m_ruleId(0),
|
||||
m_chainedRuleChild(nullptr),
|
||||
m_chainedRuleParent(NULL),
|
||||
m_fileName(std::move(fileName)),
|
||||
m_marker(""),
|
||||
m_rev(""),
|
||||
m_ver(""),
|
||||
m_accuracy(0),
|
||||
m_maturity(0),
|
||||
m_lineNumber(lineNumber),
|
||||
m_variables(variables),
|
||||
m_operator(op),
|
||||
m_disruptiveAction(nullptr),
|
||||
@@ -111,19 +110,10 @@ Rule::Rule(Operator *op,
|
||||
m_containsStaticBlockAction(false),
|
||||
m_isChained(false),
|
||||
m_isSecMarker(false),
|
||||
m_unconditional(false),
|
||||
m_phase(-1) {
|
||||
m_unconditional(false) {
|
||||
|
||||
organizeActions(actions);
|
||||
|
||||
/**
|
||||
* If phase is not entered, we assume phase 2. For historical reasons.
|
||||
*
|
||||
*/
|
||||
if (m_phase == -1) {
|
||||
m_phase = modsecurity::Phases::RequestHeadersPhase;
|
||||
}
|
||||
|
||||
delete actions;
|
||||
}
|
||||
|
||||
@@ -381,7 +371,7 @@ void Rule::executeTransformations(
|
||||
// Notice that first we make sure that won't be a t:none
|
||||
// on the target rule.
|
||||
if (none == 0) {
|
||||
for (auto &a : trans->m_rules->m_defaultActions[this->m_phase]) {
|
||||
for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) {
|
||||
if (a->action_kind \
|
||||
!= actions::Action::RunTimeBeforeMatchAttemptKind) {
|
||||
continue;
|
||||
@@ -566,7 +556,7 @@ void Rule::executeActionsAfterFullMatch(Transaction *trans,
|
||||
bool containsBlock, std::shared_ptr<RuleMessage> ruleMessage) {
|
||||
bool disruptiveAlreadyExecuted = false;
|
||||
|
||||
for (auto &a : trans->m_rules->m_defaultActions[this->m_phase]) {
|
||||
for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) {
|
||||
if (a.get()->action_kind != actions::Action::RunTimeOnlyIfMatchKind) {
|
||||
continue;
|
||||
}
|
||||
|
@@ -133,42 +133,38 @@ int RulesSet::evaluate(int phase, Transaction *t) {
|
||||
//}
|
||||
|
||||
for (int i = 0; i < rules->size(); i++) {
|
||||
Rule *rule = rules->at(i).get();
|
||||
if (t->m_marker.empty() == false) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + std::to_string(rule->m_ruleId) \
|
||||
+ "' due to a SecMarker: " + t->m_marker);
|
||||
#ifndef NO_LOGS
|
||||
m_secmarker_skipped++;
|
||||
#endif
|
||||
ms_dbg_a(t, 9, "Rule: " + rule->m_marker);
|
||||
// FIXME: This is not meant to be here. At the end of this refactoring,
|
||||
// the shared pointer won't be used.
|
||||
std::shared_ptr<RuleBase> rule = rules->at(i);
|
||||
if (t->isInsideAMarker() && !rule->isMarker()) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \
|
||||
+ "' due to a SecMarker: " + *t->getCurrentMarker());
|
||||
|
||||
if (rule->isMarker() && rule->m_marker == t->m_marker) {
|
||||
ms_dbg_a(t, 4, "Out of a SecMarker after skip " \
|
||||
+ std::to_string(m_secmarker_skipped) + " rules.");
|
||||
t->m_marker.clear();
|
||||
#ifndef NO_LOGS
|
||||
m_secmarker_skipped = 0;
|
||||
#endif
|
||||
}
|
||||
} else if (rule->isMarker()) {
|
||||
rule->evaluate(t, NULL);
|
||||
} else if (t->m_skip_next > 0) {
|
||||
t->m_skip_next--;
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + std::to_string(rule->m_ruleId) \
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \
|
||||
+ "' due to a `skip' action. Still " + \
|
||||
std::to_string(t->m_skip_next) + " to be skipped.");
|
||||
} else if (t->m_allowType
|
||||
!= actions::disruptive::NoneAllowType) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + std::to_string(rule->m_ruleId) \
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \
|
||||
+ "' as request trough the utilization of an `allow' action.");
|
||||
} else if (m_exceptions.contains(rule->m_ruleId)) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + std::to_string(rule->m_ruleId) \
|
||||
+ "'. Removed by an SecRuleRemove directive.");
|
||||
} else {
|
||||
RuleBase *base = rule.get();
|
||||
Rule *ruleWithOperator = dynamic_cast<Rule *>(base);
|
||||
if (m_exceptions.contains(ruleWithOperator->m_ruleId)) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \
|
||||
+ "'. Removed by an SecRuleRemove directive.");
|
||||
continue;
|
||||
}
|
||||
bool remove_rule = false;
|
||||
if (m_exceptions.m_remove_rule_by_msg.empty() == false) {
|
||||
for (auto &z : m_exceptions.m_remove_rule_by_msg) {
|
||||
if (rule->containsMsg(z, t) == true) {
|
||||
if (ruleWithOperator->containsMsg(z, t) == true) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" \
|
||||
+ std::to_string(rule->m_ruleId) \
|
||||
+ ruleWithOperator->getReference() \
|
||||
+ "'. Removed by a SecRuleRemoveByMsg directive.");
|
||||
remove_rule = true;
|
||||
break;
|
||||
@@ -181,9 +177,9 @@ int RulesSet::evaluate(int phase, Transaction *t) {
|
||||
|
||||
if (m_exceptions.m_remove_rule_by_tag.empty() == false) {
|
||||
for (auto &z : m_exceptions.m_remove_rule_by_tag) {
|
||||
if (rule->containsTag(z, t) == true) {
|
||||
if (ruleWithOperator->containsTag(z, t) == true) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" \
|
||||
+ std::to_string(rule->m_ruleId) \
|
||||
+ ruleWithOperator->getReference() \
|
||||
+ "'. Removed by a SecRuleRemoveByTag directive.");
|
||||
remove_rule = true;
|
||||
break;
|
||||
@@ -196,9 +192,9 @@ int RulesSet::evaluate(int phase, Transaction *t) {
|
||||
|
||||
if (t->m_ruleRemoveByTag.empty() == false) {
|
||||
for (auto &z : t->m_ruleRemoveByTag) {
|
||||
if (rule->containsTag(z, t) == true) {
|
||||
if (ruleWithOperator->containsTag(z, t) == true) {
|
||||
ms_dbg_a(t, 9, "Skipped rule id '" \
|
||||
+ std::to_string(rule->m_ruleId) \
|
||||
+ ruleWithOperator->getReference() \
|
||||
+ "'. Skipped due to a ruleRemoveByTag action.");
|
||||
remove_rule = true;
|
||||
break;
|
||||
|
@@ -29,7 +29,7 @@
|
||||
namespace modsecurity {
|
||||
|
||||
|
||||
bool RulesSetPhases::insert(std::shared_ptr<Rule> rule) {
|
||||
bool RulesSetPhases::insert(std::shared_ptr<RuleBase> rule) {
|
||||
if (rule->getPhase() >= modsecurity::Phases::NUMBER_OF_PHASES) {
|
||||
return false;
|
||||
}
|
||||
@@ -46,8 +46,8 @@ int RulesSetPhases::append(RulesSetPhases *from, std::ostringstream *err) {
|
||||
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
v.reserve(m_rulesAtPhase[i].size());
|
||||
for (size_t z = 0; z < m_rulesAtPhase[i].size(); z++) {
|
||||
Rule *rule_ckc = m_rulesAtPhase[i].at(z).get();
|
||||
if (rule_ckc->isMarker() == true) {
|
||||
Rule *rule_ckc = dynamic_cast<Rule *>(m_rulesAtPhase[i].at(z).get());
|
||||
if (!rule_ckc) {
|
||||
continue;
|
||||
}
|
||||
v.push_back(rule_ckc->m_ruleId);
|
||||
|
@@ -126,7 +126,6 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData)
|
||||
m_requestBody(),
|
||||
m_responseBody(),
|
||||
/* m_id(), */
|
||||
m_marker(""),
|
||||
m_skip_next(0),
|
||||
m_allowType(modsecurity::actions::disruptive::NoneAllowType),
|
||||
m_uri_decoded(""),
|
||||
@@ -200,7 +199,6 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, char *id, void *logCb
|
||||
m_requestBody(),
|
||||
m_responseBody(),
|
||||
m_id(std::unique_ptr<std::string>(new std::string(id))),
|
||||
m_marker(""),
|
||||
m_skip_next(0),
|
||||
m_allowType(modsecurity::actions::disruptive::NoneAllowType),
|
||||
m_uri_decoded(""),
|
||||
|
Reference in New Issue
Block a user