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:
@@ -26,6 +26,7 @@
|
||||
#define HEADERS_MODSECURITY_RULE_H_
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "modsecurity/modsecurity.h"
|
||||
#include "modsecurity/variable_value.h"
|
||||
|
||||
|
||||
@@ -63,7 +64,80 @@ using Tags = std::vector<actions::Tag *>;
|
||||
using SetVars = std::vector<actions::SetVar *>;
|
||||
using MatchActions = std::vector<actions::Action *>;
|
||||
|
||||
class Rule {
|
||||
class RuleBase {
|
||||
public:
|
||||
RuleBase(std::unique_ptr<std::string> fileName, int lineNumber)
|
||||
: m_fileName(std::move(fileName)),
|
||||
m_lineNumber(lineNumber),
|
||||
m_phase(modsecurity::Phases::RequestHeadersPhase) {
|
||||
}
|
||||
|
||||
virtual bool evaluate(Transaction *transaction,
|
||||
std::shared_ptr<RuleMessage> rm) = 0;
|
||||
|
||||
std::shared_ptr<std::string> getFileName() const {
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
int getLineNumber() const {
|
||||
return m_lineNumber;
|
||||
}
|
||||
|
||||
int getPhase() const { return m_phase; }
|
||||
void setPhase(int phase) { m_phase = phase; }
|
||||
|
||||
virtual std::string getReference() {
|
||||
return *m_fileName + ":" + std::to_string(m_lineNumber);
|
||||
}
|
||||
|
||||
|
||||
virtual bool isMarker() { return false; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::string> m_fileName;
|
||||
int m_lineNumber;
|
||||
// FIXME: phase may not be neede to SecMarker.
|
||||
int m_phase;
|
||||
};
|
||||
|
||||
|
||||
class RuleMarker : public RuleBase {
|
||||
public:
|
||||
RuleMarker(
|
||||
const std::string &name,
|
||||
std::unique_ptr<std::string> fileName,
|
||||
int lineNumber)
|
||||
: RuleBase(std::move(fileName), lineNumber),
|
||||
m_name(std::make_shared<std::string>(name)) { }
|
||||
|
||||
|
||||
virtual bool evaluate(Transaction *transaction,
|
||||
std::shared_ptr<RuleMessage> rm) override {
|
||||
|
||||
if (transaction->isInsideAMarker()) {
|
||||
if (*transaction->getCurrentMarker() == *m_name) {
|
||||
transaction->removeMarker();
|
||||
// FIXME: Move this to .cc
|
||||
// ms_dbg_a(transaction, 4, "Out of a SecMarker " + *m_name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
std::shared_ptr<std::string> getName() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool isMarker() override { return true; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::string> m_name;
|
||||
};
|
||||
|
||||
|
||||
class Rule : public RuleBase {
|
||||
public:
|
||||
Rule(operators::Operator *op,
|
||||
variables::Variables *variables,
|
||||
@@ -71,11 +145,13 @@ class Rule {
|
||||
Transformations *transformations,
|
||||
std::unique_ptr<std::string> fileName,
|
||||
int lineNumber);
|
||||
explicit Rule(const std::string &marker);
|
||||
explicit Rule(const std::string &marker,
|
||||
std::unique_ptr<std::string> fileName,
|
||||
int lineNumber);
|
||||
virtual ~Rule();
|
||||
|
||||
virtual bool evaluate(Transaction *transaction,
|
||||
std::shared_ptr<RuleMessage> rm);
|
||||
std::shared_ptr<RuleMessage> rm) override;
|
||||
|
||||
void organizeActions(std::vector<actions::Action *> *actions);
|
||||
void cleanUpActions();
|
||||
@@ -119,8 +195,6 @@ class Rule {
|
||||
|
||||
inline bool isUnconditional() const { return m_operator == NULL; }
|
||||
|
||||
virtual bool isMarker() { return m_isSecMarker; }
|
||||
|
||||
inline bool isChained() const { return m_isChained == true; }
|
||||
inline bool hasCaptureAction() const { return m_containsCaptureAction == true; }
|
||||
inline void setChained(bool b) { m_isChained = b; }
|
||||
@@ -133,23 +207,23 @@ class Rule {
|
||||
std::string msg(Transaction *t);
|
||||
inline bool hasSeverity() const { return m_severity != NULL; }
|
||||
int severity() const;
|
||||
int getPhase() const { return m_phase; }
|
||||
void setPhase(int phase) { m_phase = phase; }
|
||||
|
||||
std::string getOperatorName() const;
|
||||
|
||||
int64_t m_ruleId;
|
||||
|
||||
virtual std::string getReference() override {
|
||||
return std::to_string(m_ruleId);
|
||||
}
|
||||
|
||||
std::unique_ptr<Rule> m_chainedRuleChild;
|
||||
Rule *m_chainedRuleParent;
|
||||
|
||||
std::shared_ptr<std::string> m_fileName;
|
||||
|
||||
std::string m_marker;
|
||||
std::string m_rev;
|
||||
std::string m_ver;
|
||||
int m_accuracy;
|
||||
int m_maturity;
|
||||
int m_lineNumber;
|
||||
|
||||
private:
|
||||
modsecurity::variables::Variables *m_variables;
|
||||
@@ -174,7 +248,7 @@ class Rule {
|
||||
bool m_isSecMarker:1;
|
||||
bool m_unconditional:1;
|
||||
|
||||
int m_phase;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@@ -55,9 +55,9 @@ class RuleMessage {
|
||||
m_reference(""),
|
||||
m_rev(rule->m_rev),
|
||||
m_rule(rule),
|
||||
m_ruleFile(rule->m_fileName),
|
||||
m_ruleFile(rule->getFileName()),
|
||||
m_ruleId(rule->m_ruleId),
|
||||
m_ruleLine(rule->m_lineNumber),
|
||||
m_ruleLine(rule->getLineNumber()),
|
||||
m_saveMessage(true),
|
||||
m_serverIpAddress(trans->m_serverIpAddress),
|
||||
m_severity(0),
|
||||
|
@@ -40,7 +40,7 @@ class Rules {
|
||||
public:
|
||||
void dump() const {
|
||||
for (int j = 0; j < m_rules.size(); j++) {
|
||||
std::cout << " Rule ID: " << std::to_string(m_rules.at(j)->m_ruleId);
|
||||
std::cout << " Rule ID: " << m_rules.at(j)->getReference();
|
||||
std::cout << "--" << m_rules.at(j) << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,8 @@ class Rules {
|
||||
int append(Rules *from, const std::vector<int64_t> &ids, std::ostringstream *err) {
|
||||
size_t j = 0;
|
||||
for (; j < from->size(); j++) {
|
||||
Rule *rule = from->at(j).get();
|
||||
if (std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) {
|
||||
Rule *rule = dynamic_cast<Rule *>(from->at(j).get());
|
||||
if (rule && std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) {
|
||||
if (err != NULL) {
|
||||
*err << "Rule id: " << std::to_string(rule->m_ruleId) \
|
||||
<< " is duplicated" << std::endl;
|
||||
@@ -61,28 +61,28 @@ class Rules {
|
||||
return j;
|
||||
}
|
||||
|
||||
bool insert(std::shared_ptr<Rule> rule) {
|
||||
bool insert(std::shared_ptr<RuleBase> rule) {
|
||||
return insert(rule, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool insert(std::shared_ptr<Rule> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
|
||||
if (ids != nullptr && std::binary_search(ids->begin(), ids->end(), rule->m_ruleId)) {
|
||||
bool insert(std::shared_ptr<RuleBase> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
|
||||
Rule *r = dynamic_cast<Rule *>(rule.get());
|
||||
if (ids != nullptr && std::binary_search(ids->begin(), ids->end(), r->m_ruleId)) {
|
||||
if (err != nullptr) {
|
||||
*err << "Rule id: " << std::to_string(rule->m_ruleId) \
|
||||
*err << "Rule id: " << std::to_string(r->m_ruleId) \
|
||||
<< " is duplicated" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rules.push_back(rule);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t size() const { return m_rules.size(); }
|
||||
std::shared_ptr<Rule> operator[](int index) const { return m_rules[index]; }
|
||||
std::shared_ptr<Rule> at(int index) const { return m_rules[index]; }
|
||||
std::shared_ptr<RuleBase> operator[](int index) const { return m_rules[index]; }
|
||||
std::shared_ptr<RuleBase> at(int index) const { return m_rules[index]; }
|
||||
|
||||
std::vector<std::shared_ptr<Rule> > m_rules;
|
||||
std::vector<std::shared_ptr<RuleBase> > m_rules;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -40,7 +40,7 @@ class Rule;
|
||||
class RulesSetPhases {
|
||||
public:
|
||||
|
||||
bool insert(std::shared_ptr<Rule> rule);
|
||||
bool insert(std::shared_ptr<RuleBase> rule);
|
||||
|
||||
int append(RulesSetPhases *from, std::ostringstream *err);
|
||||
void dump() const;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -48,6 +49,7 @@ typedef struct Rules_t RulesSet;
|
||||
#include "modsecurity/collection/collection.h"
|
||||
#include "modsecurity/variable_origin.h"
|
||||
|
||||
|
||||
#ifndef NO_LOGS
|
||||
#define ms_dbg(b, c) \
|
||||
do { \
|
||||
@@ -284,9 +286,38 @@ class TransactionAnchoredVariables {
|
||||
int m_variableOffset;
|
||||
};
|
||||
|
||||
class TransactionSecMarkerManagement {
|
||||
public:
|
||||
bool isInsideAMarker() const {
|
||||
if (m_marker) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::string> getCurrentMarker() const {
|
||||
if (m_marker) {
|
||||
return m_marker;
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void removeMarker() {
|
||||
m_marker.reset();
|
||||
}
|
||||
|
||||
void addMarker(std::shared_ptr<std::string> name) {
|
||||
m_marker = name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::string> m_marker;
|
||||
};
|
||||
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
class Transaction : public TransactionAnchoredVariables {
|
||||
class Transaction : public TransactionAnchoredVariables, public TransactionSecMarkerManagement {
|
||||
public:
|
||||
Transaction(ModSecurity *transaction, RulesSet *rules, void *logCbData);
|
||||
Transaction(ModSecurity *transaction, RulesSet *rules, char *id,
|
||||
@@ -518,12 +549,6 @@ class Transaction : public TransactionAnchoredVariables {
|
||||
*/
|
||||
std::shared_ptr<std::string> m_id;
|
||||
|
||||
/**
|
||||
* Holds the SecMarker name that this transaction should wait to perform
|
||||
* rules evaluation again.
|
||||
*/
|
||||
std::string m_marker;
|
||||
|
||||
/**
|
||||
* Holds the amount of rules that should be skipped. If bigger than 0 the
|
||||
* current rule should be skipped and the number needs to be decreased.
|
||||
|
Reference in New Issue
Block a user