From c7a78926ee60635e025f4a8e0ea2bc04e71a4db8 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Mon, 18 May 2020 15:08:17 -0300 Subject: [PATCH] actions: Compute the rule association during rules load --- CHANGES | 5 +- headers/modsecurity/actions/action.h | 3 +- headers/modsecurity/rule.h | 1 + headers/modsecurity/variable_value.h | 15 +- src/actions/action_with_run_time_string.h | 87 +++++++++++ src/actions/disruptive/redirect.cc | 2 +- src/actions/disruptive/redirect.h | 32 ++-- src/actions/init_col.cc | 2 +- src/actions/init_col.h | 30 ++-- src/actions/log_data.cc | 7 +- src/actions/log_data.h | 25 ++-- src/actions/msg.cc | 8 +- src/actions/msg.h | 24 +-- src/actions/set_env.cc | 7 +- src/actions/set_env.h | 25 ++-- src/actions/set_rsc.cc | 8 +- src/actions/set_rsc.h | 25 ++-- src/actions/set_sid.cc | 8 +- src/actions/set_sid.h | 25 ++-- src/actions/set_uid.cc | 8 +- src/actions/set_uid.h | 26 ++-- src/actions/set_var.cc | 19 ++- src/actions/set_var.h | 51 ++++++- src/actions/tag.cc | 8 +- src/actions/tag.h | 27 +++- src/actions/xmlns.h | 22 ++- src/modsecurity.cc | 1 + src/operators/inspect_file.cc | 4 +- src/operators/rx.cc | 14 +- src/operators/rx.h | 2 +- src/parser/seclang-parser.cc | 6 +- src/parser/seclang-parser.yy | 6 +- src/rule_with_actions.cc | 31 +++- src/rule_with_actions.h | 25 +++- src/rule_with_actions.h.rej | 15 ++ src/rule_with_operator.cc | 16 +- src/rule_with_operator.h | 10 +- src/run_time_string.cc | 30 ++-- src/run_time_string.h | 68 +++++++-- src/transaction.cc | 3 +- src/variables/duration.cc | 1 - src/variables/duration.h | 1 - src/variables/env.cc | 1 - src/variables/env.h | 1 - src/variables/global.h | 16 +- src/variables/highest_severity.cc | 1 - src/variables/highest_severity.h | 1 - src/variables/ip.h | 16 +- src/variables/modsec_build.cc | 1 - src/variables/modsec_build.h | 1 - src/variables/remote_user.cc | 1 - src/variables/remote_user.h | 1 - src/variables/resource.h | 16 +- src/variables/rule.h | 147 +++++++++++-------- src/variables/rule_variable.h | 60 ++++++++ src/variables/session.h | 15 +- src/variables/time.cc | 1 - src/variables/time.h | 1 - src/variables/time_day.cc | 1 - src/variables/time_day.h | 1 - src/variables/time_epoch.cc | 1 - src/variables/time_epoch.h | 1 - src/variables/time_hour.cc | 1 - src/variables/time_hour.h | 1 - src/variables/time_min.cc | 1 - src/variables/time_min.h | 1 - src/variables/time_mon.cc | 1 - src/variables/time_mon.h | 1 - src/variables/time_sec.cc | 1 - src/variables/time_sec.h | 1 - src/variables/time_wday.cc | 1 - src/variables/time_wday.h | 1 - src/variables/time_year.cc | 1 - src/variables/time_year.h | 1 - src/variables/tx.h | 16 +- src/variables/user.h | 16 +- src/variables/variable.h | 57 +++++-- src/variables/variable_with_runtime_string.h | 61 ++++++++ src/variables/web_app_id.h | 1 - src/variables/xml.cc | 20 ++- src/variables/xml.h | 44 ++++-- 81 files changed, 835 insertions(+), 409 deletions(-) create mode 100644 src/actions/action_with_run_time_string.h create mode 100644 src/rule_with_actions.h.rej create mode 100644 src/variables/rule_variable.h create mode 100644 src/variables/variable_with_runtime_string.h diff --git a/CHANGES b/CHANGES index b378e7d3..cb7f8249 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ v3.x.y - YYYY-MMM-DD (to be released) ------------------------------------- - + + - actions: Computes Rule association while loading the rules given a + performance boost on run time. + [@zimmerle] - Regression: Mark the test as failed in case of segfault. [@zimmerle] - Replaced t:lowerCase backend for a better performance. diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index fd728f66..b1b277ec 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -24,6 +24,7 @@ #include "modsecurity/intervention.h" #include "modsecurity/rule.h" + #ifndef HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #define HEADERS_MODSECURITY_ACTIONS_ACTION_H_ @@ -32,7 +33,7 @@ namespace modsecurity { class Transaction; class RuleWithActions; - +class RunTimeString; namespace actions { diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index f4d5eb47..fef3d14d 100644 --- a/headers/modsecurity/rule.h +++ b/headers/modsecurity/rule.h @@ -29,6 +29,7 @@ #include "modsecurity/modsecurity.h" #include "modsecurity/variable_value.h" + #ifdef __cplusplus namespace modsecurity { diff --git a/headers/modsecurity/variable_value.h b/headers/modsecurity/variable_value.h index a3e8f924..e632f1e6 100644 --- a/headers/modsecurity/variable_value.h +++ b/headers/modsecurity/variable_value.h @@ -70,8 +70,19 @@ class VariableValue { } } - VariableValue(const VariableValue &v) = delete; - + VariableValue(const VariableValue &o) : + m_collection(o.m_collection), + m_key(o.m_key), + m_keyWithCollection(o.m_keyWithCollection), + m_value(o.m_value) + { + for (auto &i : o.m_orign) { + std::unique_ptr origin(new VariableOrigin()); + origin->m_offset = i->m_offset; + origin->m_length = i->m_length; + m_orign.push_back(std::move(origin)); + } + } const std::string& getKey() const { return m_key; diff --git a/src/actions/action_with_run_time_string.h b/src/actions/action_with_run_time_string.h new file mode 100644 index 00000000..0c38a27a --- /dev/null +++ b/src/actions/action_with_run_time_string.h @@ -0,0 +1,87 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 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 "modsecurity/actions/action.h" +#include "src/run_time_string.h" + +#ifndef SRC_ACTIONS_ACTION_WITH_RUN_TIME_STRING_H_ +#define SRC_ACTIONS_ACTION_WITH_RUN_TIME_STRING_H_ + +namespace modsecurity { +namespace actions { + +class ActionWithRunTimeString : public Action { + public: + ActionWithRunTimeString( + const std::string &name, + int king, + std::unique_ptr string) + : Action(name, king), + m_string(std::move(string)) + { }; + + ActionWithRunTimeString(const std::string &name, + std::unique_ptr string) + : Action(name), + m_string(std::move(string)) + { }; + + ActionWithRunTimeString(const std::string &name, + int king) + : Action(name, king), + m_string(nullptr) + { }; + + ActionWithRunTimeString(const std::string &name) + : Action(name), + m_string(nullptr) + { }; + + ActionWithRunTimeString(const ActionWithRunTimeString &a) + : Action(a), + m_string(a.m_string?std::unique_ptr(new RunTimeString(*a.m_string.get())):nullptr) + { }; + + ActionWithRunTimeString& operator=(const ActionWithRunTimeString& a) + { + m_string = std::unique_ptr(new RunTimeString(*a.m_string.get())); + return *this; + } + + virtual void populate(RuleWithActions *rule) { + if (m_string) { + m_string->populate(rule); + } + } + + std::string getEvaluatedRunTimeString(Transaction *transaction) const noexcept { + return (m_string == nullptr)?"":m_string->evaluate(transaction); + } + + bool hasRunTimeString() const noexcept { + return m_string != nullptr; + } + + virtual ActionWithRunTimeString* clone() = 0; + + private: + std::unique_ptr m_string; +}; + + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_ACTION_WITH_RUN_TIME_STRING_H_ diff --git a/src/actions/disruptive/redirect.cc b/src/actions/disruptive/redirect.cc index e2a75c0d..92436938 100644 --- a/src/actions/disruptive/redirect.cc +++ b/src/actions/disruptive/redirect.cc @@ -35,7 +35,7 @@ bool Redirect::init(std::string *error) { bool Redirect::execute(RuleWithActions *rule, Transaction *transaction) { - std::string m_urlExpanded(m_string->evaluate(transaction)); + std::string m_urlExpanded(getEvaluatedRunTimeString(transaction)); /* if it was changed before, lets keep it. */ if (transaction->m_it.status == 200 || (!(transaction->m_it.status <= 307 && transaction->m_it.status >= 301))) { diff --git a/src/actions/disruptive/redirect.h b/src/actions/disruptive/redirect.h index 6ffd495d..e0cceda8 100644 --- a/src/actions/disruptive/redirect.h +++ b/src/actions/disruptive/redirect.h @@ -19,7 +19,7 @@ #include "modsecurity/actions/action.h" #include "modsecurity/rule_message.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_DISRUPTIVE_REDIRECT_H_ #define SRC_ACTIONS_DISRUPTIVE_REDIRECT_H_ @@ -34,25 +34,33 @@ namespace actions { namespace disruptive { -class Redirect : public Action { +class Redirect : public ActionWithRunTimeString { public: - explicit Redirect(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_status(0), - m_string(nullptr) { } + explicit Redirect(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "redirert", + RunTimeOnlyIfMatchKind, + std::move(runTimeString)), + m_status(0) + { }; - explicit Redirect(std::unique_ptr z) - : Action("redirert", RunTimeOnlyIfMatchKind), - m_status(0), - m_string(std::move(z)) { } + explicit Redirect(const Redirect &action) + : ActionWithRunTimeString(action), + m_status(action.m_status) + { }; + + bool init(std::string *error) override; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + bool isDisruptive() override { return true; } + virtual ActionWithRunTimeString *clone() override { + return new Redirect(*this); + } + private: int m_status; - std::unique_ptr m_string; }; diff --git a/src/actions/init_col.cc b/src/actions/init_col.cc index 4ac9dece..f3d6e536 100644 --- a/src/actions/init_col.cc +++ b/src/actions/init_col.cc @@ -55,7 +55,7 @@ bool InitCol::init(std::string *error) { bool InitCol::execute(RuleWithActions *rule, Transaction *t) { - std::string collectionName(m_string->evaluate(t)); + std::string collectionName(getEvaluatedRunTimeString(t)); if (m_collection_key == "ip") { t->m_collections.m_ip_collection_key = collectionName; diff --git a/src/actions/init_col.h b/src/actions/init_col.h index 012baa7a..dacdd3af 100644 --- a/src/actions/init_col.h +++ b/src/actions/init_col.h @@ -18,31 +18,43 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_INIT_COL_H_ #define SRC_ACTIONS_INIT_COL_H_ -class Transaction; namespace modsecurity { class Transaction; namespace actions { -class InitCol : public Action { +class InitCol : public ActionWithRunTimeString { public: - explicit InitCol(const std::string &action) : Action(action) { } + InitCol( + const std::string &action, + std::unique_ptr runTimeString + ) : ActionWithRunTimeString( + action, + std::move(runTimeString) + ) + { }; - InitCol(const std::string &action, std::unique_ptr z) - : Action(action, RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + InitCol(const InitCol &action) + : ActionWithRunTimeString(action), + m_collection_key(action.m_collection_key) + { }; + + bool init(std::string *error) override; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + + virtual ActionWithRunTimeString *clone() override { + return new InitCol(*this); + } + private: std::string m_collection_key; - std::shared_ptr m_string; }; diff --git a/src/actions/log_data.cc b/src/actions/log_data.cc index d4a52e43..20ea7e32 100644 --- a/src/actions/log_data.cc +++ b/src/actions/log_data.cc @@ -30,16 +30,11 @@ namespace actions { bool LogData::execute(RuleWithActions *rule, Transaction *transaction) { - transaction->messageGetLast()->m_data = data(transaction); + transaction->messageGetLast()->m_data = getEvaluatedRunTimeString(transaction); return true; } -std::string LogData::data(Transaction *transaction) { - std::string a(m_string->evaluate(transaction)); - return a; -} - } // namespace actions } // namespace modsecurity diff --git a/src/actions/log_data.h b/src/actions/log_data.h index 175d780c..f55c4f82 100644 --- a/src/actions/log_data.h +++ b/src/actions/log_data.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_LOG_DATA_H_ #define SRC_ACTIONS_LOG_DATA_H_ @@ -30,20 +30,25 @@ class Transaction; namespace actions { -class LogData : public Action { +class LogData : public ActionWithRunTimeString { public: - explicit LogData(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit LogData(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "logdata", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit LogData(std::unique_ptr z) - : Action("logdata", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit LogData(const LogData &data) + : ActionWithRunTimeString(data) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - std::string data(Transaction *Transaction); - - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new LogData(*this); + } }; diff --git a/src/actions/msg.cc b/src/actions/msg.cc index aae342b3..34d832dc 100644 --- a/src/actions/msg.cc +++ b/src/actions/msg.cc @@ -47,7 +47,7 @@ namespace actions { bool Msg::execute(RuleWithActions *rule, Transaction *transaction) { - std::string msg = data(transaction); + std::string msg = getEvaluatedRunTimeString(transaction); transaction->messageGetLast()->m_message = msg; ms_dbg_a(transaction, 9, "Saving msg: " + msg); @@ -55,11 +55,5 @@ bool Msg::execute(RuleWithActions *rule, Transaction *transaction) { } -std::string Msg::data(Transaction *t) { - std::string a(m_string->evaluate(t)); - return a; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/msg.h b/src/actions/msg.h index 3aecdb42..c9b6b12b 100644 --- a/src/actions/msg.h +++ b/src/actions/msg.h @@ -19,7 +19,7 @@ #include "modsecurity/actions/action.h" #include "modsecurity/rule_message.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_MSG_H_ #define SRC_ACTIONS_MSG_H_ @@ -31,19 +31,25 @@ class Transaction; namespace actions { -class Msg : public Action { +class Msg : public ActionWithRunTimeString { public: - explicit Msg(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit Msg(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "msg", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit Msg(std::unique_ptr z) - : Action("msg", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit Msg(const Msg &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - std::string data(Transaction *Transaction); - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new Msg(*this); + } }; diff --git a/src/actions/set_env.cc b/src/actions/set_env.cc index 0079c68d..a96b6ec7 100644 --- a/src/actions/set_env.cc +++ b/src/actions/set_env.cc @@ -28,13 +28,8 @@ namespace modsecurity { namespace actions { -bool SetENV::init(std::string *error) { - return true; -} - - bool SetENV::execute(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "Setting envoriment variable: " + colNameExpanded + "."); diff --git a/src/actions/set_env.h b/src/actions/set_env.h index 72f3848e..0fa1399e 100644 --- a/src/actions/set_env.h +++ b/src/actions/set_env.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_SET_ENV_H_ #define SRC_ACTIONS_SET_ENV_H_ @@ -30,20 +30,25 @@ class Transaction; namespace actions { -class SetENV : public Action { +class SetENV : public ActionWithRunTimeString { public: - explicit SetENV(const std::string &_action) - : Action(_action) { } + explicit SetENV(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "setenv", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit SetENV(std::unique_ptr z) - : Action("setenv", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetENV(const SetENV &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; - private: - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new SetENV(*this); + } }; diff --git a/src/actions/set_rsc.cc b/src/actions/set_rsc.cc index 6977a6db..e34e2c72 100644 --- a/src/actions/set_rsc.cc +++ b/src/actions/set_rsc.cc @@ -26,13 +26,8 @@ namespace modsecurity { namespace actions { -bool SetRSC::init(std::string *error) { - return true; -} - - bool SetRSC::execute(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "RESOURCE initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +37,6 @@ bool SetRSC::execute(RuleWithActions *rule, Transaction *t) { return true; } + } // namespace actions } // namespace modsecurity diff --git a/src/actions/set_rsc.h b/src/actions/set_rsc.h index 44cb4bfe..66a5f535 100644 --- a/src/actions/set_rsc.h +++ b/src/actions/set_rsc.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_SET_RSC_H_ #define SRC_ACTIONS_SET_RSC_H_ @@ -30,20 +30,25 @@ class Transaction; namespace actions { -class SetRSC : public Action { +class SetRSC : public ActionWithRunTimeString { public: - explicit SetRSC(const std::string &_action) - : Action(_action) { } + explicit SetRSC(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "setsrc", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit SetRSC(std::unique_ptr z) - : Action("setsrc", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetRSC(const SetRSC &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; - private: - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new SetRSC(*this); + } }; diff --git a/src/actions/set_sid.cc b/src/actions/set_sid.cc index f6da9cc8..9359ebcd 100644 --- a/src/actions/set_sid.cc +++ b/src/actions/set_sid.cc @@ -26,13 +26,8 @@ namespace modsecurity { namespace actions { -bool SetSID::init(std::string *error) { - return true; -} - - bool SetSID::execute(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "Session ID initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +37,6 @@ bool SetSID::execute(RuleWithActions *rule, Transaction *t) { return true; } + } // namespace actions } // namespace modsecurity diff --git a/src/actions/set_sid.h b/src/actions/set_sid.h index 41a2b652..71305e90 100644 --- a/src/actions/set_sid.h +++ b/src/actions/set_sid.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_SET_SID_H_ #define SRC_ACTIONS_SET_SID_H_ @@ -30,20 +30,25 @@ class Transaction; namespace actions { -class SetSID : public Action { +class SetSID : public ActionWithRunTimeString { public: - explicit SetSID(const std::string &_action) - : Action(_action) { } + explicit SetSID(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "setsid", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit SetSID(std::unique_ptr z) - : Action("setsid", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + SetSID(const SetSID &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; - private: - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new SetSID(*this); + } }; diff --git a/src/actions/set_uid.cc b/src/actions/set_uid.cc index dd89d1d7..1c60ab49 100644 --- a/src/actions/set_uid.cc +++ b/src/actions/set_uid.cc @@ -26,13 +26,8 @@ namespace modsecurity { namespace actions { -bool SetUID::init(std::string *error) { - return true; -} - - bool SetUID::execute(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "User collection initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +37,6 @@ bool SetUID::execute(RuleWithActions *rule, Transaction *t) { return true; } + } // namespace actions } // namespace modsecurity diff --git a/src/actions/set_uid.h b/src/actions/set_uid.h index bb5959b0..0191e5ff 100644 --- a/src/actions/set_uid.h +++ b/src/actions/set_uid.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_SET_UID_H_ #define SRC_ACTIONS_SET_UID_H_ @@ -30,20 +30,26 @@ class Transaction; namespace actions { -class SetUID : public Action { +class SetUID : public ActionWithRunTimeString { public: - explicit SetUID(const std::string &_action) - : Action(_action) { } + explicit SetUID(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "setuid", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - explicit SetUID(std::unique_ptr z) - : Action("setuid", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetUID(const SetUID &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; - private: - std::shared_ptr m_string; + virtual ActionWithRunTimeString *clone() override { + return new SetUID(*this); + } + }; diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 5c289d98..1fc6c084 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -46,8 +46,8 @@ bool SetVar::execute(RuleWithActions *rule, Transaction *t) { std::string targetValue; std::string resolvedPre; - if (m_string) { - resolvedPre = m_string->evaluate(t, rule); + if (hasRunTimeString()) { + resolvedPre = getEvaluatedRunTimeString(t); } std::string m_variableNameExpanded; @@ -66,17 +66,17 @@ bool SetVar::execute(RuleWithActions *rule, Transaction *t) { variables::User_DynamicElement *user = dynamic_cast< variables::User_DynamicElement *> (v); if (tx) { - m_variableNameExpanded = tx->m_string->evaluate(t, rule); + m_variableNameExpanded = tx->evaluateRunTimeString(t); } else if (session) { - m_variableNameExpanded = session->m_string->evaluate(t, rule); + m_variableNameExpanded = session->evaluateRunTimeString(t); } else if (ip) { - m_variableNameExpanded = ip->m_string->evaluate(t, rule); + m_variableNameExpanded = ip->evaluateRunTimeString(t); } else if (resource) { - m_variableNameExpanded = resource->m_string->evaluate(t, rule); + m_variableNameExpanded = resource->evaluateRunTimeString(t); } else if (global) { - m_variableNameExpanded = global->m_string->evaluate(t, rule); + m_variableNameExpanded = global->evaluateRunTimeString(t); } else if (user) { - m_variableNameExpanded = user->m_string->evaluate(t, rule); + m_variableNameExpanded = user->evaluateRunTimeString(t); } else { m_variableNameExpanded = m_variable->m_name; } @@ -114,8 +114,7 @@ bool SetVar::execute(RuleWithActions *rule, Transaction *t) { try { std::vector l; - RuleWithOperator *rr = dynamic_cast(rule); - m_variable->evaluate(t, rr, &l); + m_variable->evaluate(t, &l); if (l.size() == 0) { value = 0; } else { diff --git a/src/actions/set_var.h b/src/actions/set_var.h index 303ebeb7..40f2b2b6 100644 --- a/src/actions/set_var.h +++ b/src/actions/set_var.h @@ -18,7 +18,8 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" #ifndef SRC_ACTIONS_SET_VAR_H_ #define SRC_ACTIONS_SET_VAR_H_ @@ -42,29 +43,63 @@ enum SetVarOperation { unsetOperation, }; -class SetVar : public Action { +class SetVar : public ActionWithRunTimeString { public: SetVar(SetVarOperation operation, std::unique_ptr variable, std::unique_ptr predicate) - : Action("setvar"), + : ActionWithRunTimeString("setvar", std::move(predicate)), m_operation(operation), - m_variable(std::move(variable)), - m_string(std::move(predicate)) { } + m_variable(std::move(variable)) + { }; + SetVar(SetVarOperation operation, std::unique_ptr variable) - : Action("setvar"), + : ActionWithRunTimeString("setvar"), m_operation(operation), - m_variable(std::move(variable)) { } + m_variable(std::move(variable)) + { }; + + + SetVar(const SetVar &var) + : ActionWithRunTimeString(var), + m_operation(var.m_operation), + m_variable(var.m_variable) + { + variables::RuleVariable *rv = dynamic_cast(m_variable.get()); + if (rv != nullptr) { + auto nrv = rv->clone(); + rv = dynamic_cast(nrv); + rv->populate(nullptr); + m_variable = std::unique_ptr(nrv); + } + }; + + bool execute(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + void populate(RuleWithActions *rule) override { + ActionWithRunTimeString::populate(rule); + variables::RuleVariable *rulev = dynamic_cast(m_variable.get()); + if (rulev != nullptr) { + rulev->populate(rule); + } + variables::VariableWithRunTimeString *rulev2 = dynamic_cast(m_variable.get()); + if (rulev2 != nullptr) { + rulev2->populate(rule); + } + } + + virtual ActionWithRunTimeString *clone() override { + return new SetVar(*this); + } + private: SetVarOperation m_operation; std::shared_ptr m_variable; - std::shared_ptr m_string; }; } // namespace actions diff --git a/src/actions/tag.cc b/src/actions/tag.cc index 2bf0d46d..4ae4a6ed 100644 --- a/src/actions/tag.cc +++ b/src/actions/tag.cc @@ -50,14 +50,8 @@ namespace modsecurity { namespace actions { -std::string Tag::getName(Transaction *transaction) { - std::string tag(m_string->evaluate(transaction)); - return tag; -} - - bool Tag::execute(RuleWithActions *rule, Transaction *transaction) { - std::string tag = getName(transaction); + std::string tag = getTagName(transaction); ms_dbg_a(transaction, 9, "Rule tag: " + tag); transaction->messageGetLast()->m_tags.push_back(tag); diff --git a/src/actions/tag.h b/src/actions/tag.h index c976ebc0..d41857c3 100644 --- a/src/actions/tag.h +++ b/src/actions/tag.h @@ -18,7 +18,7 @@ #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" #ifndef SRC_ACTIONS_TAG_H_ #define SRC_ACTIONS_TAG_H_ @@ -30,18 +30,29 @@ class Transaction; namespace actions { -class Tag : public Action { +class Tag : public ActionWithRunTimeString { public: - explicit Tag(std::unique_ptr z) - : Action("tag", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit Tag(std::unique_ptr runTimeString) + : ActionWithRunTimeString( + "tag", + RunTimeOnlyIfMatchKind, + std::move(runTimeString) + ) + { }; - std::string getName(Transaction *transaction); + explicit Tag(const Tag &action) + : ActionWithRunTimeString(action) + { }; bool execute(RuleWithActions *rule, Transaction *transaction) override; - protected: - std::shared_ptr m_string; + inline std::string getTagName(Transaction *transaction) const { + return getEvaluatedRunTimeString(transaction); + } + + virtual ActionWithRunTimeString *clone() override { + return new Tag(*this); + } }; diff --git a/src/actions/xmlns.h b/src/actions/xmlns.h index d401cf0f..9dae3347 100644 --- a/src/actions/xmlns.h +++ b/src/actions/xmlns.h @@ -29,7 +29,18 @@ namespace actions { class XmlNS : public Action { public: - explicit XmlNS(const std::string &action) : Action(action) { } + explicit XmlNS(const std::string &action) + : Action(action), + m_scope(""), + m_href("") + { }; + + XmlNS(const XmlNS &o) + : Action(o), + m_scope(o.m_scope), + m_href(o.m_href) + { }; + bool execute(RuleWithActions *rule, Transaction *transaction) override { return true; @@ -37,6 +48,15 @@ class XmlNS : public Action { bool init(std::string *error) override; + std::string getScope() const { + return m_scope; + } + + std::string getHref() const { + return m_href; + } + + private: std::string m_scope; std::string m_href; }; diff --git a/src/modsecurity.cc b/src/modsecurity.cc index 2f70d470..fd564524 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -212,6 +212,7 @@ void ModSecurity::serverLog(void *data, RuleMessage *rm) { m_logCb(data, a); return; } + m_logCb(data, a); return; } diff --git a/src/operators/inspect_file.cc b/src/operators/inspect_file.cc index 9346ec0a..e89ae0a7 100644 --- a/src/operators/inspect_file.cc +++ b/src/operators/inspect_file.cc @@ -54,7 +54,7 @@ bool InspectFile::evaluate(Transaction *transaction, const bpstd::string_view &str, RuleMessage *ruleMessage) { if (m_isScript) { - return m_lua.run(transaction, str.c_str()); + return m_lua.run(transaction, str.to_string()); } else { FILE *in; char buff[512]; @@ -64,7 +64,7 @@ bool InspectFile::evaluate(Transaction *transaction, openstr.append(m_param); openstr.append(" "); - openstr.append(str.c_str()); + openstr.append(str.to_string()); if (!(in = popen(openstr.c_str(), "r"))) { return false; } diff --git a/src/operators/rx.cc b/src/operators/rx.cc index 7df9886e..e74ccff4 100644 --- a/src/operators/rx.cc +++ b/src/operators/rx.cc @@ -30,7 +30,7 @@ namespace operators { bool Rx::init(const std::string &file, std::string *error) { - if (m_string->m_containsMacro == false) { + if (m_string->containsMacro() == false) { m_re = new Regex(m_param); } @@ -44,11 +44,11 @@ bool Rx::evaluate(Transaction *transaction, RuleMessage *ruleMessage) { Regex *re; - if (m_param.empty() && !m_string->m_containsMacro) { + if (m_param.empty() && !m_string->containsMacro()) { return true; } - if (m_string->m_containsMacro) { + if (m_string->containsMacro()) { std::string eparam(m_string->evaluate(transaction)); re = new Regex(eparam); } else { @@ -73,12 +73,12 @@ bool Rx::evaluate(Transaction *transaction, logOffset(ruleMessage, capture.m_offset, capture.m_length); } - if (!captures.empty()) { - return true; + if (m_string->containsMacro()) { + delete re; } - if (m_string->m_containsMacro) { - delete re; + if (!captures.empty()) { + return true; } return false; diff --git a/src/operators/rx.h b/src/operators/rx.h index 0ef05c83..7420968a 100644 --- a/src/operators/rx.h +++ b/src/operators/rx.h @@ -43,7 +43,7 @@ class Rx : public Operator { } ~Rx() { - if (m_string->m_containsMacro == false && m_re != NULL) { + if (m_string->containsMacro() == false && m_re != NULL) { delete m_re; m_re = NULL; } diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc index cc8dfc3a..9e174d81 100644 --- a/src/parser/seclang-parser.cc +++ b/src/parser/seclang-parser.cc @@ -3800,7 +3800,7 @@ namespace yy { case 216: #line 2089 "seclang-parser.yy" { - VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); + VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_WithNSPath(yystack_[0].value.as < std::string > ())); } #line 3806 "seclang-parser.cc" break; @@ -3808,7 +3808,7 @@ namespace yy { case 217: #line 2093 "seclang-parser.yy" { - VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); + VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_WithNSPath(yystack_[0].value.as < std::string > ())); } #line 3814 "seclang-parser.cc" break; @@ -3816,7 +3816,7 @@ namespace yy { case 218: #line 2097 "seclang-parser.yy" { - VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_NoDictElement()); + VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_WithoutNSPath()); } #line 3822 "seclang-parser.cc" break; diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 805c7ea1..c3e1bbea 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -2087,15 +2087,15 @@ var: } | RUN_TIME_VAR_XML DICT_ELEMENT { - VARIABLE_CONTAINER($$, new variables::XML("XML:" + $2)); + VARIABLE_CONTAINER($$, new variables::XML_WithNSPath($2)); } | RUN_TIME_VAR_XML DICT_ELEMENT_REGEXP { - VARIABLE_CONTAINER($$, new variables::XML("XML:" + $2)); + VARIABLE_CONTAINER($$, new variables::XML_WithNSPath($2)); } | RUN_TIME_VAR_XML { - VARIABLE_CONTAINER($$, new variables::XML_NoDictElement()); + VARIABLE_CONTAINER($$, new variables::XML_WithoutNSPath()); } | VARIABLE_FILES_TMP_NAMES DICT_ELEMENT { diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 79634968..b98e2346 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -46,6 +46,7 @@ #include "src/actions/transformations/transformation.h" #include "src/actions/xmlns.h" #include "src/utils/string.h" +#include "src/actions/action_with_run_time_string.h" namespace modsecurity { @@ -104,6 +105,14 @@ RuleWithActions::RuleWithActions( } void RuleWithActions::addDefaultAction(std::shared_ptr a) { + + actions::ActionWithRunTimeString *arts = dynamic_cast(a.get()); + if (arts != nullptr) { + a = std::unique_ptr(arts->clone()); + arts = dynamic_cast(a.get()); + arts->populate(this); + } + if (a->m_actionKind == Action::ConfigurationKind) { if (dynamic_cast(a.get())) { actions::Accuracy *accuracy = dynamic_cast(a.get()); @@ -133,7 +142,8 @@ void RuleWithActions::addDefaultAction(std::shared_ptr a) { } else if (dynamic_cast(a.get())) { m_defaultActionMsg = std::static_pointer_cast(a); } else if (dynamic_cast(a.get())) { - m_defaultActionActionsSetVar.push_back(std::static_pointer_cast(a)); + actions::SetVar *var = dynamic_cast(a.get()); + m_actionsSetVar.push_back(std::unique_ptr(var)); } else if (dynamic_cast(a.get())) { m_defaultActionActionsTag.push_back(std::static_pointer_cast(a)); } else if (dynamic_cast(a.get())) { @@ -158,6 +168,13 @@ void RuleWithActions::addDefaultAction(std::shared_ptr a) { } void RuleWithActions::addAction(actions::Action *a) { + actions::ActionWithRunTimeString *arts = dynamic_cast(a); + if (arts != nullptr) { + a = arts->clone(); + arts = dynamic_cast(a); + arts->populate(this); + } + if (a->m_actionKind == Action::ConfigurationKind) { if (dynamic_cast(a)) { actions::Accuracy *accuracy = dynamic_cast(a); @@ -188,7 +205,8 @@ void RuleWithActions::addAction(actions::Action *a) { } else if (dynamic_cast(a)) { m_msg = std::unique_ptr(dynamic_cast(a)); } else if (dynamic_cast(a)) { - m_actionsSetVar.push_back(std::unique_ptr(dynamic_cast(a))); + actions::SetVar *var = dynamic_cast(a); + m_actionsSetVar.push_back(std::unique_ptr(var)); } else if (dynamic_cast(a)) { actions::Maturity *maturity = dynamic_cast(a); m_maturity = maturity->getMaturity(); @@ -460,7 +478,7 @@ void RuleWithActions::executeTransformation( bool RuleWithActions::containsTag(const std::string& name, Transaction *t) const { for (auto &tag : getTagsAction()) { - if (tag != NULL && tag->getName(t) == name) { + if (tag != NULL && tag->getTagName(t) == name) { return true; } } @@ -469,13 +487,12 @@ bool RuleWithActions::containsTag(const std::string& name, Transaction *t) const bool RuleWithActions::containsMsg(const std::string& name, Transaction *t) { - return m_msg && m_msg->data(t) == name; + return m_msg && m_msg->getEvaluatedRunTimeString(t) == name; } -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::getLogData(Transaction *t) const { return m_logData->getEvaluatedRunTimeString(t); } +std::string RuleWithActions::getMessage(Transaction *t) const { return m_msg->getEvaluatedRunTimeString(t); } } // namespace modsecurity diff --git a/src/rule_with_actions.h b/src/rule_with_actions.h index d9489670..a890d579 100644 --- a/src/rule_with_actions.h +++ b/src/rule_with_actions.h @@ -155,7 +155,9 @@ class RuleWithActions : public Rule { m_defaultContainsNoLogAction(r.m_defaultContainsNoLogAction), m_defaultContainsMultiMatchAction(r.m_defaultContainsMultiMatchAction), m_defaultContainsStaticBlockAction(r.m_defaultContainsStaticBlockAction), - m_isChained(r.m_isChained) { }; + m_isChained(r.m_isChained) { + // TODO: Verify if it is necessary to process any other copy. + }; RuleWithActions &operator=(const RuleWithActions& r) { Rule::operator = (r); @@ -199,6 +201,7 @@ class RuleWithActions : public Rule { m_defaultContainsStaticBlockAction = r.m_defaultContainsStaticBlockAction; m_isChained = r.m_isChained; return *this; + // TODO: Verify if it is necessary to process any other copy. } @@ -358,13 +361,13 @@ class RuleWithActions : public Rule { inline bool hasLogDataAction() const { return m_logData != nullptr || m_defaultActionLogData != nullptr; } inline std::shared_ptr getLogDataAction() const { return m_logData; } - std::string getLogData(/*const */Transaction *t); + std::string getLogData(/*const */Transaction *t) const; inline void setLogDataAction(const std::shared_ptr &data) { m_logData = data; } inline bool hasMessageAction() const { return m_msg != nullptr || m_defaultActionMsg != nullptr; } inline std::shared_ptr getMessageAction() const { return m_msg; } inline void setMessageAction(const std::shared_ptr &msg) { m_msg = msg; } - std::string getMessage(/*const */Transaction *t); + std::string getMessage(/*const */Transaction *t) const; inline bool hasSeverityAction() const { return m_severity != SEVERITY_NOT_SET || m_defaultSeverity != SEVERITY_NOT_SET; } @@ -373,19 +376,19 @@ class RuleWithActions : public Rule { inline void setSeverity(unsigned int severity) { m_severity = severity; } inline bool hasRevisionAction() const { return m_revision != ""; } - inline std::string getRevision() const { return m_revision; }; + inline const std::string getRevision() const { return m_revision; }; inline void setRevision(const std::string &revision) { m_revision.assign(revision); } inline bool hasVersionAction() const { return m_version != ""; } - inline std::string getVersion() const { return m_version; }; + inline const std::string getVersion() const { return m_version; }; inline void setVersion(const std::string &version) { m_version.assign(version); } inline bool hasAccuracyAction() const { return m_accuracy != ACCURACY_NOT_SET || m_defaultAccuracy != ACCURACY_NOT_SET; } - inline int getAccuracy() const { return m_accuracy; } + inline const int getAccuracy() const { return m_accuracy; } inline void setAccuracy(unsigned int accuracy) { m_accuracy = accuracy; } inline bool hasMaturityAction() const { return m_maturity != MATURITY_NOT_SET || m_defaultMaturity != MATURITY_NOT_SET; } - inline int getMaturity() const { return m_maturity; } + inline const int getMaturity() const { return m_maturity; } inline void setDefaultActionMaturity(unsigned int maturity) { m_defaultMaturity = maturity; } inline void setMaturity(unsigned int maturity) { m_maturity = maturity; } @@ -441,6 +444,14 @@ class RuleWithActions : public Rule { return m_chainedRuleParent; } + XmlNSs getXmlNSs() const { + XmlNSs dst; + for (auto &a : m_XmlNSs) { + dst.push_back(a); + } + return dst; + } + XmlNSsPtr getXmlNSsPtr() const { /** * FIXME: this is not conteplating SecRuleUpdateActionBy* yet. diff --git a/src/rule_with_actions.h.rej b/src/rule_with_actions.h.rej new file mode 100644 index 00000000..a490a2f0 --- /dev/null +++ b/src/rule_with_actions.h.rej @@ -0,0 +1,15 @@ +--- src/rule_with_actions.h ++++ src/rule_with_actions.h +@@ -520,11 +528,10 @@ class RuleWithActions : public Rule { + for (auto &a : m_XmlNSs) { + dst.push_back(a.get()); + } +- ++ + return dst; + } + +- + virtual void dump(std::stringstream &out) const override { + out << "RuleWithActions" << std::endl; + } diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 7cc6bbad..a8ac21ff 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -40,10 +40,12 @@ #include "src/actions/set_var.h" #include "src/actions/block.h" #include "src/variables/variable.h" +#include "src/variables/rule.h" #include "src/rule_with_operator.h" #include "modsecurity/string_view.hpp" + namespace modsecurity { using operators::Operator; @@ -60,7 +62,14 @@ RuleWithOperator::RuleWithOperator(Operator *op, int lineNumber) : RuleWithActions(actions, transformations, std::move(fileName), lineNumber), m_variables(std::unique_ptr(_variables)), - m_operator(std::unique_ptr(op)) { /* */ } + m_operator(std::unique_ptr(op)) { + for (auto &a : *m_variables.get()) { + variables::RuleVariable *vrule = dynamic_cast(a); + if (vrule != nullptr) { + vrule->populate(this); + } + } + } @@ -247,8 +256,7 @@ bool RuleWithOperator::evaluate(Transaction *trans) { + " against " \ + variables + "."); } else { - ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId() -) \ + ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \ + ") Executing operator \"" + getOperatorName() \ + " against " \ + variables + "."); @@ -262,7 +270,7 @@ bool RuleWithOperator::evaluate(Transaction *trans) { if (!var) { continue; } - var->evaluate(trans, this, &e); + var->evaluate(trans, &e); for (const VariableValue *v : e) { TransformationsResults transformationsResults; const std::string &value = v->getValue(); diff --git a/src/rule_with_operator.h b/src/rule_with_operator.h index d194de2b..1fd0fd6c 100644 --- a/src/rule_with_operator.h +++ b/src/rule_with_operator.h @@ -51,7 +51,15 @@ class RuleWithOperator : public RuleWithActions { RuleWithOperator(const RuleWithOperator &op) : RuleWithActions(op), m_variables(op.m_variables), - m_operator(op.m_operator) { }; + m_operator(op.m_operator) + { + for (auto &a : *m_variables.get()) { + variables::RuleVariable *vrule = dynamic_cast(a); + if (vrule != nullptr) { + vrule->populate(this); + } + } + }; RuleWithOperator &operator=(const RuleWithOperator& r) { RuleWithActions::operator = (r); diff --git a/src/run_time_string.cc b/src/run_time_string.cc index 2c433cff..3a95c7dc 100644 --- a/src/run_time_string.cc +++ b/src/run_time_string.cc @@ -41,36 +41,30 @@ void RunTimeString::appendText(const std::string &text) { void RunTimeString::appendVar( std::unique_ptr var) { std::unique_ptr r(new RunTimeElementHolder); - r->m_var = std::move(var); + r->m_variable = std::move(var); m_elements.push_back(std::move(r)); m_containsMacro = true; } -std::string RunTimeString::evaluate(Transaction *t) { - return evaluate(t, NULL); -} - - -std::string RunTimeString::evaluate(Transaction *t, Rule *r) { - std::string s; - for (auto &z : m_elements) { - if (z->m_string.size() > 0) { - s.append(z->m_string); - } else if (z->m_var != NULL && t != NULL) { +std::string RunTimeString::evaluate(Transaction *transaction) { + std::string retString; + // FIXME: Educated guess the size of retString based on the size of the elements. + for (auto &element : m_elements) { + if (element->m_string.size() > 0) { + retString.append(element->m_string); + } else if (element->m_variable != nullptr && transaction != nullptr) { std::vector l; - // FIXME: This cast should be removed. - RuleWithOperator *rr = dynamic_cast(r); - z->m_var->evaluate(t, rr, &l); - if (l.size() > 0) { - s.append(l[0]->getValue()); + element->m_variable->evaluate(transaction, &l); + if (!l.empty()) { + retString.append(l[0]->getValue()); } for (auto &i : l) { delete i; } } } - return s; + return retString; } } // namespace modsecurity diff --git a/src/run_time_string.h b/src/run_time_string.h index 85b02dd0..c6109a9e 100644 --- a/src/run_time_string.h +++ b/src/run_time_string.h @@ -25,6 +25,7 @@ #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/variables/variable.h" +#include "src/variables/rule_variable.h" #ifndef SRC_RUN_TIME_STRING_H_ @@ -34,29 +35,72 @@ namespace modsecurity { class RunTimeElementHolder { public: - RunTimeElementHolder() : - m_string("") { - m_var.reset(NULL); - } - std::unique_ptr m_var; + RunTimeElementHolder() + : m_string(""), + m_variable(nullptr) + { }; + + + RunTimeElementHolder(const RunTimeElementHolder &other) + : m_string(other.m_string), + m_variable(other.m_variable) { + variables::RuleVariable *rv = dynamic_cast(m_variable.get()); + if (rv != nullptr) { + auto nrv = rv->clone(); + rv = dynamic_cast(nrv); + rv->populate(nullptr); + m_variable = std::unique_ptr(nrv); + } + }; + + /* protected: */ std::string m_string; + std::shared_ptr m_variable; }; class RunTimeString { public: - RunTimeString() : - m_containsMacro(false) { } + RunTimeString() + : m_containsMacro(false), + m_elements() + { }; + + + RunTimeString(const RunTimeString &other) + : m_containsMacro(other.m_containsMacro), + m_elements() + { + for (auto &m : other.m_elements) { + m_elements.push_back(std::unique_ptr(new RunTimeElementHolder(*m.get()))); + } + }; + + void appendText(const std::string &text); void appendVar(std::unique_ptr var); + + std::string evaluate(Transaction *t); - std::string evaluate(Transaction *t, Rule *r); - std::string evaluate() { + + inline std::string evaluate() { return evaluate(NULL); } - inline bool containsMacro() const { return m_containsMacro; } - bool m_containsMacro; - protected: + + inline bool containsMacro() const { return m_containsMacro; } + + + void populate(RuleWithActions *rule) { + for (auto &a : m_elements) { + modsecurity::variables::RuleVariable *vrule = dynamic_cast(a->m_variable.get()); + if (vrule != nullptr) { + vrule->populate(rule); + } + } + } + + private: + bool m_containsMacro; std::list> m_elements; }; diff --git a/src/transaction.cc b/src/transaction.cc index 4cfd70e9..eea5ff00 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -344,7 +344,6 @@ int Transaction::processConnection(const char *client, int cPort, ms_dbg(4, "Transaction context created."); ms_dbg(4, "Starting phase CONNECTION. (SecRules 0)"); - m_variableRemoteHost.set(*m_clientIpAddress.get(), m_variableOffset); m_variableUniqueID.set(*m_id.get(), m_variableOffset); m_variableRemoteAddr.set(*m_clientIpAddress.get(), m_variableOffset); @@ -1495,7 +1494,7 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, /** TODO: Check variable */ variables::RemoteUser *r = new variables::RemoteUser("REMOTE_USER"); std::vector l; - r->evaluate(this, NULL, &l); + r->evaluate(this, &l); delete r; ss << utils::string::dash_if_empty( diff --git a/src/variables/duration.cc b/src/variables/duration.cc index b60db675..cfbf98c9 100644 --- a/src/variables/duration.cc +++ b/src/variables/duration.cc @@ -28,7 +28,6 @@ namespace modsecurity { namespace variables { void Duration::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { double e = utils::cpu_seconds() - transaction->m_creationTimeStamp; diff --git a/src/variables/duration.h b/src/variables/duration.h index ec35b73f..ff97affc 100644 --- a/src/variables/duration.h +++ b/src/variables/duration.h @@ -35,7 +35,6 @@ class Duration : public Variable { m_retName("DURATION") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/env.cc b/src/variables/env.cc index 9566b752..10b34076 100644 --- a/src/variables/env.cc +++ b/src/variables/env.cc @@ -33,7 +33,6 @@ namespace modsecurity { namespace variables { void Env::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { for (char **current = environ; *current; current++) { std::string env = std::string(*current); diff --git a/src/variables/env.h b/src/variables/env.h index 505c91e0..b41101b6 100644 --- a/src/variables/env.h +++ b/src/variables/env.h @@ -34,7 +34,6 @@ class Env : public Variable { : Variable(_name) { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; }; diff --git a/src/variables/global.h b/src/variables/global.h index 4fdf906c..6aaacbbc 100644 --- a/src/variables/global.h +++ b/src/variables/global.h @@ -25,6 +25,7 @@ #include "src/variables/variable.h" #include "src/run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" namespace modsecurity { @@ -39,7 +40,6 @@ class Global_DictElement : public Variable { m_dictElement("GLOBAL:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_global_collection->resolveMultiMatches( m_name, t->m_collections.m_global_collection_key, @@ -56,7 +56,6 @@ class Global_NoDictElement : public Variable { : Variable("GLOBAL") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_global_collection->resolveMultiMatches("", t->m_collections.m_global_collection_key, @@ -72,7 +71,6 @@ class Global_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_global_collection->resolveRegularExpression( m_dictElement, @@ -84,14 +82,16 @@ class Global_DictElementRegexp : public VariableRegex { }; -class Global_DynamicElement : public Variable { +class Global_DynamicElement : public VariableWithRunTimeString { public: explicit Global_DynamicElement(std::unique_ptr dictElement) - : Variable("GLOBAL:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "GLOBAL:dynamic", + std::move(dictElement) + ) + { }; void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_global_collection->resolveMultiMatches( @@ -113,8 +113,6 @@ class Global_DynamicElement : public Variable { t->m_rules->m_secWebAppId.m_value, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/highest_severity.cc b/src/variables/highest_severity.cc index 7059bc11..068797f6 100644 --- a/src/variables/highest_severity.cc +++ b/src/variables/highest_severity.cc @@ -27,7 +27,6 @@ namespace modsecurity { namespace variables { void HighestSeverity::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { transaction->m_variableHighestSeverityAction.assign( std::to_string(transaction->m_highestSeverityAction)); diff --git a/src/variables/highest_severity.h b/src/variables/highest_severity.h index ecc6cc1e..2479d6c1 100644 --- a/src/variables/highest_severity.h +++ b/src/variables/highest_severity.h @@ -35,7 +35,6 @@ class HighestSeverity : public Variable { { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; }; diff --git a/src/variables/ip.h b/src/variables/ip.h index 6f3efa94..1622e033 100644 --- a/src/variables/ip.h +++ b/src/variables/ip.h @@ -25,6 +25,7 @@ #include "src/variables/variable.h" #include "src/run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" namespace modsecurity { @@ -39,7 +40,6 @@ class Ip_DictElement : public Variable { m_dictElement("IP:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_ip_collection->resolveMultiMatches( m_name, t->m_collections.m_ip_collection_key, @@ -56,7 +56,6 @@ class Ip_NoDictElement : public Variable { : Variable("IP") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_ip_collection->resolveMultiMatches("", t->m_collections.m_ip_collection_key, @@ -72,7 +71,6 @@ class Ip_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_ip_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_ip_collection_key, @@ -83,14 +81,16 @@ class Ip_DictElementRegexp : public VariableRegex { }; -class Ip_DynamicElement : public Variable { +class Ip_DynamicElement : public VariableWithRunTimeString { public: explicit Ip_DynamicElement(std::unique_ptr dictElement) - : Variable("IP:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "IP:dynamic", + std::move(dictElement) + ) + { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_ip_collection->resolveMultiMatches( @@ -112,8 +112,6 @@ class Ip_DynamicElement : public Variable { t->m_rules->m_secWebAppId.m_value, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/modsec_build.cc b/src/variables/modsec_build.cc index 594b3bf5..d296fa2d 100644 --- a/src/variables/modsec_build.cc +++ b/src/variables/modsec_build.cc @@ -25,7 +25,6 @@ namespace modsecurity { namespace variables { void ModsecBuild::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { l->push_back(new VariableValue(&m_retName, &m_build)); diff --git a/src/variables/modsec_build.h b/src/variables/modsec_build.h index 318f7ef8..0ab101e5 100644 --- a/src/variables/modsec_build.h +++ b/src/variables/modsec_build.h @@ -44,7 +44,6 @@ class ModsecBuild : public Variable { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_build; diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index aa751a38..25f09b9f 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -37,7 +37,6 @@ namespace variables { void RemoteUser::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { size_t pos; std::string base64; diff --git a/src/variables/remote_user.h b/src/variables/remote_user.h index 3b099a79..370c892c 100644 --- a/src/variables/remote_user.h +++ b/src/variables/remote_user.h @@ -37,7 +37,6 @@ class RemoteUser : public Variable { m_retName("REMOTE_USER") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/resource.h b/src/variables/resource.h index aa352ba1..edcc4a4a 100644 --- a/src/variables/resource.h +++ b/src/variables/resource.h @@ -25,6 +25,7 @@ #include "src/variables/variable.h" #include "src/run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" namespace modsecurity { @@ -39,7 +40,6 @@ class Resource_DictElement : public Variable { m_dictElement("RESOURCE:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_resource_collection->resolveMultiMatches( m_name, t->m_collections.m_resource_collection_key, @@ -56,7 +56,6 @@ class Resource_NoDictElement : public Variable { : Variable("RESOURCE") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_resource_collection->resolveMultiMatches(m_name, t->m_collections.m_resource_collection_key, @@ -72,7 +71,6 @@ class Resource_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_resource_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_resource_collection_key, @@ -83,14 +81,16 @@ class Resource_DictElementRegexp : public VariableRegex { }; -class Resource_DynamicElement : public Variable { +class Resource_DynamicElement : public VariableWithRunTimeString { public: explicit Resource_DynamicElement(std::unique_ptr dictElement) - : Variable("RESOURCE:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "RESOURCE:dynamic", + std::move(dictElement) + ) + { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_resource_collection->resolveMultiMatches( @@ -111,8 +111,6 @@ class Resource_DynamicElement : public Variable { var, t->m_collections.m_resource_collection_key, t->m_rules->m_secWebAppId.m_value, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/rule.h b/src/variables/rule.h index 1d63d50f..475b3c31 100644 --- a/src/variables/rule.h +++ b/src/variables/rule.h @@ -33,21 +33,32 @@ class Transaction; namespace variables { -class Rule_DictElement : public VariableDictElement { \ +class Rule_DictElement : public RuleVariable, public VariableDictElement { public: explicit Rule_DictElement(const std::string &dictElement) - : VariableDictElement(std::string("RULE"), dictElement) { } + : RuleVariable(), + VariableDictElement( + std::string("RULE"), + dictElement + ) + { }; + + + Rule_DictElement(const Rule_DictElement &r) + : RuleVariable(), + VariableDictElement(r) + { }; + + + virtual Variable *clone() override { + return new Rule_DictElement(*this); + }; static void id(Transaction *t, - RuleWithActions *rule, + const RuleWithActions *rule, std::vector *l) { - RuleWithActions *r = rule; - - if (!r || r->getId() == 0) { - return; - } std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(r->getId())); + std::string *a = new std::string(std::to_string(rule->getId())); VariableValue *var = new VariableValue(&m_rule, &m_rule_id, a ); @@ -59,18 +70,14 @@ class Rule_DictElement : public VariableDictElement { \ } + static void rev(Transaction *t, - RuleWithActions *rule, + const RuleWithActions *rule, std::vector *l) { - RuleWithActions *r = rule; - if (!r) { - return; - } - - if (r->hasRevisionAction()) { + if (rule->hasRevisionAction()) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->getRevision()); + std::string *a = new std::string(rule->getRevision()); VariableValue *var = new VariableValue(&m_rule, &m_rule_rev, a ); @@ -84,17 +91,12 @@ class Rule_DictElement : public VariableDictElement { \ static void severity(Transaction *t, - RuleWithActions *rule, + const RuleWithActions *rule, std::vector *l) { - RuleWithActions *r = rule; - if (!r) { - return; - } - - if (r->hasSeverityAction()) { + if (rule->hasSeverityAction()) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(r->getSeverity())); + std::string *a = new std::string(std::to_string(rule->getSeverity())); VariableValue *var = new VariableValue(&m_rule, &m_rule_severity, a ); @@ -104,21 +106,16 @@ class Rule_DictElement : public VariableDictElement { \ var->addOrigin(std::move(origin)); l->push_back(var); } + } - static void logData(Transaction *t, - RuleWithActions *rule, + const RuleWithActions *rule, std::vector *l) { - RuleWithActions *r = rule; - if (!r) { - return; - } - - if (r->hasLogDataAction()) { + if (rule->hasLogDataAction()) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->getLogData(t)); + std::string *a = new std::string(rule->getLogData(t)); VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata, a ); @@ -131,17 +128,12 @@ class Rule_DictElement : public VariableDictElement { \ } static void msg(Transaction *t, - RuleWithActions *rule, + const RuleWithActions *rule, std::vector *l) { - RuleWithActions *r = rule; - if (!r) { - return; - } - - if (r->hasMessageAction()) { + if (rule->hasMessageAction()) { std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->getMessage(t)); + std::string *a = new std::string(rule->getMessage(t)); VariableValue *var = new VariableValue(&m_rule, &m_rule_msg, a ); @@ -154,26 +146,26 @@ class Rule_DictElement : public VariableDictElement { \ } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { + if (m_dictElement == "id") { - id(t, rule, l); + id(t, getRule(), l); return; } if (m_dictElement == "rev") { - rev(t, rule, l); + rev(t, getRule(), l); return; } if (m_dictElement == "severity") { - severity(t, rule, l); + severity(t, getRule(), l); return; } if (m_dictElement == "logdata") { - logData(t, rule, l); + logData(t, getRule(), l); return; } if (m_dictElement == "msg") { - msg(t, rule, l); + msg(t, getRule(), l); return; } } @@ -187,52 +179,77 @@ class Rule_DictElement : public VariableDictElement { \ }; -class Rule_DictElementRegexp : public VariableRegex { +class Rule_DictElementRegexp : public RuleVariable, public VariableRegex { public: explicit Rule_DictElementRegexp(const std::string ®ex) - : VariableRegex("RULE", regex) { } + : RuleVariable(), + VariableRegex("RULE", regex) + { }; + + + Rule_DictElementRegexp(const Rule_DictElementRegexp &r) + : RuleVariable(), + VariableRegex(r) + { }; + void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { + if (Utils::regex_search("id", m_r) > 0) { - Rule_DictElement::id(t, rule, l); + Rule_DictElement::id(t, getRule(), l); return; } if (Utils::regex_search("rev", m_r) > 0) { - Rule_DictElement::rev(t, rule, l); + Rule_DictElement::rev(t, getRule(), l); return; } if (Utils::regex_search("severity", m_r) > 0) { - Rule_DictElement::severity(t, rule, l); + Rule_DictElement::severity(t, getRule(), l); return; } if (Utils::regex_search("logdata", m_r) > 0) { - Rule_DictElement::logData(t, rule, l); + Rule_DictElement::logData(t, getRule(), l); return; } if (Utils::regex_search("msg", m_r) > 0) { - Rule_DictElement::msg(t, rule, l); + Rule_DictElement::msg(t, getRule(), l); return; } } + + virtual Variable *clone() override { + return new Rule_DictElementRegexp(*this); + }; }; -class Rule_NoDictElement : public Variable { +class Rule_NoDictElement : public RuleVariable, public Variable { public: - explicit Rule_NoDictElement() - : Variable("RULE") { } + Rule_NoDictElement() + : RuleVariable(), + Variable("RULE") + { }; + + + explicit Rule_NoDictElement(const Rule_DictElementRegexp &r) + : RuleVariable(), + Variable(r) + { }; + void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { - Rule_DictElement::id(t, rule, l); - Rule_DictElement::rev(t, rule, l); - Rule_DictElement::severity(t, rule, l); - Rule_DictElement::logData(t, rule, l); - Rule_DictElement::msg(t, rule, l); + Rule_DictElement::id(t, getRule(), l); + Rule_DictElement::rev(t, getRule(), l); + Rule_DictElement::severity(t, getRule(), l); + Rule_DictElement::logData(t, getRule(), l); + Rule_DictElement::msg(t, getRule(), l); } + + virtual Variable *clone() override { + return new Rule_NoDictElement(*this); + }; }; // DEFINE_VARIABLE_DICT(Rule, RULE, m_variableRule) diff --git a/src/variables/rule_variable.h b/src/variables/rule_variable.h new file mode 100644 index 00000000..47714f16 --- /dev/null +++ b/src/variables/rule_variable.h @@ -0,0 +1,60 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 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 +#include +#include + +#ifndef SRC_VARIABLES_RULE_VARIABLE_H_ +#define SRC_VARIABLES_RULE_VARIABLE_H_ + +#include "src/rule_with_actions.h" + + +namespace modsecurity { + +class Transaction; +namespace variables { + +class RuleVariable { + public: + RuleVariable() + : m_rule(nullptr) + { }; + + RuleVariable(const RuleVariable &a) + : m_rule(a.m_rule) + { }; + + + void populate(const RuleWithActions *rule) { + m_rule = rule; + } + + const RuleWithActions *getRule() const noexcept { + return m_rule; + } + + virtual Variable* clone() = 0; + + private: + const RuleWithActions *m_rule; +}; + + +} // namespace variables +} // namespace modsecurity + +#endif // SRC_VARIABLES_RULE_VARIABLE_H_ diff --git a/src/variables/session.h b/src/variables/session.h index bc831e31..ce810080 100644 --- a/src/variables/session.h +++ b/src/variables/session.h @@ -39,7 +39,6 @@ class Session_DictElement : public Variable { m_dictElement("SESSION:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_session_collection->resolveMultiMatches( m_name, t->m_collections.m_session_collection_key, @@ -56,7 +55,6 @@ class Session_NoDictElement : public Variable { : Variable("SESSION") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_session_collection->resolveMultiMatches("", t->m_collections.m_session_collection_key, @@ -72,7 +70,6 @@ class Session_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_session_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_session_collection_key, @@ -83,14 +80,16 @@ class Session_DictElementRegexp : public VariableRegex { }; -class Session_DynamicElement : public Variable { +class Session_DynamicElement : public VariableWithRunTimeString { public: explicit Session_DynamicElement(std::unique_ptr dictElement) - : Variable("SESSION:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "SESSION:dynamic", + std::move(dictElement) + ) + { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_session_collection->resolveMultiMatches( @@ -112,8 +111,6 @@ class Session_DynamicElement : public Variable { t->m_rules->m_secWebAppId.m_value, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/time.cc b/src/variables/time.cc index b14e9610..63872e9e 100644 --- a/src/variables/time.cc +++ b/src/variables/time.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void Time::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; diff --git a/src/variables/time.h b/src/variables/time.h index 4f3dec89..5499527f 100644 --- a/src/variables/time.h +++ b/src/variables/time.h @@ -36,7 +36,6 @@ class Time : public Variable { m_retName("TIME") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_day.cc b/src/variables/time_day.cc index f16500e9..08c77047 100644 --- a/src/variables/time_day.cc +++ b/src/variables/time_day.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeDay::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_day.h b/src/variables/time_day.h index 946ba3aa..c977670a 100644 --- a/src/variables/time_day.h +++ b/src/variables/time_day.h @@ -35,7 +35,6 @@ class TimeDay : public Variable { m_retName("TIME_DAY") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_epoch.cc b/src/variables/time_epoch.cc index f7ee0f52..a96b4e0d 100644 --- a/src/variables/time_epoch.cc +++ b/src/variables/time_epoch.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeEpoch::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { transaction->m_variableTimeEpoch.assign( std::to_string(std::time(nullptr))); diff --git a/src/variables/time_epoch.h b/src/variables/time_epoch.h index a259e863..322b4480 100644 --- a/src/variables/time_epoch.h +++ b/src/variables/time_epoch.h @@ -35,7 +35,6 @@ class TimeEpoch : public Variable { m_retName("TIME_EPOCH") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_hour.cc b/src/variables/time_hour.cc index 380f471a..9d0e842a 100644 --- a/src/variables/time_hour.cc +++ b/src/variables/time_hour.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeHour::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_hour.h b/src/variables/time_hour.h index aad53515..222de215 100644 --- a/src/variables/time_hour.h +++ b/src/variables/time_hour.h @@ -35,7 +35,6 @@ class TimeHour : public Variable { m_retName("TIME_HOUR") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_min.cc b/src/variables/time_min.cc index 099e6685..693fbf7c 100644 --- a/src/variables/time_min.cc +++ b/src/variables/time_min.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeMin::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_min.h b/src/variables/time_min.h index fd26eb26..272ae8f2 100644 --- a/src/variables/time_min.h +++ b/src/variables/time_min.h @@ -35,7 +35,6 @@ class TimeMin : public Variable { m_retName("TIME_MIN") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_mon.cc b/src/variables/time_mon.cc index c1ff8175..1f70f3ed 100644 --- a/src/variables/time_mon.cc +++ b/src/variables/time_mon.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeMon::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_mon.h b/src/variables/time_mon.h index e54866a3..80cd631d 100644 --- a/src/variables/time_mon.h +++ b/src/variables/time_mon.h @@ -35,7 +35,6 @@ class TimeMon : public Variable { m_retName("TIME_MON") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_sec.cc b/src/variables/time_sec.cc index 9e7a76cd..8869082d 100644 --- a/src/variables/time_sec.cc +++ b/src/variables/time_sec.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeSec::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_sec.h b/src/variables/time_sec.h index 2c9b431a..0813785e 100644 --- a/src/variables/time_sec.h +++ b/src/variables/time_sec.h @@ -35,7 +35,6 @@ class TimeSec : public Variable { m_retName("TIME_SEC") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_wday.cc b/src/variables/time_wday.cc index daf29a7d..04f91ac7 100644 --- a/src/variables/time_wday.cc +++ b/src/variables/time_wday.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeWDay::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_wday.h b/src/variables/time_wday.h index 3969e74b..5b258ea8 100644 --- a/src/variables/time_wday.h +++ b/src/variables/time_wday.h @@ -35,7 +35,6 @@ class TimeWDay : public Variable { m_retName("TIME_WDAY") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/time_year.cc b/src/variables/time_year.cc index dbec656c..0a39c93a 100644 --- a/src/variables/time_year.cc +++ b/src/variables/time_year.cc @@ -34,7 +34,6 @@ namespace modsecurity { namespace variables { void TimeYear::evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) { char tstr[200]; struct tm timeinfo; diff --git a/src/variables/time_year.h b/src/variables/time_year.h index 52099a83..f14eb4a5 100644 --- a/src/variables/time_year.h +++ b/src/variables/time_year.h @@ -35,7 +35,6 @@ class TimeYear : public Variable { m_retName("TIME_YEAR") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; std::string m_retName; }; diff --git a/src/variables/tx.h b/src/variables/tx.h index c665433d..ab426b04 100644 --- a/src/variables/tx.h +++ b/src/variables/tx.h @@ -25,6 +25,7 @@ #include "src/variables/variable.h" #include "src/run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" namespace modsecurity { @@ -39,7 +40,6 @@ class Tx_DictElement : public Variable { m_dictElement("TX:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_tx_collection->resolveMultiMatches( m_name, l, m_keyExclusion); @@ -55,7 +55,6 @@ class Tx_NoDictElement : public Variable { : Variable("TX") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_tx_collection->resolveMultiMatches("", l, m_keyExclusion); @@ -70,7 +69,6 @@ class Tx_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_tx_collection->resolveRegularExpression( m_dictElement, l, m_keyExclusion); @@ -80,14 +78,16 @@ class Tx_DictElementRegexp : public VariableRegex { }; -class Tx_DynamicElement : public Variable { +class Tx_DynamicElement : public VariableWithRunTimeString { public: explicit Tx_DynamicElement(std::unique_ptr dictElement) - : Variable("TX:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "TX:dynamic", + std::move(dictElement) + ) + { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_tx_collection->resolveMultiMatches(string, l, @@ -102,8 +102,6 @@ class Tx_DynamicElement : public Variable { std::string value) { t->m_collections.m_tx_collection->storeOrUpdateFirst(var, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/user.h b/src/variables/user.h index 88600198..b8d758a5 100644 --- a/src/variables/user.h +++ b/src/variables/user.h @@ -25,6 +25,7 @@ #include "src/variables/variable.h" #include "src/run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" namespace modsecurity { @@ -39,7 +40,6 @@ class User_DictElement : public Variable { m_dictElement("USER:" + dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_user_collection->resolveMultiMatches( m_name, t->m_collections.m_user_collection_key, @@ -56,7 +56,6 @@ class User_NoDictElement : public Variable { : Variable("USER") { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_user_collection->resolveMultiMatches(m_name, t->m_collections.m_user_collection_key, @@ -72,7 +71,6 @@ class User_DictElementRegexp : public VariableRegex { m_dictElement(dictElement) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { t->m_collections.m_user_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_user_collection_key, @@ -83,14 +81,16 @@ class User_DictElementRegexp : public VariableRegex { }; -class User_DynamicElement : public Variable { +class User_DynamicElement : public VariableWithRunTimeString { public: explicit User_DynamicElement(std::unique_ptr dictElement) - : Variable("USER:dynamic"), - m_string(std::move(dictElement)) { } + : VariableWithRunTimeString( + "USER:dynamic", + std::move(dictElement) + ) + { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::string string = m_string->evaluate(t); t->m_collections.m_user_collection->resolveMultiMatches( @@ -112,8 +112,6 @@ class User_DynamicElement : public Variable { t->m_rules->m_secWebAppId.m_value, value); } - - std::unique_ptr m_string; }; diff --git a/src/variables/variable.h b/src/variables/variable.h index d3ad71a2..62c1f786 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -23,7 +23,6 @@ #include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" #include "src/utils/string.h" #include "src/utils/regex.h" @@ -49,7 +48,6 @@ class n ## _DictElementRegexp : public VariableRegex { \ : VariableRegex(#N, regex) { } \ \ void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ std::vector *l) override { \ transaction-> e .resolveRegularExpression(&m_r, l, \ m_keyExclusion); \ @@ -64,7 +62,6 @@ class n ## _DictElement : public VariableDictElement { \ : VariableDictElement(#N, dictElement) { } \ \ void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ std::vector *l) override { \ transaction-> e .resolve(m_dictElement, l); \ } \ @@ -78,7 +75,6 @@ class n ## _NoDictElement : public Variable { \ : Variable(#N) { } \ \ void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ std::vector *l) override { \ transaction-> e .resolve(l, m_keyExclusion); \ } \ @@ -92,13 +88,14 @@ class n : public Variable { \ : Variable(#N) { } \ \ void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ std::vector *l) override { \ transaction-> e .evaluate(l); \ } \ }; +// FIXME: Copy methods for variables modificators needs to be done. + namespace modsecurity { class Transaction; @@ -151,8 +148,19 @@ class KeyExclusionString : public KeyExclusion { class KeyExclusions : public std::deque> { public: - KeyExclusions() { - } + + KeyExclusions() + : std::deque>() + { }; + + + KeyExclusions(const KeyExclusions &k) + : std::deque>() + { + //for (auto &a : k) { + + //} + }; bool toOmit(std::string a) { for (auto &z : *this) { @@ -545,12 +553,20 @@ class VariableMonkeyResolution { class Variable : public VariableMonkeyResolution { public: explicit Variable(const std::string &name); + explicit Variable(Variable *_name); + + Variable(const Variable &v) + : m_name(v.m_name), + m_collectionName(v.m_collectionName), + m_fullName(v.m_fullName), + m_keyExclusion(v.m_keyExclusion) + { }; + virtual ~Variable() { } virtual void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) = 0; @@ -586,7 +602,14 @@ class Variable : public VariableMonkeyResolution { class VariableDictElement : public Variable { public: VariableDictElement(const std::string &name, const std::string &dict_element) - : m_dictElement(dict_element), Variable(name + ":" + dict_element) { } + : m_dictElement(dict_element), Variable(name + ":" + dict_element) + { }; + + VariableDictElement(const VariableDictElement &v) + : m_dictElement(v.m_dictElement), + Variable(v) + { }; + std::string m_dictElement; }; @@ -597,7 +620,15 @@ class VariableRegex : public Variable { VariableRegex(const std::string &name, const std::string ®ex) : m_r(regex), m_regex(regex), - Variable(name + ":" + "regex(" + regex + ")") { } + Variable(name + ":" + "regex(" + regex + ")") + { } + + VariableRegex(const VariableRegex &v) + : m_r(v.m_regex), + m_regex(v.m_regex), + Variable(v) + { }; + Utils::Regex m_r; // FIXME: no need for that. @@ -644,9 +675,8 @@ class VariableModificatorExclusion : public Variable { m_base(std::move(var)) { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { - m_base->evaluate(t, rule, l); + m_base->evaluate(t, l); } std::unique_ptr m_base; @@ -662,13 +692,12 @@ class VariableModificatorCount : public Variable { } void evaluate(Transaction *t, - RuleWithActions *rule, std::vector *l) override { std::vector reslIn; VariableValue *val = NULL; int count = 0; - m_base->evaluate(t, rule, &reslIn); + m_base->evaluate(t, &reslIn); for (const VariableValue *a : reslIn) { count++; diff --git a/src/variables/variable_with_runtime_string.h b/src/variables/variable_with_runtime_string.h new file mode 100644 index 00000000..0e248cc8 --- /dev/null +++ b/src/variables/variable_with_runtime_string.h @@ -0,0 +1,61 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 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 "src/variables/variable.h" +#include "src/run_time_string.h" + +#ifndef SRC_VARIABLES_VARIABLE_WITH_RUN_TIME_STRING_H_ +#define SRC_VARIABLES_VARIABLE_WITH_RUN_TIME_STRING_H_ + +namespace modsecurity { +namespace variables { + +class VariableWithRunTimeString : public Variable { + public: + VariableWithRunTimeString(const std::string &name, std::unique_ptr string) + : Variable(name), + m_string(std::move(string)) + { }; + + VariableWithRunTimeString(const VariableWithRunTimeString &v) + : Variable(v), + m_string(std::unique_ptr(new RunTimeString(*v.m_string.get()))) + { }; + + VariableWithRunTimeString& operator=(const VariableWithRunTimeString& v) + { + m_string = std::unique_ptr(new RunTimeString(*v.m_string.get())); + return *this; + } + + virtual void populate(RuleWithActions *rule) { + if (m_string) { + m_string->populate(rule); + } + } + + std::string evaluateRunTimeString(Transaction *t) { + return m_string->evaluate(t); + } + + protected: + std::unique_ptr m_string; +}; + + +} // namespace variables +} // namespace modsecurity + +#endif // SRC_VARIABLES_VARIABLE_WITH_RUN_TIME_STRING_H_ diff --git a/src/variables/web_app_id.h b/src/variables/web_app_id.h index 47cf4229..68a87858 100644 --- a/src/variables/web_app_id.h +++ b/src/variables/web_app_id.h @@ -36,7 +36,6 @@ class WebAppId : public Variable { : Variable("WEBAPPID") { } void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override { const std::string rname = transaction->m_rules->m_secWebAppId.m_value; l->push_back(new VariableValue(&m_name, &rname)); diff --git a/src/variables/xml.cc b/src/variables/xml.cc index 3c9604ce..af4026f3 100644 --- a/src/variables/xml.cc +++ b/src/variables/xml.cc @@ -49,13 +49,11 @@ namespace modsecurity { namespace variables { #ifndef WITH_LIBXML2 -void XML::evaluate(Transaction *t, - RuleWithActions *rule, +void XML_WithNSPath::evaluate(Transaction *t, std::vector *l) { } #else -void XML::evaluate(Transaction *t, - RuleWithActions *rule, +void XML_WithNSPath::evaluate(Transaction *t, std::vector *l) { xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; @@ -88,20 +86,20 @@ void XML::evaluate(Transaction *t, return; } - if (rule == NULL) { + if (getRule() == NULL) { ms_dbg_a(t, 2, "XML: Can't look for xmlns, internal error."); } else { - std::vector acts = rule->getXmlNSsPtr(); + XmlNSsPtr acts = getRule()->getXmlNSsPtr(); for (auto &z : acts) { - if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->m_scope.c_str(), - (const xmlChar*)z->m_href.c_str()) != 0) { + if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->getScope().c_str(), + (const xmlChar*)z->getHref().c_str()) != 0) { ms_dbg_a(t, 1, "Failed to register XML namespace href \"" + \ - z->m_href + "\" prefix \"" + z->m_scope + "\"."); + z->getHref() + "\" prefix \"" + z->getScope() + "\"."); return; } - ms_dbg_a(t, 4, "Registered XML namespace href \"" + z->m_href + \ - "\" prefix \"" + z->m_scope + "\""); + ms_dbg_a(t, 4, "Registered XML namespace href \"" + z->getHref() + \ + "\" prefix \"" + z->getScope() + "\""); } } diff --git a/src/variables/xml.h b/src/variables/xml.h index 7b0181fe..fae54895 100644 --- a/src/variables/xml.h +++ b/src/variables/xml.h @@ -24,43 +24,63 @@ #include "src/variables/variable.h" #include "src/variables/xml.h" +#include "src/variables/rule_variable.h" namespace modsecurity { class Transaction; namespace variables { - /* Invocation without an XPath expression makes sense * with functions that manipulate the document tree. */ -class XML_NoDictElement : public Variable { +class XML_WithoutNSPath : public RuleVariable, public Variable { public: - XML_NoDictElement() - : Variable("XML"), + XML_WithoutNSPath() + : RuleVariable(), + Variable("XML"), m_plain("[XML document tree]"), - m_var(&m_name, &m_plain) { - } + m_var(&m_name, &m_plain) + { }; + + XML_WithoutNSPath(const XML_WithoutNSPath &r) + : RuleVariable(r), + Variable(r), + m_plain(r.m_plain), + m_var(r.m_var) + { }; void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override { l->push_back(new VariableValue(&m_var)); } + virtual variables::Variable *clone() override { + return new XML_WithoutNSPath(*this); + }; + std::string m_plain; VariableValue m_var; }; - -class XML : public Variable { +class XML_WithNSPath : public RuleVariable, public VariableDictElement { public: - explicit XML(const std::string &_name) - : Variable(_name) { } + explicit XML_WithNSPath(const std::string &nsPath) + : RuleVariable(), + VariableDictElement("XML", nsPath) + { }; + + XML_WithNSPath(const XML_WithNSPath &r) + : RuleVariable(), + VariableDictElement(r) + { }; void evaluate(Transaction *transaction, - RuleWithActions *rule, std::vector *l) override; + + virtual Variable *clone() override { + return new XML_WithNSPath(*this); + }; };