Refactoring in the Rule class to make it more elegant

This commit is contained in:
Felipe Zimmerle 2019-02-25 20:22:38 -03:00
parent 5770da30a1
commit c6913737f2
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
23 changed files with 191 additions and 210 deletions

View File

@ -36,38 +36,10 @@ namespace variables {
class Variable; class Variable;
class Variables; class Variables;
} }
namespace actions {
class Action;
class Severity;
class LogData;
class Msg;
class Rev;
class SetVar;
class Tag;
namespace transformations {
class Transformation;
}
}
namespace operators { namespace operators {
class Operator; class Operator;
} }
using TransformationResult = std::pair<std::shared_ptr<std::string>,
std::shared_ptr<std::string>>;
using TransformationResults = std::list<TransformationResult>;
using Transformation = actions::transformations::Transformation;
using Transformations = std::vector<std::shared_ptr<Transformation> >;
using TransformationsPtr = std::vector<Transformation *>;
using Actions = std::vector<actions::Action *>;
using Tags = std::vector<std::shared_ptr<actions::Tag> >;
using TagsPtr = std::vector<actions::Tag *>;
using SetVars = std::vector<std::shared_ptr<actions::SetVar> >;
using SetVarsPtr = std::vector<actions::SetVar *>;
using MatchActions = std::vector<std::shared_ptr<actions::Action > >;
using MatchActionsPtr = std::vector<actions::Action *>;
class Rule { class Rule {
public: public:

View File

@ -113,7 +113,7 @@ class RuleMessage {
int getRuleId() const { int getRuleId() const {
if (m_rule) { if (m_rule) {
return m_rule->m_ruleId; return m_rule->getId();
} }
return -1; return -1;
} }
@ -148,7 +148,7 @@ class RuleMessage {
std::string getVer() const { std::string getVer() const {
if (m_rule) { if (m_rule) {
return m_rule->getRevision(); return m_rule->getVersion();
} }
return ""; return "";
} }

View File

@ -30,10 +30,43 @@
#include "modsecurity/variable_value.h" #include "modsecurity/variable_value.h"
#include "modsecurity/rule.h" #include "modsecurity/rule.h"
#ifdef __cplusplus #ifdef __cplusplus
namespace modsecurity { namespace modsecurity {
namespace actions {
class Action;
class Severity;
class LogData;
class Msg;
class Rev;
class SetVar;
class Tag;
class XmlNS;
namespace transformations {
class Transformation;
}
}
using TransformationResult = std::pair<std::shared_ptr<std::string>,
std::shared_ptr<std::string>>;
using TransformationResults = std::list<TransformationResult>;
using Transformation = actions::transformations::Transformation;
using Transformations = std::vector<std::shared_ptr<Transformation> >;
using TransformationsPtr = std::vector<Transformation *>;
using Action = actions::Action;
using Actions = std::vector<actions::Action *>;
using Tags = std::vector<std::shared_ptr<actions::Tag> >;
using TagsPtr = std::vector<actions::Tag *>;
using SetVars = std::vector<std::shared_ptr<actions::SetVar> >;
using SetVarsPtr = std::vector<actions::SetVar *>;
using MatchActions = std::vector<std::shared_ptr<actions::Action > >;
using MatchActionsPtr = std::vector<actions::Action *>;
using XmlNSs = std::vector<std::shared_ptr<actions::XmlNS> >;
using XmlNSsPtr = std::vector<actions::XmlNS *>;
class RuleWithActions : public Rule { class RuleWithActions : public Rule {
public: public:
@ -41,12 +74,12 @@ class RuleWithActions : public Rule {
int ACCURACY_NOT_SET = 10; int ACCURACY_NOT_SET = 10;
int MATURITY_NOT_SET = 10; int MATURITY_NOT_SET = 10;
RuleWithActions( RuleWithActions(
Actions *a, Actions *a,
Transformations *t, Transformations *t,
std::unique_ptr<std::string> fileName, std::unique_ptr<std::string> fileName,
int lineNumber); int lineNumber);
~RuleWithActions(); ~RuleWithActions();
RuleWithActions(const RuleWithActions &r) RuleWithActions(const RuleWithActions &r)
@ -60,6 +93,7 @@ class RuleWithActions : public Rule {
m_actionsRuntimePos(r.m_actionsRuntimePos), m_actionsRuntimePos(r.m_actionsRuntimePos),
m_actionsSetVar(r.m_actionsSetVar), m_actionsSetVar(r.m_actionsSetVar),
m_actionsTag(r.m_actionsTag), m_actionsTag(r.m_actionsTag),
m_XmlNSs(r.m_XmlNSs),
m_defaultActionDisruptiveAction(r.m_defaultActionDisruptiveAction), m_defaultActionDisruptiveAction(r.m_defaultActionDisruptiveAction),
m_defaultActionLogData(r.m_defaultActionLogData), m_defaultActionLogData(r.m_defaultActionLogData),
m_defaultActionMsg(r.m_defaultActionMsg), m_defaultActionMsg(r.m_defaultActionMsg),
@ -95,29 +129,27 @@ class RuleWithActions : public Rule {
void executeActionsIndependentOfChainedRuleResult( void executeActionsIndependentOfChainedRuleResult(
Transaction *trasn, Transaction *trasn);
bool *containsDisruptive);
void executeActionsAfterFullMatch( void executeActionsAfterFullMatch(
Transaction *trasn, Transaction *trasn);
bool containsDisruptive);
void executeAction(Transaction *trans, void executeAction(Transaction *trans,
bool containsBlock, Action *a,
actions::Action *a,
bool context); bool context);
void executeTransformations( void executeTransformations(
Transaction *trasn, const std::string &value, TransformationResults &ret); Transaction *transaction,
const std::string &value,
TransformationResults &ret);
inline void executeTransformation( inline void executeTransformation(
actions::transformations::Transformation *a, actions::transformations::Transformation *a,
std::shared_ptr<std::string> *value, std::shared_ptr<std::string> *value,
Transaction *trans, Transaction *trans,
TransformationResults *ret, TransformationResults *ret,
std::string *path, std::string *path) const;
int *nth) const;
void addAction(actions::Action *a); void addAction(actions::Action *a);
@ -308,13 +340,46 @@ class RuleWithActions : public Rule {
return dst; return dst;
} }
inline int64_t getId() const { return m_ruleId; }
void setId(int id) {
m_ruleId = id;
}
void setChainedNext(std::unique_ptr<RuleWithActions> r) {
m_chainedRuleChild = std::move(r);
}
inline RuleWithActions *getChainedNext() const {
return m_chainedRuleChild.get();
}
void setChainedParent(RuleWithActions *r) {
m_chainedRuleParent = r;
}
inline RuleWithActions *getChainedParent() {
return m_chainedRuleParent;
}
XmlNSsPtr getXmlNSsPtr() const {
/**
* FIXME: this is not conteplating SecRuleUpdateActionBy* yet.
*
*/
XmlNSsPtr dst;
for (auto &a : m_XmlNSs) {
dst.push_back(a.get());
}
return dst;
}
private:
int64_t m_ruleId; int64_t m_ruleId;
std::shared_ptr<RuleWithActions> m_chainedRuleChild; std::shared_ptr<RuleWithActions> m_chainedRuleChild;
RuleWithActions *m_chainedRuleParent; RuleWithActions *m_chainedRuleParent;
private:
/* actions */ /* actions */
std::shared_ptr<actions::Action> m_disruptiveAction; std::shared_ptr<actions::Action> m_disruptiveAction;
std::shared_ptr<actions::LogData> m_logData; std::shared_ptr<actions::LogData> m_logData;
@ -322,6 +387,7 @@ class RuleWithActions : public Rule {
MatchActions m_actionsRuntimePos; MatchActions m_actionsRuntimePos;
SetVars m_actionsSetVar; SetVars m_actionsSetVar;
Tags m_actionsTag; Tags m_actionsTag;
XmlNSs m_XmlNSs;
/* actions || SecDefaultAction */ /* actions || SecDefaultAction */
std::shared_ptr<actions::Action> m_defaultActionDisruptiveAction; std::shared_ptr<actions::Action> m_defaultActionDisruptiveAction;

View File

@ -70,7 +70,7 @@ class RuleWithOperator : public RuleWithActions {
std::string getOperatorName() const; std::string getOperatorName() const;
virtual std::string getReference() override { virtual std::string getReference() override {
return std::to_string(m_ruleId); return std::to_string(getId());
} }
private: private:

View File

@ -51,9 +51,9 @@ class Rules {
size_t j = 0; size_t j = 0;
for (; j < from->size(); j++) { for (; j < from->size(); j++) {
RuleWithOperator *rule = dynamic_cast<RuleWithOperator *>(from->at(j).get()); RuleWithOperator *rule = dynamic_cast<RuleWithOperator *>(from->at(j).get());
if (rule && std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) { if (rule && std::binary_search(ids.begin(), ids.end(), rule->getId())) {
if (err != NULL) { if (err != NULL) {
*err << "Rule id: " << std::to_string(rule->m_ruleId) \ *err << "Rule id: " << std::to_string(rule->getId()) \
<< " is duplicated" << std::endl; << " is duplicated" << std::endl;
} }
return -1; return -1;
@ -69,9 +69,9 @@ class Rules {
bool insert(std::shared_ptr<Rule> rule, const std::vector<int64_t> *ids, std::ostringstream *err) { bool insert(std::shared_ptr<Rule> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
RuleWithOperator *r = dynamic_cast<RuleWithOperator *>(rule.get()); RuleWithOperator *r = dynamic_cast<RuleWithOperator *>(rule.get());
if (r && ids != nullptr && std::binary_search(ids->begin(), ids->end(), r->m_ruleId)) { if (r && ids != nullptr && std::binary_search(ids->begin(), ids->end(), r->getId())) {
if (err != nullptr) { if (err != nullptr) {
*err << "Rule id: " << std::to_string(r->m_ruleId) \ *err << "Rule id: " << std::to_string(r->getId()) \
<< " is duplicated" << std::endl; << " is duplicated" << std::endl;
} }
return false; return false;

View File

@ -49,7 +49,7 @@ bool RuleId::init(std::string *error) {
bool RuleId::evaluate(RuleWithActions *rule, Transaction *transaction) { bool RuleId::evaluate(RuleWithActions *rule, Transaction *transaction) {
rule->m_ruleId = m_ruleId; rule->setId(m_ruleId);
return true; return true;
} }

View File

@ -35,7 +35,7 @@ class EscapeSeqDecode : public Transformation {
std::string evaluate(const std::string &exp, std::string evaluate(const std::string &exp,
Transaction *transaction) override; Transaction *transaction) override;
int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len);
}; };
} // namespace transformations } // namespace transformations

View File

@ -36,7 +36,7 @@ class UrlEncode : public Transformation {
std::string evaluate(const std::string &exp, std::string evaluate(const std::string &exp,
Transaction *transaction) override; Transaction *transaction) override;
std::string url_enc(const char *input, static std::string url_enc(const char *input,
unsigned int input_len, int *changed); unsigned int input_len, int *changed);
}; };

View File

@ -88,77 +88,79 @@ int Driver::addSecRule(std::unique_ptr<RuleWithActions> r) {
m_parserError << " chain starter rules."; m_parserError << " chain starter rules.";
return false; return false;
} }
m_lastRule->m_chainedRuleChild = std::move(r);
m_lastRule->m_chainedRuleChild->m_chainedRuleParent = m_lastRule; m_lastRule->setChainedNext(std::move(r));
m_lastRule = m_lastRule->m_chainedRuleChild.get(); m_lastRule->getChainedNext()->setChainedParent(m_lastRule);
m_lastRule = m_lastRule->getChainedNext();
/* Lets set all meta-data to the first rule */ /* Lets set all meta-data to the first rule */
RuleWithActions *firstRule = m_lastRule; RuleWithActions *firstRule = m_lastRule;
if (!firstRule->hasChainAction()) { if (!firstRule->hasChainAction()) {
while (firstRule->m_chainedRuleParent != nullptr) { while (firstRule->getChainedParent() != nullptr) {
if (firstRule->hasMessageAction()) { if (firstRule->hasMessageAction()) {
firstRule->m_chainedRuleParent->setMessageAction( firstRule->getChainedParent()->setMessageAction(
firstRule->getMessageAction() firstRule->getMessageAction()
); );
firstRule->setMessageAction(nullptr); firstRule->setMessageAction(nullptr);
} }
if (firstRule->hasLogDataAction()) { if (firstRule->hasLogDataAction()) {
firstRule->m_chainedRuleParent->setLogDataAction( firstRule->getChainedParent()->setLogDataAction(
firstRule->getLogDataAction() firstRule->getLogDataAction()
); );
firstRule->setLogDataAction(nullptr); firstRule->setLogDataAction(nullptr);
} }
if (firstRule->hasSeverityAction()) { if (firstRule->hasSeverityAction()) {
firstRule->m_chainedRuleParent->setSeverity( firstRule->getChainedParent()->setSeverity(
firstRule->getSeverity() firstRule->getSeverity()
); );
} }
if (firstRule->hasRevisionAction()) { if (firstRule->hasRevisionAction()) {
firstRule->m_chainedRuleParent->setRevision( firstRule->getChainedParent()->setRevision(
firstRule->getRevision() firstRule->getRevision()
); );
} }
if (firstRule->hasVersionAction()) { if (firstRule->hasVersionAction()) {
firstRule->m_chainedRuleParent->setVersion( firstRule->getChainedParent()->setVersion(
firstRule->getVersion() firstRule->getVersion()
); );
} }
if (firstRule->hasAccuracyAction()) { if (firstRule->hasAccuracyAction()) {
firstRule->m_chainedRuleParent->setAccuracy( firstRule->getChainedParent()->setAccuracy(
firstRule->getAccuracy() firstRule->getAccuracy()
); );
} }
if (firstRule->hasMaturityAction()) { if (firstRule->hasMaturityAction()) {
firstRule->m_chainedRuleParent->setMaturity( firstRule->getChainedParent()->setMaturity(
firstRule->getMaturity() firstRule->getMaturity()
); );
} }
if (firstRule->hasTagAction()) { if (firstRule->hasTagAction()) {
firstRule->m_chainedRuleParent->setTags( firstRule->getChainedParent()->setTags(
firstRule->getTagsAction() firstRule->getTagsAction()
); );
firstRule->cleanTags(); firstRule->cleanTags();
} }
if (firstRule->hasDisruptiveAction()) { if (firstRule->hasDisruptiveAction()) {
firstRule->m_chainedRuleParent->setDisruptiveAction( firstRule->getChainedParent()->setDisruptiveAction(
firstRule->getDisruptiveAction() firstRule->getDisruptiveAction()
); );
firstRule->setDisruptiveAction(nullptr); firstRule->setDisruptiveAction(nullptr);
} }
firstRule->m_chainedRuleParent->setHasBlockAction( firstRule->getChainedParent()->setHasBlockAction(
firstRule->hasBlockAction() firstRule->hasBlockAction()
); );
firstRule->m_chainedRuleParent->setHasLogAction( firstRule->getChainedParent()->setHasLogAction(
firstRule->hasLogAction() firstRule->hasLogAction()
); );
firstRule->m_chainedRuleParent->setHasLogAction( firstRule->getChainedParent()->setHasLogAction(
firstRule->hasNoLogAction() firstRule->hasNoLogAction()
); );
firstRule = firstRule->m_chainedRuleParent; firstRule = firstRule->getChainedParent();
} }
} }
return true; return true;
} }
@ -167,7 +169,7 @@ int Driver::addSecRule(std::unique_ptr<RuleWithActions> r) {
* Checking if the rule has an ID and also checking if this ID is not used * Checking if the rule has an ID and also checking if this ID is not used
* by other rule * by other rule
*/ */
if (rule->m_ruleId == 0) { if (rule->getId() == 0) {
m_parserError << "Rules must have an ID. File: "; m_parserError << "Rules must have an ID. File: ";
m_parserError << rule->getFileName() << " at line: "; m_parserError << rule->getFileName() << " at line: ";
m_parserError << std::to_string(rule->getLineNumber()) << std::endl; m_parserError << std::to_string(rule->getLineNumber()) << std::endl;
@ -178,8 +180,8 @@ int Driver::addSecRule(std::unique_ptr<RuleWithActions> r) {
Rules *rules = m_rulesSetPhases[i]; Rules *rules = m_rulesSetPhases[i];
for (int j = 0; j < rules->size(); j++) { for (int j = 0; j < rules->size(); j++) {
RuleWithOperator *lr = dynamic_cast<RuleWithOperator *>(rules->at(j).get()); RuleWithOperator *lr = dynamic_cast<RuleWithOperator *>(rules->at(j).get());
if (lr && lr->m_ruleId == rule->m_ruleId) { if (lr && lr->getId() == rule->getId()) {
m_parserError << "Rule id: " << std::to_string(rule->m_ruleId) \ m_parserError << "Rule id: " << std::to_string(rule->getId()) \
<< " is duplicated" << std::endl; << " is duplicated" << std::endl;
return false; return false;
} }

View File

@ -26,15 +26,12 @@ bool RuleScript::evaluate(Transaction *trans) {
ms_dbg_a(trans, 4, " Executing script: " + m_name + "."); ms_dbg_a(trans, 4, " Executing script: " + m_name + ".");
bool containsDisruptive = false; executeActionsIndependentOfChainedRuleResult(trans);
executeActionsIndependentOfChainedRuleResult(trans,
&containsDisruptive);
bool ret = m_lua->run(trans); bool ret = m_lua->run(trans);
if (ret) { if (ret) {
executeActionsAfterFullMatch(trans, containsDisruptive); executeActionsAfterFullMatch(trans);
} }
return ret; return ret;

View File

@ -22,16 +22,12 @@ namespace modsecurity {
bool RuleUnconditional::evaluate(Transaction *trans) { bool RuleUnconditional::evaluate(Transaction *trans) {
RuleWithActions::evaluate(trans); RuleWithActions::evaluate(trans);
// FIXME: This needs to be romeved on the runtime exeption review. ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \
bool containsBlock = false;
ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \
+ ") Executing unconditional rule..."); + ") Executing unconditional rule...");
executeActionsIndependentOfChainedRuleResult(trans, executeActionsIndependentOfChainedRuleResult(trans);
&containsBlock);
executeActionsAfterFullMatch(trans, containsBlock); executeActionsAfterFullMatch(trans);
trans->logMatchLastRuleOnTheChain(this); trans->logMatchLastRuleOnTheChain(this);

View File

@ -18,47 +18,38 @@
#include <stdio.h> #include <stdio.h>
#include <algorithm> #include <algorithm>
#include <iostream>
#include <string>
#include <cstring> #include <cstring>
#include <iostream>
#include <list> #include <list>
#include <utility>
#include <memory> #include <memory>
#include <string>
#include <utility>
#include "modsecurity/rules_set.h"
#include "src/operators/operator.h"
#include "modsecurity/actions/action.h" #include "modsecurity/actions/action.h"
#include "modsecurity/modsecurity.h" #include "modsecurity/modsecurity.h"
#include "src/actions/transformations/none.h"
#include "src/actions/tag.h"
#include "src/utils/string.h"
#include "modsecurity/rule_message.h" #include "modsecurity/rule_message.h"
#include "modsecurity/rules_set.h"
#include "modsecurity/rule_with_actions.h" #include "modsecurity/rule_with_actions.h"
#include "src/actions/accuracy.h" #include "src/actions/accuracy.h"
#include "src/actions/maturity.h" #include "src/actions/block.h"
#include "src/actions/capture.h"
#include "src/actions/log_data.h"
#include "src/actions/msg.h" #include "src/actions/msg.h"
#include "src/actions/maturity.h"
#include "src/actions/multi_match.h"
#include "src/actions/rev.h"
#include "src/actions/log.h" #include "src/actions/log.h"
#include "src/actions/no_log.h" #include "src/actions/no_log.h"
#include "src/actions/log_data.h"
#include "src/actions/rev.h"
#include "src/actions/severity.h"
#include "src/actions/capture.h"
#include "src/actions/multi_match.h"
#include "src/actions/set_var.h" #include "src/actions/set_var.h"
#include "src/actions/block.h" #include "src/actions/severity.h"
#include "src/variables/variable.h" #include "src/actions/tag.h"
#include "src/actions/transformations/transformation.h"
#include "src/actions/xmlns.h"
#include "src/utils/string.h"
namespace modsecurity { namespace modsecurity {
using operators::Operator;
using actions::Action;
using variables::Variable;
using actions::transformations::None;
using actions::transformations::Transformation;
RuleWithActions::RuleWithActions( RuleWithActions::RuleWithActions(
Actions *actions, Actions *actions,
Transformations *transformations, Transformations *transformations,
@ -74,6 +65,7 @@ RuleWithActions::RuleWithActions(
m_actionsRuntimePos(), m_actionsRuntimePos(),
m_actionsSetVar(), m_actionsSetVar(),
m_actionsTag(), m_actionsTag(),
m_XmlNSs(),
m_defaultActionDisruptiveAction(nullptr), m_defaultActionDisruptiveAction(nullptr),
m_defaultActionLogData(nullptr), m_defaultActionLogData(nullptr),
m_defaultActionMsg(nullptr), m_defaultActionMsg(nullptr),
@ -215,8 +207,10 @@ void RuleWithActions::addAction(actions::Action *a) {
} else if (dynamic_cast<actions::Tag *>(a)) { } else if (dynamic_cast<actions::Tag *>(a)) {
m_actionsTag.push_back(std::unique_ptr<actions::Tag>(dynamic_cast<actions::Tag *>(a))); m_actionsTag.push_back(std::unique_ptr<actions::Tag>(dynamic_cast<actions::Tag *>(a)));
} else if (dynamic_cast<actions::Block *>(a)) { } else if (dynamic_cast<actions::Block *>(a)) {
m_actionsRuntimePos.push_back(std::unique_ptr<actions::Block>(dynamic_cast<actions::Block*>(a))); m_actionsRuntimePos.push_back(std::unique_ptr<actions::Block>(dynamic_cast<actions::Block *>(a)));
m_containsStaticBlockAction = true; m_containsStaticBlockAction = true;
} else if (dynamic_cast<actions::XmlNS *>(a)) {
m_XmlNSs.push_back(std::unique_ptr<actions::XmlNS>(dynamic_cast<actions::XmlNS *>(a)));
} else if (a->isDisruptive() == true) { } else if (a->isDisruptive() == true) {
m_disruptiveAction = std::unique_ptr<Action>(a); m_disruptiveAction = std::unique_ptr<Action>(a);
} else { } else {
@ -237,12 +231,6 @@ RuleWithActions::~RuleWithActions() { }
bool RuleWithActions::evaluate(Transaction *transaction) { bool RuleWithActions::evaluate(Transaction *transaction) {
/* Rule evaluate is pure virtual.
*
* Rule::evaluate(transaction);
*/
/* Matched vars needs to be clear at every new rule execution */ /* Matched vars needs to be clear at every new rule execution */
transaction->m_matched.clear(); transaction->m_matched.clear();
@ -250,8 +238,7 @@ bool RuleWithActions::evaluate(Transaction *transaction) {
} }
void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans, void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans) {
bool *containsBlock) {
for (actions::SetVar *a : getSetVarsActionsPtr()) { for (actions::SetVar *a : getSetVarsActionsPtr()) {
ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \ ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \
@ -268,7 +255,6 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *
actions::Action *a = dynamic_cast<actions::Action*>(b.second.get()); actions::Action *a = dynamic_cast<actions::Action*>(b.second.get());
if (a->isDisruptive() == true && *a->m_name.get() == "block") { if (a->isDisruptive() == true && *a->m_name.get() == "block") {
ms_dbg_a(trans, 9, "Rule contains a `block' action"); ms_dbg_a(trans, 9, "Rule contains a `block' action");
*containsBlock = true;
} else if (*a->m_name.get() == "setvar") { } else if (*a->m_name.get() == "setvar") {
ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \ ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \
"action: " + *a->m_name.get()); "action: " + *a->m_name.get());
@ -290,8 +276,7 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *
} }
void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans) {
bool containsBlock) {
bool disruptiveAlreadyExecuted = false; bool disruptiveAlreadyExecuted = false;
#if 0 #if 0
@ -300,7 +285,8 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans,
continue; continue;
} }
if (!a.get()->isDisruptive()) { if (!a.get()->isDisruptive()) {
executeAction(trans, containsBlock, a.get(), true); executeAction(trans, a.get(), true);
} }
} }
#endif #endif
@ -311,35 +297,40 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans,
a->evaluate(this, trans, *trans->messageGetLast()); a->evaluate(this, trans, *trans->messageGetLast());
} }
/**
*
* FIXME: SecRuleUpdateActionBy should be runtime
*
*/
for (auto &b : for (auto &b :
trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) { trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) {
if (m_ruleId != b.first) { if (m_ruleId != b.first) {
continue; continue;
} }
actions::Action *a = dynamic_cast<actions::Action*>(b.second.get()); actions::Action *a = dynamic_cast<actions::Action*>(b.second.get());
executeAction(trans, containsBlock, a, false); executeAction(trans, a, false);
disruptiveAlreadyExecuted = true; disruptiveAlreadyExecuted = true;
} }
for (auto &a : getMatchActionsPtr()) { for (auto &a : getMatchActionsPtr()) {
if (!a->isDisruptive() if (!a->isDisruptive()
&& !(disruptiveAlreadyExecuted && !(disruptiveAlreadyExecuted
&& dynamic_cast<actions::Block *>(a))) { && dynamic_cast<actions::Block *>(a))) {
executeAction(trans, containsBlock, a, false); executeAction(trans, a, false);
} }
} }
if (!disruptiveAlreadyExecuted && m_disruptiveAction != nullptr) { if (!disruptiveAlreadyExecuted && m_disruptiveAction != nullptr) {
executeAction(trans, containsBlock, executeAction(trans,
m_disruptiveAction.get(), false); m_disruptiveAction.get(), false);
} else if (!disruptiveAlreadyExecuted && hasBlockAction() } else if (!disruptiveAlreadyExecuted && hasBlockAction()
&& m_defaultActionDisruptiveAction != nullptr) { && m_defaultActionDisruptiveAction != nullptr) {
executeAction(trans, containsBlock, executeAction(trans,
m_defaultActionDisruptiveAction.get(), false); m_defaultActionDisruptiveAction.get(), false);
} }
} }
void RuleWithActions::executeAction(Transaction *trans, void RuleWithActions::executeAction(Transaction *trans,
bool containsBlock,
Action *a, bool defaultContext) { Action *a, bool defaultContext) {
if (a->isDisruptive() == false && *a->m_name.get() != "block") { if (a->isDisruptive() == false && *a->m_name.get() != "block") {
ms_dbg_a(trans, 9, "Running " \ ms_dbg_a(trans, 9, "Running " \
@ -348,15 +339,15 @@ void RuleWithActions::executeAction(Transaction *trans,
return; return;
} }
if (defaultContext && !containsBlock) { if (defaultContext && !hasBlockAction()) {
ms_dbg_a(trans, 4, "Ignoring action: " + *a->m_name.get() + \ ms_dbg_a(trans, 4, "Ignoring action: " + *a->m_name.get() + \
" (rule does not cotains block)"); " (rule does not cotains block)");
return; return;
} }
if (trans->getRuleEngineState() == RulesSet::EnabledRuleEngine) { if (trans->getRuleEngineState() == RulesSet::EnabledRuleEngine) {
ms_dbg_a(trans, 4, "Running (disruptive) action: " + *a->m_name.get() + \ ms_dbg_a(trans, 4, "Running (disruptive) action: " +
"."); *a->m_name.get() + ".");
a->evaluate(this, trans, *trans->messageGetLast()); a->evaluate(this, trans, *trans->messageGetLast());
return; return;
} }
@ -371,8 +362,7 @@ inline void RuleWithActions::executeTransformation(
std::shared_ptr<std::string> *value, std::shared_ptr<std::string> *value,
Transaction *trans, Transaction *trans,
TransformationResults *ret, TransformationResults *ret,
std::string *path, std::string *path) const {
int *nth) const {
std::string *oldValue = (*value).get(); std::string *oldValue = (*value).get();
std::string newValue = a->evaluate(*oldValue, trans); std::string newValue = a->evaluate(*oldValue, trans);
@ -381,7 +371,6 @@ inline void RuleWithActions::executeTransformation(
std::shared_ptr<std::string> u(new std::string(newValue)); std::shared_ptr<std::string> u(new std::string(newValue));
if (m_containsMultiMatchAction) { if (m_containsMultiMatchAction) {
ret->push_back(std::make_pair(u, a->m_name)); ret->push_back(std::make_pair(u, a->m_name));
(*nth)++;
} }
*value = u; *value = u;
} }
@ -392,16 +381,16 @@ inline void RuleWithActions::executeTransformation(
path->append("," + *a->m_name.get()); path->append("," + *a->m_name.get());
} }
ms_dbg_a(trans, 9, " T (" + \ ms_dbg_a(trans, 9, "Transformation " + \
std::to_string(*nth) + ") " + \
*a->m_name.get() + ": \"" + \ *a->m_name.get() + ": \"" + \
utils::string::limitTo(80, newValue) +"\""); utils::string::limitTo(80, newValue) + "\"");
} }
void RuleWithActions::executeTransformations( void RuleWithActions::executeTransformations(
Transaction *trans, const std::string &in, TransformationResults &ret) { Transaction *trans,
const std::string &in,
TransformationResults &ret) {
int none = 0; int none = 0;
int transformations = 0;
std::string path(""); std::string path("");
std::shared_ptr<std::string> value = std::shared_ptr<std::string> value =
std::shared_ptr<std::string>(new std::string(in)); std::shared_ptr<std::string>(new std::string(in));
@ -421,9 +410,7 @@ void RuleWithActions::executeTransformations(
for (Transformation *a : getTransformationPtr()) { for (Transformation *a : getTransformationPtr()) {
if (none == 0) { if (none == 0) {
Transformation *t = dynamic_cast<Transformation *>(a); executeTransformation(a, &value, trans, &ret, &path);
executeTransformation(t, &value, trans, &ret, &path,
&transformations);
} }
if (a->m_isNone) { if (a->m_isNone) {
none--; none--;
@ -450,9 +437,7 @@ void RuleWithActions::executeTransformations(
} }
Transformation *a = dynamic_cast<Transformation*>(b.second.get()); Transformation *a = dynamic_cast<Transformation*>(b.second.get());
if (none == 0) { if (none == 0) {
Transformation *t = dynamic_cast<Transformation *>(a); executeTransformation(a, &value, trans, &ret, &path);
executeTransformation(t, &value, trans, &ret, &path,
&transformations);
} }
if (a->m_isNone) { if (a->m_isNone) {
none--; none--;
@ -488,42 +473,6 @@ bool RuleWithActions::containsMsg(const std::string& name, Transaction *t) {
} }
std::vector<actions::Action *> RuleWithActions::getActionsByName(const std::string& name,
Transaction *trans) {
std::vector<actions::Action *> ret;
for (auto &z : getMatchActionsPtr()) {
if (*z->m_name.get() == name) {
ret.push_back(z);
}
}
for (auto &z : getTransformationPtr()) {
if (*z->m_name.get() == name) {
ret.push_back(z);
}
}
for (auto &b :
trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) {
if (m_ruleId != b.first) {
continue;
}
actions::Action *z = dynamic_cast<actions::Action*>(b.second.get());
if (*z->m_name.get() == name) {
ret.push_back(z);
}
}
for (auto &b :
trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) {
if (m_ruleId != b.first) {
continue;
}
actions::Action *z = dynamic_cast<actions::Action*>(b.second.get());
if (*z->m_name.get() == name) {
ret.push_back(z);
}
}
return ret;
}
std::string RuleWithActions::getLogData(Transaction *t) { return m_logData->data(t); } std::string RuleWithActions::getLogData(Transaction *t) { return m_logData->data(t); }
std::string RuleWithActions::getMessage(Transaction *t) { return m_msg->data(t); } std::string RuleWithActions::getMessage(Transaction *t) { return m_msg->data(t); }

View File

@ -150,7 +150,7 @@ void RuleWithOperator::getVariablesExceptions(Transaction *t,
} }
for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) { for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) {
if (m_ruleId != a.first) { if (getId() != a.first) {
continue; continue;
} }
Variable *b = a.second.get(); Variable *b = a.second.get();
@ -178,7 +178,7 @@ inline void RuleWithOperator::getFinalVars(variables::Variables *vars,
if (std::find_if(trans->m_ruleRemoveTargetById.begin(), if (std::find_if(trans->m_ruleRemoveTargetById.begin(),
trans->m_ruleRemoveTargetById.end(), trans->m_ruleRemoveTargetById.end(),
[&, variable, this](std::pair<int, std::string> &m) -> bool { [&, variable, this](std::pair<int, std::string> &m) -> bool {
return m.first == m_ruleId return m.first == getId()
&& m.second == *variable->m_fullName.get(); && m.second == *variable->m_fullName.get();
}) != trans->m_ruleRemoveTargetById.end()) { }) != trans->m_ruleRemoveTargetById.end()) {
continue; continue;
@ -216,18 +216,18 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
// FIXME: Make a class runTimeException to handle this cases. // FIXME: Make a class runTimeException to handle this cases.
for (auto &i : trans->m_ruleRemoveById) { for (auto &i : trans->m_ruleRemoveById) {
if (m_ruleId != i) { if (getId() != i) {
continue; continue;
} }
ms_dbg_a(trans, 9, "Rule id: " + std::to_string(m_ruleId) + ms_dbg_a(trans, 9, "Rule id: " + std::to_string(getId()) +
" was skipped due to a ruleRemoveById action..."); " was skipped due to a ruleRemoveById action...");
return true; return true;
} }
for (auto &i : trans->m_ruleRemoveByIdRange) { for (auto &i : trans->m_ruleRemoveByIdRange) {
if (!(i.first <= m_ruleId && i.second >= m_ruleId)) { if (!(i.first <= getId() && i.second >= getId())) {
continue; continue;
} }
ms_dbg_a(trans, 9, "Rule id: " + std::to_string(m_ruleId) + ms_dbg_a(trans, 9, "Rule id: " + std::to_string(getId()) +
" was skipped due to a ruleRemoveById action..."); " was skipped due to a ruleRemoveById action...");
return true; return true;
} }
@ -241,14 +241,15 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
} else { } else {
eparam = "\"" + eparam + "\""; eparam = "\"" + eparam + "\"";
} }
ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \ ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \
+ ") Executing operator \"" + getOperatorName() \ + ") Executing operator \"" + getOperatorName() \
+ "\" with param " \ + "\" with param " \
+ eparam \ + eparam \
+ " against " \ + " against " \
+ variables + "."); + variables + ".");
} else { } else {
ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \ ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()
) \
+ ") Executing operator \"" + getOperatorName() \ + ") Executing operator \"" + getOperatorName() \
+ " against " \ + " against " \
+ variables + "."); + variables + ".");
@ -271,7 +272,7 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
std::find_if(trans->m_ruleRemoveTargetById.begin(), std::find_if(trans->m_ruleRemoveTargetById.begin(),
trans->m_ruleRemoveTargetById.end(), trans->m_ruleRemoveTargetById.end(),
[&, v, this](std::pair<int, std::string> &m) -> bool { [&, v, this](std::pair<int, std::string> &m) -> bool {
return m.first == m_ruleId && m.second == v->getKeyWithCollection(); return m.first == getId() && m.second == v->getKeyWithCollection();
}) != trans->m_ruleRemoveTargetById.end() }) != trans->m_ruleRemoveTargetById.end()
) { ) {
delete v; delete v;
@ -311,8 +312,7 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
trans->messageGetLast()->m_reference.append(*valueTemp.second); trans->messageGetLast()->m_reference.append(*valueTemp.second);
updateMatchedVars(trans, key, valueAfterTrans); updateMatchedVars(trans, key, valueAfterTrans);
executeActionsIndependentOfChainedRuleResult(trans, executeActionsIndependentOfChainedRuleResult(trans);
&containsBlock);
globalRet = true; globalRet = true;
} }
@ -336,14 +336,14 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
} }
/* FIXME: this check should happens on the parser. */ /* FIXME: this check should happens on the parser. */
if (this->m_chainedRuleChild == nullptr) { if (getChainedNext() == nullptr) {
ms_dbg_a(trans, 4, "Rule is marked as chained but there " \ ms_dbg_a(trans, 4, "Rule is marked as chained but there " \
"isn't a subsequent rule."); "isn't a subsequent rule.");
goto end_clean; goto end_clean;
} }
ms_dbg_a(trans, 4, "Executing chained rule."); ms_dbg_a(trans, 4, "Executing chained rule.");
recursiveGlobalRet = m_chainedRuleChild->evaluate(trans); recursiveGlobalRet = getChainedNext()->evaluate(trans);
if (recursiveGlobalRet == true) { if (recursiveGlobalRet == true) {
goto end_exec; goto end_exec;
@ -353,7 +353,7 @@ end_clean:
return false; return false;
end_exec: end_exec:
executeActionsAfterFullMatch(trans, containsBlock); executeActionsAfterFullMatch(trans);
/* last rule in the chain. */ /* last rule in the chain. */
trans->logMatchLastRuleOnTheChain(this); trans->logMatchLastRuleOnTheChain(this);

View File

@ -198,7 +198,7 @@ int RulesSet::evaluate(int phase, Transaction *t) {
Rule *base = rule.get(); Rule *base = rule.get();
RuleWithActions *ruleWithActions = dynamic_cast<RuleWithActions *>(base); RuleWithActions *ruleWithActions = dynamic_cast<RuleWithActions *>(base);
// FIXME: Those should be treated inside the rule itself // FIXME: Those should be treated inside the rule itself
if (ruleWithActions && m_exceptions.contains(ruleWithActions->m_ruleId)) { if (ruleWithActions && m_exceptions.contains(ruleWithActions->getId())) {
ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \ ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \
+ "'. Removed by an SecRuleRemove directive."); + "'. Removed by an SecRuleRemove directive.");
continue; continue;

View File

@ -50,7 +50,7 @@ int RulesSetPhases::append(RulesSetPhases *from, std::ostringstream *err) {
if (!rule_ckc) { if (!rule_ckc) {
continue; continue;
} }
v.push_back(rule_ckc->m_ruleId); v.push_back(rule_ckc->getId());
} }
} }
std::sort (v.begin(), v.end()); std::sort (v.begin(), v.end());

View File

@ -42,11 +42,11 @@ class Rule_DictElement : public VariableDictElement { \
std::vector<const VariableValue *> *l) { std::vector<const VariableValue *> *l) {
RuleWithActions *r = rule; RuleWithActions *r = rule;
if (!r || r->m_ruleId == 0) { if (!r || r->getId() == 0) {
return; return;
} }
std::unique_ptr<VariableOrigin> origin(new VariableOrigin()); std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
std::string *a = new std::string(std::to_string(r->m_ruleId)); std::string *a = new std::string(std::to_string(r->getId()));
VariableValue *var = new VariableValue(&m_rule, &m_rule_id, VariableValue *var = new VariableValue(&m_rule, &m_rule_id,
a a
); );

View File

@ -89,9 +89,8 @@ void XML::evaluate(Transaction *t,
if (rule == NULL) { if (rule == NULL) {
ms_dbg_a(t, 2, "XML: Can't look for xmlns, internal error."); ms_dbg_a(t, 2, "XML: Can't look for xmlns, internal error.");
} else { } else {
std::vector<actions::Action *> acts = rule->getActionsByName("xmlns", t); std::vector<actions::XmlNS *> acts = rule->getXmlNSsPtr();
for (auto &x : acts) { for (auto &z : acts) {
actions::XmlNS *z = (actions::XmlNS *)x;
if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->m_scope.c_str(), if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->m_scope.c_str(),
(const xmlChar*)z->m_href.c_str()) != 0) { (const xmlChar*)z->m_href.c_str()) != 0) {
ms_dbg_a(t, 1, "Failed to register XML namespace href \"" + \ ms_dbg_a(t, 1, "Failed to register XML namespace href \"" + \

View File

@ -49,7 +49,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 403 "http_code": 403
}, },
@ -109,7 +109,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 302, "http_code": 302,
"redirect_url": "http://www.google.com" "redirect_url": "http://www.google.com"
@ -169,7 +169,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 306, "http_code": 306,
"redirect_url": "http://www.google.com" "redirect_url": "http://www.google.com"
@ -229,7 +229,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 500 "http_code": 500
}, },
@ -288,7 +288,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 500 "http_code": 500
}, },
@ -347,7 +347,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 500 "http_code": 500
}, },

View File

@ -40,7 +40,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 403 "http_code": 403
}, },
@ -97,7 +97,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 403 "http_code": 403
}, },
@ -155,7 +155,7 @@
}, },
"expected": { "expected": {
"audit_log": "", "audit_log": "",
"debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "debug_log": "\\[9\\] Transformation t:trim: \"test",
"error_log": "", "error_log": "",
"http_code": 403 "http_code": 403
}, },

View File

@ -48,7 +48,7 @@
}, },
"expected":{ "expected":{
"audit_log":"", "audit_log":"",
"debug_log":"T \\(0\\) t:lowercase: \"test2\"", "debug_log":"Transformation t:lowercase: \"test2\"",
"error_log":"" "error_log":""
}, },
"rules":[ "rules":[

View File

@ -31,7 +31,7 @@
] ]
}, },
"expected":{ "expected":{
"debug_log":"T \\(0\\) t:trim: \"no need.\"" "debug_log":"Transformation t:trim: \"no need.\""
}, },
"rules":[ "rules":[
"SecRuleEngine On", "SecRuleEngine On",

View File

@ -51,7 +51,7 @@
] ]
}, },
"expected":{ "expected":{
"debug_log":"T \\(0\\) t:trim: \"small_text_file" "debug_log":"Transformation t:trim: \"small_text_file"
}, },
"rules":[ "rules":[
"SecRuleEngine On", "SecRuleEngine On",

View File

@ -51,7 +51,7 @@
] ]
}, },
"expected":{ "expected":{
"debug_log":"T \\(0\\) t:trim: \"filedata" "debug_log":"Transformation t:trim: \"filedata"
}, },
"rules":[ "rules":[
"SecRuleEngine On", "SecRuleEngine On",