Merge pull request #3253 from eduar-hte/rule-message

Simplified handling of RuleMessage by removing usage of std::shared_ptr
This commit is contained in:
Ervin Hegedus 2024-10-15 18:13:31 +02:00 committed by GitHub
commit 99ce9779e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 432 additions and 525 deletions

View File

@ -171,13 +171,13 @@ endfunction()
# unit tests # unit tests
file(GLOB unitTestSources ${BASE_DIR}/test/unit/*.cc) file(GLOB unitTestSources ${BASE_DIR}/test/unit/*.cc)
add_executable(unit_tests ${unitTestSources}) add_executable(unit_tests ${unitTestSources} ${BASE_DIR}/test/common/custom_debug_log.cc)
setTestTargetProperties(unit_tests) setTestTargetProperties(unit_tests)
target_compile_options(unit_tests PRIVATE /wd4805) target_compile_options(unit_tests PRIVATE /wd4805)
# regression tests # regression tests
file(GLOB regressionTestsSources ${BASE_DIR}/test/regression/*.cc) file(GLOB regressionTestsSources ${BASE_DIR}/test/regression/*.cc)
add_executable(regression_tests ${regressionTestsSources}) add_executable(regression_tests ${regressionTestsSources} ${BASE_DIR}/test/common/custom_debug_log.cc)
setTestTargetProperties(regression_tests) setTestTargetProperties(regression_tests)
macro(add_regression_test_capability compile_definition flag) macro(add_regression_test_capability compile_definition flag)

View File

@ -160,13 +160,13 @@ class ReadingLogsViaRuleMessage {
std::cout << std::endl; std::cout << std::endl;
if (ruleMessage->m_isDisruptive) { if (ruleMessage->m_isDisruptive) {
std::cout << " * Disruptive action: "; std::cout << " * Disruptive action: ";
std::cout << modsecurity::RuleMessage::log(ruleMessage); std::cout << modsecurity::RuleMessage::log(*ruleMessage);
std::cout << std::endl; std::cout << std::endl;
std::cout << " ** %d is meant to be informed by the webserver."; std::cout << " ** %d is meant to be informed by the webserver.";
std::cout << std::endl; std::cout << std::endl;
} else { } else {
std::cout << " * Match, but no disruptive action: "; std::cout << " * Match, but no disruptive action: ";
std::cout << modsecurity::RuleMessage::log(ruleMessage); std::cout << modsecurity::RuleMessage::log(*ruleMessage);
std::cout << std::endl; std::cout << std::endl;
} }
} }

View File

@ -81,13 +81,13 @@ static void logCb(void *data, const void *ruleMessagev) {
std::cout << std::endl; std::cout << std::endl;
if (ruleMessage->m_isDisruptive) { if (ruleMessage->m_isDisruptive) {
std::cout << " * Disruptive action: "; std::cout << " * Disruptive action: ";
std::cout << modsecurity::RuleMessage::log(ruleMessage); std::cout << modsecurity::RuleMessage::log(*ruleMessage);
std::cout << std::endl; std::cout << std::endl;
std::cout << " ** %d is meant to be informed by the webserver."; std::cout << " ** %d is meant to be informed by the webserver.";
std::cout << std::endl; std::cout << std::endl;
} else { } else {
std::cout << " * Match, but no disruptive action: "; std::cout << " * Match, but no disruptive action: ";
std::cout << modsecurity::RuleMessage::log(ruleMessage); std::cout << modsecurity::RuleMessage::log(*ruleMessage);
std::cout << std::endl; std::cout << std::endl;
} }
} }

View File

@ -89,7 +89,7 @@ class Action {
virtual bool evaluate(RuleWithActions *rule, Transaction *transaction); virtual bool evaluate(RuleWithActions *rule, Transaction *transaction);
virtual bool evaluate(RuleWithActions *rule, Transaction *transaction, virtual bool evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
return evaluate(rule, transaction); return evaluate(rule, transaction);
} }
virtual bool init(std::string *error) { return true; } virtual bool init(std::string *error) { return true; }

View File

@ -292,7 +292,7 @@ class ModSecurity {
*/ */
void setServerLogCb(ModSecLogCb cb, int properties); void setServerLogCb(ModSecLogCb cb, int properties);
void serverLog(void *data, std::shared_ptr<RuleMessage> rm); void serverLog(void *data, const RuleMessage &rm);
const std::string& getConnectorInformation() const; const std::string& getConnectorInformation() const;

View File

@ -78,8 +78,7 @@ class Rule {
virtual bool evaluate(Transaction *transaction) = 0; virtual bool evaluate(Transaction *transaction) = 0;
virtual bool evaluate(Transaction *transaction, virtual bool evaluate(Transaction *transaction, RuleMessage &ruleMessage) = 0;
std::shared_ptr<RuleMessage> rm) = 0;
const std::string& getFileName() const { const std::string& getFileName() const {
return m_fileName; return m_fileName;

View File

@ -42,8 +42,7 @@ class RuleMarker : public Rule {
RuleMarker &operator=(const RuleMarker &r) = delete; RuleMarker &operator=(const RuleMarker &r) = delete;
virtual bool evaluate(Transaction *transaction, virtual bool evaluate(Transaction *transaction, RuleMessage &ruleMessage) override {
std::shared_ptr<RuleMessage> rm) override {
return evaluate(transaction); return evaluate(transaction);
} }

View File

@ -13,14 +13,6 @@
* *
*/ */
#ifdef __cplusplus
#include <stack>
#include <vector>
#include <string>
#include <list>
#include <cstring>
#endif
#ifndef HEADERS_MODSECURITY_RULE_MESSAGE_H_ #ifndef HEADERS_MODSECURITY_RULE_MESSAGE_H_
#define HEADERS_MODSECURITY_RULE_MESSAGE_H_ #define HEADERS_MODSECURITY_RULE_MESSAGE_H_
@ -31,8 +23,10 @@
#ifdef __cplusplus #ifdef __cplusplus
namespace modsecurity { #include <string>
#include <list>
namespace modsecurity {
class RuleMessage { class RuleMessage {
@ -45,43 +39,51 @@ class RuleMessage {
RuleMessage(const RuleWithActions &rule, const Transaction &trans) : RuleMessage(const RuleWithActions &rule, const Transaction &trans) :
m_rule(rule), m_rule(rule),
m_transaction(trans) m_transaction(trans)
{ } {
reset(true);
}
RuleMessage(const RuleMessage &ruleMessage) = default; RuleMessage(const RuleMessage &ruleMessage) = default;
RuleMessage &operator=(const RuleMessage &ruleMessage) = delete; RuleMessage &operator=(const RuleMessage &ruleMessage) = delete;
void clean() { void reset(const bool resetSaveMessage)
m_data = ""; {
m_match = ""; m_data.clear();
m_isDisruptive = false; m_isDisruptive = false;
m_reference = ""; m_match.clear();
m_message.clear();
m_noAuditLog = false;
m_reference.clear();
if (resetSaveMessage == true)
m_saveMessage = true;
m_severity = 0; m_severity = 0;
m_tags.clear();
} }
std::string log() { std::string log() const {
return log(this, 0); return log(*this, 0);
} }
std::string log(int props) { std::string log(int props) const {
return log(this, props); return log(*this, props);
} }
std::string log(int props, int responseCode) { std::string log(int props, int responseCode) const {
return log(this, props, responseCode); return log(*this, props, responseCode);
} }
std::string errorLog() { std::string errorLog() const {
return log(this, return log(*this,
ClientLogMessageInfo | ErrorLogTailLogMessageInfo); ClientLogMessageInfo | ErrorLogTailLogMessageInfo);
} }
static std::string log(const RuleMessage *rm, int props, int code); static std::string log(const RuleMessage &rm, int props, int code);
static std::string log(const RuleMessage *rm, int props) { static std::string log(const RuleMessage &rm, int props) {
return log(rm, props, -1); return log(rm, props, -1);
} }
static std::string log(const RuleMessage *rm) { static std::string log(const RuleMessage &rm) {
return log(rm, 0); return log(rm, 0);
} }
static std::string _details(const RuleMessage *rm); static std::string _details(const RuleMessage &rm);
static std::string _errorLogTail(const RuleMessage *rm); static std::string _errorLogTail(const RuleMessage &rm);
int getPhase() const { return m_rule.getPhase() - 1; } int getPhase() const { return m_rule.getPhase() - 1; }

View File

@ -36,7 +36,7 @@ class RuleUnconditional : public RuleWithActions {
public: public:
using RuleWithActions::RuleWithActions; using RuleWithActions::RuleWithActions;
virtual bool evaluate(Transaction *transaction, std::shared_ptr<RuleMessage> ruleMessage) override; virtual bool evaluate(Transaction *transaction, RuleMessage &ruleMessage) override;
}; };

View File

@ -51,21 +51,21 @@ class RuleWithActions : public Rule {
virtual bool evaluate(Transaction *transaction) override; virtual bool evaluate(Transaction *transaction) override;
virtual bool evaluate(Transaction *transaction, std::shared_ptr<RuleMessage> ruleMessage) override; virtual bool evaluate(Transaction *transaction, RuleMessage &ruleMessage) override;
void executeActionsIndependentOfChainedRuleResult( void executeActionsIndependentOfChainedRuleResult(
Transaction *trasn, Transaction *trasn,
bool *containsDisruptive, bool *containsDisruptive,
std::shared_ptr<RuleMessage> ruleMessage); RuleMessage &ruleMessage);
void executeActionsAfterFullMatch( void executeActionsAfterFullMatch(
Transaction *trasn, Transaction *trasn,
bool containsDisruptive, bool containsDisruptive,
std::shared_ptr<RuleMessage> ruleMessage); RuleMessage &ruleMessage);
void executeAction(Transaction *trans, void executeAction(Transaction *trans,
bool containsBlock, bool containsBlock,
std::shared_ptr<RuleMessage> ruleMessage, RuleMessage &ruleMessage,
actions::Action *a, actions::Action *a,
bool context); bool context);
@ -74,7 +74,7 @@ class RuleWithActions : public Rule {
const Transaction *trasn, const std::string &value, TransformationResults &ret); const Transaction *trasn, const std::string &value, TransformationResults &ret);
void performLogging(Transaction *trans, void performLogging(Transaction *trans,
std::shared_ptr<RuleMessage> ruleMessage, RuleMessage &ruleMessage,
bool lastLog = true, bool lastLog = true,
bool chainedParentNull = false) const; bool chainedParentNull = false) const;

View File

@ -47,8 +47,7 @@ class RuleWithOperator : public RuleWithActions {
~RuleWithOperator() override; ~RuleWithOperator() override;
bool evaluate(Transaction *transaction, bool evaluate(Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
void getVariablesExceptions(Transaction &t, void getVariablesExceptions(Transaction &t,
variables::Variables *exclusion, variables::Variables *addition); variables::Variables *exclusion, variables::Variables *addition);
@ -56,7 +55,7 @@ class RuleWithOperator : public RuleWithActions {
variables::Variables *eclusion, Transaction *trans); variables::Variables *eclusion, Transaction *trans);
bool executeOperatorAt(Transaction *trasn, const std::string &key, bool executeOperatorAt(Transaction *trasn, const std::string &key,
const std::string &value, std::shared_ptr<RuleMessage> rm); const std::string &value, RuleMessage &ruleMessage);
static void updateMatchedVars(Transaction *trasn, const std::string &key, static void updateMatchedVars(Transaction *trasn, const std::string &key,
const std::string &value); const std::string &value);

View File

@ -407,7 +407,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
#ifndef NO_LOGS #ifndef NO_LOGS
void debug(int, const std::string &) const; // cppcheck-suppress functionStatic void debug(int, const std::string &) const; // cppcheck-suppress functionStatic
#endif #endif
void serverLog(std::shared_ptr<RuleMessage> rm); void serverLog(const RuleMessage &rm);
int getRuleEngineState() const; int getRuleEngineState() const;

View File

@ -27,11 +27,10 @@ namespace modsecurity {
namespace actions { namespace actions {
bool AuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, bool AuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) { ruleMessage.m_noAuditLog = false;
rm->m_noAuditLog = false;
ms_dbg_a(transaction, 9, "Saving transaction to logs"); ms_dbg_a(transaction, 9, "Saving transaction to logs");
rm->m_saveMessage = true; ruleMessage.m_saveMessage = true;
return true; return true;
} }

View File

@ -35,8 +35,7 @@ class AuditLog : public Action {
explicit AuditLog(const std::string &action) explicit AuditLog(const std::string &action)
: Action(action) { } : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
}; };

View File

@ -29,15 +29,14 @@ namespace modsecurity {
namespace actions { namespace actions {
bool Block::evaluate(RuleWithActions *rule, Transaction *transaction, bool Block::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) {
ms_dbg_a(transaction, 8, "Marking request as disruptive."); ms_dbg_a(transaction, 8, "Marking request as disruptive.");
for (auto &a : transaction->m_rules->m_defaultActions[rule->getPhase()]) { for (auto &a : transaction->m_rules->m_defaultActions[rule->getPhase()]) {
if (a->isDisruptive() == false) { if (a->isDisruptive() == false) {
continue; continue;
} }
a->evaluate(rule, transaction, rm); a->evaluate(rule, transaction, ruleMessage);
} }
return true; return true;

View File

@ -35,8 +35,7 @@ class Block : public Action {
public: public:
explicit Block(const std::string &action) : Action(action) { } explicit Block(const std::string &action) : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
}; };

View File

@ -39,7 +39,7 @@ bool Status::init(std::string *error) {
bool Status::evaluate(RuleWithActions *rule, Transaction *transaction, bool Status::evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> rm) { RuleMessage &ruleMessage) {
transaction->m_it.status = m_status; transaction->m_it.status = m_status;
return true; return true;
} }

View File

@ -37,8 +37,7 @@ class Status : public Action {
: Action(action), m_status(0) { } : Action(action), m_status(0) { }
bool init(std::string *error) override; bool init(std::string *error) override;
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
int m_status; int m_status;
}; };

View File

@ -29,7 +29,7 @@ namespace disruptive {
bool Deny::evaluate(RuleWithActions *rule, Transaction *transaction, bool Deny::evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> rm) { RuleMessage &ruleMessage) {
ms_dbg_a(transaction, 8, "Running action deny"); ms_dbg_a(transaction, 8, "Running action deny");
if (transaction->m_it.status == 200) { if (transaction->m_it.status == 200) {
@ -38,9 +38,9 @@ bool Deny::evaluate(RuleWithActions *rule, Transaction *transaction,
transaction->m_it.disruptive = true; transaction->m_it.disruptive = true;
intervention::freeLog(&transaction->m_it); intervention::freeLog(&transaction->m_it);
rm->m_isDisruptive = true; ruleMessage.m_isDisruptive = true;
transaction->m_it.log = strdup( transaction->m_it.log = strdup(
rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); ruleMessage.log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str());
return true; return true;
} }

View File

@ -33,8 +33,7 @@ class Deny : public Action {
public: public:
explicit Deny(const std::string &action) : Action(action) { } explicit Deny(const std::string &action) : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
bool isDisruptive() override { return true; } bool isDisruptive() override { return true; }
}; };

View File

@ -33,7 +33,7 @@ namespace disruptive {
bool Drop::evaluate(RuleWithActions *rule, Transaction *transaction, bool Drop::evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> rm) { RuleMessage &ruleMessage) {
ms_dbg_a(transaction, 8, "Running action drop " \ ms_dbg_a(transaction, 8, "Running action drop " \
"[executing deny instead of drop.]"); "[executing deny instead of drop.]");
@ -43,9 +43,9 @@ bool Drop::evaluate(RuleWithActions *rule, Transaction *transaction,
transaction->m_it.disruptive = true; transaction->m_it.disruptive = true;
intervention::freeLog(&transaction->m_it); intervention::freeLog(&transaction->m_it);
rm->m_isDisruptive = true; ruleMessage.m_isDisruptive = true;
transaction->m_it.log = strdup( transaction->m_it.log = strdup(
rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); ruleMessage.log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str());
return true; return true;
} }

View File

@ -32,8 +32,7 @@ class Drop : public Action {
public: public:
explicit Drop(const std::string &action) : Action(action) { } explicit Drop(const std::string &action) : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
bool isDisruptive() override { return true; } bool isDisruptive() override { return true; }
}; };

View File

@ -30,7 +30,7 @@ namespace disruptive {
bool Pass::evaluate(RuleWithActions *rule, Transaction *transaction, bool Pass::evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> rm) { RuleMessage &ruleMessage) {
intervention::free(&transaction->m_it); intervention::free(&transaction->m_it);
intervention::reset(&transaction->m_it); intervention::reset(&transaction->m_it);

View File

@ -31,8 +31,7 @@ class Pass : public Action {
public: public:
explicit Pass(const std::string &action) : Action(action) { } explicit Pass(const std::string &action) : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
bool isDisruptive() override { return true; } bool isDisruptive() override { return true; }
}; };

View File

@ -35,7 +35,7 @@ bool Redirect::init(std::string *error) {
bool Redirect::evaluate(RuleWithActions *rule, Transaction *transaction, bool Redirect::evaluate(RuleWithActions *rule, Transaction *transaction,
std::shared_ptr<RuleMessage> rm) { RuleMessage &ruleMessage) {
std::string m_urlExpanded(m_string->evaluate(transaction)); std::string m_urlExpanded(m_string->evaluate(transaction));
/* if it was changed before, lets keep it. */ /* if it was changed before, lets keep it. */
if (transaction->m_it.status == 200 if (transaction->m_it.status == 200
@ -47,9 +47,9 @@ bool Redirect::evaluate(RuleWithActions *rule, Transaction *transaction,
transaction->m_it.url = strdup(m_urlExpanded.c_str()); transaction->m_it.url = strdup(m_urlExpanded.c_str());
transaction->m_it.disruptive = true; transaction->m_it.disruptive = true;
intervention::freeLog(&transaction->m_it); intervention::freeLog(&transaction->m_it);
rm->m_isDisruptive = true; ruleMessage.m_isDisruptive = true;
transaction->m_it.log = strdup( transaction->m_it.log = strdup(
rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); ruleMessage.log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str());
return true; return true;
} }

View File

@ -46,8 +46,7 @@ class Redirect : public Action {
m_status(0), m_status(0),
m_string(std::move(z)) { } m_string(std::move(z)) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
bool init(std::string *error) override; bool init(std::string *error) override;
bool isDisruptive() override { return true; } bool isDisruptive() override { return true; }

View File

@ -28,10 +28,9 @@ namespace modsecurity {
namespace actions { namespace actions {
bool Log::evaluate(RuleWithActions *rule, Transaction *transaction, bool Log::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) {
ms_dbg_a(transaction, 9, "Saving transaction to logs"); ms_dbg_a(transaction, 9, "Saving transaction to logs");
rm->m_saveMessage = true; ruleMessage.m_saveMessage = true;
return true; return true;
} }

View File

@ -33,8 +33,7 @@ class Log : public Action {
explicit Log(const std::string &action) explicit Log(const std::string &action)
: Action(action) { } : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
}; };
} // namespace actions } // namespace actions

View File

@ -29,9 +29,8 @@ namespace modsecurity {
namespace actions { namespace actions {
bool LogData::evaluate(RuleWithActions *rule, Transaction *transaction, bool LogData::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) { ruleMessage.m_data = data(transaction);
rm->m_data = data(transaction);
return true; return true;
} }

View File

@ -39,8 +39,7 @@ class LogData : public Action {
: Action("logdata"), : Action("logdata"),
m_string(std::move(z)) { } m_string(std::move(z)) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
std::string data(Transaction *Transaction); std::string data(Transaction *Transaction);

View File

@ -46,10 +46,9 @@ namespace modsecurity {
namespace actions { namespace actions {
bool Msg::evaluate(RuleWithActions *rule, Transaction *transaction, bool Msg::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) { const auto msg = data(transaction);
std::string msg = data(transaction); ruleMessage.m_message = msg;
rm->m_message = msg;
ms_dbg_a(transaction, 9, "Saving msg: " + msg); ms_dbg_a(transaction, 9, "Saving msg: " + msg);
return true; return true;

View File

@ -40,8 +40,7 @@ class Msg : public Action {
: Action("msg"), : Action("msg"),
m_string(std::move(z)) { } m_string(std::move(z)) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
std::string data(Transaction *Transaction); std::string data(Transaction *Transaction);
std::unique_ptr<RunTimeString> m_string; std::unique_ptr<RunTimeString> m_string;

View File

@ -26,10 +26,9 @@ namespace modsecurity {
namespace actions { namespace actions {
bool NoAuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, bool NoAuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) { ruleMessage.m_noAuditLog = true;
rm->m_noAuditLog = true; ruleMessage.m_saveMessage = false;
rm->m_saveMessage = false;
return true; return true;
} }

View File

@ -35,8 +35,7 @@ class NoAuditLog : public Action {
explicit NoAuditLog(const std::string &action) explicit NoAuditLog(const std::string &action)
: Action(action) { } : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
}; };
} // namespace actions } // namespace actions

View File

@ -29,9 +29,8 @@ namespace modsecurity {
namespace actions { namespace actions {
bool NoLog::evaluate(RuleWithActions *rule, Transaction *transaction, bool NoLog::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) { ruleMessage.m_saveMessage = false;
rm->m_saveMessage = false;
return true; return true;
} }

View File

@ -33,8 +33,7 @@ class NoLog : public Action {
explicit NoLog(const std::string &action) explicit NoLog(const std::string &action)
: Action(action) { } : Action(action) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
}; };
} // namespace actions } // namespace actions

View File

@ -71,13 +71,12 @@ bool Severity::init(std::string *error) {
} }
bool Severity::evaluate(RuleWithActions *rule, Transaction *transaction, bool Severity::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) {
ms_dbg_a(transaction, 9, "This rule severity is: " + \ ms_dbg_a(transaction, 9, "This rule severity is: " + \
std::to_string(this->m_severity) + " current transaction is: " + \ std::to_string(this->m_severity) + " current transaction is: " + \
std::to_string(transaction->m_highestSeverityAction)); std::to_string(transaction->m_highestSeverityAction));
rm->m_severity = m_severity; ruleMessage.m_severity = m_severity;
if (transaction->m_highestSeverityAction > this->m_severity) { if (transaction->m_highestSeverityAction > this->m_severity) {
transaction->m_highestSeverityAction = this->m_severity; transaction->m_highestSeverityAction = this->m_severity;

View File

@ -35,8 +35,7 @@ class Severity : public Action {
: Action(action), : Action(action),
m_severity(0) { } m_severity(0) { }
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
bool init(std::string *error) override; bool init(std::string *error) override;
int m_severity; int m_severity;

View File

@ -57,12 +57,11 @@ std::string Tag::getName(Transaction *transaction) {
} }
bool Tag::evaluate(RuleWithActions *rule, Transaction *transaction, bool Tag::evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) {
std::shared_ptr<RuleMessage> rm) {
std::string tag = getName(transaction); std::string tag = getName(transaction);
ms_dbg_a(transaction, 9, "Rule tag: " + tag); ms_dbg_a(transaction, 9, "Rule tag: " + tag);
rm->m_tags.push_back(tag); ruleMessage.m_tags.push_back(tag);
return true; return true;
} }

View File

@ -38,8 +38,7 @@ class Tag : public Action {
std::string getName(Transaction *transaction); std::string getName(Transaction *transaction);
bool evaluate(RuleWithActions *rule, Transaction *transaction, bool evaluate(RuleWithActions *rule, Transaction *transaction, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> rm) override;
protected: protected:
std::unique_ptr<RunTimeString> m_string; std::unique_ptr<RunTimeString> m_string;

View File

@ -190,26 +190,22 @@ const std::string& ModSecurity::getConnectorInformation() const {
return m_connector; return m_connector;
} }
void ModSecurity::serverLog(void *data, std::shared_ptr<RuleMessage> rm) { void ModSecurity::serverLog(void *data, const RuleMessage &rm) {
if (m_logCb == NULL) { if (m_logCb == NULL) {
std::cerr << "Server log callback is not set -- " << rm->errorLog(); std::cerr << "Server log callback is not set -- " << rm.errorLog();
std::cerr << std::endl; std::cerr << std::endl;
return; return;
} }
if (rm == NULL) {
return;
}
if (m_logProperties & TextLogProperty) { if (m_logProperties & TextLogProperty) {
auto d = rm->log(); auto d = rm.log();
const void *a = static_cast<const void *>(d.c_str()); auto a = static_cast<const void *>(d.c_str());
m_logCb(data, a); m_logCb(data, a);
return; return;
} }
if (m_logProperties & RuleMessageLogProperty) { if (m_logProperties & RuleMessageLogProperty) {
const void *a = static_cast<const void *>(rm.get()); auto a = static_cast<const void *>(&rm);
m_logCb(data, a); m_logCb(data, a);
return; return;
} }

View File

@ -25,7 +25,7 @@ namespace operators {
bool BeginsWith::evaluate(Transaction *transaction, RuleWithActions *rule, bool BeginsWith::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
std::string p(m_string->evaluate(transaction)); std::string p(m_string->evaluate(transaction));
if (str.size() < p.size()) { if (str.size() < p.size()) {

View File

@ -33,7 +33,7 @@ class BeginsWith : public Operator {
: Operator("BeginsWith", std::move(param)) { } : Operator("BeginsWith", std::move(param)) { }
bool evaluate(Transaction *transaction, RuleWithActions *rule, const std::string &str, bool evaluate(Transaction *transaction, RuleWithActions *rule, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
}; };
} // namespace operators } // namespace operators

View File

@ -22,7 +22,7 @@ namespace modsecurity {
namespace operators { namespace operators {
bool Contains::evaluate(Transaction *transaction, RuleWithActions *rule, bool Contains::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &input, RuleMessage &ruleMessage) {
std::string p(m_string->evaluate(transaction)); std::string p(m_string->evaluate(transaction));
size_t offset = input.find(p); size_t offset = input.find(p);

View File

@ -36,7 +36,7 @@ class Contains : public Operator {
: Operator("Contains", std::move(param)) { } : Operator("Contains", std::move(param)) { }
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
}; };
} // namespace operators } // namespace operators

View File

@ -37,7 +37,7 @@ bool ContainsWord::acceptableChar(const std::string& a, size_t pos) {
} }
bool ContainsWord::evaluate(Transaction *transaction, RuleWithActions *rule, bool ContainsWord::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
std::string paramTarget(m_string->evaluate(transaction)); std::string paramTarget(m_string->evaluate(transaction));
if (paramTarget.empty()) { if (paramTarget.empty()) {

View File

@ -34,7 +34,7 @@ class ContainsWord : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
private: private:
static bool acceptableChar(const std::string& a, size_t pos); static bool acceptableChar(const std::string& a, size_t pos);

View File

@ -26,7 +26,7 @@ namespace operators {
bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule, bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
char fingerprint[8]; char fingerprint[8];
int issqli; int issqli;

View File

@ -34,7 +34,7 @@ class DetectSQLi : public Operator {
bool evaluate(Transaction *t, RuleWithActions *rule, bool evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
}; };
} // namespace operators } // namespace operators

View File

@ -26,7 +26,7 @@ namespace operators {
bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule, bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
int is_xss; int is_xss;
is_xss = libinjection_xss(input.c_str(), input.length()); is_xss = libinjection_xss(input.c_str(), input.length());

View File

@ -33,7 +33,7 @@ class DetectXSS : public Operator {
bool evaluate(Transaction *t, RuleWithActions *rule, bool evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
}; };
} // namespace operators } // namespace operators

View File

@ -24,7 +24,7 @@ namespace operators {
bool EndsWith::evaluate(Transaction *transaction, RuleWithActions *rule, bool EndsWith::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
bool ret = false; bool ret = false;
std::string p(m_string->evaluate(transaction)); std::string p(m_string->evaluate(transaction));

View File

@ -35,7 +35,7 @@ class EndsWith : public Operator {
} }
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
}; };

View File

@ -71,8 +71,8 @@ namespace operators {
bool Operator::evaluateInternal(Transaction *transaction, bool Operator::evaluateInternal(Transaction *transaction,
RuleWithActions *rule, const std::string& a, std::shared_ptr<RuleMessage> rm) { RuleWithActions *rule, const std::string& a, RuleMessage &ruleMessage) {
bool res = evaluate(transaction, rule, a, rm); bool res = evaluate(transaction, rule, a, ruleMessage);
if (m_negation) { if (m_negation) {
return !res; return !res;

View File

@ -115,7 +115,7 @@ class Operator {
bool evaluateInternal(Transaction *t, RuleWithActions *rule, bool evaluateInternal(Transaction *t, RuleWithActions *rule,
const std::string& a); const std::string& a);
bool evaluateInternal(Transaction *t, RuleWithActions *rule, bool evaluateInternal(Transaction *t, RuleWithActions *rule,
const std::string& a, std::shared_ptr<RuleMessage> ruleMessage); const std::string& a, RuleMessage &ruleMessage);
virtual bool evaluate(Transaction *transaction, const std::string &str); virtual bool evaluate(Transaction *transaction, const std::string &str);
@ -124,16 +124,14 @@ class Operator {
return evaluate(transaction, str); return evaluate(transaction, str);
} }
virtual bool evaluate(Transaction *transaction, RuleWithActions *rule, virtual bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
return evaluate(transaction, str); return evaluate(transaction, str);
} }
static void logOffset(std::shared_ptr<RuleMessage> ruleMessage, int offset, int len) { static void logOffset(RuleMessage &ruleMessage, int offset, int len) {
if (ruleMessage) { ruleMessage.m_reference.append("o"
ruleMessage->m_reference.append("o" + std::to_string(offset) + ","
+ std::to_string(offset) + "," + std::to_string(len));
+ std::to_string(len));
}
} }
std::string m_match_message; std::string m_match_message;

View File

@ -140,7 +140,7 @@ void Pm::postOrderTraversal(acmp_btree_node_t *node) {
bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &input, RuleMessage &ruleMessage) {
int rc; int rc;
ACMPT pt; ACMPT pt;
pt.parser = m_p; pt.parser = m_p;

View File

@ -43,7 +43,7 @@ class Pm : public Operator {
~Pm(); ~Pm();
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool init(const std::string &file, std::string *error) override; bool init(const std::string &file, std::string *error) override;

View File

@ -207,7 +207,7 @@ void Rbl::furtherInfo(struct sockaddr_in *sin, const std::string &ipStr,
bool Rbl::evaluate(Transaction *t, RuleWithActions *rule, bool Rbl::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& ipStr, const std::string& ipStr,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
struct addrinfo *info = NULL; struct addrinfo *info = NULL;
std::string host = Rbl::mapIpToAddress(ipStr, t); std::string host = Rbl::mapIpToAddress(ipStr, t);
int rc = 0; int rc = 0;

View File

@ -83,7 +83,7 @@ class Rbl : public Operator {
} }
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
std::string mapIpToAddress(const std::string &ipStr, Transaction *trans) const; std::string mapIpToAddress(const std::string &ipStr, Transaction *trans) const;

View File

@ -37,7 +37,7 @@ bool Rx::init(const std::string &arg, std::string *error) {
bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
Regex *re; Regex *re;
if (m_param.empty() && !m_string->m_containsMacro) { if (m_param.empty() && !m_string->m_containsMacro) {

View File

@ -51,7 +51,7 @@ class Rx : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool init(const std::string &arg, std::string *error) override; bool init(const std::string &arg, std::string *error) override;

View File

@ -37,7 +37,7 @@ bool RxGlobal::init(const std::string &arg, std::string *error) {
bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule, bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
Regex *re; Regex *re;
if (m_param.empty() && !m_string->m_containsMacro) { if (m_param.empty() && !m_string->m_containsMacro) {

View File

@ -51,7 +51,7 @@ class RxGlobal : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool init(const std::string &arg, std::string *error) override; bool init(const std::string &arg, std::string *error) override;

View File

@ -111,7 +111,7 @@ bool ValidateByteRange::init(const std::string &file,
bool ValidateByteRange::evaluate(Transaction *transaction, RuleWithActions *rule, bool ValidateByteRange::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &input, RuleMessage &ruleMessage) {
bool ret = true; bool ret = true;
size_t count = 0; size_t count = 0;

View File

@ -39,7 +39,7 @@ class ValidateByteRange : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, const std::string &input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool getRange(const std::string &rangeRepresentation, std::string *error); bool getRange(const std::string &rangeRepresentation, std::string *error);
bool init(const std::string& file, std::string *error) override; bool init(const std::string& file, std::string *error) override;
private: private:

View File

@ -69,7 +69,7 @@ int ValidateUrlEncoding::validate_url_encoding(const char *input,
bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *rule, bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &input, RuleMessage &ruleMessage) {
size_t offset = 0; size_t offset = 0;
bool res = false; bool res = false;

View File

@ -33,7 +33,7 @@ class ValidateUrlEncoding : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &input, const std::string &input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
static int validate_url_encoding(const char *input, uint64_t input_length, static int validate_url_encoding(const char *input, uint64_t input_length,
size_t *offset); size_t *offset);

View File

@ -122,7 +122,7 @@ int ValidateUtf8Encoding::detect_utf8_character(
} }
bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *rule, bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
unsigned int i, bytes_left; unsigned int i, bytes_left;
const char *str_c = str.c_str(); const char *str_c = str.c_str();

View File

@ -33,7 +33,7 @@ class ValidateUtf8Encoding : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, const std::string &str,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
static int detect_utf8_character(const unsigned char *p_read, static int detect_utf8_character(const unsigned char *p_read,
unsigned int length); unsigned int length);

View File

@ -135,7 +135,7 @@ bool VerifyCC::init(const std::string &param2, std::string *error) {
bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& i, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& i, RuleMessage &ruleMessage) {
#ifdef WITH_PCRE2 #ifdef WITH_PCRE2
PCRE2_SIZE offset = 0; PCRE2_SIZE offset = 0;
size_t target_length = i.length(); size_t target_length = i.length();

View File

@ -49,7 +49,7 @@ class VerifyCC : public Operator {
bool evaluate(Transaction *t, RuleWithActions *rule, bool evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool init(const std::string &param, std::string *error) override; bool init(const std::string &param, std::string *error) override;
private: private:
#if WITH_PCRE2 #if WITH_PCRE2

View File

@ -109,7 +109,7 @@ bool VerifyCPF::verify(const char *cpfnumber, int len) {
bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule, bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
std::list<SMatch> matches; std::list<SMatch> matches;
bool is_cpf = false; bool is_cpf = false;
int i; int i;

View File

@ -48,7 +48,7 @@ class VerifyCPF : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool verify(const char *ssnumber, int len); bool verify(const char *ssnumber, int len);

View File

@ -111,7 +111,7 @@ invalid:
bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule, bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
std::list<SMatch> matches; std::list<SMatch> matches;
bool is_ssn = false; bool is_ssn = false;
int i; int i;

View File

@ -48,7 +48,7 @@ class VerifySSN : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;

View File

@ -78,7 +78,7 @@ bool VerifySVNR::verify(const char *svnrnumber, int len) {
bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule, bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& input, RuleMessage &ruleMessage) {
std::list<SMatch> matches; std::list<SMatch> matches;
bool is_svnr = false; bool is_svnr = false;
int i; int i;

View File

@ -34,7 +34,7 @@ class VerifySVNR : public Operator {
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string& input, const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override; RuleMessage &ruleMessage) override;
bool verify(const char *ssnumber, int len); bool verify(const char *ssnumber, int len);

View File

@ -25,7 +25,7 @@ namespace operators {
bool Within::evaluate(Transaction *transaction, RuleWithActions *rule, bool Within::evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &str, RuleMessage &ruleMessage) {
bool res = false; bool res = false;
size_t pos = 0; size_t pos = 0;
std::string paramTarget(m_string->evaluate(transaction)); std::string paramTarget(m_string->evaluate(transaction));

View File

@ -34,7 +34,7 @@ class Within : public Operator {
m_couldContainsMacro = true; m_couldContainsMacro = true;
} }
bool evaluate(Transaction *transaction, RuleWithActions *rule, bool evaluate(Transaction *transaction, RuleWithActions *rule,
const std::string &str, std::shared_ptr<RuleMessage> ruleMessage) override; const std::string &str, RuleMessage &ruleMessage) override;
}; };
} // namespace operators } // namespace operators

View File

@ -23,55 +23,55 @@
namespace modsecurity { namespace modsecurity {
std::string RuleMessage::_details(const RuleMessage *rm) { std::string RuleMessage::_details(const RuleMessage &rm) {
std::string msg; std::string msg;
msg.append(" [file \"" + rm->m_rule.getFileName() + "\"]"); msg.append(" [file \"" + rm.m_rule.getFileName() + "\"]");
msg.append(" [line \"" + std::to_string(rm->m_rule.getLineNumber()) + "\"]"); msg.append(" [line \"" + std::to_string(rm.m_rule.getLineNumber()) + "\"]");
msg.append(" [id \"" + std::to_string(rm->m_rule.m_ruleId) + "\"]"); msg.append(" [id \"" + std::to_string(rm.m_rule.m_ruleId) + "\"]");
msg.append(" [rev \"" + utils::string::toHexIfNeeded(rm->m_rule.m_rev, true) + "\"]"); msg.append(" [rev \"" + utils::string::toHexIfNeeded(rm.m_rule.m_rev, true) + "\"]");
msg.append(" [msg \"" + rm->m_message + "\"]"); msg.append(" [msg \"" + rm.m_message + "\"]");
msg.append(" [data \"" + utils::string::toHexIfNeeded(utils::string::limitTo(200, rm->m_data), true) + "\"]"); msg.append(" [data \"" + utils::string::toHexIfNeeded(utils::string::limitTo(200, rm.m_data), true) + "\"]");
msg.append(" [severity \"" + msg.append(" [severity \"" +
std::to_string(rm->m_severity) + "\"]"); std::to_string(rm.m_severity) + "\"]");
msg.append(" [ver \"" + utils::string::toHexIfNeeded(rm->m_rule.m_ver, true) + "\"]"); msg.append(" [ver \"" + utils::string::toHexIfNeeded(rm.m_rule.m_ver, true) + "\"]");
msg.append(" [maturity \"" + std::to_string(rm->m_rule.m_maturity) + "\"]"); msg.append(" [maturity \"" + std::to_string(rm.m_rule.m_maturity) + "\"]");
msg.append(" [accuracy \"" + std::to_string(rm->m_rule.m_accuracy) + "\"]"); msg.append(" [accuracy \"" + std::to_string(rm.m_rule.m_accuracy) + "\"]");
for (const auto &a : rm->m_tags) { for (const auto &a : rm.m_tags) {
msg.append(" [tag \"" + utils::string::toHexIfNeeded(a, true) + "\"]"); msg.append(" [tag \"" + utils::string::toHexIfNeeded(a, true) + "\"]");
} }
msg.append(" [hostname \"" + rm->m_transaction.m_requestHostName \ msg.append(" [hostname \"" + rm.m_transaction.m_requestHostName \
+ "\"]"); + "\"]");
msg.append(" [uri \"" + utils::string::limitTo(200, rm->m_transaction.m_uri_no_query_string_decoded) + "\"]"); msg.append(" [uri \"" + utils::string::limitTo(200, rm.m_transaction.m_uri_no_query_string_decoded) + "\"]");
msg.append(" [unique_id \"" + rm->m_transaction.m_id + "\"]"); msg.append(" [unique_id \"" + rm.m_transaction.m_id + "\"]");
msg.append(" [ref \"" + utils::string::limitTo(200, rm->m_reference) + "\"]"); msg.append(" [ref \"" + utils::string::limitTo(200, rm.m_reference) + "\"]");
return msg; return msg;
} }
std::string RuleMessage::_errorLogTail(const RuleMessage *rm) { std::string RuleMessage::_errorLogTail(const RuleMessage &rm) {
std::string msg; std::string msg;
msg.append("[hostname \"" + rm->m_transaction.m_serverIpAddress + "\"]"); msg.append("[hostname \"" + rm.m_transaction.m_serverIpAddress + "\"]");
msg.append(" [uri \"" + utils::string::limitTo(200, rm->m_transaction.m_uri_no_query_string_decoded) + "\"]"); msg.append(" [uri \"" + utils::string::limitTo(200, rm.m_transaction.m_uri_no_query_string_decoded) + "\"]");
msg.append(" [unique_id \"" + rm->m_transaction.m_id + "\"]"); msg.append(" [unique_id \"" + rm.m_transaction.m_id + "\"]");
return msg; return msg;
} }
std::string RuleMessage::log(const RuleMessage *rm, int props, int code) { std::string RuleMessage::log(const RuleMessage &rm, int props, int code) {
std::string msg(""); std::string msg("");
msg.reserve(2048); msg.reserve(2048);
if (props & ClientLogMessageInfo) { if (props & ClientLogMessageInfo) {
msg.append("[client " + rm->m_transaction.m_clientIpAddress + "] "); msg.append("[client " + rm.m_transaction.m_clientIpAddress + "] ");
} }
if (rm->m_isDisruptive) { if (rm.m_isDisruptive) {
msg.append("ModSecurity: Access denied with code "); msg.append("ModSecurity: Access denied with code ");
if (code == -1) { if (code == -1) {
msg.append("%d"); msg.append("%d");
@ -79,12 +79,12 @@ std::string RuleMessage::log(const RuleMessage *rm, int props, int code) {
msg.append(std::to_string(code)); msg.append(std::to_string(code));
} }
msg.append(" (phase "); msg.append(" (phase ");
msg.append(std::to_string(rm->getPhase()) + "). "); msg.append(std::to_string(rm.getPhase()) + "). ");
} else { } else {
msg.append("ModSecurity: Warning. "); msg.append("ModSecurity: Warning. ");
} }
msg.append(rm->m_match); msg.append(rm.m_match);
msg.append(_details(rm)); msg.append(_details(rm));
if (props & ErrorLogTailLogMessageInfo) { if (props & ErrorLogTailLogMessageInfo) {

View File

@ -23,7 +23,7 @@ bool RuleScript::init(std::string *err) {
} }
bool RuleScript::evaluate(Transaction *trans, bool RuleScript::evaluate(Transaction *trans,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
ms_dbg_a(trans, 4, " Executing script: " + m_name + "."); ms_dbg_a(trans, 4, " Executing script: " + m_name + ".");

View File

@ -59,8 +59,7 @@ class RuleScript : public RuleWithActions {
bool init(std::string *err); bool init(std::string *err);
bool evaluate(Transaction *trans, bool evaluate(Transaction *trans, RuleMessage &ruleMessage) override;
std::shared_ptr<RuleMessage> ruleMessage) override;
std::string m_name; std::string m_name;
engine::Lua m_lua; engine::Lua m_lua;

View File

@ -20,7 +20,7 @@ namespace modsecurity {
bool RuleUnconditional::evaluate(Transaction *trans, bool RuleUnconditional::evaluate(Transaction *trans,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
RuleWithActions::evaluate(trans, ruleMessage); RuleWithActions::evaluate(trans, ruleMessage);
// FIXME: This needs to be romeved on the runtime exeption review. // FIXME: This needs to be romeved on the runtime exeption review.

View File

@ -179,12 +179,13 @@ RuleWithActions::~RuleWithActions() {
bool RuleWithActions::evaluate(Transaction *transaction) { bool RuleWithActions::evaluate(Transaction *transaction) {
return evaluate(transaction, std::make_shared<RuleMessage>(*this, *transaction)); RuleMessage rm(*this, *transaction);
return evaluate(transaction, rm);
} }
bool RuleWithActions::evaluate(Transaction *transaction, bool RuleWithActions::evaluate(Transaction *transaction,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
/* Rule evaluate is pure virtual. /* Rule evaluate is pure virtual.
* *
@ -199,7 +200,7 @@ bool RuleWithActions::evaluate(Transaction *transaction,
void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans, void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans,
bool *containsBlock, std::shared_ptr<RuleMessage> ruleMessage) { bool *containsBlock, RuleMessage &ruleMessage) {
for (actions::SetVar *a : m_actionsSetVar) { for (actions::SetVar *a : m_actionsSetVar) {
ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \ ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \
@ -243,7 +244,7 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *
void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans,
bool containsBlock, std::shared_ptr<RuleMessage> ruleMessage) { bool containsBlock, RuleMessage &ruleMessage) {
bool disruptiveAlreadyExecuted = false; bool disruptiveAlreadyExecuted = false;
for (const auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer for (const auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer
@ -296,7 +297,7 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans,
void RuleWithActions::executeAction(Transaction *trans, void RuleWithActions::executeAction(Transaction *trans,
bool containsBlock, std::shared_ptr<RuleMessage> ruleMessage, bool containsBlock, RuleMessage &ruleMessage,
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 " \
@ -492,12 +493,12 @@ std::vector<actions::Action *> RuleWithActions::getActionsByName(const std::stri
} }
void RuleWithActions::performLogging(Transaction *trans, void RuleWithActions::performLogging(Transaction *trans,
std::shared_ptr<RuleMessage> ruleMessage, RuleMessage &ruleMessage,
bool lastLog, bool lastLog,
bool chainedParentNull) const { bool chainedParentNull) const {
/* last rule in the chain. */ /* last rule in the chain. */
bool isItToBeLogged = ruleMessage->m_saveMessage; bool isItToBeLogged = ruleMessage.m_saveMessage;
/** /**
* *
@ -512,31 +513,31 @@ void RuleWithActions::performLogging(Transaction *trans,
**/ **/
if (lastLog) { if (lastLog) {
if (chainedParentNull) { if (chainedParentNull) {
isItToBeLogged = (ruleMessage->m_saveMessage && (m_chainedRuleParent == nullptr)); isItToBeLogged = (ruleMessage.m_saveMessage && (m_chainedRuleParent == nullptr));
if (isItToBeLogged && !hasMultimatch()) { if (isItToBeLogged && !hasMultimatch()) {
/* warn */ /* warn */
trans->m_rulesMessages.push_back(*ruleMessage); trans->m_rulesMessages.push_back(ruleMessage);
/* error */ /* error */
if (!ruleMessage->m_isDisruptive) { if (!ruleMessage.m_isDisruptive) {
trans->serverLog(ruleMessage); trans->serverLog(ruleMessage);
} }
} }
} else if (hasBlockAction() && !hasMultimatch()) { } else if (hasBlockAction() && !hasMultimatch()) {
/* warn */ /* warn */
trans->m_rulesMessages.push_back(*ruleMessage); trans->m_rulesMessages.push_back(ruleMessage);
/* error */ /* error */
if (!ruleMessage->m_isDisruptive) { if (!ruleMessage.m_isDisruptive) {
trans->serverLog(ruleMessage); trans->serverLog(ruleMessage);
} }
} else { } else {
if (isItToBeLogged && !hasMultimatch() if (isItToBeLogged && !hasMultimatch()
&& !ruleMessage->m_message.empty()) { && !ruleMessage.m_message.empty()) {
/* warn */ /* warn */
trans->m_rulesMessages.push_back(*ruleMessage); trans->m_rulesMessages.push_back(ruleMessage);
/* error */ /* error */
if (!ruleMessage->m_isDisruptive) { if (!ruleMessage.m_isDisruptive) {
trans->serverLog(ruleMessage); trans->serverLog(ruleMessage);
} }
} }
@ -544,16 +545,14 @@ void RuleWithActions::performLogging(Transaction *trans,
} else { } else {
if (hasMultimatch() && isItToBeLogged) { if (hasMultimatch() && isItToBeLogged) {
/* warn */ /* warn */
trans->m_rulesMessages.push_back(*ruleMessage.get()); trans->m_rulesMessages.push_back(ruleMessage);
/* error */ /* error */
if (!ruleMessage->m_isDisruptive) { if (!ruleMessage.m_isDisruptive) {
trans->serverLog(ruleMessage); trans->serverLog(ruleMessage);
} }
RuleMessage *rm = new RuleMessage(*this, *trans); ruleMessage.reset(false);
rm->m_saveMessage = ruleMessage->m_saveMessage;
ruleMessage.reset(rm);
} }
} }
} }

View File

@ -102,7 +102,7 @@ void RuleWithOperator::cleanMatchedVars(Transaction *trans) {
bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string &key, bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string &key,
const std::string &value, std::shared_ptr<RuleMessage> ruleMessage) { const std::string &value, RuleMessage &ruleMessage) {
#if MSC_EXEC_CLOCK_ENABLED #if MSC_EXEC_CLOCK_ENABLED
clock_t begin = clock(); clock_t begin = clock();
clock_t end; clock_t end;
@ -202,7 +202,7 @@ inline void RuleWithOperator::getFinalVars(variables::Variables *vars,
bool RuleWithOperator::evaluate(Transaction *trans, bool RuleWithOperator::evaluate(Transaction *trans,
std::shared_ptr<RuleMessage> ruleMessage) { RuleMessage &ruleMessage) {
bool globalRet = false; bool globalRet = false;
variables::Variables *variables = this->m_variables; variables::Variables *variables = this->m_variables;
bool recursiveGlobalRet; bool recursiveGlobalRet;
@ -301,13 +301,13 @@ bool RuleWithOperator::evaluate(Transaction *trans,
const bool ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); const bool ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage);
if (ret == true) { if (ret == true) {
ruleMessage->m_match = m_operator->resolveMatchMessage(trans, ruleMessage.m_match = m_operator->resolveMatchMessage(trans,
key, value); key, value);
for (const auto &i : v->getOrigin()) { for (const auto &i : v->getOrigin()) {
ruleMessage->m_reference.append(i.toText()); ruleMessage.m_reference.append(i.toText());
} }
ruleMessage->m_reference.append(*valueTemp.second); ruleMessage.m_reference.append(*valueTemp.second);
updateMatchedVars(trans, key, valueAfterTrans); updateMatchedVars(trans, key, valueAfterTrans);
executeActionsIndependentOfChainedRuleResult(trans, executeActionsIndependentOfChainedRuleResult(trans,
&containsBlock, ruleMessage); &containsBlock, ruleMessage);

View File

@ -1529,7 +1529,7 @@ std::string Transaction::toOldAuditLogFormat(int parts,
} }
if (parts & audit_log::AuditLog::HAuditLogPart) { if (parts & audit_log::AuditLog::HAuditLogPart) {
audit_log << "--" << trailer << "-" << "H--" << std::endl; audit_log << "--" << trailer << "-" << "H--" << std::endl;
for (auto a : m_rulesMessages) { for (const auto &a : m_rulesMessages) {
audit_log << a.log(0, m_httpCodeReturned) << std::endl; audit_log << a.log(0, m_httpCodeReturned) << std::endl;
} }
audit_log << std::endl; audit_log << std::endl;
@ -1750,7 +1750,7 @@ std::string Transaction::toJSON(int parts) {
} }
void Transaction::serverLog(std::shared_ptr<RuleMessage> rm) { void Transaction::serverLog(const RuleMessage &rm) {
m_ms->serverLog(m_logCbData, rm); m_ms->serverLog(m_logCbData, rm);
} }

View File

@ -31,7 +31,8 @@ EXTRA_DIST = \
noinst_PROGRAMS += unit_tests noinst_PROGRAMS += unit_tests
unit_tests_SOURCES = \ unit_tests_SOURCES = \
unit/unit.cc \ unit/unit.cc \
unit/unit_test.cc unit/unit_test.cc \
common/custom_debug_log.cc
noinst_HEADERS = \ noinst_HEADERS = \
@ -94,7 +95,7 @@ noinst_PROGRAMS += regression_tests
regression_tests_SOURCES = \ regression_tests_SOURCES = \
regression/regression.cc \ regression/regression.cc \
regression/regression_test.cc \ regression/regression_test.cc \
regression/custom_debug_log.cc common/custom_debug_log.cc
regression_tests_LDADD = \ regression_tests_LDADD = \
$(CURL_LDADD) \ $(CURL_LDADD) \

View File

@ -0,0 +1,51 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address security@modsecurity.org.
*
*/
#include "custom_debug_log.h"
#include <iostream>
#include <string>
#include "modsecurity/debug_log.h"
#include "src/utils/regex.h"
namespace modsecurity_test {
void CustomDebugLog::write(int level, const std::string &message) {
m_log << "[" << level << "] " << message << std::endl;
}
void CustomDebugLog::write(int level, const std::string &id,
const std::string &uri, const std::string &msg) {
std::string msgf = "[" + std::to_string(level) + "] " + msg;
msgf = "[" + id + "] [" + uri + "] " + msgf;
m_log << msgf << std::endl;
}
bool CustomDebugLog::contains(const std::string &pattern) const {
modsecurity::Utils::Regex re(pattern);
std::string s = m_log.str();
return modsecurity::Utils::regex_search(s, re);
}
std::string CustomDebugLog::log_messages() const {
return m_log.str();
}
int CustomDebugLog::getDebugLogLevel() {
return 9;
}
} // namespace modsecurity_test

View File

@ -26,13 +26,12 @@ namespace modsecurity_test {
class CustomDebugLog : public modsecurity::debug_log::DebugLog { class CustomDebugLog : public modsecurity::debug_log::DebugLog {
public: public:
CustomDebugLog *new_instance(); CustomDebugLog *new_instance();
~CustomDebugLog();
void write(int level, const std::string& message) override; void write(int level, const std::string& message) override;
void write(int level, const std::string &id, void write(int level, const std::string &id,
const std::string &uri, const std::string &msg) override; const std::string &uri, const std::string &msg) override;
bool const contains(const std::string& pattern) const; bool contains(const std::string& pattern) const;
std::string const log_messages() const; std::string log_messages() const;
std::string error_log_messages(); std::string error_log_messages();
int getDebugLogLevel() override; int getDebugLogLevel() override;

View File

@ -72,18 +72,11 @@ bool ModSecurityTest<T>::load_test_json(const std::string &file) {
for ( int i = 0; i < num_tests; i++ ) { for ( int i = 0; i < num_tests; i++ ) {
yajl_val obj = node->u.array.values[i]; yajl_val obj = node->u.array.values[i];
T *u = T::from_yajl_node(obj); auto u = std::unique_ptr<T>(T::from_yajl_node(obj));
u->filename = file; u->filename = file;
if (this->count(u->filename + ":" + u->name) == 0) { const auto key = u->filename + ":" + u->name;
auto vec = new std::vector<T *>; (*this)[key].push_back(std::move(u));
vec->push_back(u);
std::string filename(u->filename + ":" + u->name);
this->insert({filename, vec});
} else {
auto vec = this->at(u->filename + ":" + u->name);
vec->push_back(u);
}
} }
yajl_tree_free(node); yajl_tree_free(node);

View File

@ -29,7 +29,7 @@ extern std::string default_test_path;
namespace modsecurity_test { namespace modsecurity_test {
template <class T> class ModSecurityTest : template <class T> class ModSecurityTest :
public std::unordered_map<std::string, std::vector<T *> *> { public std::unordered_map<std::string, std::vector<std::unique_ptr<T>>> {
public: public:
ModSecurityTest() ModSecurityTest()
: m_test_number(0), : m_test_number(0),

View File

@ -0,0 +1,42 @@
#ifndef TEST_COMMON_MODSECURITY_TEST_CONTEXT_H_
#define TEST_COMMON_MODSECURITY_TEST_CONTEXT_H_
#include "modsecurity/modsecurity.h"
#include "modsecurity/rules_set.h"
#include "modsecurity/transaction.h"
#include "custom_debug_log.h"
#include <sstream>
namespace modsecurity_test {
class ModSecurityTestContext {
public:
explicit ModSecurityTestContext(const std::string &connector)
: m_modsec_rules(new CustomDebugLog) {
m_modsec.setConnectorInformation(connector);
m_modsec.setServerLogCb(logCb);
}
~ModSecurityTestContext() = default;
modsecurity::Transaction create_transaction() {
return modsecurity::Transaction(&m_modsec,
&m_modsec_rules,
&m_server_log);
}
modsecurity::ModSecurity m_modsec;
modsecurity::RulesSet m_modsec_rules;
std::stringstream m_server_log;
private:
static void logCb(void *data, const void *msgv) {
auto msg = reinterpret_cast<const char *>(msgv);
auto ss = reinterpret_cast<std::stringstream *>(data);
*ss << msg << std::endl;
}
};
} // namespace modsecurity_test
#endif // TEST_COMMON_MODSECURITY_TEST_H_

View File

@ -1,55 +0,0 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address security@modsecurity.org.
*
*/
#include "test/regression/custom_debug_log.h"
#include <iostream>
#include <string>
#include "modsecurity/debug_log.h"
#include "src/utils/regex.h"
namespace modsecurity_test {
CustomDebugLog::~CustomDebugLog() { }
void CustomDebugLog::write(int level, const std::string& message) {
m_log << "[" << level << "] " << message << std::endl;
}
void CustomDebugLog::write(int level, const std::string &id,
const std::string &uri, const std::string &msg) {
std::string msgf = "[" + std::to_string(level) + "] " + msg;
msgf = "[" + id + "] [" + uri + "] " + msgf;
m_log << msgf << std::endl;
}
bool const CustomDebugLog::contains(const std::string& pattern) const {
modsecurity::Utils::Regex re(pattern);
std::string s = m_log.str();
return modsecurity::Utils::regex_search(s, re);
}
std::string const CustomDebugLog::log_messages() const {
return m_log.str();
}
int CustomDebugLog::getDebugLogLevel() {
return 9;
}
} // namespace modsecurity_test

View File

@ -33,7 +33,7 @@
#include "test/common/colors.h" #include "test/common/colors.h"
#include "test/regression/regression_test.h" #include "test/regression/regression_test.h"
#include "test/common/modsecurity_test_results.h" #include "test/common/modsecurity_test_results.h"
#include "test/regression/custom_debug_log.h" #include "test/common/modsecurity_test_context.h"
#include "src/utils/regex.h" #include "src/utils/regex.h"
using modsecurity_test::CustomDebugLog; using modsecurity_test::CustomDebugLog;
@ -97,40 +97,28 @@ void actions(ModSecurityTestResults<RegressionTest> *r,
if (it.status != 0) { if (it.status != 0) {
r->status = it.status; r->status = it.status;
} }
if (it.url != NULL) { if (it.url != nullptr) {
r->location.append(it.url); r->location.append(it.url);
free(it.url); free(it.url);
it.url = NULL; it.url = nullptr;
} }
if (it.log != NULL) { if (it.log != nullptr) {
*serverLog << it.log; *serverLog << it.log;
free(it.log); free(it.log);
it.log = NULL; it.log = nullptr;
} }
} }
} }
void logCb(void *data, const void *msgv) {
const char *msg = reinterpret_cast<const char*>(msgv);
std::stringstream *ss = (std::stringstream *) data;
*ss << msg << std::endl;
}
void perform_unit_test(ModSecurityTest<RegressionTest> *test, void perform_unit_test(ModSecurityTest<RegressionTest> *test,
std::vector<RegressionTest *> *tests, std::vector<std::unique_ptr<RegressionTest>> &tests,
ModSecurityTestResults<RegressionTestResult> *res, int *count) { ModSecurityTestResults<RegressionTestResult> *res, int *count)
{
for (RegressionTest *t : *tests) { for (auto &t : tests) {
CustomDebugLog *debug_log = new CustomDebugLog();
modsecurity::ModSecurity *modsec = NULL;
modsecurity::RulesSet *modsec_rules = NULL;
modsecurity::Transaction *modsec_transaction = NULL;
ModSecurityTestResults<RegressionTest> r; ModSecurityTestResults<RegressionTest> r;
std::stringstream serverLog;
RegressionTestResult *testRes = new RegressionTestResult(); RegressionTestResult *testRes = new RegressionTestResult();
testRes->test = t; testRes->test = t.get();
r.status = 200; r.status = 200;
(*count)++; (*count)++;
@ -169,11 +157,8 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
unlink("./modsec-shared-collections-lock"); unlink("./modsec-shared-collections-lock");
#endif #endif
modsec = new modsecurity::ModSecurity(); modsecurity_test::ModSecurityTestContext context("ModSecurity-regression v0.0.1-alpha" \
modsec->setConnectorInformation("ModSecurity-regression v0.0.1-alpha" \
" (ModSecurity regression test utility)"); " (ModSecurity regression test utility)");
modsec->setServerLogCb(logCb);
modsec_rules = new modsecurity::RulesSet(debug_log);
bool found = true; bool found = true;
if (t->resource.empty() == false) { if (t->resource.empty() == false) {
@ -196,15 +181,11 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
} }
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
modsec_rules->load("SecDebugLogLevel 9"); context.m_modsec_rules.load("SecDebugLogLevel 9");
if (modsec_rules->load(t->rules.c_str(), filename) < 0) { if (context.m_modsec_rules.load(t->rules.c_str(), filename) < 0) {
/* Parser error */ /* Parser error */
if (t->parser_error.empty() == true) { if (t->parser_error.empty() == true) {
/* /*
@ -219,21 +200,17 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
} }
testRes->reason << KRED << "parse failed." << RESET \ testRes->reason << KRED << "parse failed." << RESET \
<< std::endl; << std::endl;
testRes->reason << modsec_rules->getParserError() \ testRes->reason << context.m_modsec_rules.getParserError() \
<< std::endl; << std::endl;
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
Regex re(t->parser_error); Regex re(t->parser_error);
SMatch match; SMatch match;
std::string s = modsec_rules->getParserError(); const auto s = context.m_modsec_rules.getParserError();
if (regex_search(s, &match, re)) { if (regex_search(s, &match, re)) {
if (test->m_automake_output) { if (test->m_automake_output) {
@ -247,10 +224,6 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
testRes->passed = true; testRes->passed = true;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} else { } else {
/* Parser error was expected, but with a different content */ /* Parser error was expected, but with a different content */
@ -271,10 +244,6 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
} else { } else {
@ -293,190 +262,136 @@ void perform_unit_test(ModSecurityTest<RegressionTest> *test,
testRes->passed = false; testRes->passed = false;
res->push_back(testRes); res->push_back(testRes);
delete modsec_transaction;
delete modsec_rules;
delete modsec;
continue; continue;
} }
} }
modsec_transaction = new modsecurity::Transaction(modsec, modsec_rules, auto modsec_transaction = context.create_transaction();
&serverLog);
clearAuditLog(modsec_transaction->m_rules->m_auditLog->m_path1); clearAuditLog(modsec_transaction.m_rules->m_auditLog->m_path1);
modsec_transaction->processConnection(t->clientIp.c_str(), modsec_transaction.processConnection(t->clientIp.c_str(),
t->clientPort, t->serverIp.c_str(), t->serverPort); t->clientPort, t->serverIp.c_str(), t->serverPort);
if (t->hostname != "") { if (t->hostname != "") {
modsec_transaction->setRequestHostName(t->hostname); modsec_transaction.setRequestHostName(t->hostname);
} }
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
modsec_transaction->processURI(t->uri.c_str(), t->method.c_str(), modsec_transaction.processURI(t->uri.c_str(), t->method.c_str(),
t->httpVersion.c_str()); t->httpVersion.c_str());
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
for (std::pair<std::string, std::string> headers : for (const auto &[name, value] : t->request_headers) {
t->request_headers) { modsec_transaction.addRequestHeader(name.c_str(),
modsec_transaction->addRequestHeader(headers.first.c_str(), value.c_str());
headers.second.c_str());
} }
modsec_transaction->processRequestHeaders(); modsec_transaction.processRequestHeaders();
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
modsec_transaction->appendRequestBody( modsec_transaction.appendRequestBody(
(unsigned char *)t->request_body.c_str(), (unsigned char *)t->request_body.c_str(),
t->request_body.size()); t->request_body.size());
modsec_transaction->processRequestBody(); modsec_transaction.processRequestBody();
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
for (std::pair<std::string, std::string> headers : for (const auto &[name, value] : t->response_headers) {
t->response_headers) { modsec_transaction.addResponseHeader(name.c_str(),
modsec_transaction->addResponseHeader(headers.first.c_str(), value.c_str());
headers.second.c_str());
} }
modsec_transaction->processResponseHeaders(r.status, modsec_transaction.processResponseHeaders(r.status,
t->response_protocol); t->response_protocol);
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
modsec_transaction->appendResponseBody( modsec_transaction.appendResponseBody(
(unsigned char *)t->response_body.c_str(), (unsigned char *)t->response_body.c_str(),
t->response_body.size()); t->response_body.size());
modsec_transaction->processResponseBody(); modsec_transaction.processResponseBody();
actions(&r, modsec_transaction, &serverLog); actions(&r, &modsec_transaction, &context.m_server_log);
#if 0
if (r.status != 200) {
goto end;
}
#endif
#if 0 modsec_transaction.processLogging();
end:
#endif
modsec_transaction->processLogging();
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *> const auto *d = static_cast<CustomDebugLog *>(context.m_modsec_rules.m_debugLog);
(modsec_rules->m_debugLog);
if (d != NULL) { if (!d->contains(t->debug_log)) {
if (!d->contains(t->debug_log)) { if (test->m_automake_output) {
if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \
std::cout << ":test-result: FAIL " << filename \ << ":" << t->name << ":" << *count << std::endl;
<< ":" << t->name << ":" << *count << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "Debug log was not matching the " \
<< "expected results." << std::endl;
testRes->reason << KWHT << "Expecting: " << RESET \
<< t->debug_log + "";
testRes->passed = false;
} else if (r.status != t->http_code) {
if (test->m_automake_output) {
std::cout << ":test-result: FAIL " << filename \
<< ":" << t->name << ":" << *count << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "HTTP code mismatch. expecting: " + \
std::to_string(t->http_code) + \
" got: " + std::to_string(r.status) + "\n";
testRes->passed = false;
} else if (!contains(serverLog.str(), t->error_log)) {
if (test->m_automake_output) {
std::cout << ":test-result: FAIL " << filename \
<< ":" << t->name << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "Error log was not matching the " \
<< "expected results." << std::endl;
testRes->reason << KWHT << "Expecting: " << RESET \
<< t->error_log + "";
testRes->passed = false;
} else if (!t->audit_log.empty()
&& !contains(getAuditLogContent(modsec_transaction->m_rules->m_auditLog->m_path1), t->audit_log)) {
if (test->m_automake_output) {
std::cout << ":test-result: FAIL " << filename \
<< ":" << t->name << ":" << *count << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "Audit log was not matching the " \
<< "expected results." << std::endl;
testRes->reason << KWHT << "Expecting: " << RESET \
<< t->audit_log + "";
testRes->passed = false;
} else { } else {
if (test->m_automake_output) { std::cout << KRED << "failed!" << RESET << std::endl;
std::cout << ":test-result: PASS " << filename \
<< ":" << t->name << std::endl;
} else {
std::cout << KGRN << "passed!" << RESET << std::endl;
}
testRes->passed = true;
goto after_debug_log;
} }
testRes->reason << "Debug log was not matching the " \
if (testRes->passed == false) { << "expected results." << std::endl;
testRes->reason << std::endl; testRes->reason << KWHT << "Expecting: " << RESET
testRes->reason << KWHT << "Debug log:" << RESET << std::endl; << t->debug_log + "";
testRes->reason << d->log_messages() << std::endl; testRes->passed = false;
testRes->reason << KWHT << "Error log:" << RESET << std::endl; } else if (r.status != t->http_code) {
testRes->reason << serverLog.str() << std::endl; if (test->m_automake_output) {
testRes->reason << KWHT << "Audit log:" << RESET << std::endl; std::cout << ":test-result: FAIL " << filename \
testRes->reason << getAuditLogContent(modsec_transaction->m_rules->m_auditLog->m_path1) << std::endl; << ":" << t->name << ":" << *count << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
} }
testRes->reason << "HTTP code mismatch. expecting: " +
std::to_string(t->http_code) +
" got: " + std::to_string(r.status) + "\n";
testRes->passed = false;
} else if (!contains(context.m_server_log.str(), t->error_log)) {
if (test->m_automake_output) {
std::cout << ":test-result: FAIL " << filename \
<< ":" << t->name << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "Error log was not matching the " \
<< "expected results." << std::endl;
testRes->reason << KWHT << "Expecting: " << RESET \
<< t->error_log + "";
testRes->passed = false;
} else if (!t->audit_log.empty() && !contains(getAuditLogContent(modsec_transaction.m_rules->m_auditLog->m_path1), t->audit_log)) {
if (test->m_automake_output) {
std::cout << ":test-result: FAIL " << filename \
<< ":" << t->name << ":" << *count << std::endl;
} else {
std::cout << KRED << "failed!" << RESET << std::endl;
}
testRes->reason << "Audit log was not matching the " \
<< "expected results." << std::endl;
testRes->reason << KWHT << "Expecting: " << RESET \
<< t->audit_log + "";
testRes->passed = false;
} else {
if (test->m_automake_output) {
std::cout << ":test-result: PASS " << filename \
<< ":" << t->name << std::endl;
} else {
std::cout << KGRN << "passed!" << RESET << std::endl;
}
testRes->passed = true;
} }
if (testRes->passed == false) {
after_debug_log: testRes->reason << std::endl;
if (d != NULL) { testRes->reason << KWHT << "Debug log:" << RESET << std::endl;
r.log_raw_debug_log = d->log_messages(); testRes->reason << d->log_messages() << std::endl;
testRes->reason << KWHT << "Error log:" << RESET << std::endl;
testRes->reason << context.m_server_log.str() << std::endl;
testRes->reason << KWHT << "Audit log:" << RESET << std::endl;
testRes->reason << getAuditLogContent(modsec_transaction.m_rules->m_auditLog->m_path1) << std::endl;
} }
delete modsec_transaction; r.log_raw_debug_log = d->log_messages();
delete modsec_rules;
delete modsec;
/* delete debug_log; */
res->push_back(testRes); res->push_back(testRes);
} }
} }
int main(int argc, char **argv)
int main(int argc, char **argv) { {
ModSecurityTest<RegressionTest> test; ModSecurityTest<RegressionTest> test;
std::string ver(MODSECURITY_VERSION); std::string ver(MODSECURITY_VERSION);
@ -541,8 +456,8 @@ int main(int argc, char **argv) {
int counter = 0; int counter = 0;
std::list<std::string> keyList; std::list<std::string> keyList;
for (std::pair<std::string, std::vector<RegressionTest *> *> a : test) { for (const auto &[name, tests] : test) {
keyList.push_back(a.first); keyList.push_back(name);
} }
keyList.sort(); keyList.sort();
@ -556,7 +471,7 @@ int main(int argc, char **argv) {
test_number++; test_number++;
if ((test.m_test_number == 0) if ((test.m_test_number == 0)
|| (test_number == test.m_test_number)) { || (test_number == test.m_test_number)) {
std::vector<RegressionTest *> *tests = test[a]; auto &tests = test[a];
perform_unit_test(&test, tests, &res, &counter); perform_unit_test(&test, tests, &res, &counter);
} }
} }
@ -605,18 +520,10 @@ int main(int argc, char **argv) {
} }
std::cout << KCYN << std::to_string(skipped) << " "; std::cout << KCYN << std::to_string(skipped) << " ";
std::cout << "skipped test(s). " << std::to_string(disabled) << " "; std::cout << "skipped test(s). " << std::to_string(disabled) << " ";
std::cout << "disabled test(s)." << RESET << std::endl; std::cout << "disabled test(s)." << RESET << std::endl;
} }
for (std::pair<std::string, std::vector<RegressionTest *> *> a : test) {
std::vector<RegressionTest *> *vec = a.second;
for (int i = 0; i < vec->size(); i++) {
delete vec->at(i);
}
delete vec;
}
return failed; return failed;
#endif #endif
} }

View File

@ -32,6 +32,7 @@
#include "test/common/modsecurity_test.h" #include "test/common/modsecurity_test.h"
#include "test/common/modsecurity_test_results.h" #include "test/common/modsecurity_test_results.h"
#include "test/common/modsecurity_test_context.h"
#include "test/common/colors.h" #include "test/common/colors.h"
#include "test/unit/unit_test.h" #include "test/unit/unit_test.h"
#include "src/utils/string.h" #include "src/utils/string.h"
@ -69,8 +70,10 @@ struct OperatorTest {
return op; return op;
} }
static UnitTestResult eval(ItemType &op, const UnitTest &t) { static UnitTestResult eval(ItemType &op, const UnitTest &t, modsecurity::Transaction &transaction) {
return {op.evaluate(nullptr, nullptr, t.input, nullptr), {}}; modsecurity::RuleWithActions rule{nullptr, nullptr, "dummy.conf", -1};
modsecurity::RuleMessage ruleMessage{rule, transaction};
return {op.evaluate(&transaction, &rule, t.input, ruleMessage), {}};
} }
static bool check(const UnitTestResult &result, const UnitTest &t) { static bool check(const UnitTestResult &result, const UnitTest &t) {
@ -89,9 +92,9 @@ struct TransformationTest {
return tfn; return tfn;
} }
static UnitTestResult eval(const ItemType &tfn, const UnitTest &t) { static UnitTestResult eval(const ItemType &tfn, const UnitTest &t, modsecurity::Transaction &transaction) {
std::string ret = t.input; auto ret = t.input;
tfn.transform(ret, nullptr); tfn.transform(ret, &transaction);
return {1, ret}; return {1, ret};
} }
@ -102,16 +105,16 @@ struct TransformationTest {
template<typename TestType> template<typename TestType>
UnitTestResult perform_unit_test_once(const UnitTest &t) { UnitTestResult perform_unit_test_once(const UnitTest &t, modsecurity::Transaction &transaction) {
std::unique_ptr<typename TestType::ItemType> item(TestType::init(t)); std::unique_ptr<typename TestType::ItemType> item(TestType::init(t));
assert(item.get() != nullptr); assert(item.get() != nullptr);
return TestType::eval(*item.get(), t); return TestType::eval(*item.get(), t, transaction);
} }
template<typename TestType> template<typename TestType>
UnitTestResult perform_unit_test_multithreaded(const UnitTest &t) { UnitTestResult perform_unit_test_multithreaded(const UnitTest &t, modsecurity::Transaction &transaction) {
constexpr auto NUM_THREADS = 50; constexpr auto NUM_THREADS = 50;
constexpr auto ITERATIONS = 5'000; constexpr auto ITERATIONS = 5'000;
@ -126,10 +129,10 @@ UnitTestResult perform_unit_test_multithreaded(const UnitTest &t) {
{ {
auto &result = results[i]; auto &result = results[i];
threads[i] = std::thread( threads[i] = std::thread(
[&item, &t, &result]() [&item, &t, &result, &transaction]()
{ {
for (auto j = 0; j != ITERATIONS; ++j) for (auto j = 0; j != ITERATIONS; ++j)
result = TestType::eval(*item.get(), t); result = TestType::eval(*item.get(), t, transaction);
}); });
} }
@ -150,12 +153,12 @@ UnitTestResult perform_unit_test_multithreaded(const UnitTest &t) {
template<typename TestType> template<typename TestType>
void perform_unit_test_helper(const ModSecurityTest<UnitTest> &test, UnitTest &t, void perform_unit_test_helper(const ModSecurityTest<UnitTest> &test, UnitTest &t,
ModSecurityTestResults<UnitTest> &res) { ModSecurityTestResults<UnitTest> &res, modsecurity::Transaction &transaction) {
if (!test.m_test_multithreaded) if (!test.m_test_multithreaded)
t.result = perform_unit_test_once<TestType>(t); t.result = perform_unit_test_once<TestType>(t, transaction);
else else
t.result = perform_unit_test_multithreaded<TestType>(t); t.result = perform_unit_test_multithreaded<TestType>(t, transaction);
if (TestType::check(t.result, t)) { if (TestType::check(t.result, t)) {
res.push_back(&t); res.push_back(&t);
@ -172,6 +175,11 @@ void perform_unit_test(const ModSecurityTest<UnitTest> &test, UnitTest &t,
ModSecurityTestResults<UnitTest> &res) { ModSecurityTestResults<UnitTest> &res) {
bool found = true; bool found = true;
modsecurity_test::ModSecurityTestContext context("ModSecurity-unit v0.0.1-alpha"
" (ModSecurity unit test utility)");
auto transaction = context.create_transaction();
if (test.m_automake_output) { if (test.m_automake_output) {
std::cout << ":test-result: "; std::cout << ":test-result: ";
} }
@ -190,9 +198,9 @@ void perform_unit_test(const ModSecurityTest<UnitTest> &test, UnitTest &t,
} }
if (t.type == "op") { if (t.type == "op") {
perform_unit_test_helper<OperatorTest>(test, t, res); perform_unit_test_helper<OperatorTest>(test, t, res, transaction);
} else if (t.type == "tfn") { } else if (t.type == "tfn") {
perform_unit_test_helper<TransformationTest>(test, t, res); perform_unit_test_helper<TransformationTest>(test, t, res, transaction);
} else { } else {
std::cerr << "Failed. Test type is unknown: << " << t.type; std::cerr << "Failed. Test type is unknown: << " << t.type;
std::cerr << std::endl; std::cerr << std::endl;
@ -242,8 +250,8 @@ int main(int argc, char **argv) {
} }
for (auto& [filename, tests] : test) { for (auto& [filename, tests] : test) {
total += tests->size(); total += tests.size();
for (auto t : *tests) { for (auto &t : tests) {
ModSecurityTestResults<UnitTest> r; ModSecurityTestResults<UnitTest> r;
if (!test.m_automake_output) { if (!test.m_automake_output) {
@ -303,12 +311,5 @@ int main(int argc, char **argv) {
} }
} }
for (auto a : test) {
auto vec = a.second;
for(auto t : *vec)
delete t;
delete vec;
}
return failed; return failed;
} }