Splits Rule class into: Rule, RuleBase, RuleMarker

This commit is contained in:
Felipe Zimmerle
2019-02-18 15:42:13 -03:00
parent fda03c0016
commit 43f8aee6b6
18 changed files with 948 additions and 851 deletions

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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(""),