diff --git a/.travis.yml b/.travis.yml index 9e78797c12..4b6fde61d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -dist: trusty +dist: bionic sudo: true addons: @@ -9,7 +9,6 @@ addons: - libgeoip-dev - liblua5.2-dev - liblmdb-dev - - cppcheck language: cpp @@ -38,9 +37,12 @@ before_script: - '[ "$TRAVIS_OS_NAME" != osx ] || brew install libmaxminddb' - '[ "$TRAVIS_OS_NAME" != osx ] || brew install lmdb' - '[ "$TRAVIS_OS_NAME" != linux ] || sudo add-apt-repository --yes ppa:maxmind/ppa' + - '[ "$TRAVIS_OS_NAME" != linux ] || sudo add-apt-repository --yes ppa:grochefort/cppcheck' - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-get update' - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-cache search maxmind' - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-get install -y libmaxminddb-dev' + - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-get install -y cppcheck' + - '[ "$TRAVIS_OS_NAME" != linux ] || cppcheck --version' script: - ./build.sh diff --git a/CHANGES b/CHANGES index 9f60ce4d56..d703c34a0e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,38 @@ v3.x.y - YYYY-MMM-DD (to be released) ------------------------------------- - + + - Implement id ranges for ctl:ruleRemoveTargetById + [#2110 - @j0k2r, @martinhsv] + - Removed unnecessary while processing the transformations. + [#2368 - @WGH-, @zimmerle] + - auditlog: Computes whether or not to save while loading the rules. + [@zimmerle] + - 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. + [@zimmerle] + - More structured rules dump. Better supporting debugging. + [@zimmerle] + - Added the basics for supporting better error/warning handling while + loading configurations. + [@zimmerle] + - IMPORTANT: SecDefaultAction behaves changing: SecDefaultAction specified + on a child configuration will overwrite the ones specified on the parent; + Previously it was concatenating. + [@zimmerle] + - Using std::shared_ptr instead of generates its own references counters + for Rules and related. + [@zimmerle] + - Better handle shared_pointers on messages aiming for better performance. + [@zimmerle] + - Better handle memory usage on transformations aiming for better + performance. + [@zimmerle] + - Coding refactoring on the Rule class. The Rule class is now refactored + into RuleWithOperator, RuleWithActions, and RuleUnconditional. - Fix IP address logging in Section A [Issue #2300 - @inaratech, @zavazingo, @martinhsv] - Adds support to lua 5.4 diff --git a/Makefile.am b/Makefile.am index 734b6f3597..75ce55d1dd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,14 +57,16 @@ parser: cppcheck: @cppcheck -U YYSTYPE -U MBEDTLS_MD5_ALT -U MBEDTLS_SHA1_ALT \ - -D MS_CPPCHECK_DISABLED_FOR_PARSER \ + -D MS_CPPCHECK_DISABLED_FOR_PARSER -U YY_USER_INIT \ --suppressions-list=./test/cppcheck_suppressions.txt \ --enable=all \ --inconclusive \ --template="warning: {file},{line},{severity},{id},{message}" \ -I headers -I . -I others -I src -I others/mbedtls -I src/parser \ --error-exitcode=1 \ - -i "src/parser/seclang-parser.cc" -i "src/parser/seclang-scanner.cc" \ + -i "src/parser/seclang-parser.cc" \ + -i "src/parser/seclang-scanner.cc" \ + -i "parser/driver.cc" \ --force --verbose . diff --git a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h index 4e3694454a..a6595aaa94 100644 --- a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h +++ b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h @@ -176,21 +176,22 @@ class ReadingLogsViaRuleMessage { return; } - const modsecurity::RuleMessage *ruleMessage = \ - reinterpret_cast(ruleMessagev); + modsecurity::RuleMessage ruleMessage( + *reinterpret_cast(ruleMessagev)); - std::cout << "Rule Id: " << std::to_string(ruleMessage->m_ruleId); - std::cout << " phase: " << std::to_string(ruleMessage->m_phase); + + std::cout << "Rule Id: " << std::to_string(ruleMessage.getRuleId()); + std::cout << " phase: " << std::to_string(ruleMessage.getPhase()); std::cout << std::endl; - if (ruleMessage->m_isDisruptive) { + if (ruleMessage.isDisruptive()) { std::cout << " * Disruptive action: "; - std::cout << modsecurity::RuleMessage::log(ruleMessage); + std::cout << modsecurity::RuleMessage::log(&ruleMessage); std::cout << std::endl; std::cout << " ** %d is meant to be informed by the webserver."; std::cout << std::endl; } else { std::cout << " * Match, but no disruptive action: "; - std::cout << modsecurity::RuleMessage::log(ruleMessage); + std::cout << modsecurity::RuleMessage::log(&ruleMessage); std::cout << std::endl; } } diff --git a/examples/using_bodies_in_chunks/simple_request.cc b/examples/using_bodies_in_chunks/simple_request.cc index 853668bdc0..cca090109e 100644 --- a/examples/using_bodies_in_chunks/simple_request.cc +++ b/examples/using_bodies_in_chunks/simple_request.cc @@ -69,21 +69,21 @@ static void logCb(void *data, const void *ruleMessagev) { return; } - const modsecurity::RuleMessage *ruleMessage = \ - reinterpret_cast(ruleMessagev); + modsecurity::RuleMessage ruleMessage( + *reinterpret_cast(ruleMessagev)); - std::cout << "Rule Id: " << std::to_string(ruleMessage->m_ruleId); - std::cout << " phase: " << std::to_string(ruleMessage->m_phase); + std::cout << "Rule Id: " << std::to_string(ruleMessage.getRuleId()); + std::cout << " phase: " << std::to_string(ruleMessage.getPhase()); std::cout << std::endl; - if (ruleMessage->m_isDisruptive) { + if (ruleMessage.isDisruptive()) { std::cout << " * Disruptive action: "; - std::cout << modsecurity::RuleMessage::log(ruleMessage); + std::cout << modsecurity::RuleMessage::log(&ruleMessage); std::cout << std::endl; std::cout << " ** %d is meant to be informed by the webserver."; std::cout << std::endl; } else { std::cout << " * Match, but no disruptive action: "; - std::cout << modsecurity::RuleMessage::log(ruleMessage); + std::cout << modsecurity::RuleMessage::log(&ruleMessage); std::cout << std::endl; } } diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index 4409660c64..f44b115819 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -16,14 +16,11 @@ #ifdef __cplusplus #include -#include -#include + +#include #endif -#include "modsecurity/intervention.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_with_actions.h" #ifndef HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #define HEADERS_MODSECURITY_ACTIONS_ACTION_H_ @@ -32,44 +29,59 @@ namespace modsecurity { class Transaction; -class RuleWithOperator; - namespace actions { class Action { public: - explicit Action(const std::string& _action) - : m_isNone(false), - temporaryAction(false), - action_kind(2), - m_name(nullptr), - m_parser_payload("") { - set_name_and_payload(_action); - } - explicit Action(const std::string& _action, int kind) - : m_isNone(false), - temporaryAction(false), - action_kind(kind), - m_name(nullptr), - m_parser_payload("") { - set_name_and_payload(_action); - } + Action() + : m_parserPayload(""), + m_name("") + { + assert(0); + } + + + explicit Action(const std::string& action) + : m_parserPayload(sort_payload(action)), + m_name(sort_name(action)) + { } - virtual ~Action() { } - virtual std::string evaluate(const std::string &exp, - Transaction *transaction); - virtual bool evaluate(RuleWithActions *rule, Transaction *transaction); - virtual bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr ruleMessage) { - return evaluate(rule, transaction); + Action(const Action &other) + : m_parserPayload(other.m_parserPayload), + m_name(other.m_name) + { } + + + Action &operator=(const Action& a) { + m_name = a.m_name; + m_parserPayload = a.m_parserPayload; + return *this; } - virtual bool init(std::string *error) { return true; } - virtual bool isDisruptive() { return false; } - void set_name_and_payload(const std::string& data) { + virtual ~Action() + { } + + + virtual bool init(std::string *error) { + return true; + } + + const std::string *getName() const noexcept { + return &m_name; + } + + + protected: + std::string m_parserPayload; + + + private: + std::string m_name; + + static size_t get_payload_pos(const std::string& data) { size_t pos = data.find(":"); std::string t = "t:"; @@ -77,58 +89,36 @@ class Action { pos = data.find(":", 2); } + return pos; + } + + + static std::string sort_name(const std::string& data) { + size_t pos = get_payload_pos(data); if (pos == std::string::npos) { - m_name = std::shared_ptr(new std::string(data)); - return; + return data; } - m_name = std::shared_ptr(new std::string(data, 0, pos)); - m_parser_payload = std::string(data, pos + 1, data.length()); + std::string ret(data, 0, pos); + return ret; + } + - if (m_parser_payload.at(0) == '\'' && m_parser_payload.size() > 2) { - m_parser_payload.erase(0, 1); - m_parser_payload.pop_back(); + static std::string sort_payload(const std::string& data) { + size_t pos = get_payload_pos(data); + std::string ret(""); + if (pos != std::string::npos) { + ret = std::string(data, pos + 1, data.length()); + + if (ret.at(0) == '\'' && ret.size() > 2) { + ret.erase(0, 1); + ret.pop_back(); + } } - } - bool m_isNone; - bool temporaryAction; - int action_kind; - std::shared_ptr m_name; - std::string m_parser_payload; - - /** - * - * Define the action kind regarding to the execution time. - * - * - */ - enum Kind { - /** - * - * Action that are executed while loading the configuration. For instance - * the rule ID or the rule phase. - * - */ - ConfigurationKind, - /** - * - * Those are actions that demands to be executed before call the operator. - * For instance the tranformations. - * - * - */ - RunTimeBeforeMatchAttemptKind, - /** - * - * Actions that are executed after the execution of the operator, only if - * the operator returned Match (or True). For instance the disruptive - * actions. - * - */ - RunTimeOnlyIfMatchKind, - }; - }; + return ret; + } +}; } // namespace actions diff --git a/headers/modsecurity/anchored_set_variable.h b/headers/modsecurity/anchored_set_variable.h index 24d80cdac0..dc0f5fb7d8 100644 --- a/headers/modsecurity/anchored_set_variable.h +++ b/headers/modsecurity/anchored_set_variable.h @@ -27,10 +27,13 @@ #include #include #include + +#include "modsecurity/string_view.hpp" #endif #include "modsecurity/variable_value.h" + #ifndef HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_H_ #define HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_H_ @@ -69,36 +72,37 @@ struct MyHash{ class AnchoredSetVariable : public std::unordered_multimap { + std::shared_ptr, MyHash, MyEqual> { public: AnchoredSetVariable(Transaction *t, const std::string &name); - ~AnchoredSetVariable(); void unset(); - void set(const std::string &key, const std::string &value, - size_t offset); + void set(const std::string &key, const std::string &value, size_t offset) { + set(key, value, offset, value.size()); + } void set(const std::string &key, const std::string &value, size_t offset, size_t len); - void setCopy(std::string key, std::string value, size_t offset); + void set(const std::string &key, const bpstd::string_view &value, + size_t offset); - void resolve(std::vector *l); - void resolve(std::vector *l, - variables::KeyExclusions &ke); + void resolve(VariableValues *l) const noexcept; + void resolve(VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; void resolve(const std::string &key, - std::vector *l); + VariableValues *l) const noexcept; - void resolveRegularExpression(Utils::Regex *r, - std::vector *l); + void resolveRegularExpression(const Utils::Regex *r, + VariableValues *l) const noexcept; - void resolveRegularExpression(Utils::Regex *r, - std::vector *l, - variables::KeyExclusions &ke); + void resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; - std::unique_ptr resolveFirst(const std::string &key); + std::unique_ptr resolveFirst(const std::string &key) const noexcept; Transaction *m_transaction; std::string m_name; diff --git a/headers/modsecurity/anchored_variable.h b/headers/modsecurity/anchored_variable.h index aa71b56069..6a06abfebd 100644 --- a/headers/modsecurity/anchored_variable.h +++ b/headers/modsecurity/anchored_variable.h @@ -26,10 +26,14 @@ #include #include #include +#include + +#include "modsecurity/string_view.hpp" #endif #include "modsecurity/variable_value.h" + #ifndef HEADERS_MODSECURITY_ANCHORED_VARIABLE_H_ #define HEADERS_MODSECURITY_ANCHORED_VARIABLE_H_ @@ -47,27 +51,19 @@ class AnchoredVariable { AnchoredVariable(const AnchoredVariable &a) = delete; AnchoredVariable &operator= (const AnchoredVariable &a) = delete; - /* - : m_transaction(a.m_transaction), - m_offset(a.m_offset), - m_name(a.m_name), - m_value(a.m_value), - m_var(a.m_var) { } - */ - - ~AnchoredVariable(); - void unset(); void set(const std::string &a, size_t offset); + void set(const bpstd::string_view &a, size_t offset); + void set(const char *a, size_t offset); void set(const std::string &a, size_t offset, size_t offsetLen); void append(const std::string &a, size_t offset, bool spaceSeparator = false); void append(const std::string &a, size_t offset, bool spaceSeparator, int size); - void evaluate(std::vector *l); - std::string * evaluate(); - std::unique_ptr resolveFirst(); + void evaluate(VariableValues *l) const noexcept; + const std::string *evaluate() const noexcept; + std::unique_ptr resolveFirst() const noexcept; Transaction *m_transaction; int m_offset; @@ -75,7 +71,7 @@ class AnchoredVariable { std::string m_value; private: - VariableValue *m_var; + std::shared_ptr m_var; }; } // namespace modsecurity @@ -84,4 +80,3 @@ class AnchoredVariable { #endif // HEADERS_MODSECURITY_ANCHORED_VARIABLE_H_ - diff --git a/headers/modsecurity/audit_log.h b/headers/modsecurity/audit_log.h index 08ffdbfeb0..1278ecd994 100644 --- a/headers/modsecurity/audit_log.h +++ b/headers/modsecurity/audit_log.h @@ -61,7 +61,7 @@ class AuditLog { NativeAuditLogFormat }; - enum AuditLogParts { + enum AuditLogPartsEnum { /** * Audit log header (mandatory). * @@ -170,9 +170,8 @@ class AuditLog { bool init(std::string *error); virtual bool close(); - bool saveIfRelevant(Transaction *transaction); - bool saveIfRelevant(Transaction *transaction, int parts); - bool isRelevant(int status); + bool saveIfRelevant(Transaction *transaction) const noexcept; + bool isRelevant(int status) const noexcept; static int addParts(int parts, const std::string& new_parts); static int removeParts(int parts, const std::string& new_parts); diff --git a/headers/modsecurity/collection/collection.h b/headers/modsecurity/collection/collection.h index db80e8e789..0511a05fd3 100644 --- a/headers/modsecurity/collection/collection.h +++ b/headers/modsecurity/collection/collection.h @@ -57,16 +57,16 @@ class Collection { virtual void del(const std::string& key) = 0; virtual std::unique_ptr resolveFirst( - const std::string& var) = 0; + const std::string& var) const = 0; virtual void resolveSingleMatch(const std::string& var, - std::vector *l) = 0; + VariableValues *l) const noexcept = 0; virtual void resolveMultiMatches(const std::string& var, - std::vector *l, - variables::KeyExclusions &ke) = 0; + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept = 0; virtual void resolveRegularExpression(const std::string& var, - std::vector *l, - variables::KeyExclusions &ke) = 0; + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept = 0; /* store */ @@ -131,14 +131,14 @@ class Collection { /* resolveFirst */ virtual std::unique_ptr resolveFirst(const std::string& var, - std::string compartment) { + const std::string &compartment) const noexcept { std::string nkey = compartment + "::" + var; return resolveFirst(nkey); } virtual std::unique_ptr resolveFirst(const std::string& var, - std::string compartment, std::string compartment2) { + const std::string &compartment, const std::string &compartment2) const noexcept { std::string nkey = compartment + "::" + compartment2 + "::" + var; return resolveFirst(nkey); } @@ -146,15 +146,15 @@ class Collection { /* resolveSingleMatch */ virtual void resolveSingleMatch(const std::string& var, - std::string compartment, std::vector *l) { + const std::string &compartment, VariableValues *l) const noexcept { std::string nkey = compartment + "::" + var; resolveSingleMatch(nkey, l); } virtual void resolveSingleMatch(const std::string& var, - std::string compartment, std::string compartment2, - std::vector *l) { + const std::string &compartment, const std::string &compartment2, + VariableValues *l) const noexcept { std::string nkey = compartment + "::" + compartment2 + "::" + var; resolveSingleMatch(nkey, l); } @@ -162,17 +162,17 @@ class Collection { /* resolveMultiMatches */ virtual void resolveMultiMatches(const std::string& var, - std::string compartment, std::vector *l, - variables::KeyExclusions &ke) { + const std::string &compartment, VariableValues *l, + const variables::KeyExclusions &ke) const noexcept { std::string nkey = compartment + "::" + var; resolveMultiMatches(nkey, l, ke); } virtual void resolveMultiMatches(const std::string& var, - std::string compartment, std::string compartment2, - std::vector *l, - variables::KeyExclusions &ke) { + const std::string &compartment, const std::string &compartment2, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept { std::string nkey = compartment + "::" + compartment2 + "::" + var; resolveMultiMatches(nkey, l, ke); } @@ -180,16 +180,16 @@ class Collection { /* resolveRegularExpression */ virtual void resolveRegularExpression(const std::string& var, - std::string compartment, std::vector *l, - variables::KeyExclusions &ke) { + const std::string &compartment, VariableValues *l, + const variables::KeyExclusions &ke) const noexcept { std::string nkey = compartment + "::" + var; resolveRegularExpression(nkey, l, ke); } virtual void resolveRegularExpression(const std::string& var, - std::string compartment, std::string compartment2, - std::vector *l, variables::KeyExclusions &ke) { + const std::string &compartment, const std::string &compartment2, + VariableValues *l, const variables::KeyExclusions &ke) const noexcept { std::string nkey = compartment + "::" + compartment2 + "::" + var; resolveRegularExpression(nkey, l, ke); } diff --git a/headers/modsecurity/modsecurity.h b/headers/modsecurity/modsecurity.h index 83cdfd7e8f..9739c5bc9f 100644 --- a/headers/modsecurity/modsecurity.h +++ b/headers/modsecurity/modsecurity.h @@ -78,6 +78,7 @@ #include #include #include +#include #endif @@ -89,6 +90,18 @@ typedef struct ModSecurity_t modsecurity; #else namespace modsecurity { + /** + * Further that will be changed to be a stack-based string, + * for the benefit of performance. + */ + using ModSecString = std::string; + + using RulesErrors = std::vector>; + using RulesWarnings = std::vector>; + + + using RuleId = int64_t; + /** * * The Phases enumerator consists in mapping the different stages of a @@ -292,7 +305,7 @@ class ModSecurity { */ void setServerLogCb(ModSecLogCb cb, int properties); - void serverLog(void *data, std::shared_ptr rm); + void serverLog(void *data, RuleMessage *rm); const std::string& getConnectorInformation() const; diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index a8426c61f4..77507f941f 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 { @@ -36,47 +37,33 @@ namespace variables { class Variable; class Variables; } -namespace actions { -class Action; -class Severity; -class LogData; -class Msg; -class Rev; -class SetVar; -class Tag; -namespace transformations { -class Transformation; -} -} namespace operators { class Operator; } -using TransformationResult = std::pair, - std::shared_ptr>; -using TransformationResults = std::list; - -using Transformation = actions::transformations::Transformation; -using Transformations = std::vector; - -using Actions = std::vector; - -using Tags = std::vector; -using SetVars = std::vector; -using MatchActions = std::vector; class Rule { public: Rule(std::unique_ptr fileName, int lineNumber) : m_fileName(std::move(fileName)), m_lineNumber(lineNumber), - m_phase(modsecurity::Phases::RequestHeadersPhase) { - } - - virtual bool evaluate(Transaction *transaction) = 0; + m_phase(modsecurity::Phases::RequestHeadersPhase) + { } + + Rule(const Rule &r) + : m_fileName(r.m_fileName), + m_lineNumber(r.m_lineNumber), + m_phase(r.m_phase) + { } + + Rule &operator=(const Rule& other) { + m_fileName = other.m_fileName; + m_lineNumber = other.m_lineNumber; + m_phase = other.m_phase; + return *this; + } - virtual bool evaluate(Transaction *transaction, - std::shared_ptr rm) = 0; + virtual bool evaluate(Transaction *transaction) const = 0; std::shared_ptr getFileName() const { return m_fileName; @@ -89,12 +76,21 @@ class Rule { int getPhase() const { return m_phase; } void setPhase(int phase) { m_phase = phase; } - virtual std::string getReference() { + virtual std::string getReference() const { return *m_fileName + ":" + std::to_string(m_lineNumber); } + virtual void dump(std::stringstream &out) const { + out << getOriginInTextFormat() << std::endl; + } - virtual bool isMarker() { return false; } + protected: + std::string getOriginInTextFormat() const { + std::stringstream ss; + ss << "# File name: " << *getFileName() << std::endl; + ss << "# Line number: " << getLineNumber(); + return ss.str(); + } private: std::shared_ptr m_fileName; diff --git a/headers/modsecurity/rule_message.h b/headers/modsecurity/rule_message.h index b7f2306069..3dfdec17bd 100644 --- a/headers/modsecurity/rule_message.h +++ b/headers/modsecurity/rule_message.h @@ -26,14 +26,15 @@ #include "modsecurity/transaction.h" #include "modsecurity/rule.h" -#include "modsecurity/rule_with_operator.h" #ifdef __cplusplus namespace modsecurity { - - +namespace actions { +class Tag; +}; +class RuleWithActions; class RuleMessage { public: @@ -42,67 +43,49 @@ class RuleMessage { ClientLogMessageInfo = 4 }; - /** - * - * FIXME: RuleMessage is currently too big, doing a lot of - * unnecessary data duplication. Needs to be shrink down. - * - */ - RuleMessage(RuleWithActions *rule, Transaction *trans) : - m_accuracy(rule->m_accuracy), - m_clientIpAddress(trans->m_clientIpAddress), + + explicit RuleMessage(const RuleMessage &ruleMessage) : + m_severity(ruleMessage.m_severity), + m_tags(), + m_data(ruleMessage.m_data), + m_match(ruleMessage.m_match), + m_message(ruleMessage.m_message), + m_reference(ruleMessage.m_reference), + m_transaction(ruleMessage.m_transaction), + m_rule(ruleMessage.m_rule) + { } + + + RuleMessage &operator=(const RuleMessage& ruleMessage) { + m_severity = ruleMessage.m_severity; + m_tags = ruleMessage.m_tags; + m_data = ruleMessage.m_data; + m_match = ruleMessage.m_match; + m_message = ruleMessage.m_message; + m_reference = ruleMessage.m_reference; + m_transaction = ruleMessage.m_transaction; + m_rule = ruleMessage.m_rule; + return *this; + } + + + explicit RuleMessage(Transaction *transaction) : + m_severity(0), + m_tags(), m_data(""), - m_id(trans->m_id), - m_isDisruptive(false), m_match(""), - m_maturity(rule->m_maturity), m_message(""), - m_noAuditLog(false), - m_phase(rule->getPhase() - 1), m_reference(""), - m_rev(rule->m_rev), - m_rule(rule), - m_ruleFile(rule->getFileName()), - m_ruleId(rule->m_ruleId), - m_ruleLine(rule->getLineNumber()), - m_saveMessage(true), - m_serverIpAddress(trans->m_serverIpAddress), - m_severity(0), - m_uriNoQueryStringDecoded(trans->m_uri_no_query_string_decoded), - m_ver(rule->m_ver) + m_transaction(transaction), + m_rule(nullptr) { } - explicit RuleMessage(RuleMessage *rule) : - m_accuracy(rule->m_accuracy), - m_clientIpAddress(rule->m_clientIpAddress), - m_data(rule->m_data), - m_id(rule->m_id), - m_isDisruptive(rule->m_isDisruptive), - m_match(rule->m_match), - m_maturity(rule->m_maturity), - m_message(rule->m_message), - m_noAuditLog(rule->m_noAuditLog), - m_phase(rule->m_phase), - m_reference(rule->m_reference), - m_rev(rule->m_rev), - m_rule(rule->m_rule), - m_ruleFile(rule->m_ruleFile), - m_ruleId(rule->m_ruleId), - m_ruleLine(rule->m_ruleLine), - m_saveMessage(rule->m_saveMessage), - m_serverIpAddress(rule->m_serverIpAddress), - m_severity(rule->m_severity), - m_uriNoQueryStringDecoded(rule->m_uriNoQueryStringDecoded), - m_ver(rule->m_ver) - { } void clean() { m_data = ""; m_match = ""; - m_isDisruptive = false; m_reference = ""; m_severity = 0; - m_ver = ""; } std::string log() { @@ -130,29 +113,38 @@ class RuleMessage { static std::string _details(const RuleMessage *rm); static std::string _errorLogTail(const RuleMessage *rm); - int m_accuracy; - std::shared_ptr m_clientIpAddress; + const RuleWithActions *getRule() const; + void setRule(const RuleWithActions *rule); + bool isSettle() const; + int getRuleId() const; + int getPhase() const; + std::string getFileName() const; + int getLineNumber() const; + std::string getRev() const; + std::string getVer() const; + int getMaturity() const; + int getAccuracy() const; + std::string getClientIpAddress() const; + std::string getServerIpAddress() const; + std::string getRequestId() const; + std::string getUri() const; + bool isDisruptive() const; + + bool toBeAuditLog() const; + + int m_severity; + std::list m_tags; + + // Transaction std::string m_data; - std::shared_ptr m_id; - bool m_isDisruptive; std::string m_match; - int m_maturity; + std::string m_message; - bool m_noAuditLog; - int m_phase; std::string m_reference; - std::string m_rev; - RuleWithActions *m_rule; - std::shared_ptr m_ruleFile; - int m_ruleId; - int m_ruleLine; - bool m_saveMessage; - std::shared_ptr m_serverIpAddress; - int m_severity; - std::shared_ptr m_uriNoQueryStringDecoded; - std::string m_ver; - std::list m_tags; + private: + Transaction *m_transaction; + const RuleWithActions *m_rule; }; diff --git a/headers/modsecurity/rule_with_actions.h b/headers/modsecurity/rule_with_actions.h deleted file mode 100644 index 340048382e..0000000000 --- a/headers/modsecurity/rule_with_actions.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 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. - * - */ - -#ifdef __cplusplus -#include -#include -#include -#include -#include -#include -#endif - -#ifndef HEADERS_MODSECURITY_RULE_WITH_ACTIONS_H_ -#define HEADERS_MODSECURITY_RULE_WITH_ACTIONS_H_ - -#include "modsecurity/transaction.h" -#include "modsecurity/modsecurity.h" -#include "modsecurity/variable_value.h" -#include "modsecurity/rule.h" - -#ifdef __cplusplus - -namespace modsecurity { - - -class RuleWithActions : public Rule { - public: - RuleWithActions( - Actions *a, - Transformations *t, - std::unique_ptr fileName, - int lineNumber); - - ~RuleWithActions(); - - virtual bool evaluate(Transaction *transaction, std::shared_ptr ruleMessage) override; - - virtual bool evaluate(Transaction *transaction) override; - - - void executeActionsIndependentOfChainedRuleResult( - Transaction *trasn, - bool *containsDisruptive, - std::shared_ptr ruleMessage); - - void executeActionsAfterFullMatch( - Transaction *trasn, - bool containsDisruptive, - std::shared_ptr ruleMessage); - - void executeAction(Transaction *trans, - bool containsBlock, - std::shared_ptr ruleMessage, - actions::Action *a, - bool context); - - - void executeTransformations( - Transaction *trasn, const std::string &value, TransformationResults &ret); - - inline void executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const; - - - void performLogging(Transaction *trans, - std::shared_ptr ruleMessage, - bool lastLog = true, - bool chainedParentNull = false); - - std::vector getActionsByName(const std::string& name, - Transaction *t); - bool containsTag(const std::string& name, Transaction *t); - bool containsMsg(const std::string& name, Transaction *t); - - inline bool isChained() const { return m_isChained == true; } - inline bool hasCaptureAction() const { return m_containsCaptureAction == true; } - inline void setChained(bool b) { m_isChained = b; } - inline bool hasDisruptiveAction() const { return m_disruptiveAction != NULL; } - inline bool hasBlockAction() const { return m_containsStaticBlockAction == true; } - inline bool hasMultimatch() const { return m_containsMultiMatchAction == true; } - - inline bool hasLogData() const { return m_logData != NULL; } - std::string logData(Transaction *t); - inline bool hasMsg() const { return m_msg != NULL; } - std::string msg(Transaction *t); - inline bool hasSeverity() const { return m_severity != NULL; } - int severity() const; - - std::string m_rev; - std::string m_ver; - int m_accuracy; - int m_maturity; - - - int64_t m_ruleId; - - std::unique_ptr m_chainedRuleChild; - RuleWithActions *m_chainedRuleParent; - - private: - /* actions */ - actions::Action *m_disruptiveAction; - actions::LogData *m_logData; - actions::Msg *m_msg; - actions::Severity *m_severity; - MatchActions m_actionsRuntimePos; - SetVars m_actionsSetVar; - Tags m_actionsTag; - - /* actions > transformations */ - Transformations m_transformations; - - bool m_containsCaptureAction:1; - bool m_containsMultiMatchAction:1; - bool m_containsStaticBlockAction:1; - bool m_isChained:1; -}; - -} // namespace modsecurity -#endif - - -#endif // HEADERS_MODSECURITY_RULE_WITH_ACTIONS_H_ \ No newline at end of file diff --git a/headers/modsecurity/rule_with_operator.h b/headers/modsecurity/rule_with_operator.h deleted file mode 100644 index 63aff6c469..0000000000 --- a/headers/modsecurity/rule_with_operator.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 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. - * - */ - -#ifdef __cplusplus -#include -#include -#include -#include -#include -#include -#endif - -#ifndef HEADERS_MODSECURITY_RULE_WITH_OPERATOR_H_ -#define HEADERS_MODSECURITY_RULE_WITH_OPERATOR_H_ - -#include "modsecurity/transaction.h" -#include "modsecurity/modsecurity.h" -#include "modsecurity/variable_value.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_with_actions.h" - -#ifdef __cplusplus - -namespace modsecurity { - - -class RuleWithOperator : public RuleWithActions { - public: - RuleWithOperator(operators::Operator *op, - variables::Variables *variables, - std::vector *actions, - Transformations *transformations, - std::unique_ptr fileName, - int lineNumber); - - virtual ~RuleWithOperator(); - - bool evaluate(Transaction *transaction, - std::shared_ptr rm) override; - - void getVariablesExceptions(Transaction *t, - variables::Variables *exclusion, variables::Variables *addition); - inline void getFinalVars(variables::Variables *vars, - variables::Variables *eclusion, Transaction *trans); - - bool executeOperatorAt(Transaction *trasn, const std::string &key, - std::string value, std::shared_ptr rm); - - static void updateMatchedVars(Transaction *trasn, const std::string &key, - const std::string &value); - static void cleanMatchedVars(Transaction *trasn); - - - std::string getOperatorName() const; - - virtual std::string getReference() override { - return std::to_string(m_ruleId); - } - - private: - modsecurity::variables::Variables *m_variables; - operators::Operator *m_operator; -}; - - -} // namespace modsecurity -#endif - - -#endif // HEADERS_MODSECURITY_RULE_WITH_OPERATOR_H_ diff --git a/headers/modsecurity/rules.h b/headers/modsecurity/rules.h index afdd030c27..3721f8bb5b 100644 --- a/headers/modsecurity/rules.h +++ b/headers/modsecurity/rules.h @@ -27,64 +27,53 @@ #endif #include "modsecurity/rule.h" -#include "modsecurity/rule_with_operator.h" -#include "modsecurity/rule_with_actions.h" + #ifndef HEADERS_MODSECURITY_RULES_H_ #define HEADERS_MODSECURITY_RULES_H_ - #ifdef __cplusplus namespace modsecurity { +namespace actions { +namespace transformations { +class Transformation; +} +} class Rules { public: - void dump() const { - for (int j = 0; j < m_rules.size(); j++) { - std::cout << " Rule ID: " << m_rules.at(j)->getReference(); - std::cout << "--" << m_rules.at(j) << std::endl; - } - } - - int append(Rules *from, const std::vector &ids, std::ostringstream *err) { - size_t j = 0; - for (; j < from->size(); j++) { - RuleWithOperator *rule = dynamic_cast(from->at(j).get()); - if (rule && std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) { - if (err != NULL) { - *err << "Rule id: " << std::to_string(rule->m_ruleId) \ - << " is duplicated" << std::endl; - } - return -1; - } - } - m_rules.insert(m_rules.end(), from->m_rules.begin(), from->m_rules.end()); - return j; - } - - bool insert(std::shared_ptr rule) { - return insert(rule, nullptr, nullptr); - } - - bool insert(std::shared_ptr rule, const std::vector *ids, std::ostringstream *err) { - RuleWithOperator *r = dynamic_cast(rule.get()); - if (r && ids != nullptr && std::binary_search(ids->begin(), ids->end(), r->m_ruleId)) { - if (err != nullptr) { - *err << "Rule id: " << std::to_string(r->m_ruleId) \ - << " is duplicated" << std::endl; - } - return false; - } - m_rules.push_back(rule); - return true; - } - - size_t size() const { return m_rules.size(); } - std::shared_ptr operator[](int index) const { return m_rules[index]; } - std::shared_ptr at(int index) const { return m_rules[index]; } - - std::vector > m_rules; + using container=std::vector>; + using iterator=typename container::iterator; + using const_iterator=typename container::const_iterator; + + int append(Rules *from); + + bool insert(const std::shared_ptr &rule); + + size_t size() const; + + std::shared_ptr operator[](int index) const; + std::shared_ptr at(int index) const; + + void fixDefaultActions(RulesWarnings *warnings, RulesErrors *errors); + + std::vector > m_defaultActions; + std::vector > m_defaultTransformations; + + virtual void dump() { + std::stringstream ss; + dump(ss); + std::cout << ss.str(); + }; + virtual void dump(std::stringstream &out); + + inline iterator begin() noexcept { return m_rules.begin(); } + inline const_iterator cbegin() const noexcept { return m_rules.cbegin(); } + inline iterator end() noexcept { return m_rules.end(); } + inline const_iterator cend() const noexcept { return m_rules.cend(); } + private: + container m_rules; }; diff --git a/headers/modsecurity/rules_exceptions.h b/headers/modsecurity/rules_exceptions.h index a8bcf17392..8b24343e20 100644 --- a/headers/modsecurity/rules_exceptions.h +++ b/headers/modsecurity/rules_exceptions.h @@ -28,6 +28,8 @@ #include #endif +#include "modsecurity/modsecurity.h" + #ifndef HEADERS_MODSECURITY_RULES_EXCEPTIONS_H_ #define HEADERS_MODSECURITY_RULES_EXCEPTIONS_H_ @@ -37,6 +39,9 @@ namespace modsecurity { namespace actions { class Action; +namespace transformations { +class Transformation; +} } namespace variables { class Variable; @@ -48,9 +53,9 @@ class RulesExceptions { ~RulesExceptions(); bool load(const std::string &data, std::string *error); - bool addRange(int a, int b); - bool addNumber(int a); - bool contains(int a); + bool addRange(RuleId a, RuleId b); + bool addNumber(RuleId a); + bool contains(RuleId a); bool merge(RulesExceptions *from); bool loadRemoveRuleByMsg(const std::string &msg, std::string *error); @@ -64,11 +69,11 @@ class RulesExceptions { std::unique_ptr > > v, std::string *error); - bool loadUpdateTargetById(double id, + bool loadUpdateTargetById(RuleId id, std::unique_ptr > > v, std::string *error); - bool loadUpdateActionById(double id, + bool loadUpdateActionById(RuleId id, std::unique_ptr > > actions, std::string *error); @@ -76,18 +81,18 @@ class RulesExceptions { std::shared_ptr> m_variable_update_target_by_tag; std::unordered_multimap, std::shared_ptr> m_variable_update_target_by_msg; - std::unordered_multimap> m_variable_update_target_by_id; - std::unordered_multimap> m_action_pre_update_target_by_id; - std::unordered_multimap> m_action_transformation_update_target_by_id; + std::unordered_multimap> m_action_pos_update_target_by_id; std::list m_remove_rule_by_msg; std::list m_remove_rule_by_tag; private: - std::list > m_ranges; - std::list m_numbers; + std::list > m_ranges; + std::list m_numbers; }; } // namespace modsecurity diff --git a/headers/modsecurity/rules_set.h b/headers/modsecurity/rules_set.h index e587033324..7732415512 100644 --- a/headers/modsecurity/rules_set.h +++ b/headers/modsecurity/rules_set.h @@ -22,6 +22,7 @@ #include #include #include +#include #endif @@ -42,8 +43,6 @@ namespace Parser { class Driver; } - - /** @ingroup ModSecurity_CPP_API */ class RulesSet : public RulesSetProperties { public: @@ -68,12 +67,13 @@ class RulesSet : public RulesSetProperties { int load(const char *rules); int load(const char *rules, const std::string &ref); - void dump() const; + void dump(); int merge(Parser::Driver *driver); int merge(RulesSet *rules); int evaluate(int phase, Transaction *transaction); + std::string getParserError(); void debug(int level, const std::string &id, const std::string &uri, @@ -81,6 +81,7 @@ class RulesSet : public RulesSetProperties { RulesSetPhases m_rulesSetPhases; private: + bool containsDuplicatedIds(RulesWarnings *warnings, RulesErrors *errors); #ifndef NO_LOGS uint8_t m_secmarker_skipped; #endif diff --git a/headers/modsecurity/rules_set_phases.h b/headers/modsecurity/rules_set_phases.h index 59d3fdf3da..2b9b67c937 100644 --- a/headers/modsecurity/rules_set_phases.h +++ b/headers/modsecurity/rules_set_phases.h @@ -23,6 +23,7 @@ #include #include #include +#include #endif @@ -42,18 +43,33 @@ class Driver; /** @ingroup ModSecurity_CPP_API */ class RulesSetPhases { public: + using container = std::array; + using iterator = typename container::iterator; + using const_iterator = typename container::const_iterator; - bool insert(std::shared_ptr rule); + void insert(std::shared_ptr rule); + void append(RulesSetPhases *from); int append(RulesSetPhases *from, std::ostringstream *err); - void dump() const; + void dump(); - Rules *operator[](int index) { return &m_rulesAtPhase[index]; } - Rules *at(int index) { return &m_rulesAtPhase[index]; } + Rules *operator[](int index); + Rules *at(int index); + static size_t size() { return modsecurity::Phases::NUMBER_OF_PHASES; } - private: - Rules m_rulesAtPhase[8]; + void fixDefaultActions(RulesWarnings *warnings, RulesErrors *errors) { + for (auto &phase : m_rulesAtPhase) { + phase.fixDefaultActions(warnings, errors); + } + } + + inline iterator begin() noexcept { return m_rulesAtPhase.begin(); } + inline const_iterator cbegin() const noexcept { return m_rulesAtPhase.cbegin(); } + inline iterator end() noexcept { return m_rulesAtPhase.end(); } + inline const_iterator cend() const noexcept { return m_rulesAtPhase.cend(); } + private: + container m_rulesAtPhase; }; diff --git a/headers/modsecurity/rules_set_properties.h b/headers/modsecurity/rules_set_properties.h index 6a6d4262a2..e90b1ec86c 100644 --- a/headers/modsecurity/rules_set_properties.h +++ b/headers/modsecurity/rules_set_properties.h @@ -201,16 +201,6 @@ class RulesSetProperties { RulesSetProperties &operator =(const RulesSetProperties &r) = delete; ~RulesSetProperties() { - int i = 0; - - for (i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) { - std::vector > *tmp = \ - &m_defaultActions[i]; - while (tmp->empty() == false) { - tmp->pop_back(); - } - } - delete m_debugLog; delete m_auditLog; } @@ -340,7 +330,9 @@ class RulesSetProperties { static int mergeProperties(RulesSetProperties *from, - RulesSetProperties *to, std::ostringstream *err) { + RulesSetProperties *to, + RulesWarnings *warning, + RulesErrors *error) { merge_ruleengine_value(to->m_secRuleEngine, from->m_secRuleEngine, PropertyNotSetRuleEngine); @@ -410,21 +402,11 @@ class RulesSetProperties { to->m_responseBodyTypeToBeInspected.m_set = true; } - for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) { - std::vector > *actions_from = \ - &from->m_defaultActions[i]; - std::vector > *actions_to = \ - &to->m_defaultActions[i]; - for (size_t j = 0; j < actions_from->size(); j++) { - actions_to->push_back(actions_from->at(j)); - } - } - if (to->m_auditLog) { - std::string error; - to->m_auditLog->merge(from->m_auditLog, &error); - if (error.size() > 0) { - *err << error; + std::string error_; + to->m_auditLog->merge(from->m_auditLog, &error_); + if (error_.size() > 0) { + error->push_back(std::unique_ptr(new std::string(error_))); return -1; } } @@ -432,12 +414,12 @@ class RulesSetProperties { if (from->m_debugLog && to->m_debugLog && from->m_debugLog->isLogFileSet()) { if (to->m_debugLog->isLogFileSet() == false) { - std::string error; + std::string error_; to->m_debugLog->setDebugLogFile( from->m_debugLog->getDebugLogFile(), - &error); - if (error.size() > 0) { - *err << error; + &error_); + if (error_.size() > 0) { + error->push_back(std::unique_ptr(new std::string(error_))); return -1; } } @@ -481,8 +463,6 @@ class RulesSetProperties { ConfigString m_uploadTmpDirectory; ConfigString m_secArgumentSeparator; ConfigString m_secWebAppId; - std::vector > \ - m_defaultActions[modsecurity::Phases::NUMBER_OF_PHASES]; ConfigUnicodeMap m_unicodeMapTable; }; diff --git a/headers/modsecurity/string_view.hpp b/headers/modsecurity/string_view.hpp new file mode 100644 index 0000000000..ce9929534b --- /dev/null +++ b/headers/modsecurity/string_view.hpp @@ -0,0 +1,1422 @@ +/** + * \file string_view.hpp + * + * \brief This header contains the definition of the string_view type, as + * described by the C++17 standard. + * + * \author Matthew Rodusek (matthew.rodusek@gmail.com) + * \copyright Matthew Rodusek + */ + +/* + * The MIT License (MIT) + * + * Licensed under the MIT License . + * Copyright (c) 2016 Matthew Rodusek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef BPSTD_STRING_VIEW_HPP +#define BPSTD_STRING_VIEW_HPP + +#include // std:: +#include // std::char_traits +#include // std::basic_ostream +#include // std::size_t +#include // std::allocator +#include // std::out_of_range +#include // std::reverse_iterator +namespace bpstd { // back-port std + + //////////////////////////////////////////////////////////////////////////// + /// \brief A wrapper around non-owned strings. + /// + /// This is an implementation of the C++17 string_view proposal + /// + /// \ingroup core + //////////////////////////////////////////////////////////////////////////// + template< + typename CharT, + typename Traits = std::char_traits + > + class basic_string_view final + { + //------------------------------------------------------------------------ + // Public Member Types + //------------------------------------------------------------------------ + public: + + using char_type = CharT; + using traits_type = Traits; + using size_type = std::size_t; + + using value_type = CharT; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + + using iterator = const CharT*; + using const_iterator = const CharT*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + //------------------------------------------------------------------------ + // Public Members + //------------------------------------------------------------------------ + public: + + static constexpr size_type npos = size_type(-1); + + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + public: + + /// \brief Default constructs a basic_string_view without any content + constexpr basic_string_view() noexcept; + + /// \brief Constructs a basic_string_view by copying another one + /// + /// \param other the string view being copied + constexpr basic_string_view(const basic_string_view& other) noexcept = default; + + /// \brief Constructs a basic_string_view by moving anothe rone + /// + /// \param other the string view being moved + constexpr basic_string_view(basic_string_view&& other) noexcept = default; + + /// \brief Constructs a basic_string_view from a std::basic_string + /// + /// \param str the string to view + template + basic_string_view(const std::basic_string& str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi-string + /// + /// \param str the string to view + constexpr basic_string_view(const char_type* str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi string of a given size + /// + /// \param str the string to view + /// \param count the size of the string + constexpr basic_string_view(const char_type* str, size_type count) noexcept; + + //------------------------------------------------------------------------ + // Assignment + //------------------------------------------------------------------------ + public: + + /// \brief Assigns a basic_string_view from an ansi-string + /// + /// \param view the string to view + /// \return reference to \c (*this) + basic_string_view& operator=(const basic_string_view& view) = default; + + //------------------------------------------------------------------------ + // Capacity + //------------------------------------------------------------------------ + public: + + /// \brief Returns the length of the string, in terms of bytes + /// + /// \return the length of the string, in terms of bytes + constexpr size_type size() const noexcept; + + /// \copydoc basic_string_view::size + constexpr size_type length() const noexcept; + + /// \brief The largest possible number of char-like objects that can be + /// referred to by a basic_string_view. + /// \return Maximum number of characters + constexpr size_type max_size() const noexcept; + + /// \brief Returns whether the basic_string_view is empty + /// (i.e. whether its length is 0). + /// + /// \return whether the basic_string_view is empty + constexpr bool empty() const noexcept; + + //------------------------------------------------------------------------ + // Element Access + //------------------------------------------------------------------------ + public: + + /// \brief Gets the ansi-string of the current basic_string_view + /// + /// \return the ansi-string pointer + constexpr const char_type* c_str() const noexcept; + + /// \brief Gets the data of the current basic_string_view + /// + /// \note This is an alias of #c_str + /// + /// \return the data this basic_string_view contains + constexpr const char_type* data() const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference operator[](size_type pos) const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference at(size_type pos) const; + + /// \brief Access the first character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the first character of the string + constexpr const_reference front() const noexcept; + + /// \brief References the last character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the last character of the string + constexpr const_reference back() const noexcept; + + //------------------------------------------------------------------------ + // Modifiers + //------------------------------------------------------------------------ + public: + + /// \brief Moves the start of the view forward by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the start of the view + void remove_prefix(size_type n) noexcept; + + /// \brief Moves the end of the view back by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the end of the view + void remove_suffix(size_type n) noexcept; + + /// \brief Exchanges the view with that of v. + /// + /// \param v view to swap with + void swap(basic_string_view& v) noexcept; + + //------------------------------------------------------------------------ + // Conversions + //------------------------------------------------------------------------ + public: + + /// \brief Creates a basic_string with a copy of the content of the current view. + /// + /// \tparam Allocator type used to allocate internal storage + /// \param a Allocator instance to use for allocating the new string + /// + /// \return A basic_string containing a copy of the characters of the current view. + template> + constexpr std::basic_string + to_string(const Allocator& a = Allocator()) const; + + /// \copydoc basic_string_view::to_string + template + explicit constexpr operator std::basic_string() const; + + //------------------------------------------------------------------------ + // Operations + //------------------------------------------------------------------------ + public: + + /// \brief Copies the substring [pos, pos + rcount) to the character string pointed + /// to by dest, where rcount is the smaller of count and size() - pos. + /// + /// \param dest pointer to the destination character string + /// \param count requested substring length + /// \param pos position of the first character + size_type copy( char_type* dest, + size_type count = npos, + size_type pos = 0 ) const; + + /// \brief Returns a substring of this viewed string + /// + /// \param pos the position of the first character in the substring + /// \param len the length of the substring + /// \return the created substring + basic_string_view substr(size_t pos = 0, size_t len = npos) const; + + //------------------------------------------------------------------------ + + /// \brief Compares two character sequences + /// + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(basic_string_view v) const noexcept; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(size_type pos, size_type count, basic_string_view v) const; + + /// \brief Compares two character sequences + /// + /// \param pos1 position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param v view to compare + /// \param pos2 position of the second character in this view to compare + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare( size_type pos1, size_type count1, basic_string_view v, + size_type pos2, size_type count2 ) const; + + /// \brief Compares two character sequences + /// + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare(size_type pos, size_type count, const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + int compare( size_type pos, size_type count1, const char_type* s, + size_type count2 ) const; + + //------------------------------------------------------------------------ + + size_type find(basic_string_view v, size_type pos = 0) const; + + size_type find(char_type c, size_type pos = 0) const; + + size_type find(const char_type* s, size_type pos, size_type count) const; + + size_type find(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type rfind(basic_string_view v, size_type pos = npos) const; + + size_type rfind(char_type c, size_type pos = npos) const; + + size_type rfind(const char_type* s, size_type pos, size_type count) const; + + size_type rfind(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + + size_type find_first_of(basic_string_view v, size_type pos = 0) const; + + size_type find_first_of(char_type c, size_type pos = 0) const; + + size_type find_first_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_first_of(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type find_last_of(basic_string_view v, size_type pos = npos) const; + + size_type find_last_of(char_type c, size_type pos = npos) const; + + size_type find_last_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_last_of(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + + size_type find_first_not_of(basic_string_view v, size_type pos = 0) const; + + size_type find_first_not_of(char_type c, size_type pos = 0) const; + + size_type find_first_not_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_first_not_of(const char_type* s, size_type pos = 0) const; + + //------------------------------------------------------------------------ + + size_type find_last_not_of(basic_string_view v, size_type pos = npos) const; + + size_type find_last_not_of(char_type c, size_type pos = npos) const; + + size_type find_last_not_of(const char_type* s, size_type pos, size_type count) const; + + size_type find_last_not_of(const char_type* s, size_type pos = npos) const; + + //------------------------------------------------------------------------ + // Iterators + //------------------------------------------------------------------------ + public: + + /// \{ + /// \brief Retrieves the begin iterator for this basic_string_view + /// + /// \return the begin iterator + const_iterator begin() const noexcept; + const_iterator cbegin() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the end iterator for this basic_string_view + /// + /// \return the end iterator + const_iterator end() const noexcept; + const_iterator cend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse begin iterator for this basic_string_view + /// + /// \return the reverse begin iterator + const_reverse_iterator rbegin() const noexcept; + const_reverse_iterator rend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse end iterator for this basic_string_view + /// + /// \return the reverse end iterator + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + /// \} + + //------------------------------------------------------------------------ + // Private Member + //------------------------------------------------------------------------ + private: + + const char_type* m_str; ///< The internal string type + size_type m_size; ///< The size of this string + + /// \brief Checks whether \p c is one of the characters in \p str + /// + /// \param c the character to check + /// \param str the characters to compare against + /// \return true if \p c is one of the characters in \p str + static bool is_one_of(CharT c, basic_string_view str); + }; + + template + const typename basic_string_view::size_type + basic_string_view::npos; + + //-------------------------------------------------------------------------- + // Public Functions + //-------------------------------------------------------------------------- + + /// \brief Overload for ostream output of basic_string_view + /// + /// \param o The output stream to print to + /// \param str the string to print + /// \return reference to the output stream + template + std::basic_ostream& operator<<(std::basic_ostream& o, + const basic_string_view& str); + + template + void swap(basic_string_view& lhs, + basic_string_view& rhs) noexcept; + + //-------------------------------------------------------------------------- + // Comparison Functions + //-------------------------------------------------------------------------- + + template + bool operator==(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator<(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator>(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + bool operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + + //-------------------------------------------------------------------------- + // Type Aliases + //-------------------------------------------------------------------------- + + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + +} // namespace bpstd + +#ifndef BPSTD_DETAIL_STRING_VIEW_INL +#define BPSTD_DETAIL_STRING_VIEW_INL + +namespace bpstd { + + //-------------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------------- + + template + inline constexpr basic_string_view::basic_string_view() + noexcept + : m_str(nullptr), + m_size(0) + { + + } + + template + template + inline basic_string_view::basic_string_view(const std::basic_string& str) + noexcept + : m_str(str.c_str()), + m_size(str.size()) + { + + } + + template + inline constexpr basic_string_view::basic_string_view(const char_type* str) + noexcept + : m_str(str), + m_size(traits_type::length(str)) + { + + } + + template + inline constexpr basic_string_view::basic_string_view(const char_type* str, size_type count) + noexcept + : m_str(str), + m_size(count) + { + + } + + //-------------------------------------------------------------------------- + // Capacity + //-------------------------------------------------------------------------- + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::size() + const noexcept + { + return m_size; + } + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::length() + const noexcept + { + return size(); + } + + template + inline constexpr typename basic_string_view::size_type + basic_string_view::max_size() + const noexcept + { + return npos - 1; + } + + template + inline constexpr bool basic_string_view::empty() + const noexcept + { + return m_size == 0; + } + + //-------------------------------------------------------------------------- + // Element Access + //-------------------------------------------------------------------------- + + template + inline constexpr const typename basic_string_view::char_type* + basic_string_view::c_str() + const noexcept + { + return m_str; + } + + template + inline constexpr const typename basic_string_view::char_type* + basic_string_view::data() + const noexcept + { + return m_str; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::operator[](size_type pos) + const noexcept + { + return m_str[pos]; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::at(size_type pos) + const + { + return pos < m_size ? m_str[pos] : throw std::out_of_range("Input out of range in basic_string_view::at"), m_str[pos]; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::front( ) + const noexcept + { + return *m_str; + } + + template + inline constexpr typename basic_string_view::const_reference + basic_string_view::back( ) + const noexcept + { + return m_str[m_size-1]; + } + + //-------------------------------------------------------------------------- + // Modifiers + //-------------------------------------------------------------------------- + + template + inline void + basic_string_view::remove_prefix(size_type n) + noexcept + { + m_str += n, m_size -= n; + } + + template + inline void + basic_string_view::remove_suffix(size_type n) + noexcept + { + m_size -= n; + } + + template + inline void + basic_string_view::swap(basic_string_view& v) + noexcept + { + using std::swap; + swap(m_size,v.m_size); + swap(m_str,v.m_str); + } + + //-------------------------------------------------------------------------- + // Conversions + //-------------------------------------------------------------------------- + + template + template + inline constexpr std::basic_string + basic_string_view::to_string(const Allocator& a) + const + { + return std::basic_string(m_str, m_size, a); + } + + template + template + inline constexpr basic_string_view::operator + std::basic_string() + const + { + return std::basic_string(m_str, m_size); + } + + //-------------------------------------------------------------------------- + // String Operations + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::copy(char_type* dest, + size_type count, + size_type pos) + const + { + if(pos >= m_size) { + throw std::out_of_range("Index out of range in basic_string_view::copy"); + } + + const size_type rcount = std::min(m_size - pos,count+1); + std::copy( m_str + pos, m_str + pos + rcount, dest); + return rcount; + } + + template + inline basic_string_view + basic_string_view::substr(size_type pos, + size_type len) + const + { + const size_type max_length = pos > m_size ? 0 : m_size - pos; + + if (pos > size()) { + throw std::out_of_range("Index out of range in basic_string_view::substr"); + } + + return basic_string_view(m_str + pos, std::min(len, max_length) ); + } + + //-------------------------------------------------------------------------- + + template + inline int basic_string_view::compare(basic_string_view v) + const noexcept + { + const size_type rlen = std::min(m_size,v.m_size); + const int compare = Traits::compare(m_str,v.m_str,rlen); + + return (compare ? compare : (m_size < v.m_size ? -1 : (m_size > v.m_size ? 1 : 0))); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count, + basic_string_view v) + const + { + return substr(pos,count).compare(v); + } + + template + inline int basic_string_view::compare(size_type pos1, + size_type count1, + basic_string_view v, + size_type pos2, + size_type count2) + const + { + return substr(pos1,count1).compare(v.substr(pos2,count2)); + } + + template + inline int basic_string_view::compare(const char_type* s) + const + { + return compare(basic_string_view(s)); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count, + const char_type* s) + const + { + return substr(pos, count).compare(basic_string_view(s)); + } + + template + inline int basic_string_view::compare(size_type pos, + size_type count1, + const char_type* s, + size_type count2) + const + { + return substr(pos, count1).compare(basic_string_view(s, count2)); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find(basic_string_view v, + size_type pos) + const + { + // Can't find a substring if the substring is bigger than this + if (pos > size()) { + return npos; + } + if ((pos + v.size()) > size()) { + return npos; + } + + const auto offset = pos; + const auto increments = size() - v.size(); + + for (auto i = 0u; i <= increments; ++i) { + const auto j = i + offset; + if (substr(j, v.size()) == v) { + return j; + } + } + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(char_type c, + size_type pos) + const + { + return find(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(const char_type* s, size_type pos, + size_type count) + const + { + return find(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find(const char_type* s, + size_type pos) + const + { + return find(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return v.empty() ? 0u : npos; + } + if (v.empty()) { + return std::min(size() - 1, pos); + } + if (v.size() > size()) { + return npos; + } + + auto i = std::min(pos, (size() - v.size())); + while (i != npos) { + if (substr(i, v.size()) == v) { + return i; + } + --i; + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(char_type c, + size_type pos) + const + { + return rfind(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(const char_type* s, size_type pos, + size_type count) + const + { + return rfind(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::rfind(const char_type* s, + size_type pos) + const + { + return rfind(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(basic_string_view v, + size_type pos) + const + { + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(char_type c, + size_type pos) + const + { + return find_first_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(const char_type* s, size_type pos, + size_type count) + const + { + return find_first_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_of(const char_type* s, + size_type pos) + const + { + return find_first_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(char_type c, + size_type pos) + const + { + return find_last_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(const char_type* s, size_type pos, + size_type count) + const + { + return find_last_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_of(const char_type* s, + size_type pos) + const + { + return find_last_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(basic_string_view v, + size_type pos) + const + { + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (!is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(char_type c, + size_type pos) + const + { + return find_first_not_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(const char_type* s, + size_type pos, + size_type count) + const + { + return find_first_not_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_first_not_of(const char_type* s, + size_type pos) + const + { + return find_first_not_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(basic_string_view v, + size_type pos) + const + { + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (!is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(char_type c, + size_type pos) + const + { + return find_last_not_of(basic_string_view(&c, 1), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(const char_type* s, + size_type pos, + size_type count) + const + { + return find_last_not_of(basic_string_view(s, count), pos); + } + + template + inline typename basic_string_view::size_type + basic_string_view::find_last_not_of(const char_type* s, + size_type pos) + const + { + return find_last_not_of(basic_string_view(s), pos); + } + + //-------------------------------------------------------------------------- + // Iterator + //-------------------------------------------------------------------------- + + template + inline typename basic_string_view::const_iterator + basic_string_view::begin() + const noexcept + { + return m_str; + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::cbegin() + const noexcept + { + return begin(); + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::end() + const noexcept + { + return m_str + m_size; + } + + template + inline typename basic_string_view::const_iterator + basic_string_view::cend() + const noexcept + { + return cend(); + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::rbegin() + const noexcept + { + return const_reverse_iterator{end()}; + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::crbegin() + const noexcept + { + return rbegin(); + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::rend() + const noexcept + { + return const_reverse_iterator{begin()}; + } + + template + inline typename basic_string_view::const_reverse_iterator + basic_string_view::crend() + const noexcept + { + return crend(); + } + + template + inline bool basic_string_view::is_one_of(CharT c, + basic_string_view str) + { + for (auto s : str) { + if (c == s) { + return true; + } + } + return false; + } + + //-------------------------------------------------------------------------- + // Public Functions + //-------------------------------------------------------------------------- + + template + std::basic_ostream& operator<<(std::basic_ostream& o, + const basic_string_view& str) + { + o.write(str.data(),str.size()); + return o; + } + + template + inline void swap(basic_string_view& lhs, + basic_string_view& rhs) + noexcept + { + lhs.swap(rhs); + } + + //-------------------------------------------------------------------------- + // Comparison Functions + //-------------------------------------------------------------------------- + + template + inline bool operator==(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) == 0; + } + + template + inline bool operator==(basic_string_view lhs, + const CharT* rhs) + noexcept + { + return lhs == basic_string_view(rhs); + } + + template + inline bool operator==(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) == rhs; + } + + template + inline bool operator==(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) == rhs; + } + + template + inline bool operator==(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs == basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) != 0; + } + + template + inline bool operator!=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs != basic_string_view(rhs); + } + + template + inline bool operator!=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) != rhs; + } + + template + inline bool operator!=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) != rhs; + } + + template + inline bool operator!=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs != basic_string_view(rhs); + } + //-------------------------------------------------------------------------- + + template + inline bool operator<(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) < 0; + } + + template + inline bool operator<(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs < basic_string_view(rhs); + } + + template + inline bool operator<(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) < rhs; + } + + template + inline bool operator<(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) < rhs; + } + + template + inline bool operator<(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs < basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator>(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) > 0; + } + + template + inline bool operator>(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs > basic_string_view(rhs); + } + + template + inline bool operator>(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) > rhs; + } + + template + inline bool operator>(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) > rhs; + } + + template + inline bool operator>(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs > basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) <= 0; + } + + template + inline bool operator<=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs <= basic_string_view(rhs); + } + + template + inline bool operator<=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) <= rhs; + } + + template + inline bool operator<=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) <= rhs; + } + + template + inline bool operator<=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs <= basic_string_view(rhs); + } + + //-------------------------------------------------------------------------- + + template + inline bool operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) >= 0; + } + + template + inline bool operator>=(const basic_string_view& lhs, + const CharT* rhs) + noexcept + { + return lhs >= basic_string_view(rhs); + } + + template + inline bool operator>=(const CharT* lhs, + const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) >= rhs; + } + + template + inline bool operator>=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) >= rhs; + } + + template + inline bool operator>=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs >= basic_string_view(rhs); + } + +} // namespace bpstd + +#endif /* BPSTD_DETAIL_STRING_VIEW_INL */ + +#endif /* BPSTD_STRING_VIEW_HPP */ diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 2225c53217..439b9f981d 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -48,6 +48,7 @@ typedef struct Rules_t RulesSet; #include "modsecurity/variable_value.h" #include "modsecurity/collection/collection.h" #include "modsecurity/variable_origin.h" +#include "modsecurity/actions/action.h" #ifndef NO_LOGS @@ -102,6 +103,7 @@ class ModSecurity; class Transaction; class RulesSet; class RuleMessage; +class RuleWithActions; namespace actions { class Action; namespace disruptive { @@ -308,7 +310,7 @@ class TransactionSecMarkerManagement { m_marker.reset(); } - void addMarker(std::shared_ptr name) { + void addMarker(const std::shared_ptr &name) { m_marker = name; } @@ -316,8 +318,39 @@ class TransactionSecMarkerManagement { std::shared_ptr m_marker; }; +class TransactionRuleMessageManagement { + public: + explicit TransactionRuleMessageManagement(Transaction *t) + : m_transaction(t) { + messageNew(); + }; + + RuleMessage *messageGetLast(); + void messageNew(); + + void logMatchLastRuleOnTheChain(const RuleWithActions *rule); + + std::list messageGetAll(); + + void messageClear() { + m_rulesMessages.clear(); + } + + private: + /** + * This variable holds all the messages asked to be save by the utilization + * of the actions: `log_data' and `msg'. These should be included on the + * auditlogs. + */ + std::list m_rulesMessages; + + Transaction *m_transaction; +}; + + /** @ingroup ModSecurity_CPP_API */ -class Transaction : public TransactionAnchoredVariables, public TransactionSecMarkerManagement { +class Transaction : public TransactionAnchoredVariables, public TransactionSecMarkerManagement, \ + public TransactionRuleMessageManagement { public: Transaction(ModSecurity *transaction, RulesSet *rules, void *logCbData); Transaction(ModSecurity *transaction, RulesSet *rules, char *id, @@ -397,7 +430,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa #ifndef NO_LOGS void debug(int, std::string) const; #endif - void serverLog(std::shared_ptr rm); + void serverLog(RuleMessage *rm); int getRuleEngineState() const; @@ -512,6 +545,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa * */ std::list< std::pair > m_ruleRemoveTargetById; + std::list< std::pair, std::string> > m_ruleRemoveTargetByIdRange; /** * @@ -519,19 +553,12 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa int m_requestBodyAccess; /** - * The list m_auditLogModifier contains modifications to the `auditlogs' - * for this specific request, those modifications can happens via the - * utilization of the action: `ctl:auditLogParts=' + * m_auditLogParts contains auditlog parts for this specific request, + * it also holds the modifications can happens via the utilization of + * the action: `ctl:auditLogParts=' * */ - std::list< std::pair > m_auditLogModifier; - - /** - * This variable holds all the messages asked to be save by the utilization - * of the actions: `log_data' and `msg'. These should be included on the - * auditlogs. - */ - std::list m_rulesMessages; + int m_auditLogParts; /** * Holds the request body, in case of any. @@ -599,19 +626,6 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa int m_secRuleEngine; - std::string m_variableDuration; - std::map m_variableEnvs; - std::string m_variableHighestSeverityAction; - std::string m_variableRemoteUser; - std::string m_variableTime; - std::string m_variableTimeDay; - std::string m_variableTimeEpoch; - std::string m_variableTimeHour; - std::string m_variableTimeMin; - std::string m_variableTimeSec; - std::string m_variableTimeWDay; - std::string m_variableTimeYear; - private: /** * Pointer to the callback function that will be called to fill diff --git a/headers/modsecurity/variable_origin.h b/headers/modsecurity/variable_origin.h index 88079a7fae..dce5e4ff24 100644 --- a/headers/modsecurity/variable_origin.h +++ b/headers/modsecurity/variable_origin.h @@ -37,7 +37,7 @@ class VariableOrigin { : m_length(0), m_offset(0) { } - std::string toText() { + std::string toText() const { std::string offset = std::to_string(m_offset); std::string len = std::to_string(m_length); return "v" + offset + "," + len; diff --git a/headers/modsecurity/variable_value.h b/headers/modsecurity/variable_value.h index a3e8f92474..5fdc42ddb8 100644 --- a/headers/modsecurity/variable_value.h +++ b/headers/modsecurity/variable_value.h @@ -20,9 +20,13 @@ #include #include #include +#include #endif #include "modsecurity/variable_origin.h" +#ifdef __cplusplus +#include "modsecurity/string_view.hpp" +#endif #ifndef HEADERS_MODSECURITY_VARIABLE_VALUE_H_ #define HEADERS_MODSECURITY_VARIABLE_VALUE_H_ @@ -34,85 +38,210 @@ typedef struct Variable_t VariableValue; #ifdef __cplusplus namespace modsecurity { +class VariableValue; +using VariableValues = std::vector>; +using Origins = std::vector; + class Collection; class VariableValue { public: - using Origins = std::list>; - - explicit VariableValue(const std::string *key, + /** + * + * + * Use cases for VariableValue creation: + * + * AnchoredSet - Use case A (eg. ARGS). - Collection + Key + * Anchored - Use case B (eg. REQUEST_URI). - Key + * Custom - Use case C (eg. WEBAPP_ID). - Key + * CustomSet + * Fixed - Use case D (eg. TX). - Collection + Key + * Dynamic - Use case E (eg. ENV). - Collection + Key + * + * + * | Key | Collec. | Key + Collec. | Value | Full Name + * A | & | & | * | & | * + * B | x | & | * | & | & + * C | x | & | * | & | & + * D | & | & | * | & | * + * E | & | & | * | * | * + * + * + * + * Currently big picture of getName and getKey: + * + * getName() + * - Lua Engine - RuleWithOperator - Transaction + * - UpdateMatchedVar - logging (audit) + * - ExecuteOperatorAt + * - ResolveMatchMsg + * - RulesExceptions (key and value) + * + * + * getKey() + * - Transaction - Variable + * - LogGen - Contains + * - Regexp + * + * + * Performance strategy: Delay the name resolution till is really necessary. + * + * + */ + + + /** + * + * Use case C + VariableModificatorCount + * + * + **/ + explicit VariableValue(const std::string *collection, const std::string *value = nullptr) - : m_collection(""), - m_key(*key), - m_keyWithCollection(*key), - m_value(value != nullptr?*value:"") - { } + : m_origin(), + m_value(new std::string(value != nullptr?*value:"")), // FIXME: no need for to copy here. + m_valueHolder(nullptr), + m_key(nullptr), + m_keyHolder(nullptr), + m_collection(new std::string(*collection)) // FIXME: no need for to copy here. + { }; + + + /* Use case D.1. - ARGS */ + VariableValue(const std::string *collection, + std::unique_ptr key, + std::unique_ptr value) + : m_origin(), + m_value(nullptr), + m_valueHolder(std::move(value)), + m_key(nullptr), + m_keyHolder(std::move(key)), + m_collection(collection) + { + m_value = m_valueHolder.get(); + m_key = m_keyHolder.get(); + }; + + /* Use case D.2. - RULE */ VariableValue(const std::string *collection, const std::string *key, - const std::string *value) - : m_collection(*collection), - m_key(*key), - m_keyWithCollection(*collection + ":" + *key), - m_value(*value) - { } - - explicit VariableValue(const VariableValue *o) : - m_collection(o->m_collection), - m_key(o->m_key), - m_keyWithCollection(o->m_keyWithCollection), - m_value(o->m_value) + std::unique_ptr value) + : m_origin(), + m_value(nullptr), + m_valueHolder(std::move(value)), + m_key(key), + m_keyHolder(nullptr), + m_collection(collection) { - 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)); - } - } + m_value = m_valueHolder.get(); + }; + + + /* Use case D.3. - TX */ + VariableValue(const std::string *collection, + const std::string *key, + const std::string *value) + : m_origin(), + m_value(value), + m_valueHolder(nullptr), + m_key(key), + m_keyHolder(nullptr), + m_collection(collection) + { }; + - VariableValue(const VariableValue &v) = delete; + // FIXME: It maybe the case for VariableValue to use string_view for everything. + /* Use case D.4. - MATCHED_VARS */ + VariableValue(const std::string *collection, + const std::string *key, + const bpstd::string_view *value) + : m_origin(), + m_value(), + m_valueHolder(std::unique_ptr(new std::string(value->c_str()))), + m_key(key), + m_keyHolder(nullptr), + m_collection(collection) + { + m_value = m_valueHolder.get(); + }; + + + /* Use case E.1. - Env */ + VariableValue(std::unique_ptr value, + std::unique_ptr key, + std::shared_ptr collection) + : m_origin(), + m_value(nullptr), + m_valueHolder(std::move(value)), + m_key(nullptr), + m_keyHolder(std::move(key)), + m_collection(collection.get()) + { + m_value = m_valueHolder.get(); + m_key = m_keyHolder.get(); + }; + + + /* Use case E.2. - DURATION */ + VariableValue(std::unique_ptr value, + const std::string *collection) + : m_origin(), + m_value(nullptr), + m_valueHolder(std::move(value)), + m_key(nullptr), + m_keyHolder(nullptr), + m_collection(collection) + { + m_value = m_valueHolder.get(); + }; - const std::string& getKey() const { - return m_key; - } + VariableValue(const VariableValue &o) = delete; + VariableValue operator=(const VariableValue &o) = delete; - const std::string& getKeyWithCollection() const { - return m_keyWithCollection; + const std::string& getValue() const noexcept { + return *m_value; } - const std::string& getCollection() const { - return m_collection; + const std::string& getKey() const noexcept { + return *m_key; } - const std::string& getValue() const { - return m_value; + inline const std::string getName() const noexcept { + if (m_key == nullptr || m_key->empty()) { + return *m_collection; + } + return *m_collection + ":" + *m_key; } void setValue(const std::string &value) { - m_value = value; + m_value = &value; } - void addOrigin(std::unique_ptr origin) { - m_orign.push_back(std::move(origin)); + void addOrigin(VariableOrigin origin) { + m_origin.push_back(std::move(origin)); } const Origins& getOrigin() const { - return m_orign; + return m_origin; } private: - Origins m_orign; - std::string m_collection; - std::string m_key; - std::string m_keyWithCollection; - std::string m_value; + Origins m_origin; + + const std::string *m_value; + std::unique_ptr m_valueHolder; + + const std::string *m_key; + std::unique_ptr m_keyHolder; + + const std::string *m_collection; }; } // namespace modsecurity diff --git a/src/Makefile.am b/src/Makefile.am index e6496ccc40..7a134857f5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,21 +42,19 @@ pkginclude_HEADERS = \ ../headers/modsecurity/intervention.h \ ../headers/modsecurity/modsecurity.h \ ../headers/modsecurity/rule.h \ - ../headers/modsecurity/rule_marker.h \ - ../headers/modsecurity/rule_unconditional.h \ - ../headers/modsecurity/rule_with_actions.h \ - ../headers/modsecurity/rule_with_operator.h \ ../headers/modsecurity/rules.h \ ../headers/modsecurity/rule_message.h \ ../headers/modsecurity/rules_set.h \ ../headers/modsecurity/rules_set_phases.h \ ../headers/modsecurity/rules_set_properties.h \ ../headers/modsecurity/rules_exceptions.h \ + ../headers/modsecurity/string_view.hpp \ ../headers/modsecurity/transaction.h \ ../headers/modsecurity/variable_origin.h \ ../headers/modsecurity/variable_value.h + libmodsecurity_includesub_collection_HEADERS = \ ../headers/modsecurity/collection/collection.h \ ../headers/modsecurity/collection/collections.h @@ -286,8 +284,10 @@ libmodsecurity_la_SOURCES = \ debug_log/debug_log_writer.cc \ run_time_string.cc \ rule.cc \ + rules.cc \ rule_unconditional.cc \ rule_with_actions.cc \ + rule_with_actions_properties.cc \ rule_with_operator.cc \ rule_message.cc \ rule_script.cc \ @@ -313,6 +313,7 @@ libmodsecurity_la_CPPFLAGS = \ -fPIC \ -O3 \ -I../headers \ + $(CURL_CFLAGS) \ $(GEOIP_CFLAGS) \ $(GLOBAL_CPPFLAGS) \ $(MODSEC_NO_LOGS) \ diff --git a/src/actions/accuracy.cc b/src/actions/accuracy.cc index 58a26f376d..da59bbb4c3 100644 --- a/src/actions/accuracy.cc +++ b/src/actions/accuracy.cc @@ -13,15 +13,11 @@ * */ + #include "src/actions/accuracy.h" -#include #include -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" - namespace modsecurity { namespace actions { @@ -29,9 +25,9 @@ namespace actions { bool Accuracy::init(std::string *error) { try { - m_accuracy = std::stoi(m_parser_payload); + m_accuracy = std::stoi(m_parserPayload); } catch (...) { - error->assign("Accuracy: The input \"" + m_parser_payload + "\" is " \ + error->assign("Accuracy: The input \"" + m_parserPayload + "\" is " \ "not a number."); return false; } @@ -39,11 +35,5 @@ bool Accuracy::init(std::string *error) { } -bool Accuracy::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->m_accuracy = m_accuracy; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/accuracy.h b/src/actions/accuracy.h index 761a0bcc3e..99b802ee83 100644 --- a/src/actions/accuracy.h +++ b/src/actions/accuracy.h @@ -13,29 +13,32 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_ACCURACY_H_ #define SRC_ACTIONS_ACCURACY_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Accuracy : public Action { +class Accuracy : public ActionTypeRuleMetaData { public: - explicit Accuracy(const std::string &action) - : Action(action, ConfigurationKind), + explicit Accuracy(const std::string &action) + : Action(action), m_accuracy(0) { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + void configure(RuleWithActions *rule) override { + rule->setAccuracy(m_accuracy); + } + private: int m_accuracy; }; diff --git a/src/actions/action.cc b/src/actions/action.cc index 8a2409d1a1..cf11ade86e 100644 --- a/src/actions/action.cc +++ b/src/actions/action.cc @@ -15,46 +15,10 @@ #include "modsecurity/actions/action.h" -#include -#include - -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "src/utils/string.h" - -#include "src/actions/block.h" -#include "src/actions/chain.h" -#include "src/actions/disruptive/deny.h" -#include "src/actions/disruptive/redirect.h" -#include "src/actions/data/status.h" -#include "src/actions/rule_id.h" -#include "src/actions/phase.h" -#include "src/actions/severity.h" -#include "src/actions/capture.h" -#include "src/actions/disruptive/pass.h" -#include "src/actions/log.h" -#include "src/actions/no_log.h" -#include "src/actions/no_audit_log.h" -#include "src/actions/multi_match.h" - - -#define IF_MATCH(a) \ - if (op.compare(1, std::strlen(#a), #a) == 0) namespace modsecurity { namespace actions { -std::string Action::evaluate(const std::string &value, - Transaction *transaction) { - return value; -} - - -bool Action::evaluate(RuleWithActions *rule, Transaction *transaction) { - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/action_allowed_in_sec_default_action.h b/src/actions/action_allowed_in_sec_default_action.h new file mode 100644 index 0000000000..1d23f08ec7 --- /dev/null +++ b/src/actions/action_allowed_in_sec_default_action.h @@ -0,0 +1,34 @@ +/* + * 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" + +#ifndef SRC_ACTIONS_ACTION_ALLOWED_IN_SEC_DEFAULT_ACTION_H_ +#define SRC_ACTIONS_ACTION_ALLOWED_IN_SEC_DEFAULT_ACTION_H_ + + +namespace modsecurity { +namespace actions { + + +class ActionAllowedAsSecDefaultAction : public virtual Action { + public: +}; + + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_ACTION_ALLOWED_IN_SEC_DEFAULT_ACTION_H_ diff --git a/src/actions/action_type_rule_metadata.h b/src/actions/action_type_rule_metadata.h new file mode 100644 index 0000000000..2470a4b87c --- /dev/null +++ b/src/actions/action_type_rule_metadata.h @@ -0,0 +1,47 @@ +/* + * 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/rule_with_actions.h" + +#ifndef SRC_ACTIONS_ACTION_TYPE_CONFIGURE_H_ +#define SRC_ACTIONS_ACTION_TYPE_CONFIGURE_H_ + + +namespace modsecurity { +namespace actions { + + +class ActionTypeRuleMetaData : public virtual Action { + public: + /** + * + * Action that are executed while loading the configuration. For instance + * the rule ID or the rule phase. + * + */ + ActionTypeRuleMetaData() + : Action() + { }; + + virtual void configure(RuleWithActions *rule) = 0; +}; + + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_ACTION_TYPE_CONFIGURE_H_ diff --git a/src/actions/action_with_execution.h b/src/actions/action_with_execution.h new file mode 100644 index 0000000000..277b7d0d22 --- /dev/null +++ b/src/actions/action_with_execution.h @@ -0,0 +1,41 @@ +/* + * 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/rule_with_actions.h" + +#ifndef SRC_ACTIONS_ACTION_WITH_EXECUTION_H_ +#define SRC_ACTIONS_ACTION_WITH_EXECUTION_H_ + + +namespace modsecurity { +namespace actions { + + +class ActionWithExecution : public virtual Action { + public: + ActionWithExecution() + : Action() + { }; + + virtual bool execute(Transaction *t) const noexcept = 0; +}; + + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_ACTION_WITH_EXECUTION_H_ 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 0000000000..2d1b577dd6 --- /dev/null +++ b/src/actions/action_with_run_time_string.h @@ -0,0 +1,70 @@ +/* + * 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 + +#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 virtual Action { + public: + explicit ActionWithRunTimeString(std::unique_ptr string = nullptr) + : m_string(std::move(string)) + { } + + ActionWithRunTimeString(const ActionWithRunTimeString &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(const RuleWithActions *rule) { + if (m_string) { + m_string->populate(rule); + } + } + + std::string getEvaluatedRunTimeString(const Transaction *transaction) const noexcept { + return (!m_string)?"":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/audit_log.cc b/src/actions/audit_log.cc index e0af6a7431..362b3f796f 100644 --- a/src/actions/audit_log.cc +++ b/src/actions/audit_log.cc @@ -15,27 +15,10 @@ #include "src/actions/audit_log.h" -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "modsecurity/rule_message.h" -#include "modsecurity/rules_set.h" namespace modsecurity { namespace actions { -bool AuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - rm->m_noAuditLog = false; - ms_dbg_a(transaction, 9, "Saving transaction to logs"); - rm->m_saveMessage = true; - - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/audit_log.h b/src/actions/audit_log.h index c0b3b84924..0f34bab552 100644 --- a/src/actions/audit_log.h +++ b/src/actions/audit_log.h @@ -13,35 +13,36 @@ * */ -#include -#include -#include "modsecurity/actions/action.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + #ifndef SRC_ACTIONS_AUDIT_LOG_H_ #define SRC_ACTIONS_AUDIT_LOG_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; - namespace actions { -class AuditLog : public Action { +class AuditLog : public ActionTypeRuleMetaData, + public ActionAllowedAsSecDefaultAction { public: - explicit AuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + AuditLog() + : Action("auditLog") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + void configure(RuleWithActions *rule) override { + rule->setAuditLog(true); + } }; } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_AUDIT_LOG_H_ diff --git a/src/actions/block.cc b/src/actions/block.cc index df1a23ab0c..31b1a8b6d5 100644 --- a/src/actions/block.cc +++ b/src/actions/block.cc @@ -13,36 +13,13 @@ * */ -#include "src/actions/block.h" -#include -#include -#include +#include "src/actions/block.h" -#include "modsecurity/rules_set.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/intervention.h" -#include "src/actions/data/status.h" namespace modsecurity { namespace actions { -bool Block::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - ms_dbg_a(transaction, 8, "Marking request as disruptive."); - - for (auto &a : transaction->m_rules->m_defaultActions[rule->getPhase()]) { - if (a->isDisruptive() == false) { - continue; - } - a->evaluate(rule, transaction, rm); - } - - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/block.h b/src/actions/block.h index b5f33b479f..e50d83722f 100644 --- a/src/actions/block.h +++ b/src/actions/block.h @@ -13,35 +13,37 @@ * */ + #include #include -#include "modsecurity/actions/action.h" -#include "modsecurity/rule_message.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_allowed_in_sec_default_action.h" -#ifndef SRC_ACTIONS_DISRUPTIVE_BLOCK_H_ -#define SRC_ACTIONS_DISRUPTIVE_BLOCK_H_ -#ifdef __cplusplus -class Transaction; +#ifndef SRC_ACTIONS_BLOCK_H_ +#define SRC_ACTIONS_BLOCK_H_ -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { -class Block : public Action { +class Block : public ActionTypeRuleMetaData, + public ActionAllowedAsSecDefaultAction { public: - explicit Block(const std::string &action) : Action(action) { } + Block() + : Action("block") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + void configure(RuleWithActions *rule) override { + rule->setBlock(true); + } }; } // namespace actions } // namespace modsecurity -#endif -#endif // SRC_ACTIONS_DISRUPTIVE_BLOCK_H_ + +#endif // SRC_ACTIONS_BLOCK_H_ diff --git a/src/actions/capture.cc b/src/actions/capture.cc index 966b240df5..83abc16c32 100644 --- a/src/actions/capture.cc +++ b/src/actions/capture.cc @@ -13,29 +13,13 @@ * */ -#include "src/actions/capture.h" - -#include -#include -#include -#include "modsecurity/transaction.h" +#include "src/actions/capture.h" -#include "modsecurity/rule.h" -#include "src/operators/operator.h" -#include "src/operators/pm.h" -#include "src/operators/rx.h" -#include "src/operators/contains.h" -#include "src/operators/detect_sqli.h" namespace modsecurity { namespace actions { -bool Capture::evaluate(RuleWithActions *rule, Transaction *transaction) { - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/capture.h b/src/actions/capture.h index 841d1ecb14..28bb02fb86 100644 --- a/src/actions/capture.h +++ b/src/actions/capture.h @@ -13,25 +13,28 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_CAPTURE_H_ #define SRC_ACTIONS_CAPTURE_H_ namespace modsecurity { -class RuleWithOperator; namespace actions { -class Capture : public Action { +class Capture : public ActionTypeRuleMetaData { public: - explicit Capture(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + Capture() + : Action("capture") { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + void configure(RuleWithActions *rule) override { + rule->setHasCapture(true); + } }; diff --git a/src/actions/chain.cc b/src/actions/chain.cc index 06419c342e..8fe949190c 100644 --- a/src/actions/chain.cc +++ b/src/actions/chain.cc @@ -13,23 +13,13 @@ * */ -#include "src/actions/chain.h" -#include -#include +#include "src/actions/chain.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" namespace modsecurity { namespace actions { -bool Chain::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->setChained(true); - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/chain.h b/src/actions/chain.h index 6a1532d29b..f1b55f8920 100644 --- a/src/actions/chain.h +++ b/src/actions/chain.h @@ -13,33 +13,34 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_CHAIN_H_ #define SRC_ACTIONS_CHAIN_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; -class RuleWithOperator; - namespace actions { -class Chain : public Action { +class Chain : public ActionTypeRuleMetaData { public: - explicit Chain(const std::string &action) - : Action(action, ConfigurationKind) { } + Chain() + : Action("chain") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + void configure(RuleWithActions *rule) override { + rule->setHasChainAction(true); + } }; + } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_CHAIN_H_ diff --git a/src/actions/ctl/audit_log_parts.cc b/src/actions/ctl/audit_log_parts.cc index 2a8d7f0113..d06bd6bc51 100644 --- a/src/actions/ctl/audit_log_parts.cc +++ b/src/actions/ctl/audit_log_parts.cc @@ -13,13 +13,20 @@ * */ + #include "src/actions/ctl/audit_log_parts.h" -#include #include #include #include "modsecurity/transaction.h" +#include "modsecurity/audit_log.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + namespace modsecurity { namespace actions { @@ -27,20 +34,39 @@ namespace ctl { bool AuditLogParts::init(std::string *error) { - std::string what(m_parser_payload, 14, 1); - mParts = std::string(m_parser_payload, 15, m_parser_payload.length()-15); + std::string what(m_parserPayload, 14, 1); + std::string parts_str(m_parserPayload, 15, m_parserPayload.length()-15); + + if ((what != "-") && (what != "+")) { + error->assign("ctl:auditLogParts modificators expects add or " \ + "remove (+/-) in front of the modificator. Got: " + what); + return false; + } + + int flags = AuditLog::addParts(0, parts_str); + if (what == "+") { - mPartsAction = 0; + m_partsToModify = flags; } else { - mPartsAction = 1; + m_partsToModify = -1 * flags; } return true; } -bool AuditLogParts::evaluate(RuleWithActions *rule, Transaction *transaction) { - transaction->m_auditLogModifier.push_back( - std::make_pair(mPartsAction, mParts)); + +bool AuditLogParts::execute(Transaction *transaction) const noexcept { + ms_dbg_a(transaction, 7, "AuditLog parts before modification: " + + std::to_string(transaction->m_auditLogParts) + "."); + + if (m_partsToModify < 0) { + transaction->m_auditLogParts = \ + transaction->m_auditLogParts & ~(m_partsToModify * -1); + } else { + transaction->m_auditLogParts = \ + transaction->m_auditLogParts | m_partsToModify; + } + return true; } diff --git a/src/actions/ctl/audit_log_parts.h b/src/actions/ctl/audit_log_parts.h index 6638fa0fb5..f1a8de677f 100644 --- a/src/actions/ctl/audit_log_parts.h +++ b/src/actions/ctl/audit_log_parts.h @@ -13,32 +13,36 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_CTL_AUDIT_LOG_PARTS_H_ #define SRC_ACTIONS_CTL_AUDIT_LOG_PARTS_H_ + namespace modsecurity { namespace actions { namespace ctl { -class AuditLogParts : public Action { +class AuditLogParts : public ActionWithExecution { public: - explicit AuditLogParts(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - mPartsAction(0), - mParts("") { } + explicit AuditLogParts(const std::string &action) + : Action(action), + m_partsToModify(0) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + bool execute(Transaction *transaction) const noexcept override; + protected: - int mPartsAction; - std::string mParts; + int m_partsToModify; }; @@ -46,4 +50,5 @@ class AuditLogParts : public Action { } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_CTL_AUDIT_LOG_PARTS_H_ diff --git a/src/actions/ctl/request_body_access.cc b/src/actions/ctl/request_body_access.cc index 5f7edc250c..e95e270133 100644 --- a/src/actions/ctl/request_body_access.cc +++ b/src/actions/ctl/request_body_access.cc @@ -13,40 +13,44 @@ * */ + #include "src/actions/ctl/request_body_access.h" -#include #include #include "modsecurity/rules_set_properties.h" #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { bool RequestBodyAccess::init(std::string *error) { - std::string what(m_parser_payload, 18, m_parser_payload.size() - 18); + std::string what(m_parserPayload, 18, m_parserPayload.size() - 18); if (what == "true") { - m_request_body_access = true; + m_requestBodyAccess = true; } else if (what == "false") { - m_request_body_access = false; + m_requestBodyAccess = false; } else { error->assign("Internal error. Expected: true or false, got: " \ - + m_parser_payload); + + m_parserPayload); return false; } return true; } -bool RequestBodyAccess::evaluate(RuleWithActions *rule, Transaction *transaction) { - if (m_request_body_access) { - transaction->m_requestBodyAccess = RulesSetProperties::TrueConfigBoolean; + +bool RequestBodyAccess::execute(Transaction *transaction) const noexcept { + if (m_requestBodyAccess) { + transaction->m_requestBodyAccess = + RulesSetProperties::TrueConfigBoolean; } else { - transaction->m_requestBodyAccess = RulesSetProperties::FalseConfigBoolean; + transaction->m_requestBodyAccess = + RulesSetProperties::FalseConfigBoolean; } return true; diff --git a/src/actions/ctl/request_body_access.h b/src/actions/ctl/request_body_access.h index 4bbd8f6848..c1cdb5a243 100644 --- a/src/actions/ctl/request_body_access.h +++ b/src/actions/ctl/request_body_access.h @@ -13,30 +13,36 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_REQUEST_BODY_ACCESS_H_ #define SRC_ACTIONS_CTL_REQUEST_BODY_ACCESS_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RequestBodyAccess : public Action { +class RequestBodyAccess : public ActionWithExecution { public: - explicit RequestBodyAccess(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_request_body_access(false) { } + explicit RequestBodyAccess(const std::string &action) + : Action(action), + m_requestBodyAccess(false) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool m_request_body_access; + bool execute(Transaction *transaction) const noexcept override; + + private: + bool m_requestBodyAccess; }; @@ -44,4 +50,5 @@ class RequestBodyAccess : public Action { } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_CTL_REQUEST_BODY_ACCESS_H_ diff --git a/src/actions/ctl/request_body_processor_json.cc b/src/actions/ctl/request_body_processor_json.cc index a80c4edeae..65389955be 100644 --- a/src/actions/ctl/request_body_processor_json.cc +++ b/src/actions/ctl/request_body_processor_json.cc @@ -13,20 +13,20 @@ * */ + #include "src/actions/ctl/request_body_processor_json.h" -#include #include #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { -bool RequestBodyProcessorJSON::evaluate(RuleWithActions *rule, - Transaction *transaction) { +bool RequestBodyProcessorJSON::execute(Transaction *transaction) const noexcept { transaction->m_requestBodyProcessor = Transaction::JSONRequestBody; transaction->m_variableReqbodyProcessor.set("JSON", transaction->m_variableOffset); diff --git a/src/actions/ctl/request_body_processor_json.h b/src/actions/ctl/request_body_processor_json.h index 42a6372345..ac0dd41dea 100644 --- a/src/actions/ctl/request_body_processor_json.h +++ b/src/actions/ctl/request_body_processor_json.h @@ -13,25 +13,30 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_JSON_H_ #define SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_JSON_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RequestBodyProcessorJSON : public Action { +class RequestBodyProcessorJSON : public ActionWithExecution { public: - explicit RequestBodyProcessorJSON(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit RequestBodyProcessorJSON(const std::string &action) + : Action(action) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; }; diff --git a/src/actions/ctl/request_body_processor_urlencoded.cc b/src/actions/ctl/request_body_processor_urlencoded.cc index 222970e701..9394937bce 100644 --- a/src/actions/ctl/request_body_processor_urlencoded.cc +++ b/src/actions/ctl/request_body_processor_urlencoded.cc @@ -13,20 +13,21 @@ * */ + #include "src/actions/ctl/request_body_processor_urlencoded.h" -#include #include #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { -bool RequestBodyProcessorURLENCODED::evaluate(RuleWithActions *rule, - Transaction *transaction) { +bool RequestBodyProcessorURLENCODED::execute( + Transaction *transaction) const noexcept { transaction->m_requestBodyType = Transaction::WWWFormUrlEncoded; transaction->m_variableReqbodyProcessor.set("URLENCODED", transaction->m_variableOffset); diff --git a/src/actions/ctl/request_body_processor_urlencoded.h b/src/actions/ctl/request_body_processor_urlencoded.h index 0564881535..28044d65a8 100644 --- a/src/actions/ctl/request_body_processor_urlencoded.h +++ b/src/actions/ctl/request_body_processor_urlencoded.h @@ -13,25 +13,30 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_URLENCODED_H_ #define SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_URLENCODED_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RequestBodyProcessorURLENCODED : public Action { +class RequestBodyProcessorURLENCODED : public ActionWithExecution { public: - explicit RequestBodyProcessorURLENCODED(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit RequestBodyProcessorURLENCODED(const std::string &action) + : Action(action) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; }; diff --git a/src/actions/ctl/request_body_processor_xml.cc b/src/actions/ctl/request_body_processor_xml.cc index 4876c20bbb..ca281734a2 100644 --- a/src/actions/ctl/request_body_processor_xml.cc +++ b/src/actions/ctl/request_body_processor_xml.cc @@ -13,20 +13,20 @@ * */ + #include "src/actions/ctl/request_body_processor_xml.h" -#include #include #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { -bool RequestBodyProcessorXML::evaluate(RuleWithActions *rule, - Transaction *transaction) { +bool RequestBodyProcessorXML::execute(Transaction *transaction) const noexcept { transaction->m_requestBodyProcessor = Transaction::XMLRequestBody; transaction->m_variableReqbodyProcessor.set("XML", transaction->m_variableOffset); diff --git a/src/actions/ctl/request_body_processor_xml.h b/src/actions/ctl/request_body_processor_xml.h index 509c0f7437..46bb85a7fd 100644 --- a/src/actions/ctl/request_body_processor_xml.h +++ b/src/actions/ctl/request_body_processor_xml.h @@ -13,25 +13,30 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_XML_H_ #define SRC_ACTIONS_CTL_REQUEST_BODY_PROCESSOR_XML_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RequestBodyProcessorXML : public Action { +class RequestBodyProcessorXML : public ActionWithExecution { public: - explicit RequestBodyProcessorXML(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit RequestBodyProcessorXML(const std::string &action) + : Action(action) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; }; diff --git a/src/actions/ctl/rule_engine.cc b/src/actions/ctl/rule_engine.cc index 10f1b2e899..81612af7b2 100644 --- a/src/actions/ctl/rule_engine.cc +++ b/src/actions/ctl/rule_engine.cc @@ -13,22 +13,23 @@ * */ + #include "src/actions/ctl/rule_engine.h" -#include #include #include "modsecurity/rules_set_properties.h" #include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { bool RuleEngine::init(std::string *error) { - std::string what(m_parser_payload, 11, m_parser_payload.size() - 11); + std::string what(m_parserPayload, 11, m_parserPayload.size() - 11); if (what == "on") { m_ruleEngine = RulesSetProperties::EnabledRuleEngine; @@ -38,14 +39,15 @@ bool RuleEngine::init(std::string *error) { m_ruleEngine = RulesSetProperties::DetectionOnlyRuleEngine; } else { error->assign("Internal error. Expected: On, Off or DetectionOnly; " \ - "got: " + m_parser_payload); + "got: " + m_parserPayload); return false; } return true; } -bool RuleEngine::evaluate(RuleWithActions *rule, Transaction *transaction) { + +bool RuleEngine::execute(Transaction *transaction) const noexcept { std::stringstream a; a << "Setting SecRuleEngine to "; a << modsecurity::RulesSetProperties::ruleEngineStateString(m_ruleEngine); diff --git a/src/actions/ctl/rule_engine.h b/src/actions/ctl/rule_engine.h index 304389bdc7..c8c87f4338 100644 --- a/src/actions/ctl/rule_engine.h +++ b/src/actions/ctl/rule_engine.h @@ -13,30 +13,35 @@ * */ + #include #include "modsecurity/rules_set_properties.h" #include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_RULE_ENGINE_H_ #define SRC_ACTIONS_CTL_RULE_ENGINE_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RuleEngine : public Action { +class RuleEngine : public ActionWithExecution { public: - explicit RuleEngine(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_ruleEngine(RulesSetProperties::PropertyNotSetRuleEngine) { } + explicit RuleEngine(const std::string &action) + : Action(action), + m_ruleEngine(RulesSetProperties::PropertyNotSetRuleEngine) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + + private: RulesSetProperties::RuleEngine m_ruleEngine; }; diff --git a/src/actions/ctl/rule_remove_by_id.cc b/src/actions/ctl/rule_remove_by_id.cc index 431a7a9c49..f6fb9b7bb0 100644 --- a/src/actions/ctl/rule_remove_by_id.cc +++ b/src/actions/ctl/rule_remove_by_id.cc @@ -13,21 +13,25 @@ * */ + #include "src/actions/ctl/rule_remove_by_id.h" -#include #include +#include +#include #include "modsecurity/transaction.h" + #include "src/utils/string.h" + namespace modsecurity { namespace actions { namespace ctl { bool RuleRemoveById::init(std::string *error) { - std::string what(m_parser_payload, 15, m_parser_payload.size() - 15); + std::string what(m_parserPayload, 15, m_parserPayload.size() - 15); bool added = false; std::vector toRemove = utils::string::ssplit(what, ' '); for (std::string &a : toRemove) { @@ -83,7 +87,8 @@ bool RuleRemoveById::init(std::string *error) { return false; } -bool RuleRemoveById::evaluate(RuleWithActions *rule, Transaction *transaction) { + +bool RuleRemoveById::execute(Transaction *transaction) const noexcept { for (auto &i : m_ids) { transaction->m_ruleRemoveById.push_back(i); } diff --git a/src/actions/ctl/rule_remove_by_id.h b/src/actions/ctl/rule_remove_by_id.h index 7af416a6c4..b4e06fb9ed 100644 --- a/src/actions/ctl/rule_remove_by_id.h +++ b/src/actions/ctl/rule_remove_by_id.h @@ -13,28 +13,36 @@ * */ + #include +#include +#include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_RULE_REMOVE_BY_ID_H_ #define SRC_ACTIONS_CTL_RULE_REMOVE_BY_ID_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RuleRemoveById : public Action { +class RuleRemoveById : public ActionWithExecution { public: - explicit RuleRemoveById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit RuleRemoveById(const std::string &action) + : Action(action) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + + private: std::list > m_ranges; std::list m_ids; }; diff --git a/src/actions/ctl/rule_remove_by_tag.cc b/src/actions/ctl/rule_remove_by_tag.cc index c6c9ffe037..0d491256c5 100644 --- a/src/actions/ctl/rule_remove_by_tag.cc +++ b/src/actions/ctl/rule_remove_by_tag.cc @@ -13,26 +13,28 @@ * */ + #include "src/actions/ctl/rule_remove_by_tag.h" -#include #include #include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { namespace ctl { bool RuleRemoveByTag::init(std::string *error) { - std::string what(m_parser_payload, 16, m_parser_payload.size() - 16); + std::string what(m_parserPayload, 16, m_parserPayload.size() - 16); m_tag = what; return true; } -bool RuleRemoveByTag::evaluate(RuleWithActions *rule, Transaction *transaction) { + +bool RuleRemoveByTag::execute(Transaction *transaction) const noexcept { transaction->m_ruleRemoveByTag.push_back(m_tag); return true; } diff --git a/src/actions/ctl/rule_remove_by_tag.h b/src/actions/ctl/rule_remove_by_tag.h index bd38ec0303..3461b636d7 100644 --- a/src/actions/ctl/rule_remove_by_tag.h +++ b/src/actions/ctl/rule_remove_by_tag.h @@ -13,29 +13,35 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_RULE_REMOVE_BY_TAG_H_ #define SRC_ACTIONS_CTL_RULE_REMOVE_BY_TAG_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RuleRemoveByTag : public Action { +class RuleRemoveByTag : public ActionWithExecution { public: - explicit RuleRemoveByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_tag("") { } + explicit RuleRemoveByTag(const std::string &action) + : Action(action), + m_tag("") + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + + private: std::string m_tag; }; diff --git a/src/actions/ctl/rule_remove_target_by_id.cc b/src/actions/ctl/rule_remove_target_by_id.cc index 233a0ae0da..26c89e47ac 100644 --- a/src/actions/ctl/rule_remove_target_by_id.cc +++ b/src/actions/ctl/rule_remove_target_by_id.cc @@ -13,14 +13,15 @@ * */ + #include "src/actions/ctl/rule_remove_target_by_id.h" -#include #include #include #include #include "modsecurity/transaction.h" + #include "src/utils/string.h" @@ -30,7 +31,7 @@ namespace ctl { bool RuleRemoveTargetById::init(std::string *error) { - std::string what(m_parser_payload, 21, m_parser_payload.size() - 21); + std::string what(m_parserPayload, 21, m_parserPayload.size() - 21); std::vector param = utils::string::split(what, ';'); if (param.size() < 2) { @@ -38,12 +39,36 @@ bool RuleRemoveTargetById::init(std::string *error) { return false; } - try { - m_id = std::stoi(param[0]); - } catch(...) { - error->assign("Not able to convert '" + param[0] + - "' into a number"); - return false; + size_t dash = param[0].find('-'); + if (dash != std::string::npos) { + std::string n1s = std::string(param[0], 0, dash); + std::string n2s = std::string(param[0], dash + 1, param[0].size() - (dash + 1)); + int n1n = 0; + int n2n = 0; + try { + n1n = std::stoi(n1s); + } catch(...) { + error->assign("Not a number: " + n1s); + return false; + } + try { + n2n = std::stoi(n2s); + } catch(...) { + error->assign("Not a number: " + n2s); + return false; + } + if (n1n > n2n) { + error->assign("Invalid range: " + param[0]); + } + m_id = n1n; + m_id_end_of_range = n2n; + } else { + try { + m_id = std::stoi(param[0]); + } catch(...) { + error->assign("Not able to convert '" + param[0] + "' into a number"); + return false; + } } m_target = param[1]; @@ -51,9 +76,14 @@ bool RuleRemoveTargetById::init(std::string *error) { return true; } -bool RuleRemoveTargetById::evaluate(RuleWithActions *rule, Transaction *transaction) { - transaction->m_ruleRemoveTargetById.push_back( - std::make_pair(m_id, m_target)); + +bool RuleRemoveTargetById::execute(Transaction *transaction) const noexcept { + if (m_id_end_of_range == 0) { + transaction->m_ruleRemoveTargetById.push_back(std::make_pair(m_id, m_target)); + } else { + std::pair id_range = std::make_pair(m_id, m_id_end_of_range); + transaction->m_ruleRemoveTargetByIdRange.push_back(std::make_pair(id_range, m_target)); + } return true; } diff --git a/src/actions/ctl/rule_remove_target_by_id.h b/src/actions/ctl/rule_remove_target_by_id.h index e001c288e4..6ff98dfcb5 100644 --- a/src/actions/ctl/rule_remove_target_by_id.h +++ b/src/actions/ctl/rule_remove_target_by_id.h @@ -13,31 +13,39 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_ #define SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RuleRemoveTargetById : public Action { +class RuleRemoveTargetById : public ActionWithExecution { public: - explicit RuleRemoveTargetById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + explicit RuleRemoveTargetById(const std::string &action) + : Action(action), m_id(0), - m_target("") { } + m_id_end_of_range(0), + m_target("") + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + + private: int m_id; + int m_id_end_of_range; std::string m_target; }; diff --git a/src/actions/ctl/rule_remove_target_by_tag.cc b/src/actions/ctl/rule_remove_target_by_tag.cc index 25ec2ca85a..6f30df6561 100644 --- a/src/actions/ctl/rule_remove_target_by_tag.cc +++ b/src/actions/ctl/rule_remove_target_by_tag.cc @@ -13,14 +13,15 @@ * */ + #include "src/actions/ctl/rule_remove_target_by_tag.h" -#include #include #include #include #include "modsecurity/transaction.h" + #include "src/utils/string.h" @@ -30,7 +31,7 @@ namespace ctl { bool RuleRemoveTargetByTag::init(std::string *error) { - std::string what(m_parser_payload, 22, m_parser_payload.size() - 22); + std::string what(m_parserPayload, 22, m_parserPayload.size() - 22); std::vector param = utils::string::split(what, ';'); if (param.size() < 2) { @@ -44,7 +45,8 @@ bool RuleRemoveTargetByTag::init(std::string *error) { return true; } -bool RuleRemoveTargetByTag::evaluate(RuleWithActions *rule, Transaction *transaction) { + +bool RuleRemoveTargetByTag::execute(Transaction *transaction) const noexcept { transaction->m_ruleRemoveTargetByTag.push_back( std::make_pair(m_tag, m_target)); return true; diff --git a/src/actions/ctl/rule_remove_target_by_tag.h b/src/actions/ctl/rule_remove_target_by_tag.h index 2a23a34e07..eadc4e0fa2 100644 --- a/src/actions/ctl/rule_remove_target_by_tag.h +++ b/src/actions/ctl/rule_remove_target_by_tag.h @@ -13,28 +13,34 @@ * */ + #include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/action_with_execution.h" #ifndef SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_TAG_H_ #define SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_TAG_H_ + namespace modsecurity { namespace actions { namespace ctl { -class RuleRemoveTargetByTag : public Action { +class RuleRemoveTargetByTag : public ActionWithExecution { public: - explicit RuleRemoveTargetByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit RuleRemoveTargetByTag(const std::string &action) + : Action(action) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + + private: std::string m_tag; std::string m_target; }; @@ -44,4 +50,5 @@ class RuleRemoveTargetByTag : public Action { } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_TAG_H_ diff --git a/src/actions/data/status.cc b/src/actions/data/status.cc index 1317b1d3ff..93213316af 100644 --- a/src/actions/data/status.cc +++ b/src/actions/data/status.cc @@ -13,11 +13,10 @@ * */ + #include "src/actions/data/status.h" -#include #include -#include #include "modsecurity/transaction.h" @@ -26,11 +25,12 @@ namespace modsecurity { namespace actions { namespace data { + bool Status::init(std::string *error) { try { - m_status = std::stoi(m_parser_payload); + m_status = std::stoi(m_parserPayload); } catch (...) { - error->assign("Not a valid number: " + m_parser_payload); + error->assign("Not a valid number: " + m_parserPayload); return false; } @@ -38,8 +38,7 @@ bool Status::init(std::string *error) { } -bool Status::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { +bool Status::execute(Transaction *transaction) const noexcept { transaction->m_it.status = m_status; return true; } diff --git a/src/actions/data/status.h b/src/actions/data/status.h index 214cbcffae..b5d51ba773 100644 --- a/src/actions/data/status.h +++ b/src/actions/data/status.h @@ -13,33 +13,37 @@ * */ + #include -#include #include "modsecurity/actions/action.h" -#include "modsecurity/rule_message.h" +#include "modsecurity/transaction.h" + +#include "src/actions/action_allowed_in_sec_default_action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_DATA_STATUS_H_ #define SRC_ACTIONS_DATA_STATUS_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; namespace actions { namespace data { -class Status : public Action { +class Status : public ActionAllowedAsSecDefaultAction, public ActionWithExecution { public: - explicit Status(const std::string &action) : Action(action, 2), - m_status(0) { } + explicit Status(const std::string &action) + : Action(action), + m_status(0) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + bool execute(Transaction *transaction) const noexcept override; + + private: int m_status; }; @@ -47,6 +51,6 @@ class Status : public Action { } // namespace data } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_DATA_STATUS_H_ diff --git a/src/actions/disruptive/allow.cc b/src/actions/disruptive/allow.cc index 3a360b5538..c644ee7460 100644 --- a/src/actions/disruptive/allow.cc +++ b/src/actions/disruptive/allow.cc @@ -13,16 +13,19 @@ * */ + #include "src/actions/disruptive/allow.h" -#include #include -#include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + #include "src/utils/string.h" -#include "modsecurity/modsecurity.h" namespace modsecurity { @@ -31,7 +34,7 @@ namespace disruptive { bool Allow::init(std::string *error) { - std::string a = utils::string::tolower(m_parser_payload); + std::string a = utils::string::tolower(m_parserPayload); if (a == "phase") { m_allowType = PhaseAllowType; @@ -49,7 +52,7 @@ bool Allow::init(std::string *error) { } -bool Allow::evaluate(RuleWithActions *rule, Transaction *transaction) { +bool Allow::execute(Transaction *transaction) const noexcept { ms_dbg_a(transaction, 4, "Dropping the evaluation of upcoming rules " \ "in favor of an `allow' action of type: " \ + allowTypeToName(m_allowType)); diff --git a/src/actions/disruptive/allow.h b/src/actions/disruptive/allow.h index de79b20515..e8dd14e79f 100644 --- a/src/actions/disruptive/allow.h +++ b/src/actions/disruptive/allow.h @@ -13,20 +13,21 @@ * */ + #include #include "modsecurity/actions/action.h" +#include "modsecurity/transaction.h" + +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_DISRUPTIVE_ALLOW_H_ #define SRC_ACTIONS_DISRUPTIVE_ALLOW_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; -class RuleWithOperator; - namespace actions { namespace disruptive { @@ -51,17 +52,18 @@ enum AllowType : int { }; -class Allow : public Action { +class Allow : public ActionDisruptive, public ActionWithExecution { public: - explicit Allow(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_allowType(NoneAllowType) { } - + explicit Allow(const std::string &action) + : Action(action), + m_allowType(NoneAllowType) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool isDisruptive() override { return true; } + bool execute(Transaction *transaction) const noexcept override; + + private: AllowType m_allowType; static std::string allowTypeToName(AllowType a) { @@ -83,6 +85,6 @@ class Allow : public Action { } // namespace disruptive } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_DISRUPTIVE_ALLOW_H_ diff --git a/src/actions/disruptive/deny.cc b/src/actions/disruptive/deny.cc index 40572edecd..44e17621b1 100644 --- a/src/actions/disruptive/deny.cc +++ b/src/actions/disruptive/deny.cc @@ -13,23 +13,26 @@ * */ + #include "src/actions/disruptive/deny.h" -#include -#include #include -#include -#include #include "modsecurity/transaction.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" +#include "modsecurity/rule_message.h" + namespace modsecurity { namespace actions { namespace disruptive { -bool Deny::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { +bool Deny::execute(Transaction *transaction) const noexcept { ms_dbg_a(transaction, 8, "Running action deny"); if (transaction->m_it.status == 200) { @@ -38,9 +41,10 @@ bool Deny::evaluate(RuleWithActions *rule, Transaction *transaction, transaction->m_it.disruptive = true; intervention::freeLog(&transaction->m_it); - rm->m_isDisruptive = true; transaction->m_it.log = strdup( - rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); + transaction->messageGetLast()->log( + RuleMessage::LogMessageInfo::ClientLogMessageInfo) + .c_str()); return true; } diff --git a/src/actions/disruptive/deny.h b/src/actions/disruptive/deny.h index 4e72ba174e..21381f4981 100644 --- a/src/actions/disruptive/deny.h +++ b/src/actions/disruptive/deny.h @@ -13,29 +13,32 @@ * */ + #include -#include -#include "modsecurity/rules_set.h" #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule_message.h" + +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_DISRUPTIVE_DENY_H_ #define SRC_ACTIONS_DISRUPTIVE_DENY_H_ + namespace modsecurity { namespace actions { namespace disruptive { -class Deny : public Action { +class Deny : public ActionDisruptive, public ActionWithExecution { public: - explicit Deny(const std::string &action) : Action(action) { } + Deny() + : Action("deny") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; - bool isDisruptive() override { return true; } + bool execute(Transaction *transaction) const noexcept override; }; @@ -43,4 +46,5 @@ class Deny : public Action { } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_DISRUPTIVE_DENY_H_ diff --git a/src/actions/disruptive/disruptive_action.h b/src/actions/disruptive/disruptive_action.h new file mode 100644 index 0000000000..125ca1460a --- /dev/null +++ b/src/actions/disruptive/disruptive_action.h @@ -0,0 +1,42 @@ +/* + * 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 "modsecurity/actions/action.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + + +#ifndef SRC_ACTIONS_DISRUPTIVE_DISRUPTIVE_ACTION_H_ +#define SRC_ACTIONS_DISRUPTIVE_DISRUPTIVE_ACTION_H_ + + +namespace modsecurity { +namespace actions { +namespace disruptive { + + +class ActionDisruptive : public ActionAllowedAsSecDefaultAction { + public: +}; + + +} // namespace disruptive +} // namespace actions +} // namespace modsecurity + + +#endif // SRC_ACTIONS_DISRUPTIVE_DISRUPTIVE_ACTION_H_ diff --git a/src/actions/disruptive/drop.cc b/src/actions/disruptive/drop.cc index 097bd56826..a4f1864a98 100644 --- a/src/actions/disruptive/drop.cc +++ b/src/actions/disruptive/drop.cc @@ -13,27 +13,26 @@ * */ + #include "src/actions/disruptive/drop.h" -#include -#include #include -#include -#include -#include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "src/utils/string.h" -#include "modsecurity/modsecurity.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" +#include "modsecurity/rule_message.h" + namespace modsecurity { namespace actions { namespace disruptive { -bool Drop::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { +bool Drop::execute(Transaction *transaction) const noexcept { ms_dbg_a(transaction, 8, "Running action drop " \ "[executing deny instead of drop.]"); @@ -43,9 +42,11 @@ bool Drop::evaluate(RuleWithActions *rule, Transaction *transaction, transaction->m_it.disruptive = true; intervention::freeLog(&transaction->m_it); - rm->m_isDisruptive = true; + transaction->m_it.log = strdup( - rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); + transaction->messageGetLast()->log( + RuleMessage::LogMessageInfo::ClientLogMessageInfo) + .c_str()); return true; } diff --git a/src/actions/disruptive/drop.h b/src/actions/disruptive/drop.h index 2da823c8b0..840bf83010 100644 --- a/src/actions/disruptive/drop.h +++ b/src/actions/disruptive/drop.h @@ -13,28 +13,32 @@ * */ + #include -#include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule_message.h" + +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_DISRUPTIVE_DROP_H_ #define SRC_ACTIONS_DISRUPTIVE_DROP_H_ + namespace modsecurity { namespace actions { namespace disruptive { -class Drop : public Action { +class Drop : public ActionDisruptive, public ActionWithExecution { public: - explicit Drop(const std::string &action) : Action(action) { } + Drop() + : Action("drop") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; - bool isDisruptive() override { return true; } + bool execute(Transaction *transaction) const noexcept override; }; diff --git a/src/actions/disruptive/pass.cc b/src/actions/disruptive/pass.cc index 4b4c8fad65..84941334b0 100644 --- a/src/actions/disruptive/pass.cc +++ b/src/actions/disruptive/pass.cc @@ -13,24 +13,25 @@ * */ + #include "src/actions/disruptive/pass.h" -#include #include -#include -#include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_message.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + namespace modsecurity { namespace actions { namespace disruptive { -bool Pass::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { +bool Pass::execute(Transaction *transaction) const noexcept { intervention::free(&transaction->m_it); intervention::reset(&transaction->m_it); diff --git a/src/actions/disruptive/pass.h b/src/actions/disruptive/pass.h index dc1f6a583e..023aa2108c 100644 --- a/src/actions/disruptive/pass.h +++ b/src/actions/disruptive/pass.h @@ -13,27 +13,32 @@ * */ + #include -#include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/action_with_execution.h" + + #ifndef SRC_ACTIONS_DISRUPTIVE_PASS_H_ #define SRC_ACTIONS_DISRUPTIVE_PASS_H_ + namespace modsecurity { namespace actions { namespace disruptive { -class Pass : public Action { +class Pass : public ActionDisruptive, public ActionWithExecution { public: - explicit Pass(const std::string &action) : Action(action) { } + Pass() + : Action("pass") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; - bool isDisruptive() override { return true; } + bool execute(Transaction *transaction) const noexcept override; }; diff --git a/src/actions/disruptive/redirect.cc b/src/actions/disruptive/redirect.cc index 07ac262576..fd41938647 100644 --- a/src/actions/disruptive/redirect.cc +++ b/src/actions/disruptive/redirect.cc @@ -13,33 +13,31 @@ * */ + #include "src/actions/disruptive/redirect.h" -#include -#include #include -#include #include "modsecurity/transaction.h" -#include "src/utils/string.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" +#include "modsecurity/rule_message.h" + namespace modsecurity { namespace actions { namespace disruptive { -bool Redirect::init(std::string *error) { - m_status = 302; - return true; -} - - -bool Redirect::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - std::string m_urlExpanded(m_string->evaluate(transaction)); +bool Redirect::execute(Transaction *transaction) const noexcept { + 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))) { + || (!(transaction->m_it.status <= 307 + && transaction->m_it.status >= 301))) { transaction->m_it.status = m_status; } @@ -47,9 +45,11 @@ bool Redirect::evaluate(RuleWithActions *rule, Transaction *transaction, transaction->m_it.url = strdup(m_urlExpanded.c_str()); transaction->m_it.disruptive = true; intervention::freeLog(&transaction->m_it); - rm->m_isDisruptive = true; + transaction->m_it.log = strdup( - rm->log(RuleMessage::LogMessageInfo::ClientLogMessageInfo).c_str()); + transaction->messageGetLast()->log( + RuleMessage::LogMessageInfo::ClientLogMessageInfo) + .c_str()); return true; } diff --git a/src/actions/disruptive/redirect.h b/src/actions/disruptive/redirect.h index 6988954161..a4094b633c 100644 --- a/src/actions/disruptive/redirect.h +++ b/src/actions/disruptive/redirect.h @@ -13,53 +13,62 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "modsecurity/rule_message.h" +#include "modsecurity/transaction.h" + +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/disruptive/disruptive_action.h" #include "src/run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_DISRUPTIVE_REDIRECT_H_ #define SRC_ACTIONS_DISRUPTIVE_REDIRECT_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; - namespace actions { namespace disruptive { -class Redirect : public Action { +class Redirect : public ActionWithRunTimeString, public ActionDisruptive, + public ActionWithExecution { public: - explicit Redirect(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_status(0), - m_string(nullptr) { } + explicit Redirect(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("redirect"), + m_status(302) + { } + - explicit Redirect(std::unique_ptr z) - : Action("redirert", RunTimeOnlyIfMatchKind), - m_status(0), - m_string(std::move(z)) { } + explicit Redirect(const Redirect &action) + : ActionWithRunTimeString(action), + ActionDisruptive(action), + Action(action), + m_status(action.m_status) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; - bool init(std::string *error) override; - bool isDisruptive() override { return true; } + + bool execute(Transaction *transaction) const noexcept override; + + + ActionWithRunTimeString *clone() override { + return new Redirect(*this); + } private: int m_status; - std::unique_ptr m_string; }; } // namespace disruptive } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_DISRUPTIVE_REDIRECT_H_ diff --git a/src/actions/exec.cc b/src/actions/exec.cc index 93cc5ff2bf..5047846faa 100644 --- a/src/actions/exec.cc +++ b/src/actions/exec.cc @@ -13,15 +13,18 @@ * */ + #include "src/actions/exec.h" -#include #include -#include "modsecurity/rules_set.h" -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + #include "src/utils/system.h" #include "src/engine/lua.h" @@ -33,7 +36,7 @@ namespace actions { bool Exec::init(std::string *error) { std::string err; - m_script = utils::find_resource(m_parser_payload, "", &err); + m_script = utils::find_resource(m_parserPayload, "", &err); if (m_script.size() == 0) { error->assign("exec: Script not found: " + err); @@ -49,7 +52,7 @@ bool Exec::init(std::string *error) { } -bool Exec::evaluate(RuleWithActions *rule, Transaction *t) { +bool Exec::execute(Transaction *t) const noexcept { ms_dbg_a(t, 8, "Running script... " + m_script); m_lua.run(t); return true; diff --git a/src/actions/exec.h b/src/actions/exec.h index 42537d038e..6398ea9dad 100644 --- a/src/actions/exec.h +++ b/src/actions/exec.h @@ -13,30 +13,32 @@ * */ + #include #include "modsecurity/actions/action.h" #include "src/engine/lua.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_EXEC_H_ #define SRC_ACTIONS_EXEC_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Exec : public Action { +class Exec : public ActionWithExecution { public: - explicit Exec(const std::string &action) + explicit Exec(const std::string &action) : Action(action), - m_script("") { } + m_script("") + { } ~Exec() { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; bool init(std::string *error) override; private: diff --git a/src/actions/expire_var.h b/src/actions/expire_var.h new file mode 100644 index 0000000000..415fb14611 --- /dev/null +++ b/src/actions/expire_var.h @@ -0,0 +1,54 @@ +/* + * 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 + +#include "modsecurity/actions/action.h" +#include "modsecurity/transaction.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.h" + + +#ifndef SRC_ACTIONS_EXPIRE_VAR_H_ +#define SRC_ACTIONS_EXPIRE_VAR_H_ + + +namespace modsecurity { +namespace actions { + + +class ExpireVar : public ActionWithExecution { + public: + explicit ExpireVar(const std::string &action) + : Action(action) + { } + + ~ExpireVar() { } + + bool execute(Transaction *transaction) const noexcept override { return true; }; + bool init(std::string *error) override { return true; }; + + private: +}; + + +} // namespace actions +} // namespace modsecurity + + +#endif // SRC_ACTIONS_EXPIRE_VAR_H_ diff --git a/src/actions/init_col.cc b/src/actions/init_col.cc index 246084503d..fb4b48b84a 100644 --- a/src/actions/init_col.cc +++ b/src/actions/init_col.cc @@ -13,14 +13,17 @@ * */ + #include "src/actions/init_col.h" -#include #include -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" namespace modsecurity { @@ -28,9 +31,9 @@ namespace actions { bool InitCol::init(std::string *error) { - int posEquals = m_parser_payload.find("="); + int posEquals = m_parserPayload.find("="); - if (m_parser_payload.size() < 2) { + if (m_parserPayload.size() < 2) { error->assign("Something wrong with initcol format: too small"); return false; } @@ -40,7 +43,7 @@ bool InitCol::init(std::string *error) { return false; } - m_collection_key = std::string(m_parser_payload, 0, posEquals); + m_collection_key = std::string(m_parserPayload, 0, posEquals); if (m_collection_key != "ip" && m_collection_key != "global" && @@ -54,8 +57,8 @@ bool InitCol::init(std::string *error) { } -bool InitCol::evaluate(RuleWithActions *rule, Transaction *t) { - std::string collectionName(m_string->evaluate(t)); +bool InitCol::execute(Transaction *t) const noexcept { + 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 a7086204d6..58a34de8c5 100644 --- a/src/actions/init_col.h +++ b/src/actions/init_col.h @@ -13,36 +13,50 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.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 ActionWithExecution { public: - explicit InitCol(const std::string &action) : Action(action) { } + InitCol( + const std::string &action, + std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action(action) + { } - InitCol(const std::string &action, std::unique_ptr z) - : Action(action, RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + InitCol(const InitCol &action) + : ActionWithRunTimeString(action), + Action(action), + m_collection_key(action.m_collection_key) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + + bool execute(Transaction *transaction) const noexcept override; + + ActionWithRunTimeString *clone() override { + return new InitCol(*this); + } + private: std::string m_collection_key; - std::unique_ptr m_string; }; diff --git a/src/actions/log.cc b/src/actions/log.cc index 320c0bf4bc..3d0b5ae703 100644 --- a/src/actions/log.cc +++ b/src/actions/log.cc @@ -13,28 +13,13 @@ * */ -#include "src/actions/log.h" -#include -#include -#include +#include "src/actions/log.h" -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "src/operators/operator.h" -#include "modsecurity/rule_message.h" namespace modsecurity { namespace actions { -bool Log::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - ms_dbg_a(transaction, 9, "Saving transaction to logs"); - rm->m_saveMessage = true; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/log.h b/src/actions/log.h index 07726ad9a1..b69edca7f3 100644 --- a/src/actions/log.h +++ b/src/actions/log.h @@ -13,30 +13,36 @@ * */ -#include -#include #include "modsecurity/actions/action.h" +#include "src/actions/action_allowed_in_sec_default_action.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/rule_with_actions.h" + + #ifndef SRC_ACTIONS_LOG_H_ #define SRC_ACTIONS_LOG_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Log : public Action { +class Log : public ActionTypeRuleMetaData, + public ActionAllowedAsSecDefaultAction { public: - explicit Log(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + Log() + : Action("log") + { } + + void configure(RuleWithActions *rule) override { + rule->setLog(true); + } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; }; + } // namespace actions } // namespace modsecurity diff --git a/src/actions/log_data.cc b/src/actions/log_data.cc index 359dd299fe..ed8fa44bc6 100644 --- a/src/actions/log_data.cc +++ b/src/actions/log_data.cc @@ -13,34 +13,24 @@ * */ + #include "src/actions/log_data.h" -#include #include -#include -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" #include "modsecurity/rule_message.h" namespace modsecurity { namespace actions { - -bool LogData::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - rm->m_data = data(transaction); - +bool LogData::execute(Transaction *transaction) const noexcept { + 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 486d826bc2..3aacd7f46f 100644 --- a/src/actions/log_data.h +++ b/src/actions/log_data.h @@ -13,38 +13,40 @@ * */ -#include -#include -#include #include "modsecurity/actions/action.h" + +#include "src/actions/action_with_run_time_string.h" #include "src/run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_LOG_DATA_H_ #define SRC_ACTIONS_LOG_DATA_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class LogData : public Action { +class LogData : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit LogData(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit LogData(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("logdata") + { } - explicit LogData(std::unique_ptr z) - : Action("logdata", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit LogData(const LogData &data) + : ActionWithRunTimeString(data), + Action(data) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + bool execute(Transaction *transaction) const noexcept override; - std::string data(Transaction *Transaction); + ActionWithRunTimeString *clone() override { + return new LogData(*this); + } - std::unique_ptr m_string; }; diff --git a/src/actions/maturity.cc b/src/actions/maturity.cc index b601208d9f..ee12200f84 100644 --- a/src/actions/maturity.cc +++ b/src/actions/maturity.cc @@ -13,15 +13,11 @@ * */ + #include "src/actions/maturity.h" -#include #include -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" - namespace modsecurity { namespace actions { @@ -29,9 +25,9 @@ namespace actions { bool Maturity::init(std::string *error) { try { - m_maturity = std::stoi(m_parser_payload); + m_maturity = std::stoi(m_parserPayload); } catch (...) { - error->assign("Maturity: The input \"" + m_parser_payload + "\" is " \ + error->assign("Maturity: The input \"" + m_parserPayload + "\" is " \ "not a number."); return false; } @@ -39,11 +35,5 @@ bool Maturity::init(std::string *error) { } -bool Maturity::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->m_maturity = m_maturity; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/maturity.h b/src/actions/maturity.h index 4fa5a5eda5..729476eb74 100644 --- a/src/actions/maturity.h +++ b/src/actions/maturity.h @@ -13,9 +13,11 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_MATURITY_H_ #define SRC_ACTIONS_MATURITY_H_ @@ -27,15 +29,18 @@ class Transaction; namespace actions { -class Maturity : public Action { +class Maturity : public ActionTypeRuleMetaData { public: - explicit Maturity(const std::string &action) - : Action(action, ConfigurationKind), + explicit Maturity(const std::string &action) + : Action(action), m_maturity(0) { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + void configure(RuleWithActions *rule) override { + rule->setMaturity(m_maturity); + } + private: int m_maturity; }; diff --git a/src/actions/msg.cc b/src/actions/msg.cc index c553b1d655..157e710488 100644 --- a/src/actions/msg.cc +++ b/src/actions/msg.cc @@ -13,16 +13,19 @@ * */ + #include "src/actions/msg.h" -#include #include -#include -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_message.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + +#include "src/run_time_string.h" /* * Description: Assigns a custom message to the rule or chain in which it @@ -46,21 +49,14 @@ namespace modsecurity { namespace actions { -bool Msg::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - std::string msg = data(transaction); - rm->m_message = msg; +bool Msg::execute(Transaction *transaction) const noexcept { + std::string msg = getEvaluatedRunTimeString(transaction); + transaction->messageGetLast()->m_message = msg; ms_dbg_a(transaction, 9, "Saving msg: " + msg); return true; } -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 8f6ad06fda..5379258acb 100644 --- a/src/actions/msg.h +++ b/src/actions/msg.h @@ -13,13 +13,16 @@ * */ + #include #include #include #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" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_MSG_H_ #define SRC_ACTIONS_MSG_H_ @@ -31,20 +34,23 @@ class Transaction; namespace actions { -class Msg : public Action { +class Msg : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit Msg(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + explicit Msg(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("msg") + { }; - explicit Msg(std::unique_ptr z) - : Action("msg", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit Msg(const Msg &action) + : ActionWithRunTimeString(action), + Action(action) + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + bool execute(Transaction *transaction) const noexcept override; - std::string data(Transaction *Transaction); - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new Msg(*this); + } }; diff --git a/src/actions/multi_match.cc b/src/actions/multi_match.cc index 71189c2c0c..cf39e15021 100644 --- a/src/actions/multi_match.cc +++ b/src/actions/multi_match.cc @@ -13,22 +13,13 @@ * */ -#include "src/actions/multi_match.h" -#include -#include +#include "src/actions/multi_match.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" namespace modsecurity { namespace actions { -bool MultiMatch::evaluate(RuleWithActions *rule, Transaction *transaction) { - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/multi_match.h b/src/actions/multi_match.h index abab94f8ce..74f1431337 100644 --- a/src/actions/multi_match.h +++ b/src/actions/multi_match.h @@ -13,33 +13,34 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_MULTI_MATCH_H_ #define SRC_ACTIONS_MULTI_MATCH_H_ -#ifdef __cplusplus -class Transaction; - namespace modsecurity { -class Transaction; -class RuleWithOperator; - namespace actions { -class MultiMatch : public Action { +class MultiMatch : public ActionTypeRuleMetaData { public: - explicit MultiMatch(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + MultiMatch() + : Action("multiMatch") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + + void configure(RuleWithActions *rule) override { + rule->setMultiMatch(true); + } }; + } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_MULTI_MATCH_H_ diff --git a/src/actions/no_audit_log.cc b/src/actions/no_audit_log.cc index ef5d8bb234..a8387d181b 100644 --- a/src/actions/no_audit_log.cc +++ b/src/actions/no_audit_log.cc @@ -13,27 +13,13 @@ * */ -#include "src/actions/no_audit_log.h" -#include -#include +#include "src/actions/no_audit_log.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_message.h" namespace modsecurity { namespace actions { -bool NoAuditLog::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - rm->m_noAuditLog = true; - rm->m_saveMessage = false; - - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/no_audit_log.h b/src/actions/no_audit_log.h index fbcac6d688..604d65c825 100644 --- a/src/actions/no_audit_log.h +++ b/src/actions/no_audit_log.h @@ -13,34 +13,36 @@ * */ -#include -#include #include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + + #ifndef SRC_ACTIONS_NO_AUDIT_LOG_H_ #define SRC_ACTIONS_NO_AUDIT_LOG_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; - namespace actions { -class NoAuditLog : public Action { +class NoAuditLog : public ActionTypeRuleMetaData, + public ActionAllowedAsSecDefaultAction { public: - explicit NoAuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + NoAuditLog() + : Action("noAuditLog") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + void configure(RuleWithActions *rule) override { + rule->setNoAuditLog(true); + } }; + } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_NO_AUDIT_LOG_H_ diff --git a/src/actions/no_log.cc b/src/actions/no_log.cc index 4b28240610..5375201e1f 100644 --- a/src/actions/no_log.cc +++ b/src/actions/no_log.cc @@ -13,28 +13,13 @@ * */ -#include "src/actions/no_log.h" - -#include -#include -#include -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "src/operators/operator.h" -#include "modsecurity/rule_message.h" +#include "src/actions/no_log.h" namespace modsecurity { namespace actions { -bool NoLog::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - rm->m_saveMessage = false; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/no_log.h b/src/actions/no_log.h index 78e1892db6..6d74068aa8 100644 --- a/src/actions/no_log.h +++ b/src/actions/no_log.h @@ -13,30 +13,34 @@ * */ -#include -#include #include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + + #ifndef SRC_ACTIONS_NO_LOG_H_ #define SRC_ACTIONS_NO_LOG_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class NoLog : public Action { +class NoLog : public ActionTypeRuleMetaData, + public ActionAllowedAsSecDefaultAction { public: - explicit NoLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + NoLog() + : Action("noLog") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; + void configure(RuleWithActions *rule) override { + rule->setNoLog(true); + } }; + } // namespace actions } // namespace modsecurity diff --git a/src/actions/phase.cc b/src/actions/phase.cc index d82cbe027f..fe772bf38c 100644 --- a/src/actions/phase.cc +++ b/src/actions/phase.cc @@ -15,12 +15,10 @@ #include "src/actions/phase.h" -#include #include #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/modsecurity.h" + #include "src/utils/string.h" @@ -28,11 +26,11 @@ namespace modsecurity { namespace actions { bool Phase::init(std::string *error) { - std::string a = utils::string::tolower(m_parser_payload); + std::string a = utils::string::tolower(m_parserPayload); m_phase = -1; try { - m_phase = std::stoi(m_parser_payload); + m_phase = std::stoi(m_parserPayload); if (m_phase == 0) { m_phase = modsecurity::Phases::ConnectionPhase; m_secRulesPhase = 0; @@ -52,7 +50,7 @@ bool Phase::init(std::string *error) { m_phase = modsecurity::Phases::LoggingPhase; m_secRulesPhase = 5; } else { - error->assign("Unknown phase: " + m_parser_payload); + error->assign("Unknown phase: " + m_parserPayload); return false; } } catch (...) { @@ -72,10 +70,5 @@ bool Phase::init(std::string *error) { } -bool Phase::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->setPhase(m_phase); - return true; -} - } // namespace actions } // namespace modsecurity diff --git a/src/actions/phase.h b/src/actions/phase.h index c85842e5bb..be1f007983 100644 --- a/src/actions/phase.h +++ b/src/actions/phase.h @@ -13,38 +13,48 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_PHASE_H_ #define SRC_ACTIONS_PHASE_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; -class RuleWithOperator; - namespace actions { -class Phase : public Action { +class Phase : public ActionTypeRuleMetaData { public: - explicit Phase(const std::string &action) : Action(action, ConfigurationKind), + explicit Phase(const std::string &action) + : Action(action), m_phase(0), m_secRulesPhase(0) { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + void configure(RuleWithActions *rule) override { + rule->setPhase(m_phase); + } + + int getSecRulePhase() const { + return m_secRulesPhase; + } + + int getPhase() const { + return m_phase; + } + + private: int m_phase; int m_secRulesPhase; }; + } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_PHASE_H_ diff --git a/src/actions/rev.cc b/src/actions/rev.cc index 7d886b9624..49e1c1b5aa 100644 --- a/src/actions/rev.cc +++ b/src/actions/rev.cc @@ -13,28 +13,18 @@ * */ + #include "src/actions/rev.h" -#include #include -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" - namespace modsecurity { namespace actions { bool Rev::init(std::string *error) { - m_rev = m_parser_payload; - return true; -} - - -bool Rev::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->m_rev = m_rev; + m_revision = m_parserPayload; return true; } diff --git a/src/actions/rev.h b/src/actions/rev.h index feb1012d24..b577bd21e6 100644 --- a/src/actions/rev.h +++ b/src/actions/rev.h @@ -13,29 +13,35 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_REV_H_ #define SRC_ACTIONS_REV_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Rev : public Action { +class Rev : public ActionTypeRuleMetaData { public: - explicit Rev(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Rev(const std::string &action) + : Action(action), + m_revision("") + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; + void configure(RuleWithActions *rule) override { + rule->setRevision(m_revision); + } + private: - std::string m_rev; + std::string m_revision; }; diff --git a/src/actions/rule_id.cc b/src/actions/rule_id.cc index a5b646128c..c5d5f9ae6a 100644 --- a/src/actions/rule_id.cc +++ b/src/actions/rule_id.cc @@ -13,33 +13,29 @@ * */ + #include "src/actions/rule_id.h" -#include #include -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" namespace modsecurity { namespace actions { bool RuleId::init(std::string *error) { - std::string a = m_parser_payload; + std::string a = m_parserPayload; - try { - m_ruleId = std::stod(a); - } catch (...) { + std::istringstream iss(a); + iss >> m_ruleId; + if (iss.fail()) { m_ruleId = 0; error->assign("The input \"" + a + "\" does not " \ "seems to be a valid rule id."); return false; } - std::ostringstream oss; - oss << std::setprecision(40) << m_ruleId; - if (a != oss.str() || m_ruleId < 0) { + if (a != std::to_string(m_ruleId) || m_ruleId < 0) { error->assign("The input \"" + a + "\" does not seems " \ "to be a valid rule id."); return false; @@ -48,11 +44,5 @@ bool RuleId::init(std::string *error) { } -bool RuleId::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->m_ruleId = m_ruleId; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/rule_id.h b/src/actions/rule_id.h index 0a6b380718..de7265a3b9 100644 --- a/src/actions/rule_id.h +++ b/src/actions/rule_id.h @@ -13,38 +13,40 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_RULE_ID_H_ #define SRC_ACTIONS_RULE_ID_H_ -#ifdef __cplusplus -class Transaction; namespace modsecurity { -class Transaction; -class RuleWithOperator; - namespace actions { -class RuleId : public Action { +class RuleId : public ActionTypeRuleMetaData { public: - explicit RuleId(const std::string &action) - : Action(action, ConfigurationKind), - m_ruleId(0) { } + explicit RuleId(const std::string &action) + : Action(action), + m_ruleId(0) + { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + + void configure(RuleWithActions *rule) override { + rule->setId(m_ruleId); + } private: - double m_ruleId; + modsecurity::RuleId m_ruleId; }; + } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_RULE_ID_H_ diff --git a/src/actions/set_env.cc b/src/actions/set_env.cc index 7541916380..f802954c3f 100644 --- a/src/actions/set_env.cc +++ b/src/actions/set_env.cc @@ -13,26 +13,27 @@ * */ + #include "src/actions/set_env.h" -#include #include #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "src/utils/string.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" -namespace modsecurity { -namespace actions { +#include "src/run_time_string.h" -bool SetENV::init(std::string *error) { - return true; -} +namespace modsecurity { +namespace actions { -bool SetENV::evaluate(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); +bool SetENV::execute(Transaction *t) const noexcept { + 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 fcfc411f99..d60a11da59 100644 --- a/src/actions/set_env.h +++ b/src/actions/set_env.h @@ -13,12 +13,15 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SET_ENV_H_ #define SRC_ACTIONS_SET_ENV_H_ @@ -30,20 +33,23 @@ class Transaction; namespace actions { -class SetENV : public Action { +class SetENV : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit SetENV(const std::string &_action) - : Action(_action) { } + explicit SetENV(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("setenv") + { }; - explicit SetENV(std::unique_ptr z) - : Action("setenv", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetENV(const SetENV &action) + : ActionWithRunTimeString(action), + Action(action) + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + bool execute(Transaction *transaction) const noexcept override; - private: - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new SetENV(*this); + } }; diff --git a/src/actions/set_rsc.cc b/src/actions/set_rsc.cc index 34db37b213..75c35e05c0 100644 --- a/src/actions/set_rsc.cc +++ b/src/actions/set_rsc.cc @@ -13,26 +13,25 @@ * */ + #include "src/actions/set_rsc.h" -#include #include #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" namespace modsecurity { namespace actions { -bool SetRSC::init(std::string *error) { - return true; -} - - -bool SetRSC::evaluate(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); +bool SetRSC::execute(Transaction *t) const noexcept { + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "RESOURCE initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +41,6 @@ bool SetRSC::evaluate(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 013e066286..058f536524 100644 --- a/src/actions/set_rsc.h +++ b/src/actions/set_rsc.h @@ -13,12 +13,15 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SET_RSC_H_ #define SRC_ACTIONS_SET_RSC_H_ @@ -30,20 +33,23 @@ class Transaction; namespace actions { -class SetRSC : public Action { +class SetRSC : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit SetRSC(const std::string &_action) - : Action(_action) { } + explicit SetRSC(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("setsrc") + { }; - explicit SetRSC(std::unique_ptr z) - : Action("setsrc", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetRSC(const SetRSC &action) + : ActionWithRunTimeString(action), + Action(action) + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + bool execute(Transaction *transaction) const noexcept override; - private: - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new SetRSC(*this); + } }; diff --git a/src/actions/set_sid.cc b/src/actions/set_sid.cc index e4c531115f..820edb4e97 100644 --- a/src/actions/set_sid.cc +++ b/src/actions/set_sid.cc @@ -13,26 +13,25 @@ * */ + #include "src/actions/set_sid.h" -#include #include #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" namespace modsecurity { namespace actions { -bool SetSID::init(std::string *error) { - return true; -} - - -bool SetSID::evaluate(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); +bool SetSID::execute(Transaction *t) const noexcept { + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "Session ID initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +41,6 @@ bool SetSID::evaluate(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 c8353854b7..2928a18a48 100644 --- a/src/actions/set_sid.h +++ b/src/actions/set_sid.h @@ -13,12 +13,15 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SET_SID_H_ #define SRC_ACTIONS_SET_SID_H_ @@ -30,20 +33,23 @@ class Transaction; namespace actions { -class SetSID : public Action { +class SetSID : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit SetSID(const std::string &_action) - : Action(_action) { } + explicit SetSID(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("setsid") + { }; - explicit SetSID(std::unique_ptr z) - : Action("setsid", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + SetSID(const SetSID &action) + : ActionWithRunTimeString(action), + Action(action) + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + bool execute(Transaction *transaction) const noexcept override; - private: - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new SetSID(*this); + } }; diff --git a/src/actions/set_uid.cc b/src/actions/set_uid.cc index 90de7e47ff..7069a1cabb 100644 --- a/src/actions/set_uid.cc +++ b/src/actions/set_uid.cc @@ -13,26 +13,25 @@ * */ + #include "src/actions/set_uid.h" -#include #include #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" namespace modsecurity { namespace actions { -bool SetUID::init(std::string *error) { - return true; -} - - -bool SetUID::evaluate(RuleWithActions *rule, Transaction *t) { - std::string colNameExpanded(m_string->evaluate(t)); +bool SetUID::execute(Transaction *t) const noexcept { + std::string colNameExpanded(getEvaluatedRunTimeString(t)); ms_dbg_a(t, 8, "User collection initiated with value: \'" + colNameExpanded + "\'."); @@ -42,5 +41,6 @@ bool SetUID::evaluate(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 b2f341a688..4a7c363a3b 100644 --- a/src/actions/set_uid.h +++ b/src/actions/set_uid.h @@ -13,12 +13,15 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SET_UID_H_ #define SRC_ACTIONS_SET_UID_H_ @@ -30,20 +33,23 @@ class Transaction; namespace actions { -class SetUID : public Action { +class SetUID : public ActionWithRunTimeString, public ActionWithExecution { public: - explicit SetUID(const std::string &_action) - : Action(_action) { } + explicit SetUID(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("setuid") + { }; - explicit SetUID(std::unique_ptr z) - : Action("setuid", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit SetUID(const SetUID &action) + : ActionWithRunTimeString(action), + Action(action) + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + bool execute(Transaction *transaction) const noexcept override; - private: - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new SetUID(*this); + } }; diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index c9f7f6653a..88412910aa 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -13,39 +13,36 @@ * */ + #include "src/actions/set_var.h" -#include #include -#include -#include "modsecurity/rules_set.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "src/utils/string.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + #include "src/variables/global.h" #include "src/variables/ip.h" #include "src/variables/resource.h" #include "src/variables/session.h" #include "src/variables/tx.h" #include "src/variables/user.h" -#include "src/variables/variable.h" + namespace modsecurity { namespace actions { -bool SetVar::init(std::string *error) { - return true; -} - - -bool SetVar::evaluate(RuleWithActions *rule, Transaction *t) { +bool SetVar::execute(Transaction *t) const noexcept { std::string targetValue; std::string resolvedPre; - if (m_string) { - resolvedPre = m_string->evaluate(t, rule); + if (hasRunTimeString()) { + resolvedPre = getEvaluatedRunTimeString(t); } std::string m_variableNameExpanded; @@ -64,19 +61,19 @@ bool SetVar::evaluate(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; + m_variableNameExpanded = *m_variable->getVariableKey(); } if (m_operation == setOperation) { @@ -111,16 +108,12 @@ bool SetVar::evaluate(RuleWithActions *rule, Transaction *t) { } try { - std::vector l; - RuleWithOperator *rr = dynamic_cast(rule); - m_variable->evaluate(t, rr, &l); + VariableValues l; + m_variable->evaluate(t, &l); if (l.size() == 0) { value = 0; } else { value = stoi(l[0]->getValue()); - for (auto &i : l) { - delete i; - } } } catch (...) { value = 0; @@ -133,7 +126,7 @@ bool SetVar::evaluate(RuleWithActions *rule, Transaction *t) { } } - ms_dbg_a(t, 8, "Saving variable: " + m_variable->m_collectionName \ + ms_dbg_a(t, 8, "Saving variable: " + *m_variable->getVariableKeyWithCollection() \ + ":" + m_variableNameExpanded + " with value: " + targetValue); if (tx) { diff --git a/src/actions/set_var.h b/src/actions/set_var.h index 22905a8cc5..bb0d1daa32 100644 --- a/src/actions/set_var.h +++ b/src/actions/set_var.h @@ -13,22 +13,27 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "modsecurity/transaction.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/variables/variable_with_runtime_string.h" +#include "src/rule_with_operator.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SET_VAR_H_ #define SRC_ACTIONS_SET_VAR_H_ -namespace modsecurity { -class Transaction; -class RuleWithOperator; +namespace modsecurity { namespace actions { + enum SetVarOperation { /* Set variable to something */ setOperation, @@ -42,31 +47,74 @@ enum SetVarOperation { unsetOperation, }; -class SetVar : public Action { + +class SetVar : public ActionWithRunTimeString, public ActionWithExecution { public: SetVar(SetVarOperation operation, std::unique_ptr variable, std::unique_ptr predicate) - : Action("setvar"), + : ActionWithRunTimeString(std::move(predicate)), m_operation(operation), m_variable(std::move(variable)), - m_string(std::move(predicate)) { } + Action("setvar") + { } + SetVar(SetVarOperation operation, std::unique_ptr variable) - : Action("setvar"), + : ActionWithRunTimeString(), + Action("setvar"), m_operation(operation), - m_variable(std::move(variable)) { } + m_variable(std::move(variable)) + { } + - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; - bool init(std::string *error) override; + SetVar(const SetVar &var) + : ActionWithRunTimeString(var), + Action(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(Transaction *transaction) const noexcept override; + + void populate(const 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); + } + } + + ActionWithRunTimeString *clone() override { + return new SetVar(*this); + } private: SetVarOperation m_operation; - std::unique_ptr m_variable; - std::unique_ptr m_string; + std::shared_ptr m_variable; }; + } // namespace actions } // namespace modsecurity diff --git a/src/actions/severity.cc b/src/actions/severity.cc index f7db6bbdbf..99f574be38 100644 --- a/src/actions/severity.cc +++ b/src/actions/severity.cc @@ -13,18 +13,18 @@ * */ + #include "src/actions/severity.h" -#include #include -#include +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ #include "modsecurity/rules_set.h" -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" + #include "src/utils/string.h" -#include "modsecurity/rule_message.h" namespace modsecurity { @@ -32,7 +32,7 @@ namespace actions { bool Severity::init(std::string *error) { - std::string a = utils::string::tolower(m_parser_payload); + std::string a = utils::string::tolower(m_parserPayload); if (a == "emergency") { m_severity = 0; return true; @@ -71,21 +71,5 @@ bool Severity::init(std::string *error) { } -bool Severity::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - ms_dbg_a(transaction, 9, "This rule severity is: " + \ - std::to_string(this->m_severity) + " current transaction is: " + \ - std::to_string(transaction->m_highestSeverityAction)); - - rm->m_severity = m_severity; - - if (transaction->m_highestSeverityAction > this->m_severity) { - transaction->m_highestSeverityAction = this->m_severity; - } - - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/severity.h b/src/actions/severity.h index b9cd812007..d40d102fda 100644 --- a/src/actions/severity.h +++ b/src/actions/severity.h @@ -13,38 +13,41 @@ * */ + #include #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_SEVERITY_H_ #define SRC_ACTIONS_SEVERITY_H_ -#ifdef __cplusplus namespace modsecurity { -class Transaction; - namespace actions { -class Severity : public Action { +class Severity : public ActionTypeRuleMetaData { public: - explicit Severity(const std::string &action) + explicit Severity(const std::string &action) : Action(action), - m_severity(0) { } + m_severity(0) + { } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; bool init(std::string *error) override; + void configure(RuleWithActions *rule) override { + rule->setSeverity(m_severity); + } + + private: int m_severity; }; } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_SEVERITY_H_ diff --git a/src/actions/skip.cc b/src/actions/skip.cc index 1f7d208118..994e9e91df 100644 --- a/src/actions/skip.cc +++ b/src/actions/skip.cc @@ -13,14 +13,18 @@ * */ + #include "src/actions/skip.h" -#include #include -#include "modsecurity/rules_set.h" -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + namespace modsecurity { namespace actions { @@ -28,9 +32,9 @@ namespace actions { bool Skip::init(std::string *error) { try { - m_skip_next = std::stoi(m_parser_payload); + m_skip_next = std::stoi(m_parserPayload); } catch (...) { - error->assign("Skip: The input \"" + m_parser_payload + "\" is " \ + error->assign("Skip: The input \"" + m_parserPayload + "\" is " \ "not a number."); return false; } @@ -38,7 +42,7 @@ bool Skip::init(std::string *error) { } -bool Skip::evaluate(RuleWithActions *rule, Transaction *transaction) { +bool Skip::execute(Transaction *transaction) const noexcept { ms_dbg_a(transaction, 5, "Skipping the next " + \ std::to_string(m_skip_next) + " rules."); diff --git a/src/actions/skip.h b/src/actions/skip.h index 97d2c50f78..6d362eb5c2 100644 --- a/src/actions/skip.h +++ b/src/actions/skip.h @@ -13,9 +13,12 @@ * */ + #include #include "modsecurity/actions/action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SKIP_H_ #define SRC_ACTIONS_SKIP_H_ @@ -27,15 +30,16 @@ class Transaction; namespace actions { -class Skip : public Action { +class Skip : public ActionWithExecution { public: - explicit Skip(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + explicit Skip(const std::string &action) + : Action(action), m_skip_next(0) { } bool init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + bool execute(Transaction *transaction) const noexcept override; + private: int m_skip_next; }; diff --git a/src/actions/skip_after.cc b/src/actions/skip_after.cc index dce03d499c..61daf11535 100644 --- a/src/actions/skip_after.cc +++ b/src/actions/skip_after.cc @@ -13,21 +13,24 @@ * */ + #include "src/actions/skip_after.h" -#include #include -#include "modsecurity/rules_set.h" -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" namespace modsecurity { namespace actions { -bool SkipAfter::evaluate(RuleWithActions *rule, Transaction *transaction) { +bool SkipAfter::execute(Transaction *transaction) const noexcept { ms_dbg_a(transaction, 5, "Setting skipAfter for: " + *m_skipName); transaction->addMarker(m_skipName); return true; diff --git a/src/actions/skip_after.h b/src/actions/skip_after.h index 8a2148d8ed..eee6e8263f 100644 --- a/src/actions/skip_after.h +++ b/src/actions/skip_after.h @@ -13,34 +13,39 @@ * */ + #include #include #include "modsecurity/actions/action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_SKIP_AFTER_H_ #define SRC_ACTIONS_SKIP_AFTER_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class SkipAfter : public Action { +class SkipAfter : public ActionWithExecution { public: - explicit SkipAfter(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), - m_skipName(std::make_shared(m_parser_payload)) { } + explicit SkipAfter(const std::string &action) + : Action(action), + m_skipName(std::make_shared(m_parserPayload)) + { } + + bool execute(Transaction *transaction) const noexcept override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; private: - std::shared_ptr m_skipName; + // FIXME: This should be a regular pointer instead of a shared pointer. + std::shared_ptr m_skipName; }; } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_SKIP_AFTER_H_ diff --git a/src/actions/tag.cc b/src/actions/tag.cc index 3ec06cd126..a880d483f5 100644 --- a/src/actions/tag.cc +++ b/src/actions/tag.cc @@ -13,16 +13,18 @@ * */ + #include "src/actions/tag.h" -#include #include -#include -#include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_message.h" +/** + * FIXME: rules_set.h inclusion is here due to ms_dbg_a. + * It should be removed. + */ +#include "modsecurity/rules_set.h" + /** * Description: Assigns a tag (category) to a rule or a chain. @@ -50,19 +52,8 @@ namespace modsecurity { namespace actions { -std::string Tag::getName(Transaction *transaction) { - std::string tag(m_string->evaluate(transaction)); - return tag; -} - - -bool Tag::evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) { - std::string tag = getName(transaction); - ms_dbg_a(transaction, 9, "Rule tag: " + tag); - - rm->m_tags.push_back(tag); - +bool Tag::execute(Transaction *transaction) const noexcept { + ms_dbg_a(transaction, 9, "Rule tag: " + getTagName(transaction)); return true; } diff --git a/src/actions/tag.h b/src/actions/tag.h index 45d77892ff..100fd9c657 100644 --- a/src/actions/tag.h +++ b/src/actions/tag.h @@ -13,36 +13,48 @@ * */ + #include #include #include #include "modsecurity/actions/action.h" -#include "src/run_time_string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/action_allowed_in_sec_default_action.h" +#include "src/actions/action_with_execution.h" + #ifndef SRC_ACTIONS_TAG_H_ #define SRC_ACTIONS_TAG_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Tag : public Action { +class Tag : public ActionWithRunTimeString, + public ActionAllowedAsSecDefaultAction, public ActionWithExecution { public: - explicit Tag(std::unique_ptr z) - : Action("tag", RunTimeOnlyIfMatchKind), - m_string(std::move(z)) { } + explicit Tag(std::unique_ptr runTimeString) + : ActionWithRunTimeString(std::move(runTimeString)), + Action("tag") + { } + + explicit Tag(const Tag &action) + : ActionWithRunTimeString(action), + Action(action) + { } + + bool execute(Transaction *transaction) const noexcept override; - std::string getName(Transaction *transaction); + inline std::string getTagName(const Transaction *transaction) const { + return getEvaluatedRunTimeString(transaction); + } - bool evaluate(RuleWithActions *rule, Transaction *transaction, - std::shared_ptr rm) override; - protected: - std::unique_ptr m_string; + ActionWithRunTimeString *clone() override { + return new Tag(*this); + } }; diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index e72fefea49..eda000c1ac 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -13,17 +13,13 @@ * */ + #include "src/actions/transformations/base64_decode.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" @@ -32,11 +28,12 @@ namespace actions { namespace transformations { -std::string Base64Decode::evaluate(const std::string &value, - Transaction *transaction) { +void Base64Decode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + std::string value(in.c_str(), in.size()); std::string ret = Utils::Base64::decode(value); - - return ret; + out.assign(ret.c_str(), ret.size()); } diff --git a/src/actions/transformations/base64_decode.h b/src/actions/transformations/base64_decode.h index 6676a99e67..bfaa5275b3 100644 --- a/src/actions/transformations/base64_decode.h +++ b/src/actions/transformations/base64_decode.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Base64Decode : public Transformation { public: - explicit Base64Decode(const std::string &action) : Transformation(action) { } + Base64Decode() + : Action("t:base64Decode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ diff --git a/src/actions/transformations/base64_decode_ext.cc b/src/actions/transformations/base64_decode_ext.cc index 3ea9887c47..a267ccac7d 100644 --- a/src/actions/transformations/base64_decode_ext.cc +++ b/src/actions/transformations/base64_decode_ext.cc @@ -13,17 +13,13 @@ * */ + #include "src/actions/transformations/base64_decode_ext.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" @@ -32,11 +28,11 @@ namespace actions { namespace transformations { -std::string Base64DecodeExt::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode_forgiven(value); - - return ret; +void Base64DecodeExt::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + std::string ret = Utils::Base64::decode_forgiven(in.c_str()); + out.assign(ret.c_str(), ret.size()); } diff --git a/src/actions/transformations/base64_decode_ext.h b/src/actions/transformations/base64_decode_ext.h index 595e31f259..c08c2c7f23 100644 --- a/src/actions/transformations/base64_decode_ext.h +++ b/src/actions/transformations/base64_decode_ext.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Base64DecodeExt : public Transformation { public: - explicit Base64DecodeExt(const std::string &action) : Transformation(action) { } + Base64DecodeExt() + : Action("t:base64DecodeExt") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ diff --git a/src/actions/transformations/base64_encode.cc b/src/actions/transformations/base64_encode.cc index ffc2465a09..6a3d740abb 100644 --- a/src/actions/transformations/base64_encode.cc +++ b/src/actions/transformations/base64_encode.cc @@ -13,17 +13,13 @@ * */ + #include "src/actions/transformations/base64_encode.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" @@ -32,11 +28,12 @@ namespace actions { namespace transformations { -std::string Base64Encode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::encode(value); - - return ret; +void Base64Encode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + std::string ret = Utils::Base64::encode( + std::string(in.c_str(), in.size())); + out.assign(ret.c_str(), ret.size()); } diff --git a/src/actions/transformations/base64_encode.h b/src/actions/transformations/base64_encode.h index a5dfd0bae0..c953187868 100644 --- a/src/actions/transformations/base64_encode.h +++ b/src/actions/transformations/base64_encode.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Base64Encode : public Transformation { public: - explicit Base64Encode(const std::string &action) : Transformation(action) { } + Base64Encode() + : Action("t:base64Encode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ diff --git a/src/actions/transformations/cmd_line.cc b/src/actions/transformations/cmd_line.cc index 8fd73e814e..edf0befc71 100644 --- a/src/actions/transformations/cmd_line.cc +++ b/src/actions/transformations/cmd_line.cc @@ -15,15 +15,10 @@ #include "src/actions/transformations/cmd_line.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -31,12 +26,12 @@ namespace actions { namespace transformations { -std::string CmdLine::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; +void CmdLine::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int space = 0; - for (auto& a : value) { + for (auto& a : in) { switch (a) { /* remove some characters */ case '"': @@ -53,7 +48,7 @@ std::string CmdLine::evaluate(const std::string &value, case '\r': case '\n': if (space == 0) { - ret.append(" "); + out.append(" "); space++; } break; @@ -62,22 +57,20 @@ std::string CmdLine::evaluate(const std::string &value, case '/': case '(': if (space) { - ret.pop_back(); + out.pop_back(); } space = 0; - ret.append(&a, 1); + out.append(&a, 1); break; /* copy normal characters */ default : char b = std::tolower(a); - ret.append(&b, 1); + out.append(&b, 1); space = 0; break; } } - - return ret; } diff --git a/src/actions/transformations/cmd_line.h b/src/actions/transformations/cmd_line.h index 81baf84811..0c92edd0a0 100644 --- a/src/actions/transformations/cmd_line.h +++ b/src/actions/transformations/cmd_line.h @@ -13,35 +13,40 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class CmdLine : public Transformation { public: - explicit CmdLine(const std::string &action) - : Transformation(action) { } + CmdLine() + : Action("t:cmdLine") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 3a0518d79c..319367bf0d 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -13,54 +13,45 @@ * */ + #include "src/actions/transformations/compress_whitespace.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -CompressWhitespace::CompressWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string CompressWhitespace::evaluate(const std::string &value, - Transaction *transaction) { - std::string a; +void CompressWhitespace::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int inWhiteSpace = 0; - int i = 0; + size_t i = 0; + out.reserve(in.size()); - while (i < value.size()) { - if (isspace(value[i])) { + while (i < in.size()) { + if (isspace(in[i])) { if (inWhiteSpace) { i++; continue; } else { inWhiteSpace = 1; - a.append(" ", 1); + out.append(" ", 1); } } else { inWhiteSpace = 0; - a.append(&value.at(i), 1); + out.append(&in.at(i), 1); } i++; } - - return a; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/compress_whitespace.h b/src/actions/transformations/compress_whitespace.h index d8b193703e..ba4c56f285 100644 --- a/src/actions/transformations/compress_whitespace.h +++ b/src/actions/transformations/compress_whitespace.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class CompressWhitespace : public Transformation { public: + CompressWhitespace() + : Action("t:compressWhitespace") + { } - explicit CompressWhitespace(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index 4b23618f1a..081b721598 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -13,19 +13,14 @@ * */ -#include "src/actions/transformations/css_decode.h" -#include +#include "src/actions/transformations/css_decode.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" @@ -34,20 +29,13 @@ namespace actions { namespace transformations { -std::string CssDecode::evaluate(const std::string &value, - Transaction *transaction) { - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - CssDecode::css_decode_inplace(reinterpret_cast(tmp), - value.size()); - - std::string ret(tmp, 0, value.size()); - free(tmp); - return ret; +void CssDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + auto size = CssDecode::css_decode_inplace( + reinterpret_cast(&out[0]), out.size()); + out.resize(size); } diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index 5d41e04d5b..c584ee5b5c 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -13,30 +13,37 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { class CssDecode : public Transformation { public: - explicit CssDecode(const std::string &action) - : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + CssDecode() + : Action("t:cssDecode") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; - static int css_decode_inplace(unsigned char *input, int64_t input_len); + private: + static int css_decode_inplace(unsigned char *input, + int64_t input_len); }; @@ -44,6 +51,5 @@ class CssDecode : public Transformation { } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index e32a42d062..f03255eaef 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -13,29 +13,21 @@ * */ + #include "src/actions/transformations/escape_seq_decode.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" + namespace modsecurity { namespace actions { namespace transformations { -EscapeSeqDecode::EscapeSeqDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, int input_len) { @@ -140,21 +132,14 @@ int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, } -std::string EscapeSeqDecode::evaluate(const std::string &value, - Transaction *transaction) { - - unsigned char *tmp = (unsigned char *) malloc(sizeof(char) - * value.size() + 1); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int size = ansi_c_sequences_decode_inplace(tmp, value.size()); - - std::string ret(""); - ret.assign(reinterpret_cast(tmp), size); - free(tmp); +void EscapeSeqDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { - return ret; + out.assign(in); + auto size = ansi_c_sequences_decode_inplace( + reinterpret_cast(&out[0]), out.size()); + out.resize(size); } } // namespace transformations diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index 654548aa85..9dd4f29608 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -13,35 +13,43 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class EscapeSeqDecode : public Transformation { public: + EscapeSeqDecode() + : Action("t:escapeSeqDecode") + { } - explicit EscapeSeqDecode(const std::string &action) ; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); + private: + static int ansi_c_sequences_decode_inplace(unsigned char *input, + int input_len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ diff --git a/src/actions/transformations/hex_decode.cc b/src/actions/transformations/hex_decode.cc index bc72228fc6..6a43e9756c 100644 --- a/src/actions/transformations/hex_decode.cc +++ b/src/actions/transformations/hex_decode.cc @@ -13,46 +13,31 @@ * */ + #include "src/actions/transformations/hex_decode.h" -#include #include -#include -#include -#include -#include -#include #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + +#include "modsecurity/modsecurity.h" +#include "modsecurity/transaction.h" + #include "src/utils/string.h" + namespace modsecurity { namespace actions { namespace transformations { -std::string HexDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - int size = 0; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - - return ret; +void HexDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + auto size = inplace(reinterpret_cast( + &out[0]), out.length()); + out.resize(size); } diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index 8f8aa2ebb2..4af8bfc962 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -13,35 +13,42 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class HexDecode : public Transformation { public: - explicit HexDecode(const std::string &action) : Transformation(action) { } + HexDecode() + : Action("t:hexDecode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + private: static int inplace(unsigned char *data, int len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ diff --git a/src/actions/transformations/hex_encode.cc b/src/actions/transformations/hex_encode.cc index 912c6f2760..b1676f2241 100644 --- a/src/actions/transformations/hex_encode.cc +++ b/src/actions/transformations/hex_encode.cc @@ -13,41 +13,33 @@ * */ + #include "src/actions/transformations/hex_encode.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -HexEncode::HexEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string HexEncode::evaluate(const std::string &value, - Transaction *transaction) { +void HexEncode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { std::stringstream result; - for (std::size_t i=0; i < value.length(); i++) { - unsigned int ii = (unsigned char)(value[i]); + for (std::size_t i=0; i < in.length(); i++) { + int ii = reinterpret_cast(in[i]); result << std::setw(2) << std::setfill('0') << std::hex << ii; } - return result.str(); + out.assign(result.str().c_str()); } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/hex_encode.h b/src/actions/transformations/hex_encode.h index b76e2672fd..545bf046e7 100644 --- a/src/actions/transformations/hex_encode.h +++ b/src/actions/transformations/hex_encode.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class HexEncode : public Transformation { public: + HexEncode() + : Action("t:hexEncode") + { } - explicit HexEncode(const std::string &action); - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index 48257e76ef..64f5ce9a8b 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -13,19 +13,15 @@ * */ -#include "src/actions/transformations/html_entity_decode.h" -#include +#include "src/actions/transformations/html_entity_decode.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + +#include "src/utils/string.h" namespace modsecurity { @@ -33,26 +29,13 @@ namespace actions { namespace transformations { -std::string HtmlEntityDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); - - return ret; +void HtmlEntityDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + auto i = inplace(reinterpret_cast( + &out[0]), out.length()); + out.resize(i); } diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index eaf5ae0b31..5413dd0754 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -13,32 +13,35 @@ * */ + #include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" -#include "src/utils/string.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { class HtmlEntityDecode : public Transformation { public: - explicit HtmlEntityDecode(const std::string &action) - : Transformation(action) { } + HtmlEntityDecode() + : Action("t:htmlEntityDecode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + private: static int inplace(unsigned char *input, uint64_t input_len); }; @@ -47,6 +50,5 @@ class HtmlEntityDecode : public Transformation { } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 89f33b9f0f..b5779713b5 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -13,19 +13,14 @@ * */ -#include "src/actions/transformations/js_decode.h" -#include +#include "src/actions/transformations/js_decode.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" @@ -34,26 +29,14 @@ namespace actions { namespace transformations { -std::string JsDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); +void JsDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { - return ret; + out.assign(in); + auto i = inplace(reinterpret_cast( + &out[0]), out.length()); + out.resize(i); } diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index e680aebca3..b0c15cda51 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -13,35 +13,42 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class JsDecode : public Transformation { public: - explicit JsDecode(const std::string &action) - : Transformation(action) { } + JsDecode() + : Action("t:jsDecode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + + private: static int inplace(unsigned char *input, uint64_t input_len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ diff --git a/src/actions/transformations/length.cc b/src/actions/transformations/length.cc index e27cd41b86..7aaeadcf66 100644 --- a/src/actions/transformations/length.cc +++ b/src/actions/transformations/length.cc @@ -13,32 +13,24 @@ * */ + #include "src/actions/transformations/length.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -Length::Length(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string Length::evaluate(const std::string &value, - Transaction *transaction) { - return std::to_string(value.size()); +void Length::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(std::to_string(in.size()).c_str()); } } // namespace transformations diff --git a/src/actions/transformations/length.h b/src/actions/transformations/length.h index 7974b5c105..38227be756 100644 --- a/src/actions/transformations/length.h +++ b/src/actions/transformations/length.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Length : public Transformation { public: + Length() + : Action("t:length") + { }; - explicit Length(const std::string &action); - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index fcf3ba79df..1fb39c29f2 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -13,35 +13,28 @@ * */ + #include "src/actions/transformations/lower_case.h" #include #include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" + namespace modsecurity { namespace actions { namespace transformations { -LowerCase::LowerCase(const std::string &a) - : Transformation(a) { +void LowerCase::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.resize(in.size()); + std::transform(in.begin(), in.end(), out.begin(), ::tolower); } -std::string LowerCase::evaluate(const std::string &val, - Transaction *transaction) { - std::locale loc; - std::string value(val); - - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::tolower(value[i], loc); - } - - return value; -} } // namespace transformations } // namespace actions diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 12eee32114..b072a0379d 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -13,34 +13,39 @@ * */ + #include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ -#ifdef __cplusplus namespace modsecurity { -class Transaction; namespace actions { namespace transformations { class LowerCase : public Transformation { public: - explicit LowerCase(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + LowerCase() + : Action("t:lowerCase") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ diff --git a/src/actions/transformations/md5.cc b/src/actions/transformations/md5.cc index 8becdb2681..4e833fa5e8 100644 --- a/src/actions/transformations/md5.cc +++ b/src/actions/transformations/md5.cc @@ -13,17 +13,14 @@ * */ + #include "src/actions/transformations/md5.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/md5.h" namespace modsecurity { @@ -31,11 +28,12 @@ namespace actions { namespace transformations { -std::string Md5::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Md5::digest(value); +void Md5::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + std::string ret = Utils::Md5::digest(std::string(in.c_str(), in.size())); - return ret; + out.assign(ret.c_str(), ret.size()); } diff --git a/src/actions/transformations/md5.h b/src/actions/transformations/md5.h index 1742b8b541..7cae8fe15c 100644 --- a/src/actions/transformations/md5.h +++ b/src/actions/transformations/md5.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ #define SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Md5 : public Transformation { public: - explicit Md5(const std::string &action) : Transformation(action) { } + Md5() + : Action("t:md5") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ diff --git a/src/actions/transformations/none.cc b/src/actions/transformations/none.cc index 79ab0b844b..425c371db0 100644 --- a/src/actions/transformations/none.cc +++ b/src/actions/transformations/none.cc @@ -13,17 +13,13 @@ * */ + #include "src/actions/transformations/none.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -31,10 +27,9 @@ namespace actions { namespace transformations { -std::string None::evaluate(const std::string &value, - Transaction *transaction) { - return value; -} +void None::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { } } // namespace transformations diff --git a/src/actions/transformations/none.h b/src/actions/transformations/none.h index 00bf37a76b..30a22d90ff 100644 --- a/src/actions/transformations/none.h +++ b/src/actions/transformations/none.h @@ -13,35 +13,40 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class None : public Transformation { public: - explicit None(const std::string &action) - : Transformation(action) - { m_isNone = true; } - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + None() + : + Action("t:none") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index ad76a22a46..00d0c4fc4d 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -13,47 +13,27 @@ * */ -#include "src/actions/transformations/normalise_path.h" -#include +#include "src/actions/transformations/normalise_path.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -NormalisePath::NormalisePath(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string NormalisePath::evaluate(const std::string &value, - Transaction *transaction) { +void NormalisePath::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int changed = 0; - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = normalize_path_inplace((unsigned char *)tmp, - value.size(), 0, &changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - return ret; + out.assign(in); + auto size = normalize_path_inplace(reinterpret_cast(&out[0]), out.length(), 0, &changed); + out.resize(size); } diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index 3c98d7f95d..3015637e21 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -13,37 +13,42 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class NormalisePath : public Transformation { public: + NormalisePath() + : Action("t:normalisePath") + { } - explicit NormalisePath(const std::string &action); - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; static int normalize_path_inplace(unsigned char *input, int input_len, int win, int *changed); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ diff --git a/src/actions/transformations/normalise_path_win.cc b/src/actions/transformations/normalise_path_win.cc index 8970e8b968..8ac4b59546 100644 --- a/src/actions/transformations/normalise_path_win.cc +++ b/src/actions/transformations/normalise_path_win.cc @@ -13,19 +13,16 @@ * */ + #include "src/actions/transformations/normalise_path_win.h" #include - -#include #include -#include -#include -#include -#include + +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/actions/transformations/normalise_path.h" @@ -34,24 +31,15 @@ namespace actions { namespace transformations { -std::string NormalisePathWin::evaluate(const std::string &value, - Transaction *transaction) { +void NormalisePathWin::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int changed; - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = NormalisePath::normalize_path_inplace( - reinterpret_cast(tmp), - value.size(), 1, &changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - return ret; + out.assign(in); + auto size = NormalisePath::normalize_path_inplace( + reinterpret_cast(&out[0]), out.length(), 1, &changed); + out.resize(size); } diff --git a/src/actions/transformations/normalise_path_win.h b/src/actions/transformations/normalise_path_win.h index 61ce0ca0b1..e919a87e0c 100644 --- a/src/actions/transformations/normalise_path_win.h +++ b/src/actions/transformations/normalise_path_win.h @@ -13,30 +13,36 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ namespace modsecurity { -class Transaction; - namespace actions { namespace transformations { + class NormalisePathWin : public Transformation { public: - explicit NormalisePathWin(const std::string &action) - : Transformation(action) { } + NormalisePathWin() + : Action("t:normalisePathWin") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/parity_even_7bit.cc b/src/actions/transformations/parity_even_7bit.cc index 357fe7594c..38d0676c1b 100644 --- a/src/actions/transformations/parity_even_7bit.cc +++ b/src/actions/transformations/parity_even_7bit.cc @@ -13,18 +13,13 @@ * */ + #include "src/actions/transformations/parity_even_7bit.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -32,28 +27,14 @@ namespace actions { namespace transformations { -std::string ParityEven7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - std::memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; +void ParityEven7bit::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + inplace(reinterpret_cast(&out[0]), out.size()); } + bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { uint64_t i; @@ -76,7 +57,6 @@ bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { } - } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/parity_even_7bit.h b/src/actions/transformations/parity_even_7bit.h index 7ec5f2aabe..d73b6d7a61 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -13,33 +13,42 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class ParityEven7bit : public Transformation { public: - explicit ParityEven7bit(const std::string &action) : Transformation(action) { } + ParityEven7bit() + : Action("t:parityEven7bit") + { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + + private: static bool inplace(unsigned char *input, uint64_t input_len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ diff --git a/src/actions/transformations/parity_odd_7bit.cc b/src/actions/transformations/parity_odd_7bit.cc index fbd6c8fcc2..629f29145b 100644 --- a/src/actions/transformations/parity_odd_7bit.cc +++ b/src/actions/transformations/parity_odd_7bit.cc @@ -13,18 +13,13 @@ * */ + #include "src/actions/transformations/parity_odd_7bit.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -32,28 +27,14 @@ namespace actions { namespace transformations { -std::string ParityOdd7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; +void ParityOdd7bit::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + inplace(reinterpret_cast(&out[0]), out.length()); } + bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) { uint64_t i; diff --git a/src/actions/transformations/parity_odd_7bit.h b/src/actions/transformations/parity_odd_7bit.h index 9af53722aa..3442e1add5 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -13,33 +13,43 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class ParityOdd7bit : public Transformation { public: - explicit ParityOdd7bit(const std::string &action) : Transformation(action) { } + ParityOdd7bit() + : Action("t:parityOdd7bit") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; - std::string evaluate(const std::string &exp, Transaction *transaction) override; + private: static bool inplace(unsigned char *input, uint64_t input_len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif + #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ diff --git a/src/actions/transformations/parity_zero_7bit.cc b/src/actions/transformations/parity_zero_7bit.cc index 93a0f974e2..4e785a7b21 100644 --- a/src/actions/transformations/parity_zero_7bit.cc +++ b/src/actions/transformations/parity_zero_7bit.cc @@ -13,18 +13,13 @@ * */ + #include "src/actions/transformations/parity_zero_7bit.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -32,26 +27,11 @@ namespace actions { namespace transformations { -std::string ParityZero7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; +void ParityZero7bit::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + inplace(reinterpret_cast(&out[0]), out.length()); } diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index 5e30dd5d0d..e0bd4b7606 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -13,33 +13,42 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class ParityZero7bit : public Transformation { public: - explicit ParityZero7bit(const std::string &action) : Transformation(action) { } + ParityZero7bit() + : Action("t:parityZero7bit") + { } - std::string evaluate(const std::string &exp, Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + + private: static bool inplace(unsigned char *input, uint64_t input_len); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ diff --git a/src/actions/transformations/remove_comments.cc b/src/actions/transformations/remove_comments.cc index 4bce61b55e..4fcdcac5e8 100644 --- a/src/actions/transformations/remove_comments.cc +++ b/src/actions/transformations/remove_comments.cc @@ -13,18 +13,13 @@ * */ + #include "src/actions/transformations/remove_comments.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -32,21 +27,21 @@ namespace actions { namespace transformations { -std::string RemoveComments::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; +void RemoveComments::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { unsigned char *input; input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); + (malloc(sizeof(char) * in.length()+1)); if (input == NULL) { - return ""; + return; } - memcpy(input, value.c_str(), value.length()+1); + memcpy(input, in.c_str(), in.length()+1); - uint64_t input_len = value.size(); + uint64_t input_len = in.size(); uint64_t i, j, incomment; i = j = incomment = 0; @@ -100,10 +95,8 @@ std::string RemoveComments::evaluate(const std::string &value, input[j++] = ' '; } - ret.assign(reinterpret_cast(input), j); + out.assign(reinterpret_cast(input), j); free(input); - - return ret; } diff --git a/src/actions/transformations/remove_comments.h b/src/actions/transformations/remove_comments.h index 46ad2a7e92..fca978e4b8 100644 --- a/src/actions/transformations/remove_comments.h +++ b/src/actions/transformations/remove_comments.h @@ -13,28 +13,32 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { class RemoveComments : public Transformation { public: - explicit RemoveComments(const std::string &action) : Transformation(action) { } + RemoveComments() + : Action("t:removeComments") { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override;; }; @@ -42,6 +46,5 @@ class RemoveComments : public Transformation { } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index 68bd28c314..132a2f178d 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -13,65 +13,58 @@ * */ + #include "src/actions/transformations/remove_comments_char.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -RemoveCommentsChar::RemoveCommentsChar(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string RemoveCommentsChar::evaluate(const std::string &val, - Transaction *transaction) { +void RemoveCommentsChar::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int64_t i; - std::string value(val); + out = in; i = 0; - while (i < value.size()) { - if (value.at(i) == '/' - && (i+1 < value.size()) && value.at(i+1) == '*') { - value.erase(i, 2); - } else if (value.at(i) == '*' - && (i+1 < value.size()) && value.at(i+1) == '/') { - value.erase(i, 2); - } else if (value.at(i) == '<' - && (i+1 < value.size()) - && value.at(i+1) == '!' - && (i+2 < value.size()) - && value.at(i+2) == '-' - && (i+3 < value.size()) - && value.at(i+3) == '-') { - value.erase(i, 4); - } else if (value.at(i) == '-' - && (i+1 < value.size()) && value.at(i+1) == '-' - && (i+2 < value.size()) && value.at(i+2) == '>') { - value.erase(i, 3); - } else if (value.at(i) == '-' - && (i+1 < value.size()) && value.at(i+1) == '-') { - value.erase(i, 2); - } else if (value.at(i) == '#') { - value.erase(i, 1); + while (i < out.size()) { + if (out.at(i) == '/' + && (i+1 < out.size()) && out.at(i+1) == '*') { + out.erase(i, 2); + } else if (out.at(i) == '*' + && (i+1 < out.size()) && out.at(i+1) == '/') { + out.erase(i, 2); + } else if (out.at(i) == '<' + && (i+1 < out.size()) + && out.at(i+1) == '!' + && (i+2 < out.size()) + && out.at(i+2) == '-' + && (i+3 < out.size()) + && out.at(i+3) == '-') { + out.erase(i, 4); + } else if (out.at(i) == '-' + && (i+1 < out.size()) && out.at(i+1) == '-' + && (i+2 < out.size()) && out.at(i+2) == '>') { + out.erase(i, 3); + } else if (out.at(i) == '-' + && (i+1 < out.size()) && out.at(i+1) == '-') { + out.erase(i, 2); + } else if (out.at(i) == '#') { + out.erase(i, 1); } else { i++; } } - return value; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/remove_comments_char.h b/src/actions/transformations/remove_comments_char.h index 03091ceb2e..97d1099c34 100644 --- a/src/actions/transformations/remove_comments_char.h +++ b/src/actions/transformations/remove_comments_char.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class RemoveCommentsChar : public Transformation { public: - explicit RemoveCommentsChar(const std::string &action); + RemoveCommentsChar() + : Action("t:removeCommentsChar") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ diff --git a/src/actions/transformations/remove_nulls.cc b/src/actions/transformations/remove_nulls.cc index 991956d001..1f6c4f73dc 100644 --- a/src/actions/transformations/remove_nulls.cc +++ b/src/actions/transformations/remove_nulls.cc @@ -13,19 +13,13 @@ * */ -#include "src/actions/transformations/remove_nulls.h" -#include +#include "src/actions/transformations/remove_nulls.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -33,21 +27,20 @@ namespace actions { namespace transformations { -std::string RemoveNulls::evaluate(const std::string &val, - Transaction *transaction) { +void RemoveNulls::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int64_t i; - std::string value(val); + out = in; i = 0; - while (i < value.size()) { - if (value.at(i) == '\0') { - value.erase(i, 1); + while (i < out.size()) { + if (out.at(i) == '\0') { + out.erase(i, 1); } else { i++; } } - - return value; } diff --git a/src/actions/transformations/remove_nulls.h b/src/actions/transformations/remove_nulls.h index 6d5a082037..664fdb1476 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class RemoveNulls : public Transformation { public: - explicit RemoveNulls(const std::string &action) - : Transformation(action) { } + RemoveNulls() + : Action("t:removeNulls") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index a3687cc3a1..3e665057e7 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -13,40 +13,33 @@ * */ + #include "src/actions/transformations/remove_whitespace.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#define NBSP 160 // non breaking space char +#include "src/utils/string.h" + namespace modsecurity { namespace actions { namespace transformations { -RemoveWhitespace::RemoveWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string RemoveWhitespace::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); +void RemoveWhitespace::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out = in; int64_t i = 0; // loop through all the chars - while (i < value.size()) { + while (i < out.size()) { // remove whitespaces and non breaking spaces (NBSP) - if (isspace(value[i]) || (value[i] == NBSP)) { - value.erase(i, 1); + if (isspace(out[i]) || (out[i] == NBSP)) { + out.erase(i, 1); } else { /* if the space is not a whitespace char, increment counter counter should not be incremented if a character is erased because @@ -54,10 +47,9 @@ std::string RemoveWhitespace::evaluate(const std::string &val, i++; } } - - return value; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/remove_whitespace.h b/src/actions/transformations/remove_whitespace.h index c2968ddc68..e4a388f640 100644 --- a/src/actions/transformations/remove_whitespace.h +++ b/src/actions/transformations/remove_whitespace.h @@ -13,33 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class RemoveWhitespace : public Transformation { public: - explicit RemoveWhitespace(const std::string &action); + RemoveWhitespace() + : Action("t:removeWhitespace") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index 6f0250cb0c..220a551fe8 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -13,42 +13,34 @@ * */ + #include "src/actions/transformations/replace_comments.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -ReplaceComments::ReplaceComments(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceComments::evaluate(const std::string &value, - Transaction *transaction) { +void ReplaceComments::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { uint64_t i, j, incomment; char *input = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(input, value.c_str(), value.size() + 1); - input[value.size()] = '\0'; + malloc(sizeof(char) * in.size() + 1)); + memcpy(input, in.c_str(), in.size() + 1); + input[in.size()] = '\0'; i = j = incomment = 0; - while (i < value.size()) { + while (i < in.size()) { if (incomment == 0) { - if ((input[i] == '/') && (i + 1 < value.size()) + if ((input[i] == '/') && (i + 1 < in.size()) && (input[i + 1] == '*')) { incomment = 1; i += 2; @@ -58,7 +50,7 @@ std::string ReplaceComments::evaluate(const std::string &value, j++; } } else { - if ((input[i] == '*') && (i + 1 < value.size()) + if ((input[i] == '*') && (i + 1 < in.size()) && (input[i + 1] == '/')) { incomment = 0; i += 2; @@ -74,13 +66,9 @@ std::string ReplaceComments::evaluate(const std::string &value, input[j++] = ' '; } - - std::string resp; - resp.append(reinterpret_cast(input), j); + out.append(reinterpret_cast(input), j); free(input); - - return resp; } } // namespace transformations diff --git a/src/actions/transformations/replace_comments.h b/src/actions/transformations/replace_comments.h index a2c06a4c49..024f6a20d1 100644 --- a/src/actions/transformations/replace_comments.h +++ b/src/actions/transformations/replace_comments.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class ReplaceComments : public Transformation { public: + ReplaceComments() + : Action("t:removeComments") + { } - explicit ReplaceComments(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index 7f20d0dadf..97b0ae24dc 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -13,46 +13,38 @@ * */ + #include "src/actions/transformations/replace_nulls.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" namespace modsecurity { namespace actions { namespace transformations { -ReplaceNulls::ReplaceNulls(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceNulls::evaluate(const std::string &val, - Transaction *transaction) { +void ReplaceNulls::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int64_t i; - std::string value(val); + out = in; i = 0; - while (i < value.size()) { - if (value.at(i) == '\0') { - value.erase(i, 1); - value.insert(i, " ", 1); + while (i < out.size()) { + if (out.at(i) == '\0') { + out.erase(i, 1); + out.insert(i, " ", 1); } else { i++; } } - - return value; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/replace_nulls.h b/src/actions/transformations/replace_nulls.h index 7af92643f1..d16250049c 100644 --- a/src/actions/transformations/replace_nulls.h +++ b/src/actions/transformations/replace_nulls.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class ReplaceNulls : public Transformation { public: + ReplaceNulls() + : Action("t:replaceNulls") + { } - explicit ReplaceNulls(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index 0c30512acc..2460103291 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -13,17 +13,14 @@ * */ + #include "src/actions/transformations/sha1.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/sha1.h" @@ -31,17 +28,17 @@ namespace modsecurity { namespace actions { namespace transformations { -Sha1::Sha1(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string Sha1::evaluate(const std::string &value, - Transaction *transaction) { +void Sha1::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + auto a = Utils::Sha1::digest( + std::string(in.c_str(), in.size())); - return Utils::Sha1::digest(value); + out.assign(a.c_str(), a.size()); } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/sha1.h b/src/actions/transformations/sha1.h index 87e5aaa1e3..1437e6c910 100644 --- a/src/actions/transformations/sha1.h +++ b/src/actions/transformations/sha1.h @@ -13,32 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Sha1 : public Transformation { public: - explicit Sha1(const std::string &action) ; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + Sha1() + : Action("t:sha1") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index b33deac735..b7cefc196a 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -13,18 +13,14 @@ * */ + #include "src/actions/transformations/sql_hex_decode.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" @@ -32,36 +28,13 @@ namespace modsecurity { namespace actions { namespace transformations { -#ifndef VALID_HEX -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ - || ((X >= 'a') && (X <= 'f')) \ - || ((X >= 'A') && (X <= 'F'))) -#endif -#ifndef ISODIGIT -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) -#endif - -std::string SqlHexDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - int size = 0; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - return ret; +void SqlHexDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + auto size = inplace(reinterpret_cast(&out[0]), out.size()); + out.resize(size); } diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index 4ef5a63e48..fc6e979a1b 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -13,28 +13,34 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ -#ifdef __cplusplus namespace modsecurity { -class Transaction; - namespace actions { namespace transformations { + class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(const std::string &action) : Transformation(action) { } + SqlHexDecode() + : Action("t:sqlHexDecode") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + private: static int inplace(unsigned char *data, int len); static int mytolower(int ch) { @@ -45,10 +51,10 @@ class SqlHexDecode : public Transformation { } }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index fae80ee62d..cb4c78adb1 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -13,15 +13,14 @@ * */ -#include "src/actions/transformations/transformation.h" -#include +#include "src/actions/transformations/transformation.h" -#include #include #include "modsecurity/transaction.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/base64_decode_ext.h" #include "src/actions/transformations/base64_decode.h" #include "src/actions/transformations/base64_encode.h" @@ -60,65 +59,103 @@ #include "src/actions/transformations/utf8_to_unicode.h" -#define IF_MATCH(b) \ - if (a.compare(2, std::strlen(#b), #b) == 0) - - namespace modsecurity { namespace actions { namespace transformations { -std::string Transformation::evaluate(const std::string &value, - Transaction *transaction) { - return value; -} +class TransformationDoesNotExist : public std::exception { + public: + explicit TransformationDoesNotExist(const char *name) + : m_transformation(name) + { } + + explicit TransformationDoesNotExist(const std::string& name) + : m_transformation(name) + { } + + virtual ~TransformationDoesNotExist() throw (){} -Transformation* Transformation::instantiate(std::string a) { - IF_MATCH(base64DecodeExt) { return new Base64DecodeExt(a); } - IF_MATCH(base64Decode) { return new Base64Decode(a); } - IF_MATCH(base64Encode) { return new Base64Encode(a); } - IF_MATCH(cmd_line) { return new CmdLine(a); } - IF_MATCH(compress_whitespace) { return new CompressWhitespace(a); } - IF_MATCH(cssDecode) { return new CssDecode(a); } - IF_MATCH(escapeSeqDecode) { return new EscapeSeqDecode(a); } - IF_MATCH(hexDecode) { return new HexDecode(a); } - IF_MATCH(hexEncode) { return new HexEncode(a); } - IF_MATCH(htmlEntityDecode) { return new HtmlEntityDecode(a); } - IF_MATCH(jsDecode) { return new JsDecode(a); } - IF_MATCH(length) { return new Length(a); } - IF_MATCH(lowercase) { return new LowerCase(a); } - IF_MATCH(md5) { return new Md5(a); } - IF_MATCH(none) { return new None(a); } - IF_MATCH(normalizePathWin) { return new NormalisePathWin(a); } - IF_MATCH(normalisePathWin) { return new NormalisePathWin(a); } - IF_MATCH(normalizePath) { return new NormalisePath(a); } - IF_MATCH(normalisePath) { return new NormalisePath(a); } - IF_MATCH(parityEven7bit) { return new ParityEven7bit(a); } - IF_MATCH(parityOdd7bit) { return new ParityOdd7bit(a); } - IF_MATCH(parityZero7bit) { return new ParityZero7bit(a); } - IF_MATCH(removeCommentsChar) { return new RemoveCommentsChar(a); } - IF_MATCH(removeComments) { return new RemoveComments(a); } - IF_MATCH(removeNulls) { return new RemoveNulls(a); } - IF_MATCH(removeWhitespace) { return new RemoveWhitespace(a); } - IF_MATCH(compressWhitespace) { return new CompressWhitespace(a); } - IF_MATCH(replaceComments) { return new ReplaceComments(a); } - IF_MATCH(replaceNulls) { return new ReplaceNulls(a); } - IF_MATCH(sha1) { return new Sha1(a); } - IF_MATCH(sqlHexDecode) { return new SqlHexDecode(a); } - IF_MATCH(transformation) { return new Transformation(a); } - IF_MATCH(trimLeft) { return new TrimLeft(a); } - IF_MATCH(trimRight) { return new TrimRight(a); } - IF_MATCH(trim) { return new Trim(a); } - IF_MATCH(uppercase) { return new UpperCase(a); } - IF_MATCH(urlDecodeUni) { return new UrlDecodeUni(a); } - IF_MATCH(urlDecode) { return new UrlDecode(a); } - IF_MATCH(urlEncode) { return new UrlEncode(a); } - IF_MATCH(utf8toUnicode) { return new Utf8ToUnicode(a); } - - return new Transformation(a); + virtual const char* what() const throw() { + return strdup(std::string("Transformation not found: " + m_transformation + \ + ". Make sure that the new transformation is registered at: " + \ + "transformation.cc").c_str()); + } + + private: + std::string m_transformation; +}; + + +Transformation* Transformation::instantiate( + const std::string &transformationName) { + /** + * + * FIXME: Once part of ModSecurity, the transformation needs to register + * here. That is necessary to load transformations from external + * resources such as Python and Lua, not to mention the + * unit/regression framework. + * + * Today this registration is manual; as seen below, the idea is to + * have those automatically generated. To avoid transformations not + * to be listed. + */ + + std::string name(transformationName); + name.erase(std::remove(name.begin(), name.end(), '_'), name.end()); + + if (match(name, "t:base64DecodeExt")) { return new Base64DecodeExt(); } + if (match(name, "t:base64Decode")) { return new Base64Decode(); } + if (match(name, "t:base64Encode")) { return new Base64Encode(); } + if (match(name, "t:cmdLine")) { return new CmdLine(); } + if (match(name, "t:compressWhitespace")) { + return new CompressWhitespace(); + } + if (match(name, "t:cssDecode")) { return new CssDecode(); } + if (match(name, "t:escapeSeqDecode")) { return new EscapeSeqDecode(); } + if (match(name, "t:hexDecode")) { return new HexDecode(); } + if (match(name, "t:hexEncode")) { return new HexEncode(); } + if (match(name, "t:htmlEntityDecode")) { return new HtmlEntityDecode(); } + if (match(name, "t:jsDecode")) { return new JsDecode(); } + if (match(name, "t:length")) { return new Length(); } + if (match(name, "t:lowercase")) { return new LowerCase(); } + if (match(name, "t:md5")) { return new Md5(); } + if (match(name, "t:none")) { return new None(); } + if (match(name, "t:normalizePathWin")) { return new NormalisePathWin(); } + if (match(name, "t:normalisePathWin")) { return new NormalisePathWin(); } + if (match(name, "t:normalizePath")) { return new NormalisePath(); } + if (match(name, "t:normalisePath")) { return new NormalisePath(); } + if (match(name, "t:parityEven7bit")) { return new ParityEven7bit(); } + if (match(name, "t:parityOdd7bit")) { return new ParityOdd7bit(); } + if (match(name, "t:parityZero7bit")) { return new ParityZero7bit(); } + if (match(name, "t:removeCommentsChar")) { + return new RemoveCommentsChar(); + } + if (match(name, "t:removeComments")) { return new RemoveComments(); } + if (match(name, "t:removeNulls")) { return new RemoveNulls(); } + if (match(name, "t:removeWhitespace")) { return new RemoveWhitespace(); } + if (match(name, "t:compressWhitespace")) { + return new CompressWhitespace(); + } + if (match(name, "t:replaceComments")) { return new ReplaceComments(); } + if (match(name, "t:replaceNulls")) { return new ReplaceNulls(); } + if (match(name, "t:sha1")) { return new Sha1(); } + if (match(name, "t:sqlHexDecode")) { return new SqlHexDecode(); } + if (match(name, "t:trimLeft")) { return new TrimLeft(); } + if (match(name, "t:trimRight")) { return new TrimRight(); } + if (match(name, "t:trim")) { return new Trim(); } + if (match(name, "t:uppercase")) { return new UpperCase(); } + if (match(name, "t:urlDecodeUni")) { return new UrlDecodeUni(); } + if (match(name, "t:urlDecode")) { return new UrlDecode(); } + if (match(name, "t:urlEncode")) { return new UrlEncode(); } + if (match(name, "t:utf8toUnicode")) { return new Utf8ToUnicode(); } + + throw TransformationDoesNotExist(name); + + return nullptr; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/transformation.h b/src/actions/transformations/transformation.h index 57f20416a9..e614d3b487 100644 --- a/src/actions/transformations/transformation.h +++ b/src/actions/transformations/transformation.h @@ -13,34 +13,47 @@ * */ + +#include #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" +#include "src/actions/action_allowed_in_sec_default_action.h" + + #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ namespace modsecurity { -class Transaction; - namespace actions { namespace transformations { -class Transformation : public Action { - public: - explicit Transformation(const std::string& _action) - : Action(_action, RunTimeBeforeMatchAttemptKind) { } - explicit Transformation(const std::string& _action, int kind) - : Action(_action, kind) { } - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static Transformation* instantiate(std::string a); +class Transformation : public ActionAllowedAsSecDefaultAction { + public: + virtual void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept = 0; + + virtual ~Transformation() + { } + + static Transformation* instantiate(const std::string &name); + + private: + static bool match(const std::string &a, const std::string &b) noexcept { + return ((a.size() == b.size()) + && std::equal(a.begin(), a.end(), b.begin(), + [](const char & c1, const char & c2) { + return (c1 == c2 || std::toupper(c1) == std::toupper(c2)); + })); + } }; + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index 4954237aa0..983c74a8fd 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -13,55 +13,45 @@ * */ + #include "src/actions/transformations/trim.h" -#include -#include -#include #include -#include -#include +#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" + namespace modsecurity { namespace actions { namespace transformations { -std::string *Trim::ltrim(std::string *s) { +void Trim::ltrim(ModSecString *s) { s->erase(s->begin(), std::find_if(s->begin(), s->end(), std::not1(std::ptr_fun(std::isspace)))); - return s; } -std::string *Trim::rtrim(std::string *s) { +void Trim::rtrim(ModSecString *s) { s->erase(std::find_if(s->rbegin(), s->rend(), std::not1(std::ptr_fun(std::isspace))).base(), s->end()); - return s; } -std::string *Trim::trim(std::string *s) { - return ltrim(rtrim(s)); +void Trim::trim(ModSecString *s) { + rtrim(s); + ltrim(s); } -Trim::Trim(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - -std::string -Trim::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->trim(&value); -} +void Trim::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out = in; + trim(&out); +}; } // namespace transformations diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index 4deebb4fcb..ff90918237 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -13,38 +13,48 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class Trim : public Transformation { public: - - explicit Trim(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string *ltrim(std::string *s); - std::string *rtrim(std::string *s); - std::string *trim(std::string *s); + Trim() + : Action("t:trim") + { } + + explicit Trim(const std::string &trim) + : Action(trim) + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + + protected: + void ltrim(ModSecString *s); + void rtrim(ModSecString *s); + void trim(ModSecString *s); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index 9116e3c857..9ad9487e7d 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -13,36 +13,28 @@ * */ + #include "src/actions/transformations/trim_left.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/actions/transformations/trim.h" -#include "modsecurity/actions/action.h" namespace modsecurity { namespace actions { namespace transformations { +void TrimLeft::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out = in; + ltrim(&out); +}; -TrimLeft::TrimLeft(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} - -std::string TrimLeft::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *ltrim(&value); -} } // namespace transformations } // namespace actions diff --git a/src/actions/transformations/trim_left.h b/src/actions/transformations/trim_left.h index e7799208dd..ba731f603b 100644 --- a/src/actions/transformations/trim_left.h +++ b/src/actions/transformations/trim_left.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" + #include "src/actions/transformations/trim.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class TrimLeft : public Trim { public: - explicit TrimLeft(const std::string &action) ; + TrimLeft() + : Action("t:trimLeft") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index bb7cac0828..21bd85dc9b 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -13,34 +13,27 @@ * */ + #include "src/actions/transformations/trim_right.h" -#include #include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" + namespace modsecurity { namespace actions { namespace transformations { -TrimRight::TrimRight(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} +void TrimRight::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out = in; + rtrim(&out); +}; -std::string TrimRight::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->rtrim(&value); -} } // namespace transformations } // namespace actions diff --git a/src/actions/transformations/trim_right.h b/src/actions/transformations/trim_right.h index 8c10092875..3799e6bcd6 100644 --- a/src/actions/transformations/trim_right.h +++ b/src/actions/transformations/trim_right.h @@ -13,34 +13,39 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" + #include "src/actions/transformations/trim.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class TrimRight : public Trim { public: - explicit TrimRight(const std::string &action) ; + TrimRight() + : Action("t:trimRight") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index 0ae77c0e90..431d4b590b 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -13,36 +13,31 @@ * */ + #include "src/actions/transformations/upper_case.h" -#include #include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" + namespace modsecurity { namespace actions { namespace transformations { -UpperCase::UpperCase(const std::string &a) - : Transformation(a) { -} - -std::string UpperCase::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); +void UpperCase::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { std::locale loc; - - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::toupper(value[i], loc); + out.reserve(in.size()); + for (std::string::size_type i=0; i < in.size(); ++i) { + out += std::toupper(in[i], loc); } - - return value; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/upper_case.h b/src/actions/transformations/upper_case.h index 542df2832b..9082cb77a0 100644 --- a/src/actions/transformations/upper_case.h +++ b/src/actions/transformations/upper_case.h @@ -13,35 +13,39 @@ * */ + #include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ -#ifdef __cplusplus namespace modsecurity { -class Transaction; namespace actions { namespace transformations { class UpperCase : public Transformation { public: - explicit UpperCase(const std::string &action) ; + UpperCase() + : Action("t:upperCase") + { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index c533b7e883..fcdbbf358d 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -13,49 +13,33 @@ * */ + #include "src/actions/transformations/url_decode.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/decode.h" + namespace modsecurity { namespace actions { namespace transformations { -UrlDecode::UrlDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string UrlDecode::evaluate(const std::string &value, - Transaction *transaction) { - unsigned char *val = NULL; +void UrlDecode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int invalid_count = 0; int changed; - val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); - memcpy(val, value.c_str(), value.size() + 1); - val[value.size()] = '\0'; - - int size = utils::urldecode_nonstrict_inplace(val, value.size(), + out.assign(in); + int size = utils::urldecode_nonstrict_inplace( + reinterpret_cast(&out[0]), out.size(), &invalid_count, &changed); - std::string out; - - out.append((const char *)val, size); - - free(val); - - return out; + out.resize(size); } diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index 9e39045b77..938bb005e9 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -13,36 +13,39 @@ * */ + #include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { class UrlDecode : public Transformation { public: + UrlDecode() + : Action("t:urlDecode") + { } - explicit UrlDecode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index 9533125012..77f16ff8fb 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -13,24 +13,16 @@ * */ -#include "src/actions/transformations/url_decode_uni.h" -#include +#include "src/actions/transformations/url_decode_uni.h" -#include #include -#include -#include -#include -#include -#include -#include "modsecurity/rules_set_properties.h" -#include "modsecurity/rules_set.h" +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "modsecurity/rules_set.h" + #include "src/utils/string.h" -#include "src/utils/system.h" namespace modsecurity { @@ -38,26 +30,12 @@ namespace actions { namespace transformations { -std::string UrlDecodeUni::evaluate(const std::string &value, - Transaction *t) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length(), t); - - ret.assign(reinterpret_cast(input), i); - free(input); - - return ret; +void UrlDecodeUni::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { + out.assign(in); + size_t i = inplace(reinterpret_cast(&out[0]), out.length(), t); + out.resize(i); } @@ -66,7 +44,7 @@ std::string UrlDecodeUni::evaluate(const std::string &value, * IMP1 Assumes NUL-terminated */ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, - Transaction *t) { + const Transaction *t) { unsigned char *d = input; int64_t i, count, fact, j, xv; int Code, hmap = -1; diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index b04aef893a..5f053fef8d 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -13,35 +13,43 @@ * */ + #include -#include "modsecurity/rules_set_properties.h" +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ -#ifdef __cplusplus namespace modsecurity { -class Transaction; namespace actions { namespace transformations { + class UrlDecodeUni : public Transformation { public: - explicit UrlDecodeUni(const std::string &action) : Transformation(action) { } + UrlDecodeUni() + : Action("t:urlDecodeUni") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; - std::string evaluate(const std::string &exp, Transaction *transaction) override; + private: static int inplace(unsigned char *input, uint64_t input_len, - Transaction *transaction); + const Transaction *transaction); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 23a8f16753..139e2aa354 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -13,30 +13,23 @@ * */ + #include "src/actions/transformations/url_encode.h" -#include #include -#include -#include -#include -#include + +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" + namespace modsecurity { namespace actions { namespace transformations { -UrlEncode::UrlEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - std::string UrlEncode::url_enc(const char *input, unsigned int input_len, int *changed) { char *rval, *d; @@ -87,13 +80,13 @@ std::string UrlEncode::url_enc(const char *input, } -std::string UrlEncode::evaluate(const std::string &value, - Transaction *transaction) { +void UrlEncode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int changed; - std::string ret = url_enc(value.c_str(), value.size(), &changed); - - return ret; + std::string ret = url_enc(in.c_str(), in.size(), &changed); + out.assign(ret.c_str(), ret.size()); } diff --git a/src/actions/transformations/url_encode.h b/src/actions/transformations/url_encode.h index 438301f73c..d6e342b1a8 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -13,37 +13,43 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +namespace modsecurity { namespace actions { namespace transformations { + class UrlEncode : public Transformation { public: + UrlEncode() + : Action("t:urlEncode") + { } - explicit UrlEncode(const std::string &action) ; + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string url_enc(const char *input, + private: + static std::string url_enc(const char *input, unsigned int input_len, int *changed); }; + } // namespace transformations } // namespace actions } // namespace modsecurity -#endif #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index 38d9a2b784..824ce7dd77 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -13,18 +13,14 @@ * */ + #include "src/actions/transformations/utf8_to_unicode.h" -#include #include -#include -#include -#include -#include -#include +#include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" + #include "src/utils/string.h" @@ -33,35 +29,22 @@ namespace actions { namespace transformations { -std::string Utf8ToUnicode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; +void Utf8ToUnicode::execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept { int changed = 0; - char *out; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } + char *out2; - memcpy(input, value.c_str(), value.length()+1); - - out = inplace(input, value.size() + 1, &changed); - free(input); - if (out != NULL) { - ret.assign(reinterpret_cast(out), - strlen(reinterpret_cast(out))); - free(out); + out2 = inplace(reinterpret_cast(&in[0]), in.size() + 1, &changed); + if (out2 != NULL) { + out.assign(reinterpret_cast(out2), + strlen(reinterpret_cast(out2))); + free(out2); } - - return ret; } -char *Utf8ToUnicode::inplace(unsigned char *input, +char *Utf8ToUnicode::inplace(const unsigned char *input, uint64_t input_len, int *changed) { unsigned int count = 0; char *data; @@ -71,8 +54,8 @@ char *Utf8ToUnicode::inplace(unsigned char *input, unsigned char unicode[8]; *changed = 0; - /* RFC3629 states that UTF-8 are encoded using sequences of 1 to 4 octets. */ - /* Max size per character should fit in 4 bytes */ + /* RFC3629 states that UTF-8 are encoded using sequences of 1 to 4 */ + /* octets. Max size per character should fit in 4 bytes */ len = input_len * 4 + 1; data = reinterpret_cast(malloc(sizeof(char) * len)); if (data == NULL) { @@ -89,7 +72,7 @@ char *Utf8ToUnicode::inplace(unsigned char *input, int unicode_len = 0; unsigned int d = 0; unsigned char c; - unsigned char *utf = (unsigned char *)&input[i]; + const unsigned char *utf = &input[i]; c = *utf; diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index c76bb0a285..5b0c37d4c7 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -13,37 +13,48 @@ * */ + #include +#include "modsecurity/modsecurity.h" #include "modsecurity/actions/action.h" + #include "src/actions/transformations/transformation.h" + #ifndef SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ -#define UNICODE_ERROR_CHARACTERS_MISSING -1 -#define UNICODE_ERROR_INVALID_ENCODING -2 -#define UNICODE_ERROR_OVERLONG_CHARACTER -3 -#define UNICODE_ERROR_RESTRICTED_CHARACTER -4 -#define UNICODE_ERROR_DECODING_ERROR -5 namespace modsecurity { -class Transaction; - namespace actions { namespace transformations { + class Utf8ToUnicode : public Transformation { public: - explicit Utf8ToUnicode(const std::string &action) : Transformation(action) { } - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static char *inplace(unsigned char *input, uint64_t input_len, + Utf8ToUnicode() + : Action("t:utf8toUnicode") + { } + + void execute(const Transaction *t, + const ModSecString &in, + ModSecString &out) noexcept override; + + private: + enum UnicodeError { + UNICODE_ERROR_CHARACTERS_MISSING = -1, + UNICODE_ERROR_INVALID_ENCODING = -2, + UNICODE_ERROR_OVERLONG_CHARACTER = -3, + UNICODE_ERROR_RESTRICTED_CHARACTER = -4, + UNICODE_ERROR_DECODING_ERROR = -5 + }; + + static char *inplace(const unsigned char *input, uint64_t input_len, int *changed); }; + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/ver.cc b/src/actions/ver.cc index 5b4fd13bcf..5fa44344b5 100644 --- a/src/actions/ver.cc +++ b/src/actions/ver.cc @@ -13,25 +13,13 @@ * */ -#include "src/actions/ver.h" - -#include -#include -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "src/actions/ver.h" namespace modsecurity { namespace actions { -bool Ver::evaluate(RuleWithActions *rule, Transaction *transaction) { - rule->m_ver = m_parser_payload; - return true; -} - - } // namespace actions } // namespace modsecurity diff --git a/src/actions/ver.h b/src/actions/ver.h index 0108188ae3..d442080005 100644 --- a/src/actions/ver.h +++ b/src/actions/ver.h @@ -13,28 +13,33 @@ * */ + #include -#include "modsecurity/actions/action.h" +#include "src/actions/action_type_rule_metadata.h" + #ifndef SRC_ACTIONS_VER_H_ #define SRC_ACTIONS_VER_H_ -class Transaction; namespace modsecurity { -class Transaction; namespace actions { -class Ver : public Action { +class Ver : public ActionTypeRuleMetaData { public: - explicit Ver(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Ver(const std::string &action) + : Action(action), + m_version("") + { }; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override; + void configure(RuleWithActions *rule) override { + rule->setVersion(m_version); + } private: - std::string m_ver; + std::string m_version; }; diff --git a/src/actions/xmlns.cc b/src/actions/xmlns.cc index 7b90361bd7..512bc62157 100644 --- a/src/actions/xmlns.cc +++ b/src/actions/xmlns.cc @@ -13,13 +13,13 @@ * */ + #include "src/actions/xmlns.h" -#include #include #include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" + namespace modsecurity { namespace actions { @@ -29,13 +29,13 @@ bool XmlNS::init(std::string *error) { size_t pos; std::string http = "http://"; - pos = m_parser_payload.find("="); + pos = m_parserPayload.find("="); if (pos == std::string::npos) { error->assign("XMLS: Bad format, missing equals sign."); return false; } - m_scope = std::string(m_parser_payload, 0, pos); - m_href = std::string(m_parser_payload, pos+1, m_parser_payload.size()); + m_scope = std::string(m_parserPayload, 0, pos); + m_href = std::string(m_parserPayload, pos+1, m_parserPayload.size()); if (m_href.empty() || m_scope.empty()) { error->assign("XMLS: XMLNS is invalid. Expecting a " \ diff --git a/src/actions/xmlns.h b/src/actions/xmlns.h index 9dda7900bf..d03b48b97c 100644 --- a/src/actions/xmlns.h +++ b/src/actions/xmlns.h @@ -13,6 +13,7 @@ * */ + #include #include "modsecurity/actions/action.h" @@ -20,23 +21,36 @@ #ifndef SRC_ACTIONS_XMLNS_H_ #define SRC_ACTIONS_XMLNS_H_ -class Transaction; namespace modsecurity { -class Transaction; 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 init(std::string *error) override; - bool evaluate(RuleWithActions *rule, Transaction *transaction) override { - return true; + std::string getScope() const { + return m_scope; } - bool init(std::string *error) override; + std::string getHref() const { + return m_href; + } + private: std::string m_scope; std::string m_href; }; @@ -45,4 +59,5 @@ class XmlNS : public Action { } // namespace actions } // namespace modsecurity + #endif // SRC_ACTIONS_XMLNS_H_ diff --git a/src/anchored_set_variable.cc b/src/anchored_set_variable.cc index 1282af6213..43a9562184 100644 --- a/src/anchored_set_variable.cc +++ b/src/anchored_set_variable.cc @@ -36,44 +36,34 @@ AnchoredSetVariable::AnchoredSetVariable(Transaction *t, } -AnchoredSetVariable::~AnchoredSetVariable() { - unset(); -} - - void AnchoredSetVariable::unset() { - for (const auto& x : *this) { - VariableValue *var = x.second; - delete var; - } clear(); } +// FIXME: It may not be necessary to copy the content of void AnchoredSetVariable::set(const std::string &key, const std::string &value, size_t offset, size_t len) { - std::unique_ptr origin(new VariableOrigin()); - std::string *v = new std::string(value); - VariableValue *var = new VariableValue(&m_name, &key, v); - delete v; + auto var = std::make_shared(&m_name, + std::unique_ptr(new std::string(key)), + std::unique_ptr(new std::string(value))); - origin->m_offset = offset; - origin->m_length = len; + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = len; var->addOrigin(std::move(origin)); - emplace(key, var); + emplace(key, std::move(var)); } void AnchoredSetVariable::set(const std::string &key, - const std::string &value, size_t offset) { - std::unique_ptr origin(new VariableOrigin()); - std::string *v = new std::string(value); - VariableValue *var = new VariableValue(&m_name, &key, v); - delete v; + const bpstd::string_view &value, size_t offset) { + auto var = std::make_shared(&m_name, &key, &value); - origin->m_offset = offset; - origin->m_length = value.size(); + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = value.size(); var->addOrigin(std::move(origin)); emplace(key, var); @@ -81,19 +71,19 @@ void AnchoredSetVariable::set(const std::string &key, void AnchoredSetVariable::resolve( - std::vector *l) { + VariableValues *l) const noexcept { for (const auto& x : *this) { - l->insert(l->begin(), new VariableValue(x.second)); + l->insert(l->begin(), x.second); } } void AnchoredSetVariable::resolve( - std::vector *l, - variables::KeyExclusions &ke) { + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept { for (const auto& x : *this) { if (!ke.toOmit(x.first)) { - l->insert(l->begin(), new VariableValue(x.second)); + l->insert(l->begin(), x.second); } else { ms_dbg_a(m_transaction, 7, "Excluding key: " + x.first + " from target value."); @@ -103,16 +93,16 @@ void AnchoredSetVariable::resolve( void AnchoredSetVariable::resolve(const std::string &key, - std::vector *l) { + VariableValues *l) const noexcept { auto range = this->equal_range(key); for (auto it = range.first; it != range.second; ++it) { - l->push_back(new VariableValue(it->second)); + l->push_back(it->second); } } std::unique_ptr AnchoredSetVariable::resolveFirst( - const std::string &key) { + const std::string &key) const noexcept { auto range = equal_range(key); for (auto it = range.first; it != range.second; ++it) { std::unique_ptr b(new std::string()); @@ -123,28 +113,28 @@ std::unique_ptr AnchoredSetVariable::resolveFirst( } -void AnchoredSetVariable::resolveRegularExpression(Utils::Regex *r, - std::vector *l) { +void AnchoredSetVariable::resolveRegularExpression(const Utils::Regex *r, + VariableValues *l) const noexcept { for (const auto& x : *this) { int ret = Utils::regex_search(x.first, *r); if (ret <= 0) { continue; } - l->insert(l->begin(), new VariableValue(x.second)); + l->insert(l->begin(), x.second); } } -void AnchoredSetVariable::resolveRegularExpression(Utils::Regex *r, - std::vector *l, - variables::KeyExclusions &ke) { +void AnchoredSetVariable::resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept { for (const auto& x : *this) { int ret = Utils::regex_search(x.first, *r); if (ret <= 0) { continue; } if (!ke.toOmit(x.first)) { - l->insert(l->begin(), new VariableValue(x.second)); + l->insert(l->begin(), x.second); } else { ms_dbg_a(m_transaction, 7, "Excluding key: " + x.first + " from target value."); diff --git a/src/anchored_variable.cc b/src/anchored_variable.cc index 35be6d38fb..940714c474 100644 --- a/src/anchored_variable.cc +++ b/src/anchored_variable.cc @@ -23,6 +23,7 @@ #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/utils/regex.h" +#include "modsecurity/string_view.hpp" namespace modsecurity { @@ -31,22 +32,11 @@ AnchoredVariable::AnchoredVariable(Transaction *t, const std::string &name) : m_transaction(t), m_offset(0), - m_name(""), + m_name(name), m_value(""), - m_var(NULL) { - m_name.append(name); - m_var = new VariableValue(&m_name); + m_var(std::make_shared(&name)) { } - -AnchoredVariable::~AnchoredVariable() { - if (m_var) { - delete (m_var); - m_var = NULL; - } -} - - void AnchoredVariable::unset() { m_value.clear(); } @@ -54,78 +44,95 @@ void AnchoredVariable::unset() { void AnchoredVariable::set(const std::string &a, size_t offset, size_t offsetLen) { - std::unique_ptr origin(new VariableOrigin()); m_offset = offset; m_value.assign(a.c_str(), a.size()); - origin->m_offset = offset; - origin->m_length = offsetLen; + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = offsetLen; m_var->addOrigin(std::move(origin)); } void AnchoredVariable::set(const std::string &a, size_t offset) { - std::unique_ptr origin(new VariableOrigin()); + m_offset = offset; + m_value.assign(a.c_str(), a.size()); + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = m_value.size(); + m_var->addOrigin(std::move(origin)); +} + + +void AnchoredVariable::set(const char *a, size_t offset) { + VariableOrigin origin; + + m_offset = offset; + m_value.assign(a, strlen(a)); + origin.m_offset = offset; + origin.m_length = m_value.size(); + m_var->addOrigin(std::move(origin)); +} + + +void AnchoredVariable::set(const bpstd::string_view &a, size_t offset) { + VariableOrigin origin; m_offset = offset; m_value.assign(a.c_str(), a.size()); - origin->m_offset = offset; - origin->m_length = m_value.size(); + origin.m_offset = offset; + origin.m_length = m_value.size(); + m_var->addOrigin(std::move(origin)); } void AnchoredVariable::append(const std::string &a, size_t offset, bool spaceSeparator) { - std::unique_ptr origin( - new VariableOrigin()); - if (spaceSeparator && !m_value.empty()) { m_value.append(" " + a); } else { m_value.append(a); } m_offset = offset; - origin->m_offset = offset; - origin->m_length = a.size(); + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = a.size(); m_var->addOrigin(std::move(origin)); } void AnchoredVariable::append(const std::string &a, size_t offset, bool spaceSeparator, int size) { - std::unique_ptr origin( - new VariableOrigin()); - if (spaceSeparator && !m_value.empty()) { m_value.append(" " + a); } else { m_value.append(a); } m_offset = offset; - origin->m_offset = offset; - origin->m_length = size; + VariableOrigin origin; + origin.m_offset = offset; + origin.m_length = size; m_var->addOrigin(std::move(origin)); } -void AnchoredVariable::evaluate(std::vector *l) { +void AnchoredVariable::evaluate(VariableValues *l) const noexcept { if (m_name.empty()) { return; } m_var->setValue(m_value); - VariableValue *m_var2 = new VariableValue(m_var); - l->push_back(m_var2); + l->push_back(m_var); } -std::string * AnchoredVariable::evaluate() { +const std::string *AnchoredVariable::evaluate() const noexcept { return &m_value; } -std::unique_ptr AnchoredVariable::resolveFirst() { +std::unique_ptr AnchoredVariable::resolveFirst() const noexcept { if (m_value.empty()) { return nullptr; } diff --git a/src/audit_log/audit_log.cc b/src/audit_log/audit_log.cc index f65d38b6f6..d6105b532a 100644 --- a/src/audit_log/audit_log.cc +++ b/src/audit_log/audit_log.cc @@ -266,14 +266,13 @@ bool AuditLog::init(std::string *error) { } -bool AuditLog::isRelevant(int status) { +bool AuditLog::isRelevant(int status) const noexcept { std::string sstatus = std::to_string(status); if (m_relevant.empty()) { return false; } - if (sstatus.empty()) { return true; } @@ -283,50 +282,34 @@ bool AuditLog::isRelevant(int status) { } -bool AuditLog::saveIfRelevant(Transaction *transaction) { - return saveIfRelevant(transaction, -1); -} - - -bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) { - bool saveAnyway = false; +bool AuditLog::saveIfRelevant(Transaction *transaction) const noexcept { if (m_status == OffAuditLogStatus || m_status == NotSetLogStatus) { ms_dbg_a(transaction, 5, "Audit log engine was not set."); - return true; - } - - for (RuleMessage &i : transaction->m_rulesMessages) { - if (i.m_noAuditLog == false) { - saveAnyway = true; - break; - } + return false; } if ((m_status == RelevantOnlyAuditLogStatus - && this->isRelevant(transaction->m_httpCodeReturned) == false) - && saveAnyway == false) { + && isRelevant(transaction->m_httpCodeReturned) == false)) { ms_dbg_a(transaction, 9, "Return code `" + std::to_string(transaction->m_httpCodeReturned) + "'" \ " is not interesting to audit logs, relevant code(s): `" + m_relevant + "'."); - return false; } - if (parts == -1) { - parts = m_parts; - } ms_dbg_a(transaction, 5, "Saving this request as part " \ "of the audit logs."); + if (m_writer == NULL) { ms_dbg_a(transaction, 1, "Internal error, audit log writer is null"); - } else { - std::string error; - bool a = m_writer->write(transaction, parts, &error); - if (a == false) { - ms_dbg_a(transaction, 1, "Cannot save the audit log: " + error); - return false; - } + return false; + } + + std::string error; + bool a = m_writer->write(transaction, transaction->m_auditLogParts, &error); + if (a == false) { + ms_dbg_a(transaction, 1, "Cannot save the audit log: " + error); + return false; } return true; diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index 717f998216..0b2196d9b9 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -86,17 +86,17 @@ void InMemoryPerProcess::del(const std::string& key) { void InMemoryPerProcess::resolveSingleMatch(const std::string& var, - std::vector *l) { + VariableValues *l) const noexcept { auto range = this->equal_range(var); for (auto it = range.first; it != range.second; ++it) { - l->push_back(new VariableValue(&m_name, &it->first, &it->second)); + l->push_back(std::make_shared(&m_name, &it->first, &it->second)); } } void InMemoryPerProcess::resolveMultiMatches(const std::string& var, - std::vector *l, variables::KeyExclusions &ke) { + VariableValues *l, const variables::KeyExclusions &ke) const noexcept { size_t keySize = var.size(); l->reserve(15); @@ -105,8 +105,7 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, if (ke.toOmit(i.first)) { continue; } - l->insert(l->begin(), new VariableValue(&m_name, &i.first, - &i.second)); + l->insert(l->begin(), std::make_shared(&m_name, &i.first, &i.second)); } } else { auto range = this->equal_range(var); @@ -114,15 +113,15 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, if (ke.toOmit(var)) { continue; } - l->insert(l->begin(), new VariableValue(&m_name, &var, - &it->second)); + l->insert(l->begin(), std::make_shared(&m_name, &it->first, &it->second)); + } } } void InMemoryPerProcess::resolveRegularExpression(const std::string& var, - std::vector *l, variables::KeyExclusions &ke) { + VariableValues *l, const variables::KeyExclusions &ke) const noexcept { //if (var.find(":") == std::string::npos) { // return; @@ -155,13 +154,13 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var, if (ke.toOmit(x.first)) { continue; } - l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second)); + l->insert(l->begin(), std::make_shared(&m_name, &x.first, &x.second)); } } std::unique_ptr InMemoryPerProcess::resolveFirst( - const std::string& var) { + const std::string& var) const noexcept { auto range = equal_range(var); for (auto it = range.first; it != range.second; ++it) { return std::unique_ptr(new std::string(it->second)); diff --git a/src/collection/backend/in_memory-per_process.h b/src/collection/backend/in_memory-per_process.h index 0550fbc7b0..4390c93b2f 100644 --- a/src/collection/backend/in_memory-per_process.h +++ b/src/collection/backend/in_memory-per_process.h @@ -84,16 +84,16 @@ class InMemoryPerProcess : void del(const std::string& key) override; - std::unique_ptr resolveFirst(const std::string& var) override; + std::unique_ptr resolveFirst(const std::string& var) const noexcept override; void resolveSingleMatch(const std::string& var, - std::vector *l) override; + VariableValues *l) const noexcept override; void resolveMultiMatches(const std::string& var, - std::vector *l, - variables::KeyExclusions &ke) override; + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept override; void resolveRegularExpression(const std::string& var, - std::vector *l, - variables::KeyExclusions &ke) override; + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept override; private: pthread_mutex_t m_lock; diff --git a/src/collection/backend/lmdb.cc b/src/collection/backend/lmdb.cc index 55afb1c548..b2f5280dd9 100644 --- a/src/collection/backend/lmdb.cc +++ b/src/collection/backend/lmdb.cc @@ -262,7 +262,7 @@ bool LMDB::storeOrUpdateFirst(const std::string &key, void LMDB::resolveSingleMatch(const std::string& var, - std::vector *l) { + VariableValues *l) { int rc; MDB_txn *txn; MDB_dbi dbi; @@ -287,11 +287,10 @@ void LMDB::resolveSingleMatch(const std::string& var, mdb_cursor_open(txn, dbi, &cursor); while ((rc = mdb_cursor_get(cursor, &mdb_key, &mdb_value_ret, MDB_NEXT_DUP)) == 0) { - std::string *a = new std::string( + std::string a( reinterpret_cast(mdb_value_ret.mv_data), mdb_value_ret.mv_size); - VariableValue *v = new VariableValue(&var, a); - l->push_back(v); + l->emplace_back(&var, &a); } mdb_cursor_close(cursor); @@ -466,7 +465,7 @@ void LMDB::del(const std::string& key) { void LMDB::resolveMultiMatches(const std::string& var, - std::vector *l, + VariableValues *l, variables::KeyExclusions &ke) { MDB_val key, data; MDB_txn *txn = NULL; @@ -496,7 +495,7 @@ void LMDB::resolveMultiMatches(const std::string& var, if (keySize == 0) { while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - l->insert(l->begin(), new VariableValue( + l->insert(l->begin(), std::make_shared( &m_name, new std::string(reinterpret_cast(key.mv_data), key.mv_size), @@ -507,7 +506,7 @@ void LMDB::resolveMultiMatches(const std::string& var, while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { char *a = reinterpret_cast(key.mv_data); if (strncmp(var.c_str(), a, keySize) == 0) { - l->insert(l->begin(), new VariableValue( + l->insert(l->begin(), std::make_shared( &m_name, new std::string(reinterpret_cast(key.mv_data), key.mv_size), @@ -528,7 +527,7 @@ void LMDB::resolveMultiMatches(const std::string& var, void LMDB::resolveRegularExpression(const std::string& var, - std::vector *l, + VariableValues *l, variables::KeyExclusions &ke) { MDB_val key, data; MDB_txn *txn = NULL; diff --git a/src/collection/backend/lmdb.h b/src/collection/backend/lmdb.h index d31a8d9560..25d48004ef 100644 --- a/src/collection/backend/lmdb.h +++ b/src/collection/backend/lmdb.h @@ -66,12 +66,12 @@ class LMDB : std::unique_ptr resolveFirst(const std::string& var) override; void resolveSingleMatch(const std::string& var, - std::vector *l) override; + VariableValues *l) const override; void resolveMultiMatches(const std::string& var, - std::vector *l, + VariableValues *l, variables::KeyExclusions &ke) override; void resolveRegularExpression(const std::string& var, - std::vector *l, + VariableValues *l, variables::KeyExclusions &ke) override; private: diff --git a/src/engine/lua.cc b/src/engine/lua.cc index 9619ef09ba..8d111f4948 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -65,8 +65,7 @@ bool Lua::isCompatible(const std::string &script, Lua *l, std::string *error) { bool Lua::load(const std::string &script, std::string *err) { #ifdef WITH_LUA - lua_State *L = NULL; - L = luaL_newstate(); + lua_State *L = luaL_newstate(); luaL_openlibs(L); m_scriptName = script; @@ -122,7 +121,7 @@ const char *Lua::blob_reader(lua_State *L, void *ud, size_t *size) { #endif -int Lua::run(Transaction *t, const std::string &str) { +int Lua::run(Transaction *t, const std::string &str) const { #ifdef WITH_LUA std::string luaRet; const char *a = NULL; @@ -139,10 +138,12 @@ int Lua::run(Transaction *t, const std::string &str) { luaL_setfuncs(L, mscLuaLib, 0); lua_setglobal(L, "m"); + LuaScriptBlob blob(m_blob); + #ifdef WITH_LUA_5_1 - int rc = lua_load(L, Lua::blob_reader, &m_blob, m_scriptName.c_str()); + int rc = lua_load(L, Lua::blob_reader, &blob, m_scriptName.c_str()); #else - int rc = lua_load(L, Lua::blob_reader, &m_blob, m_scriptName.c_str(), + int rc = lua_load(L, Lua::blob_reader, &blob, m_scriptName.c_str(), NULL); #endif if (rc != LUA_OK) { @@ -234,7 +235,7 @@ int Lua::run(Transaction *t, const std::string &str) { #ifdef WITH_LUA int Lua::log(lua_State *L) { - const Transaction *t = NULL; + const Transaction *t(NULL); const char *text; int level; @@ -256,9 +257,9 @@ int Lua::log(lua_State *L) { int Lua::getvar(lua_State *L) { - const char *varname = NULL; - Transaction *t = NULL; - void *z = NULL; + const char *varname(NULL); + Transaction *t(NULL); + void *z(NULL); /* Retrieve parameters. */ varname = reinterpret_cast(luaL_checkstring(L, 1)); @@ -282,10 +283,10 @@ int Lua::getvar(lua_State *L) { int Lua::getvars(lua_State *L) { - const char *varname = NULL; - Transaction *t = NULL; - void *z = NULL; - std::vector l; + const char *varname(NULL); + Transaction *t(NULL); + void *z(NULL); + VariableValues l; int idx = 1; /* Retrieve parameters. */ @@ -303,7 +304,7 @@ int Lua::getvars(lua_State *L) { lua_newtable(L); lua_pushstring(L, "name"); - lua_pushlstring(L, i->getKeyWithCollection().c_str(), i->getKeyWithCollection().size()); + lua_pushlstring(L, i->getName().c_str(), i->getName().size()); lua_settable(L, -3); lua_pushstring(L, "value"); @@ -314,25 +315,21 @@ int Lua::getvars(lua_State *L) { idx++; } - for (const VariableValue * i : l) { - delete i; - } - return 1; } int Lua::setvar(lua_State *L) { - Transaction *t = NULL; - const char *var_value = NULL; - const char *var_name = NULL; + Transaction *t(NULL); + const char *var_value(NULL); + const char *var_name(NULL); std::string vname; std::string collection; std::string variableName; int nargs = lua_gettop(L); char *chr = NULL; size_t pos; - void *z = NULL; + void *z(NULL); lua_getglobal(L, "__transaction"); z = const_cast(lua_topointer(L, -1)); @@ -440,20 +437,24 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + ModSecString in; + ModSecString out; + in.assign(newVar.c_str(), newVar.size()); + tfn->execute(t, in, out); + newVar.assign(out.c_str(), out.size()); + delete tfn; } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ + std::string(name)); } - delete tfn; } return newVar; } if (lua_isstring(L, idx)) { - const char *name = NULL; + const char *name(NULL); name = reinterpret_cast(luaL_checkstring(L, idx)); actions::transformations::Transformation *tfn = \ @@ -462,7 +463,11 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + ModSecString in; + ModSecString out; + in.assign(newVar.c_str(), newVar.size()); + tfn->execute(t, in, out); + newVar.assign(out.c_str(), out.size()); delete tfn; } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ diff --git a/src/engine/lua.h b/src/engine/lua.h index d2c209f360..da60876e79 100644 --- a/src/engine/lua.h +++ b/src/engine/lua.h @@ -34,7 +34,8 @@ class LuaScriptBlob { public: LuaScriptBlob() : m_data(NULL), - m_len(0) { } + m_len(0) + { } ~LuaScriptBlob() { if (m_data) { @@ -43,10 +44,17 @@ class LuaScriptBlob { } } + LuaScriptBlob(const LuaScriptBlob &other) : + m_data(NULL), + m_len(other.m_len) { + m_data = (unsigned char *)std::malloc(m_len); + // FIXME: m_data NULL? + std::memcpy(m_data, other.m_data, m_len); + } + void write(const void *data, size_t len) { - unsigned char *d = NULL; - d = (unsigned char *)realloc((unsigned char *)m_data, len + m_len); + unsigned char *d = (unsigned char *)realloc((unsigned char *)m_data, len + m_len); std::memcpy(d + m_len, data, len); m_len = m_len + len; m_data = d; @@ -69,7 +77,7 @@ class Lua { Lua() { } bool load(const std::string &script, std::string *err); - int run(Transaction *t, const std::string &str=""); + int run(Transaction *t, const std::string &str="") const; static bool isCompatible(const std::string &script, Lua *l, std::string *error); #ifdef WITH_LUA diff --git a/src/modsecurity.cc b/src/modsecurity.cc index ac8e52563a..fd56452499 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -188,7 +188,7 @@ const std::string& ModSecurity::getConnectorInformation() const { return m_connector; } -void ModSecurity::serverLog(void *data, std::shared_ptr rm) { +void ModSecurity::serverLog(void *data, RuleMessage *rm) { if (m_logCb == NULL) { std::cerr << "Server log callback is not set -- " << rm->errorLog(); std::cerr << std::endl; @@ -207,11 +207,12 @@ void ModSecurity::serverLog(void *data, std::shared_ptr rm) { } if (m_logProperties & RuleMessageLogProperty) { - const void *a = static_cast(rm.get()); + const void *a = static_cast(rm); if (m_logProperties & IncludeFullHighlightLogProperty) { m_logCb(data, a); return; } + m_logCb(data, a); return; } @@ -256,7 +257,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, strlen("highlight")); yajl_gen_array_open(g); - while (vars.size() > 0) { + while (!vars.empty()) { std::string value; yajl_gen_map_open(g); vars.pop_back(); @@ -303,9 +304,11 @@ int ModSecurity::processContentOffset(const char *content, size_t len, varValue.size()); yajl_gen_map_close(g); - while (trans.size() > 0) { + while (!trans.empty()) { modsecurity::actions::transformations::Transformation *t; - std::string varValueRes; + ModSecString in; + ModSecString out; + yajl_gen_map_open(g); yajl_gen_string(g, reinterpret_cast("transformation"), @@ -317,8 +320,9 @@ int ModSecurity::processContentOffset(const char *content, size_t len, t = modsecurity::actions::transformations::Transformation::instantiate( trans.back().str().c_str()); - varValueRes = t->evaluate(varValue, NULL); - varValue.assign(varValueRes); + in.assign(varValue.c_str()); + t->execute(NULL, in, out); + varValue.assign(out.c_str()); trans.pop_back(); yajl_gen_string(g, reinterpret_cast("value"), @@ -338,7 +342,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, yajl_gen_map_open(g); - while (ops.size() > 0) { + while (!ops.empty()) { std::string value; yajl_gen_string(g, reinterpret_cast("highlight"), strlen("highlight")); diff --git a/src/operators/begins_with.cc b/src/operators/begins_with.cc index e2766ec3f2..49b7c7db0d 100644 --- a/src/operators/begins_with.cc +++ b/src/operators/begins_with.cc @@ -24,8 +24,10 @@ namespace modsecurity { namespace operators { -bool BeginsWith::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { +bool BeginsWith::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); if (str.size() < p.size()) { diff --git a/src/operators/begins_with.h b/src/operators/begins_with.h index e8470d982f..130a10cab8 100644 --- a/src/operators/begins_with.h +++ b/src/operators/begins_with.h @@ -32,8 +32,10 @@ class BeginsWith : public Operator { explicit BeginsWith(std::unique_ptr param) : Operator("BeginsWith", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, const std::string &str, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/contains.cc b/src/operators/contains.cc index e63e8adcc1..637d966c0f 100644 --- a/src/operators/contains.cc +++ b/src/operators/contains.cc @@ -21,10 +21,12 @@ namespace modsecurity { namespace operators { -bool Contains::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, std::shared_ptr ruleMessage) { +bool Contains::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - size_t offset = input.find(p); + size_t offset = input.to_string().find(p); bool contains = offset != std::string::npos; diff --git a/src/operators/contains.h b/src/operators/contains.h index 8bab08528a..4a00e2235c 100644 --- a/src/operators/contains.h +++ b/src/operators/contains.h @@ -33,10 +33,12 @@ class Contains : public Operator { public: /** @ingroup ModSecurity_Operator */ explicit Contains(std::unique_ptr param) - : Operator("Contains", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, - std::shared_ptr ruleMessage) override; + : Operator("Contains", std::move(param)) { }; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/contains_word.cc b/src/operators/contains_word.cc index 262b9b1947..36c03e030d 100644 --- a/src/operators/contains_word.cc +++ b/src/operators/contains_word.cc @@ -23,7 +23,7 @@ namespace modsecurity { namespace operators { -bool ContainsWord::acceptableChar(const std::string& a, size_t pos) { +bool ContainsWord::acceptableChar(const bpstd::string_view &a, size_t pos) { if (a.size() - 1 < pos) { return false; } @@ -36,37 +36,40 @@ bool ContainsWord::acceptableChar(const std::string& a, size_t pos) { return true; } -bool ContainsWord::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { +bool ContainsWord::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &inputView, + RuleMessage *ruleMessage) { std::string paramTarget(m_string->evaluate(transaction)); + std::string input = inputView.to_string(); if (paramTarget.empty()) { return true; } - if (str.empty()) { + if (input.empty()) { return false; } - if (str == paramTarget) { + if (input == paramTarget) { return true; } - size_t pos = str.find(paramTarget); + size_t pos = input.find(paramTarget); while (pos != std::string::npos) { - if (pos == 0 && acceptableChar(str, paramTarget.size())) { + if (pos == 0 && acceptableChar(input, paramTarget.size())) { logOffset(ruleMessage, 0, paramTarget.size()); return true; } - if (pos + paramTarget.size() == str.size() && - acceptableChar(str, pos - 1)) { + if (pos + paramTarget.size() == input.size() && + acceptableChar(input, pos - 1)) { logOffset(ruleMessage, pos, paramTarget.size()); return true; } - if (acceptableChar(str, pos - 1) && - acceptableChar(str, pos + paramTarget.size())) { + if (acceptableChar(input, pos - 1) && + acceptableChar(input, pos + paramTarget.size())) { logOffset(ruleMessage, pos, paramTarget.size()); return true; } - pos = str.find(paramTarget, pos + 1); + pos = input.find(paramTarget, pos + 1); } return false; diff --git a/src/operators/contains_word.h b/src/operators/contains_word.h index c9698d215b..de697a5f91 100644 --- a/src/operators/contains_word.h +++ b/src/operators/contains_word.h @@ -32,12 +32,13 @@ class ContainsWord : public Operator { explicit ContainsWord(std::unique_ptr param) : Operator("ContainsWord", std::move(param)) { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; private: - static bool acceptableChar(const std::string& a, size_t pos); + static bool acceptableChar(const bpstd::string_view &a, size_t pos); }; } // namespace operators diff --git a/src/operators/detect_sqli.cc b/src/operators/detect_sqli.cc index 16f31c18e7..c99861e51a 100644 --- a/src/operators/detect_sqli.cc +++ b/src/operators/detect_sqli.cc @@ -20,38 +20,43 @@ #include "src/operators/operator.h" #include "others/libinjection/src/libinjection.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { -bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool DetectSQLi::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { char fingerprint[8]; int issqli; issqli = libinjection_sqli(input.c_str(), input.length(), fingerprint); + if (!transaction) { + goto tisempty; + } + if (issqli) { - if (t) { - t->m_matched.push_back(fingerprint); - ms_dbg_a(t, 4, "detected SQLi using libinjection with " \ - "fingerprint '" + std::string(fingerprint) + "' at: '" + - input + "'"); - if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( - "0", std::string(fingerprint)); - ms_dbg_a(t, 7, "Added DetectSQLi match TX.0: " + \ - std::string(fingerprint)); - } + transaction->m_matched.push_back(fingerprint); + ms_dbg_a(transaction, 4, "detected SQLi using libinjection with " \ + "fingerprint '" + std::string(fingerprint) + "' at: '" + + input.to_string() + "'"); + if (rule && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( + "0", std::string(fingerprint)); + ms_dbg_a(transaction, 7, "Added DetectSQLi match TX.0: " + \ + std::string(fingerprint)); } } else { - if (t) { - ms_dbg_a(t, 9, "detected SQLi: not able to find an " \ - "inject on '" + input + "'"); - } + ms_dbg_a(transaction, 9, "detected SQLi: not able to find an " \ + "inject on '" + input.to_string() + "'"); } +tisempty: return issqli != 0; } diff --git a/src/operators/detect_sqli.h b/src/operators/detect_sqli.h index 2dc0d74836..02a207758d 100644 --- a/src/operators/detect_sqli.h +++ b/src/operators/detect_sqli.h @@ -32,9 +32,10 @@ class DetectSQLi : public Operator { m_match_message.assign("detected SQLi using libinjection."); } - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/detect_xss.cc b/src/operators/detect_xss.cc index 7386f36544..eb44f5d1aa 100644 --- a/src/operators/detect_xss.cc +++ b/src/operators/detect_xss.cc @@ -19,30 +19,33 @@ #include "src/operators/operator.h" #include "others/libinjection/src/libinjection.h" +#include "src/rule_with_actions.h" namespace modsecurity { namespace operators { -bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool DetectXSS::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { int is_xss; is_xss = libinjection_xss(input.c_str(), input.length()); - if (t) { + if (transaction) { if (is_xss) { - ms_dbg_a(t, 5, "detected XSS using libinjection."); - if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + ms_dbg_a(transaction, 5, "detected XSS using libinjection."); + if (rule && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(input)); - ms_dbg_a(t, 7, "Added DetectXSS match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added DetectXSS match TX.0: " + \ std::string(input)); } } else { - ms_dbg_a(t, 9, "libinjection was not able to " \ - "find any XSS in: " + input); + ms_dbg_a(transaction, 9, "libinjection was not able to " \ + "find any XSS in: " + input.to_string()); } } return is_xss != 0; diff --git a/src/operators/detect_xss.h b/src/operators/detect_xss.h index 266fdf364c..748da98b9a 100644 --- a/src/operators/detect_xss.h +++ b/src/operators/detect_xss.h @@ -31,9 +31,10 @@ class DetectXSS : public Operator { m_match_message.assign("detected XSS using libinjection."); } - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/ends_with.cc b/src/operators/ends_with.cc index 632fc8fe39..bf27d4ff74 100644 --- a/src/operators/ends_with.cc +++ b/src/operators/ends_with.cc @@ -23,16 +23,18 @@ namespace modsecurity { namespace operators { -bool EndsWith::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { +bool EndsWith::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { bool ret = false; std::string p(m_string->evaluate(transaction)); - if (str.length() >= p.length()) { - ret = (0 == str.compare(str.length() - p.length(), + if (input.length() >= p.length()) { + ret = (0 == input.compare(input.length() - p.length(), p.length(), p)); if (ret) { - logOffset(ruleMessage, str.length() - p.length(), + logOffset(ruleMessage, input.length() - p.length(), p.size()); } } diff --git a/src/operators/ends_with.h b/src/operators/ends_with.h index c5352618cf..8c206255eb 100644 --- a/src/operators/ends_with.h +++ b/src/operators/ends_with.h @@ -33,9 +33,11 @@ class EndsWith : public Operator { : Operator("EndsWith", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, - std::shared_ptr ruleMessage) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; diff --git a/src/operators/eq.cc b/src/operators/eq.cc index c9b31bf6ee..7a611dac4f 100644 --- a/src/operators/eq.cc +++ b/src/operators/eq.cc @@ -24,7 +24,10 @@ namespace modsecurity { namespace operators { -bool Eq::evaluate(Transaction *transaction, const std::string &input) { +bool Eq::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { int p = 0; int i = 0; std::string pt(m_string->evaluate(transaction)); @@ -35,7 +38,7 @@ bool Eq::evaluate(Transaction *transaction, const std::string &input) { p = 0; } try { - i = std::stoi(input); + i = std::stoi(input.c_str()); } catch (...) { i = 0; } diff --git a/src/operators/eq.h b/src/operators/eq.h index 30ac861484..1c426c2539 100644 --- a/src/operators/eq.h +++ b/src/operators/eq.h @@ -31,7 +31,11 @@ class Eq : public Operator { /** @ingroup ModSecurity_Operator */ explicit Eq(std::unique_ptr param) : Operator("Eq", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/fuzzy_hash.cc b/src/operators/fuzzy_hash.cc index 1d57ab8c47..732236b0cb 100644 --- a/src/operators/fuzzy_hash.cc +++ b/src/operators/fuzzy_hash.cc @@ -96,21 +96,24 @@ FuzzyHash::~FuzzyHash() { } -bool FuzzyHash::evaluate(Transaction *t, const std::string &str) { +bool FuzzyHash::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { #ifdef WITH_SSDEEP char result[FUZZY_MAX_RESULT]; struct fuzzy_hash_chunk *chunk = m_head; if (fuzzy_hash_buf((const unsigned char*)str.c_str(), str.size(), result)) { - ms_dbg_a(t, 4, "Problems generating fuzzy hash"); + ms_dbg_a(transaction, 4, "Problems generating fuzzy hash"); return false; } while (chunk != NULL) { int i = fuzzy_compare(chunk->data, result); if (i >= m_threshold) { - ms_dbg_a(t, 4, "Fuzzy hash: matched " \ + ms_dbg_a(transaction, 4, "Fuzzy hash: matched " \ "with score: " + std::to_string(i) + "."); return true; } diff --git a/src/operators/fuzzy_hash.h b/src/operators/fuzzy_hash.h index c470b09ad9..c0ebfcb0a7 100644 --- a/src/operators/fuzzy_hash.h +++ b/src/operators/fuzzy_hash.h @@ -44,9 +44,12 @@ class FuzzyHash : public Operator { m_head(NULL) { } ~FuzzyHash(); - bool evaluate(Transaction *transaction, const std::string &std) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; - bool init(const std::string ¶m, std::string *error) override; + bool init(const std::string &file, std::string *error) override; private: int m_threshold; struct fuzzy_hash_chunk *m_head; diff --git a/src/operators/ge.cc b/src/operators/ge.cc index 0d27cfe8b7..e0c859440d 100644 --- a/src/operators/ge.cc +++ b/src/operators/ge.cc @@ -23,11 +23,13 @@ namespace modsecurity { namespace operators { -bool Ge::evaluate(Transaction *transaction, const std::string &input) { +bool Ge::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - std::string i = input; - bool ge = atoll(i.c_str()) >= atoll(p.c_str()); + bool ge = atoll(str.c_str()) >= atoll(p.c_str()); return ge; } diff --git a/src/operators/ge.h b/src/operators/ge.h index 57ca2a7c24..6f0bfc88ba 100644 --- a/src/operators/ge.h +++ b/src/operators/ge.h @@ -32,7 +32,11 @@ class Ge : public Operator { : Operator("Ge", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/geo_lookup.cc b/src/operators/geo_lookup.cc index 51fb81288e..28989c5df1 100644 --- a/src/operators/geo_lookup.cc +++ b/src/operators/geo_lookup.cc @@ -34,16 +34,19 @@ namespace modsecurity { namespace operators { -bool GeoLookup::evaluate(Transaction *trans, const std::string &exp) { +bool GeoLookup::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { using std::placeholders::_1; using std::placeholders::_2; bool ret = true; - if (trans) { - ret = Utils::GeoLookup::getInstance().lookup(exp, trans, - std::bind(&GeoLookup::debug, this, trans, _1, _2)); + if (transaction) { + ret = Utils::GeoLookup::getInstance().lookup(str.c_str(), transaction, + std::bind(&GeoLookup::debug, this, transaction, _1, _2)); } else { - ret = Utils::GeoLookup::getInstance().lookup(exp, NULL, + ret = Utils::GeoLookup::getInstance().lookup(str.c_str(), NULL, nullptr); } diff --git a/src/operators/geo_lookup.h b/src/operators/geo_lookup.h index 757f9c2c6e..5dd872b049 100644 --- a/src/operators/geo_lookup.h +++ b/src/operators/geo_lookup.h @@ -29,11 +29,15 @@ class GeoLookup : public Operator { /** @ingroup ModSecurity_Operator */ GeoLookup() : Operator("GeoLookup") { } - bool evaluate(Transaction *transaction, const std::string &exp) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; protected: - bool debug(Transaction *transaction, int x, const std::string &a) { - ms_dbg_a(transaction, x, a); + bool debug(Transaction *transaction, int x, const bpstd::string_view &str) { + ms_dbg_a(transaction, x, str.to_string()); return true; } }; diff --git a/src/operators/gsblookup.cc b/src/operators/gsblookup.cc index e5f697f075..2c094b7470 100644 --- a/src/operators/gsblookup.cc +++ b/src/operators/gsblookup.cc @@ -23,7 +23,10 @@ namespace modsecurity { namespace operators { -bool GsbLookup::evaluate(Transaction *transaction, const std::string &str) { +bool GsbLookup::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { /** * @todo Implement the operator GeoLookup. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#gsblookup diff --git a/src/operators/gsblookup.h b/src/operators/gsblookup.h index 57360ac627..c9eb726550 100644 --- a/src/operators/gsblookup.h +++ b/src/operators/gsblookup.h @@ -31,7 +31,10 @@ class GsbLookup : public Operator { explicit GsbLookup(std::unique_ptr param) : Operator("GsbLookup", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/gt.cc b/src/operators/gt.cc index 1c967bbde2..32da3bc6e8 100644 --- a/src/operators/gt.cc +++ b/src/operators/gt.cc @@ -23,10 +23,13 @@ namespace modsecurity { namespace operators { -bool Gt::evaluate(Transaction *transaction, const std::string &input) { +bool Gt::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool gt = atoll(input.c_str()) > atoll(p.c_str()); + bool gt = atoll(str.c_str()) > atoll(p.c_str()); return gt; } diff --git a/src/operators/gt.h b/src/operators/gt.h index ac7fe134f4..13562f8d71 100644 --- a/src/operators/gt.h +++ b/src/operators/gt.h @@ -33,7 +33,11 @@ class Gt : public Operator { : Operator("Gt", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/inspect_file.cc b/src/operators/inspect_file.cc index db0483d134..69cf73c64e 100644 --- a/src/operators/inspect_file.cc +++ b/src/operators/inspect_file.cc @@ -49,9 +49,12 @@ bool InspectFile::init(const std::string ¶m2, std::string *error) { } -bool InspectFile::evaluate(Transaction *transaction, const std::string &str) { +bool InspectFile::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { if (m_isScript) { - return m_lua.run(transaction, str); + return m_lua.run(transaction, str.to_string()); } else { FILE *in; char buff[512]; @@ -61,7 +64,7 @@ bool InspectFile::evaluate(Transaction *transaction, const std::string &str) { openstr.append(m_param); openstr.append(" "); - openstr.append(str); + openstr.append(str.to_string()); if (!(in = popen(openstr.c_str(), "r"))) { return false; } diff --git a/src/operators/inspect_file.h b/src/operators/inspect_file.h index 4bdac5ebab..65acde7fde 100644 --- a/src/operators/inspect_file.h +++ b/src/operators/inspect_file.h @@ -35,8 +35,13 @@ class InspectFile : public Operator { m_file(""), m_isScript(false) { } - bool init(const std::string ¶m, std::string *error) override; - bool evaluate(Transaction *transaction, const std::string &str) override; + bool init(const std::string &file, std::string *error) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + private: std::string m_file; bool m_isScript; diff --git a/src/operators/ip_match.cc b/src/operators/ip_match.cc index ec84a8b785..94c16c2137 100644 --- a/src/operators/ip_match.cc +++ b/src/operators/ip_match.cc @@ -37,8 +37,11 @@ bool IpMatch::init(const std::string &file, std::string *error) { } -bool IpMatch::evaluate(Transaction *transaction, const std::string &input) { - return m_tree.contains(input); +bool IpMatch::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { + return m_tree.contains(str.c_str()); } diff --git a/src/operators/ip_match.h b/src/operators/ip_match.h index c84327fb4c..3522024b0c 100644 --- a/src/operators/ip_match.h +++ b/src/operators/ip_match.h @@ -34,7 +34,10 @@ class IpMatch : public Operator { IpMatch(const std::string &n, std::unique_ptr param) : Operator(n, std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/le.cc b/src/operators/le.cc index cc2e3dc60d..4abd6f0f72 100644 --- a/src/operators/le.cc +++ b/src/operators/le.cc @@ -23,10 +23,13 @@ namespace modsecurity { namespace operators { -bool Le::evaluate(Transaction *transaction, const std::string &input) { +bool Le::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool le = atoll(input.c_str()) <= atoll(p.c_str()); + bool le = atoll(str.c_str()) <= atoll(p.c_str()); return le; } diff --git a/src/operators/le.h b/src/operators/le.h index a463b3e8c4..d3f4bd348e 100644 --- a/src/operators/le.h +++ b/src/operators/le.h @@ -34,7 +34,10 @@ class Le : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; diff --git a/src/operators/lt.cc b/src/operators/lt.cc index 8458cd1aeb..3e3b2eba2b 100644 --- a/src/operators/lt.cc +++ b/src/operators/lt.cc @@ -22,10 +22,13 @@ namespace modsecurity { namespace operators { -bool Lt::evaluate(Transaction *transaction, const std::string &input) { +bool Lt::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool lt = atoll(input.c_str()) < atoll(p.c_str()); + bool lt = atoll(str.c_str()) < atoll(p.c_str()); return lt; } diff --git a/src/operators/lt.h b/src/operators/lt.h index 6a95adef47..b96240ea56 100644 --- a/src/operators/lt.h +++ b/src/operators/lt.h @@ -34,7 +34,10 @@ class Lt : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/no_match.cc b/src/operators/no_match.cc index c0979e1de9..180a6d4c6b 100644 --- a/src/operators/no_match.cc +++ b/src/operators/no_match.cc @@ -20,7 +20,10 @@ namespace modsecurity { namespace operators { -bool NoMatch::evaluate(Transaction *transaction, const std::string &str) { +bool NoMatch::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { return false; } diff --git a/src/operators/no_match.h b/src/operators/no_match.h index 8016905899..74c18b4bfc 100644 --- a/src/operators/no_match.h +++ b/src/operators/no_match.h @@ -32,7 +32,10 @@ class NoMatch : public Operator { NoMatch() : Operator("NoMatch") { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/operator.cc b/src/operators/operator.cc index 3bb12ce8ef..d3d7cb6e7d 100644 --- a/src/operators/operator.cc +++ b/src/operators/operator.cc @@ -70,7 +70,7 @@ namespace operators { bool Operator::evaluateInternal(Transaction *transaction, - RuleWithActions *rule, const std::string& a, std::shared_ptr rm) { + const RuleWithActions *rule, const bpstd::string_view &a, RuleMessage *rm) { bool res = evaluate(transaction, rule, a, rm); if (m_negation) { @@ -80,34 +80,14 @@ bool Operator::evaluateInternal(Transaction *transaction, return res; } -bool Operator::evaluateInternal(Transaction *transaction, - RuleWithActions *rule, const std::string& a) { - bool res = evaluate(transaction, rule, a); - - if (m_negation) { - return !res; - } - - return res; -} - -bool Operator::evaluateInternal(Transaction *transaction, - const std::string& a) { - bool res = evaluate(transaction, a); - - if (m_negation) { - return !res; - } - - return res; -} - std::string Operator::resolveMatchMessage(Transaction *t, - std::string key, std::string value) { + const VariableValue *v) { std::string ret = m_match_message; if (ret.empty() == true) { + const std::string &key = v->getName(); + const std::string &value = v->getValue(); if (m_couldContainsMacro == false) { ret = "Matched \"Operator `" + m_op + "' with parameter `" + utils::string::limitTo(200, m_param) + @@ -131,7 +111,10 @@ std::string Operator::resolveMatchMessage(Transaction *t, } -bool Operator::evaluate(Transaction *transaction, const std::string& a) { +bool Operator::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { ms_dbg_a(transaction, 2, "Operator: " + m_op + \ " is not implemented or malfunctioning."); return true; @@ -140,7 +123,7 @@ bool Operator::evaluate(Transaction *transaction, const std::string& a) { Operator *Operator::instantiate(std::string op, std::string param_str) { std::string op_ = utils::string::tolower(op); std::unique_ptr param(new RunTimeString()); - param->appendText(param_str); + param->append(param_str); IF_MATCH(beginswith) { return new BeginsWith(std::move(param)); } IF_MATCH(contains) { return new Contains(std::move(param)); } diff --git a/src/operators/operator.h b/src/operators/operator.h index 523b9209c4..a45e2c2684 100644 --- a/src/operators/operator.h +++ b/src/operators/operator.h @@ -24,6 +24,7 @@ #include "modsecurity/rule.h" #include "modsecurity/rule_message.h" #include "src/run_time_string.h" +#include "modsecurity/string_view.hpp" namespace modsecurity { namespace operators { @@ -107,27 +108,18 @@ class Operator { return true; } - virtual std::string resolveMatchMessage(Transaction *t, - std::string key, std::string value); - - bool evaluateInternal(Transaction *t, const std::string& a); - bool evaluateInternal(Transaction *t, RuleWithActions *rule, - const std::string& a); - bool evaluateInternal(Transaction *t, RuleWithActions *rule, - const std::string& a, std::shared_ptr ruleMessage); + bool evaluateInternal(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view& a, + RuleMessage *ruleMessage); + virtual bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage); - virtual bool evaluate(Transaction *transaction, const std::string &str); - virtual bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str) { - return evaluate(transaction, str); - } - virtual bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { - return evaluate(transaction, str); - } - static void logOffset(std::shared_ptr ruleMessage, int offset, int len) { + static void logOffset(RuleMessage *ruleMessage, int offset, int len) { if (ruleMessage) { ruleMessage->m_reference.append("o" + std::to_string(offset) + "," @@ -135,6 +127,10 @@ class Operator { } } + virtual std::string resolveMatchMessage(Transaction *t, + const VariableValue *v); + + std::string m_match_message; bool m_negation; std::string m_op; diff --git a/src/operators/pm.cc b/src/operators/pm.cc index 8c747ed301..09887834a6 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -28,6 +28,8 @@ #include "src/operators/operator.h" #include "src/utils/acmp.h" #include "src/utils/string.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { @@ -81,9 +83,11 @@ void Pm::postOrderTraversal(acmp_btree_node_t *node) { } -bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, std::shared_ptr ruleMessage) { - int rc; +bool Pm::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { + int rc = -1; ACMPT pt; pt.parser = m_p; pt.ptr = NULL; @@ -91,7 +95,7 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, #ifdef MODSEC_MUTEX_ON_PM pthread_mutex_lock(&m_lock); #endif - rc = acmp_process_quick(&pt, &match, input.c_str(), input.length()); + rc = acmp_process_quick(&pt, &match, str.c_str(), str.length()); #ifdef MODSEC_MUTEX_ON_PM pthread_mutex_unlock(&m_lock); #endif @@ -101,7 +105,7 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, logOffset(ruleMessage, rc - match_.size() + 1, match_.size()); transaction->m_matched.push_back(match_); - if (rule && rule->hasCaptureAction()) { + if (rule && rule->hasCapture()) { transaction->m_collections.m_tx_collection->storeOrUpdateFirst("0", match_); ms_dbg_a(transaction, 7, "Added pm match TX.0: " + \ diff --git a/src/operators/pm.h b/src/operators/pm.h index 0c2e58f3b8..604cbba736 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -41,9 +41,11 @@ class Pm : public Operator { m_p = acmp_create(0); } ~Pm(); - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, - std::shared_ptr ruleMessage) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/pm_from_file.cc b/src/operators/pm_from_file.cc index 46d00c1032..53f326958a 100644 --- a/src/operators/pm_from_file.cc +++ b/src/operators/pm_from_file.cc @@ -56,7 +56,7 @@ bool PmFromFile::init(const std::string &config, std::string *error) { iss = new std::stringstream(client.content); } else { std::string err; - std::string resource = utils::find_resource(m_param, config, &err); + std::string resource = utils::find_resource(m_param, config.c_str(), &err); iss = new std::ifstream(resource, std::ios::in); if (((std::ifstream *)iss)->is_open() == false) { diff --git a/src/operators/rbl.cc b/src/operators/rbl.cc index 6753435f65..c756051bd6 100644 --- a/src/operators/rbl.cc +++ b/src/operators/rbl.cc @@ -25,6 +25,8 @@ #include "modsecurity/rules_set.h" #include "src/operators/operator.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { @@ -200,11 +202,12 @@ void Rbl::furtherInfo(struct sockaddr_in *sin, const std::string &ipStr, } -bool Rbl::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& ipStr, - std::shared_ptr ruleMessage) { +bool Rbl::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { struct addrinfo *info = NULL; - std::string host = Rbl::mapIpToAddress(ipStr, t); + std::string host = Rbl::mapIpToAddress(str.c_str(), transaction); int rc = 0; if (host.empty()) { @@ -217,20 +220,20 @@ bool Rbl::evaluate(Transaction *t, RuleWithActions *rule, if (info != NULL) { freeaddrinfo(info); } - ms_dbg_a(t, 5, "RBL lookup of " + ipStr + " failed."); + ms_dbg_a(transaction, 5, "RBL lookup of " + str.to_string() + " failed."); return false; } struct sockaddr *addr = info->ai_addr; struct sockaddr_in *sin = (struct sockaddr_in *) addr; - furtherInfo(sin, ipStr, t, m_provider); + furtherInfo(sin, str.c_str(), transaction, m_provider); freeaddrinfo(info); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( - "0", std::string(ipStr)); - ms_dbg_a(t, 7, "Added RXL match TX.0: " + \ - std::string(ipStr)); + if (rule && transaction && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( + "0", std::string(str)); + ms_dbg_a(transaction, 7, "Added RXL match TX.0: " + \ + std::string(str)); } return true; diff --git a/src/operators/rbl.h b/src/operators/rbl.h index 4cc1fc25a2..bd81914275 100644 --- a/src/operators/rbl.h +++ b/src/operators/rbl.h @@ -76,9 +76,11 @@ class Rbl : public Operator { m_provider = RblProvider::httpbl; } } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; std::string mapIpToAddress(const std::string &ipStr, Transaction *trans) const; diff --git a/src/operators/rsub.cc b/src/operators/rsub.cc index 122ae70b5a..5b83f9c27c 100644 --- a/src/operators/rsub.cc +++ b/src/operators/rsub.cc @@ -23,7 +23,10 @@ namespace modsecurity { namespace operators { -bool Rsub::evaluate(Transaction *transaction, const std::string &str) { +bool Rsub::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { /** * @todo Implement the operator Rsub. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#rsub diff --git a/src/operators/rsub.h b/src/operators/rsub.h index ae4eb248f2..b2a9a59f38 100644 --- a/src/operators/rsub.h +++ b/src/operators/rsub.h @@ -32,7 +32,11 @@ class Rsub : public Operator { /** @ingroup ModSecurity_Operator */ explicit Rsub(std::unique_ptr param) : Operator("Rsub", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; diff --git a/src/operators/rx.cc b/src/operators/rx.cc index b4fc6ff4d7..5b79d23fec 100644 --- a/src/operators/rx.cc +++ b/src/operators/rx.cc @@ -22,13 +22,15 @@ #include "src/operators/operator.h" #include "modsecurity/rule.h" #include "modsecurity/rule_message.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { -bool Rx::init(const std::string &arg, std::string *error) { - if (m_string->m_containsMacro == false) { +bool Rx::init(const std::string &file, std::string *error) { + if (m_string->containsMacro() == false) { m_re = new Regex(m_param); } @@ -36,15 +38,17 @@ bool Rx::init(const std::string &arg, std::string *error) { } -bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool Rx::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + 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 { @@ -52,9 +56,9 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, } std::vector captures; - re->searchOneMatch(input, captures); - - if (rule && rule->hasCaptureAction() && transaction) { + // FIXME: searchOneMatch should accept string_view. + re->searchOneMatch(input.c_str(), captures); + if (rule && rule->hasCapture() && transaction) { for (const Utils::SMatchCapture& capture : captures) { const std::string capture_substring(input.substr(capture.m_offset,capture.m_length)); transaction->m_collections.m_tx_collection->storeOrUpdateFirst( @@ -69,11 +73,11 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule, logOffset(ruleMessage, capture.m_offset, capture.m_length); } - if (m_string->m_containsMacro) { + if (m_string->containsMacro()) { delete re; } - if (captures.size() > 0) { + if (!captures.empty()) { return true; } diff --git a/src/operators/rx.h b/src/operators/rx.h index 97cc12a3aa..481b393d36 100644 --- a/src/operators/rx.h +++ b/src/operators/rx.h @@ -43,17 +43,18 @@ 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; } } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; - bool init(const std::string &arg, std::string *error) override; + bool init(const std::string &file, std::string *error) override; private: Regex *m_re; diff --git a/src/operators/str_eq.cc b/src/operators/str_eq.cc index fd083f9003..4f6c30c39d 100644 --- a/src/operators/str_eq.cc +++ b/src/operators/str_eq.cc @@ -20,9 +20,12 @@ namespace modsecurity { namespace operators { -bool StrEq::evaluate(Transaction *transaction, const std::string &str) { +bool StrEq::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string pt(m_string->evaluate(transaction)); - return !pt.compare(str); + return !pt.compare(str.to_string()); } diff --git a/src/operators/str_eq.h b/src/operators/str_eq.h index 87e46bf586..29632172b3 100644 --- a/src/operators/str_eq.h +++ b/src/operators/str_eq.h @@ -34,7 +34,10 @@ class StrEq : public Operator { explicit StrEq(std::unique_ptr param) : Operator("StrEq", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/str_match.cc b/src/operators/str_match.cc index 2fae6f0f88..e4e56ffa31 100644 --- a/src/operators/str_match.cc +++ b/src/operators/str_match.cc @@ -24,9 +24,12 @@ namespace modsecurity { namespace operators { -bool StrMatch::evaluate(Transaction *transaction, const std::string &input) { +bool StrMatch::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { std::string p(m_string->evaluate(transaction)); - bool ret = input.find(p) != std::string::npos; + bool ret = str.find(p) != std::string::npos; return ret; } diff --git a/src/operators/str_match.h b/src/operators/str_match.h index c941117d34..1f16bbd440 100644 --- a/src/operators/str_match.h +++ b/src/operators/str_match.h @@ -34,7 +34,10 @@ class StrMatch : public Operator { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, const std::string &input) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/unconditional_match.cc b/src/operators/unconditional_match.cc index 54c6a43aa0..64010eff6c 100644 --- a/src/operators/unconditional_match.cc +++ b/src/operators/unconditional_match.cc @@ -19,7 +19,9 @@ namespace modsecurity { namespace operators { bool UnconditionalMatch::evaluate(Transaction *transaction, - const std::string &input) { + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { return true; } diff --git a/src/operators/unconditional_match.h b/src/operators/unconditional_match.h index 8a08d828a5..cbb2ce50ca 100644 --- a/src/operators/unconditional_match.h +++ b/src/operators/unconditional_match.h @@ -31,7 +31,10 @@ class UnconditionalMatch : public Operator { UnconditionalMatch() : Operator("UnconditionalMatch") { } - bool evaluate(Transaction *transaction, const std::string &exp) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/validate_byte_range.cc b/src/operators/validate_byte_range.cc index 47f67b5cd7..5687d6d492 100644 --- a/src/operators/validate_byte_range.cc +++ b/src/operators/validate_byte_range.cc @@ -23,7 +23,7 @@ namespace modsecurity { namespace operators { -bool ValidateByteRange::getRange(const std::string &rangeRepresentation, +bool ValidateByteRange::getRange(const bpstd::string_view &rangeRepresentation, std::string *error) { size_t pos = rangeRepresentation.find_first_of("-"); int start; @@ -31,9 +31,10 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation, if (pos == std::string::npos) { try { - start = std::stoi(rangeRepresentation); + start = std::stoi(rangeRepresentation.c_str()); } catch(...) { - error->assign("Not able to convert '" + rangeRepresentation + + error->assign("Not able to convert '" + \ + rangeRepresentation.to_string() + "' into a number"); return false; } @@ -42,19 +43,19 @@ bool ValidateByteRange::getRange(const std::string &rangeRepresentation, } try { - start = std::stoi(std::string(rangeRepresentation, 0, pos)); + start = std::stoi(std::string(rangeRepresentation.c_str(), 0, pos)); } catch (...) { error->assign("Not able to convert '" + - std::string(rangeRepresentation, 0, pos) + + std::string(rangeRepresentation.c_str(), 0, pos) + "' into a number"); return false; } try { - end = std::stoi(std::string(rangeRepresentation, pos + 1, + end = std::stoi(std::string(rangeRepresentation.c_str(), pos + 1, rangeRepresentation.length() - (pos + 1))); } catch (...) { - error->assign("Not able to convert '" + std::string(rangeRepresentation, + error->assign("Not able to convert '" + std::string(rangeRepresentation.c_str(), pos + 1, rangeRepresentation.length() - (pos + 1)) + "' into a number"); return false; @@ -110,16 +111,18 @@ bool ValidateByteRange::init(const std::string &file, } -bool ValidateByteRange::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, std::shared_ptr ruleMessage) { +bool ValidateByteRange::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { bool ret = true; size_t count = 0; - for (int i = 0; i < input.length(); i++) { - int x = (unsigned char) input.at(i); + for (int i = 0; i < str.length(); i++) { + int x = (unsigned char) str.at(i); if (!(table[x >> 3] & (1 << (x & 0x7)))) { // debug(9, "Value " + std::to_string(x) + " in " + - // input + " ouside range: " + param); + // str + " ouside range: " + param); logOffset(ruleMessage, i, 1); count++; } diff --git a/src/operators/validate_byte_range.h b/src/operators/validate_byte_range.h index d50f2997dc..244ac9c52d 100644 --- a/src/operators/validate_byte_range.h +++ b/src/operators/validate_byte_range.h @@ -37,10 +37,12 @@ class ValidateByteRange : public Operator { } ~ValidateByteRange() override { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, - std::shared_ptr ruleMessage) override; - bool getRange(const std::string &rangeRepresentation, std::string *error); + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + + bool getRange(const bpstd::string_view &rangeRepresentation, std::string *error); bool init(const std::string& file, std::string *error) override; private: std::vector ranges; diff --git a/src/operators/validate_dtd.cc b/src/operators/validate_dtd.cc index 144041c7a4..226d595ad8 100644 --- a/src/operators/validate_dtd.cc +++ b/src/operators/validate_dtd.cc @@ -43,25 +43,28 @@ bool ValidateDTD::init(const std::string &file, std::string *error) { } -bool ValidateDTD::evaluate(Transaction *t, const std::string &str) { +bool ValidateDTD::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { xmlValidCtxtPtr cvp; m_dtd = xmlParseDTD(NULL, (const xmlChar *)m_resource.c_str()); if (m_dtd == NULL) { std::string err = std::string("XML: Failed to load DTD: ") \ + m_resource; - ms_dbg_a(t, 4, err); + ms_dbg_a(transaction, 4, err); return true; } - if (t->m_xml->m_data.doc == NULL) { - ms_dbg_a(t, 4, "XML document tree could not "\ + if (transaction->m_xml->m_data.doc == NULL) { + ms_dbg_a(transaction, 4, "XML document tree could not "\ "be found for DTD validation."); return true; } - if (t->m_xml->m_data.well_formed != 1) { - ms_dbg_a(t, 4, "XML: DTD validation failed because " \ + if (transaction->m_xml->m_data.well_formed != 1) { + ms_dbg_a(transaction, 4, "XML: DTD validation failed because " \ "content is not well formed."); return true; } @@ -78,22 +81,23 @@ bool ValidateDTD::evaluate(Transaction *t, const std::string &str) { cvp = xmlNewValidCtxt(); if (cvp == NULL) { - ms_dbg_a(t, 4, "XML: Failed to create a validation context."); + ms_dbg_a(transaction, 4, + "XML: Failed to create a validation context."); return true; } /* Send validator errors/warnings to msr_log */ cvp->error = (xmlSchemaValidityErrorFunc)error_runtime; cvp->warning = (xmlSchemaValidityErrorFunc)warn_runtime; - cvp->userData = t; + cvp->userData = transaction; - if (!xmlValidateDtd(cvp, t->m_xml->m_data.doc, m_dtd)) { - ms_dbg_a(t, 4, "XML: DTD validation failed."); + if (!xmlValidateDtd(cvp, transaction->m_xml->m_data.doc, m_dtd)) { + ms_dbg_a(transaction, 4, "XML: DTD validation failed."); xmlFreeValidCtxt(cvp); return true; } - ms_dbg_a(t, 4, std::string("XML: Successfully validated " \ + ms_dbg_a(transaction, 4, std::string("XML: Successfully validated " \ "payload against DTD: ") + m_resource); xmlFreeValidCtxt(cvp); diff --git a/src/operators/validate_dtd.h b/src/operators/validate_dtd.h index 07e3af5dd4..944fa66a7c 100644 --- a/src/operators/validate_dtd.h +++ b/src/operators/validate_dtd.h @@ -46,7 +46,11 @@ class ValidateDTD : public Operator { } } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/validate_hash.cc b/src/operators/validate_hash.cc index 6d99c8c82c..652c79cf4b 100644 --- a/src/operators/validate_hash.cc +++ b/src/operators/validate_hash.cc @@ -22,7 +22,10 @@ namespace modsecurity { namespace operators { -bool ValidateHash::evaluate(Transaction *transaction, const std::string &str) { +bool ValidateHash::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { /** * @todo Implement the operator ValidateHash. * Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#validateHash diff --git a/src/operators/validate_hash.h b/src/operators/validate_hash.h index d462971b7b..0d811d228a 100644 --- a/src/operators/validate_hash.h +++ b/src/operators/validate_hash.h @@ -31,7 +31,11 @@ class ValidateHash : public Operator { /** @ingroup ModSecurity_Operator */ explicit ValidateHash(std::unique_ptr param) : Operator("ValidateHash", std::move(param)) { } - bool evaluate(Transaction *transaction, const std::string &str) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/operators/validate_schema.cc b/src/operators/validate_schema.cc index c66ffec8ef..65b471703d 100644 --- a/src/operators/validate_schema.cc +++ b/src/operators/validate_schema.cc @@ -39,8 +39,10 @@ bool ValidateSchema::init(const std::string &file, std::string *error) { } -bool ValidateSchema::evaluate(Transaction *t, - const std::string &str) { +bool ValidateSchema::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { int rc; m_parserCtx = xmlSchemaNewParserCtxt(m_resource.c_str()); @@ -52,7 +54,7 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); return true; } @@ -75,7 +77,7 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << " " << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); xmlSchemaFreeParserCtxt(m_parserCtx); return true; } @@ -86,23 +88,23 @@ bool ValidateSchema::evaluate(Transaction *t, if (m_err.empty() == false) { err << " " << m_err; } - ms_dbg_a(t, 4, err.str()); + ms_dbg_a(transaction, 4, err.str()); return true; } /* Send validator errors/warnings to msr_log */ xmlSchemaSetValidErrors(m_validCtx, (xmlSchemaValidityErrorFunc)error_runtime, - (xmlSchemaValidityWarningFunc)warn_runtime, t); + (xmlSchemaValidityWarningFunc)warn_runtime, transaction); - if (t->m_xml->m_data.doc == NULL) { - ms_dbg_a(t, 4, "XML document tree could not be found for " \ + if (transaction->m_xml->m_data.doc == NULL) { + ms_dbg_a(transaction, 4, "XML document tree could not be found for " \ "schema validation."); return true; } - if (t->m_xml->m_data.well_formed != 1) { - ms_dbg_a(t, 4, "XML: Schema validation failed because " \ + if (transaction->m_xml->m_data.well_formed != 1) { + ms_dbg_a(transaction, 4, "XML: Schema validation failed because " \ "content is not well formed."); return true; } @@ -116,15 +118,15 @@ bool ValidateSchema::evaluate(Transaction *t, } */ - rc = xmlSchemaValidateDoc(m_validCtx, t->m_xml->m_data.doc); + rc = xmlSchemaValidateDoc(m_validCtx, transaction->m_xml->m_data.doc); if (rc != 0) { - ms_dbg_a(t, 4, "XML: Schema validation failed."); + ms_dbg_a(transaction, 4, "XML: Schema validation failed."); xmlSchemaFree(m_schema); xmlSchemaFreeParserCtxt(m_parserCtx); return true; /* No match. */ } - ms_dbg_a(t, 4, "XML: Successfully validated payload against " \ + ms_dbg_a(transaction, 4, "XML: Successfully validated payload against " \ "Schema: " + m_resource); xmlSchemaFree(m_schema); xmlSchemaFreeParserCtxt(m_parserCtx); diff --git a/src/operators/validate_schema.h b/src/operators/validate_schema.h index 242a209b1e..1182773528 100644 --- a/src/operators/validate_schema.h +++ b/src/operators/validate_schema.h @@ -58,7 +58,11 @@ class ValidateSchema : public Operator { } } - bool evaluate(Transaction *transaction, const std::string &str) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + bool init(const std::string &file, std::string *error) override; diff --git a/src/operators/validate_url_encoding.cc b/src/operators/validate_url_encoding.cc index f04a5fa78c..b2b073b2ba 100644 --- a/src/operators/validate_url_encoding.cc +++ b/src/operators/validate_url_encoding.cc @@ -68,8 +68,10 @@ int ValidateUrlEncoding::validate_url_encoding(const char *input, } -bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, std::shared_ptr ruleMessage) { +bool ValidateUrlEncoding::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { size_t offset = 0; bool res = false; @@ -82,14 +84,15 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru case 1 : /* Encoding is valid */ if (transaction) { - ms_dbg_a(transaction, 7, "Valid URL Encoding at '" +input + "'"); + ms_dbg_a(transaction, 7, "Valid URL Encoding at '" + \ + input.to_string() + "'"); } res = false; break; case -2 : if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Non-hexadecimal " - "digits used at '" + input + "'"); + "digits used at '" + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; /* Invalid match. */ @@ -97,7 +100,7 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru case -3 : if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Not enough " \ - "characters at the end of input at '" + input + "'"); + "characters at the end of input at '" + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; /* Invalid match. */ @@ -107,7 +110,7 @@ bool ValidateUrlEncoding::evaluate(Transaction *transaction, RuleWithActions *ru if (transaction) { ms_dbg_a(transaction, 7, "Invalid URL Encoding: Internal " \ "Error (rc = " + std::to_string(rc) + ") at '" + - input + "'"); + input.to_string() + "'"); logOffset(ruleMessage, offset, input.size()); } res = true; diff --git a/src/operators/validate_url_encoding.h b/src/operators/validate_url_encoding.h index 80d61b96c9..b48ee78d73 100644 --- a/src/operators/validate_url_encoding.h +++ b/src/operators/validate_url_encoding.h @@ -31,9 +31,10 @@ class ValidateUrlEncoding : public Operator { ValidateUrlEncoding() : Operator("ValidateUrlEncoding") { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; static int validate_url_encoding(const char *input, uint64_t input_length, size_t *offset); diff --git a/src/operators/validate_utf8_encoding.cc b/src/operators/validate_utf8_encoding.cc index 9374116a9e..319d48f6dd 100644 --- a/src/operators/validate_utf8_encoding.cc +++ b/src/operators/validate_utf8_encoding.cc @@ -113,8 +113,10 @@ int ValidateUtf8Encoding::detect_utf8_character( return unicode_len; } -bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { +bool ValidateUtf8Encoding::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { unsigned int i, bytes_left; const char *str_c = str.c_str(); @@ -128,7 +130,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "not enough bytes in character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); } return true; @@ -137,7 +139,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "invalid byte value in character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -147,7 +149,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "overlong character detected " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -157,7 +159,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (transaction) { ms_dbg_a(transaction, 8, "Invalid UTF-8 encoding: " "use of restricted character " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -166,7 +168,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r case UNICODE_ERROR_DECODING_ERROR : if (transaction) { ms_dbg_a(transaction, 8, "Error validating UTF-8 decoding " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } @@ -177,7 +179,7 @@ bool ValidateUtf8Encoding::evaluate(Transaction *transaction, RuleWithActions *r if (rc <= 0) { if (transaction) { ms_dbg_a(transaction, 8, "Internal error during UTF-8 validation " - "at " + str + ". [offset \"" + + "at " + str.to_string() + ". [offset \"" + std::to_string(i) + "\"]"); logOffset(ruleMessage, i, str.size()); } diff --git a/src/operators/validate_utf8_encoding.h b/src/operators/validate_utf8_encoding.h index e01c19a225..49ae82947a 100644 --- a/src/operators/validate_utf8_encoding.h +++ b/src/operators/validate_utf8_encoding.h @@ -38,9 +38,10 @@ class ValidateUtf8Encoding : public Operator { ValidateUtf8Encoding() : Operator("ValidateUtf8Encoding") { } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; static int detect_utf8_character(const unsigned char *p_read, unsigned int length); diff --git a/src/operators/verify_cc.cc b/src/operators/verify_cc.cc index 2976bd28df..3acab21354 100644 --- a/src/operators/verify_cc.cc +++ b/src/operators/verify_cc.cc @@ -21,6 +21,8 @@ #include #include "src/operators/operator.h" +#include "src/rule_with_actions.h" + #if PCRE_HAVE_JIT #define pcre_study_opt PCRE_STUDY_JIT_COMPILE @@ -117,8 +119,10 @@ bool VerifyCC::init(const std::string ¶m2, std::string *error) { } -bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& i, std::shared_ptr ruleMessage) { +bool VerifyCC::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &i, + RuleMessage *ruleMessage) { int offset = 0; int target_length = i.length(); @@ -137,18 +141,18 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule, return false; } if (ret > 0) { - match = std::string(i, ovector[0], ovector[1] - ovector[0]); + match = std::string(i.to_string(), ovector[0], ovector[1] - ovector[0]); int is_cc = luhnVerify(match.c_str(), match.size()); if (is_cc) { - if (t) { - if (rule && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + if (transaction) { + if (rule && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(match)); - ms_dbg_a(t, 7, "Added VerifyCC match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifyCC match TX.0: " + \ std::string(match)); } - ms_dbg_a(t, 9, "CC# match \"" + m_param + - "\" at " + i + ". [offset " + + ms_dbg_a(transaction, 9, "CC# match \"" + m_param + + "\" at " + i.to_string() + ". [offset " + std::to_string(offset) + "]"); } return true; diff --git a/src/operators/verify_cc.h b/src/operators/verify_cc.h index ee97f2b4b9..e14c756671 100644 --- a/src/operators/verify_cc.h +++ b/src/operators/verify_cc.h @@ -35,10 +35,13 @@ class VerifyCC : public Operator { m_pce(NULL) { } ~VerifyCC(); - bool evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; bool init(const std::string ¶m, std::string *error) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; + private: pcre *m_pc; pcre_extra *m_pce; diff --git a/src/operators/verify_cpf.cc b/src/operators/verify_cpf.cc index 0ec49ac479..fe2e51e620 100644 --- a/src/operators/verify_cpf.cc +++ b/src/operators/verify_cpf.cc @@ -19,6 +19,8 @@ #include #include "src/operators/operator.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { @@ -108,8 +110,10 @@ bool VerifyCPF::verify(const char *cpfnumber, int len) { } -bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool VerifyCPF::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::list matches; bool is_cpf = false; int i; @@ -119,15 +123,15 @@ bool VerifyCPF::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_cpf == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & m : matches) { is_cpf = verify(m.str().c_str(), m.str().size()); if (is_cpf) { logOffset(ruleMessage, m.offset(), m.str().size()); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + if (rule && transaction && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", m.str()); - ms_dbg_a(t, 7, "Added VerifyCPF match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifyCPF match TX.0: " + \ m.str()); } diff --git a/src/operators/verify_cpf.h b/src/operators/verify_cpf.h index c5b0dfa593..0b5e8b3db6 100644 --- a/src/operators/verify_cpf.h +++ b/src/operators/verify_cpf.h @@ -46,9 +46,10 @@ class VerifyCPF : public Operator { bool operator=(const VerifyCPF &a) = delete; VerifyCPF(const VerifyCPF &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; bool verify(const char *ssnumber, int len); diff --git a/src/operators/verify_ssn.cc b/src/operators/verify_ssn.cc index 00b0c5c201..79e35cfaec 100644 --- a/src/operators/verify_ssn.cc +++ b/src/operators/verify_ssn.cc @@ -20,6 +20,8 @@ #include #include "src/operators/operator.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace operators { @@ -110,8 +112,10 @@ bool VerifySSN::verify(const char *ssnumber, int len) { } -bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool VerifySSN::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) { std::list matches; bool is_ssn = false; int i; @@ -121,15 +125,15 @@ bool VerifySSN::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_ssn == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & j : matches) { is_ssn = verify(j.str().c_str(), j.str().size()); if (is_ssn) { logOffset(ruleMessage, j.offset(), j.str().size()); - if (rule && t && rule->hasCaptureAction()) { - t->m_collections.m_tx_collection->storeOrUpdateFirst( + if (rule && transaction && rule->hasCapture()) { + transaction->m_collections.m_tx_collection->storeOrUpdateFirst( "0", j.str()); - ms_dbg_a(t, 7, "Added VerifySSN match TX.0: " + \ + ms_dbg_a(transaction, 7, "Added VerifySSN match TX.0: " + \ j.str()); } diff --git a/src/operators/verify_ssn.h b/src/operators/verify_ssn.h index 86f3341344..55c5cb12f0 100644 --- a/src/operators/verify_ssn.h +++ b/src/operators/verify_ssn.h @@ -46,9 +46,10 @@ class VerifySSN : public Operator { bool operator=(const VerifySSN &a) = delete; VerifySSN(const VerifySSN &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; diff --git a/src/operators/verify_svnr.cc b/src/operators/verify_svnr.cc index 248e6b4ec1..908500cff4 100644 --- a/src/operators/verify_svnr.cc +++ b/src/operators/verify_svnr.cc @@ -9,6 +9,7 @@ #include "modsecurity/rule_message.h" #include "modsecurity/rules_set_properties.h" +#include "src/rule_with_actions.h" namespace modsecurity { namespace operators { @@ -77,8 +78,10 @@ bool VerifySVNR::verify(const char *svnrnumber, int len) { } -bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule, - const std::string& input, std::shared_ptr ruleMessage) { +bool VerifySVNR::evaluate(Transaction *t, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage* ruleMessage) { std::list matches; bool is_svnr = false; int i; @@ -88,13 +91,13 @@ bool VerifySVNR::evaluate(Transaction *t, RuleWithActions *rule, } for (i = 0; i < input.size() - 1 && is_svnr == false; i++) { - matches = m_re->searchAll(input.substr(i, input.size())); + matches = m_re->searchAll(input.substr(i, input.size()).to_string()); for (const auto & j : matches) { is_svnr = verify(j.str().c_str(), j.str().size()); if (is_svnr) { logOffset(ruleMessage, j.offset(), j.str().size()); - if (rule && t && rule->hasCaptureAction()) { + if (rule && t && rule->hasCapture()) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", j.str()); ms_dbg_a(t, 7, "Added VerifySVNR match TX.0: " + \ diff --git a/src/operators/verify_svnr.h b/src/operators/verify_svnr.h index 6fe9df9afb..5a9511fc81 100644 --- a/src/operators/verify_svnr.h +++ b/src/operators/verify_svnr.h @@ -32,9 +32,10 @@ class VerifySVNR : public Operator { bool operator=(const VerifySVNR &a) = delete; VerifySVNR(const VerifySVNR &a) = delete; - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string& input, - std::shared_ptr ruleMessage) override; + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; bool verify(const char *ssnumber, int len); diff --git a/src/operators/within.cc b/src/operators/within.cc index f83f53a718..bb74392129 100644 --- a/src/operators/within.cc +++ b/src/operators/within.cc @@ -24,8 +24,10 @@ namespace modsecurity { namespace operators { -bool Within::evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) { +bool Within::evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &str, + RuleMessage *ruleMessage) { bool res = false; size_t pos = 0; std::string paramTarget(m_string->evaluate(transaction)); @@ -34,7 +36,7 @@ bool Within::evaluate(Transaction *transaction, RuleWithActions *rule, return true; } - pos = paramTarget.find(str); + pos = paramTarget.find(str.c_str()); res = pos != std::string::npos; if (res) { logOffset(ruleMessage, pos, str.size()); diff --git a/src/operators/within.h b/src/operators/within.h index 1a03aa687c..81f371b10c 100644 --- a/src/operators/within.h +++ b/src/operators/within.h @@ -33,8 +33,11 @@ class Within : public Operator { : Operator("Within", std::move(param)) { m_couldContainsMacro = true; } - bool evaluate(Transaction *transaction, RuleWithActions *rule, - const std::string &str, std::shared_ptr ruleMessage) override; + + bool evaluate(Transaction *transaction, + const RuleWithActions *rule, + const bpstd::string_view &input, + RuleMessage *ruleMessage) override; }; } // namespace operators diff --git a/src/parser/driver.cc b/src/parser/driver.cc index 6e97ae0f04..acb7d6b886 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -18,7 +18,7 @@ #include "modsecurity/rules_set_properties.h" #include "src/parser/seclang-parser.hh" #include "modsecurity/audit_log.h" -#include "modsecurity/rule_marker.h" +#include "src/rule_marker.h" using modsecurity::audit_log::AuditLog; using modsecurity::RuleWithOperator; @@ -81,16 +81,95 @@ int Driver::addSecRule(std::unique_ptr r) { } /* is it a chained rule? */ - if (m_lastRule != nullptr && m_lastRule->isChained()) { + if (m_lastRule != nullptr && m_lastRule->hasChainAction()) { r->setPhase(m_lastRule->getPhase()); if (r->hasDisruptiveAction()) { m_parserError << "Disruptive actions can only be specified by"; m_parserError << " chain starter rules."; return false; } - m_lastRule->m_chainedRuleChild = std::move(r); - m_lastRule->m_chainedRuleChild->m_chainedRuleParent = m_lastRule; - m_lastRule = m_lastRule->m_chainedRuleChild.get(); + + m_lastRule->setChainedNext(std::move(r)); + m_lastRule->getChainedNext()->setChainedParent(m_lastRule); + m_lastRule = m_lastRule->getChainedNext(); + + /* Lets set all meta-data to the first rule */ + RuleWithActions *firstRule = m_lastRule; + if (!firstRule->hasChainAction()) { + while (firstRule->getChainedParent() != nullptr) { + if (firstRule->hasMessageAction()) { + firstRule->getChainedParent()->setMessageAction( + firstRule->getMessageAction() + ); + firstRule->setMessageAction(nullptr); + } + if (firstRule->hasLogDataAction()) { + firstRule->getChainedParent()->setLogDataAction( + firstRule->getLogDataAction() + ); + firstRule->setLogDataAction(nullptr); + } + if (firstRule->hasSeverity()) { + firstRule->getChainedParent()->setSeverity( + firstRule->getSeverity() + ); + } + if (firstRule->hasRevision()) { + firstRule->getChainedParent()->setRevision( + firstRule->getRevision() + ); + } + if (firstRule->hasVersion()) { + firstRule->getChainedParent()->setVersion( + firstRule->getVersion() + ); + } + if (firstRule->hasAccuracy()) { + firstRule->getChainedParent()->setAccuracy( + firstRule->getAccuracy() + ); + } + if (firstRule->hasMaturity()) { + firstRule->getChainedParent()->setMaturity( + firstRule->getMaturity() + ); + } + + if (firstRule->hasTags()) { + firstRule->getChainedParent()->setTags( + firstRule->getTags() + ); + firstRule->clearTags(); + } + + /* disruptive can only be set on the first rule + if (firstRule->hasDisruptiveAction()) { + firstRule->getChainedParent()->setDisruptiveAction( + firstRule->getDisruptiveAction() + ); + firstRule->setDisruptiveAction(nullptr); + } + */ + + firstRule->getChainedParent()->setBlock( + firstRule->hasBlock() + ); + firstRule->getChainedParent()->setLog( + firstRule->hasLog() + ); + firstRule->getChainedParent()->setNoLog( + firstRule->hasNoLog() + ); + firstRule->getChainedParent()->setAuditLog( + firstRule->hasAuditLog() + ); + firstRule->getChainedParent()->setNoAuditLog( + firstRule->hasNoAuditLog() + ); + firstRule = firstRule->getChainedParent(); + } + } + return true; } @@ -99,26 +178,15 @@ int Driver::addSecRule(std::unique_ptr r) { * Checking if the rule has an ID and also checking if this ID is not used * by other rule */ - if (rule->m_ruleId == 0) { + if (rule->getId() == 0) { m_parserError << "Rules must have an ID. File: "; m_parserError << rule->getFileName() << " at line: "; m_parserError << std::to_string(rule->getLineNumber()) << std::endl; return false; } - for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) { - Rules *rules = m_rulesSetPhases[i]; - for (int j = 0; j < rules->size(); j++) { - RuleWithOperator *lr = dynamic_cast(rules->at(j).get()); - if (lr && lr->m_ruleId == rule->m_ruleId) { - m_parserError << "Rule id: " << std::to_string(rule->m_ruleId) \ - << " is duplicated" << std::endl; - return false; - } - } - } - m_lastRule = rule.get(); + m_rulesSetPhases.insert(rule); return true; diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc index 5dbda16ff9..fca05dd5d1 100644 --- a/src/parser/seclang-parser.cc +++ b/src/parser/seclang-parser.cc @@ -42,7 +42,7 @@ // Unqualified %code blocks. -#line 324 "seclang-parser.yy" +#line 327 "seclang-parser.yy" #include "src/parser/driver.h" @@ -1314,7 +1314,7 @@ namespace yy { // User initialization code. -#line 317 "seclang-parser.yy" +#line 320 "seclang-parser.yy" { // Initialize the initial location. yyla.location.begin.filename = yyla.location.end.filename = new std::string(driver.file); @@ -1685,7 +1685,7 @@ namespace yy { switch (yyn) { case 2: // input: "end of file" -#line 709 "seclang-parser.yy" +#line 712 "seclang-parser.yy" { return 0; } @@ -1693,7 +1693,7 @@ namespace yy { break; case 6: // audit_log: "CONFIG_DIR_AUDIT_DIR_MOD" -#line 722 "seclang-parser.yy" +#line 725 "seclang-parser.yy" { driver.m_auditLog->setStorageDirMode(strtol(yystack_[0].value.as < std::string > ().c_str(), NULL, 8)); } @@ -1701,7 +1701,7 @@ namespace yy { break; case 7: // audit_log: "CONFIG_DIR_AUDIT_DIR" -#line 728 "seclang-parser.yy" +#line 731 "seclang-parser.yy" { driver.m_auditLog->setStorageDir(yystack_[0].value.as < std::string > ()); } @@ -1709,7 +1709,7 @@ namespace yy { break; case 8: // audit_log: "CONFIG_DIR_AUDIT_ENG" "CONFIG_VALUE_RELEVANT_ONLY" -#line 734 "seclang-parser.yy" +#line 737 "seclang-parser.yy" { driver.m_auditLog->setStatus(modsecurity::audit_log::AuditLog::RelevantOnlyAuditLogStatus); } @@ -1717,7 +1717,7 @@ namespace yy { break; case 9: // audit_log: "CONFIG_DIR_AUDIT_ENG" "CONFIG_VALUE_OFF" -#line 738 "seclang-parser.yy" +#line 741 "seclang-parser.yy" { driver.m_auditLog->setStatus(modsecurity::audit_log::AuditLog::OffAuditLogStatus); } @@ -1725,7 +1725,7 @@ namespace yy { break; case 10: // audit_log: "CONFIG_DIR_AUDIT_ENG" "CONFIG_VALUE_ON" -#line 742 "seclang-parser.yy" +#line 745 "seclang-parser.yy" { driver.m_auditLog->setStatus(modsecurity::audit_log::AuditLog::OnAuditLogStatus); } @@ -1733,7 +1733,7 @@ namespace yy { break; case 11: // audit_log: "CONFIG_DIR_AUDIT_FLE_MOD" -#line 748 "seclang-parser.yy" +#line 751 "seclang-parser.yy" { driver.m_auditLog->setFileMode(strtol(yystack_[0].value.as < std::string > ().c_str(), NULL, 8)); } @@ -1741,7 +1741,7 @@ namespace yy { break; case 12: // audit_log: "CONFIG_DIR_AUDIT_LOG2" -#line 754 "seclang-parser.yy" +#line 757 "seclang-parser.yy" { driver.m_auditLog->setFilePath2(yystack_[0].value.as < std::string > ()); } @@ -1749,7 +1749,7 @@ namespace yy { break; case 13: // audit_log: "CONFIG_DIR_AUDIT_LOG_P" -#line 760 "seclang-parser.yy" +#line 763 "seclang-parser.yy" { driver.m_auditLog->setParts(yystack_[0].value.as < std::string > ()); } @@ -1757,7 +1757,7 @@ namespace yy { break; case 14: // audit_log: "CONFIG_DIR_AUDIT_LOG" -#line 766 "seclang-parser.yy" +#line 769 "seclang-parser.yy" { driver.m_auditLog->setFilePath1(yystack_[0].value.as < std::string > ()); } @@ -1765,7 +1765,7 @@ namespace yy { break; case 15: // audit_log: CONFIG_DIR_AUDIT_LOG_FMT JSON -#line 771 "seclang-parser.yy" +#line 774 "seclang-parser.yy" { driver.m_auditLog->setFormat(modsecurity::audit_log::AuditLog::JSONAuditLogFormat); } @@ -1773,7 +1773,7 @@ namespace yy { break; case 16: // audit_log: CONFIG_DIR_AUDIT_LOG_FMT NATIVE -#line 776 "seclang-parser.yy" +#line 779 "seclang-parser.yy" { driver.m_auditLog->setFormat(modsecurity::audit_log::AuditLog::NativeAuditLogFormat); } @@ -1781,7 +1781,7 @@ namespace yy { break; case 17: // audit_log: "CONFIG_DIR_AUDIT_STS" -#line 782 "seclang-parser.yy" +#line 785 "seclang-parser.yy" { std::string relevant_status(yystack_[0].value.as < std::string > ()); driver.m_auditLog->setRelevantStatus(relevant_status); @@ -1790,7 +1790,7 @@ namespace yy { break; case 18: // audit_log: "CONFIG_DIR_AUDIT_TPE" "CONFIG_VALUE_SERIAL" -#line 789 "seclang-parser.yy" +#line 792 "seclang-parser.yy" { driver.m_auditLog->setType(modsecurity::audit_log::AuditLog::SerialAuditLogType); } @@ -1798,7 +1798,7 @@ namespace yy { break; case 19: // audit_log: "CONFIG_DIR_AUDIT_TPE" "CONFIG_VALUE_PARALLEL" -#line 793 "seclang-parser.yy" +#line 796 "seclang-parser.yy" { driver.m_auditLog->setType(modsecurity::audit_log::AuditLog::ParallelAuditLogType); } @@ -1806,7 +1806,7 @@ namespace yy { break; case 20: // audit_log: "CONFIG_DIR_AUDIT_TPE" "CONFIG_VALUE_HTTPS" -#line 797 "seclang-parser.yy" +#line 800 "seclang-parser.yy" { driver.m_auditLog->setType(modsecurity::audit_log::AuditLog::HttpsAuditLogType); } @@ -1814,7 +1814,7 @@ namespace yy { break; case 21: // audit_log: "CONFIG_UPDLOAD_KEEP_FILES" "CONFIG_VALUE_ON" -#line 803 "seclang-parser.yy" +#line 806 "seclang-parser.yy" { driver.m_uploadKeepFiles = modsecurity::RulesSetProperties::TrueConfigBoolean; } @@ -1822,7 +1822,7 @@ namespace yy { break; case 22: // audit_log: "CONFIG_UPDLOAD_KEEP_FILES" "CONFIG_VALUE_OFF" -#line 807 "seclang-parser.yy" +#line 810 "seclang-parser.yy" { driver.m_uploadKeepFiles = modsecurity::RulesSetProperties::FalseConfigBoolean; } @@ -1830,7 +1830,7 @@ namespace yy { break; case 23: // audit_log: "CONFIG_UPDLOAD_KEEP_FILES" "CONFIG_VALUE_RELEVANT_ONLY" -#line 811 "seclang-parser.yy" +#line 814 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecUploadKeepFiles RelevantOnly is not currently supported. Accepted values are On or Off"); YYERROR; @@ -1839,7 +1839,7 @@ namespace yy { break; case 24: // audit_log: "CONFIG_UPLOAD_FILE_LIMIT" -#line 816 "seclang-parser.yy" +#line 819 "seclang-parser.yy" { driver.m_uploadFileLimit.m_set = true; driver.m_uploadFileLimit.m_value = strtol(yystack_[0].value.as < std::string > ().c_str(), NULL, 10); @@ -1848,7 +1848,7 @@ namespace yy { break; case 25: // audit_log: "CONFIG_UPLOAD_FILE_MODE" -#line 821 "seclang-parser.yy" +#line 824 "seclang-parser.yy" { driver.m_uploadFileMode.m_set = true; driver.m_uploadFileMode.m_value = strtol(yystack_[0].value.as < std::string > ().c_str(), NULL, 8); @@ -1857,7 +1857,7 @@ namespace yy { break; case 26: // audit_log: "CONFIG_UPLOAD_DIR" -#line 826 "seclang-parser.yy" +#line 829 "seclang-parser.yy" { driver.m_uploadDirectory.m_set = true; driver.m_uploadDirectory.m_value = yystack_[0].value.as < std::string > (); @@ -1866,7 +1866,7 @@ namespace yy { break; case 27: // audit_log: "CONFIG_UPDLOAD_SAVE_TMP_FILES" "CONFIG_VALUE_ON" -#line 831 "seclang-parser.yy" +#line 834 "seclang-parser.yy" { driver.m_tmpSaveUploadedFiles = modsecurity::RulesSetProperties::TrueConfigBoolean; } @@ -1874,7 +1874,7 @@ namespace yy { break; case 28: // audit_log: "CONFIG_UPDLOAD_SAVE_TMP_FILES" "CONFIG_VALUE_OFF" -#line 835 "seclang-parser.yy" +#line 838 "seclang-parser.yy" { driver.m_tmpSaveUploadedFiles = modsecurity::RulesSetProperties::FalseConfigBoolean; } @@ -1882,7 +1882,7 @@ namespace yy { break; case 29: // actions: "QUOTATION_MARK" actions_may_quoted "QUOTATION_MARK" -#line 842 "seclang-parser.yy" +#line 845 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[1].value.as < std::unique_ptr > > > ()); } @@ -1890,7 +1890,7 @@ namespace yy { break; case 30: // actions: actions_may_quoted -#line 846 "seclang-parser.yy" +#line 849 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); } @@ -1898,7 +1898,7 @@ namespace yy { break; case 31: // actions_may_quoted: actions_may_quoted "," act -#line 853 "seclang-parser.yy" +#line 856 "seclang-parser.yy" { ACTION_INIT(yystack_[0].value.as < std::unique_ptr > (), yystack_[3].location) yystack_[2].value.as < std::unique_ptr > > > ()->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); @@ -1908,7 +1908,7 @@ namespace yy { break; case 32: // actions_may_quoted: act -#line 859 "seclang-parser.yy" +#line 862 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); ACTION_INIT(yystack_[0].value.as < std::unique_ptr > (), yystack_[1].location) @@ -1919,7 +1919,7 @@ namespace yy { break; case 33: // op: op_before_init -#line 869 "seclang-parser.yy" +#line 872 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > () = std::move(yystack_[0].value.as < std::unique_ptr > ()); std::string error; @@ -1932,7 +1932,7 @@ namespace yy { break; case 34: // op: "NOT" op_before_init -#line 878 "seclang-parser.yy" +#line 881 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > () = std::move(yystack_[0].value.as < std::unique_ptr > ()); yylhs.value.as < std::unique_ptr > ()->m_negation = true; @@ -1946,7 +1946,7 @@ namespace yy { break; case 35: // op: run_time_string -#line 888 "seclang-parser.yy" +#line 891 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Rx(std::move(yystack_[0].value.as < std::unique_ptr > ()))); std::string error; @@ -1959,7 +1959,7 @@ namespace yy { break; case 36: // op: "NOT" run_time_string -#line 897 "seclang-parser.yy" +#line 900 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Rx(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yylhs.value.as < std::unique_ptr > ()->m_negation = true; @@ -1973,7 +1973,7 @@ namespace yy { break; case 37: // op_before_init: "OPERATOR_UNCONDITIONAL_MATCH" -#line 910 "seclang-parser.yy" +#line 913 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::UnconditionalMatch()); } @@ -1981,7 +1981,7 @@ namespace yy { break; case 38: // op_before_init: "OPERATOR_DETECT_SQLI" -#line 914 "seclang-parser.yy" +#line 917 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::DetectSQLi()); } @@ -1989,7 +1989,7 @@ namespace yy { break; case 39: // op_before_init: "OPERATOR_DETECT_XSS" -#line 918 "seclang-parser.yy" +#line 921 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::DetectXSS()); } @@ -1997,7 +1997,7 @@ namespace yy { break; case 40: // op_before_init: "OPERATOR_VALIDATE_URL_ENCODING" -#line 922 "seclang-parser.yy" +#line 925 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ValidateUrlEncoding()); } @@ -2005,7 +2005,7 @@ namespace yy { break; case 41: // op_before_init: "OPERATOR_VALIDATE_UTF8_ENCODING" -#line 926 "seclang-parser.yy" +#line 929 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ValidateUtf8Encoding()); } @@ -2013,7 +2013,7 @@ namespace yy { break; case 42: // op_before_init: "OPERATOR_INSPECT_FILE" run_time_string -#line 930 "seclang-parser.yy" +#line 933 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::InspectFile(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2021,7 +2021,7 @@ namespace yy { break; case 43: // op_before_init: "OPERATOR_FUZZY_HASH" run_time_string -#line 934 "seclang-parser.yy" +#line 937 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::FuzzyHash(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2029,7 +2029,7 @@ namespace yy { break; case 44: // op_before_init: "OPERATOR_VALIDATE_BYTE_RANGE" run_time_string -#line 938 "seclang-parser.yy" +#line 941 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ValidateByteRange(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2037,7 +2037,7 @@ namespace yy { break; case 45: // op_before_init: "OPERATOR_VALIDATE_DTD" run_time_string -#line 942 "seclang-parser.yy" +#line 945 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ValidateDTD(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2045,7 +2045,7 @@ namespace yy { break; case 46: // op_before_init: "OPERATOR_VALIDATE_HASH" run_time_string -#line 946 "seclang-parser.yy" +#line 949 "seclang-parser.yy" { /* $$ = new operators::ValidateHash($1); */ OPERATOR_NOT_SUPPORTED("ValidateHash", yystack_[2].location); @@ -2054,7 +2054,7 @@ namespace yy { break; case 47: // op_before_init: "OPERATOR_VALIDATE_SCHEMA" run_time_string -#line 951 "seclang-parser.yy" +#line 954 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ValidateSchema(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2062,7 +2062,7 @@ namespace yy { break; case 48: // op_before_init: "OPERATOR_VERIFY_CC" run_time_string -#line 955 "seclang-parser.yy" +#line 958 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::VerifyCC(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2070,7 +2070,7 @@ namespace yy { break; case 49: // op_before_init: "OPERATOR_VERIFY_CPF" run_time_string -#line 959 "seclang-parser.yy" +#line 962 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::VerifyCPF(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2078,7 +2078,7 @@ namespace yy { break; case 50: // op_before_init: "OPERATOR_VERIFY_SSN" run_time_string -#line 963 "seclang-parser.yy" +#line 966 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::VerifySSN(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2086,7 +2086,7 @@ namespace yy { break; case 51: // op_before_init: "OPERATOR_VERIFY_SVNR" run_time_string -#line 967 "seclang-parser.yy" +#line 970 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::VerifySVNR(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2094,7 +2094,7 @@ namespace yy { break; case 52: // op_before_init: "OPERATOR_GSB_LOOKUP" run_time_string -#line 971 "seclang-parser.yy" +#line 974 "seclang-parser.yy" { /* $$ = new operators::GsbLookup($1); */ OPERATOR_NOT_SUPPORTED("GsbLookup", yystack_[2].location); @@ -2103,7 +2103,7 @@ namespace yy { break; case 53: // op_before_init: "OPERATOR_RSUB" run_time_string -#line 976 "seclang-parser.yy" +#line 979 "seclang-parser.yy" { /* $$ = new operators::Rsub($1); */ OPERATOR_NOT_SUPPORTED("Rsub", yystack_[2].location); @@ -2112,7 +2112,7 @@ namespace yy { break; case 54: // op_before_init: "OPERATOR_WITHIN" run_time_string -#line 981 "seclang-parser.yy" +#line 984 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Within(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2120,7 +2120,7 @@ namespace yy { break; case 55: // op_before_init: "OPERATOR_CONTAINS_WORD" run_time_string -#line 985 "seclang-parser.yy" +#line 988 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::ContainsWord(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2128,7 +2128,7 @@ namespace yy { break; case 56: // op_before_init: "OPERATOR_CONTAINS" run_time_string -#line 989 "seclang-parser.yy" +#line 992 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Contains(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2136,7 +2136,7 @@ namespace yy { break; case 57: // op_before_init: "OPERATOR_ENDS_WITH" run_time_string -#line 993 "seclang-parser.yy" +#line 996 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::EndsWith(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2144,7 +2144,7 @@ namespace yy { break; case 58: // op_before_init: "OPERATOR_EQ" run_time_string -#line 997 "seclang-parser.yy" +#line 1000 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Eq(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2152,7 +2152,7 @@ namespace yy { break; case 59: // op_before_init: "OPERATOR_GE" run_time_string -#line 1001 "seclang-parser.yy" +#line 1004 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Ge(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2160,7 +2160,7 @@ namespace yy { break; case 60: // op_before_init: "OPERATOR_GT" run_time_string -#line 1005 "seclang-parser.yy" +#line 1008 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Gt(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2168,7 +2168,7 @@ namespace yy { break; case 61: // op_before_init: "OPERATOR_IP_MATCH_FROM_FILE" run_time_string -#line 1009 "seclang-parser.yy" +#line 1012 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::IpMatchF(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2176,7 +2176,7 @@ namespace yy { break; case 62: // op_before_init: "OPERATOR_IP_MATCH" run_time_string -#line 1013 "seclang-parser.yy" +#line 1016 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::IpMatch(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2184,7 +2184,7 @@ namespace yy { break; case 63: // op_before_init: "OPERATOR_LE" run_time_string -#line 1017 "seclang-parser.yy" +#line 1020 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Le(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2192,7 +2192,7 @@ namespace yy { break; case 64: // op_before_init: "OPERATOR_LT" run_time_string -#line 1021 "seclang-parser.yy" +#line 1024 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Lt(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2200,7 +2200,7 @@ namespace yy { break; case 65: // op_before_init: "OPERATOR_PM_FROM_FILE" run_time_string -#line 1025 "seclang-parser.yy" +#line 1028 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::PmFromFile(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2208,7 +2208,7 @@ namespace yy { break; case 66: // op_before_init: "OPERATOR_PM" run_time_string -#line 1029 "seclang-parser.yy" +#line 1032 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Pm(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2216,7 +2216,7 @@ namespace yy { break; case 67: // op_before_init: "OPERATOR_RBL" run_time_string -#line 1033 "seclang-parser.yy" +#line 1036 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Rbl(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2224,7 +2224,7 @@ namespace yy { break; case 68: // op_before_init: "OPERATOR_RX" run_time_string -#line 1037 "seclang-parser.yy" +#line 1040 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::Rx(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2232,7 +2232,7 @@ namespace yy { break; case 69: // op_before_init: "OPERATOR_STR_EQ" run_time_string -#line 1041 "seclang-parser.yy" +#line 1044 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::StrEq(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2240,7 +2240,7 @@ namespace yy { break; case 70: // op_before_init: "OPERATOR_STR_MATCH" run_time_string -#line 1045 "seclang-parser.yy" +#line 1048 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::StrMatch(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2248,7 +2248,7 @@ namespace yy { break; case 71: // op_before_init: "OPERATOR_BEGINS_WITH" run_time_string -#line 1049 "seclang-parser.yy" +#line 1052 "seclang-parser.yy" { OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::BeginsWith(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } @@ -2256,7 +2256,7 @@ namespace yy { break; case 72: // op_before_init: "OPERATOR_GEOLOOKUP" -#line 1053 "seclang-parser.yy" +#line 1056 "seclang-parser.yy" { #if defined(WITH_GEOIP) or defined(WITH_MAXMIND) OPERATOR_CONTAINER(yylhs.value.as < std::unique_ptr > (), new operators::GeoLookup()); @@ -2271,15 +2271,17 @@ namespace yy { break; case 74: // expression: "DIRECTIVE" variables op actions -#line 1068 "seclang-parser.yy" +#line 1071 "seclang-parser.yy" { - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } variables::Variables *v = new variables::Variables(); @@ -2296,16 +2298,16 @@ namespace yy { /* file name */ std::unique_ptr(new std::string(*yystack_[3].location.end.filename)), /* line number */ yystack_[3].location.end.line )); - + // TODO: filename should be a shared_ptr. if (driver.addSecRule(std::move(rule)) == false) { YYERROR; } } -#line 2305 "seclang-parser.cc" +#line 2307 "seclang-parser.cc" break; case 75: // expression: "DIRECTIVE" variables op -#line 1098 "seclang-parser.yy" +#line 1103 "seclang-parser.yy" { variables::Variables *v = new variables::Variables(); for (auto &i : *yystack_[1].value.as < std::unique_ptr > > > ().get()) { @@ -2324,19 +2326,21 @@ namespace yy { YYERROR; } } -#line 2328 "seclang-parser.cc" +#line 2330 "seclang-parser.cc" break; case 76: // expression: "CONFIG_DIR_SEC_ACTION" actions -#line 1117 "seclang-parser.yy" +#line 1122 "seclang-parser.yy" { - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } std::unique_ptr rule(new RuleUnconditional( @@ -2347,20 +2351,22 @@ namespace yy { )); driver.addSecAction(std::move(rule)); } -#line 2351 "seclang-parser.cc" +#line 2355 "seclang-parser.cc" break; case 77: // expression: "DIRECTIVE_SECRULESCRIPT" actions -#line 1136 "seclang-parser.yy" +#line 1143 "seclang-parser.yy" { std::string err; - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } std::unique_ptr r(new RuleScript( @@ -2379,52 +2385,46 @@ namespace yy { YYERROR; } } -#line 2383 "seclang-parser.cc" +#line 2389 "seclang-parser.cc" break; case 78: // expression: "CONFIG_DIR_SEC_DEFAULT_ACTION" actions -#line 1164 "seclang-parser.yy" +#line 1173 "seclang-parser.yy" { bool hasDisruptive = false; - std::vector *actions = new std::vector(); + std::vector> *actions = new std::vector>(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - actions->push_back(i.release()); + actions->push_back(std::move(i)); } - std::vector checkedActions; + std::vector> checkedActions; int definedPhase = -1; int secRuleDefinedPhase = -1; - for (actions::Action *a : *actions) { - actions::Phase *phase = dynamic_cast(a); - if (a->isDisruptive() == true && dynamic_cast(a) == NULL) { + for (auto &a : *actions) { + actions::Phase *phase = dynamic_cast(a.get()); + if (dynamic_cast(a.get()) != NULL + && dynamic_cast(a.get()) == NULL) { hasDisruptive = true; } if (phase != NULL) { - definedPhase = phase->m_phase; - secRuleDefinedPhase = phase->m_secRulesPhase; + definedPhase = phase->getPhase(); + secRuleDefinedPhase = phase->getSecRulePhase(); delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { - actions::transformations::None *none = dynamic_cast(a); - if (none != NULL) { - driver.error(yystack_[2].location, "The transformation none is not suitable to be part of the SecDefaultActions"); - YYERROR; - } + } else if (dynamic_cast(a.get()) + && !dynamic_cast(a.get())) { checkedActions.push_back(a); } else { - driver.error(yystack_[2].location, "The action '" + *a->m_name.get() + "' is not suitable to be part of the SecDefaultActions"); + driver.error(yystack_[2].location, "The action '" + *a->getName() + "' is not suitable to be part of the SecDefaultActions"); YYERROR; } } if (definedPhase == -1) { definedPhase = modsecurity::Phases::RequestHeadersPhase; } - if (hasDisruptive == false) { driver.error(yystack_[2].location, "SecDefaultAction must specify a disruptive action."); YYERROR; } - - if (!driver.m_defaultActions[definedPhase].empty()) { + if (!driver.m_rulesSetPhases[definedPhase]->m_defaultActions.empty()) { std::stringstream ss; ss << "SecDefaultActions can only be placed once per phase and configuration context. Phase "; ss << secRuleDefinedPhase; @@ -2432,86 +2432,88 @@ namespace yy { driver.error(yystack_[2].location, ss.str()); YYERROR; } - - for (actions::Action *a : checkedActions) { - driver.m_defaultActions[definedPhase].push_back( - std::unique_ptr(a)); + for (auto &a : checkedActions) { + if (dynamic_cast(a.get())) { + driver.m_rulesSetPhases[definedPhase]->m_defaultTransformations.push_back( + std::dynamic_pointer_cast(a)); + } else { + driver.m_rulesSetPhases[definedPhase]->m_defaultActions.push_back(a); + } } - - delete actions; + //delete actions; } -#line 2444 "seclang-parser.cc" +#line 2446 "seclang-parser.cc" break; case 79: // expression: "CONFIG_DIR_SEC_MARKER" -#line 1221 "seclang-parser.yy" +#line 1226 "seclang-parser.yy" { driver.addSecMarker(modsecurity::utils::string::removeBracketsIfNeeded(yystack_[0].value.as < std::string > ()), /* file name */ std::unique_ptr(new std::string(*yystack_[0].location.end.filename)), /* line number */ yystack_[0].location.end.line ); } -#line 2455 "seclang-parser.cc" +#line 2457 "seclang-parser.cc" break; case 80: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_OFF" -#line 1228 "seclang-parser.yy" +#line 1233 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DisabledRuleEngine; } -#line 2463 "seclang-parser.cc" +#line 2465 "seclang-parser.cc" break; case 81: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_ON" -#line 1232 "seclang-parser.yy" +#line 1237 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::EnabledRuleEngine; } -#line 2471 "seclang-parser.cc" +#line 2473 "seclang-parser.cc" break; case 82: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_DETC" -#line 1236 "seclang-parser.yy" +#line 1241 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DetectionOnlyRuleEngine; } -#line 2479 "seclang-parser.cc" +#line 2481 "seclang-parser.cc" break; case 83: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_ON" -#line 1240 "seclang-parser.yy" +#line 1245 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2487 "seclang-parser.cc" +#line 2489 "seclang-parser.cc" break; case 84: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_OFF" -#line 1244 "seclang-parser.yy" +#line 1249 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2495 "seclang-parser.cc" +#line 2497 "seclang-parser.cc" break; case 85: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_ON" -#line 1248 "seclang-parser.yy" +#line 1253 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2503 "seclang-parser.cc" +#line 2505 "seclang-parser.cc" break; case 86: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_OFF" -#line 1252 "seclang-parser.yy" +#line 1257 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2511 "seclang-parser.cc" +#line 2513 "seclang-parser.cc" break; case 87: // expression: "CONFIG_SEC_ARGUMENT_SEPARATOR" -#line 1256 "seclang-parser.yy" +#line 1261 "seclang-parser.yy" { if (yystack_[0].value.as < std::string > ().length() != 1) { driver.error(yystack_[1].location, "Argument separator should be set to a single character."); @@ -2520,259 +2522,259 @@ namespace yy { driver.m_secArgumentSeparator.m_value = yystack_[0].value.as < std::string > (); driver.m_secArgumentSeparator.m_set = true; } -#line 2524 "seclang-parser.cc" +#line 2526 "seclang-parser.cc" break; case 88: // expression: "CONFIG_COMPONENT_SIG" -#line 1265 "seclang-parser.yy" +#line 1270 "seclang-parser.yy" { driver.m_components.push_back(yystack_[0].value.as < std::string > ()); } -#line 2532 "seclang-parser.cc" +#line 2534 "seclang-parser.cc" break; case 89: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_ON" -#line 1269 "seclang-parser.yy" +#line 1274 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecConnEngine is not yet supported."); YYERROR; } -#line 2541 "seclang-parser.cc" +#line 2543 "seclang-parser.cc" break; case 90: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_OFF" -#line 1274 "seclang-parser.yy" +#line 1279 "seclang-parser.yy" { } -#line 2548 "seclang-parser.cc" +#line 2550 "seclang-parser.cc" break; case 91: // expression: "CONFIG_SEC_WEB_APP_ID" -#line 1277 "seclang-parser.yy" +#line 1282 "seclang-parser.yy" { driver.m_secWebAppId.m_value = yystack_[0].value.as < std::string > (); driver.m_secWebAppId.m_set = true; } -#line 2557 "seclang-parser.cc" +#line 2559 "seclang-parser.cc" break; case 92: // expression: "CONFIG_SEC_SERVER_SIG" -#line 1282 "seclang-parser.yy" +#line 1287 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecServerSignature is not supported."); YYERROR; } -#line 2566 "seclang-parser.cc" +#line 2568 "seclang-parser.cc" break; case 93: // expression: "CONFIG_SEC_CACHE_TRANSFORMATIONS" -#line 1287 "seclang-parser.yy" +#line 1292 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCacheTransformations is not supported."); YYERROR; } -#line 2575 "seclang-parser.cc" +#line 2577 "seclang-parser.cc" break; case 94: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_ON" -#line 1292 "seclang-parser.yy" +#line 1297 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecDisableBackendCompression is not supported."); YYERROR; } -#line 2584 "seclang-parser.cc" +#line 2586 "seclang-parser.cc" break; case 95: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_OFF" -#line 1297 "seclang-parser.yy" +#line 1302 "seclang-parser.yy" { } -#line 2591 "seclang-parser.cc" +#line 2593 "seclang-parser.cc" break; case 96: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_ON" -#line 1300 "seclang-parser.yy" +#line 1305 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecContentInjection is not yet supported."); YYERROR; } -#line 2600 "seclang-parser.cc" +#line 2602 "seclang-parser.cc" break; case 97: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_OFF" -#line 1305 "seclang-parser.yy" +#line 1310 "seclang-parser.yy" { } -#line 2607 "seclang-parser.cc" +#line 2609 "seclang-parser.cc" break; case 98: // expression: "CONFIG_SEC_CHROOT_DIR" -#line 1308 "seclang-parser.yy" +#line 1313 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecChrootDir is not supported."); YYERROR; } -#line 2616 "seclang-parser.cc" +#line 2618 "seclang-parser.cc" break; case 99: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_ON" -#line 1313 "seclang-parser.yy" +#line 1318 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecHashEngine is not yet supported."); YYERROR; } -#line 2625 "seclang-parser.cc" +#line 2627 "seclang-parser.cc" break; case 100: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_OFF" -#line 1318 "seclang-parser.yy" +#line 1323 "seclang-parser.yy" { } -#line 2632 "seclang-parser.cc" +#line 2634 "seclang-parser.cc" break; case 101: // expression: "CONFIG_SEC_HASH_KEY" -#line 1321 "seclang-parser.yy" +#line 1326 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashKey is not yet supported."); YYERROR; } -#line 2641 "seclang-parser.cc" +#line 2643 "seclang-parser.cc" break; case 102: // expression: "CONFIG_SEC_HASH_PARAM" -#line 1326 "seclang-parser.yy" +#line 1331 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashParam is not yet supported."); YYERROR; } -#line 2650 "seclang-parser.cc" +#line 2652 "seclang-parser.cc" break; case 103: // expression: "CONFIG_SEC_HASH_METHOD_RX" -#line 1331 "seclang-parser.yy" +#line 1336 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodRx is not yet supported."); YYERROR; } -#line 2659 "seclang-parser.cc" +#line 2661 "seclang-parser.cc" break; case 104: // expression: "CONFIG_SEC_HASH_METHOD_PM" -#line 1336 "seclang-parser.yy" +#line 1341 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodPm is not yet supported."); YYERROR; } -#line 2668 "seclang-parser.cc" +#line 2670 "seclang-parser.cc" break; case 105: // expression: "CONFIG_DIR_GSB_DB" -#line 1341 "seclang-parser.yy" +#line 1346 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGsbLookupDb is not supported."); YYERROR; } -#line 2677 "seclang-parser.cc" +#line 2679 "seclang-parser.cc" break; case 106: // expression: "CONFIG_SEC_GUARDIAN_LOG" -#line 1346 "seclang-parser.yy" +#line 1351 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGuardianLog is not supported."); YYERROR; } -#line 2686 "seclang-parser.cc" +#line 2688 "seclang-parser.cc" break; case 107: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_ON" -#line 1351 "seclang-parser.yy" +#line 1356 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecInterceptOnError is not yet supported."); YYERROR; } -#line 2695 "seclang-parser.cc" +#line 2697 "seclang-parser.cc" break; case 108: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_OFF" -#line 1356 "seclang-parser.yy" +#line 1361 "seclang-parser.yy" { } -#line 2702 "seclang-parser.cc" +#line 2704 "seclang-parser.cc" break; case 109: // expression: "CONFIG_SEC_CONN_R_STATE_LIMIT" -#line 1359 "seclang-parser.yy" +#line 1364 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnReadStateLimit is not yet supported."); YYERROR; } -#line 2711 "seclang-parser.cc" +#line 2713 "seclang-parser.cc" break; case 110: // expression: "CONFIG_SEC_CONN_W_STATE_LIMIT" -#line 1364 "seclang-parser.yy" +#line 1369 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnWriteStateLimit is not yet supported."); YYERROR; } -#line 2720 "seclang-parser.cc" +#line 2722 "seclang-parser.cc" break; case 111: // expression: "CONFIG_SEC_SENSOR_ID" -#line 1369 "seclang-parser.yy" +#line 1374 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecSensorId is not yet supported."); YYERROR; } -#line 2729 "seclang-parser.cc" +#line 2731 "seclang-parser.cc" break; case 112: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_ON" -#line 1374 "seclang-parser.yy" +#line 1379 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecRuleInheritance is not yet supported."); YYERROR; } -#line 2738 "seclang-parser.cc" +#line 2740 "seclang-parser.cc" break; case 113: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_OFF" -#line 1379 "seclang-parser.yy" +#line 1384 "seclang-parser.yy" { } -#line 2745 "seclang-parser.cc" +#line 2747 "seclang-parser.cc" break; case 114: // expression: "CONFIG_SEC_RULE_PERF_TIME" -#line 1382 "seclang-parser.yy" +#line 1387 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecRulePerfTime is not yet supported."); YYERROR; } -#line 2754 "seclang-parser.cc" +#line 2756 "seclang-parser.cc" break; case 115: // expression: "CONFIG_SEC_STREAM_IN_BODY_INSPECTION" -#line 1387 "seclang-parser.yy" +#line 1392 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamInBodyInspection is not supported."); YYERROR; } -#line 2763 "seclang-parser.cc" +#line 2765 "seclang-parser.cc" break; case 116: // expression: "CONFIG_SEC_STREAM_OUT_BODY_INSPECTION" -#line 1392 "seclang-parser.yy" +#line 1397 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamOutBodyInspection is not supported."); YYERROR; } -#line 2772 "seclang-parser.cc" +#line 2774 "seclang-parser.cc" break; case 117: // expression: "CONFIG_SEC_RULE_REMOVE_BY_ID" -#line 1397 "seclang-parser.yy" +#line 1402 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.load(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2785,11 +2787,11 @@ namespace yy { YYERROR; } } -#line 2789 "seclang-parser.cc" +#line 2791 "seclang-parser.cc" break; case 118: // expression: "CONFIG_SEC_RULE_REMOVE_BY_TAG" -#line 1410 "seclang-parser.yy" +#line 1415 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByTag(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2802,11 +2804,11 @@ namespace yy { YYERROR; } } -#line 2806 "seclang-parser.cc" +#line 2808 "seclang-parser.cc" break; case 119: // expression: "CONFIG_SEC_RULE_REMOVE_BY_MSG" -#line 1423 "seclang-parser.yy" +#line 1428 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByMsg(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2819,11 +2821,11 @@ namespace yy { YYERROR; } } -#line 2823 "seclang-parser.cc" +#line 2825 "seclang-parser.cc" break; case 120: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG" variables_pre_process -#line 1436 "seclang-parser.yy" +#line 1441 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByTag(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2836,11 +2838,11 @@ namespace yy { YYERROR; } } -#line 2840 "seclang-parser.cc" +#line 2842 "seclang-parser.cc" break; case 121: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG" variables_pre_process -#line 1449 "seclang-parser.yy" +#line 1454 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByMsg(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2853,17 +2855,17 @@ namespace yy { YYERROR; } } -#line 2857 "seclang-parser.cc" +#line 2859 "seclang-parser.cc" break; case 122: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID" variables_pre_process -#line 1462 "seclang-parser.yy" +#line 1467 "seclang-parser.yy" { std::string error; - double ruleId; - try { - ruleId = std::stod(yystack_[1].value.as < std::string > ()); - } catch (...) { + std::istringstream iss(yystack_[1].value.as < std::string > ()); + RuleId ruleId; + iss >> ruleId; + if (iss.fail()) { std::stringstream ss; ss << "SecRuleUpdateTargetById: failed to load:"; ss << "The input \"" + yystack_[1].value.as < std::string > () + "\" does not "; @@ -2883,17 +2885,17 @@ namespace yy { YYERROR; } } -#line 2887 "seclang-parser.cc" +#line 2889 "seclang-parser.cc" break; case 123: // expression: "CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID" actions -#line 1488 "seclang-parser.yy" +#line 1493 "seclang-parser.yy" { std::string error; - double ruleId; - try { - ruleId = std::stod(yystack_[1].value.as < std::string > ()); - } catch (...) { + std::istringstream iss(yystack_[1].value.as < std::string > ()); + RuleId ruleId; + iss >> ruleId; + if (iss.fail()) { std::stringstream ss; ss << "SecRuleUpdateActionById: failed to load:"; ss << "The input \"" + yystack_[1].value.as < std::string > () + "\" does not "; @@ -2914,11 +2916,11 @@ namespace yy { YYERROR; } } -#line 2918 "seclang-parser.cc" +#line 2920 "seclang-parser.cc" break; case 124: // expression: "CONFIG_DIR_DEBUG_LVL" -#line 1516 "seclang-parser.yy" +#line 1521 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { driver.m_debugLog->setDebugLogLevel(atoi(yystack_[0].value.as < std::string > ().c_str())); @@ -2930,11 +2932,11 @@ namespace yy { YYERROR; } } -#line 2934 "seclang-parser.cc" +#line 2936 "seclang-parser.cc" break; case 125: // expression: "CONFIG_DIR_DEBUG_LOG" -#line 1528 "seclang-parser.yy" +#line 1533 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { std::string error; @@ -2953,11 +2955,11 @@ namespace yy { YYERROR; } } -#line 2957 "seclang-parser.cc" +#line 2959 "seclang-parser.cc" break; case 126: // expression: "CONFIG_DIR_GEO_DB" -#line 1548 "seclang-parser.yy" +#line 1553 "seclang-parser.yy" { #if defined(WITH_GEOIP) or defined(WITH_MAXMIND) std::string err; @@ -2984,38 +2986,38 @@ namespace yy { YYERROR; #endif // WITH_GEOIP } -#line 2988 "seclang-parser.cc" +#line 2990 "seclang-parser.cc" break; case 127: // expression: "CONFIG_DIR_ARGS_LIMIT" -#line 1575 "seclang-parser.yy" +#line 1580 "seclang-parser.yy" { driver.m_argumentsLimit.m_set = true; driver.m_argumentsLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 2997 "seclang-parser.cc" +#line 2999 "seclang-parser.cc" break; case 128: // expression: "CONFIG_DIR_REQ_BODY_LIMIT" -#line 1581 "seclang-parser.yy" +#line 1586 "seclang-parser.yy" { driver.m_requestBodyLimit.m_set = true; driver.m_requestBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3006 "seclang-parser.cc" +#line 3008 "seclang-parser.cc" break; case 129: // expression: "CONFIG_DIR_REQ_BODY_NO_FILES_LIMIT" -#line 1586 "seclang-parser.yy" +#line 1591 "seclang-parser.yy" { driver.m_requestBodyNoFilesLimit.m_set = true; driver.m_requestBodyNoFilesLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3015 "seclang-parser.cc" +#line 3017 "seclang-parser.cc" break; case 130: // expression: "CONFIG_DIR_REQ_BODY_IN_MEMORY_LIMIT" -#line 1591 "seclang-parser.yy" +#line 1596 "seclang-parser.yy" { std::stringstream ss; ss << "As of ModSecurity version 3.0, SecRequestBodyInMemoryLimit is no longer "; @@ -3024,68 +3026,68 @@ namespace yy { driver.error(yystack_[1].location, ss.str()); YYERROR; } -#line 3028 "seclang-parser.cc" +#line 3030 "seclang-parser.cc" break; case 131: // expression: "CONFIG_DIR_RES_BODY_LIMIT" -#line 1600 "seclang-parser.yy" +#line 1605 "seclang-parser.yy" { driver.m_responseBodyLimit.m_set = true; driver.m_responseBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3037 "seclang-parser.cc" +#line 3039 "seclang-parser.cc" break; case 132: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1605 "seclang-parser.yy" +#line 1610 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3045 "seclang-parser.cc" +#line 3047 "seclang-parser.cc" break; case 133: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1609 "seclang-parser.yy" +#line 1614 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3053 "seclang-parser.cc" +#line 3055 "seclang-parser.cc" break; case 134: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1613 "seclang-parser.yy" +#line 1618 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3061 "seclang-parser.cc" +#line 3063 "seclang-parser.cc" break; case 135: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1617 "seclang-parser.yy" +#line 1622 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3069 "seclang-parser.cc" +#line 3071 "seclang-parser.cc" break; case 136: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_ABORT" -#line 1621 "seclang-parser.yy" +#line 1626 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction; } -#line 3077 "seclang-parser.cc" +#line 3079 "seclang-parser.cc" break; case 137: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_WARN" -#line 1625 "seclang-parser.yy" +#line 1630 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction; } -#line 3085 "seclang-parser.cc" +#line 3087 "seclang-parser.cc" break; case 140: // expression: "CONGIG_DIR_RESPONSE_BODY_MP" -#line 1639 "seclang-parser.yy" +#line 1644 "seclang-parser.yy" { std::istringstream buf(yystack_[0].value.as < std::string > ()); std::istream_iterator beg(buf), end; @@ -3097,37 +3099,37 @@ namespace yy { driver.m_responseBodyTypeToBeInspected.m_value.insert(*it); } } -#line 3101 "seclang-parser.cc" +#line 3103 "seclang-parser.cc" break; case 141: // expression: "CONGIG_DIR_RESPONSE_BODY_MP_CLEAR" -#line 1651 "seclang-parser.yy" +#line 1656 "seclang-parser.yy" { driver.m_responseBodyTypeToBeInspected.m_set = true; driver.m_responseBodyTypeToBeInspected.m_clear = true; driver.m_responseBodyTypeToBeInspected.m_value.clear(); } -#line 3111 "seclang-parser.cc" +#line 3113 "seclang-parser.cc" break; case 142: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_OFF" -#line 1657 "seclang-parser.yy" +#line 1662 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 3119 "seclang-parser.cc" +#line 3121 "seclang-parser.cc" break; case 143: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_ON" -#line 1661 "seclang-parser.yy" +#line 1666 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 3127 "seclang-parser.cc" +#line 3129 "seclang-parser.cc" break; case 144: // expression: "CONGIG_DIR_SEC_TMP_DIR" -#line 1665 "seclang-parser.yy" +#line 1670 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended std::stringstream ss; @@ -3138,31 +3140,31 @@ namespace yy { YYERROR; */ } -#line 3142 "seclang-parser.cc" +#line 3144 "seclang-parser.cc" break; case 147: // expression: "CONGIG_DIR_SEC_COOKIE_FORMAT" -#line 1686 "seclang-parser.yy" +#line 1691 "seclang-parser.yy" { if (atoi(yystack_[0].value.as < std::string > ().c_str()) == 1) { driver.error(yystack_[1].location, "SecCookieFormat 1 is not yet supported."); YYERROR; } } -#line 3153 "seclang-parser.cc" +#line 3155 "seclang-parser.cc" break; case 148: // expression: "CONFIG_SEC_COOKIEV0_SEPARATOR" -#line 1693 "seclang-parser.yy" +#line 1698 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCookieV0Separator is not yet supported."); YYERROR; } -#line 3162 "seclang-parser.cc" +#line 3164 "seclang-parser.cc" break; case 150: // expression: "CONFIG_DIR_UNICODE_MAP_FILE" -#line 1703 "seclang-parser.yy" +#line 1708 "seclang-parser.yy" { std::string error; std::vector param; @@ -3216,31 +3218,31 @@ namespace yy { } } -#line 3220 "seclang-parser.cc" +#line 3222 "seclang-parser.cc" break; case 151: // expression: "CONFIG_SEC_COLLECTION_TIMEOUT" -#line 1757 "seclang-parser.yy" +#line 1762 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default CRS installations with crs-setup.conf-recommended driver.error(@0, "SecCollectionTimeout is not yet supported."); YYERROR; */ } -#line 3231 "seclang-parser.cc" +#line 3233 "seclang-parser.cc" break; case 152: // expression: "CONFIG_SEC_HTTP_BLKEY" -#line 1764 "seclang-parser.yy" +#line 1769 "seclang-parser.yy" { driver.m_httpblKey.m_set = true; driver.m_httpblKey.m_value = yystack_[0].value.as < std::string > (); } -#line 3240 "seclang-parser.cc" +#line 3242 "seclang-parser.cc" break; case 153: // variables: variables_pre_process -#line 1772 "seclang-parser.yy" +#line 1777 "seclang-parser.yy" { std::unique_ptr > > originalList = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); std::unique_ptr>> newList(new std::vector>()); @@ -3274,2363 +3276,2362 @@ namespace yy { } yylhs.value.as < std::unique_ptr > > > () = std::move(newNewList); } -#line 3278 "seclang-parser.cc" +#line 3280 "seclang-parser.cc" break; case 154: // variables_pre_process: variables_may_be_quoted -#line 1809 "seclang-parser.yy" +#line 1814 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); } -#line 3286 "seclang-parser.cc" +#line 3288 "seclang-parser.cc" break; case 155: // variables_pre_process: "QUOTATION_MARK" variables_may_be_quoted "QUOTATION_MARK" -#line 1813 "seclang-parser.yy" +#line 1818 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[1].value.as < std::unique_ptr > > > ()); } -#line 3294 "seclang-parser.cc" +#line 3296 "seclang-parser.cc" break; case 156: // variables_may_be_quoted: variables_may_be_quoted PIPE var -#line 1820 "seclang-parser.yy" +#line 1825 "seclang-parser.yy" { yystack_[2].value.as < std::unique_ptr > > > ()->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[2].value.as < std::unique_ptr > > > ()); } -#line 3303 "seclang-parser.cc" +#line 3305 "seclang-parser.cc" break; case 157: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_EXCLUSION var -#line 1825 "seclang-parser.yy" +#line 1830 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3313 "seclang-parser.cc" +#line 3315 "seclang-parser.cc" break; case 158: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_COUNT var -#line 1831 "seclang-parser.yy" +#line 1836 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3323 "seclang-parser.cc" +#line 3325 "seclang-parser.cc" break; case 159: // variables_may_be_quoted: var -#line 1837 "seclang-parser.yy" +#line 1842 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); b->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3333 "seclang-parser.cc" +#line 3335 "seclang-parser.cc" break; case 160: // variables_may_be_quoted: VAR_EXCLUSION var -#line 1843 "seclang-parser.yy" +#line 1848 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3344 "seclang-parser.cc" +#line 3346 "seclang-parser.cc" break; case 161: // variables_may_be_quoted: VAR_COUNT var -#line 1850 "seclang-parser.yy" +#line 1855 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3355 "seclang-parser.cc" +#line 3357 "seclang-parser.cc" break; case 162: // var: VARIABLE_ARGS "Dictionary element" -#line 1860 "seclang-parser.yy" +#line 1865 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3363 "seclang-parser.cc" +#line 3365 "seclang-parser.cc" break; case 163: // var: VARIABLE_ARGS "Dictionary element, selected by regexp" -#line 1864 "seclang-parser.yy" +#line 1869 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3371 "seclang-parser.cc" +#line 3373 "seclang-parser.cc" break; case 164: // var: VARIABLE_ARGS -#line 1868 "seclang-parser.yy" +#line 1873 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_NoDictElement()); } -#line 3379 "seclang-parser.cc" +#line 3381 "seclang-parser.cc" break; case 165: // var: VARIABLE_ARGS_POST "Dictionary element" -#line 1872 "seclang-parser.yy" +#line 1877 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3387 "seclang-parser.cc" +#line 3389 "seclang-parser.cc" break; case 166: // var: VARIABLE_ARGS_POST "Dictionary element, selected by regexp" -#line 1876 "seclang-parser.yy" +#line 1881 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3395 "seclang-parser.cc" +#line 3397 "seclang-parser.cc" break; case 167: // var: VARIABLE_ARGS_POST -#line 1880 "seclang-parser.yy" +#line 1885 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_NoDictElement()); } -#line 3403 "seclang-parser.cc" +#line 3405 "seclang-parser.cc" break; case 168: // var: VARIABLE_ARGS_GET "Dictionary element" -#line 1884 "seclang-parser.yy" +#line 1889 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3411 "seclang-parser.cc" +#line 3413 "seclang-parser.cc" break; case 169: // var: VARIABLE_ARGS_GET "Dictionary element, selected by regexp" -#line 1888 "seclang-parser.yy" +#line 1893 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3419 "seclang-parser.cc" +#line 3421 "seclang-parser.cc" break; case 170: // var: VARIABLE_ARGS_GET -#line 1892 "seclang-parser.yy" +#line 1897 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_NoDictElement()); } -#line 3427 "seclang-parser.cc" +#line 3429 "seclang-parser.cc" break; case 171: // var: VARIABLE_FILES_SIZES "Dictionary element" -#line 1896 "seclang-parser.yy" +#line 1901 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3435 "seclang-parser.cc" +#line 3437 "seclang-parser.cc" break; case 172: // var: VARIABLE_FILES_SIZES "Dictionary element, selected by regexp" -#line 1900 "seclang-parser.yy" +#line 1905 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3443 "seclang-parser.cc" +#line 3445 "seclang-parser.cc" break; case 173: // var: VARIABLE_FILES_SIZES -#line 1904 "seclang-parser.yy" +#line 1909 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_NoDictElement()); } -#line 3451 "seclang-parser.cc" +#line 3453 "seclang-parser.cc" break; case 174: // var: VARIABLE_FILES_NAMES "Dictionary element" -#line 1908 "seclang-parser.yy" +#line 1913 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3459 "seclang-parser.cc" +#line 3461 "seclang-parser.cc" break; case 175: // var: VARIABLE_FILES_NAMES "Dictionary element, selected by regexp" -#line 1912 "seclang-parser.yy" +#line 1917 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3467 "seclang-parser.cc" +#line 3469 "seclang-parser.cc" break; case 176: // var: VARIABLE_FILES_NAMES -#line 1916 "seclang-parser.yy" +#line 1921 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_NoDictElement()); } -#line 3475 "seclang-parser.cc" +#line 3477 "seclang-parser.cc" break; case 177: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element" -#line 1920 "seclang-parser.yy" +#line 1925 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3483 "seclang-parser.cc" +#line 3485 "seclang-parser.cc" break; case 178: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element, selected by regexp" -#line 1924 "seclang-parser.yy" +#line 1929 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3491 "seclang-parser.cc" +#line 3493 "seclang-parser.cc" break; case 179: // var: VARIABLE_FILES_TMP_CONTENT -#line 1928 "seclang-parser.yy" +#line 1933 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_NoDictElement()); } -#line 3499 "seclang-parser.cc" +#line 3501 "seclang-parser.cc" break; case 180: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element" -#line 1932 "seclang-parser.yy" +#line 1937 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3507 "seclang-parser.cc" +#line 3509 "seclang-parser.cc" break; case 181: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element, selected by regexp" -#line 1936 "seclang-parser.yy" +#line 1941 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3515 "seclang-parser.cc" +#line 3517 "seclang-parser.cc" break; case 182: // var: VARIABLE_MULTIPART_FILENAME -#line 1940 "seclang-parser.yy" +#line 1945 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_NoDictElement()); } -#line 3523 "seclang-parser.cc" +#line 3525 "seclang-parser.cc" break; case 183: // var: VARIABLE_MULTIPART_NAME "Dictionary element" -#line 1944 "seclang-parser.yy" +#line 1949 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3531 "seclang-parser.cc" +#line 3533 "seclang-parser.cc" break; case 184: // var: VARIABLE_MULTIPART_NAME "Dictionary element, selected by regexp" -#line 1948 "seclang-parser.yy" +#line 1953 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3539 "seclang-parser.cc" +#line 3541 "seclang-parser.cc" break; case 185: // var: VARIABLE_MULTIPART_NAME -#line 1952 "seclang-parser.yy" +#line 1957 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_NoDictElement()); } -#line 3547 "seclang-parser.cc" +#line 3549 "seclang-parser.cc" break; case 186: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element" -#line 1956 "seclang-parser.yy" +#line 1961 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3555 "seclang-parser.cc" +#line 3557 "seclang-parser.cc" break; case 187: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element, selected by regexp" -#line 1960 "seclang-parser.yy" +#line 1965 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3563 "seclang-parser.cc" +#line 3565 "seclang-parser.cc" break; case 188: // var: VARIABLE_MATCHED_VARS_NAMES -#line 1964 "seclang-parser.yy" +#line 1969 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_NoDictElement()); } -#line 3571 "seclang-parser.cc" +#line 3573 "seclang-parser.cc" break; case 189: // var: VARIABLE_MATCHED_VARS "Dictionary element" -#line 1968 "seclang-parser.yy" +#line 1973 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3579 "seclang-parser.cc" +#line 3581 "seclang-parser.cc" break; case 190: // var: VARIABLE_MATCHED_VARS "Dictionary element, selected by regexp" -#line 1972 "seclang-parser.yy" +#line 1977 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3587 "seclang-parser.cc" +#line 3589 "seclang-parser.cc" break; case 191: // var: VARIABLE_MATCHED_VARS -#line 1976 "seclang-parser.yy" +#line 1981 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_NoDictElement()); } -#line 3595 "seclang-parser.cc" +#line 3597 "seclang-parser.cc" break; case 192: // var: VARIABLE_FILES "Dictionary element" -#line 1980 "seclang-parser.yy" +#line 1985 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3603 "seclang-parser.cc" +#line 3605 "seclang-parser.cc" break; case 193: // var: VARIABLE_FILES "Dictionary element, selected by regexp" -#line 1984 "seclang-parser.yy" +#line 1989 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3611 "seclang-parser.cc" +#line 3613 "seclang-parser.cc" break; case 194: // var: VARIABLE_FILES -#line 1988 "seclang-parser.yy" +#line 1993 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_NoDictElement()); } -#line 3619 "seclang-parser.cc" +#line 3621 "seclang-parser.cc" break; case 195: // var: VARIABLE_REQUEST_COOKIES "Dictionary element" -#line 1992 "seclang-parser.yy" +#line 1997 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3627 "seclang-parser.cc" +#line 3629 "seclang-parser.cc" break; case 196: // var: VARIABLE_REQUEST_COOKIES "Dictionary element, selected by regexp" -#line 1996 "seclang-parser.yy" +#line 2001 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3635 "seclang-parser.cc" +#line 3637 "seclang-parser.cc" break; case 197: // var: VARIABLE_REQUEST_COOKIES -#line 2000 "seclang-parser.yy" +#line 2005 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_NoDictElement()); } -#line 3643 "seclang-parser.cc" +#line 3645 "seclang-parser.cc" break; case 198: // var: VARIABLE_REQUEST_HEADERS "Dictionary element" -#line 2004 "seclang-parser.yy" +#line 2009 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3651 "seclang-parser.cc" +#line 3653 "seclang-parser.cc" break; case 199: // var: VARIABLE_REQUEST_HEADERS "Dictionary element, selected by regexp" -#line 2008 "seclang-parser.yy" +#line 2013 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3659 "seclang-parser.cc" +#line 3661 "seclang-parser.cc" break; case 200: // var: VARIABLE_REQUEST_HEADERS -#line 2012 "seclang-parser.yy" +#line 2017 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_NoDictElement()); } -#line 3667 "seclang-parser.cc" +#line 3669 "seclang-parser.cc" break; case 201: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element" -#line 2016 "seclang-parser.yy" +#line 2021 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3675 "seclang-parser.cc" +#line 3677 "seclang-parser.cc" break; case 202: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element, selected by regexp" -#line 2020 "seclang-parser.yy" +#line 2025 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3683 "seclang-parser.cc" +#line 3685 "seclang-parser.cc" break; case 203: // var: VARIABLE_RESPONSE_HEADERS -#line 2024 "seclang-parser.yy" +#line 2029 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_NoDictElement()); } -#line 3691 "seclang-parser.cc" +#line 3693 "seclang-parser.cc" break; case 204: // var: VARIABLE_GEO "Dictionary element" -#line 2028 "seclang-parser.yy" +#line 2033 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3699 "seclang-parser.cc" +#line 3701 "seclang-parser.cc" break; case 205: // var: VARIABLE_GEO "Dictionary element, selected by regexp" -#line 2032 "seclang-parser.yy" +#line 2037 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3707 "seclang-parser.cc" +#line 3709 "seclang-parser.cc" break; case 206: // var: VARIABLE_GEO -#line 2036 "seclang-parser.yy" +#line 2041 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_NoDictElement()); } -#line 3715 "seclang-parser.cc" +#line 3717 "seclang-parser.cc" break; case 207: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element" -#line 2040 "seclang-parser.yy" +#line 2045 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3723 "seclang-parser.cc" +#line 3725 "seclang-parser.cc" break; case 208: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element, selected by regexp" -#line 2044 "seclang-parser.yy" +#line 2049 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3731 "seclang-parser.cc" +#line 3733 "seclang-parser.cc" break; case 209: // var: VARIABLE_REQUEST_COOKIES_NAMES -#line 2048 "seclang-parser.yy" +#line 2053 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_NoDictElement()); } -#line 3739 "seclang-parser.cc" +#line 3741 "seclang-parser.cc" break; case 210: // var: VARIABLE_RULE "Dictionary element" -#line 2052 "seclang-parser.yy" +#line 2057 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3747 "seclang-parser.cc" +#line 3749 "seclang-parser.cc" break; case 211: // var: VARIABLE_RULE "Dictionary element, selected by regexp" -#line 2056 "seclang-parser.yy" +#line 2061 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3755 "seclang-parser.cc" +#line 3757 "seclang-parser.cc" break; case 212: // var: VARIABLE_RULE -#line 2060 "seclang-parser.yy" +#line 2065 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_NoDictElement()); } -#line 3763 "seclang-parser.cc" +#line 3765 "seclang-parser.cc" break; case 213: // var: "RUN_TIME_VAR_ENV" "Dictionary element" -#line 2064 "seclang-parser.yy" +#line 2069 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3771 "seclang-parser.cc" +#line 3773 "seclang-parser.cc" break; case 214: // var: "RUN_TIME_VAR_ENV" "Dictionary element, selected by regexp" -#line 2068 "seclang-parser.yy" +#line 2073 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3779 "seclang-parser.cc" +#line 3781 "seclang-parser.cc" break; case 215: // var: "RUN_TIME_VAR_ENV" -#line 2072 "seclang-parser.yy" +#line 2077 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV")); } -#line 3787 "seclang-parser.cc" +#line 3789 "seclang-parser.cc" break; case 216: // var: "RUN_TIME_VAR_XML" "Dictionary element" -#line 2076 "seclang-parser.yy" +#line 2081 "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 3795 "seclang-parser.cc" +#line 3797 "seclang-parser.cc" break; case 217: // var: "RUN_TIME_VAR_XML" "Dictionary element, selected by regexp" -#line 2080 "seclang-parser.yy" +#line 2085 "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 3803 "seclang-parser.cc" +#line 3805 "seclang-parser.cc" break; case 218: // var: "RUN_TIME_VAR_XML" -#line 2084 "seclang-parser.yy" +#line 2089 "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 3811 "seclang-parser.cc" +#line 3813 "seclang-parser.cc" break; case 219: // var: "FILES_TMPNAMES" "Dictionary element" -#line 2088 "seclang-parser.yy" +#line 2093 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3819 "seclang-parser.cc" +#line 3821 "seclang-parser.cc" break; case 220: // var: "FILES_TMPNAMES" "Dictionary element, selected by regexp" -#line 2092 "seclang-parser.yy" +#line 2097 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3827 "seclang-parser.cc" +#line 3829 "seclang-parser.cc" break; case 221: // var: "FILES_TMPNAMES" -#line 2096 "seclang-parser.yy" +#line 2101 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_NoDictElement()); } -#line 3835 "seclang-parser.cc" +#line 3837 "seclang-parser.cc" break; case 222: // var: "RESOURCE" run_time_string -#line 2100 "seclang-parser.yy" +#line 2105 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3843 "seclang-parser.cc" +#line 3845 "seclang-parser.cc" break; case 223: // var: "RESOURCE" "Dictionary element" -#line 2104 "seclang-parser.yy" +#line 2109 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3851 "seclang-parser.cc" +#line 3853 "seclang-parser.cc" break; case 224: // var: "RESOURCE" "Dictionary element, selected by regexp" -#line 2108 "seclang-parser.yy" +#line 2113 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3859 "seclang-parser.cc" +#line 3861 "seclang-parser.cc" break; case 225: // var: "RESOURCE" -#line 2112 "seclang-parser.yy" +#line 2117 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_NoDictElement()); } -#line 3867 "seclang-parser.cc" +#line 3869 "seclang-parser.cc" break; case 226: // var: "VARIABLE_IP" run_time_string -#line 2116 "seclang-parser.yy" +#line 2121 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3875 "seclang-parser.cc" +#line 3877 "seclang-parser.cc" break; case 227: // var: "VARIABLE_IP" "Dictionary element" -#line 2120 "seclang-parser.yy" +#line 2125 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3883 "seclang-parser.cc" +#line 3885 "seclang-parser.cc" break; case 228: // var: "VARIABLE_IP" "Dictionary element, selected by regexp" -#line 2124 "seclang-parser.yy" +#line 2129 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3891 "seclang-parser.cc" +#line 3893 "seclang-parser.cc" break; case 229: // var: "VARIABLE_IP" -#line 2128 "seclang-parser.yy" +#line 2133 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_NoDictElement()); } -#line 3899 "seclang-parser.cc" +#line 3901 "seclang-parser.cc" break; case 230: // var: "VARIABLE_GLOBAL" run_time_string -#line 2132 "seclang-parser.yy" +#line 2137 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3907 "seclang-parser.cc" +#line 3909 "seclang-parser.cc" break; case 231: // var: "VARIABLE_GLOBAL" "Dictionary element" -#line 2136 "seclang-parser.yy" +#line 2141 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3915 "seclang-parser.cc" +#line 3917 "seclang-parser.cc" break; case 232: // var: "VARIABLE_GLOBAL" "Dictionary element, selected by regexp" -#line 2140 "seclang-parser.yy" +#line 2145 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3923 "seclang-parser.cc" +#line 3925 "seclang-parser.cc" break; case 233: // var: "VARIABLE_GLOBAL" -#line 2144 "seclang-parser.yy" +#line 2149 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_NoDictElement()); } -#line 3931 "seclang-parser.cc" +#line 3933 "seclang-parser.cc" break; case 234: // var: "VARIABLE_USER" run_time_string -#line 2148 "seclang-parser.yy" +#line 2153 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3939 "seclang-parser.cc" +#line 3941 "seclang-parser.cc" break; case 235: // var: "VARIABLE_USER" "Dictionary element" -#line 2152 "seclang-parser.yy" +#line 2157 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3947 "seclang-parser.cc" +#line 3949 "seclang-parser.cc" break; case 236: // var: "VARIABLE_USER" "Dictionary element, selected by regexp" -#line 2156 "seclang-parser.yy" +#line 2161 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3955 "seclang-parser.cc" +#line 3957 "seclang-parser.cc" break; case 237: // var: "VARIABLE_USER" -#line 2160 "seclang-parser.yy" +#line 2165 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_NoDictElement()); } -#line 3963 "seclang-parser.cc" +#line 3965 "seclang-parser.cc" break; case 238: // var: "VARIABLE_TX" run_time_string -#line 2164 "seclang-parser.yy" +#line 2169 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3971 "seclang-parser.cc" +#line 3973 "seclang-parser.cc" break; case 239: // var: "VARIABLE_TX" "Dictionary element" -#line 2168 "seclang-parser.yy" +#line 2173 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3979 "seclang-parser.cc" +#line 3981 "seclang-parser.cc" break; case 240: // var: "VARIABLE_TX" "Dictionary element, selected by regexp" -#line 2172 "seclang-parser.yy" +#line 2177 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3987 "seclang-parser.cc" +#line 3989 "seclang-parser.cc" break; case 241: // var: "VARIABLE_TX" -#line 2176 "seclang-parser.yy" +#line 2181 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_NoDictElement()); } -#line 3995 "seclang-parser.cc" +#line 3997 "seclang-parser.cc" break; case 242: // var: "VARIABLE_SESSION" run_time_string -#line 2180 "seclang-parser.yy" +#line 2185 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4003 "seclang-parser.cc" +#line 4005 "seclang-parser.cc" break; case 243: // var: "VARIABLE_SESSION" "Dictionary element" -#line 2184 "seclang-parser.yy" +#line 2189 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4011 "seclang-parser.cc" +#line 4013 "seclang-parser.cc" break; case 244: // var: "VARIABLE_SESSION" "Dictionary element, selected by regexp" -#line 2188 "seclang-parser.yy" +#line 2193 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4019 "seclang-parser.cc" +#line 4021 "seclang-parser.cc" break; case 245: // var: "VARIABLE_SESSION" -#line 2192 "seclang-parser.yy" +#line 2197 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_NoDictElement()); } -#line 4027 "seclang-parser.cc" +#line 4029 "seclang-parser.cc" break; case 246: // var: "Variable ARGS_NAMES" "Dictionary element" -#line 2196 "seclang-parser.yy" +#line 2201 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4035 "seclang-parser.cc" +#line 4037 "seclang-parser.cc" break; case 247: // var: "Variable ARGS_NAMES" "Dictionary element, selected by regexp" -#line 2200 "seclang-parser.yy" +#line 2205 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4043 "seclang-parser.cc" +#line 4045 "seclang-parser.cc" break; case 248: // var: "Variable ARGS_NAMES" -#line 2204 "seclang-parser.yy" +#line 2209 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_NoDictElement()); } -#line 4051 "seclang-parser.cc" +#line 4053 "seclang-parser.cc" break; case 249: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element" -#line 2208 "seclang-parser.yy" +#line 2213 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4059 "seclang-parser.cc" +#line 4061 "seclang-parser.cc" break; case 250: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element, selected by regexp" -#line 2212 "seclang-parser.yy" +#line 2217 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4067 "seclang-parser.cc" +#line 4069 "seclang-parser.cc" break; case 251: // var: VARIABLE_ARGS_GET_NAMES -#line 2216 "seclang-parser.yy" +#line 2221 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_NoDictElement()); } -#line 4075 "seclang-parser.cc" +#line 4077 "seclang-parser.cc" break; case 252: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element" -#line 2221 "seclang-parser.yy" +#line 2226 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4083 "seclang-parser.cc" +#line 4085 "seclang-parser.cc" break; case 253: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element, selected by regexp" -#line 2225 "seclang-parser.yy" +#line 2230 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4091 "seclang-parser.cc" +#line 4093 "seclang-parser.cc" break; case 254: // var: VARIABLE_ARGS_POST_NAMES -#line 2229 "seclang-parser.yy" +#line 2234 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_NoDictElement()); } -#line 4099 "seclang-parser.cc" +#line 4101 "seclang-parser.cc" break; case 255: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element" -#line 2234 "seclang-parser.yy" +#line 2239 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4107 "seclang-parser.cc" +#line 4109 "seclang-parser.cc" break; case 256: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2238 "seclang-parser.yy" +#line 2243 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4115 "seclang-parser.cc" +#line 4117 "seclang-parser.cc" break; case 257: // var: VARIABLE_REQUEST_HEADERS_NAMES -#line 2242 "seclang-parser.yy" +#line 2247 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_NoDictElement()); } -#line 4123 "seclang-parser.cc" +#line 4125 "seclang-parser.cc" break; case 258: // var: VARIABLE_RESPONSE_CONTENT_TYPE -#line 2247 "seclang-parser.yy" +#line 2252 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentType()); } -#line 4131 "seclang-parser.cc" +#line 4133 "seclang-parser.cc" break; case 259: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element" -#line 2252 "seclang-parser.yy" +#line 2257 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4139 "seclang-parser.cc" +#line 4141 "seclang-parser.cc" break; case 260: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2256 "seclang-parser.yy" +#line 2261 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4147 "seclang-parser.cc" +#line 4149 "seclang-parser.cc" break; case 261: // var: VARIABLE_RESPONSE_HEADERS_NAMES -#line 2260 "seclang-parser.yy" +#line 2265 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_NoDictElement()); } -#line 4155 "seclang-parser.cc" +#line 4157 "seclang-parser.cc" break; case 262: // var: VARIABLE_ARGS_COMBINED_SIZE -#line 2264 "seclang-parser.yy" +#line 2269 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsCombinedSize()); } -#line 4163 "seclang-parser.cc" +#line 4165 "seclang-parser.cc" break; case 263: // var: "AUTH_TYPE" -#line 2268 "seclang-parser.yy" +#line 2273 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::AuthType()); } -#line 4171 "seclang-parser.cc" +#line 4173 "seclang-parser.cc" break; case 264: // var: "FILES_COMBINED_SIZE" -#line 2272 "seclang-parser.yy" +#line 2277 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesCombinedSize()); } -#line 4179 "seclang-parser.cc" +#line 4181 "seclang-parser.cc" break; case 265: // var: "FULL_REQUEST" -#line 2276 "seclang-parser.yy" +#line 2281 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequest()); } -#line 4187 "seclang-parser.cc" +#line 4189 "seclang-parser.cc" break; case 266: // var: "FULL_REQUEST_LENGTH" -#line 2280 "seclang-parser.yy" +#line 2285 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequestLength()); } -#line 4195 "seclang-parser.cc" +#line 4197 "seclang-parser.cc" break; case 267: // var: "INBOUND_DATA_ERROR" -#line 2284 "seclang-parser.yy" +#line 2289 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::InboundDataError()); } -#line 4203 "seclang-parser.cc" +#line 4205 "seclang-parser.cc" break; case 268: // var: "MATCHED_VAR" -#line 2288 "seclang-parser.yy" +#line 2293 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVar()); } -#line 4211 "seclang-parser.cc" +#line 4213 "seclang-parser.cc" break; case 269: // var: "MATCHED_VAR_NAME" -#line 2292 "seclang-parser.yy" +#line 2297 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarName()); } -#line 4219 "seclang-parser.cc" +#line 4221 "seclang-parser.cc" break; case 270: // var: VARIABLE_MULTIPART_BOUNDARY_QUOTED -#line 2296 "seclang-parser.yy" +#line 2301 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryQuoted()); } -#line 4227 "seclang-parser.cc" +#line 4229 "seclang-parser.cc" break; case 271: // var: VARIABLE_MULTIPART_BOUNDARY_WHITESPACE -#line 2300 "seclang-parser.yy" +#line 2305 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryWhiteSpace()); } -#line 4235 "seclang-parser.cc" +#line 4237 "seclang-parser.cc" break; case 272: // var: "MULTIPART_CRLF_LF_LINES" -#line 2304 "seclang-parser.yy" +#line 2309 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartCrlfLFLines()); } -#line 4243 "seclang-parser.cc" +#line 4245 "seclang-parser.cc" break; case 273: // var: "MULTIPART_DATA_AFTER" -#line 2308 "seclang-parser.yy" +#line 2313 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateAfter()); } -#line 4251 "seclang-parser.cc" +#line 4253 "seclang-parser.cc" break; case 274: // var: VARIABLE_MULTIPART_DATA_BEFORE -#line 2312 "seclang-parser.yy" +#line 2317 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateBefore()); } -#line 4259 "seclang-parser.cc" +#line 4261 "seclang-parser.cc" break; case 275: // var: "MULTIPART_FILE_LIMIT_EXCEEDED" -#line 2316 "seclang-parser.yy" +#line 2321 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartFileLimitExceeded()); } -#line 4267 "seclang-parser.cc" +#line 4269 "seclang-parser.cc" break; case 276: // var: "MULTIPART_HEADER_FOLDING" -#line 2320 "seclang-parser.yy" +#line 2325 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartHeaderFolding()); } -#line 4275 "seclang-parser.cc" +#line 4277 "seclang-parser.cc" break; case 277: // var: "MULTIPART_INVALID_HEADER_FOLDING" -#line 2324 "seclang-parser.yy" +#line 2329 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidHeaderFolding()); } -#line 4283 "seclang-parser.cc" +#line 4285 "seclang-parser.cc" break; case 278: // var: VARIABLE_MULTIPART_INVALID_PART -#line 2328 "seclang-parser.yy" +#line 2333 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidPart()); } -#line 4291 "seclang-parser.cc" +#line 4293 "seclang-parser.cc" break; case 279: // var: "MULTIPART_INVALID_QUOTING" -#line 2332 "seclang-parser.yy" +#line 2337 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidQuoting()); } -#line 4299 "seclang-parser.cc" +#line 4301 "seclang-parser.cc" break; case 280: // var: VARIABLE_MULTIPART_LF_LINE -#line 2336 "seclang-parser.yy" +#line 2341 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartLFLine()); } -#line 4307 "seclang-parser.cc" +#line 4309 "seclang-parser.cc" break; case 281: // var: VARIABLE_MULTIPART_MISSING_SEMICOLON -#line 2340 "seclang-parser.yy" +#line 2345 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4315 "seclang-parser.cc" +#line 4317 "seclang-parser.cc" break; case 282: // var: VARIABLE_MULTIPART_SEMICOLON_MISSING -#line 2344 "seclang-parser.yy" +#line 2349 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4323 "seclang-parser.cc" +#line 4325 "seclang-parser.cc" break; case 283: // var: "MULTIPART_STRICT_ERROR" -#line 2348 "seclang-parser.yy" +#line 2353 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartStrictError()); } -#line 4331 "seclang-parser.cc" +#line 4333 "seclang-parser.cc" break; case 284: // var: "MULTIPART_UNMATCHED_BOUNDARY" -#line 2352 "seclang-parser.yy" +#line 2357 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartUnmatchedBoundary()); } -#line 4339 "seclang-parser.cc" +#line 4341 "seclang-parser.cc" break; case 285: // var: "OUTBOUND_DATA_ERROR" -#line 2356 "seclang-parser.yy" +#line 2361 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::OutboundDataError()); } -#line 4347 "seclang-parser.cc" +#line 4349 "seclang-parser.cc" break; case 286: // var: "PATH_INFO" -#line 2360 "seclang-parser.yy" +#line 2365 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::PathInfo()); } -#line 4355 "seclang-parser.cc" +#line 4357 "seclang-parser.cc" break; case 287: // var: "QUERY_STRING" -#line 2364 "seclang-parser.yy" +#line 2369 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::QueryString()); } -#line 4363 "seclang-parser.cc" +#line 4365 "seclang-parser.cc" break; case 288: // var: "REMOTE_ADDR" -#line 2368 "seclang-parser.yy" +#line 2373 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteAddr()); } -#line 4371 "seclang-parser.cc" +#line 4373 "seclang-parser.cc" break; case 289: // var: "REMOTE_HOST" -#line 2372 "seclang-parser.yy" +#line 2377 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteHost()); } -#line 4379 "seclang-parser.cc" +#line 4381 "seclang-parser.cc" break; case 290: // var: "REMOTE_PORT" -#line 2376 "seclang-parser.yy" +#line 2381 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemotePort()); } -#line 4387 "seclang-parser.cc" +#line 4389 "seclang-parser.cc" break; case 291: // var: "REQBODY_ERROR" -#line 2380 "seclang-parser.yy" +#line 2385 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyError()); } -#line 4395 "seclang-parser.cc" +#line 4397 "seclang-parser.cc" break; case 292: // var: "REQBODY_ERROR_MSG" -#line 2384 "seclang-parser.yy" +#line 2389 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyErrorMsg()); } -#line 4403 "seclang-parser.cc" +#line 4405 "seclang-parser.cc" break; case 293: // var: "REQBODY_PROCESSOR" -#line 2388 "seclang-parser.yy" +#line 2393 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessor()); } -#line 4411 "seclang-parser.cc" +#line 4413 "seclang-parser.cc" break; case 294: // var: "REQBODY_PROCESSOR_ERROR" -#line 2392 "seclang-parser.yy" +#line 2397 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorError()); } -#line 4419 "seclang-parser.cc" +#line 4421 "seclang-parser.cc" break; case 295: // var: "REQBODY_PROCESSOR_ERROR_MSG" -#line 2396 "seclang-parser.yy" +#line 2401 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorErrorMsg()); } -#line 4427 "seclang-parser.cc" +#line 4429 "seclang-parser.cc" break; case 296: // var: "REQUEST_BASENAME" -#line 2400 "seclang-parser.yy" +#line 2405 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBasename()); } -#line 4435 "seclang-parser.cc" +#line 4437 "seclang-parser.cc" break; case 297: // var: "REQUEST_BODY" -#line 2404 "seclang-parser.yy" +#line 2409 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBody()); } -#line 4443 "seclang-parser.cc" +#line 4445 "seclang-parser.cc" break; case 298: // var: "REQUEST_BODY_LENGTH" -#line 2408 "seclang-parser.yy" +#line 2413 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBodyLength()); } -#line 4451 "seclang-parser.cc" +#line 4453 "seclang-parser.cc" break; case 299: // var: "REQUEST_FILENAME" -#line 2412 "seclang-parser.yy" +#line 2417 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestFilename()); } -#line 4459 "seclang-parser.cc" +#line 4461 "seclang-parser.cc" break; case 300: // var: "REQUEST_LINE" -#line 2416 "seclang-parser.yy" +#line 2421 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestLine()); } -#line 4467 "seclang-parser.cc" +#line 4469 "seclang-parser.cc" break; case 301: // var: "REQUEST_METHOD" -#line 2420 "seclang-parser.yy" +#line 2425 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestMethod()); } -#line 4475 "seclang-parser.cc" +#line 4477 "seclang-parser.cc" break; case 302: // var: "REQUEST_PROTOCOL" -#line 2424 "seclang-parser.yy" +#line 2429 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestProtocol()); } -#line 4483 "seclang-parser.cc" +#line 4485 "seclang-parser.cc" break; case 303: // var: "REQUEST_URI" -#line 2428 "seclang-parser.yy" +#line 2433 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURI()); } -#line 4491 "seclang-parser.cc" +#line 4493 "seclang-parser.cc" break; case 304: // var: "REQUEST_URI_RAW" -#line 2432 "seclang-parser.yy" +#line 2437 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURIRaw()); } -#line 4499 "seclang-parser.cc" +#line 4501 "seclang-parser.cc" break; case 305: // var: "RESPONSE_BODY" -#line 2436 "seclang-parser.yy" +#line 2441 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseBody()); } -#line 4507 "seclang-parser.cc" +#line 4509 "seclang-parser.cc" break; case 306: // var: "RESPONSE_CONTENT_LENGTH" -#line 2440 "seclang-parser.yy" +#line 2445 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentLength()); } -#line 4515 "seclang-parser.cc" +#line 4517 "seclang-parser.cc" break; case 307: // var: "RESPONSE_PROTOCOL" -#line 2444 "seclang-parser.yy" +#line 2449 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseProtocol()); } -#line 4523 "seclang-parser.cc" +#line 4525 "seclang-parser.cc" break; case 308: // var: "RESPONSE_STATUS" -#line 2448 "seclang-parser.yy" +#line 2453 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseStatus()); } -#line 4531 "seclang-parser.cc" +#line 4533 "seclang-parser.cc" break; case 309: // var: "SERVER_ADDR" -#line 2452 "seclang-parser.yy" +#line 2457 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerAddr()); } -#line 4539 "seclang-parser.cc" +#line 4541 "seclang-parser.cc" break; case 310: // var: "SERVER_NAME" -#line 2456 "seclang-parser.yy" +#line 2461 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerName()); } -#line 4547 "seclang-parser.cc" +#line 4549 "seclang-parser.cc" break; case 311: // var: "SERVER_PORT" -#line 2460 "seclang-parser.yy" +#line 2465 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerPort()); } -#line 4555 "seclang-parser.cc" +#line 4557 "seclang-parser.cc" break; case 312: // var: "SESSIONID" -#line 2464 "seclang-parser.yy" +#line 2469 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::SessionID()); } -#line 4563 "seclang-parser.cc" +#line 4565 "seclang-parser.cc" break; case 313: // var: "UNIQUE_ID" -#line 2468 "seclang-parser.yy" +#line 2473 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UniqueID()); } -#line 4571 "seclang-parser.cc" +#line 4573 "seclang-parser.cc" break; case 314: // var: "URLENCODED_ERROR" -#line 2472 "seclang-parser.yy" +#line 2477 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UrlEncodedError()); } -#line 4579 "seclang-parser.cc" +#line 4581 "seclang-parser.cc" break; case 315: // var: "USERID" -#line 2476 "seclang-parser.yy" +#line 2481 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UserID()); } -#line 4587 "seclang-parser.cc" +#line 4589 "seclang-parser.cc" break; case 316: // var: "VARIABLE_STATUS" -#line 2480 "seclang-parser.yy" +#line 2485 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4595 "seclang-parser.cc" +#line 4597 "seclang-parser.cc" break; case 317: // var: "VARIABLE_STATUS_LINE" -#line 2484 "seclang-parser.yy" +#line 2489 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4603 "seclang-parser.cc" +#line 4605 "seclang-parser.cc" break; case 318: // var: "WEBAPPID" -#line 2488 "seclang-parser.yy" +#line 2493 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::WebAppId()); } -#line 4611 "seclang-parser.cc" +#line 4613 "seclang-parser.cc" break; case 319: // var: "RUN_TIME_VAR_DUR" -#line 2492 "seclang-parser.yy" +#line 2497 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Duration(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4622 "seclang-parser.cc" +#line 4624 "seclang-parser.cc" break; case 320: // var: "RUN_TIME_VAR_BLD" -#line 2500 "seclang-parser.yy" +#line 2505 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new ModsecBuild(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4633 "seclang-parser.cc" +#line 4635 "seclang-parser.cc" break; case 321: // var: "RUN_TIME_VAR_HSV" -#line 2507 "seclang-parser.yy" +#line 2512 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new HighestSeverity(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4644 "seclang-parser.cc" +#line 4646 "seclang-parser.cc" break; case 322: // var: "RUN_TIME_VAR_REMOTE_USER" -#line 2514 "seclang-parser.yy" +#line 2519 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new RemoteUser(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4655 "seclang-parser.cc" +#line 4657 "seclang-parser.cc" break; case 323: // var: "RUN_TIME_VAR_TIME" -#line 2521 "seclang-parser.yy" +#line 2526 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Time(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4666 "seclang-parser.cc" +#line 4668 "seclang-parser.cc" break; case 324: // var: "RUN_TIME_VAR_TIME_DAY" -#line 2528 "seclang-parser.yy" +#line 2533 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4677 "seclang-parser.cc" +#line 4679 "seclang-parser.cc" break; case 325: // var: "RUN_TIME_VAR_TIME_EPOCH" -#line 2535 "seclang-parser.yy" +#line 2540 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeEpoch(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4688 "seclang-parser.cc" +#line 4690 "seclang-parser.cc" break; case 326: // var: "RUN_TIME_VAR_TIME_HOUR" -#line 2542 "seclang-parser.yy" +#line 2547 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeHour(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4699 "seclang-parser.cc" +#line 4701 "seclang-parser.cc" break; case 327: // var: "RUN_TIME_VAR_TIME_MIN" -#line 2549 "seclang-parser.yy" +#line 2554 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMin(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4710 "seclang-parser.cc" +#line 4712 "seclang-parser.cc" break; case 328: // var: "RUN_TIME_VAR_TIME_MON" -#line 2556 "seclang-parser.yy" +#line 2561 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMon(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4721 "seclang-parser.cc" +#line 4723 "seclang-parser.cc" break; case 329: // var: "RUN_TIME_VAR_TIME_SEC" -#line 2563 "seclang-parser.yy" +#line 2568 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeSec(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4732 "seclang-parser.cc" +#line 4734 "seclang-parser.cc" break; case 330: // var: "RUN_TIME_VAR_TIME_WDAY" -#line 2570 "seclang-parser.yy" +#line 2575 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeWDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4743 "seclang-parser.cc" +#line 4745 "seclang-parser.cc" break; case 331: // var: "RUN_TIME_VAR_TIME_YEAR" -#line 2577 "seclang-parser.yy" +#line 2582 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeYear(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4754 "seclang-parser.cc" +#line 4756 "seclang-parser.cc" break; case 332: // act: "Accuracy" -#line 2587 "seclang-parser.yy" +#line 2592 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Accuracy(yystack_[0].value.as < std::string > ())); } -#line 4762 "seclang-parser.cc" +#line 4764 "seclang-parser.cc" break; case 333: // act: "Allow" -#line 2591 "seclang-parser.yy" +#line 2596 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Allow(yystack_[0].value.as < std::string > ())); } -#line 4770 "seclang-parser.cc" +#line 4772 "seclang-parser.cc" break; case 334: // act: "Append" -#line 2595 "seclang-parser.yy" +#line 2600 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Append", yystack_[1].location); } -#line 4778 "seclang-parser.cc" +#line 4780 "seclang-parser.cc" break; case 335: // act: "AuditLog" -#line 2599 "seclang-parser.yy" +#line 2604 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::AuditLog(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::AuditLog()); } -#line 4786 "seclang-parser.cc" +#line 4788 "seclang-parser.cc" break; case 336: // act: "Block" -#line 2603 "seclang-parser.yy" +#line 2608 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Block(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Block()); } -#line 4794 "seclang-parser.cc" +#line 4796 "seclang-parser.cc" break; case 337: // act: "Capture" -#line 2607 "seclang-parser.yy" +#line 2612 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Capture(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Capture()); } -#line 4802 "seclang-parser.cc" +#line 4804 "seclang-parser.cc" break; case 338: // act: "Chain" -#line 2611 "seclang-parser.yy" +#line 2616 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Chain(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Chain()); } -#line 4810 "seclang-parser.cc" +#line 4812 "seclang-parser.cc" break; case 339: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_ON" -#line 2615 "seclang-parser.yy" +#line 2620 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4819 "seclang-parser.cc" +#line 4821 "seclang-parser.cc" break; case 340: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_OFF" -#line 2620 "seclang-parser.yy" +#line 2625 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4828 "seclang-parser.cc" +#line 4830 "seclang-parser.cc" break; case 341: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_RELEVANT_ONLY" -#line 2625 "seclang-parser.yy" +#line 2630 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4837 "seclang-parser.cc" +#line 4839 "seclang-parser.cc" break; case 342: // act: "ACTION_CTL_AUDIT_LOG_PARTS" -#line 2630 "seclang-parser.yy" +#line 2635 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditLogParts(yystack_[0].value.as < std::string > ())); } -#line 4845 "seclang-parser.cc" +#line 4847 "seclang-parser.cc" break; case 343: // act: "ACTION_CTL_BDY_JSON" -#line 2634 "seclang-parser.yy" +#line 2639 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorJSON(yystack_[0].value.as < std::string > ())); } -#line 4853 "seclang-parser.cc" +#line 4855 "seclang-parser.cc" break; case 344: // act: "ACTION_CTL_BDY_XML" -#line 2638 "seclang-parser.yy" +#line 2643 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorXML(yystack_[0].value.as < std::string > ())); } -#line 4861 "seclang-parser.cc" +#line 4863 "seclang-parser.cc" break; case 345: // act: "ACTION_CTL_BDY_URLENCODED" -#line 2642 "seclang-parser.yy" +#line 2647 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorURLENCODED(yystack_[0].value.as < std::string > ())); } -#line 4869 "seclang-parser.cc" +#line 4871 "seclang-parser.cc" break; case 346: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_ON" -#line 2646 "seclang-parser.yy" +#line 2651 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4878 "seclang-parser.cc" +#line 4880 "seclang-parser.cc" break; case 347: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_OFF" -#line 2651 "seclang-parser.yy" +#line 2656 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4887 "seclang-parser.cc" +#line 4889 "seclang-parser.cc" break; case 348: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_ON" -#line 2656 "seclang-parser.yy" +#line 2661 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "true")); } -#line 4895 "seclang-parser.cc" +#line 4897 "seclang-parser.cc" break; case 349: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_OFF" -#line 2660 "seclang-parser.yy" +#line 2665 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "false")); } -#line 4903 "seclang-parser.cc" +#line 4905 "seclang-parser.cc" break; case 350: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_ON" -#line 2664 "seclang-parser.yy" +#line 2669 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=on")); } -#line 4911 "seclang-parser.cc" +#line 4913 "seclang-parser.cc" break; case 351: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_OFF" -#line 2668 "seclang-parser.yy" +#line 2673 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=off")); } -#line 4919 "seclang-parser.cc" +#line 4921 "seclang-parser.cc" break; case 352: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_DETC" -#line 2672 "seclang-parser.yy" +#line 2677 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=detectiononly")); } -#line 4927 "seclang-parser.cc" +#line 4929 "seclang-parser.cc" break; case 353: // act: "ACTION_CTL_RULE_REMOVE_BY_ID" -#line 2676 "seclang-parser.yy" +#line 2681 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveById(yystack_[0].value.as < std::string > ())); } -#line 4935 "seclang-parser.cc" +#line 4937 "seclang-parser.cc" break; case 354: // act: "ACTION_CTL_RULE_REMOVE_BY_TAG" -#line 2680 "seclang-parser.yy" +#line 2685 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveByTag(yystack_[0].value.as < std::string > ())); } -#line 4943 "seclang-parser.cc" +#line 4945 "seclang-parser.cc" break; case 355: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_ID" -#line 2684 "seclang-parser.yy" +#line 2689 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetById(yystack_[0].value.as < std::string > ())); } -#line 4951 "seclang-parser.cc" +#line 4953 "seclang-parser.cc" break; case 356: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG" -#line 2688 "seclang-parser.yy" +#line 2693 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetByTag(yystack_[0].value.as < std::string > ())); } -#line 4959 "seclang-parser.cc" +#line 4961 "seclang-parser.cc" break; case 357: // act: "Deny" -#line 2692 "seclang-parser.yy" +#line 2697 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Deny(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Deny()); } -#line 4967 "seclang-parser.cc" +#line 4969 "seclang-parser.cc" break; case 358: // act: "DeprecateVar" -#line 2696 "seclang-parser.yy" +#line 2701 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("DeprecateVar", yystack_[1].location); } -#line 4975 "seclang-parser.cc" +#line 4977 "seclang-parser.cc" break; case 359: // act: "Drop" -#line 2700 "seclang-parser.yy" +#line 2705 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Drop(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Drop()); } -#line 4983 "seclang-parser.cc" +#line 4985 "seclang-parser.cc" break; case 360: // act: "Exec" -#line 2704 "seclang-parser.yy" +#line 2709 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Exec(yystack_[0].value.as < std::string > ())); } -#line 4991 "seclang-parser.cc" +#line 4993 "seclang-parser.cc" break; case 361: // act: "ExpireVar" -#line 2708 "seclang-parser.yy" +#line 2713 "seclang-parser.yy" { - //ACTION_NOT_SUPPORTED("ExpireVar", @0); - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ExpireVar(yystack_[0].value.as < std::string > ())); } -#line 5000 "seclang-parser.cc" +#line 5001 "seclang-parser.cc" break; case 362: // act: "Id" -#line 2713 "seclang-parser.yy" +#line 2717 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::RuleId(yystack_[0].value.as < std::string > ())); } -#line 5008 "seclang-parser.cc" +#line 5009 "seclang-parser.cc" break; case 363: // act: "InitCol" run_time_string -#line 2717 "seclang-parser.yy" +#line 2721 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::InitCol(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5016 "seclang-parser.cc" +#line 5017 "seclang-parser.cc" break; case 364: // act: "LogData" run_time_string -#line 2721 "seclang-parser.yy" +#line 2725 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::LogData(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5024 "seclang-parser.cc" +#line 5025 "seclang-parser.cc" break; case 365: // act: "Log" -#line 2725 "seclang-parser.yy" +#line 2729 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Log(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Log()); } -#line 5032 "seclang-parser.cc" +#line 5033 "seclang-parser.cc" break; case 366: // act: "Maturity" -#line 2729 "seclang-parser.yy" +#line 2733 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Maturity(yystack_[0].value.as < std::string > ())); } -#line 5040 "seclang-parser.cc" +#line 5041 "seclang-parser.cc" break; case 367: // act: "Msg" run_time_string -#line 2733 "seclang-parser.yy" +#line 2737 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Msg(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5048 "seclang-parser.cc" +#line 5049 "seclang-parser.cc" break; case 368: // act: "MultiMatch" -#line 2737 "seclang-parser.yy" +#line 2741 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::MultiMatch(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::MultiMatch()); } -#line 5056 "seclang-parser.cc" +#line 5057 "seclang-parser.cc" break; case 369: // act: "NoAuditLog" -#line 2741 "seclang-parser.yy" +#line 2745 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoAuditLog(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoAuditLog()); } -#line 5064 "seclang-parser.cc" +#line 5065 "seclang-parser.cc" break; case 370: // act: "NoLog" -#line 2745 "seclang-parser.yy" +#line 2749 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoLog(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoLog()); } -#line 5072 "seclang-parser.cc" +#line 5073 "seclang-parser.cc" break; case 371: // act: "Pass" -#line 2749 "seclang-parser.yy" +#line 2753 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Pass(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Pass()); } -#line 5080 "seclang-parser.cc" +#line 5081 "seclang-parser.cc" break; case 372: // act: "Pause" -#line 2753 "seclang-parser.yy" +#line 2757 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Pause", yystack_[1].location); } -#line 5088 "seclang-parser.cc" +#line 5089 "seclang-parser.cc" break; case 373: // act: "Phase" -#line 2757 "seclang-parser.yy" +#line 2761 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Phase(yystack_[0].value.as < std::string > ())); } -#line 5096 "seclang-parser.cc" +#line 5097 "seclang-parser.cc" break; case 374: // act: "Prepend" -#line 2761 "seclang-parser.yy" +#line 2765 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Prepend", yystack_[1].location); } -#line 5104 "seclang-parser.cc" +#line 5105 "seclang-parser.cc" break; case 375: // act: "Proxy" -#line 2765 "seclang-parser.yy" +#line 2769 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Proxy", yystack_[1].location); } -#line 5112 "seclang-parser.cc" +#line 5113 "seclang-parser.cc" break; case 376: // act: "Redirect" run_time_string -#line 2769 "seclang-parser.yy" +#line 2773 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Redirect(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5120 "seclang-parser.cc" +#line 5121 "seclang-parser.cc" break; case 377: // act: "Rev" -#line 2773 "seclang-parser.yy" +#line 2777 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Rev(yystack_[0].value.as < std::string > ())); } -#line 5128 "seclang-parser.cc" +#line 5129 "seclang-parser.cc" break; case 378: // act: "SanitiseArg" -#line 2777 "seclang-parser.yy" +#line 2781 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseArg", yystack_[1].location); } -#line 5136 "seclang-parser.cc" +#line 5137 "seclang-parser.cc" break; case 379: // act: "SanitiseMatched" -#line 2781 "seclang-parser.yy" +#line 2785 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatched", yystack_[1].location); } -#line 5144 "seclang-parser.cc" +#line 5145 "seclang-parser.cc" break; case 380: // act: "SanitiseMatchedBytes" -#line 2785 "seclang-parser.yy" +#line 2789 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatchedBytes", yystack_[1].location); } -#line 5152 "seclang-parser.cc" +#line 5153 "seclang-parser.cc" break; case 381: // act: "SanitiseRequestHeader" -#line 2789 "seclang-parser.yy" +#line 2793 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseRequestHeader", yystack_[1].location); } -#line 5160 "seclang-parser.cc" +#line 5161 "seclang-parser.cc" break; case 382: // act: "SanitiseResponseHeader" -#line 2793 "seclang-parser.yy" +#line 2797 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseResponseHeader", yystack_[1].location); } -#line 5168 "seclang-parser.cc" +#line 5169 "seclang-parser.cc" break; case 383: // act: "SetEnv" run_time_string -#line 2797 "seclang-parser.yy" +#line 2801 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetENV(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5176 "seclang-parser.cc" +#line 5177 "seclang-parser.cc" break; case 384: // act: "SetRsc" run_time_string -#line 2801 "seclang-parser.yy" +#line 2805 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetRSC(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5184 "seclang-parser.cc" +#line 5185 "seclang-parser.cc" break; case 385: // act: "SetSid" run_time_string -#line 2805 "seclang-parser.yy" +#line 2809 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetSID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5192 "seclang-parser.cc" +#line 5193 "seclang-parser.cc" break; case 386: // act: "SetUID" run_time_string -#line 2809 "seclang-parser.yy" +#line 2813 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetUID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5200 "seclang-parser.cc" +#line 5201 "seclang-parser.cc" break; case 387: // act: "SetVar" setvar_action -#line 2813 "seclang-parser.yy" +#line 2817 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > () = std::move(yystack_[0].value.as < std::unique_ptr > ()); } -#line 5208 "seclang-parser.cc" +#line 5209 "seclang-parser.cc" break; case 388: // act: "Severity" -#line 2817 "seclang-parser.yy" +#line 2821 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Severity(yystack_[0].value.as < std::string > ())); } -#line 5216 "seclang-parser.cc" +#line 5217 "seclang-parser.cc" break; case 389: // act: "Skip" -#line 2821 "seclang-parser.yy" +#line 2825 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Skip(yystack_[0].value.as < std::string > ())); } -#line 5224 "seclang-parser.cc" +#line 5225 "seclang-parser.cc" break; case 390: // act: "SkipAfter" -#line 2825 "seclang-parser.yy" +#line 2829 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SkipAfter(yystack_[0].value.as < std::string > ())); } -#line 5232 "seclang-parser.cc" +#line 5233 "seclang-parser.cc" break; case 391: // act: "Status" -#line 2829 "seclang-parser.yy" +#line 2833 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::data::Status(yystack_[0].value.as < std::string > ())); } -#line 5240 "seclang-parser.cc" +#line 5241 "seclang-parser.cc" break; case 392: // act: "Tag" run_time_string -#line 2833 "seclang-parser.yy" +#line 2837 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Tag(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5248 "seclang-parser.cc" +#line 5249 "seclang-parser.cc" break; case 393: // act: "Ver" -#line 2837 "seclang-parser.yy" +#line 2841 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Ver(yystack_[0].value.as < std::string > ())); } -#line 5256 "seclang-parser.cc" +#line 5257 "seclang-parser.cc" break; case 394: // act: "xmlns" -#line 2841 "seclang-parser.yy" +#line 2845 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::XmlNS(yystack_[0].value.as < std::string > ())); } -#line 5264 "seclang-parser.cc" +#line 5265 "seclang-parser.cc" break; case 395: // act: "ACTION_TRANSFORMATION_PARITY_ZERO_7_BIT" -#line 2845 "seclang-parser.yy" +#line 2849 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityZero7bit(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityZero7bit()); } -#line 5272 "seclang-parser.cc" +#line 5273 "seclang-parser.cc" break; case 396: // act: "ACTION_TRANSFORMATION_PARITY_ODD_7_BIT" -#line 2849 "seclang-parser.yy" +#line 2853 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityOdd7bit(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityOdd7bit()); } -#line 5280 "seclang-parser.cc" +#line 5281 "seclang-parser.cc" break; case 397: // act: "ACTION_TRANSFORMATION_PARITY_EVEN_7_BIT" -#line 2853 "seclang-parser.yy" +#line 2857 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityEven7bit(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityEven7bit()); } -#line 5288 "seclang-parser.cc" +#line 5289 "seclang-parser.cc" break; case 398: // act: "ACTION_TRANSFORMATION_SQL_HEX_DECODE" -#line 2857 "seclang-parser.yy" +#line 2861 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::SqlHexDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::SqlHexDecode()); } -#line 5296 "seclang-parser.cc" +#line 5297 "seclang-parser.cc" break; case 399: // act: "ACTION_TRANSFORMATION_BASE_64_ENCODE" -#line 2861 "seclang-parser.yy" +#line 2865 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Encode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Encode()); } -#line 5304 "seclang-parser.cc" +#line 5305 "seclang-parser.cc" break; case 400: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE" -#line 2865 "seclang-parser.yy" +#line 2869 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Decode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Decode()); } -#line 5312 "seclang-parser.cc" +#line 5313 "seclang-parser.cc" break; case 401: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE_EXT" -#line 2869 "seclang-parser.yy" +#line 2873 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64DecodeExt(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64DecodeExt()); } -#line 5320 "seclang-parser.cc" +#line 5321 "seclang-parser.cc" break; case 402: // act: "ACTION_TRANSFORMATION_CMD_LINE" -#line 2873 "seclang-parser.yy" +#line 2877 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CmdLine(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CmdLine()); } -#line 5328 "seclang-parser.cc" +#line 5329 "seclang-parser.cc" break; case 403: // act: "ACTION_TRANSFORMATION_SHA1" -#line 2877 "seclang-parser.yy" +#line 2881 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Sha1(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Sha1()); } -#line 5336 "seclang-parser.cc" +#line 5337 "seclang-parser.cc" break; case 404: // act: "ACTION_TRANSFORMATION_MD5" -#line 2881 "seclang-parser.yy" +#line 2885 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Md5(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Md5()); } -#line 5344 "seclang-parser.cc" +#line 5345 "seclang-parser.cc" break; case 405: // act: "ACTION_TRANSFORMATION_ESCAPE_SEQ_DECODE" -#line 2885 "seclang-parser.yy" +#line 2889 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::EscapeSeqDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::EscapeSeqDecode()); } -#line 5352 "seclang-parser.cc" +#line 5353 "seclang-parser.cc" break; case 406: // act: "ACTION_TRANSFORMATION_HEX_ENCODE" -#line 2889 "seclang-parser.yy" +#line 2893 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexEncode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexEncode()); } -#line 5360 "seclang-parser.cc" +#line 5361 "seclang-parser.cc" break; case 407: // act: "ACTION_TRANSFORMATION_HEX_DECODE" -#line 2893 "seclang-parser.yy" +#line 2897 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexDecode()); } -#line 5368 "seclang-parser.cc" +#line 5369 "seclang-parser.cc" break; case 408: // act: "ACTION_TRANSFORMATION_LOWERCASE" -#line 2897 "seclang-parser.yy" +#line 2901 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::LowerCase(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::LowerCase()); } -#line 5376 "seclang-parser.cc" +#line 5377 "seclang-parser.cc" break; case 409: // act: "ACTION_TRANSFORMATION_UPPERCASE" -#line 2901 "seclang-parser.yy" +#line 2905 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UpperCase(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UpperCase()); } -#line 5384 "seclang-parser.cc" +#line 5385 "seclang-parser.cc" break; case 410: // act: "ACTION_TRANSFORMATION_URL_DECODE_UNI" -#line 2905 "seclang-parser.yy" +#line 2909 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecodeUni(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecodeUni()); } -#line 5392 "seclang-parser.cc" +#line 5393 "seclang-parser.cc" break; case 411: // act: "ACTION_TRANSFORMATION_URL_DECODE" -#line 2909 "seclang-parser.yy" +#line 2913 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecode()); } -#line 5400 "seclang-parser.cc" +#line 5401 "seclang-parser.cc" break; case 412: // act: "ACTION_TRANSFORMATION_URL_ENCODE" -#line 2913 "seclang-parser.yy" +#line 2917 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlEncode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlEncode()); } -#line 5408 "seclang-parser.cc" +#line 5409 "seclang-parser.cc" break; case 413: // act: "ACTION_TRANSFORMATION_NONE" -#line 2917 "seclang-parser.yy" +#line 2921 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::None(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::None()); } -#line 5416 "seclang-parser.cc" +#line 5417 "seclang-parser.cc" break; case 414: // act: "ACTION_TRANSFORMATION_COMPRESS_WHITESPACE" -#line 2921 "seclang-parser.yy" +#line 2925 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CompressWhitespace(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CompressWhitespace()); } -#line 5424 "seclang-parser.cc" +#line 5425 "seclang-parser.cc" break; case 415: // act: "ACTION_TRANSFORMATION_REMOVE_WHITESPACE" -#line 2925 "seclang-parser.yy" +#line 2929 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveWhitespace(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveWhitespace()); } -#line 5432 "seclang-parser.cc" +#line 5433 "seclang-parser.cc" break; case 416: // act: "ACTION_TRANSFORMATION_REPLACE_NULLS" -#line 2929 "seclang-parser.yy" +#line 2933 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceNulls(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceNulls()); } -#line 5440 "seclang-parser.cc" +#line 5441 "seclang-parser.cc" break; case 417: // act: "ACTION_TRANSFORMATION_REMOVE_NULLS" -#line 2933 "seclang-parser.yy" +#line 2937 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveNulls(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveNulls()); } -#line 5448 "seclang-parser.cc" +#line 5449 "seclang-parser.cc" break; case 418: // act: "ACTION_TRANSFORMATION_HTML_ENTITY_DECODE" -#line 2937 "seclang-parser.yy" +#line 2941 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HtmlEntityDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HtmlEntityDecode()); } -#line 5456 "seclang-parser.cc" +#line 5457 "seclang-parser.cc" break; case 419: // act: "ACTION_TRANSFORMATION_JS_DECODE" -#line 2941 "seclang-parser.yy" +#line 2945 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::JsDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::JsDecode()); } -#line 5464 "seclang-parser.cc" +#line 5465 "seclang-parser.cc" break; case 420: // act: "ACTION_TRANSFORMATION_CSS_DECODE" -#line 2945 "seclang-parser.yy" +#line 2949 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CssDecode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CssDecode()); } -#line 5472 "seclang-parser.cc" +#line 5473 "seclang-parser.cc" break; case 421: // act: "ACTION_TRANSFORMATION_TRIM" -#line 2949 "seclang-parser.yy" +#line 2953 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Trim(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Trim()); } -#line 5480 "seclang-parser.cc" +#line 5481 "seclang-parser.cc" break; case 422: // act: "ACTION_TRANSFORMATION_TRIM_LEFT" -#line 2953 "seclang-parser.yy" +#line 2957 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimLeft(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimLeft()); } -#line 5488 "seclang-parser.cc" +#line 5489 "seclang-parser.cc" break; case 423: // act: "ACTION_TRANSFORMATION_TRIM_RIGHT" -#line 2957 "seclang-parser.yy" +#line 2961 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimRight(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimRight()); } -#line 5496 "seclang-parser.cc" +#line 5497 "seclang-parser.cc" break; case 424: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH_WIN" -#line 2961 "seclang-parser.yy" +#line 2965 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePathWin(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePathWin()); } -#line 5504 "seclang-parser.cc" +#line 5505 "seclang-parser.cc" break; case 425: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH" -#line 2965 "seclang-parser.yy" +#line 2969 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePath(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePath()); } -#line 5512 "seclang-parser.cc" +#line 5513 "seclang-parser.cc" break; case 426: // act: "ACTION_TRANSFORMATION_LENGTH" -#line 2969 "seclang-parser.yy" +#line 2973 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Length(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Length()); } -#line 5520 "seclang-parser.cc" +#line 5521 "seclang-parser.cc" break; case 427: // act: "ACTION_TRANSFORMATION_UTF8_TO_UNICODE" -#line 2973 "seclang-parser.yy" +#line 2977 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Utf8ToUnicode(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Utf8ToUnicode()); } -#line 5528 "seclang-parser.cc" +#line 5529 "seclang-parser.cc" break; case 428: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS_CHAR" -#line 2977 "seclang-parser.yy" +#line 2981 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveCommentsChar(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveCommentsChar()); } -#line 5536 "seclang-parser.cc" +#line 5537 "seclang-parser.cc" break; case 429: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS" -#line 2981 "seclang-parser.yy" +#line 2985 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveComments(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveComments()); } -#line 5544 "seclang-parser.cc" +#line 5545 "seclang-parser.cc" break; case 430: // act: "ACTION_TRANSFORMATION_REPLACE_COMMENTS" -#line 2985 "seclang-parser.yy" +#line 2989 "seclang-parser.yy" { - ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceComments(yystack_[0].value.as < std::string > ())); + ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceComments()); } -#line 5552 "seclang-parser.cc" +#line 5553 "seclang-parser.cc" break; case 431: // setvar_action: "NOT" var -#line 2992 "seclang-parser.yy" +#line 2996 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::unsetOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5560 "seclang-parser.cc" +#line 5561 "seclang-parser.cc" break; case 432: // setvar_action: var -#line 2996 "seclang-parser.yy" +#line 3000 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setToOneOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5568 "seclang-parser.cc" +#line 5569 "seclang-parser.cc" break; case 433: // setvar_action: var SETVAR_OPERATION_EQUALS run_time_string -#line 3000 "seclang-parser.yy" +#line 3004 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5576 "seclang-parser.cc" +#line 5577 "seclang-parser.cc" break; case 434: // setvar_action: var SETVAR_OPERATION_EQUALS_PLUS run_time_string -#line 3004 "seclang-parser.yy" +#line 3008 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::sumAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5584 "seclang-parser.cc" +#line 5585 "seclang-parser.cc" break; case 435: // setvar_action: var SETVAR_OPERATION_EQUALS_MINUS run_time_string -#line 3008 "seclang-parser.yy" +#line 3012 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5592 "seclang-parser.cc" +#line 5593 "seclang-parser.cc" break; case 436: // run_time_string: run_time_string "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3015 "seclang-parser.yy" +#line 3019 "seclang-parser.yy" { - yystack_[1].value.as < std::unique_ptr > ()->appendText(yystack_[0].value.as < std::string > ()); + yystack_[1].value.as < std::unique_ptr > ()->append(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5601 "seclang-parser.cc" +#line 5602 "seclang-parser.cc" break; case 437: // run_time_string: run_time_string var -#line 3020 "seclang-parser.yy" +#line 3024 "seclang-parser.yy" { - yystack_[1].value.as < std::unique_ptr > ()->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); + yystack_[1].value.as < std::unique_ptr > ()->append(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5610 "seclang-parser.cc" +#line 5611 "seclang-parser.cc" break; case 438: // run_time_string: "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3025 "seclang-parser.yy" +#line 3029 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); - r->appendText(yystack_[0].value.as < std::string > ()); + r->append(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5620 "seclang-parser.cc" +#line 5621 "seclang-parser.cc" break; case 439: // run_time_string: var -#line 3031 "seclang-parser.yy" +#line 3035 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); - r->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); + r->append(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5630 "seclang-parser.cc" +#line 5631 "seclang-parser.cc" break; -#line 5634 "seclang-parser.cc" +#line 5635 "seclang-parser.cc" default: break; @@ -7120,50 +7121,50 @@ namespace yy { const short seclang_parser::yyrline_[] = { - 0, 708, 708, 712, 713, 716, 721, 727, 733, 737, - 741, 747, 753, 759, 765, 770, 775, 781, 788, 792, - 796, 802, 806, 810, 815, 820, 825, 830, 834, 841, - 845, 852, 858, 868, 877, 887, 896, 909, 913, 917, - 921, 925, 929, 933, 937, 941, 945, 950, 954, 958, - 962, 966, 970, 975, 980, 984, 988, 992, 996, 1000, - 1004, 1008, 1012, 1016, 1020, 1024, 1028, 1032, 1036, 1040, - 1044, 1048, 1052, 1066, 1067, 1097, 1116, 1135, 1163, 1220, - 1227, 1231, 1235, 1239, 1243, 1247, 1251, 1255, 1264, 1268, - 1273, 1276, 1281, 1286, 1291, 1296, 1299, 1304, 1307, 1312, - 1317, 1320, 1325, 1330, 1335, 1340, 1345, 1350, 1355, 1358, - 1363, 1368, 1373, 1378, 1381, 1386, 1391, 1396, 1409, 1422, - 1435, 1448, 1461, 1487, 1515, 1527, 1547, 1574, 1580, 1585, - 1590, 1599, 1604, 1608, 1612, 1616, 1620, 1624, 1628, 1633, - 1638, 1650, 1656, 1660, 1664, 1675, 1684, 1685, 1692, 1697, - 1702, 1756, 1763, 1771, 1808, 1812, 1819, 1824, 1830, 1836, - 1842, 1849, 1859, 1863, 1867, 1871, 1875, 1879, 1883, 1887, - 1891, 1895, 1899, 1903, 1907, 1911, 1915, 1919, 1923, 1927, - 1931, 1935, 1939, 1943, 1947, 1951, 1955, 1959, 1963, 1967, - 1971, 1975, 1979, 1983, 1987, 1991, 1995, 1999, 2003, 2007, - 2011, 2015, 2019, 2023, 2027, 2031, 2035, 2039, 2043, 2047, - 2051, 2055, 2059, 2063, 2067, 2071, 2075, 2079, 2083, 2087, - 2091, 2095, 2099, 2103, 2107, 2111, 2115, 2119, 2123, 2127, - 2131, 2135, 2139, 2143, 2147, 2151, 2155, 2159, 2163, 2167, - 2171, 2175, 2179, 2183, 2187, 2191, 2195, 2199, 2203, 2207, - 2211, 2215, 2220, 2224, 2228, 2233, 2237, 2241, 2246, 2251, - 2255, 2259, 2263, 2267, 2271, 2275, 2279, 2283, 2287, 2291, - 2295, 2299, 2303, 2307, 2311, 2315, 2319, 2323, 2327, 2331, - 2335, 2339, 2343, 2347, 2351, 2355, 2359, 2363, 2367, 2371, - 2375, 2379, 2383, 2387, 2391, 2395, 2399, 2403, 2407, 2411, - 2415, 2419, 2423, 2427, 2431, 2435, 2439, 2443, 2447, 2451, - 2455, 2459, 2463, 2467, 2471, 2475, 2479, 2483, 2487, 2491, - 2499, 2506, 2513, 2520, 2527, 2534, 2541, 2548, 2555, 2562, - 2569, 2576, 2586, 2590, 2594, 2598, 2602, 2606, 2610, 2614, - 2619, 2624, 2629, 2633, 2637, 2641, 2645, 2650, 2655, 2659, - 2663, 2667, 2671, 2675, 2679, 2683, 2687, 2691, 2695, 2699, - 2703, 2707, 2712, 2716, 2720, 2724, 2728, 2732, 2736, 2740, - 2744, 2748, 2752, 2756, 2760, 2764, 2768, 2772, 2776, 2780, - 2784, 2788, 2792, 2796, 2800, 2804, 2808, 2812, 2816, 2820, - 2824, 2828, 2832, 2836, 2840, 2844, 2848, 2852, 2856, 2860, - 2864, 2868, 2872, 2876, 2880, 2884, 2888, 2892, 2896, 2900, - 2904, 2908, 2912, 2916, 2920, 2924, 2928, 2932, 2936, 2940, - 2944, 2948, 2952, 2956, 2960, 2964, 2968, 2972, 2976, 2980, - 2984, 2991, 2995, 2999, 3003, 3007, 3014, 3019, 3024, 3030 + 0, 711, 711, 715, 716, 719, 724, 730, 736, 740, + 744, 750, 756, 762, 768, 773, 778, 784, 791, 795, + 799, 805, 809, 813, 818, 823, 828, 833, 837, 844, + 848, 855, 861, 871, 880, 890, 899, 912, 916, 920, + 924, 928, 932, 936, 940, 944, 948, 953, 957, 961, + 965, 969, 973, 978, 983, 987, 991, 995, 999, 1003, + 1007, 1011, 1015, 1019, 1023, 1027, 1031, 1035, 1039, 1043, + 1047, 1051, 1055, 1069, 1070, 1102, 1121, 1142, 1172, 1225, + 1232, 1236, 1240, 1244, 1248, 1252, 1256, 1260, 1269, 1273, + 1278, 1281, 1286, 1291, 1296, 1301, 1304, 1309, 1312, 1317, + 1322, 1325, 1330, 1335, 1340, 1345, 1350, 1355, 1360, 1363, + 1368, 1373, 1378, 1383, 1386, 1391, 1396, 1401, 1414, 1427, + 1440, 1453, 1466, 1492, 1520, 1532, 1552, 1579, 1585, 1590, + 1595, 1604, 1609, 1613, 1617, 1621, 1625, 1629, 1633, 1638, + 1643, 1655, 1661, 1665, 1669, 1680, 1689, 1690, 1697, 1702, + 1707, 1761, 1768, 1776, 1813, 1817, 1824, 1829, 1835, 1841, + 1847, 1854, 1864, 1868, 1872, 1876, 1880, 1884, 1888, 1892, + 1896, 1900, 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, + 1936, 1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968, 1972, + 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, + 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048, 2052, + 2056, 2060, 2064, 2068, 2072, 2076, 2080, 2084, 2088, 2092, + 2096, 2100, 2104, 2108, 2112, 2116, 2120, 2124, 2128, 2132, + 2136, 2140, 2144, 2148, 2152, 2156, 2160, 2164, 2168, 2172, + 2176, 2180, 2184, 2188, 2192, 2196, 2200, 2204, 2208, 2212, + 2216, 2220, 2225, 2229, 2233, 2238, 2242, 2246, 2251, 2256, + 2260, 2264, 2268, 2272, 2276, 2280, 2284, 2288, 2292, 2296, + 2300, 2304, 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, + 2340, 2344, 2348, 2352, 2356, 2360, 2364, 2368, 2372, 2376, + 2380, 2384, 2388, 2392, 2396, 2400, 2404, 2408, 2412, 2416, + 2420, 2424, 2428, 2432, 2436, 2440, 2444, 2448, 2452, 2456, + 2460, 2464, 2468, 2472, 2476, 2480, 2484, 2488, 2492, 2496, + 2504, 2511, 2518, 2525, 2532, 2539, 2546, 2553, 2560, 2567, + 2574, 2581, 2591, 2595, 2599, 2603, 2607, 2611, 2615, 2619, + 2624, 2629, 2634, 2638, 2642, 2646, 2650, 2655, 2660, 2664, + 2668, 2672, 2676, 2680, 2684, 2688, 2692, 2696, 2700, 2704, + 2708, 2712, 2716, 2720, 2724, 2728, 2732, 2736, 2740, 2744, + 2748, 2752, 2756, 2760, 2764, 2768, 2772, 2776, 2780, 2784, + 2788, 2792, 2796, 2800, 2804, 2808, 2812, 2816, 2820, 2824, + 2828, 2832, 2836, 2840, 2844, 2848, 2852, 2856, 2860, 2864, + 2868, 2872, 2876, 2880, 2884, 2888, 2892, 2896, 2900, 2904, + 2908, 2912, 2916, 2920, 2924, 2928, 2932, 2936, 2940, 2944, + 2948, 2952, 2956, 2960, 2964, 2968, 2972, 2976, 2980, 2984, + 2988, 2995, 2999, 3003, 3007, 3011, 3018, 3023, 3028, 3034 }; void @@ -7195,9 +7196,9 @@ namespace yy { } // yy -#line 7199 "seclang-parser.cc" +#line 7200 "seclang-parser.cc" -#line 3037 "seclang-parser.yy" +#line 3041 "seclang-parser.yy" void yy::seclang_parser::error (const location_type& l, const std::string& m) { diff --git a/src/parser/seclang-parser.hh b/src/parser/seclang-parser.hh index 5dc370bd52..208f989fd0 100644 --- a/src/parser/seclang-parser.hh +++ b/src/parser/seclang-parser.hh @@ -56,7 +56,9 @@ class Driver; } } -#include "modsecurity/rule_unconditional.h" +#include "src/rule_unconditional.h" +#include "src/rule_with_operator.h" +#include "src/rule_with_actions.h" #include "src/rule_script.h" #include "src/actions/accuracy.h" @@ -82,6 +84,7 @@ class Driver; #include "src/actions/disruptive/redirect.h" #include "src/actions/init_col.h" #include "src/actions/exec.h" +#include "src/actions/expire_var.h" #include "src/actions/log_data.h" #include "src/actions/log.h" #include "src/actions/maturity.h" @@ -349,7 +352,7 @@ using namespace modsecurity::operators; a = std::move(c); -#line 353 "seclang-parser.hh" +#line 356 "seclang-parser.hh" # include # include // std::abort @@ -483,7 +486,7 @@ using namespace modsecurity::operators; #endif namespace yy { -#line 487 "seclang-parser.hh" +#line 490 "seclang-parser.hh" @@ -8585,7 +8588,7 @@ switch (yykind) } } // yy -#line 8589 "seclang-parser.hh" +#line 8592 "seclang-parser.hh" diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 02e8e9eab9..0031237c89 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -17,7 +17,9 @@ class Driver; } } -#include "modsecurity/rule_unconditional.h" +#include "src/rule_unconditional.h" +#include "src/rule_with_operator.h" +#include "src/rule_with_actions.h" #include "src/rule_script.h" #include "src/actions/accuracy.h" @@ -43,6 +45,7 @@ class Driver; #include "src/actions/disruptive/redirect.h" #include "src/actions/init_col.h" #include "src/actions/exec.h" +#include "src/actions/expire_var.h" #include "src/actions/log_data.h" #include "src/actions/log.h" #include "src/actions/maturity.h" @@ -1066,13 +1069,15 @@ expression: audit_log | DIRECTIVE variables op actions { - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *$4.get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } variables::Variables *v = new variables::Variables(); @@ -1089,7 +1094,7 @@ expression: /* file name */ std::unique_ptr(new std::string(*@1.end.filename)), /* line number */ @1.end.line )); - + // TODO: filename should be a shared_ptr. if (driver.addSecRule(std::move(rule)) == false) { YYERROR; } @@ -1115,13 +1120,15 @@ expression: } | CONFIG_DIR_SEC_ACTION actions { - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *$2.get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } std::unique_ptr rule(new RuleUnconditional( @@ -1135,13 +1142,15 @@ expression: | DIRECTIVE_SECRULESCRIPT actions { std::string err; - std::vector *a = new std::vector(); - std::vector *t = new std::vector(); + std::vector> *a = new std::vector>(); + std::vector > *t = new std::vector >(); for (auto &i : *$2.get()) { if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + std::shared_ptr at = std::move(i); + std::shared_ptr t2 = std::dynamic_pointer_cast(std::move(at)); + t->push_back(std::move(t2)); } else { - a->push_back(i.release()); + a->push_back(std::move(i)); } } std::unique_ptr r(new RuleScript( @@ -1163,45 +1172,39 @@ expression: | CONFIG_DIR_SEC_DEFAULT_ACTION actions { bool hasDisruptive = false; - std::vector *actions = new std::vector(); + std::vector> *actions = new std::vector>(); for (auto &i : *$2.get()) { - actions->push_back(i.release()); + actions->push_back(std::move(i)); } - std::vector checkedActions; + std::vector> checkedActions; int definedPhase = -1; int secRuleDefinedPhase = -1; - for (actions::Action *a : *actions) { - actions::Phase *phase = dynamic_cast(a); - if (a->isDisruptive() == true && dynamic_cast(a) == NULL) { + for (auto &a : *actions) { + actions::Phase *phase = dynamic_cast(a.get()); + if (dynamic_cast(a.get()) != NULL + && dynamic_cast(a.get()) == NULL) { hasDisruptive = true; } if (phase != NULL) { - definedPhase = phase->m_phase; - secRuleDefinedPhase = phase->m_secRulesPhase; + definedPhase = phase->getPhase(); + secRuleDefinedPhase = phase->getSecRulePhase(); delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { - actions::transformations::None *none = dynamic_cast(a); - if (none != NULL) { - driver.error(@0, "The transformation none is not suitable to be part of the SecDefaultActions"); - YYERROR; - } + } else if (dynamic_cast(a.get()) + && !dynamic_cast(a.get())) { checkedActions.push_back(a); } else { - driver.error(@0, "The action '" + *a->m_name.get() + "' is not suitable to be part of the SecDefaultActions"); + driver.error(@0, "The action '" + *a->getName() + "' is not suitable to be part of the SecDefaultActions"); YYERROR; } } if (definedPhase == -1) { definedPhase = modsecurity::Phases::RequestHeadersPhase; } - if (hasDisruptive == false) { driver.error(@0, "SecDefaultAction must specify a disruptive action."); YYERROR; } - - if (!driver.m_defaultActions[definedPhase].empty()) { + if (!driver.m_rulesSetPhases[definedPhase]->m_defaultActions.empty()) { std::stringstream ss; ss << "SecDefaultActions can only be placed once per phase and configuration context. Phase "; ss << secRuleDefinedPhase; @@ -1209,13 +1212,15 @@ expression: driver.error(@0, ss.str()); YYERROR; } - - for (actions::Action *a : checkedActions) { - driver.m_defaultActions[definedPhase].push_back( - std::unique_ptr(a)); + for (auto &a : checkedActions) { + if (dynamic_cast(a.get())) { + driver.m_rulesSetPhases[definedPhase]->m_defaultTransformations.push_back( + std::dynamic_pointer_cast(a)); + } else { + driver.m_rulesSetPhases[definedPhase]->m_defaultActions.push_back(a); + } } - - delete actions; + //delete actions; } | CONFIG_DIR_SEC_MARKER { @@ -1461,10 +1466,10 @@ expression: | CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID variables_pre_process { std::string error; - double ruleId; - try { - ruleId = std::stod($1); - } catch (...) { + std::istringstream iss($1); + RuleId ruleId; + iss >> ruleId; + if (iss.fail()) { std::stringstream ss; ss << "SecRuleUpdateTargetById: failed to load:"; ss << "The input \"" + $1 + "\" does not "; @@ -1487,10 +1492,10 @@ expression: | CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID actions { std::string error; - double ruleId; - try { - ruleId = std::stod($1); - } catch (...) { + std::istringstream iss($1); + RuleId ruleId; + iss >> ruleId; + if (iss.fail()) { std::stringstream ss; ss << "SecRuleUpdateActionById: failed to load:"; ss << "The input \"" + $1 + "\" does not "; @@ -2074,15 +2079,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 { @@ -2597,19 +2602,19 @@ act: } | ACTION_AUDIT_LOG { - ACTION_CONTAINER($$, new actions::AuditLog($1)); + ACTION_CONTAINER($$, new actions::AuditLog()); } | ACTION_BLOCK { - ACTION_CONTAINER($$, new actions::Block($1)); + ACTION_CONTAINER($$, new actions::Block()); } | ACTION_CAPTURE { - ACTION_CONTAINER($$, new actions::Capture($1)); + ACTION_CONTAINER($$, new actions::Capture()); } | ACTION_CHAIN { - ACTION_CONTAINER($$, new actions::Chain($1)); + ACTION_CONTAINER($$, new actions::Chain()); } | ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_ON { @@ -2690,7 +2695,7 @@ act: } | ACTION_DENY { - ACTION_CONTAINER($$, new actions::disruptive::Deny($1)); + ACTION_CONTAINER($$, new actions::disruptive::Deny()); } | ACTION_DEPRECATE_VAR { @@ -2698,7 +2703,7 @@ act: } | ACTION_DROP { - ACTION_CONTAINER($$, new actions::disruptive::Drop($1)); + ACTION_CONTAINER($$, new actions::disruptive::Drop()); } | ACTION_EXEC { @@ -2706,8 +2711,7 @@ act: } | ACTION_EXPIRE_VAR { - //ACTION_NOT_SUPPORTED("ExpireVar", @0); - ACTION_CONTAINER($$, new actions::Action($1)); + ACTION_CONTAINER($$, new actions::ExpireVar($1)); } | ACTION_ID { @@ -2723,7 +2727,7 @@ act: } | ACTION_LOG { - ACTION_CONTAINER($$, new actions::Log($1)); + ACTION_CONTAINER($$, new actions::Log()); } | ACTION_MATURITY { @@ -2735,19 +2739,19 @@ act: } | ACTION_MULTI_MATCH { - ACTION_CONTAINER($$, new actions::MultiMatch($1)); + ACTION_CONTAINER($$, new actions::MultiMatch()); } | ACTION_NO_AUDIT_LOG { - ACTION_CONTAINER($$, new actions::NoAuditLog($1)); + ACTION_CONTAINER($$, new actions::NoAuditLog()); } | ACTION_NO_LOG { - ACTION_CONTAINER($$, new actions::NoLog($1)); + ACTION_CONTAINER($$, new actions::NoLog()); } | ACTION_PASS { - ACTION_CONTAINER($$, new actions::disruptive::Pass($1)); + ACTION_CONTAINER($$, new actions::disruptive::Pass()); } | ACTION_PAUSE { @@ -2843,147 +2847,147 @@ act: } | ACTION_TRANSFORMATION_PARITY_ZERO_7_BIT { - ACTION_CONTAINER($$, new actions::transformations::ParityZero7bit($1)); + ACTION_CONTAINER($$, new actions::transformations::ParityZero7bit()); } | ACTION_TRANSFORMATION_PARITY_ODD_7_BIT { - ACTION_CONTAINER($$, new actions::transformations::ParityOdd7bit($1)); + ACTION_CONTAINER($$, new actions::transformations::ParityOdd7bit()); } | ACTION_TRANSFORMATION_PARITY_EVEN_7_BIT { - ACTION_CONTAINER($$, new actions::transformations::ParityEven7bit($1)); + ACTION_CONTAINER($$, new actions::transformations::ParityEven7bit()); } | ACTION_TRANSFORMATION_SQL_HEX_DECODE { - ACTION_CONTAINER($$, new actions::transformations::SqlHexDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::SqlHexDecode()); } | ACTION_TRANSFORMATION_BASE_64_ENCODE { - ACTION_CONTAINER($$, new actions::transformations::Base64Encode($1)); + ACTION_CONTAINER($$, new actions::transformations::Base64Encode()); } | ACTION_TRANSFORMATION_BASE_64_DECODE { - ACTION_CONTAINER($$, new actions::transformations::Base64Decode($1)); + ACTION_CONTAINER($$, new actions::transformations::Base64Decode()); } | ACTION_TRANSFORMATION_BASE_64_DECODE_EXT { - ACTION_CONTAINER($$, new actions::transformations::Base64DecodeExt($1)); + ACTION_CONTAINER($$, new actions::transformations::Base64DecodeExt()); } | ACTION_TRANSFORMATION_CMD_LINE { - ACTION_CONTAINER($$, new actions::transformations::CmdLine($1)); + ACTION_CONTAINER($$, new actions::transformations::CmdLine()); } | ACTION_TRANSFORMATION_SHA1 { - ACTION_CONTAINER($$, new actions::transformations::Sha1($1)); + ACTION_CONTAINER($$, new actions::transformations::Sha1()); } | ACTION_TRANSFORMATION_MD5 { - ACTION_CONTAINER($$, new actions::transformations::Md5($1)); + ACTION_CONTAINER($$, new actions::transformations::Md5()); } | ACTION_TRANSFORMATION_ESCAPE_SEQ_DECODE { - ACTION_CONTAINER($$, new actions::transformations::EscapeSeqDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::EscapeSeqDecode()); } | ACTION_TRANSFORMATION_HEX_ENCODE { - ACTION_CONTAINER($$, new actions::transformations::HexEncode($1)); + ACTION_CONTAINER($$, new actions::transformations::HexEncode()); } | ACTION_TRANSFORMATION_HEX_DECODE { - ACTION_CONTAINER($$, new actions::transformations::HexDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::HexDecode()); } | ACTION_TRANSFORMATION_LOWERCASE { - ACTION_CONTAINER($$, new actions::transformations::LowerCase($1)); + ACTION_CONTAINER($$, new actions::transformations::LowerCase()); } | ACTION_TRANSFORMATION_UPPERCASE { - ACTION_CONTAINER($$, new actions::transformations::UpperCase($1)); + ACTION_CONTAINER($$, new actions::transformations::UpperCase()); } | ACTION_TRANSFORMATION_URL_DECODE_UNI { - ACTION_CONTAINER($$, new actions::transformations::UrlDecodeUni($1)); + ACTION_CONTAINER($$, new actions::transformations::UrlDecodeUni()); } | ACTION_TRANSFORMATION_URL_DECODE { - ACTION_CONTAINER($$, new actions::transformations::UrlDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::UrlDecode()); } | ACTION_TRANSFORMATION_URL_ENCODE { - ACTION_CONTAINER($$, new actions::transformations::UrlEncode($1)); + ACTION_CONTAINER($$, new actions::transformations::UrlEncode()); } | ACTION_TRANSFORMATION_NONE { - ACTION_CONTAINER($$, new actions::transformations::None($1)); + ACTION_CONTAINER($$, new actions::transformations::None()); } | ACTION_TRANSFORMATION_COMPRESS_WHITESPACE { - ACTION_CONTAINER($$, new actions::transformations::CompressWhitespace($1)); + ACTION_CONTAINER($$, new actions::transformations::CompressWhitespace()); } | ACTION_TRANSFORMATION_REMOVE_WHITESPACE { - ACTION_CONTAINER($$, new actions::transformations::RemoveWhitespace($1)); + ACTION_CONTAINER($$, new actions::transformations::RemoveWhitespace()); } | ACTION_TRANSFORMATION_REPLACE_NULLS { - ACTION_CONTAINER($$, new actions::transformations::ReplaceNulls($1)); + ACTION_CONTAINER($$, new actions::transformations::ReplaceNulls()); } | ACTION_TRANSFORMATION_REMOVE_NULLS { - ACTION_CONTAINER($$, new actions::transformations::RemoveNulls($1)); + ACTION_CONTAINER($$, new actions::transformations::RemoveNulls()); } | ACTION_TRANSFORMATION_HTML_ENTITY_DECODE { - ACTION_CONTAINER($$, new actions::transformations::HtmlEntityDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::HtmlEntityDecode()); } | ACTION_TRANSFORMATION_JS_DECODE { - ACTION_CONTAINER($$, new actions::transformations::JsDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::JsDecode()); } | ACTION_TRANSFORMATION_CSS_DECODE { - ACTION_CONTAINER($$, new actions::transformations::CssDecode($1)); + ACTION_CONTAINER($$, new actions::transformations::CssDecode()); } | ACTION_TRANSFORMATION_TRIM { - ACTION_CONTAINER($$, new actions::transformations::Trim($1)); + ACTION_CONTAINER($$, new actions::transformations::Trim()); } | ACTION_TRANSFORMATION_TRIM_LEFT { - ACTION_CONTAINER($$, new actions::transformations::TrimLeft($1)); + ACTION_CONTAINER($$, new actions::transformations::TrimLeft()); } | ACTION_TRANSFORMATION_TRIM_RIGHT { - ACTION_CONTAINER($$, new actions::transformations::TrimRight($1)); + ACTION_CONTAINER($$, new actions::transformations::TrimRight()); } | ACTION_TRANSFORMATION_NORMALISE_PATH_WIN { - ACTION_CONTAINER($$, new actions::transformations::NormalisePathWin($1)); + ACTION_CONTAINER($$, new actions::transformations::NormalisePathWin()); } | ACTION_TRANSFORMATION_NORMALISE_PATH { - ACTION_CONTAINER($$, new actions::transformations::NormalisePath($1)); + ACTION_CONTAINER($$, new actions::transformations::NormalisePath()); } | ACTION_TRANSFORMATION_LENGTH { - ACTION_CONTAINER($$, new actions::transformations::Length($1)); + ACTION_CONTAINER($$, new actions::transformations::Length()); } | ACTION_TRANSFORMATION_UTF8_TO_UNICODE { - ACTION_CONTAINER($$, new actions::transformations::Utf8ToUnicode($1)); + ACTION_CONTAINER($$, new actions::transformations::Utf8ToUnicode()); } | ACTION_TRANSFORMATION_REMOVE_COMMENTS_CHAR { - ACTION_CONTAINER($$, new actions::transformations::RemoveCommentsChar($1)); + ACTION_CONTAINER($$, new actions::transformations::RemoveCommentsChar()); } | ACTION_TRANSFORMATION_REMOVE_COMMENTS { - ACTION_CONTAINER($$, new actions::transformations::RemoveComments($1)); + ACTION_CONTAINER($$, new actions::transformations::RemoveComments()); } | ACTION_TRANSFORMATION_REPLACE_COMMENTS { - ACTION_CONTAINER($$, new actions::transformations::ReplaceComments($1)); + ACTION_CONTAINER($$, new actions::transformations::ReplaceComments()); } ; @@ -3013,24 +3017,24 @@ setvar_action: run_time_string: run_time_string FREE_TEXT_QUOTE_MACRO_EXPANSION { - $1->appendText($2); + $1->append($2); $$ = std::move($1); } | run_time_string var { - $1->appendVar(std::move($2)); + $1->append(std::move($2)); $$ = std::move($1); } | FREE_TEXT_QUOTE_MACRO_EXPANSION { std::unique_ptr r(new RunTimeString()); - r->appendText($1); + r->append($1); $$ = std::move(r); } | var { std::unique_ptr r(new RunTimeString()); - r->appendVar(std::move($1)); + r->append(std::move($1)); $$ = std::move(r); } ; diff --git a/headers/modsecurity/rule_marker.h b/src/rule_marker.h similarity index 78% rename from headers/modsecurity/rule_marker.h rename to src/rule_marker.h index 06d5b499fa..280cacb69f 100644 --- a/headers/modsecurity/rule_marker.h +++ b/src/rule_marker.h @@ -44,13 +44,17 @@ class RuleMarker : public Rule { : Rule(std::move(fileName), lineNumber), m_name(std::make_shared(name)) { } + RuleMarker(RuleMarker &&r) : + Rule(r), + m_name(std::move(r.m_name)) + { }; - virtual bool evaluate(Transaction *transaction, - std::shared_ptr rm) override { - return evaluate(transaction); - } + RuleMarker(const RuleMarker &r) : + Rule(r), + m_name(std::move(r.m_name)) + { }; - virtual bool evaluate(Transaction *transaction) override { + virtual bool evaluate(Transaction *transaction) const override { if (transaction->isInsideAMarker()) { if (*transaction->getCurrentMarker() == *m_name) { transaction->removeMarker(); @@ -63,11 +67,14 @@ class RuleMarker : public Rule { }; - std::shared_ptr getName() { + std::shared_ptr getName() const { return m_name; } - bool isMarker() override { return true; } + virtual void dump(std::stringstream &out) const override { + Rule::dump(out); + out << "SecMarker \"" << *getName() << "\"" << std::endl; + } private: std::shared_ptr m_name; diff --git a/src/rule_message.cc b/src/rule_message.cc index 7e394c14b4..b8d1e19081 100644 --- a/src/rule_message.cc +++ b/src/rule_message.cc @@ -19,6 +19,9 @@ #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/utils/string.h" +#include "src/actions/tag.h" +#include "src/rule_with_actions.h" + namespace modsecurity { @@ -26,27 +29,25 @@ namespace modsecurity { std::string RuleMessage::_details(const RuleMessage *rm) { std::string msg; - msg.append(" [file \"" + std::string(*rm->m_ruleFile.get()) + "\"]"); - msg.append(" [line \"" + std::to_string(rm->m_ruleLine) + "\"]"); - msg.append(" [id \"" + std::to_string(rm->m_ruleId) + "\"]"); - msg.append(" [rev \"" + rm->m_rev + "\"]"); + msg.append(" [file \"" + rm->getFileName() + "\"]"); + msg.append(" [line \"" + std::to_string(rm->getLineNumber()) + "\"]"); + msg.append(" [id \"" + std::to_string(rm->getRuleId()) + "\"]"); + msg.append(" [rev \"" + rm->getRev() + "\"]"); msg.append(" [msg \"" + rm->m_message + "\"]"); msg.append(" [data \"" + utils::string::limitTo(200, rm->m_data) + "\"]"); msg.append(" [severity \"" + std::to_string(rm->m_severity) + "\"]"); - msg.append(" [ver \"" + rm->m_ver + "\"]"); - msg.append(" [maturity \"" + std::to_string(rm->m_maturity) + "\"]"); - msg.append(" [accuracy \"" + std::to_string(rm->m_accuracy) + "\"]"); - for (auto &a : rm->m_tags) { + msg.append(" [ver \"" + rm->getVer() + "\"]"); + msg.append(" [maturity \"" + std::to_string(rm->getMaturity()) + "\"]"); + msg.append(" [accuracy \"" + std::to_string(rm->getAccuracy()) + "\"]"); + for (auto a : rm->m_tags) { msg.append(" [tag \"" + a + "\"]"); } - - msg.append(" [hostname \"" + *rm->m_serverIpAddress.get() \ - + "\"]"); - msg.append(" [uri \"" + utils::string::limitTo(200, *rm->m_uriNoQueryStringDecoded.get()) + "\"]"); - msg.append(" [unique_id \"" + *rm->m_id + "\"]"); - msg.append(" [ref \"" + utils::string::limitTo(200, rm->m_reference) + "\"]"); + msg.append(" [hostname \"" + rm->getServerIpAddress() + "\"]"); + msg.append(" [uri \"" + utils::string::limitTo(200, rm->getUri()) + "\"]"); + msg.append(" [unique_id \"" + rm->getRequestId() + "\"]"); + msg.append(" [ref \"" + rm->m_reference + "\"]"); return msg; } @@ -55,9 +56,9 @@ std::string RuleMessage::_details(const RuleMessage *rm) { std::string RuleMessage::_errorLogTail(const RuleMessage *rm) { std::string msg; - msg.append("[hostname \"" + *rm->m_serverIpAddress.get() + "\"]"); - msg.append(" [uri \"" + utils::string::limitTo(200, *rm->m_uriNoQueryStringDecoded.get()) + "\"]"); - msg.append(" [unique_id \"" + *rm->m_id + "\"]"); + msg.append("[hostname \"" + rm->getServerIpAddress() + "\"]"); + msg.append(" [uri \"" + rm->getUri() + "\"]"); + msg.append(" [unique_id \"" + rm->getRequestId() + "\"]"); return msg; } @@ -68,10 +69,11 @@ std::string RuleMessage::log(const RuleMessage *rm, int props, int code) { msg.reserve(2048); if (props & ClientLogMessageInfo) { - msg.append("[client " + std::string(*rm->m_clientIpAddress.get()) + "] "); + msg.append("[client " + rm->getClientIpAddress() + "] "); } - if (rm->m_isDisruptive) { + if (rm->isDisruptive() + && (rm->m_transaction->getRuleEngineState() == RulesSet::EnabledRuleEngine)) { msg.append("ModSecurity: Access denied with code "); if (code == -1) { msg.append("%d"); @@ -79,7 +81,7 @@ std::string RuleMessage::log(const RuleMessage *rm, int props, int code) { msg.append(std::to_string(code)); } msg.append(" (phase "); - msg.append(std::to_string(rm->m_rule->getPhase() - 1) + "). "); + msg.append(std::to_string(rm->getPhase() - 1) + "). "); } else { msg.append("ModSecurity: Warning. "); } @@ -95,4 +97,131 @@ std::string RuleMessage::log(const RuleMessage *rm, int props, int code) { } -} // namespace modsecurity +const RuleWithActions *RuleMessage::getRule() const { + return m_rule; +} + + +void RuleMessage::setRule(const RuleWithActions *rule) { + m_rule = rule; +} + + +bool RuleMessage::isSettle() const { + return m_rule != nullptr; +} + + +int RuleMessage::getRuleId() const { + if (m_rule) { + return m_rule->getId(); + } + return -1; +} + + +int RuleMessage::getPhase() const { + if (m_rule) { + return m_rule->getPhase(); + } + return 0; +} + + +std::string RuleMessage::getFileName() const { + if (m_rule) { + return *m_rule->getFileName().get(); + } + return ""; +} + + +int RuleMessage::getLineNumber() const { + if (m_rule) { + return m_rule->getLineNumber(); + } + return 0; +} + + +std::string RuleMessage::getRev() const { + if (m_rule) { + return m_rule->getRevision(); + } + return ""; +} + + +std::string RuleMessage::getVer() const { + if (m_rule) { + return m_rule->getVersion(); + } + return ""; +} + + +int RuleMessage::getMaturity() const { + if (m_rule) { + return m_rule->getMaturity(); + } + return 0; +} + + +int RuleMessage::getAccuracy() const { + if (m_rule) { + return m_rule->getAccuracy(); + } + return 0; +} + + +bool RuleMessage::toBeAuditLog() const { + if (m_rule) { + return m_rule->isItToBeAuditLogged(); + } + return false; +} + + +std::string RuleMessage::getClientIpAddress() const { + if (m_transaction) { + return *m_transaction->m_clientIpAddress.get(); + } + return ""; +} + + +std::string RuleMessage::getServerIpAddress() const { + if (m_transaction) { + return *m_transaction->m_serverIpAddress.get(); + } + return ""; +} + + +std::string RuleMessage::getRequestId() const { + if (m_transaction) { + return *m_transaction->m_id.get(); + } + return ""; +} + + +std::string RuleMessage::getUri() const { + if (m_transaction) { + return *m_transaction->m_uri_no_query_string_decoded.get(); + } + return ""; +} + + +bool RuleMessage::isDisruptive() const { + if (m_rule) { + return m_rule->isDisruptive(); + } + return 0; +} + + +} // namespace modsecurity diff --git a/src/rule_script.cc b/src/rule_script.cc index e4ce531562..3018823198 100644 --- a/src/rule_script.cc +++ b/src/rule_script.cc @@ -19,23 +19,19 @@ namespace modsecurity { bool RuleScript::init(std::string *err) { - return m_lua.load(m_name, err); + return m_lua->load(m_name, err); } -bool RuleScript::evaluate(Transaction *trans, - std::shared_ptr ruleMessage) { +bool RuleScript::evaluate(Transaction *trans) const { ms_dbg_a(trans, 4, " Executing script: " + m_name + "."); - bool containsDisruptive = false; + executeActionsIndependentOfChainedRuleResult(trans); - executeActionsIndependentOfChainedRuleResult(trans, - &containsDisruptive, ruleMessage); - - bool ret = m_lua.run(trans); + bool ret = m_lua->run(trans); if (ret) { - executeActionsAfterFullMatch(trans, containsDisruptive, ruleMessage); + executeActionsAfterFullMatch(trans); } return ret; diff --git a/src/rule_script.h b/src/rule_script.h index f8b7930596..321486b093 100644 --- a/src/rule_script.h +++ b/src/rule_script.h @@ -32,6 +32,8 @@ #include "src/actions/log_data.h" #include "src/actions/severity.h" #include "src/variables/variable.h" +#include "src/rule_with_actions.h" + #ifndef SRC_RULE_SCRIPT_H_ #define SRC_RULE_SCRIPT_H_ @@ -45,20 +47,31 @@ using actions::Action; class RuleScript : public RuleWithActions { public: RuleScript(const std::string &name, - std::vector *actions, + Actions *actions, Transformations *t, std::unique_ptr fileName, int lineNumber) : RuleWithActions(actions, t, std::move(fileName), lineNumber), - m_name(name) { } + m_name(name), + m_lua(std::unique_ptr(new engine::Lua())) { } - bool init(std::string *err); - bool evaluate(Transaction *trans, - std::shared_ptr ruleMessage) override; + RuleScript(const RuleScript &rs) + : RuleWithActions(rs), + m_name(rs.m_name), + m_lua(rs.m_lua) { } + RuleScript &operator=(const RuleScript& r) { + RuleWithActions::operator = (r); + m_name = r.m_name; + m_lua = r.m_lua; + return *this; + } + + bool init(std::string *err); + bool evaluate(Transaction *trans) const override; std::string m_name; - engine::Lua m_lua; + std::shared_ptr m_lua; }; } // namespace modsecurity diff --git a/src/rule_unconditional.cc b/src/rule_unconditional.cc index 17532c67bb..d04ca4a46a 100644 --- a/src/rule_unconditional.cc +++ b/src/rule_unconditional.cc @@ -13,28 +13,23 @@ * */ -#include "modsecurity/rule_unconditional.h" +#include "src/rule_unconditional.h" namespace modsecurity { -bool RuleUnconditional::evaluate(Transaction *trans, - std::shared_ptr ruleMessage) { - RuleWithActions::evaluate(trans, ruleMessage); +bool RuleUnconditional::evaluate(Transaction *trans) const { + RuleWithActions::evaluate(trans); - // FIXME: This needs to be romeved on the runtime exeption review. - bool containsBlock = false; - - ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \ + ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \ + ") Executing unconditional rule..."); - executeActionsIndependentOfChainedRuleResult(trans, - &containsBlock, ruleMessage); + executeActionsIndependentOfChainedRuleResult(trans); - executeActionsAfterFullMatch(trans, containsBlock, ruleMessage); + executeActionsAfterFullMatch(trans); - performLogging(trans, ruleMessage); + trans->logMatchLastRuleOnTheChain(this); return true; } diff --git a/headers/modsecurity/rule_unconditional.h b/src/rule_unconditional.h similarity index 77% rename from headers/modsecurity/rule_unconditional.h rename to src/rule_unconditional.h index 04abb90ac1..c44f55eb76 100644 --- a/headers/modsecurity/rule_unconditional.h +++ b/src/rule_unconditional.h @@ -22,15 +22,15 @@ #include #endif -#ifndef HEADERS_MODSECURITY_RULE_UNCONDITIONAL_H_ -#define HEADERS_MODSECURITY_RULE_UNCONDITIONAL_H_ +#ifndef SRC_RULE_UNCONDITIONAL_H_ +#define SRC_RULE_UNCONDITIONAL_H_ #include "modsecurity/modsecurity.h" #include "modsecurity/variable_value.h" #include "modsecurity/rule.h" #include "modsecurity/rules_set.h" -#include "modsecurity/rule_with_actions.h" #include "modsecurity/actions/action.h" +#include "src/rule_with_actions.h" #ifdef __cplusplus @@ -40,13 +40,17 @@ namespace modsecurity { class RuleUnconditional : public RuleWithActions { public: RuleUnconditional( - std::vector *actions, + Actions *actions, Transformations *transformations, std::unique_ptr fileName, int lineNumber) : RuleWithActions(actions, transformations, std::move(fileName), lineNumber) { } - virtual bool evaluate(Transaction *transaction, std::shared_ptr ruleMessage) override; + RuleUnconditional(const RuleUnconditional &r) + : RuleWithActions(r) + { } + + virtual bool evaluate(Transaction *transaction) const override; private: }; @@ -56,4 +60,4 @@ class RuleUnconditional : public RuleWithActions { #endif -#endif // HEADERS_MODSECURITY_RULE_UNCONDITIONAL_H_ +#endif // SRC_RULE_UNCONDITIONAL_H_ diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index a2d7306eed..627760f626 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -18,41 +18,47 @@ #include #include -#include -#include #include +#include #include -#include #include +#include +#include -#include "modsecurity/rules_set.h" -#include "src/operators/operator.h" #include "modsecurity/actions/action.h" #include "modsecurity/modsecurity.h" -#include "src/actions/transformations/none.h" -#include "src/actions/tag.h" -#include "src/utils/string.h" #include "modsecurity/rule_message.h" -#include "modsecurity/rule_with_actions.h" -#include "src/actions/msg.h" -#include "src/actions/log_data.h" -#include "src/actions/severity.h" +#include "modsecurity/rules_set.h" +#include "src/rule_with_actions.h" +#include "src/actions/accuracy.h" +#include "src/actions/block.h" #include "src/actions/capture.h" +#include "src/actions/log_data.h" +#include "src/actions/msg.h" +#include "src/actions/maturity.h" #include "src/actions/multi_match.h" +#include "src/actions/rev.h" +#include "src/actions/log.h" +#include "src/actions/no_log.h" #include "src/actions/set_var.h" -#include "src/actions/block.h" -#include "src/variables/variable.h" +#include "src/actions/severity.h" +#include "src/actions/tag.h" +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/transformations/transformation.h" +#include "src/actions/transformations/none.h" +#include "src/actions/xmlns.h" +#include "src/utils/string.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/phase.h" +#include "src/actions/chain.h" +#include "src/actions/rule_id.h" +#include "src/actions/ver.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_allowed_in_sec_default_action.h" namespace modsecurity { -using operators::Operator; -using actions::Action; -using variables::Variable; -using actions::transformations::None; -using actions::transformations::Transformation; - - RuleWithActions::RuleWithActions( Actions *actions, @@ -60,128 +66,212 @@ RuleWithActions::RuleWithActions( std::unique_ptr fileName, int lineNumber) : Rule(std::move(fileName), lineNumber), - m_rev(""), - m_ver(""), - m_accuracy(0), - m_maturity(0), + RuleWithActionsProperties(transformations), m_ruleId(0), m_chainedRuleChild(nullptr), m_chainedRuleParent(nullptr), - m_disruptiveAction(nullptr), - m_logData(nullptr), - m_msg(nullptr), - m_severity(nullptr), - m_actionsRuntimePos(), - m_actionsSetVar(), - m_actionsTag(), - m_transformations(transformations != NULL ? *transformations : Transformations()), - m_containsCaptureAction(false), - m_containsMultiMatchAction(false), - m_containsStaticBlockAction(false), - m_isChained(false) { - + m_XmlNSs(), + m_accuracy(ACCURACY_NOT_SET), + m_maturity(MATURITY_NOT_SET), + m_severity(SEVERITY_NOT_SET), + m_containsCapture(false), + m_isChained(false), + m_revision(""), + m_version(""), + m_actionMsg(nullptr), + m_actionLogData(nullptr), + m_defaultActions() +{ + // FIXME: split confs on parser. + std::vector> confs; + std::vector> newActions; if (actions) { - for (Action *a : *actions) { - if (a->action_kind == Action::ConfigurationKind) { - a->evaluate(this, NULL); - delete a; - - } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) { - if (dynamic_cast(a)) { - m_containsCaptureAction = true; - delete a; - } else if (dynamic_cast(a)) { - m_containsMultiMatchAction = true; - delete a; - } else if (dynamic_cast(a)) { - m_severity = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_logData = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_msg = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_actionsSetVar.push_back( - dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsTag.push_back(dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsRuntimePos.push_back(a); - m_containsStaticBlockAction = true; - } else if (a->isDisruptive() == true) { - if (m_disruptiveAction != nullptr) { - delete m_disruptiveAction; - m_disruptiveAction = nullptr; - } - m_disruptiveAction = a; - } else { - m_actionsRuntimePos.push_back(a); - } - } else { - delete a; - std::cout << "General failure, action: " << a->m_name; - std::cout << " has an unknown type." << std::endl; - throw; + for (auto &a : *actions) { + if (std::dynamic_pointer_cast(a)) { + confs.push_back(std::dynamic_pointer_cast(a)); + continue; + } else if (std::dynamic_pointer_cast(a)) { + setDisruptiveAction(std::dynamic_pointer_cast(a)); + continue; } + newActions.push_back(a); } - delete actions; } -} -RuleWithActions::~RuleWithActions() { - if (m_severity) { - delete m_severity; - m_severity = nullptr; - } - if (m_logData) { - delete m_logData; - m_logData = nullptr; - } - if (m_msg) { - delete m_msg; - m_msg = nullptr; - } - while (m_transformations.empty() == false) { - auto *a = m_transformations.back(); - m_transformations.pop_back(); - delete a; + + /** + * + * Those are actions that only fit the propose to update something in + * the rule: META-DATA; e.g. RuleID. + * + * The merge action takes care of those properties. Once configured the + * action can be forgotten. + * + */ + for (auto &c : confs) { + c->configure(this); } - while (m_actionsRuntimePos.empty() == false) { - auto *a = m_actionsRuntimePos.back(); - m_actionsRuntimePos.pop_back(); - delete a; + + for (auto &a : newActions) { + if (std::dynamic_pointer_cast(a)) { + addSetVar(std::dynamic_pointer_cast(a)); + continue; + } + if (std::dynamic_pointer_cast(a)) { + addTag(std::dynamic_pointer_cast(a)); + continue; + } + if (std::dynamic_pointer_cast(a)) { + m_XmlNSs.push_back(std::dynamic_pointer_cast(a)); + continue; + } + if (std::dynamic_pointer_cast(a)) { + m_actionLogData = std::dynamic_pointer_cast(a); + continue; + } + if (std::dynamic_pointer_cast(a)) { + m_actionMsg = std::dynamic_pointer_cast(a); + continue; + } + + addGenericMatchAction(std::dynamic_pointer_cast(a)); } - while (m_actionsSetVar.empty() == false) { - auto *a = m_actionsSetVar.back(); - m_actionsSetVar.pop_back(); - delete a; + populate(this); +} + + +RuleWithActions::RuleWithActions(const RuleWithActions &r) + : Rule(r), + RuleWithActionsProperties(r), + m_ruleId(r.m_ruleId), + m_chainedRuleChild(r.m_chainedRuleChild), + m_chainedRuleParent(r.m_chainedRuleParent), + m_XmlNSs(/*r.m_XmlNSs*/), + m_accuracy(r.m_accuracy), + m_maturity(r.m_maturity), + m_severity(r.m_severity), + m_containsCapture(r.m_containsCapture), + m_isChained(r.m_isChained), + m_revision(r.m_revision), + m_version(r.m_version), + m_actionMsg(nullptr /*r.m_actionMsg*/), + m_actionLogData(nullptr /* r.m_actionLogData */), + m_defaultActions(r.m_defaultActions) { + copyActionsWithRunTimeStrings(r); + m_defaultActions.populate(this); + populate(this); +} + + +RuleWithActions &RuleWithActions::operator=(const RuleWithActions& r) { + Rule::operator = (r); + RuleWithActionsProperties::operator = (r); + m_ruleId = r.m_ruleId; + m_chainedRuleChild = r.m_chainedRuleChild; + m_chainedRuleParent = r.m_chainedRuleParent; + /*m_XmlNSs = r.m_XmlNSs;*/ + m_accuracy = r.m_accuracy; + m_maturity = r.m_maturity; + m_severity = r.m_severity; + m_containsCapture = r.m_containsCapture; + m_isChained = r.m_isChained; + m_revision = r.m_revision; + m_version = r.m_version; + /*m_actionMsg = r.m_actionMsg;*/ + /*m_actionLogData = r.m_actionLogData;*/ + m_defaultActions = r.m_defaultActions; + copyActionsWithRunTimeStrings(r); + m_defaultActions.populate(this); + populate(this); + return *this; +} + + +void inline RuleWithActions::copyActionsWithRunTimeStrings(const RuleWithActions &r) { + if (r.m_actionLogData) { + actions::ActionWithRunTimeString *arts = dynamic_cast(r.m_actionLogData.get()); + if (!arts) { + /* Humpf? */ + m_actionLogData = r.m_actionLogData; + } else { + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::ActionWithRunTimeString *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_actionLogData = z; + } } - while (m_actionsTag.empty() == false) { - auto *a = m_actionsTag.back(); - m_actionsTag.pop_back(); - delete a; + if (r.m_actionMsg) { + actions::ActionWithRunTimeString *arts = dynamic_cast(r.m_actionMsg.get()); + if (!arts) { + /* Humpf? */ + m_actionMsg = r.m_actionMsg; + } else { + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::ActionWithRunTimeString *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_actionMsg = z; + } } - if (m_disruptiveAction != nullptr) { - delete m_disruptiveAction; - m_disruptiveAction = nullptr; + for (auto &i : r.m_XmlNSs) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (!arts) { + /* Humpf? */ + m_XmlNSs.push_back(i); + } else { + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::ActionWithRunTimeString *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_XmlNSs.push_back(z); + } } } -bool RuleWithActions::evaluate(Transaction *transaction) { - RuleMessage rm(this, transaction); - std::shared_ptr rm2 = std::make_shared(&rm); - return evaluate(transaction, rm2); -} - -bool RuleWithActions::evaluate(Transaction *transaction, - std::shared_ptr ruleMessage) { +void RuleWithActions::addDefaultAction(std::shared_ptr a) { + actions::ActionAllowedAsSecDefaultAction *d = dynamic_cast(a.get()); + if (d == nullptr) { + throw std::runtime_error("Action is being used as DefaultAction but not allowed."); + } - /* Rule evaluate is pure virtual. + /** + * + * ActionWithRunTimeString needs to be aware of the Rule that it + * belongs to. It is necessary to resolve some variables + * (e.g. Rule); Clone and associate are mandatory. * - * Rule::evaluate(transaction, ruleMessage); */ + 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 (std::dynamic_pointer_cast(a)) { + m_defaultActions.addSetVar(std::dynamic_pointer_cast(a)); + return; + } + if (std::dynamic_pointer_cast(a)) { + m_defaultActions.addTag(std::dynamic_pointer_cast(a)); + return; + } + if (std::dynamic_pointer_cast(a)) { + m_defaultActions.setBlock(true); + return; + } + if (std::dynamic_pointer_cast(a)) { + m_defaultActions.setDisruptiveAction(std::dynamic_pointer_cast(a)); + return; + } + std::shared_ptr bp = std::dynamic_pointer_cast(a); + if (!bp) { + return; + } + m_defaultActions.addGenericMatchAction(bp); +} + +bool RuleWithActions::evaluate(Transaction *transaction) const { /* Matched vars needs to be clear at every new rule execution */ transaction->m_matched.clear(); @@ -189,361 +279,209 @@ bool RuleWithActions::evaluate(Transaction *transaction, } -void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans, - bool *containsBlock, std::shared_ptr ruleMessage) { +void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *trans) const { + /* setVar */ + auto f = [](Transaction *t, const std::shared_ptr &var) { + ms_dbg_a(t, 4, "Running [independent] (non-disruptive) action: " + *var->getName()); + var->execute(t); + }; + for (auto &a : m_defaultActions.getSetVars()) { f(trans, a); } + for (auto &a : getSetVars()) { f(trans, a); } - for (actions::SetVar *a : m_actionsSetVar) { - ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \ - "action: " + *a->m_name.get()); - a->evaluate(this, trans); + if (m_actionLogData) { + m_actionLogData->execute(trans); } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *a = dynamic_cast(b.second.get()); - if (a->isDisruptive() == true && *a->m_name.get() == "block") { - ms_dbg_a(trans, 9, "Rule contains a `block' action"); - *containsBlock = true; - } else if (*a->m_name.get() == "setvar") { - ms_dbg_a(trans, 4, "Running [independent] (non-disruptive) " \ - "action: " + *a->m_name.get()); - a->evaluate(this, trans, ruleMessage); - } - } - - if (m_severity) { - m_severity->evaluate(this, trans, ruleMessage); - } - - if (m_logData) { - m_logData->evaluate(this, trans, ruleMessage); - } - - if (m_msg) { - m_msg->evaluate(this, trans, ruleMessage); + if (m_actionMsg) { + m_actionMsg->execute(trans); } } -void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, - bool containsBlock, std::shared_ptr ruleMessage) { +void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans) const { bool disruptiveAlreadyExecuted = false; - for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { - if (a.get()->action_kind != actions::Action::RunTimeOnlyIfMatchKind) { - continue; - } - if (!a.get()->isDisruptive()) { - executeAction(trans, containsBlock, ruleMessage, a.get(), true); - } - } + /* tags */ + auto f = [](Transaction *t, const std::shared_ptr &tag) { + ms_dbg_a(t, 4, "Running (non-disruptive) action: " + tag->getTagName(t)); + tag->execute(t); + }; + for (auto &a : m_defaultActions.getTags()) { f(trans, a); } + for (auto &a : getTags()) { f(trans, a); } - for (actions::Tag *a : this->m_actionsTag) { - ms_dbg_a(trans, 4, "Running (non-disruptive) action: " \ - + *a->m_name.get()); - a->evaluate(this, trans, ruleMessage); - } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *a = dynamic_cast(b.second.get()); - executeAction(trans, containsBlock, ruleMessage, a, false); - disruptiveAlreadyExecuted = true; - } - for (Action *a : this->m_actionsRuntimePos) { - if (!a->isDisruptive() - && !(disruptiveAlreadyExecuted - && dynamic_cast(a))) { - executeAction(trans, containsBlock, ruleMessage, a, false); + /** + * FIXME: SecRuleUpdateActionBy should be runtime + */ + auto range = trans->m_rules->m_exceptions.m_action_pos_update_target_by_id.equal_range(m_ruleId); + for (auto it = range.first; it != range.second; ++it) { + ActionWithExecution *a = dynamic_cast(it->second.get()); + if (dynamic_cast(a)) { + trans->messageGetLast()->setRule(this); + disruptiveAlreadyExecuted = true; } + ms_dbg_a(trans, 9, "Running action placed by updateTargetById: " + *a->getName()); + a->execute(trans); } - if (!disruptiveAlreadyExecuted && m_disruptiveAction != nullptr) { - executeAction(trans, containsBlock, ruleMessage, - m_disruptiveAction, false); - } -} - -void RuleWithActions::executeAction(Transaction *trans, - bool containsBlock, std::shared_ptr ruleMessage, - Action *a, bool defaultContext) { - if (a->isDisruptive() == false && *a->m_name.get() != "block") { - ms_dbg_a(trans, 9, "Running " \ - "action: " + *a->m_name.get()); - a->evaluate(this, trans, ruleMessage); - return; - } + /* generic actions */ + auto fg = [](Transaction *t, const std::shared_ptr &a) { + ms_dbg_a(t, 9, "Running action: " + *a->getName()); + a->execute(t); + }; + for (auto &a : m_defaultActions.getGenericMatchActions()) { fg(trans, a); } + for (auto &a : getGenericMatchActions()) { fg(trans, a); } - if (defaultContext && !containsBlock) { - ms_dbg_a(trans, 4, "Ignoring action: " + *a->m_name.get() + \ - " (rule does not cotains block)"); + /* disruptive actions */ + if (disruptiveAlreadyExecuted) { return; } + auto fd = [](Transaction *t, const std::shared_ptr &a) { + if (t->getRuleEngineState() == RulesSet::EnabledRuleEngine) { + ms_dbg_a(t, 4, "Running (disruptive) action: " + *a->getName() + "."); + const ActionWithExecution *ae = dynamic_cast(a.get()); + ae->execute(t); + return; + } - if (trans->getRuleEngineState() == RulesSet::EnabledRuleEngine) { - ms_dbg_a(trans, 4, "Running (disruptive) action: " + *a->m_name.get() + \ - "."); - a->evaluate(this, trans, ruleMessage); - return; + ms_dbg_a(t, 4, "Not running disruptive action: " \ + + *a->getName() + ". SecRuleEngine is not On."); + }; + if (hasDisruptiveAction()) { + trans->messageGetLast()->setRule(this); + fd(trans, getDisruptiveAction()); + } else if ((hasBlock() || m_defaultActions.hasBlock()) && m_defaultActions.hasDisruptiveAction()) { + trans->messageGetLast()->setRule(this); + fd(trans, m_defaultActions.getDisruptiveAction()); } - - ms_dbg_a(trans, 4, "Not running any disruptive action (or block): " \ - + *a->m_name.get() + ". SecRuleEngine is not On."); } -inline void RuleWithActions::executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, +void RuleWithActions::executeTransformations( Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const { - - std::string *oldValue = (*value).get(); - std::string newValue = a->evaluate(*oldValue, trans); - - if (newValue != *oldValue) { - std::shared_ptr u(new std::string(newValue)); - if (m_containsMultiMatchAction) { - ret->push_back(std::make_pair(u, a->m_name)); - (*nth)++; - } - *value = u; - } + const std::string &in, + TransformationsResults &results) const { + int none = 0; - if (path->empty()) { - path->append(*a->m_name.get()); - } else { - path->append("," + *a->m_name.get()); - } + ModSecString ssin; + ssin.assign(in.c_str(), in.size()); + results.push_back(TransformationResult(&ssin)); - ms_dbg_a(trans, 9, " T (" + \ - std::to_string(*nth) + ") " + \ - *a->m_name.get() + ": \"" + \ - utils::string::limitTo(80, newValue) +"\""); -} - -void RuleWithActions::executeTransformations( - Transaction *trans, const std::string &in, TransformationResults &ret) { - int none = 0; - int transformations = 0; - std::string path(""); - std::shared_ptr value = - std::shared_ptr(new std::string(in)); - - if (m_containsMultiMatchAction == true) { - /* keep the original value */ - ret.push_back(std::make_pair( - std::shared_ptr(new std::string(*value)), - std::shared_ptr(new std::string(path)))); + //FIXME: none should be pre-computed. + for (auto &action : m_defaultActions.getTransformations()) { + if (dynamic_cast(action.get())) { + none++; + } } - - for (Action *a : m_transformations) { - if (a->m_isNone) { + for (auto &action : getTransformations()) { + if (dynamic_cast(action.get())) { none++; } } - - // Check for transformations on the SecDefaultAction - // Notice that first we make sure that won't be a t:none - // on the target rule. - if (none == 0) { - for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { - if (a->action_kind \ - != actions::Action::RunTimeBeforeMatchAttemptKind) { - continue; - } - - // FIXME: here the object needs to be a transformation already. - Transformation *t = dynamic_cast(a.get()); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + // FIXME: It can't be something different from transformation. Sort this + // on rules compile time. + auto range = trans->m_rules->m_exceptions.m_action_transformation_update_target_by_id.equal_range(m_ruleId); + for (auto it = range.first; it != range.second; ++it) { + Transformation *t = it->second.get(); + if (dynamic_cast(t)) { + none++; } } - for (Transformation *a : m_transformations) { + for (auto &t : m_defaultActions.getTransformations()) { if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + executeTransformation(trans, &results, t.get()); } - if (a->m_isNone) { + if (dynamic_cast(t.get())) { none--; } } - // FIXME: It can't be something different from transformation. Sort this - // on rules compile time. - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; + for (auto &t : getTransformations()) { + if (none == 0) { + executeTransformation(trans, &results, t.get()); } - Transformation *a = dynamic_cast(b.second.get()); - if (a->m_isNone) { - none++; + if (dynamic_cast(t.get())) { + none--; } } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - Transformation *a = dynamic_cast(b.second.get()); + for (auto it = range.first; it != range.second; ++it) { + Transformation *t = it->second.get(); if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + executeTransformation(trans, &results, t); } - if (a->m_isNone) { + if (dynamic_cast(t)) { none--; } } +} - if (m_containsMultiMatchAction == true) { - ms_dbg_a(trans, 9, "multiMatch is enabled. " \ - + std::to_string(ret.size()) + \ - " values to be tested."); - } - if (!m_containsMultiMatchAction) { - ret.push_back(std::make_pair( - std::shared_ptr(new std::string(*value)), - std::shared_ptr(new std::string(path)))); - } + +void RuleWithActions::executeTransformation( + Transaction *transaction, + TransformationsResults *ret, + Transformation *transformation) { + executeTransformation( + transaction, + *ret->back().getAfter(), + ret, + transformation + ); } -bool RuleWithActions::containsTag(const std::string& name, Transaction *t) { - for (auto &tag : m_actionsTag) { - if (tag != NULL && tag->getName(t) == name) { - return true; - } - } - return false; -} +void RuleWithActions::executeTransformation( + Transaction *transaction, + ModSecString &in, + TransformationsResults *ret, + Transformation *transformation) { + + ModSecString out; + transformation->execute(transaction, in, out); + ms_dbg_a(transaction, 9, " T (" + std::to_string(ret->size() - 1) + ") " + \ + *transformation->getName() + ": \"" + \ + utils::string::limitTo(80, out.c_str()) + "\""); -bool RuleWithActions::containsMsg(const std::string& name, Transaction *t) { - return m_msg && m_msg->data(t) == name; + ret->push_back( + TransformationResult( + out, + transformation->getName() + ) + ); } -std::vector RuleWithActions::getActionsByName(const std::string& name, - Transaction *trans) { - std::vector ret; - for (auto &z : m_actionsRuntimePos) { - if (*z->m_name.get() == name) { - ret.push_back(z); - } - } - for (auto &z : m_transformations) { - if (*z->m_name.get() == name) { - ret.push_back(z); - } - } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *z = dynamic_cast(b.second.get()); - if (*z->m_name.get() == name) { - ret.push_back(z); +bool RuleWithActions::containsTag(const std::string& name, const Transaction *t) const noexcept { + for (auto &tag : m_defaultActions.getTags()) { + if (tag != nullptr && tag->getTagName(t) == name) { + return true; } } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *z = dynamic_cast(b.second.get()); - if (*z->m_name.get() == name) { - ret.push_back(z); + for (auto &tag : getTags()) { + if (tag != nullptr && tag->getTagName(t) == name) { + return true; } } - return ret; + return false; } -void RuleWithActions::performLogging(Transaction *trans, - std::shared_ptr ruleMessage, - bool lastLog, - bool chainedParentNull) { - /* last rule in the chain. */ - bool isItToBeLogged = ruleMessage->m_saveMessage; +bool RuleWithActions::containsMsg(const std::string& name, const Transaction *t) const noexcept { + return m_actionMsg && m_actionMsg->getEvaluatedRunTimeString(t) == name; +} - /** - * - * RuleMessage is stacked allocated for the rule execution, - * anything beyond this may lead to invalid pointer access. - * - * In case of a warning, o set of messages is saved to be read - * at audit log generation. Therefore demands a copy here. - * - * FIXME: Study an way to avoid the copy. - * - **/ - if (lastLog) { - if (chainedParentNull) { - isItToBeLogged = (ruleMessage->m_saveMessage && (m_chainedRuleParent == nullptr)); - if (isItToBeLogged && !hasMultimatch()) { - /* warn */ - trans->m_rulesMessages.push_back(*ruleMessage); - - /* error */ - if (!ruleMessage->m_isDisruptive) { - trans->serverLog(ruleMessage); - } - } - } else if (hasBlockAction() && !hasMultimatch()) { - /* warn */ - trans->m_rulesMessages.push_back(*ruleMessage); - /* error */ - if (!ruleMessage->m_isDisruptive) { - trans->serverLog(ruleMessage); - } - } else { - if (isItToBeLogged && !hasMultimatch() - && !ruleMessage->m_message.empty()) { - /* warn */ - trans->m_rulesMessages.push_back(*ruleMessage); - - /* error */ - if (!ruleMessage->m_isDisruptive) { - trans->serverLog(ruleMessage); - } - } - } - } else { - if (hasMultimatch() && isItToBeLogged) { - /* warn */ - trans->m_rulesMessages.push_back(*ruleMessage.get()); - - /* error */ - if (!ruleMessage->m_isDisruptive) { - trans->serverLog(ruleMessage); - } - RuleMessage *rm = new RuleMessage(this, trans); - rm->m_saveMessage = ruleMessage->m_saveMessage; - ruleMessage.reset(rm); - } - } +std::string RuleWithActions::getLogData(const Transaction *t) const noexcept { + return m_actionLogData->getEvaluatedRunTimeString(t); } -std::string RuleWithActions::logData(Transaction *t) { return m_logData->data(t); } -std::string RuleWithActions::msg(Transaction *t) { return m_msg->data(t); } -int RuleWithActions::severity() const { return m_severity->m_severity; } +std::string RuleWithActions::getMessage(const Transaction *t) const noexcept { + return m_actionMsg->getEvaluatedRunTimeString(t); +} } // namespace modsecurity diff --git a/src/rule_with_actions.h b/src/rule_with_actions.h new file mode 100644 index 0000000000..865170bc22 --- /dev/null +++ b/src/rule_with_actions.h @@ -0,0 +1,377 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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. + * + */ + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include +#endif + +#ifndef SRC_RULE_WITH_ACTIONS_H_ +#define SRC_RULE_WITH_ACTIONS_H_ + +#include "modsecurity/actions/action.h" +#include "modsecurity/modsecurity.h" +#include "modsecurity/rule.h" +#include "modsecurity/rule_message.h" +#include "modsecurity/rules_set.h" +#include "modsecurity/transaction.h" +#include "modsecurity/variable_value.h" +#include "src/actions/action_allowed_in_sec_default_action.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/action_with_execution.h" +#include "src/actions/action_with_run_time_string.h" +#include "src/actions/disruptive/disruptive_action.h" +#include "src/actions/transformations/transformation.h" +#include "src/actions/xmlns.h" +#include "src/rule_with_actions.h" +#include "src/rule_with_actions_properties.h" +#include "src/utils/string.h" +#include "src/transformation_result.h" + +#ifdef __cplusplus + + +namespace modsecurity { + using XmlNSs = std::vector >; + using XmlNSsPtr = std::vector; + + +namespace actions { +class Action; +class Severity; +class LogData; +class Msg; +class Rev; +class XmlNS; +namespace transformations { +class Transformation; +} +} + + +class RuleWithActions : public Rule, public RuleWithActionsProperties { + public: + + using Action = actions::Action; + using Actions = std::vector>; + using ActionTypeRuleMetaData = actions::ActionTypeRuleMetaData; + + const unsigned int SEVERITY_NOT_SET = 10; + const unsigned int ACCURACY_NOT_SET = 10; + const unsigned int MATURITY_NOT_SET = 10; + + RuleWithActions( + Actions *a, + Transformations *t, + std::unique_ptr fileName, + int lineNumber); + + RuleWithActions(const RuleWithActions &r); + RuleWithActions &operator=(const RuleWithActions& r); + + virtual bool evaluate(Transaction *transaction) const override; + + void executeActionsIndependentOfChainedRuleResult( + Transaction *trasaction) const; + + void executeActionsAfterFullMatch( + Transaction *transaction) const; + + // FIXME: Pass a callback for the transformation execution. + static void executeTransformation( + Transaction *transaction, + TransformationsResults *ret, + Transformation *transformation); + + static void executeTransformation( + Transaction *transaction, + ModSecString &in, + TransformationsResults *ret, + Transformation *transformation); + + void executeTransformations( + Transaction *transaction, + const std::string &value, + TransformationsResults &results) const; + + /* */ + bool containsTag(const std::string& name, const Transaction *t) const noexcept; + bool containsMsg(const std::string& name, const Transaction *t) const noexcept; + + + /* default Actions */ + void clearDefaultActions() { + m_defaultActions.clear(); + } + void addDefaultAction(std::shared_ptr a); + void addDefaulTransformation(std::shared_ptr t) { + m_defaultActions.addTransformation(t); + } + + + /* rule id */ + // FIXME: not ever rule has an id. e.g. chained rule. */ + inline const RuleId getId() const noexcept { return m_ruleId; } + void setId(int id) noexcept { + m_ruleId = id; + } + + + /* capture */ + inline void setHasCapture(bool b) noexcept { + m_containsCapture = b; + } + inline bool hasCapture() const noexcept { + return m_containsCapture; + } + + + /* accuracy */ + inline const int getAccuracy() const noexcept { + return m_accuracy; + } + inline void setAccuracy(unsigned int accuracy) noexcept { + m_accuracy = accuracy; + } + inline bool hasAccuracy() const noexcept { + return m_accuracy != ACCURACY_NOT_SET; + } + + + /* severity */ + inline int getSeverity() const noexcept { + return m_severity; + } + inline void setSeverity(unsigned int severity) noexcept { + m_severity = severity; + } + inline bool hasSeverity() const noexcept { + return m_severity != SEVERITY_NOT_SET; + } + + + /* revision */ + inline const std::string getRevision() const noexcept { + return m_revision; + }; + inline void setRevision(const std::string &revision) noexcept { + m_revision.assign(revision); + } + inline bool hasRevision() const noexcept { + return m_revision != ""; + } + + + /* version */ + inline const std::string getVersion() const noexcept { + return m_version; + }; + inline void setVersion(const std::string &version) noexcept { + m_version.assign(version); + } + inline bool hasVersion() const noexcept { + return m_version != ""; + } + + + /* maturity */ + inline const int getMaturity() const noexcept { + return m_maturity; + } + inline void setMaturity(unsigned int maturity) noexcept { + m_maturity = maturity; + } + inline bool hasMaturity() const noexcept { + return m_maturity != MATURITY_NOT_SET; + } + + + /* logData */ + inline std::shared_ptr getLogDataAction() const noexcept { + return m_actionLogData; + } + std::string getLogData(const Transaction *t) const noexcept; + inline void setLogDataAction(const std::shared_ptr &data) noexcept { + m_actionLogData = data; + } + inline bool hasLogDataAction() const noexcept { + return m_actionLogData != nullptr; + } + + + /* message */ + inline std::shared_ptr getMessageAction() const noexcept { + return m_actionMsg; + } + std::string getMessage(const Transaction *t) const noexcept; + inline void setMessageAction(const std::shared_ptr &msg) noexcept { + m_actionMsg = msg; + } + inline bool hasMessageAction() const noexcept { + return m_actionMsg != nullptr; + } + + + /* multimatch */ + inline bool processMultiMatch() const noexcept { + return hasMultiMatch() || m_defaultActions.hasMultiMatch(); + } + + + /* isDisruptive */ + inline bool isDisruptive() const { + return hasDisruptiveAction() || ((m_defaultActions.hasBlock() || hasBlock()) && m_defaultActions.hasBlock()); + } + + + /* logging */ + inline bool isItToBeLogged() const noexcept { + if (hasNoLog()) { + return false; + } + if (m_defaultActions.hasNoLog() && !hasNoLog()) { + return false; + } + if (!hasDisruptiveAction() && !(hasBlock() || m_defaultActions.hasBlock())) { + return false; + } + if (!m_defaultActions.hasDisruptiveAction() && !hasDisruptiveAction()) { + return false; + } + return true; + } + + inline bool isItToBeAuditLogged() const noexcept { + if (hasAuditLog()) { + return true; + } + if (m_defaultActions.hasAuditLog() && !hasNoAuditLog()) { + return true; + } + if (isItToBeLogged()) { + return true; + } + return false; + } + + + /* chained rule */ + /* FIXME: The chained rule needs to have its own class. */ + void setChainedNext(std::unique_ptr r) { + m_chainedRuleChild = std::move(r); + } + inline RuleWithActions *getChainedNext() const { + return m_chainedRuleChild.get(); + } + void setChainedParent(RuleWithActions *r) { + m_chainedRuleParent = r; + } + inline RuleWithActions *getChainedParent() { + return m_chainedRuleParent; + } + inline bool hasChainAction() const { return m_isChained == true; } + inline void setHasChainAction(bool b) { m_isChained = b; } + inline bool hasChainedParent() const { return m_chainedRuleParent != nullptr; } + inline bool hasChainedChild() const { return m_chainedRuleChild.get() != nullptr; } + + + + 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. + * + */ + XmlNSsPtr dst; + for (auto &a : m_XmlNSs) { + dst.push_back(a.get()); + } + + return dst; + } + + + virtual void dump(std::stringstream &out) const override { + out << "RuleWithActions" << std::endl; + } + + private: + void inline copyActionsWithRunTimeStrings(const RuleWithActions &o); + + RuleId m_ruleId; + + std::shared_ptr m_chainedRuleChild; + RuleWithActions *m_chainedRuleParent; + + /* xmlns */ + XmlNSs m_XmlNSs; + + /** + * 1-9 where 9 is very strong and 1 has many false positives + */ + unsigned int m_accuracy:4; + /** + * 1-9 where 9 is extensively tested and 1 is a brand new experimental rule + */ + unsigned int m_maturity:4; + /** + * 0 - EMERGENCY: is generated from correlation of anomaly + * scoring data where there is an inbound + * attack and an outbound leakage. + * 1 - ALERT: is generated from correlation where there is + * an inbound attack and an outbound application + * level error. + * 2 - CRITICAL: Anomaly Score of 5. Is the highest severity + * level possible without correlation. It is + * normally generated by the web attack rules + * (40 level files). + * 3 - ERROR: Error - Anomaly Score of 4. Is generated mostly + * from outbound leakage rules (50 level files). + * 4 - WARNING: Anomaly Score of 3. Is generated by malicious + * client rules (35 level files). + * 5 - NOTICE: Anomaly Score of 2. Is generated by the Protocol + * policy and anomaly files. + * 6 - INFO + * 7 - DEBUG + **/ + unsigned int m_severity:4; + bool m_containsCapture:1; + bool m_isChained:1; + std::string m_revision; + std::string m_version; + std::shared_ptr m_actionMsg; + std::shared_ptr m_actionLogData; + + /* SecDefaultAction */ + RuleWithActionsProperties m_defaultActions; +}; + +} // namespace modsecurity +#endif + + +#endif // SRC_RULE_WITH_ACTIONS_H_ + diff --git a/src/rule_with_actions_properties.cc b/src/rule_with_actions_properties.cc new file mode 100644 index 0000000000..a7b3a466f5 --- /dev/null +++ b/src/rule_with_actions_properties.cc @@ -0,0 +1,150 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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/rule.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/actions/set_var.h" +#include "src/actions/tag.h" +#include "src/actions/transformations/transformation.h" + + +namespace modsecurity { + + +RuleWithActionsProperties::RuleWithActionsProperties(Transformations *transformations) : + m_hasAuditLog(false), + m_hasBlock(false), + m_hasLog(false), + m_hasMultiMatch(false), + m_hasNoAuditLog(false), + m_hasNoLog(false), + m_executeIfMatchActions(), + m_setVars(), + m_disruptiveAction(nullptr), + m_tags(), + m_transformations(transformations != nullptr ? *transformations : Transformations()) +{ } + + + +RuleWithActionsProperties::RuleWithActionsProperties(const RuleWithActionsProperties &o) : + m_hasAuditLog(o.m_hasAuditLog), + m_hasBlock(o.m_hasBlock), + m_hasLog(o.m_hasLog), + m_hasMultiMatch(o.m_hasMultiMatch), + m_hasNoAuditLog(o.m_hasNoAuditLog), + m_hasNoLog(o.m_hasNoAuditLog), + m_executeIfMatchActions(), + m_setVars(), + m_disruptiveAction(o.m_disruptiveAction), + m_tags(), + m_transformations(o.m_transformations) +{ + copyActionsWithRunTimeStrings(o); +} + + +RuleWithActionsProperties &RuleWithActionsProperties::operator=(const RuleWithActionsProperties &o) { + m_hasAuditLog = o.m_hasAuditLog; + m_hasBlock = o.m_hasBlock; + m_hasLog = o.m_hasLog; + m_hasMultiMatch = o.m_hasMultiMatch; + m_hasNoAuditLog = o.m_hasNoAuditLog; + m_hasNoLog = o.m_hasNoAuditLog; + m_disruptiveAction = o.m_disruptiveAction; + m_transformations = o.m_transformations; + copyActionsWithRunTimeStrings(o); + + return *this; +} + + +void inline RuleWithActionsProperties::copyActionsWithRunTimeStrings(const RuleWithActionsProperties &o) { + for (auto &i : o.m_executeIfMatchActions) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (!arts) { + m_executeIfMatchActions.push_back(i); + continue; + } + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::ActionWithRunTimeString *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_executeIfMatchActions.push_back(z); + } + for (auto &i : o.m_setVars) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (!arts) { + m_setVars.push_back(i); + continue; + } + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::ActionWithRunTimeString *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_setVars.push_back(z); + } + for (auto &i : o.m_tags) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (!arts) { + m_tags.push_back(i); + continue; + } + std::shared_ptr z(dynamic_cast(arts->clone())); + actions::Tag *aa = dynamic_cast(z.get()); + aa->populate(nullptr); + m_tags.push_back(z); + } +} + + +void RuleWithActionsProperties::populate(const RuleWithActions *r) const { + /** + * + * ActionWithRunTimeString needs to be aware of the Rule that it + * belongs to. It is necessary to resolve some variables + * (e.g. Rule); Clone and associate are mandatory. + * + */ + for (auto &i : m_executeIfMatchActions) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (arts != nullptr) { + arts->populate(r); + } + } + for (auto &i : m_setVars) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (arts != nullptr) { + arts->populate(r); + } + } + for (auto &i : m_tags) { + actions::ActionWithRunTimeString *arts = dynamic_cast(i.get()); + if (arts != nullptr) { + arts->populate(r); + } + } +} + + +} // namespace modsecurity diff --git a/src/rule_with_actions_properties.h b/src/rule_with_actions_properties.h new file mode 100644 index 0000000000..32a86ed8ab --- /dev/null +++ b/src/rule_with_actions_properties.h @@ -0,0 +1,213 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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. + * + */ + + +#ifndef SRC_RULE_WITH_ACTIONS_PROPERTIES_H_ +#define SRC_RULE_WITH_ACTIONS_PROPERTIES_H_ + + +#include "modsecurity/modsecurity.h" +#include "src/actions/action_with_execution.h" +#include "src/actions/disruptive/disruptive_action.h" + +namespace modsecurity { + +namespace actions { +class SetVar; +class Tag; +namespace transformations { +class Transformation; +} +} + + +class RuleWithActionsProperties { + /** + * Properties that can be part of the SecDefaultActions. + * + */ + public: + using ActionWithExecution = actions::ActionWithExecution; + using ActionDisruptive = actions::disruptive::ActionDisruptive; + using MatchActions = std::vector>; + using SetVar = actions::SetVar; + using SetVars = std::vector>; + using Tag = actions::Tag; + using Tags = std::vector>; + using Transformation = actions::transformations::Transformation; + using Transformations = std::vector>; + + explicit RuleWithActionsProperties(Transformations *transformations = nullptr); + ~RuleWithActionsProperties() { + /* all the allocated resources are shared pointers. */ + } + + RuleWithActionsProperties(const RuleWithActionsProperties &o); + RuleWithActionsProperties &operator=(const RuleWithActionsProperties &o); + RuleWithActionsProperties(RuleWithActionsProperties &&o) = delete; + + + void clear() { + m_hasLog = false; + m_hasNoLog = false; + m_hasBlock = false; + m_setVars.clear(); + m_tags.clear(); + m_disruptiveAction = nullptr; + m_executeIfMatchActions.clear(); + m_transformations.clear(); + }; + + void populate(const RuleWithActions *r) const; + + + /* auditLog */ + bool hasAuditLog() const noexcept { + return m_hasAuditLog; + } + void setAuditLog(bool b) { + m_hasAuditLog = b; + } + + + /* log */ + bool hasLog() const noexcept { + return m_hasLog; + } + void setLog(bool b) { + m_hasLog = b; + } + + + /* MultiMatch */ + bool hasMultiMatch() const noexcept { + return m_hasMultiMatch; + } + void setMultiMatch(bool b) { + m_hasMultiMatch = b; + } + + + /* noAuditLog */ + bool hasNoAuditLog() const noexcept { + return m_hasNoAuditLog; + } + void setNoAuditLog(bool b) { + m_hasNoAuditLog = b; + } + + + /* noLog */ + bool hasNoLog() const noexcept { + return m_hasNoLog; + } + void setNoLog(bool b) { + m_hasNoLog = b; + } + + + /* block */ + bool hasBlock() const noexcept { + return m_hasBlock; + } + void setBlock(bool b) { + m_hasBlock = b; + } + + + /* transformations */ + const Transformations &getTransformations() const noexcept { + return m_transformations; + } + void addTransformation(std::shared_ptr t) { + m_transformations.push_back(t); + } + + + /* tags */ + const Tags &getTags() const noexcept { + return m_tags; + } + void setTags(Tags tags) noexcept { + m_tags.insert(m_tags.end(), tags.begin(), tags.end()); + } + void addTag(std::shared_ptr t) { + m_tags.push_back(t); + } + bool hasTags() const noexcept { + return !m_tags.empty(); + } + void clearTags() noexcept { + m_tags.clear(); + } + + + /* vars */ + const SetVars &getSetVars() const noexcept { + return m_setVars; + } + void addSetVar(std::shared_ptr t) { + m_setVars.push_back(t); + } + + + /* other match actions */ + const MatchActions &getGenericMatchActions() const noexcept { + return m_executeIfMatchActions; + } + void addGenericMatchAction(std::shared_ptr a) { + m_executeIfMatchActions.push_back(a); + } + + + /* disruptive action */ + const std::shared_ptr &getDisruptiveAction() const noexcept { + return m_disruptiveAction; + } + inline void setDisruptiveAction(std::shared_ptr d) noexcept { + m_disruptiveAction = d; + } + inline bool hasDisruptiveAction() const noexcept { + return m_disruptiveAction != nullptr; + } + + + private: + void inline copyActionsWithRunTimeStrings(const RuleWithActionsProperties &o); + + /** + * FIXME: log, noLog, AuditLog and noAuditLog are save to compute whenver log + * is necessary or not. This can be pre-computed while the actions are + * encountered amoung the rule action list. + * + */ + bool m_hasAuditLog:1; + bool m_hasBlock:1; + bool m_hasLog:1; + bool m_hasMultiMatch:1; + bool m_hasNoAuditLog:1; + bool m_hasNoLog:1; + + MatchActions m_executeIfMatchActions; + SetVars m_setVars; + std::shared_ptr m_disruptiveAction; + Tags m_tags; + Transformations m_transformations; +}; + +} // namespace modsecurity + + +#endif // SRC_RULE_WITH_ACTIONS_PROPERTIES_H_ \ No newline at end of file diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 9e8305b967..9bef6d52dc 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -13,7 +13,6 @@ * */ -#include "modsecurity/rule_with_operator.h" #include @@ -41,6 +40,10 @@ #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 { @@ -53,44 +56,44 @@ using actions::transformations::None; RuleWithOperator::RuleWithOperator(Operator *op, variables::Variables *_variables, - std::vector *actions, + Actions *actions, Transformations *transformations, std::unique_ptr fileName, int lineNumber) : RuleWithActions(actions, transformations, std::move(fileName), lineNumber), - m_variables(_variables), - m_operator(op) { /* */ } + m_variables(std::unique_ptr(_variables)), + m_operator(std::unique_ptr(op)) { + for (auto &a : *m_variables.get()) { + variables::RuleVariable *vrule = dynamic_cast(a); + if (vrule != nullptr) { + vrule->populate(this); + } + } + } -RuleWithOperator::~RuleWithOperator() { - if (m_operator != NULL) { - delete m_operator; - } - while (m_variables != NULL && m_variables->empty() == false) { - auto *a = m_variables->back(); - m_variables->pop_back(); - delete a; - } - if (m_variables != NULL) { - delete m_variables; - } +RuleWithOperator::~RuleWithOperator() { } -void RuleWithOperator::updateMatchedVars(Transaction *trans, const std::string &key, - const std::string &value) { +void RuleWithOperator::updateMatchedVars(Transaction *trans, + const VariableValue *v, + const bpstd::string_view &value) { + // FIXME: Memory leak. + const std::string *key = new std::string(v->getName()); + ms_dbg_a(trans, 9, "Matched vars updated."); trans->m_variableMatchedVar.set(value, trans->m_variableOffset); - trans->m_variableMatchedVarName.set(key, trans->m_variableOffset); + trans->m_variableMatchedVarName.set(*key, trans->m_variableOffset); - trans->m_variableMatchedVars.set(key, value, trans->m_variableOffset); - trans->m_variableMatchedVarsNames.set(key, key, trans->m_variableOffset); + trans->m_variableMatchedVars.set(*key, value, trans->m_variableOffset); + trans->m_variableMatchedVarsNames.set(*key, *key, trans->m_variableOffset); } -void RuleWithOperator::cleanMatchedVars(Transaction *trans) { +inline void RuleWithOperator::cleanMatchedVars(Transaction *trans) { ms_dbg_a(trans, 9, "Matched vars cleaned."); trans->m_variableMatchedVar.unset(); trans->m_variableMatchedVars.unset(); @@ -99,9 +102,9 @@ void RuleWithOperator::cleanMatchedVars(Transaction *trans) { } - -bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string &key, - std::string value, std::shared_ptr ruleMessage) { +bool RuleWithOperator::executeOperatorAt(Transaction *trans, + const VariableValue *v, + const bpstd::string_view &value) const { #if MSC_EXEC_CLOCK_ENABLED clock_t begin = clock(); clock_t end; @@ -109,15 +112,12 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & #endif bool ret; - ms_dbg_a(trans, 9, "Target value: \"" + utils::string::limitTo(80, - utils::string::toHexIfNeeded(value)) \ - + "\" (Variable: " + key + ")"); + ms_dbg_a(trans, 9, "Target value: \"" \ + + utils::string::limitTo(80, + utils::string::toHexIfNeeded(value.to_string())) \ + + "\" (Variable: " + v->getName() + ")"); - ret = this->m_operator->evaluateInternal(trans, this, value, ruleMessage); - - if (ret == false) { - return false; - } + ret = m_operator->evaluateInternal(trans, this, value, trans->messageGetLast()); #if MSC_EXEC_CLOCK_ENABLED end = clock(); @@ -131,7 +131,7 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & void RuleWithOperator::getVariablesExceptions(Transaction *t, - variables::Variables *exclusion, variables::Variables *addition) { + variables::Variables *exclusion, variables::Variables *addition) const { for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { if (containsTag(*a.first.get(), t) == false) { continue; @@ -161,7 +161,7 @@ void RuleWithOperator::getVariablesExceptions(Transaction *t, } for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) { - if (m_ruleId != a.first) { + if (getId() != a.first) { continue; } Variable *b = a.second.get(); @@ -177,7 +177,7 @@ void RuleWithOperator::getVariablesExceptions(Transaction *t, inline void RuleWithOperator::getFinalVars(variables::Variables *vars, - variables::Variables *exclusion, Transaction *trans) { + variables::Variables *exclusion, Transaction *trans) const { variables::Variables addition; getVariablesExceptions(trans, exclusion, &addition); @@ -189,17 +189,25 @@ inline void RuleWithOperator::getFinalVars(variables::Variables *vars, if (std::find_if(trans->m_ruleRemoveTargetById.begin(), trans->m_ruleRemoveTargetById.end(), [&, variable, this](std::pair &m) -> bool { - return m.first == m_ruleId - && m.second == *variable->m_fullName.get(); + return m.first == getId() + && m.second == *variable->getVariableKeyWithCollection(); }) != trans->m_ruleRemoveTargetById.end()) { continue; } + if (std::find_if(trans->m_ruleRemoveTargetByIdRange.begin(), + trans->m_ruleRemoveTargetByIdRange.end(), + [&, variable, this](std::pair, std::string> &m) -> bool { + return (m.first.first <= getId() && m.first.second >= getId() + && m.second == *variable->getVariableKeyWithCollection()); + }) != trans->m_ruleRemoveTargetByIdRange.end()) { + continue; + } if (std::find_if(trans->m_ruleRemoveTargetByTag.begin(), trans->m_ruleRemoveTargetByTag.end(), [&, variable, trans, this]( std::pair &m) -> bool { return containsTag(m.first, trans) - && m.second == *variable->m_fullName.get(); + && m.second == *variable->getVariableKeyWithCollection(); }) != trans->m_ruleRemoveTargetByTag.end()) { continue; } @@ -213,34 +221,31 @@ inline void RuleWithOperator::getFinalVars(variables::Variables *vars, } -bool RuleWithOperator::evaluate(Transaction *trans, - std::shared_ptr ruleMessage) { +bool RuleWithOperator::evaluate(Transaction *trans) const { bool globalRet = false; - variables::Variables *variables = this->m_variables; + variables::Variables *variables = m_variables.get(); bool recursiveGlobalRet; - bool containsBlock = hasBlockAction(); std::string eparam; variables::Variables vars; vars.reserve(4); variables::Variables exclusion; - RuleWithActions::evaluate(trans, ruleMessage); - + RuleWithActions::evaluate(trans); // FIXME: Make a class runTimeException to handle this cases. for (auto &i : trans->m_ruleRemoveById) { - if (m_ruleId != i) { + if (getId() != i) { continue; } - ms_dbg_a(trans, 9, "Rule id: " + std::to_string(m_ruleId) + + ms_dbg_a(trans, 9, "Rule id: " + std::to_string(getId()) + " was skipped due to a ruleRemoveById action..."); return true; } for (auto &i : trans->m_ruleRemoveByIdRange) { - if (!(i.first <= m_ruleId && i.second >= m_ruleId)) { + if (!(i.first <= getId() && i.second >= getId())) { continue; } - ms_dbg_a(trans, 9, "Rule id: " + std::to_string(m_ruleId) + + ms_dbg_a(trans, 9, "Rule id: " + std::to_string(getId()) + " was skipped due to a ruleRemoveById action..."); return true; } @@ -254,14 +259,14 @@ bool RuleWithOperator::evaluate(Transaction *trans, } else { eparam = "\"" + eparam + "\""; } - ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \ + ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \ + ") Executing operator \"" + getOperatorName() \ + "\" with param " \ + eparam \ + " against " \ + variables + "."); } else { - ms_dbg_a(trans, 4, "(Rule: " + std::to_string(m_ruleId) \ + ms_dbg_a(trans, 4, "(Rule: " + std::to_string(getId()) \ + ") Executing operator \"" + getOperatorName() \ + " against " \ + variables + "."); @@ -270,71 +275,94 @@ bool RuleWithOperator::evaluate(Transaction *trans, getFinalVars(&vars, &exclusion, trans); + VariableValues e; for (auto &var : vars) { - std::vector e; if (!var) { continue; } - var->evaluate(trans, this, &e); - for (const VariableValue *v : e) { + e.clear(); + var->evaluate(trans, &e); + for (const auto &vv : e) { + TransformationsResults transformationsResults; + const VariableValue *v = vv.get(); const std::string &value = v->getValue(); - const std::string &key = v->getKeyWithCollection(); if (exclusion.contains(v) || std::find_if(trans->m_ruleRemoveTargetById.begin(), trans->m_ruleRemoveTargetById.end(), [&, v, this](std::pair &m) -> bool { - return m.first == m_ruleId && m.second == v->getKeyWithCollection(); + return m.first == getId() && m.second == v->getName(); }) != trans->m_ruleRemoveTargetById.end() ) { - delete v; - v = NULL; continue; } + + if (exclusion.contains(v) || + std::find_if(trans->m_ruleRemoveTargetByIdRange.begin(), + trans->m_ruleRemoveTargetByIdRange.end(), + [&, v, this](std::pair, std::string> &m) -> bool { + return (m.first.first <= getId() && m.first.second >= getId() + && m.second == v->getName()); + }) != trans->m_ruleRemoveTargetByIdRange.end() + ) { + continue; + } + if (exclusion.contains(v) || std::find_if(trans->m_ruleRemoveTargetByTag.begin(), trans->m_ruleRemoveTargetByTag.end(), [&, v, trans, this](std::pair &m) -> bool { - return containsTag(m.first, trans) && m.second == v->getKeyWithCollection(); + return containsTag(m.first, trans) && m.second == v->getName(); }) != trans->m_ruleRemoveTargetByTag.end() ) { - delete v; - v = NULL; continue; } - TransformationResults values; - - executeTransformations(trans, value, values); + executeTransformations(trans, value, transformationsResults); - for (const auto &valueTemp : values) { + auto iter = transformationsResults.begin(); + if (!processMultiMatch()) { + iter = transformationsResults.end(); + std::advance(iter, -1); + } + while (iter != transformationsResults.end()) { bool ret; - std::string valueAfterTrans = std::move(*valueTemp.first); + auto &valueTemp = *iter; + bpstd::string_view view = *valueTemp.getAfter(); - ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); + ret = executeOperatorAt(trans, v, view); if (ret == true) { - ruleMessage->m_match = m_operator->resolveMatchMessage(trans, - key, value); - for (auto &i : v->getOrigin()) { - ruleMessage->m_reference.append(i->toText()); + trans->messageGetLast()->m_match = m_operator->resolveMatchMessage(trans, v); + + for (const auto &i : v->getOrigin()) { + trans->messageGetLast()->m_reference.append(i.toText()); } - ruleMessage->m_reference.append(*valueTemp.second); - updateMatchedVars(trans, key, valueAfterTrans); - executeActionsIndependentOfChainedRuleResult(trans, - &containsBlock, ruleMessage); + auto iter2 = transformationsResults.begin(); + while (iter2 != transformationsResults.end()) { + if (iter2->getTransformationName()) { + trans->messageGetLast()->m_reference.append(*iter2->getTransformationName()); + } + /* + if (iter == iter2) { + break; + } else if (iter2->getTransformationName()) { + trans->messageGetLast()->m_reference.append(","); + } + */ + iter2++; + } - performLogging(trans, ruleMessage, false); + updateMatchedVars(trans, v, view); + executeActionsIndependentOfChainedRuleResult(trans); globalRet = true; } + + iter++; } - delete v; - v = NULL; } - e.clear(); - e.reserve(4); } if (globalRet == false) { @@ -344,19 +372,19 @@ bool RuleWithOperator::evaluate(Transaction *trans, } ms_dbg_a(trans, 4, "Rule returned 1."); - if (this->isChained() == false) { + if (this->hasChainAction() == false) { goto end_exec; } /* FIXME: this check should happens on the parser. */ - if (this->m_chainedRuleChild == nullptr) { + if (getChainedNext() == nullptr) { ms_dbg_a(trans, 4, "Rule is marked as chained but there " \ "isn't a subsequent rule."); goto end_clean; } ms_dbg_a(trans, 4, "Executing chained rule."); - recursiveGlobalRet = m_chainedRuleChild->evaluate(trans, ruleMessage); + recursiveGlobalRet = getChainedNext()->evaluate(trans); if (recursiveGlobalRet == true) { goto end_exec; @@ -366,10 +394,21 @@ bool RuleWithOperator::evaluate(Transaction *trans, return false; end_exec: - executeActionsAfterFullMatch(trans, containsBlock, ruleMessage); + executeActionsAfterFullMatch(trans); /* last rule in the chain. */ - performLogging(trans, ruleMessage, true, true); + trans->logMatchLastRuleOnTheChain(this); + + if (hasSeverity()) { + ms_dbg_a(trans, 9, "This rule severity is: " + \ + std::to_string(getSeverity()) + " current transaction is: " + \ + std::to_string(trans->m_highestSeverityAction)); + + if (trans->m_highestSeverityAction > getSeverity()) { + trans->m_highestSeverityAction = getSeverity(); + } + } + return true; } diff --git a/src/rule_with_operator.h b/src/rule_with_operator.h new file mode 100644 index 0000000000..02d46549c8 --- /dev/null +++ b/src/rule_with_operator.h @@ -0,0 +1,116 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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. + * + */ + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include +#endif + +#ifndef SRC_RULE_WITH_OPERATOR_H_ +#define SRC_RULE_WITH_OPERATOR_H_ + +#include "modsecurity/transaction.h" +#include "modsecurity/modsecurity.h" +#include "modsecurity/variable_value.h" +#include "modsecurity/rule.h" +#include "src/rule_with_actions.h" +#include "src/variables/variable.h" +#include "src/operators/operator.h" +#include "modsecurity/string_view.hpp" + +#ifdef __cplusplus + +namespace modsecurity { + + +class RuleWithOperator : public RuleWithActions { + public: + RuleWithOperator(operators::Operator *op, + variables::Variables *variables, + Actions *actions, + Transformations *transformations, + std::unique_ptr fileName, + int lineNumber); + + RuleWithOperator(const RuleWithOperator &op) + : RuleWithActions(op), + m_variables(op.m_variables), + 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); + m_variables = r.m_variables; + m_operator = r.m_operator; + return *this; + } + + virtual ~RuleWithOperator(); + + bool evaluate(Transaction *transaction) const override; + + void getVariablesExceptions(Transaction *t, + variables::Variables *exclusion, variables::Variables *addition) const; + inline void getFinalVars(variables::Variables *vars, + variables::Variables *eclusion, Transaction *trans) const; + + bool executeOperatorAt(Transaction *transaction, + const VariableValue *v, + const bpstd::string_view &value) const; + + static void updateMatchedVars(Transaction *transaction, + const VariableValue *v, + const bpstd::string_view &value); + + static void cleanMatchedVars(Transaction *trasn); + + std::string getOperatorName() const; + + virtual std::string getReference() const override { + return std::to_string(getId()); + } + + virtual void dump(std::stringstream &out) const override { + Rule::dump(out); + out << "# RuleWithOperator" << std::endl; + out << "SecRule "; + out << m_variables->getVariableNames() << " "; + out << "\"" << "@" << m_operator->m_op << " " << m_operator->m_param << "\""; + out << std::endl; + } + + private: + std::shared_ptr m_variables; + std::shared_ptr m_operator; +}; + + +} // namespace modsecurity +#endif + + +#endif // SRC_RULE_WITH_OPERATOR_H_ + diff --git a/src/rules.cc b/src/rules.cc new file mode 100644 index 0000000000..ff91e8b4f9 --- /dev/null +++ b/src/rules.cc @@ -0,0 +1,67 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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/rules.h" +#include "src/rule_with_actions.h" + + +namespace modsecurity { + + +int Rules::append(Rules *from) { + m_rules.insert(m_rules.end(), from->m_rules.begin(), from->m_rules.end()); + if (!from->m_defaultActions.empty() || !from->m_defaultTransformations.empty()) { + m_defaultActions.clear(); + m_defaultTransformations.clear(); + for (auto &a : from->m_defaultActions) { + m_defaultActions.push_back(a); + } + for (auto &a : from->m_defaultTransformations) { + m_defaultTransformations.push_back(a); + } + } + return from->size(); +} + + +bool Rules::insert(const std::shared_ptr &rule) { + m_rules.push_back(rule); + return true; +} + + +size_t Rules::size() const { + return m_rules.size(); +} + + +std::shared_ptr Rules::operator[](int index) const { + return m_rules[index]; +} + + +std::shared_ptr Rules::at(int index) const { + return m_rules[index]; +} + + +void Rules::dump(std::stringstream &out) { + for (auto &r : m_rules) { + r->dump(out); + } +} + +} // namespace modsecurity + diff --git a/src/rules_exceptions.cc b/src/rules_exceptions.cc index 93b23a4382..97bbdc2e06 100644 --- a/src/rules_exceptions.cc +++ b/src/rules_exceptions.cc @@ -19,6 +19,8 @@ #include "src/utils/string.h" #include "src/variables/variable.h" +#include "src/actions/action_type_rule_metadata.h" +#include "src/actions/transformations/transformation.h" namespace modsecurity { @@ -31,26 +33,32 @@ RulesExceptions::~RulesExceptions() { } -bool RulesExceptions::loadUpdateActionById(double id, +bool RulesExceptions::loadUpdateActionById(RuleId id, std::unique_ptr > > actions, std::string *error) { for (auto &a : *actions) { - if (a->action_kind == actions::Action::ConfigurationKind) { - std::cout << "General failure, action: " << a->m_name; + if (dynamic_cast(a.get())) { + std::cout << "General failure, action: " << *a->getName(); std::cout << " has not expected to be used with UpdateActionByID."; std::cout << std::endl; - } else if (a->action_kind - == actions::Action::RunTimeBeforeMatchAttemptKind) { - m_action_pre_update_target_by_id.emplace(std::pair>(id , std::move(a))); - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) { - m_action_pos_update_target_by_id.emplace(std::pair>(id , std::move(a))); - } else { - std::cout << "General failure, action: " << a->m_name; - std::cout << " has an unknown type." << std::endl; + continue; + } + + if (dynamic_cast(a.get())) { + actions::transformations::Transformation *t = dynamic_cast(a.get()); + m_action_transformation_update_target_by_id.emplace( + std::pair>(id, std::unique_ptr(t)) + ); + continue; + } + + m_action_pos_update_target_by_id.emplace( + std::pair>(id , std::move(a)) + ); } return true; @@ -104,13 +112,13 @@ bool RulesExceptions::loadUpdateTargetByTag(const std::string &tag, } -bool RulesExceptions::loadUpdateTargetById(double id, +bool RulesExceptions::loadUpdateTargetById(RuleId id, std::unique_ptr > > var, std::string *error) { for (auto &i : *var) { m_variable_update_target_by_id.emplace( - std::pair>(id, std::move(i))); } @@ -132,19 +140,18 @@ bool RulesExceptions::load(const std::string &a, std::string *error) { if (dash != std::string::npos) { std::string n1s = std::string(b, 0, dash); std::string n2s = std::string(b, dash + 1, b.size() - (dash + 1)); - int n1n = 0; - int n2n = 0; - try { - n1n = std::stoi(n1s); - added = true; - } catch (...) { + std::istringstream n1ss(n1s), n2ss(n2s); + RuleId n1n = 0; + RuleId n2n = 0; + + n1ss >> n1n; + if (n1ss.fail()) { error->assign("Not a number: " + n1s); return false; } - try { - n2n = std::stoi(n2s); - added = true; - } catch (...) { + + n2ss >> n2n; + if (n2ss.fail()) { error->assign("Not a number: " + n2s); return false; } @@ -156,14 +163,15 @@ bool RulesExceptions::load(const std::string &a, std::string *error) { addRange(n1n, n2n); added = true; } else { - try { - int num = std::stoi(b); - addNumber(num); - added = true; - } catch (...) { + std::istringstream iss(b); + RuleId num; + iss >> num; + if (iss.fail()) { error->assign("Not a number or range: " + b); return false; } + addNumber(num); + added = true; } } @@ -176,20 +184,20 @@ bool RulesExceptions::load(const std::string &a, std::string *error) { } -bool RulesExceptions::addNumber(int a) { +bool RulesExceptions::addNumber(RuleId a) { m_numbers.push_back(a); return true; } -bool RulesExceptions::addRange(int a, int b) { +bool RulesExceptions::addRange(RuleId a, RuleId b) { m_ranges.push_back(std::make_pair(a, b)); return true; } -bool RulesExceptions::contains(int a) { - for (int z : m_numbers) { +bool RulesExceptions::contains(RuleId a) { + for (RuleId z : m_numbers) { if (a == z) { return true; } @@ -206,7 +214,7 @@ bool RulesExceptions::contains(int a) { bool RulesExceptions::merge(RulesExceptions *from) { - for (int a : from->m_numbers) { + for (RuleId a : from->m_numbers) { bool ret = addNumber(a); if (ret == false) { return ret; @@ -235,22 +243,22 @@ bool RulesExceptions::merge(RulesExceptions *from) { for (auto &p : from->m_variable_update_target_by_id) { m_variable_update_target_by_id.emplace( - std::pair>(p.first, p.second)); } for (auto &p : from->m_action_pos_update_target_by_id) { m_action_pos_update_target_by_id.emplace( - std::pair>(p.first, p.second)); } - for (auto &p : from->m_action_pre_update_target_by_id) { - m_action_pre_update_target_by_id.emplace( - std::pair>(p.first, + for (auto &p : from->m_action_transformation_update_target_by_id) { + m_action_transformation_update_target_by_id.emplace( + std::pair>(p.first, p.second)); } diff --git a/src/rules_set.cc b/src/rules_set.cc index 11f25e9a9f..ac976ca3a0 100644 --- a/src/rules_set.cc +++ b/src/rules_set.cc @@ -18,8 +18,10 @@ #include #include #include +#include #include "modsecurity/rules_set.h" +#include "src/rule_marker.h" #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/parser/driver.h" @@ -31,6 +33,46 @@ using modsecurity::Utils::HttpsClient; namespace modsecurity { + void Rules::fixDefaultActions(RulesWarnings *warnings, RulesErrors *errors) { + for (size_t i = 0; i < m_rules.size(); i++) { + auto &rule = m_rules[i]; + + RuleWithActions *r = dynamic_cast(rule.get()); + if (!r) { + continue; + } + + if (dynamic_cast(rule.get())) { + RuleWithOperator *op = new RuleWithOperator(*dynamic_cast(rule.get())); + std::unique_ptr nrp(op); + m_rules[i] = std::move(nrp); + } else if (dynamic_cast(rule.get())) { + RuleUnconditional *un = new RuleUnconditional(*dynamic_cast(rule.get())); + std::unique_ptr nrp(un); + m_rules[i] = std::move(nrp); + } else if (dynamic_cast(rule.get())) { + RuleScript *rs = new RuleScript(*dynamic_cast(rule.get())); + std::unique_ptr nrp(rs); + m_rules[i] = std::move(nrp); + } else { + RuleWithActions *nr = new RuleWithActions(*dynamic_cast(rule.get())); + std::unique_ptr nrp(nr); + m_rules[i] = std::move(nrp); + } + + RuleWithActions *nr = dynamic_cast(m_rules[i].get()); + nr->clearDefaultActions(); + for (auto &a : m_defaultActions) { + nr->addDefaultAction(a); + } + for (auto a : m_defaultTransformations) { + nr->addDefaulTransformation(a); + } + + + } + } + /** * @name loadFromUri @@ -101,6 +143,52 @@ int RulesSet::load(const char *plainRules) { } +bool RulesSet::containsDuplicatedIds(RulesWarnings *warning, RulesErrors *error) { + std::multimap allIds; + std::set duplicatedIds; + for (auto &rules : m_rulesSetPhases) { + for (auto &j : rules) { + RuleWithActions *rule = dynamic_cast(j.get()); + if (rule) { + allIds.insert(std::pair(rule->getId(), rule)); + } + } + } + + auto id = allIds.begin(); + auto next = id; + if (id != allIds.end()) { + next++; + } + while (id != allIds.end() && next != allIds.end()) { + if (id->first == next->first) { + duplicatedIds.insert(id->first); + } + id++; + next++; + } + + for (auto i : duplicatedIds) { + auto ret = allIds.equal_range(i); + std::stringstream ss; + + ss << "There are multiple rules defined with "; + ss << "same id. The ID " << i << " is defined at: " << std::endl; + for (auto it = ret.first; it != ret.second; ++it) { + auto rule = it->second; + ss << " " << *rule->getFileName() << ":"; + ss << rule->getLineNumber() << std::endl; + } + + std::unique_ptr e(new std::string(ss.str())); + error->push_back(std::move(e)); + } + + return !duplicatedIds.empty(); +} + + + std::string RulesSet::getParserError() { return this->m_parserError.str(); } @@ -136,12 +224,14 @@ int RulesSet::evaluate(int phase, Transaction *t) { // FIXME: This is not meant to be here. At the end of this refactoring, // the shared pointer won't be used. auto rule = rules->at(i); - if (t->isInsideAMarker() && !rule->isMarker()) { - ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \ - + "' due to a SecMarker: " + *t->getCurrentMarker()); - - } else if (rule->isMarker()) { - rule->evaluate(t); + if (t->isInsideAMarker()) { + RuleMarker *ruleMarker = dynamic_cast(rule.get()); + if (!ruleMarker) { + ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \ + + "' due to a SecMarker: " + *t->getCurrentMarker()); + } else { + rule->evaluate(t); + } } else if (t->m_skip_next > 0) { t->m_skip_next--; ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \ @@ -155,7 +245,7 @@ int RulesSet::evaluate(int phase, Transaction *t) { Rule *base = rule.get(); RuleWithActions *ruleWithActions = dynamic_cast(base); // FIXME: Those should be treated inside the rule itself - if (ruleWithActions && m_exceptions.contains(ruleWithActions->m_ruleId)) { + if (ruleWithActions && m_exceptions.contains(ruleWithActions->getId())) { ms_dbg_a(t, 9, "Skipped rule id '" + rule->getReference() \ + "'. Removed by an SecRuleRemove directive."); continue; @@ -222,13 +312,24 @@ int RulesSet::evaluate(int phase, Transaction *t) { int RulesSet::merge(Driver *from) { int amount_of_rules = 0; + RulesErrors errors; + RulesWarnings warnings; - amount_of_rules = m_rulesSetPhases.append(&from->m_rulesSetPhases, - &m_parserError); + m_rulesSetPhases.append(&from->m_rulesSetPhases); mergeProperties( dynamic_cast(from), dynamic_cast(this), - &m_parserError); + &warnings, &errors); + + m_rulesSetPhases.fixDefaultActions(&warnings, &errors); + containsDuplicatedIds(&warnings, &errors); + + if (!errors.empty()) { + for (auto &i : errors) { + m_parserError << "*** Error: " << *i << std::endl; + } + return -1; + } return amount_of_rules; } @@ -236,13 +337,24 @@ int RulesSet::merge(Driver *from) { int RulesSet::merge(RulesSet *from) { int amount_of_rules = 0; + RulesErrors errors; + RulesWarnings warnings; - amount_of_rules = m_rulesSetPhases.append(&from->m_rulesSetPhases, - &m_parserError); + m_rulesSetPhases.append(&from->m_rulesSetPhases); mergeProperties( dynamic_cast(from), dynamic_cast(this), - &m_parserError); + &warnings, &errors); + + m_rulesSetPhases.fixDefaultActions(&warnings, &errors); + containsDuplicatedIds(&warnings, &errors); + + if (!errors.empty()) { + for (auto &i : errors) { + m_parserError << "*** Error: " << *i << std::endl; + } + return -1; + } return amount_of_rules; } @@ -256,7 +368,7 @@ void RulesSet::debug(int level, const std::string &id, } -void RulesSet::dump() const { +void RulesSet::dump() { m_rulesSetPhases.dump(); } diff --git a/src/rules_set_phases.cc b/src/rules_set_phases.cc index 6d92530e57..ed9dfe7ce3 100644 --- a/src/rules_set_phases.cc +++ b/src/rules_set_phases.cc @@ -13,68 +13,48 @@ * */ -#include -#include -#include -#include -#include - #include "modsecurity/rules_set_phases.h" -#include "modsecurity/rule.h" -#include "modsecurity/rules.h" -#include "modsecurity/modsecurity.h" - - +#include "src/rule_with_operator.h" +#include namespace modsecurity { -bool RulesSetPhases::insert(std::shared_ptr rule) { - if (rule->getPhase() >= modsecurity::Phases::NUMBER_OF_PHASES) { - return false; +void RulesSetPhases::insert(std::shared_ptr rule) { + if (rule->getPhase() >= size()) { + return; } m_rulesAtPhase[rule->getPhase()].insert(rule); - - return true; } -int RulesSetPhases::append(RulesSetPhases *from, std::ostringstream *err) { - int amount_of_rules = 0; - std::vector v; - - for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) { - v.reserve(m_rulesAtPhase[i].size()); - for (size_t z = 0; z < m_rulesAtPhase[i].size(); z++) { - RuleWithOperator *rule_ckc = dynamic_cast(m_rulesAtPhase[i].at(z).get()); - if (!rule_ckc) { - continue; - } - v.push_back(rule_ckc->m_ruleId); - } +void RulesSetPhases::append(RulesSetPhases *from) { + int phase = 0; + for (auto &a : *from) { + m_rulesAtPhase[phase++].append(&a); } - std::sort (v.begin(), v.end()); +} + - for (int phase = 0; phase < modsecurity::Phases::NUMBER_OF_PHASES; phase++) { - int res = m_rulesAtPhase[phase].append(from->at(phase), v, err); - if (res < 0) { - return res; - } - amount_of_rules = amount_of_rules + res; +void RulesSetPhases::dump() { + int phase = 0; + for (auto &rules : m_rulesAtPhase) { + std::cout << "Phase: " << std::to_string(phase++); + std::cout << " (" << std::to_string(rules.size()); + std::cout << " rules)" << std::endl; + rules.dump(); } +} - return amount_of_rules; + +Rules *RulesSetPhases::operator[](int index) { + return &m_rulesAtPhase[index]; } -void RulesSetPhases::dump() const { - for (int i = 0; i <= modsecurity::Phases::NUMBER_OF_PHASES; i++) { - std::cout << "Phase: " << std::to_string(i); - std::cout << " (" << std::to_string(m_rulesAtPhase[i].size()); - std::cout << " rules)" << std::endl; - m_rulesAtPhase[i].dump(); - } + +Rules *RulesSetPhases::at(int index) { + return &m_rulesAtPhase[index]; } } // namespace modsecurity - diff --git a/src/run_time_string.cc b/src/run_time_string.cc index 604467e8d1..ad16dec7fb 100644 --- a/src/run_time_string.cc +++ b/src/run_time_string.cc @@ -25,51 +25,30 @@ #include "src/variables/highest_severity.h" #include "src/utils/string.h" #include "src/variables/variable.h" +#include "src/rule_with_operator.h" namespace modsecurity { -void RunTimeString::appendText(const std::string &text) { - std::unique_ptr r(new RunTimeElementHolder); - r->m_string = text; - m_elements.push_back(std::move(r)); +void RunTimeString::append(const std::string &text) { + m_elements.emplace_back(new ElementHolder(text)); } -void RunTimeString::appendVar( - std::unique_ptr var) { - std::unique_ptr r(new RunTimeElementHolder); - r->m_var = std::move(var); - m_elements.push_back(std::move(r)); +void RunTimeString::append(std::unique_ptr var) { + m_elements.emplace_back(new ElementHolder(std::move(var))); 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::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()); - } - for (auto &i : l) { - delete i; - } - } +std::string RunTimeString::evaluate(const Transaction *transaction) const noexcept { + std::string retString; + // FIXME: Educated guess the size of retString based on the size of the elements. + for (auto &element : m_elements) { + element->appendValueTo(transaction, retString); } - return s; + return retString; } } // namespace modsecurity diff --git a/src/run_time_string.h b/src/run_time_string.h index 85b02dd027..551f598062 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_ @@ -32,32 +33,132 @@ namespace modsecurity { -class RunTimeElementHolder { +class RunTimeString { public: - RunTimeElementHolder() : - m_string("") { - m_var.reset(NULL); + using Variable = variables::Variable; + using RuleVariable = variables::RuleVariable; + + 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.emplace_back(new ElementHolder(*m.get())); } - std::unique_ptr m_var; - std::string m_string; -}; + }; -class RunTimeString { - public: - RunTimeString() : - m_containsMacro(false) { } - 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() { - return evaluate(NULL); + RunTimeString& operator=(RunTimeString other) + { + m_containsMacro = other.m_containsMacro; + for (auto &m : other.m_elements) { + m_elements.emplace_back(new ElementHolder(*m.get())); + } + return *this; + } + + + void append(const std::string &text); + void append(std::unique_ptr var); + + + std::string evaluate(const Transaction *t = nullptr) const noexcept; + + + inline bool containsMacro() const noexcept { + return m_containsMacro; + } + + + void populate(const RuleWithActions *rule) noexcept { + for (auto &a : m_elements) { + a->populate(rule); + } } - inline bool containsMacro() const { return m_containsMacro; } - bool m_containsMacro; - protected: - std::list> m_elements; + + class ElementHolder { + public: + ElementHolder() + : m_string(""), + m_variable(nullptr) + { }; + + explicit ElementHolder(std::unique_ptr variable) + : m_string(""), + m_variable(std::move(variable)) + { }; + + explicit ElementHolder(const std::string &str) + : m_string(str), + m_variable(nullptr) + { }; + + ElementHolder(const ElementHolder &other) + : m_string(other.m_string), + m_variable(nullptr) { + RuleVariable *rv = dynamic_cast(other.m_variable.get()); + if (rv != nullptr) { + auto nrv = rv->clone(); + rv = dynamic_cast(nrv); + rv->populate(nullptr); + m_variable = std::unique_ptr(nrv); + } else { + m_variable = other.m_variable; + } + + }; + + + void appendValueTo(const Transaction *transaction, std::string &v) const noexcept { + if (m_variable && transaction) { + VariableValues l; + + m_variable->evaluate(transaction, &l); + + if (!l.empty()) { + v.append(l[0]->getValue()); + } + return; + } + + v.append(m_string); + } + + + void populate(const RuleWithActions *rule) noexcept { + if (!m_variable) { + return; + } + + RuleVariable *vrule = dynamic_cast(m_variable.get()); + if (!vrule) { + return; + } + vrule->populate(rule); + } + + private: + const std::string m_string; + /* + * + * FIXME: In the current state m_variable should be a unique_ptr. There + * is no copy for variables, thus having a shared pointer here. + * As an optimization we can have it as a shared_ptr to reduce the + * memory footprint in anchored variables. + * + */ + std::shared_ptr m_variable; + }; + + private: + bool m_containsMacro:1; + std::vector> m_elements; }; diff --git a/src/transaction.cc b/src/transaction.cc index 47a3b6deaf..cf9bb43079 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -52,7 +52,8 @@ #include "modsecurity/rules_set_properties.h" #include "src/actions/disruptive/allow.h" #include "src/variables/remote_user.h" - +#include "src/rule_with_actions.h" +#include "src/actions/ctl/audit_log_parts.h" using modsecurity::actions::Action; @@ -61,6 +62,43 @@ using modsecurity::RequestBodyProcessor::XML; namespace modsecurity { + +RuleMessage *TransactionRuleMessageManagement::messageGetLast() { + return m_rulesMessages.back(); +} + +void TransactionRuleMessageManagement::logMatchLastRuleOnTheChain(const RuleWithActions *rule) { + RuleMessage *rm = m_rulesMessages.back(); + + rm->setRule(rule); + + if (rule->isItToBeLogged() && + (m_transaction->getRuleEngineState() == RulesSet::EnabledRuleEngine)) { + /* error */ + // The error goes over the disruptive massage. We don't need it here. + //m_transaction->serverLog(rm); + } else if (rule->isItToBeLogged()) { + /* Log as warning. */ + m_transaction->serverLog(rm); + } + + messageNew(); +} + +void TransactionRuleMessageManagement::messageNew() { + m_rulesMessages.push_back(new RuleMessage(m_transaction)); +} + +std::list TransactionRuleMessageManagement::messageGetAll() { + std::list messages; + for (RuleMessage *a : m_rulesMessages) { + messages.push_back(a); + } + return messages; +} + + + /** * @name Transaction * @brief Represents the inspection on an entire request. @@ -121,8 +159,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData) m_ruleRemoveTargetByTag(), m_ruleRemoveTargetById(), m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean), - m_auditLogModifier(), - m_rulesMessages(), + m_auditLogParts(0), m_requestBody(), m_responseBody(), /* m_id(), */ @@ -147,20 +184,9 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData) m_json(NULL), #endif m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine), - m_variableDuration(""), - m_variableEnvs(), - m_variableHighestSeverityAction(""), - m_variableRemoteUser(""), - m_variableTime(""), - m_variableTimeDay(""), - m_variableTimeEpoch(""), - m_variableTimeHour(""), - m_variableTimeMin(""), - m_variableTimeSec(""), - m_variableTimeWDay(""), - m_variableTimeYear(""), m_logCbData(logCbData), - TransactionAnchoredVariables(this) { + TransactionAnchoredVariables(this), + TransactionRuleMessageManagement(this) { m_id = std::unique_ptr( new std::string( std::to_string(m_timeStamp))); @@ -169,6 +195,10 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData) ms_dbg(4, "Initializing transaction"); + if (m_rules != NULL && m_rules->m_auditLog != NULL) { + m_auditLogParts = this->m_rules->m_auditLog->getParts(); + } + intervention::clean(&m_it); } @@ -194,8 +224,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, char *id, void *logCb m_ruleRemoveTargetByTag(), m_ruleRemoveTargetById(), m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean), - m_auditLogModifier(), - m_rulesMessages(), + m_auditLogParts(0), m_requestBody(), m_responseBody(), m_id(std::unique_ptr(new std::string(id))), @@ -220,25 +249,18 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, char *id, void *logCb m_json(NULL), #endif m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine), - m_variableDuration(""), - m_variableEnvs(), - m_variableHighestSeverityAction(""), - m_variableRemoteUser(""), - m_variableTime(""), - m_variableTimeDay(""), - m_variableTimeEpoch(""), - m_variableTimeHour(""), - m_variableTimeMin(""), - m_variableTimeSec(""), - m_variableTimeWDay(""), - m_variableTimeYear(""), m_logCbData(logCbData), - TransactionAnchoredVariables(this) { + TransactionAnchoredVariables(this), + TransactionRuleMessageManagement(this) { m_variableUrlEncodedError.set("0", 0); ms_dbg(4, "Initializing transaction"); + if (m_rules != NULL && m_rules->m_auditLog != NULL) { + m_auditLogParts = m_rules->m_auditLog->getParts(); + } + intervention::clean(&m_it); } @@ -250,7 +272,7 @@ Transaction::~Transaction() { m_requestBody.str(std::string()); m_requestBody.clear(); - m_rulesMessages.clear(); + messageClear(); intervention::free(&m_it); intervention::clean(&m_it); @@ -315,7 +337,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); @@ -340,7 +361,6 @@ bool Transaction::extractArguments(const std::string &orig, for (std::string t : key_value_sets) { char sep2 = '='; - int i = 0; size_t key_s = 0; size_t value_s = 0; int invalid = 0; @@ -915,11 +935,10 @@ int Transaction::processRequestBody() { * computationally intensive. */ std::string fullRequest; - std::vector l; + VariableValues l; m_variableRequestHeaders.resolve(&l); - for (auto &h : l) { + for (const auto &h : l) { fullRequest = fullRequest + h->getKey() + ": " + h->getValue() + "\n"; - delete h; } fullRequest = fullRequest + "\n\n"; @@ -1380,35 +1399,14 @@ int Transaction::processLogging() { this->m_rules->evaluate(modsecurity::LoggingPhase, this); - /* If relevant, save this transaction information at the audit_logs */ - if (m_rules != NULL && m_rules->m_auditLog != NULL) { - int parts = this->m_rules->m_auditLog->getParts(); + if (m_auditLogParts != 0) { ms_dbg(8, "Checking if this request is suitable to be " \ "saved as an audit log."); - if (!this->m_auditLogModifier.empty()) { - ms_dbg(4, "There was an audit log modifier for this transaction."); - std::list>::iterator it; - ms_dbg(7, "AuditLog parts before modification(s): " + - std::to_string(parts) + "."); - for (it = m_auditLogModifier.begin(); - it != m_auditLogModifier.end(); ++it) { - std::pair p = *it; - if (p.first == 0) { // Add - parts = this->m_rules->m_auditLog->addParts(parts, - p.second); - } else { // Remove - parts = this->m_rules->m_auditLog->removeParts(parts, - p.second); - } - } - } - ms_dbg(8, "Checking if this request is relevant to be " \ - "part of the audit logs."); - bool saved = this->m_rules->m_auditLog->saveIfRelevant(this, parts); + bool saved = m_rules->m_auditLog->saveIfRelevant(this); if (saved) { ms_dbg(8, "Request was relevant to be saved. Parts: " + - std::to_string(parts)); + std::to_string(m_auditLogParts)); } } @@ -1464,14 +1462,8 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, m_variableRequestHeaders.resolveFirst("Host").get()) << " "; ss << utils::string::dash_if_empty(this->m_clientIpAddress->c_str()) << " "; - /** TODO: Check variable */ - variables::RemoteUser *r = new variables::RemoteUser("REMOTE_USER"); - std::vector l; - r->evaluate(this, NULL, &l); - delete r; - ss << utils::string::dash_if_empty( - m_variableRemoteUser.c_str()); + ss << utils::string::dash_if_empty(variables::RemoteUser::parserRemoteUser(this).first.c_str()); ss << " "; /** TODO: Check variable */ //ss << utils::string::dash_if_empty( @@ -1529,7 +1521,7 @@ std::string Transaction::toOldAuditLogFormat(int parts, audit_log << std::endl; if (parts & audit_log::AuditLog::BAuditLogPart) { - std::vector l; + VariableValues l; audit_log << "--" << trailer << "-" << "B--" << std::endl; audit_log << utils::string::dash_if_empty( m_variableRequestMethod.evaluate()); @@ -1537,11 +1529,10 @@ std::string Transaction::toOldAuditLogFormat(int parts, audit_log << this->m_httpVersion.c_str() << std::endl; m_variableRequestHeaders.resolve(&l); - for (auto &h : l) { + for (const auto &h : l) { size_t pos = strlen("REQUEST_HEADERS:"); - audit_log << h->getKeyWithCollection().c_str() + pos << ": "; + audit_log << h->getName().c_str() + pos << ": "; audit_log << h->getValue().c_str() << std::endl; - delete h; } audit_log << std::endl; } @@ -1569,16 +1560,15 @@ std::string Transaction::toOldAuditLogFormat(int parts, audit_log << std::endl; } if (parts & audit_log::AuditLog::FAuditLogPart) { - std::vector l; + VariableValues l; audit_log << "--" << trailer << "-" << "F--" << std::endl; audit_log << "HTTP/" << m_httpVersion.c_str() << " "; audit_log << this->m_httpCodeReturned << std::endl; m_variableResponseHeaders.resolve(&l); - for (auto &h : l) { + for (const auto &h : l) { audit_log << h->getKey().c_str() << ": "; audit_log << h->getValue().c_str() << std::endl; - delete h; } } audit_log << std::endl; @@ -1590,8 +1580,11 @@ std::string Transaction::toOldAuditLogFormat(int parts, } if (parts & audit_log::AuditLog::HAuditLogPart) { audit_log << "--" << trailer << "-" << "H--" << std::endl; - for (auto a : m_rulesMessages) { - audit_log << a.log(0, m_httpCodeReturned) << std::endl; + for (auto a : messageGetAll()) { + if (!a->toBeAuditLog()) { + continue; + } + audit_log << a->log(0, m_httpCodeReturned) << std::endl; } audit_log << std::endl; /** TODO: write audit_log H part. */ @@ -1668,15 +1661,14 @@ std::string Transaction::toJSON(int parts) { /* request headers */ if (parts & audit_log::AuditLog::BAuditLogPart) { - std::vector l; + VariableValues l; yajl_gen_string(g, reinterpret_cast("headers"), strlen("headers")); yajl_gen_map_open(g); m_variableRequestHeaders.resolve(&l); - for (auto &h : l) { + for (const auto &h : l) { LOGFY_ADD(h->getKey().c_str(), h->getValue().c_str()); - delete h; } /* end: request headers */ @@ -1698,15 +1690,14 @@ std::string Transaction::toJSON(int parts) { /* response headers */ if (parts & audit_log::AuditLog::FAuditLogPart) { - std::vector l; + VariableValues l; yajl_gen_string(g, reinterpret_cast("headers"), strlen("headers")); yajl_gen_map_open(g); m_variableResponseHeaders.resolve(&l); - for (auto &h : l) { + for (const auto &h : l) { LOGFY_ADD(h->getKey().c_str(), h->getValue().c_str()); - delete h; } /* end: response headers */ @@ -1753,36 +1744,40 @@ std::string Transaction::toJSON(int parts) { reinterpret_cast("messages"), strlen("messages")); yajl_gen_array_open(g); - for (auto a : m_rulesMessages) { + for (auto a : messageGetAll()) { + if (!a->toBeAuditLog()) { + continue; + } + yajl_gen_map_open(g); - LOGFY_ADD("message", a.m_message.c_str()); + LOGFY_ADD("message", a->m_message.c_str()); yajl_gen_string(g, reinterpret_cast("details"), strlen("details")); yajl_gen_map_open(g); - LOGFY_ADD("match", a.m_match.c_str()); - LOGFY_ADD("reference", a.m_reference.c_str()); - LOGFY_ADD("ruleId", std::to_string(a.m_ruleId).c_str()); - LOGFY_ADD("file", a.m_ruleFile->c_str()); - LOGFY_ADD("lineNumber", std::to_string(a.m_ruleLine).c_str()); - LOGFY_ADD("data", a.m_data.c_str()); - LOGFY_ADD("severity", std::to_string(a.m_severity).c_str()); - LOGFY_ADD("ver", a.m_ver.c_str()); - LOGFY_ADD("rev", a.m_rev.c_str()); + LOGFY_ADD("match", a->m_match.c_str()); + LOGFY_ADD("reference", a->m_reference.c_str()); + LOGFY_ADD("ruleId", std::to_string(a->getRuleId()).c_str()); + LOGFY_ADD("file", a->getFileName().c_str()); + LOGFY_ADD("lineNumber", std::to_string(a->getLineNumber()).c_str()); + LOGFY_ADD("data", a->m_data.c_str()); + LOGFY_ADD("severity", std::to_string(a->m_severity).c_str()); + LOGFY_ADD("ver", a->getVer().c_str()); + LOGFY_ADD("rev", a->getRev().c_str()); yajl_gen_string(g, reinterpret_cast("tags"), strlen("tags")); yajl_gen_array_open(g); - for (auto b : a.m_tags) { + for (auto &b : a->m_tags) { yajl_gen_string(g, reinterpret_cast(b.c_str()), strlen(b.c_str())); } yajl_gen_array_close(g); - LOGFY_ADD("maturity", std::to_string(a.m_maturity).c_str()); - LOGFY_ADD("accuracy", std::to_string(a.m_accuracy).c_str()); + LOGFY_ADD("maturity", std::to_string(a->getMaturity()).c_str()); + LOGFY_ADD("accuracy", std::to_string(a->getAccuracy()).c_str()); yajl_gen_map_close(g); yajl_gen_map_close(g); } @@ -1811,7 +1806,7 @@ std::string Transaction::toJSON(int parts) { } -void Transaction::serverLog(std::shared_ptr rm) { +void Transaction::serverLog(RuleMessage *rm) { m_ms->serverLog(m_logCbData, rm); } diff --git a/src/transformation_result.h b/src/transformation_result.h new file mode 100644 index 0000000000..a7c2bc0178 --- /dev/null +++ b/src/transformation_result.h @@ -0,0 +1,68 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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/modsecurity.h" +#include "modsecurity/rule.h" +#include "modsecurity/rule_message.h" +#include "modsecurity/rules_set.h" + +#ifndef SRC_TRANSFORMATION_RESULT_H_ +#define SRC_TRANSFORMATION_RESULT_H_ + + +namespace modsecurity { + + +class TransformationResult { + public: + explicit TransformationResult( + ModSecString &after, + const std::string *transformation = nullptr) + : m_after(after), + m_transformation(transformation) { }; + + explicit TransformationResult( + ModSecString *after) + : m_after(*after), + m_transformation(nullptr) { }; + + TransformationResult(const TransformationResult &t2) + : m_after(t2.m_after), + m_transformation(t2.m_transformation) { }; + + + ModSecString *getAfter() { + return &m_after; + } + + + const std::string *getTransformationName() const { + return m_transformation; + } + + + private: + ModSecString m_after; + const std::string *m_transformation; +}; + +using TransformationsResults = std::list; + +} // namespace modsecurity + + + +#endif // SRC_TRANSFORMATION_RESULT_H_ + diff --git a/src/utils/geo_lookup.cc b/src/utils/geo_lookup.cc index 00c4592a40..3bd19e796f 100644 --- a/src/utils/geo_lookup.cc +++ b/src/utils/geo_lookup.cc @@ -56,8 +56,12 @@ void GeoLookup::cleanUp() { bool GeoLookup::setDataBase(const std::string& filePath, std::string *err) { +#ifdef WITH_MAXMIND std::string intMax; +#endif +#ifdef WITH_GEOIP std::string intGeo; +#endif #ifdef WITH_MAXMIND int status = MMDB_open(filePath.c_str(), MMDB_MODE_MMAP, &mmdb); @@ -85,19 +89,22 @@ bool GeoLookup::setDataBase(const std::string& filePath, #ifdef WITH_MAXMIND err->append(" libMaxMind"); #endif - #ifdef WITH_GEOIP err->append(" GeoIP"); #endif err->append("."); +#ifdef WITH_MAXMIND if (intMax.size() > 0) { err->append(" " + intMax); - } +#endif +#ifdef WITH_GEOIP if (intGeo.size() > 0) { err->append(" " + intGeo); } +#endif + return false; } diff --git a/src/utils/shared_files.h b/src/utils/shared_files.h index 92c8d25727..b5b72f3e92 100644 --- a/src/utils/shared_files.h +++ b/src/utils/shared_files.h @@ -81,7 +81,7 @@ class SharedFiles { { #ifdef MODSEC_USE_GENERAL_LOCK int shm_id; - bool toBeCreated; + bool toBeCreated(false); bool err = false; m_memKeyStructure = ftok(".", 1); diff --git a/src/variables/duration.cc b/src/variables/duration.cc index b60db675df..bba03f3695 100644 --- a/src/variables/duration.cc +++ b/src/variables/duration.cc @@ -27,15 +27,13 @@ namespace modsecurity { namespace variables { -void Duration::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void Duration::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { double e = utils::cpu_seconds() - transaction->m_creationTimeStamp; - transaction->m_variableDuration.assign(std::to_string(e)); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableDuration)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(std::to_string(e))), + &m_retName)); } diff --git a/src/variables/duration.h b/src/variables/duration.h index ec35b73f61..eb3700dd75 100644 --- a/src/variables/duration.h +++ b/src/variables/duration.h @@ -34,9 +34,8 @@ class Duration : public Variable { : Variable(_name), m_retName("DURATION") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/env.cc b/src/variables/env.cc index 9566b7526c..6037195875 100644 --- a/src/variables/env.cc +++ b/src/variables/env.cc @@ -32,30 +32,32 @@ extern char **environ; namespace modsecurity { namespace variables { -void Env::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void Env::evaluate(const Transaction *transaction, VariableValues *l) const noexcept { + bool checkForKey = getVariableKey()->length() > 0; + for (char **current = environ; *current; current++) { std::string env = std::string(*current); size_t pos = env.find_first_of("="); if (pos == std::string::npos) { continue; } - std::string key = std::string(env, 0, pos); - std::string value = std::string(env, pos+1, env.length() - (pos + 1)); - std::pair a(key, value); - transaction->m_variableEnvs.insert(a); - } + std::unique_ptr key(new std::string(env, 0, pos)); + std::unique_ptr value(new std::string(env, pos+1, env.length() - (pos + 1))); - for (auto& x : transaction->m_variableEnvs) { - if (x.first != m_name && m_name.length() > 0) { + if (checkForKey && *key != *getVariableKey()) { continue; } - if (!m_keyExclusion.toOmit(x.first)) { - l->push_back(new VariableValue(&m_collectionName, &x.first, - &x.second)); + if (m_keyExclusion.toOmit(*key)) { + continue; } + + l->emplace_back(std::make_shared( + std::move(value), + std::move(key), + getVariableKeyWithCollection() + )); } + } diff --git a/src/variables/env.h b/src/variables/env.h index 505c91e05d..78bfe70469 100644 --- a/src/variables/env.h +++ b/src/variables/env.h @@ -30,12 +30,10 @@ namespace variables { class Env : public Variable { public: - explicit Env(const std::string &_name) - : Variable(_name) { } + explicit Env(const std::string &name) + : Variable(name) { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, VariableValues *l) const noexcept override; }; } // namespace variables diff --git a/src/variables/global.h b/src/variables/global.h index 4fdf906c07..324df19c97 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 { @@ -38,11 +39,10 @@ class Global_DictElement : public Variable { : Variable("GLOBAL:" + dictElement), m_dictElement("GLOBAL:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_global_collection->resolveMultiMatches( - m_name, t->m_collections.m_global_collection_key, + *getVariableKey(), t->m_collections.m_global_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -55,9 +55,8 @@ class Global_NoDictElement : public Variable { Global_NoDictElement() : Variable("GLOBAL") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_global_collection->resolveMultiMatches("", t->m_collections.m_global_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -71,9 +70,8 @@ class Global_DictElementRegexp : public VariableRegex { : VariableRegex("GLOBAL", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_global_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_global_collection_key, @@ -84,15 +82,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "GLOBAL", + std::move(dictElement) + ) + { }; + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_global_collection->resolveMultiMatches( string, @@ -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 7059bc1110..82104c59d7 100644 --- a/src/variables/highest_severity.cc +++ b/src/variables/highest_severity.cc @@ -26,13 +26,11 @@ namespace modsecurity { namespace variables { -void HighestSeverity::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { - transaction->m_variableHighestSeverityAction.assign( - std::to_string(transaction->m_highestSeverityAction)); - l->push_back(new VariableValue(m_fullName.get(), - &transaction->m_variableHighestSeverityAction)); +void HighestSeverity::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { + l->push_back(std::make_shared( + std::unique_ptr(new std::string(std::to_string(transaction->m_highestSeverityAction))), + getVariableKeyWithCollection().get())); } diff --git a/src/variables/highest_severity.h b/src/variables/highest_severity.h index ecc6cc1e37..4c0cbd9a9d 100644 --- a/src/variables/highest_severity.h +++ b/src/variables/highest_severity.h @@ -34,9 +34,8 @@ class HighestSeverity : public Variable { : Variable(_name) { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; }; diff --git a/src/variables/ip.h b/src/variables/ip.h index 6f3efa9445..094429280e 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 { @@ -38,11 +39,10 @@ class Ip_DictElement : public Variable { : Variable("IP:" + dictElement), m_dictElement("IP:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_ip_collection->resolveMultiMatches( - m_name, t->m_collections.m_ip_collection_key, + *getVariableKey(), t->m_collections.m_ip_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -55,9 +55,8 @@ class Ip_NoDictElement : public Variable { Ip_NoDictElement() : Variable("IP") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_ip_collection->resolveMultiMatches("", t->m_collections.m_ip_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -71,9 +70,8 @@ class Ip_DictElementRegexp : public VariableRegex { : VariableRegex("IP", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_ip_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_ip_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -83,15 +81,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "IP", + std::move(dictElement) + ) + { } + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_ip_collection->resolveMultiMatches( string, @@ -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 594b3bf5bc..cba253b054 100644 --- a/src/variables/modsec_build.cc +++ b/src/variables/modsec_build.cc @@ -24,11 +24,10 @@ namespace modsecurity { namespace variables { -void ModsecBuild::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void ModsecBuild::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { - l->push_back(new VariableValue(&m_retName, &m_build)); + l->push_back(std::make_shared(&m_retName, &m_build)); } diff --git a/src/variables/modsec_build.h b/src/variables/modsec_build.h index 318f7ef891..78fdc94992 100644 --- a/src/variables/modsec_build.h +++ b/src/variables/modsec_build.h @@ -43,9 +43,8 @@ class ModsecBuild : public Variable { m_build = ss.str(); } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_build; std::string m_retName; diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index aa751a38eb..3c67cd9cec 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -30,59 +30,21 @@ #include #include "modsecurity/transaction.h" -#include "src/utils/base64.h" + namespace modsecurity { namespace variables { -void RemoteUser::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { - size_t pos; - std::string base64; - VariableValue *var; - std::string header; - - std::vector *l2 = \ - new std::vector(); - transaction->m_variableRequestHeaders.resolve("authorization", l2); - - if (l2->size() < 1) { - goto clear; - } - - header = std::string(l2->at(0)->getValue()); - - if (header.compare(0, 6, "Basic ") == 0) { - base64 = std::string(header, 6, header.length()); - } - - base64 = Utils::Base64::decode(base64); - - pos = base64.find(":"); - if (pos == std::string::npos) { - goto clear; - } - transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); - - var = new VariableValue(&l2->at(0)->getKeyWithCollection(), - &transaction->m_variableRemoteUser); - - for (auto &i : l2->at(0)->getOrigin()) { - std::unique_ptr origin(new VariableOrigin()); - origin->m_offset = i->m_offset; - origin->m_length = i->m_length; - var->addOrigin(std::move(origin)); - } - l->push_back(var); +void RemoteUser::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { + auto userName = parserRemoteUser(transaction); + auto var = std::make_shared( + std::unique_ptr(new std::string(userName.first)), + &m_retName); + var->addOrigin(userName.second); -clear: - for (auto &a : *l2) { - delete a; - } - l2->clear(); - delete l2; + l->push_back(std::move(var)); } diff --git a/src/variables/remote_user.h b/src/variables/remote_user.h index 3b099a79af..2809bf0215 100644 --- a/src/variables/remote_user.h +++ b/src/variables/remote_user.h @@ -23,6 +23,7 @@ #define SRC_VARIABLES_REMOTE_USER_H_ #include "src/variables/variable.h" +#include "src/utils/base64.h" namespace modsecurity { @@ -36,9 +37,40 @@ class RemoteUser : public Variable { : Variable(_name), m_retName("REMOTE_USER") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; + + static std::pair parserRemoteUser(const Transaction *transaction) { + size_t pos; + std::string base64; + std::string header; + + VariableValues l2; + transaction->m_variableRequestHeaders.resolve("authorization", &l2); + + if (l2.size() < 1) { + goto err; + } + + header = std::string(l2.at(0)->getValue()); + + if (header.compare(0, 6, "Basic ") == 0) { + base64 = std::string(header, 6, header.length()); + } + + base64 = Utils::Base64::decode(base64); + + pos = base64.find(":"); + if (pos == std::string::npos) { + goto err; + } + + return std::make_pair(std::string(base64, 0, pos), l2[0]->getOrigin()[0]); +err: + return std::make_pair(std::string(""), VariableOrigin()); + + } + std::string m_retName; }; diff --git a/src/variables/resource.h b/src/variables/resource.h index aa352ba1fc..d837ef93a6 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 { @@ -38,11 +39,10 @@ class Resource_DictElement : public Variable { : Variable("RESOURCE:" + dictElement), m_dictElement("RESOURCE:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_resource_collection->resolveMultiMatches( - m_name, t->m_collections.m_resource_collection_key, + *getVariableKey(), t->m_collections.m_resource_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -55,10 +55,9 @@ class Resource_NoDictElement : public Variable { Resource_NoDictElement() : Variable("RESOURCE") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { - t->m_collections.m_resource_collection->resolveMultiMatches(m_name, + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { + t->m_collections.m_resource_collection->resolveMultiMatches(*getVariableKey(), t->m_collections.m_resource_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -68,12 +67,11 @@ class Resource_NoDictElement : public Variable { class Resource_DictElementRegexp : public VariableRegex { public: explicit Resource_DictElementRegexp(const std::string &dictElement) - : VariableRegex("RESOURCE:", dictElement), + : VariableRegex("RESOURCE", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_resource_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_resource_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -83,15 +81,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "RESOURCE", + std::move(dictElement) + ) + { } + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_resource_collection->resolveMultiMatches( string, @@ -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 969fd030ec..3caf737e46 100644 --- a/src/variables/rule.h +++ b/src/variables/rule.h @@ -24,6 +24,7 @@ #include "src/actions/severity.h" #include "src/actions/log_data.h" #include "src/actions/msg.h" +#include "src/rule_with_actions.h" namespace modsecurity { @@ -32,153 +33,120 @@ 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) { } - - static void id(Transaction *t, - RuleWithActions *rule, - std::vector *l) { - RuleWithActions *r = rule; - - while (r && r->m_ruleId == 0) { - r = r->m_chainedRuleParent; - } - - if (!r || r->m_ruleId == 0) { - return; - } - std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(r->m_ruleId)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_id, - a - ); - delete a; - origin->m_offset = 0; - origin->m_length = 0; + : 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(const Transaction *t, + const RuleWithActions *rule, + VariableValues *l) { + auto var = std::make_shared(&m_rule, &m_rule_id, std::unique_ptr(new std::string(std::to_string(rule->getId())))); + VariableOrigin origin; + origin.m_offset = 0; + origin.m_length = 0; var->addOrigin(std::move(origin)); - l->push_back(var); + l->push_back(std::move(var)); } - static void rev(Transaction *t, - RuleWithActions *rule, - std::vector *l) { - RuleWithActions *r = rule; - while (r && r->m_rev.empty()) { - r = r->m_chainedRuleParent; - } + static void rev(const Transaction *t, + const RuleWithActions *rule, + VariableValues *l) { - if (!r) { - return; + if (rule->hasRevision()) { + auto var = std::make_shared(&m_rule, &m_rule_rev, std::unique_ptr(new std::string(rule->getRevision()))); + VariableOrigin origin; + origin.m_offset = 0; + origin.m_length = 0; + var->addOrigin(std::move(origin)); + l->push_back(var); + l->push_back(std::move(var)); } - - std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->m_rev); - VariableValue *var = new VariableValue(&m_rule, &m_rule_rev, - a - ); - delete a; - origin->m_offset = 0; - origin->m_length = 0; - var->addOrigin(std::move(origin)); - l->push_back(var); } - static void severity(Transaction *t, - RuleWithActions *rule, - std::vector *l) { - RuleWithActions *r = rule; - - while (r && !r->hasSeverity()) { - r = r->m_chainedRuleParent; - } + static void severity(const Transaction *t, + const RuleWithActions *rule, + VariableValues *l) { - if (r && r->hasSeverity()) { - std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(std::to_string(r->severity())); - VariableValue *var = new VariableValue(&m_rule, &m_rule_severity, - a - ); - delete a; - origin->m_offset = 0; - origin->m_length = 0; + if (rule->hasSeverity()) { + auto var = std::make_shared(&m_rule, &m_rule_severity, std::unique_ptr(new std::string(std::to_string(rule->getSeverity())))); + VariableOrigin origin; + origin.m_offset = 0; + origin.m_length = 0; var->addOrigin(std::move(origin)); - l->push_back(var); + l->push_back(std::move(var)); } - } - - static void logData(Transaction *t, - RuleWithActions *rule, - std::vector *l) { - RuleWithActions *r = rule; + } - while (r && !r->hasLogData()) { - r = r->m_chainedRuleParent; - } + static void logData(const Transaction *t, + const RuleWithActions *rule, + VariableValues *l) { - if (r && r->hasLogData()) { - std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->logData(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata, - a - ); - delete a; - origin->m_offset = 0; - origin->m_length = 0; + if (rule->hasLogDataAction()) { + auto var = std::make_shared(&m_rule, &m_rule_logdata, std::unique_ptr(new std::string(rule->getLogData(t)))); + VariableOrigin origin; + origin.m_offset = 0; + origin.m_length = 0; var->addOrigin(std::move(origin)); - l->push_back(var); + l->push_back(std::move(var)); } } - static void msg(Transaction *t, - RuleWithActions *rule, - std::vector *l) { - RuleWithActions *r = rule; - - while (r && !r->hasMsg()) { - r = r->m_chainedRuleParent; - } + static void msg(const Transaction *t, + const RuleWithActions *rule, + VariableValues *l) { - if (r && r->hasMsg()) { - std::unique_ptr origin(new VariableOrigin()); - std::string *a = new std::string(r->msg(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_msg, - a - ); - delete a; - origin->m_offset = 0; - origin->m_length = 0; + if (rule->hasMessageAction()) { + auto var = std::make_shared(&m_rule, &m_rule_msg, std::unique_ptr(new std::string(rule->getMessage(t)))); + VariableOrigin origin; + origin.m_offset = 0; + origin.m_length = 0; var->addOrigin(std::move(origin)); - l->push_back(var); + l->push_back(std::move(var)); } } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { + if (m_dictElement == "id") { - id(t, rule, l); + id(t, getRule(), l); return; } - if (rule && m_dictElement == "rev") { - rev(t, rule, l); + if (m_dictElement == "rev") { + rev(t, getRule(), l); return; } - if (rule && m_dictElement == "severity") { - severity(t, rule, l); + if (m_dictElement == "severity") { + 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; } } @@ -192,52 +160,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(const Transaction *t, + VariableValues *l) const noexcept override { - 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") { } - - 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_NoDictElement() + : RuleVariable(), + Variable("RULE") + { }; + + + explicit Rule_NoDictElement(const Rule_DictElementRegexp &r) + : RuleVariable(), + Variable(r) + { }; + + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { + 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 0000000000..9fd64b124a --- /dev/null +++ b/src/variables/rule_variable.h @@ -0,0 +1,62 @@ +/* + * 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_ + + + +namespace modsecurity { + +class RuleWithActions; +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) { + variables::Variable *rulev = + dynamic_cast(this); + 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 bc831e31d2..8206a72e0d 100644 --- a/src/variables/session.h +++ b/src/variables/session.h @@ -38,11 +38,10 @@ class Session_DictElement : public Variable { : Variable("SESSION:" + dictElement), m_dictElement("SESSION:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_session_collection->resolveMultiMatches( - m_name, t->m_collections.m_session_collection_key, + *getVariableKey(), t->m_collections.m_session_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -55,9 +54,8 @@ class Session_NoDictElement : public Variable { Session_NoDictElement() : Variable("SESSION") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_session_collection->resolveMultiMatches("", t->m_collections.m_session_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -71,9 +69,8 @@ class Session_DictElementRegexp : public VariableRegex { : VariableRegex("SESSION", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_session_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_session_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -83,15 +80,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "SESSION", + std::move(dictElement) + ) + { } + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_session_collection->resolveMultiMatches( string, @@ -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 b14e96109d..e7478635d1 100644 --- a/src/variables/time.cc +++ b/src/variables/time.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void Time::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void Time::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; @@ -47,9 +46,9 @@ void Time::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%H:%M:%S", &timeinfo); - transaction->m_variableTime.assign(tstr); - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTime)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time.h b/src/variables/time.h index 4f3dec89c4..f51ae33db5 100644 --- a/src/variables/time.h +++ b/src/variables/time.h @@ -35,9 +35,8 @@ class Time : public Variable { : Variable(_name), m_retName("TIME") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_day.cc b/src/variables/time_day.cc index f16500e952..2085ec8110 100644 --- a/src/variables/time_day.cc +++ b/src/variables/time_day.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeDay::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeDay::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeDay::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%d", &timeinfo); - transaction->m_variableTimeDay.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeDay)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_day.h b/src/variables/time_day.h index 946ba3aaca..950e5f754d 100644 --- a/src/variables/time_day.h +++ b/src/variables/time_day.h @@ -34,9 +34,8 @@ class TimeDay : public Variable { : Variable(_name), m_retName("TIME_DAY") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_epoch.cc b/src/variables/time_epoch.cc index f7ee0f52dd..dea7e143f8 100644 --- a/src/variables/time_epoch.cc +++ b/src/variables/time_epoch.cc @@ -33,13 +33,12 @@ namespace modsecurity { namespace variables { -void TimeEpoch::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { - transaction->m_variableTimeEpoch.assign( - std::to_string(std::time(nullptr))); - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeEpoch)); +void TimeEpoch::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { + + l->push_back(std::make_shared( + std::unique_ptr(new std::string(std::to_string(std::time(nullptr)))), + &m_retName)); } diff --git a/src/variables/time_epoch.h b/src/variables/time_epoch.h index a259e8638e..c34aaf04f5 100644 --- a/src/variables/time_epoch.h +++ b/src/variables/time_epoch.h @@ -34,9 +34,8 @@ class TimeEpoch : public Variable { : Variable(_name), m_retName("TIME_EPOCH") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_hour.cc b/src/variables/time_hour.cc index 380f471a5d..4a279fcfe1 100644 --- a/src/variables/time_hour.cc +++ b/src/variables/time_hour.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeHour::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeHour::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeHour::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%H", &timeinfo); - transaction->m_variableTimeHour.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeHour)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_hour.h b/src/variables/time_hour.h index aad53515b1..9e432be0d1 100644 --- a/src/variables/time_hour.h +++ b/src/variables/time_hour.h @@ -34,9 +34,8 @@ class TimeHour : public Variable { : Variable(_name), m_retName("TIME_HOUR") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_min.cc b/src/variables/time_min.cc index 099e668533..7c499c6928 100644 --- a/src/variables/time_min.cc +++ b/src/variables/time_min.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeMin::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeMin::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeMin::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%M", &timeinfo); - transaction->m_variableTimeMin.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeMin)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_min.h b/src/variables/time_min.h index fd26eb2685..688ec0c471 100644 --- a/src/variables/time_min.h +++ b/src/variables/time_min.h @@ -34,9 +34,8 @@ class TimeMin : public Variable { : Variable(_name), m_retName("TIME_MIN") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_mon.cc b/src/variables/time_mon.cc index c1ff817561..f99a89324d 100644 --- a/src/variables/time_mon.cc +++ b/src/variables/time_mon.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeMon::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeMon::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -45,13 +44,12 @@ void TimeMon::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%m", &timeinfo); - int a = atoi(tstr); - a--; + //int a = atoi(tstr); + //a--; - transaction->m_variableTimeMin.assign(std::to_string(a)); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeMin)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_mon.h b/src/variables/time_mon.h index e54866a38a..e150b5915d 100644 --- a/src/variables/time_mon.h +++ b/src/variables/time_mon.h @@ -34,9 +34,8 @@ class TimeMon : public Variable { : Variable(_name), m_retName("TIME_MON") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_sec.cc b/src/variables/time_sec.cc index 9e7a76cd5e..f066bbe71c 100644 --- a/src/variables/time_sec.cc +++ b/src/variables/time_sec.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeSec::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeSec::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeSec::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%S", &timeinfo); - transaction->m_variableTimeSec.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeSec)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_sec.h b/src/variables/time_sec.h index 2c9b431a6e..d83b385d2e 100644 --- a/src/variables/time_sec.h +++ b/src/variables/time_sec.h @@ -34,9 +34,8 @@ class TimeSec : public Variable { : Variable(_name), m_retName("TIME_SEC") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_wday.cc b/src/variables/time_wday.cc index daf29a7d40..24d30b074b 100644 --- a/src/variables/time_wday.cc +++ b/src/variables/time_wday.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeWDay::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeWDay::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeWDay::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%u", &timeinfo); - transaction->m_variableTimeWDay.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeWDay)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_wday.h b/src/variables/time_wday.h index 3969e74b8e..9bc1bf9a96 100644 --- a/src/variables/time_wday.h +++ b/src/variables/time_wday.h @@ -34,9 +34,8 @@ class TimeWDay : public Variable { : Variable(_name), m_retName("TIME_WDAY") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/time_year.cc b/src/variables/time_year.cc index dbec656c74..23850bfe2f 100644 --- a/src/variables/time_year.cc +++ b/src/variables/time_year.cc @@ -33,9 +33,8 @@ namespace modsecurity { namespace variables { -void TimeYear::evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) { +void TimeYear::evaluate(const Transaction *transaction, + VariableValues *l) const noexcept { char tstr[200]; struct tm timeinfo; time_t timer; @@ -46,10 +45,9 @@ void TimeYear::evaluate(Transaction *transaction, localtime_r(&timer, &timeinfo); strftime(tstr, 200, "%Y", &timeinfo); - transaction->m_variableTimeYear.assign(tstr); - - l->push_back(new VariableValue(&m_retName, - &transaction->m_variableTimeYear)); + l->push_back(std::make_shared( + std::unique_ptr(new std::string(tstr)), + &m_retName)); } diff --git a/src/variables/time_year.h b/src/variables/time_year.h index 52099a8385..56c1c034a2 100644 --- a/src/variables/time_year.h +++ b/src/variables/time_year.h @@ -34,9 +34,8 @@ class TimeYear : public Variable { : Variable(_name), m_retName("TIME_YEAR") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override; std::string m_retName; }; diff --git a/src/variables/tx.h b/src/variables/tx.h index c665433d82..b6e7315145 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 { @@ -38,11 +39,10 @@ class Tx_DictElement : public Variable { : Variable("TX:" + dictElement), m_dictElement("TX:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_tx_collection->resolveMultiMatches( - m_name, l, m_keyExclusion); + *getVariableKey(), l, m_keyExclusion); } std::string m_dictElement; @@ -54,9 +54,8 @@ class Tx_NoDictElement : public Variable { Tx_NoDictElement() : Variable("TX") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_tx_collection->resolveMultiMatches("", l, m_keyExclusion); } @@ -69,9 +68,8 @@ class Tx_DictElementRegexp : public VariableRegex { : VariableRegex("TX", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_tx_collection->resolveRegularExpression( m_dictElement, l, m_keyExclusion); } @@ -80,15 +78,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "TX", + std::move(dictElement) + ) + { } + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_tx_collection->resolveMultiMatches(string, l, m_keyExclusion); @@ -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 8860019839..78040d87fb 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 { @@ -38,11 +39,10 @@ class User_DictElement : public Variable { : Variable("USER:" + dictElement), m_dictElement("USER:" + dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_user_collection->resolveMultiMatches( - m_name, t->m_collections.m_user_collection_key, + *getVariableKey(), t->m_collections.m_user_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -55,10 +55,9 @@ class User_NoDictElement : public Variable { User_NoDictElement() : Variable("USER") { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { - t->m_collections.m_user_collection->resolveMultiMatches(m_name, + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { + t->m_collections.m_user_collection->resolveMultiMatches(*getVariableKey(), t->m_collections.m_user_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); } @@ -71,9 +70,8 @@ class User_DictElementRegexp : public VariableRegex { : VariableRegex("USER", dictElement), m_dictElement(dictElement) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { t->m_collections.m_user_collection->resolveRegularExpression( m_dictElement, t->m_collections.m_user_collection_key, t->m_rules->m_secWebAppId.m_value, l, m_keyExclusion); @@ -83,15 +81,17 @@ 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)) { } - - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { + : VariableWithRunTimeString( + "USER", + std::move(dictElement) + ) + { } + + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { std::string string = m_string->evaluate(t); t->m_collections.m_user_collection->resolveMultiMatches( string, @@ -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.cc b/src/variables/variable.cc index 416ca9f4f3..161320b9ee 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -29,31 +29,25 @@ namespace variables { Variable::Variable(const std::string &name) - : m_name(name), - m_collectionName("") { - size_t a = m_name.find(":"); + : m_keyWithCollection(new std::string("")), + m_keyExclusion(), + m_collectionName(new std::string("")), + m_key(new std::string("")) { + size_t a = name.find(":"); if (a == std::string::npos) { - a = m_name.find("."); + a = name.find("."); } if (a != std::string::npos) { - m_collectionName = utils::string::toupper(std::string(m_name, 0, a)); - m_name = std::string(m_name, a + 1, m_name.size()); - m_fullName = std::make_shared(m_collectionName - + ":" + m_name); + m_collectionName->assign(utils::string::toupper(std::string(name, 0, a))); + m_key->assign(std::string(name, a + 1, name.size())); + m_keyWithCollection->assign(*m_collectionName.get() + ":" + std::string(name, a + 1, name.size())); } else { - m_fullName = std::make_shared(m_name); - m_collectionName = m_name; - m_name = ""; + m_keyWithCollection->assign(name); + m_collectionName->assign(name); } } -Variable::Variable(Variable *var) : - m_name(var->m_name), - m_collectionName(var->m_collectionName), - m_fullName(var->m_fullName) { } - - void Variable::addsKeyExclusion(Variable *v) { std::unique_ptr r; VariableModificatorExclusion *ve = \ @@ -67,7 +61,7 @@ void Variable::addsKeyExclusion(Variable *v) { vr = dynamic_cast(ve->m_base.get()); if (vr == NULL) { - r.reset(new KeyExclusionString(v->m_name)); + r.reset(new KeyExclusionString(*v->getVariableKey())); } else { r.reset(new KeyExclusionRegex(vr->m_regex)); } @@ -77,7 +71,7 @@ void Variable::addsKeyExclusion(Variable *v) { std::string operator+(const std::string &a, Variable *v) { - return a + *v->m_fullName.get(); + return a + *v->getVariableKeyWithCollection(); } diff --git a/src/variables/variable.h b/src/variables/variable.h index 09dff6b8ce..53bbdb3d1c 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" @@ -48,9 +47,8 @@ class n ## _DictElementRegexp : public VariableRegex { \ explicit n ## _DictElementRegexp(const std::string ®ex) \ : VariableRegex(#N, regex) { } \ \ - void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ - std::vector *l) override { \ + void evaluate(const Transaction *transaction, \ + VariableValues *l) const noexcept override { \ transaction-> e .resolveRegularExpression(&m_r, l, \ m_keyExclusion); \ } \ @@ -63,9 +61,8 @@ class n ## _DictElement : public VariableDictElement { \ explicit n ## _DictElement(const std::string &dictElement) \ : VariableDictElement(#N, dictElement) { } \ \ - void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ - std::vector *l) override { \ + void evaluate(const Transaction *transaction, \ + VariableValues *l) const noexcept override { \ transaction-> e .resolve(m_dictElement, l); \ } \ }; @@ -77,9 +74,8 @@ class n ## _NoDictElement : public Variable { \ explicit n ## _NoDictElement() \ : Variable(#N) { } \ \ - void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ - std::vector *l) override { \ + void evaluate(const Transaction *transaction, \ + VariableValues *l) const noexcept override { \ transaction-> e .resolve(l, m_keyExclusion); \ } \ }; @@ -91,14 +87,15 @@ class n : public Variable { \ n() \ : Variable(#N) { } \ \ - void evaluate(Transaction *transaction, \ - RuleWithActions *rule, \ - std::vector *l) override { \ + void evaluate(const Transaction *transaction, \ + VariableValues *l) const noexcept override { \ transaction-> e .evaluate(l); \ } \ }; +// FIXME: Copy methods for variables modificators needs to be done. + namespace modsecurity { class Transaction; @@ -107,7 +104,8 @@ namespace variables { class KeyExclusion { public: KeyExclusion() { } - virtual bool match(const std::string &a) = 0; + virtual bool match(const std::string &a) const = 0; + virtual bool match(const bpstd::string_view &a) const = 0; virtual ~KeyExclusion() { } }; @@ -122,9 +120,13 @@ class KeyExclusionRegex : public KeyExclusion { ~KeyExclusionRegex() override { } - bool match(const std::string &a) override { + bool match(const std::string &a) const override { return m_re.searchAll(a).size() > 0; } + bool match(const bpstd::string_view &a) const override { + // FIXME: string_view will be a good thing in searchAll. + return m_re.searchAll(std::string(a)).size() > 0; + } Utils::Regex m_re; }; @@ -137,7 +139,14 @@ class KeyExclusionString : public KeyExclusion { ~KeyExclusionString() override { } - bool match(const std::string &a) override { + bool match(const std::string &a) const override { + return a.size() == m_key.size() && std::equal(a.begin(), a.end(), + m_key.begin(), + [](char aa, char bb) { + return static_cast(toupper(aa)) == static_cast(bb); + }); + } + bool match(const bpstd::string_view &a) const override { return a.size() == m_key.size() && std::equal(a.begin(), a.end(), m_key.begin(), [](char aa, char bb) { @@ -151,10 +160,30 @@ 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(const std::string &a) const { + for (auto &z : *this) { + if (z->match(a)) { + return true; + } + } + return false; } - bool toOmit(std::string a) { + bool toOmit(const bpstd::string_view &a) const { for (auto &z : *this) { if (z->match(a)) { return true; @@ -162,6 +191,7 @@ class KeyExclusions : public std::deque> { } return false; } + }; @@ -176,9 +206,9 @@ class VariableMonkeyResolution { }); } - static void stringMatchResolveMulti(Transaction *t, + static void stringMatchResolveMulti(const Transaction *t, const std::string &variable, - std::vector *l) { + VariableValues *l) { size_t collection = variable.find("."); if (collection == std::string::npos) { collection = variable.find(":"); @@ -339,7 +369,7 @@ class VariableMonkeyResolution { } } - static std::string stringMatchResolve(Transaction *t, + static std::string stringMatchResolve(const Transaction *t, const std::string &variable) { std::unique_ptr vv = nullptr; size_t collection = variable.find("."); @@ -545,19 +575,36 @@ class VariableMonkeyResolution { class Variable : public VariableMonkeyResolution { public: explicit Variable(const std::string &name); - explicit Variable(Variable *_name); - virtual ~Variable() { } - virtual void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) = 0; + explicit Variable(Variable *var) + : m_keyWithCollection(var->m_keyWithCollection), + m_keyExclusion(var->m_keyExclusion), + m_collectionName(var->m_collectionName), + m_key(var->m_key) + { }; + + + Variable(const Variable &v) + : m_keyWithCollection(v.m_keyWithCollection), + m_keyExclusion(v.m_keyExclusion), + m_collectionName(v.m_collectionName), + m_key(v.m_key) + { }; + + + virtual ~Variable() + { }; + + virtual void evaluate(const Transaction *t, + VariableValues *l) const noexcept = 0; - bool inline belongsToCollection(Variable *var) { - return m_collectionName.size() == var->m_collectionName.size() - && std::equal(m_collectionName.begin(), m_collectionName.end(), - var->m_collectionName.begin(), + + bool inline belongsToCollection(Variable *var) const noexcept { + return m_collectionName->size() == var->m_collectionName->size() + && std::equal(m_collectionName->begin(), m_collectionName->end(), + var->m_collectionName->begin(), [](char aa, char bb) { return toupper(aa) == bb; }); @@ -567,26 +614,76 @@ class Variable : public VariableMonkeyResolution { void addsKeyExclusion(Variable *v); - bool operator==(const Variable& b) const { - return m_collectionName == b.m_collectionName && - m_name == b.m_name && - *m_fullName == *b.m_fullName; + bool operator==(const Variable& b) const noexcept { + return *m_collectionName == *b.m_collectionName && + *m_key == *b.m_key && + *m_keyWithCollection == *b.m_keyWithCollection; } - std::string& operator+=(const char * p) { return m_name; } + std::string& operator+=(const char *p) { return *m_key; } + + /** + * + * Returns the variable key, if any is specified. + * + * 'ENV:a' will return 'a' + * 'ENV' will return a blank std::shared_ptr. + * + **/ + std::shared_ptr getVariableKey() const noexcept { + return m_key; + } - std::string m_name; - std::string m_collectionName; - std::shared_ptr m_fullName; + /** + * + * Returns the Collection name. + * + * 'ENV:a' will return 'ENV' + * 'ENV' will return 'ENV' + * + **/ + std::shared_ptr getVariableCollection() const noexcept { + return m_collectionName; + } + + + /** + * + * Returns the Collection with key name. + * + * 'ENV:a' will return 'ENV:a' + * 'ENV' will return 'ENV' + * + **/ + std::shared_ptr getVariableKeyWithCollection() const noexcept { + return m_keyWithCollection; + } + + + protected: KeyExclusions m_keyExclusion; + + private: + std::shared_ptr m_keyWithCollection; + std::shared_ptr m_key; + std::shared_ptr m_collectionName; }; + + 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 +694,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. @@ -610,6 +715,7 @@ class Variables : public std::vector { return std::find_if(begin(), end(), [v](Variable *m) -> bool { return *v == *m; }) != end(); }; + bool contains(const VariableValue *v) { return std::find_if(begin(), end(), [v](Variable *m) -> bool { @@ -617,9 +723,22 @@ class Variables : public std::vector { if (r) { return r->m_r.searchAll(v->getKey()).size() > 0; } - return v->getKeyWithCollection() == *m->m_fullName.get(); + return v->getName() == *m->getVariableKeyWithCollection(); }) != end(); }; + + + std::string getVariableNames(const std::string &sep = ",") { + std::string names; + for (auto a : *this) { + if (names.length() > 0) { + names = names + sep + *a->getVariableKeyWithCollection(); + } else { + names = *a->getVariableKeyWithCollection(); + } + } + return names; + } }; @@ -629,10 +748,9 @@ class VariableModificatorExclusion : public Variable { : Variable(var.get()), m_base(std::move(var)) { } - void evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) override { - m_base->evaluate(t, rule, l); + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { + m_base->evaluate(t, l); } std::unique_ptr m_base; @@ -647,27 +765,15 @@ class VariableModificatorCount : public Variable { m_base.reset(var.release()); } - 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); - - for (const VariableValue *a : reslIn) { - count++; - delete a; - a = NULL; - } - reslIn.clear(); + void evaluate(const Transaction *t, + VariableValues *l) const noexcept override { - std::string *res = new std::string(std::to_string(count)); - val = new VariableValue(m_fullName.get(), res); - delete res; + VariableValues reslIn; + m_base->evaluate(t, &reslIn); + auto count = reslIn.size(); - l->push_back(val); + std::string res(std::to_string(count)); + l->push_back(std::make_shared(getVariableKeyWithCollection().get(), &res)); return; } diff --git a/src/variables/variable_with_runtime_string.h b/src/variables/variable_with_runtime_string.h new file mode 100644 index 0000000000..cb4b263447 --- /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(const 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 d5f1aa545f..8b79c9b62c 100644 --- a/src/variables/web_app_id.h +++ b/src/variables/web_app_id.h @@ -35,12 +35,10 @@ class WebAppId : public Variable { WebAppId() : Variable("WEBAPPID") { } - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override { - const std::string name("WEBAPPID"); + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override { const std::string rname = transaction->m_rules->m_secWebAppId.m_value; - l->push_back(new VariableValue(&m_name, &rname)); + l->push_back(std::make_shared(getVariableKeyWithCollection().get(), &rname)); } }; diff --git a/src/variables/xml.cc b/src/variables/xml.cc index 7cb14a5fcd..b2c1de762c 100644 --- a/src/variables/xml.cc +++ b/src/variables/xml.cc @@ -42,19 +42,19 @@ #include "src/request_body_processor/xml.h" #include "modsecurity/actions/action.h" #include "src/actions/xmlns.h" +#include "src/rule_with_actions.h" + namespace modsecurity { namespace variables { #ifndef WITH_LIBXML2 -void XML::evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) { } +void XML_WithNSPath::evaluate(const Transaction *t, + VariableValues *l) const noexcept { } #else -void XML::evaluate(Transaction *t, - RuleWithActions *rule, - std::vector *l) { +void XML_WithNSPath::evaluate(const Transaction *t, + VariableValues *l) const noexcept { xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; xmlNodeSetPtr nodes; @@ -63,7 +63,7 @@ void XML::evaluate(Transaction *t, int i; //size_t pos; - param = m_name; + param = *getVariableKey(); /* pos = m_name.find_first_of(":"); if (pos == std::string::npos) { @@ -86,21 +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->getActionsByName("xmlns", t); - for (auto &x : acts) { - actions::XmlNS *z = (actions::XmlNS *)x; - if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->m_scope.c_str(), - (const xmlChar*)z->m_href.c_str()) != 0) { + XmlNSsPtr acts = getRule()->getXmlNSsPtr(); + for (auto &z : acts) { + 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() + "\""); } } @@ -124,13 +123,10 @@ void XML::evaluate(Transaction *t, content = reinterpret_cast( xmlNodeGetContent(nodes->nodeTab[i])); if (content != NULL) { - std::string *a = new std::string(content); - VariableValue *var = new VariableValue(m_fullName.get(), - a); - if (!m_keyExclusion.toOmit(*m_fullName)) { - l->push_back(var); + std::string a(content); + if (!m_keyExclusion.toOmit(*getVariableKeyWithCollection())) { + l->push_back(std::make_shared(getVariableKeyWithCollection().get(), &a)); } - delete a; xmlFree(content); } } diff --git a/src/variables/xml.h b/src/variables/xml.h index 7b0181fe99..fb23acace3 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(std::make_shared(getVariableKeyWithCollection().get(), &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)); + void evaluate(const Transaction *transaction, + VariableValues *l) const noexcept override { + l->push_back(m_var); } + virtual variables::Variable *clone() override { + return new XML_WithoutNSPath(*this); + }; + std::string m_plain; - VariableValue m_var; + std::shared_ptr 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(const Transaction *transaction, + VariableValues *l) const noexcept override; - void evaluate(Transaction *transaction, - RuleWithActions *rule, - std::vector *l) override; + virtual Variable *clone() override { + return new XML_WithNSPath(*this); + }; }; diff --git a/test/cppcheck_suppressions.txt b/test/cppcheck_suppressions.txt index 0336b6aa24..78d12616fb 100644 --- a/test/cppcheck_suppressions.txt +++ b/test/cppcheck_suppressions.txt @@ -19,6 +19,12 @@ *:others/mbedtls/sha1.c +// +// 3rd party string view +// +*:headers/modsecurity/string_view.hpp + + // // Code imported from ModSecurity v2... // @@ -27,20 +33,21 @@ shiftNegative:src/utils/msc_tree.cc *:src/utils/msc_tree.cc invalidScanfArgType_int:src/rules_set_properties.cc:101 invalidScanfArgType_int:src/rules_set_properties.cc:102 +redundantAssignment:src/operators/pm.cc:94 // // ModSecurity v3 code... // -unmatchedSuppression:src/utils/geo_lookup.cc:82 +functionStatic:src/operators/geo_lookup.h:39 useInitializationList:src/utils/shared_files.h:87 unmatchedSuppression:src/utils/msc_tree.cc -functionStatic:headers/modsecurity/transaction.h:404 +functionStatic:headers/modsecurity/transaction.h:437 duplicateBranch:src/audit_log/audit_log.cc:223 unreadVariable:src/request_body_processor/multipart.cc:435 stlcstrParam:src/audit_log/writer/parallel.cc:145 -functionStatic:src/engine/lua.h:71 -functionStatic:src/engine/lua.h:72 +functionStatic:src/engine/lua.h:79 +functionStatic:src/engine/lua.h:80 functionConst:src/utils/geo_lookup.h:49 useInitializationList:src/operators/rbl.h:69 constStatement:test/common/modsecurity_test.cc:82 @@ -51,6 +58,10 @@ duplicateBranch:src/request_body_processor/multipart.cc:91 syntaxError:src/transaction.cc:62 noConstructor:src/variables/variable.h:152 duplicateBranch:src/request_body_processor/multipart.cc:93 +knownConditionTrueFalse:src/operators/validate_url_encoding.cc:79 +knownConditionTrueFalse:src/operators/verify_svnr.cc:90 +noConstructor:src/actions/rule_id.h:33 +functionStatic:src/actions/rule_id.h:35 noExplicitConstructor:seclang-parser.hh @@ -61,3 +72,17 @@ preprocessorErrorDirective funcArgNamesDifferent unmatchedSuppression missingInclude +unusedFunction +missingIncludeSystem +useStlAlgorithm +preprocessorErrorDirective +funcArgNamesDifferent +unmatchedSuppression +missingInclude + +purgedConfiguration + + +// Examples +memleak:examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h:147 +memleak:examples/using_bodies_in_chunks/simple_request.cc diff --git a/test/fuzzer/afl_fuzzer.cc b/test/fuzzer/afl_fuzzer.cc index d544bc742d..dd4ef487d7 100644 --- a/test/fuzzer/afl_fuzzer.cc +++ b/test/fuzzer/afl_fuzzer.cc @@ -121,14 +121,16 @@ using namespace modsecurity; inline void op_test(const std::string &opName, const std::string &s) { Operator *op = Operator::instantiate(opName, ""); op->init("", nullptr); - op->evaluate(nullptr, nullptr, s, nullptr); + op->execute(nullptr, nullptr, s, nullptr); delete op; } int main(int argc, char** argv) { uint8_t buf[128]; +#if 0 std::string lastString; +#endif while (__AFL_LOOP(1000)) { ssize_t read_bytes; @@ -138,7 +140,9 @@ int main(int argc, char** argv) { std::string currentString = std::string(read_bytes, 128); std::string s = currentString; +#if 0 std::string z = lastString; +#endif ModSecurity *ms = new ModSecurity(); RulesSet *rules = new RulesSet(); @@ -150,52 +154,52 @@ int main(int argc, char** argv) { /** * Transformations, generated by: * - * for i in $(grep "class " -Ri src/actions/transformations/* | grep " :" | grep -v "InstantCache" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\"\)\; $(echo $i | awk '{print tolower($0)}')-\>evaluate\(s, NULL\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; + * for i in $(grep "class " -Ri src/actions/transformations/* | grep " :" | grep -v "InstantCache" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\"\)\; $(echo $i | awk '{print tolower($0)}')-\>execute\(s, NULL\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; * */ -Base64Decode *base64decode = new Base64Decode("Base64Decode"); base64decode->evaluate(s, NULL); delete base64decode; -Base64DecodeExt *base64decodeext = new Base64DecodeExt("Base64DecodeExt"); base64decodeext->evaluate(s, NULL); delete base64decodeext; -Base64Encode *base64encode = new Base64Encode("Base64Encode"); base64encode->evaluate(s, NULL); delete base64encode; -CmdLine *cmdline = new CmdLine("CmdLine"); cmdline->evaluate(s, NULL); delete cmdline; -CompressWhitespace *compresswhitespace = new CompressWhitespace("CompressWhitespace"); compresswhitespace->evaluate(s, NULL); delete compresswhitespace; -CssDecode *cssdecode = new CssDecode("CssDecode"); cssdecode->evaluate(s, NULL); delete cssdecode; -EscapeSeqDecode *escapeseqdecode = new EscapeSeqDecode("EscapeSeqDecode"); escapeseqdecode->evaluate(s, NULL); delete escapeseqdecode; -HexDecode *hexdecode = new HexDecode("HexDecode"); hexdecode->evaluate(s, NULL); delete hexdecode; -HexEncode *hexencode = new HexEncode("HexEncode"); hexencode->evaluate(s, NULL); delete hexencode; -HtmlEntityDecode *htmlentitydecode = new HtmlEntityDecode("HtmlEntityDecode"); htmlentitydecode->evaluate(s, NULL); delete htmlentitydecode; -JsDecode *jsdecode = new JsDecode("JsDecode"); jsdecode->evaluate(s, NULL); delete jsdecode; -Length *length = new Length("Length"); length->evaluate(s, NULL); delete length; -LowerCase *lowercase = new LowerCase("LowerCase"); lowercase->evaluate(s, NULL); delete lowercase; -Md5 *md5 = new Md5("Md5"); md5->evaluate(s, NULL); delete md5; -None *none = new None("None"); none->evaluate(s, NULL); delete none; -NormalisePath *normalisepath = new NormalisePath("NormalisePath"); normalisepath->evaluate(s, NULL); delete normalisepath; -NormalisePathWin *normalisepathwin = new NormalisePathWin("NormalisePathWin"); normalisepathwin->evaluate(s, NULL); delete normalisepathwin; -ParityEven7bit *parityeven7bit = new ParityEven7bit("ParityEven7bit"); parityeven7bit->evaluate(s, NULL); delete parityeven7bit; -ParityOdd7bit *parityodd7bit = new ParityOdd7bit("ParityOdd7bit"); parityodd7bit->evaluate(s, NULL); delete parityodd7bit; -ParityZero7bit *parityzero7bit = new ParityZero7bit("ParityZero7bit"); parityzero7bit->evaluate(s, NULL); delete parityzero7bit; -RemoveComments *removecomments = new RemoveComments("RemoveComments"); removecomments->evaluate(s, NULL); delete removecomments; -RemoveCommentsChar *removecommentschar = new RemoveCommentsChar("RemoveCommentsChar"); removecommentschar->evaluate(s, NULL); delete removecommentschar; -RemoveNulls *removenulls = new RemoveNulls("RemoveNulls"); removenulls->evaluate(s, NULL); delete removenulls; -RemoveWhitespace *removewhitespace = new RemoveWhitespace("RemoveWhitespace"); removewhitespace->evaluate(s, NULL); delete removewhitespace; -ReplaceComments *replacecomments = new ReplaceComments("ReplaceComments"); replacecomments->evaluate(s, NULL); delete replacecomments; -ReplaceNulls *replacenulls = new ReplaceNulls("ReplaceNulls"); replacenulls->evaluate(s, NULL); delete replacenulls; -Sha1 *sha1 = new Sha1("Sha1"); sha1->evaluate(s, NULL); delete sha1; -SqlHexDecode *sqlhexdecode = new SqlHexDecode("SqlHexDecode"); sqlhexdecode->evaluate(s, NULL); delete sqlhexdecode; -Transformation *transformation = new Transformation("Transformation"); transformation->evaluate(s, NULL); delete transformation; -Trim *trim = new Trim("Trim"); trim->evaluate(s, NULL); delete trim; -TrimLeft *trimleft = new TrimLeft("TrimLeft"); trimleft->evaluate(s, NULL); delete trimleft; -TrimRight *trimright = new TrimRight("TrimRight"); trimright->evaluate(s, NULL); delete trimright; -UpperCase *uppercase = new UpperCase("UpperCase"); uppercase->evaluate(s, NULL); delete uppercase; -UrlDecode *urldecode = new UrlDecode("UrlDecode"); urldecode->evaluate(s, NULL); delete urldecode; -UrlDecodeUni *urldecodeuni = new UrlDecodeUni("UrlDecodeUni"); urldecodeuni->evaluate(s, NULL); delete urldecodeuni; -UrlEncode *urlencode = new UrlEncode("UrlEncode"); urlencode->evaluate(s, NULL); delete urlencode; -Utf8ToUnicode *utf8tounicode = new Utf8ToUnicode("Utf8ToUnicode"); utf8tounicode->evaluate(s, NULL); delete utf8tounicode; +Base64Decode *base64decode = new Base64Decode("Base64Decode"); base64decode->execute(s, NULL); delete base64decode; +Base64DecodeExt *base64decodeext = new Base64DecodeExt("Base64DecodeExt"); base64decodeext->execute(s, NULL); delete base64decodeext; +Base64Encode *base64encode = new Base64Encode("Base64Encode"); base64encode->execute(s, NULL); delete base64encode; +CmdLine *cmdline = new CmdLine("CmdLine"); cmdline->execute(s, NULL); delete cmdline; +CompressWhitespace *compresswhitespace = new CompressWhitespace("CompressWhitespace"); compresswhitespace->execute(s, NULL); delete compresswhitespace; +CssDecode *cssdecode = new CssDecode("CssDecode"); cssdecode->execute(s, NULL); delete cssdecode; +EscapeSeqDecode *escapeseqdecode = new EscapeSeqDecode("EscapeSeqDecode"); escapeseqdecode->execute(s, NULL); delete escapeseqdecode; +HexDecode *hexdecode = new HexDecode("HexDecode"); hexdecode->execute(s, NULL); delete hexdecode; +HexEncode *hexencode = new HexEncode("HexEncode"); hexencode->execute(s, NULL); delete hexencode; +HtmlEntityDecode *htmlentitydecode = new HtmlEntityDecode("HtmlEntityDecode"); htmlentitydecode->execute(s, NULL); delete htmlentitydecode; +JsDecode *jsdecode = new JsDecode("JsDecode"); jsdecode->execute(s, NULL); delete jsdecode; +Length *length = new Length("Length"); length->execute(s, NULL); delete length; +LowerCase *lowercase = new LowerCase("LowerCase"); lowercase->execute(s, NULL); delete lowercase; +Md5 *md5 = new Md5("Md5"); md5->execute(s, NULL); delete md5; +None *none = new None("None"); none->execute(s, NULL); delete none; +NormalisePath *normalisepath = new NormalisePath("NormalisePath"); normalisepath->execute(s, NULL); delete normalisepath; +NormalisePathWin *normalisepathwin = new NormalisePathWin("NormalisePathWin"); normalisepathwin->execute(s, NULL); delete normalisepathwin; +ParityEven7bit *parityeven7bit = new ParityEven7bit("ParityEven7bit"); parityeven7bit->execute(s, NULL); delete parityeven7bit; +ParityOdd7bit *parityodd7bit = new ParityOdd7bit("ParityOdd7bit"); parityodd7bit->execute(s, NULL); delete parityodd7bit; +ParityZero7bit *parityzero7bit = new ParityZero7bit("ParityZero7bit"); parityzero7bit->execute(s, NULL); delete parityzero7bit; +RemoveComments *removecomments = new RemoveComments("RemoveComments"); removecomments->execute(s, NULL); delete removecomments; +RemoveCommentsChar *removecommentschar = new RemoveCommentsChar("RemoveCommentsChar"); removecommentschar->execute(s, NULL); delete removecommentschar; +RemoveNulls *removenulls = new RemoveNulls("RemoveNulls"); removenulls->execute(s, NULL); delete removenulls; +RemoveWhitespace *removewhitespace = new RemoveWhitespace("RemoveWhitespace"); removewhitespace->execute(s, NULL); delete removewhitespace; +ReplaceComments *replacecomments = new ReplaceComments("ReplaceComments"); replacecomments->execute(s, NULL); delete replacecomments; +ReplaceNulls *replacenulls = new ReplaceNulls("ReplaceNulls"); replacenulls->execute(s, NULL); delete replacenulls; +Sha1 *sha1 = new Sha1("Sha1"); sha1->execute(s, NULL); delete sha1; +SqlHexDecode *sqlhexdecode = new SqlHexDecode("SqlHexDecode"); sqlhexdecode->execute(s, NULL); delete sqlhexdecode; +Transformation *transformation = new Transformation("Transformation"); transformation->execute(s, NULL); delete transformation; +Trim *trim = new Trim("Trim"); trim->execute(s, NULL); delete trim; +TrimLeft *trimleft = new TrimLeft("TrimLeft"); trimleft->execute(s, NULL); delete trimleft; +TrimRight *trimright = new TrimRight("TrimRight"); trimright->execute(s, NULL); delete trimright; +UpperCase *uppercase = new UpperCase("UpperCase"); uppercase->execute(s, NULL); delete uppercase; +UrlDecode *urldecode = new UrlDecode("UrlDecode"); urldecode->execute(s, NULL); delete urldecode; +UrlDecodeUni *urldecodeuni = new UrlDecodeUni("UrlDecodeUni"); urldecodeuni->execute(s, NULL); delete urldecodeuni; +UrlEncode *urlencode = new UrlEncode("UrlEncode"); urlencode->execute(s, NULL); delete urlencode; +Utf8ToUnicode *utf8tounicode = new Utf8ToUnicode("Utf8ToUnicode"); utf8tounicode->execute(s, NULL); delete utf8tounicode; /** * Operators, generated by: * - * for i in $(grep "class " -Ri src/operators/* | grep " :" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\", z, false\)\; $(echo $i | awk '{print tolower($0)}')-\>evaluate\(t, s\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; + * for i in $(grep "class " -Ri src/operators/* | grep " :" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\", z, false\)\; $(echo $i | awk '{print tolower($0)}')-\>execute\(t, s\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; * */ op_test("BeginsWith", s); @@ -266,8 +270,9 @@ op_test("Within", s); delete t; delete rules; delete ms; - +#if 0 lastString = currentString; +#endif } return 0; } diff --git a/test/regression/regression.cc b/test/regression/regression.cc index c4600fae4c..64db189338 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -211,7 +211,7 @@ void perform_unit_test(ModSecurityTest *test, */ if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \ - << ":" << t->name << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; } @@ -254,7 +254,7 @@ void perform_unit_test(ModSecurityTest *test, /* Parser error was expected, but with a different content */ if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \ - << ":" << t->name << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; } @@ -280,7 +280,7 @@ void perform_unit_test(ModSecurityTest *test, if (t->parser_error.empty() == false) { if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \ - << ":" << t->name << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; std::cout << KWHT << "Expected a parser error." \ @@ -387,7 +387,7 @@ void perform_unit_test(ModSecurityTest *test, if (!d->contains(t->debug_log)) { if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \ - << ":" << t->name << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; } @@ -399,7 +399,7 @@ void perform_unit_test(ModSecurityTest *test, } else if (r.status != t->http_code) { if (test->m_automake_output) { std::cout << ":test-result: FAIL " << filename \ - << ":" << t->name << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; } @@ -423,7 +423,7 @@ void perform_unit_test(ModSecurityTest *test, && !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 << std::endl; + << ":" << t->name << ":" << *count << std::endl; } else { std::cout << KRED << "failed!" << RESET << std::endl; } diff --git a/test/test-cases/regression/action-block.json b/test/test-cases/regression/action-block.json index 239df02715..8bed10927b 100644 --- a/test/test-cases/regression/action-block.json +++ b/test/test-cases/regression/action-block.json @@ -27,7 +27,7 @@ }, "rules":[ "SecRuleEngine On", - "SecDefaultAction \"phase:1,log,block,status:404\"", + "SecDefaultAction \"phase:1,log,status:404\"", "SecRule REQUEST_URI \"@contains path1\" \"phase:1,block,id:5\"" ] }, @@ -59,7 +59,7 @@ }, "rules":[ "SecRuleEngine On", - "SecDefaultAction \"phase:1,log,block,deny,status:400\"", + "SecDefaultAction \"phase:1,log,deny,status:400\"", "SecRule REQUEST_URI \"@contains path1\" \"phase:1,block,id:5\"" ] } diff --git a/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json b/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json index 142ac6230e..7c95fbc57f 100644 --- a/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json +++ b/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json @@ -95,5 +95,170 @@ "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=1;ARGS\"", "SecRule ARGS \"@contains lhebs\" \"id:1,phase:3,t:none,status:202,block,deny,tag:'CRS'\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoveTargetById (4) range: within range", + "expected":{ + "http_code": 200 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"", + "SecRule ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoveTargetById (5) range: within range but !target", + "expected":{ + "http_code": 403 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pswd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"", + "SecRule ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoveTargetById (6) range: outside of range", + "expected":{ + "http_code": 403 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"", + "SecRule ARGS \"@contains lhebs\" \"id:7,phase:2,t:none,deny,status:403\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoveTargetById (7) range: remove the collection", + "expected":{ + "http_code": 200 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS\"", + "SecRule ARGS_NAMES|ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoveTargetById (8) range: remove other collection", + "expected":{ + "http_code": 403 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS_NAMES\"", + "SecRule ARGS_NAMES|ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\"" + ] } ] diff --git a/test/test-cases/regression/action-initcol.json b/test/test-cases/regression/action-initcol.json index 5051f2e6a5..c6ddd1c21d 100644 --- a/test/test-cases/regression/action-initcol.json +++ b/test/test-cases/regression/action-initcol.json @@ -13,7 +13,6 @@ "request":{ "headers":{ "Host":"localhost", - "User-Agent":"curl/7.38.0", "Accept":"*/*", "User-Agent":"My sweet little browser" }, diff --git a/test/test-cases/regression/action-tnf-base64.json b/test/test-cases/regression/action-tnf-base64.json index 7cb047ce2f..08875aaa70 100644 --- a/test/test-cases/regression/action-tnf-base64.json +++ b/test/test-cases/regression/action-tnf-base64.json @@ -36,7 +36,7 @@ ] }, "expected":{ - "debug_log": "t:base64encode: \"dmFsdWUyCg==\"" + "debug_log": "t:base64Encode: \"dmFsdWUyCg==\"" }, "rules":[ "SecRuleEngine On", @@ -80,7 +80,7 @@ ] }, "expected":{ - "debug_log": "t:base64decode: \"value2\"" + "debug_log": "t:base64Decode: \"value2\"" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/auditlog-ctl.json b/test/test-cases/regression/auditlog-ctl.json new file mode 100644 index 0000000000..40a220b939 --- /dev/null +++ b/test/test-cases/regression/auditlog-ctl.json @@ -0,0 +1,240 @@ +[ + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "ctl:auditlogparts : +E", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "www.modsecurity.org", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1= test ¶m2=test2", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "plain\/text\n\r" + }, + "body": [ + "test" + ] + }, + "expected": { + "audit_log": "", + "debug_log": "Request was relevant to be saved. Parts: 34", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts A", + "SecAuditLogStorageDir /tmp/test", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0600", + "SecAuditLogType Parallel", + "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"", + "SecRule ARGS \"@contains test\" \"id:1,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:2,t:trim,deny,auditlog\"" + ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "ctl:auditlogparts : +E-E", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "www.modsecurity.org", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1= test ¶m2=test2", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "plain\/text\n\r" + }, + "body": [ + "test" + ] + }, + "expected": { + "audit_log": "", + "debug_log": "Request was relevant to be saved. Parts: 2", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts A", + "SecAuditLogStorageDir /tmp/test", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0600", + "SecAuditLogType Parallel", + "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"", + "SecRule ARGS \"@contains test\" \"id:1,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:2,t:trim,ctl:auditlogparts=-E\"", + "SecRule ARGS \"@contains test\" \"id:3,t:trim,deny,auditlog\"" + ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "ctl:auditlogparts : +E-E+E", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "www.modsecurity.org", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1= test ¶m2=test2", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "plain\/text\n\r" + }, + "body": [ + "test" + ] + }, + "expected": { + "audit_log": "", + "debug_log": "Request was relevant to be saved. Parts: 34", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts A", + "SecAuditLogStorageDir /tmp/test", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0600", + "SecAuditLogType Parallel", + "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"", + "SecRule ARGS \"@contains test\" \"id:1,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:2,t:trim,ctl:auditlogparts=-E\"", + "SecRule ARGS \"@contains test\" \"id:3,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:4,t:trim,deny,auditlog\"" + ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "ctl:auditlogparts : +E-E+E+H", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "www.modsecurity.org", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1= test ¶m2=test2", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "plain\/text\n\r" + }, + "body": [ + "test" + ] + }, + "expected": { + "audit_log": "", + "debug_log": "Request was relevant to be saved. Parts: 290", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts A", + "SecAuditLogStorageDir /tmp/test", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0600", + "SecAuditLogType Parallel", + "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"", + "SecRule ARGS \"@contains test\" \"id:1,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:2,t:trim,ctl:auditlogparts=-E\"", + "SecRule ARGS \"@contains test\" \"id:3,t:trim,ctl:auditlogparts=+E\"", + "SecRule ARGS \"@contains test\" \"id:4,t:trim,ctl:auditlogparts=+H\"", + "SecRule ARGS \"@contains test\" \"id:5,t:trim,deny,auditlog\"" + ] + } +] diff --git a/test/test-cases/regression/auditlog.json b/test/test-cases/regression/auditlog.json index 33b6110111..e872bbaf7a 100644 --- a/test/test-cases/regression/auditlog.json +++ b/test/test-cases/regression/auditlog.json @@ -3,7 +3,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "auditlog : basic parser test - Parallel", + "title": "auditlog : basic parser test - Parallel 1", "client": { "ip": "200.249.12.31", "port": 2313 @@ -40,7 +40,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", + "debug_log": "Saving this request as part of the audit logs", "error_log": "", "http_code": 403 }, @@ -60,7 +60,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "auditlog : basic parser test - Serial", + "title": "auditlog : basic parser test - Serial 1", "client": { "ip": "200.249.12.31", "port": 2313 @@ -96,8 +96,8 @@ ] }, "expected": { - "audit_log": "", - "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", + "audit_log": "Access denied with code 403", + "debug_log": "", "error_log": "", "http_code": 403 }, @@ -118,7 +118,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "auditlog : basic parser test - Parallel", + "title": "auditlog : basic parser test - Parallel 2", "client": { "ip": "200.249.12.31", "port": 2313 @@ -154,8 +154,8 @@ ] }, "expected": { - "audit_log": "", - "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", + "audit_log": "www.modsecurity.org 200.249.12.31", + "debug_log": "Saving this request as part of the audit logs", "error_log": "", "http_code": 403 }, @@ -220,5 +220,55 @@ "SecAuditLogType Serial", "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"" ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "auditlog : messages verification - nolog,noauditlog", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "www.modsecurity.org", + "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", + "Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Encoding": "gzip,deflate", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Keep-Alive": "300", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + }, + "uri": "\/test.pl?param1=test¶m2=test2", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "expected": { + "audit_log": "1556", + "error_log": "", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecDefaultAction \"phase:1,nolog,auditlog,status:403,pass\"", + "SecRule ARGS \"@contains test\" \"id:1555,phase:1,log,noauditlog\"", + "SecRule ARGS \"@contains test\" \"id:1556,phase:1,deny,auditlog\"", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts ABCFHZ", + "SecAuditLog /tmp/test/modsec_audit_auditlog_1.log", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0666", + "SecAuditLogType Serial", + "SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"" + ] } ] diff --git a/test/test-cases/regression/collection-regular_expression_selection.json b/test/test-cases/regression/collection-regular_expression_selection.json index cde06ac767..ec53d0c90b 100644 --- a/test/test-cases/regression/collection-regular_expression_selection.json +++ b/test/test-cases/regression/collection-regular_expression_selection.json @@ -48,12 +48,12 @@ }, "expected":{ "audit_log":"", - "debug_log":"T \\(0\\) t:lowercase: \"test2\"", + "debug_log":"T \\(0\\) t:lowerCase: \"test2\"", "error_log":"" }, "rules":[ "SecRuleEngine On", - "SecRule ARGS:/^id_/ \"@contains nops\" \"id:1,t:lowercase,block,status:404\"" + "SecRule ARGS:/^id_/ \"@contains nops\" \"id:1,t:lowerCase,block,status:404\"" ] }, { diff --git a/test/test-cases/regression/config-include-bad.json b/test/test-cases/regression/config-include-bad.json index 76797552d7..ed8b0156e0 100644 --- a/test/test-cases/regression/config-include-bad.json +++ b/test/test-cases/regression/config-include-bad.json @@ -43,7 +43,7 @@ "version_min":300000, "title":"Include - duplicate id", "expected":{ - "parser_error": "Rule id: 40 is duplicated" + "parser_error": "There are multiple rules defined with same id. The ID 40 is defined at" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/config-secdefaultaction.json b/test/test-cases/regression/config-secdefaultaction.json index bb3d7d8104..2bf6bbdab5 100644 --- a/test/test-cases/regression/config-secdefaultaction.json +++ b/test/test-cases/regression/config-secdefaultaction.json @@ -48,14 +48,14 @@ }, "expected":{ "audit_log":"", - "debug_log":"lowercase: \"300\"", + "debug_log":"lowerCase: \"300\"", "error_log":"" }, "rules":[ "SecRuleEngine On", - "SecDefaultAction \"phase:2,t:lowercase,pass\"", + "SecDefaultAction \"phase:2,t:lowerCase,pass\"", "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"phase:2,id:1,msg:'This is a test, %{REQUEST_HEADERS:Accept}%'\"", - "SecRule TX \"@contains to_test\" \"id:2,t:lowercase,t:none\"" + "SecRule TX \"@contains to_test\" \"id:2,t:lowerCase,t:none\"" ] }, { @@ -123,7 +123,7 @@ "version_max":0, "title":"Testing action :: SecDefaultAction: t:none", "expected":{ - "parser_error":"The transformation none is not suitable to be part of the SecDefaultActions" + "parser_error":"The action 't:none' is not suitable to be part of the SecDefaultActions" }, "rules":[ "SecRuleEngine On", @@ -272,11 +272,18 @@ }, "expected":{ "audit_log":"", - "debug_log":"Request was relevant to be saved.", + "debug_log":"Saving this request as part of the audit logs", "http_code": 302 }, "rules":[ "SecRuleEngine On", + "SecAuditEngine RelevantOnly", + "SecAuditLogParts ABCFHZ", + "SecAuditLog /tmp/test/modsec_audit_auditlog_1.log", + "SecAuditLogDirMode 0766", + "SecAuditLogFileMode 0666", + "SecAuditLogType Serial", + "SecAuditLogRelevantStatus \"^(?:3|4(?!04))\"", "SecDefaultAction \"phase:2,log,auditlog,status:302,redirect:'http://www.google.com'\"", "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"phase:2,id:1,block\"", "SecRule TX \"@contains to_test\" \"id:2,t:lowercase,t:none,block\"" diff --git a/test/test-cases/regression/config-update-action-by-id.json b/test/test-cases/regression/config-update-action-by-id.json index 4e1a3fc24e..6e343be5fb 100644 --- a/test/test-cases/regression/config-update-action-by-id.json +++ b/test/test-cases/regression/config-update-action-by-id.json @@ -122,7 +122,7 @@ }, "expected":{ "http_code": 200, - "debug_log": "Running action: log" + "debug_log": "Rule returned 1" }, "rules":[ "SecRuleEngine On", @@ -167,7 +167,7 @@ }, "expected":{ "http_code": 200, - "debug_log": "Running action: log" + "debug_log": "Rule returned 1" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/issue-1528.json b/test/test-cases/regression/issue-1528.json index f2257055c2..74f578eec7 100644 --- a/test/test-cases/regression/issue-1528.json +++ b/test/test-cases/regression/issue-1528.json @@ -27,12 +27,13 @@ }, "expected": { "debug_log": "Rule returned 1", - "error_log": "Matched \"Operator `Rx' with parameter `\\^attack\\$'" + "error_log": "Matched \"Operator `Rx' with parameter `\\^attack\\$'", + "http_code": 403 }, "rules": [ "SecRuleEngine On", - "SecAction \"id:1, nolog, setvar:tx.bad_value=attack\"", - "SecRule ARGS:param \"@rx ^%{tx.bad_value}$\" \"id:2,block\"" + "SecAction \"id:1, setvar:tx.bad_value=attack\"", + "SecRule ARGS:param \"@rx ^%{tx.bad_value}$\" \"id:2,log,deny\"" ] } ] diff --git a/test/test-cases/regression/issue-1844.json b/test/test-cases/regression/issue-1844.json index 6ccb1f5e8a..1d39421850 100644 --- a/test/test-cases/regression/issue-1844.json +++ b/test/test-cases/regression/issue-1844.json @@ -37,10 +37,12 @@ ] }, "expected":{ - "error_log":"line \"29\"" + "error_log":"line \"29\"", + "http_code": 403 }, "rules":[ "SecRuleEngine On", + "SecDefaultAction \"phase:request,deny\"", "SecRule WEBAPPID \"@contains test1\" \"id:1,phase:3,pass,t:trim\"", "Include test-cases/data/big-file.conf" ] @@ -83,10 +85,12 @@ ] }, "expected":{ - "error_log":"line \"55\"" + "error_log":"line \"55\"", + "http_code": 403 }, "rules":[ "SecRuleEngine On", + "SecDefaultAction \"phase:2,deny\"", "SecRule WEBAPPID \"@contains test2\" \"id:1,phase:3,pass,t:trim\"", "Include test-cases/data/big-file.conf" ] @@ -129,10 +133,12 @@ ] }, "expected":{ - "error_log":"line \"84\"" + "error_log":"line \"84\"", + "http_code": 403 }, "rules":[ "SecRuleEngine On", + "SecDefaultAction \"phase:request,deny\"", "SecRule WEBAPPID \"@contains test3\" \"id:1,phase:3,pass,t:trim\"", "Include test-cases/data/big-file.conf" ] @@ -175,11 +181,13 @@ ] }, "expected":{ - "error_log":"line \"116\"" + "error_log":"line \"116\"", + "http_code":403 }, "rules":[ "SecRuleEngine On", - "SecRule WEBAPPID \"@contains test3\" \"id:1,phase:3,pass,t:trim\"", + "SecDefaultAction \"phase:request,deny\"", + "SecRule WEBAPPID \"@contains test3\" \"id:1,phase:3,deny,t:trim\"", "Include test-cases/data/big-file.conf" ] }, @@ -221,10 +229,12 @@ ] }, "expected":{ - "error_log":"line \"174\"" + "error_log":"line \"174\"", + "http_code":403 }, "rules":[ "SecRuleEngine On", + "SecDefaultAction \"phase:request,deny\"", "SecRule WEBAPPID \"@contains test3\" \"id:1,phase:3,pass,t:trim\"", "Include test-cases/data/big-file.conf" ] @@ -267,10 +277,12 @@ ] }, "expected":{ - "error_log":"line \"174\"" + "error_log":"line \"174\"", + "http_code":403 }, "rules":[ "SecRuleEngine On", + "SecDefaultAction \"phase:request,deny\"", "SecRule WEBAPPID \"@contains test3\" \"id:1,phase:3,pass,t:trim\"", "Include test-cases/data/not-so-big-file.conf" ] diff --git a/test/test-cases/regression/misc-variable-under-quotes.json b/test/test-cases/regression/misc-variable-under-quotes.json index 5310f61e8c..c82c96e1a5 100644 --- a/test/test-cases/regression/misc-variable-under-quotes.json +++ b/test/test-cases/regression/misc-variable-under-quotes.json @@ -31,10 +31,10 @@ ] }, "expected":{ - "debug_log":"t:lowercase:" + "debug_log":"t:lowerCase:" }, "rules":[ - "SecRule \"REQUEST_LINE\" \"@contains index.php/admin/cms/wysiwyg/directive/\" \"id:1,t:lowercase,ctl:auditLogParts=+E\"" + "SecRule \"REQUEST_LINE\" \"@contains index.php/admin/cms/wysiwyg/directive/\" \"id:1,t:lowerCase,ctl:auditLogParts=+E\"" ] }, { @@ -69,10 +69,10 @@ ] }, "expected":{ - "debug_log":"t:lowercase:" + "debug_log":"t:lowerCase:" }, "rules":[ - "SecRule \"REQUEST_LINE\" \"index.php/admin/cms/wysiwyg/directive/\" \"id:1,t:lowercase,ctl:auditLogParts=+E\"" + "SecRule \"REQUEST_LINE\" \"index.php/admin/cms/wysiwyg/directive/\" \"id:1,t:lowerCase,ctl:auditLogParts=+E\"" ] } ] diff --git a/test/test-cases/regression/offset-variable.json b/test/test-cases/regression/offset-variable.json index 99c9e19a71..20d87aa2a1 100644 --- a/test/test-cases/regression/offset-variable.json +++ b/test/test-cases/regression/offset-variable.json @@ -22,10 +22,12 @@ ] }, "expected":{ - "error_log":"o0,3v23,6t:trim" + "error_log":"o0,3v23,6t:trim", + "http_code": 403 }, "rules":[ - "SecRule ARGS \"@rx val\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS \"@rx val\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny,log\"" ] }, { @@ -51,10 +53,12 @@ ] }, "expected":{ - "error_log":"o3,3v37,6t:trim" + "error_log":"o3,3v37,6t:trim", + "http_code":403 }, "rules":[ - "SecRule ARGS_GET \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_GET \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -83,11 +87,13 @@ ] }, "expected":{ - "error_log":"o3,3v142,6t:trim" + "error_log":"o3,3v142,6t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_POST \"@rx ue1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_POST \"@rx ue1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -116,11 +122,13 @@ ] }, "expected":{ - "error_log":"o3,3v156,6t:trim" + "error_log":"o3,3v156,6t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_POST \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_POST \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -149,11 +157,13 @@ ] }, "expected":{ - "error_log":"o0,6v17,6t:trim" + "error_log":"o0,6v17,6t:trim", + "http_code":403 }, "rules":[ + "SecRuleEngine On", "SecRequestBodyAccess On", - "SecRule ARGS_GET_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRule ARGS_GET_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -182,11 +192,13 @@ ] }, "expected":{ - "error_log":"o0,6v31,6t:trim" + "error_log":"o0,6v31,6t:trim", + "http_code":403 }, "rules":[ + "SecRuleEngine On", "SecRequestBodyAccess On", - "SecRule ARGS_GET_NAMES \"@rx param2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRule ARGS_GET_NAMES \"@rx param2\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -219,7 +231,7 @@ }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_GET_NAMES \"@rx am1 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRule ARGS_GET_NAMES \"@rx am1 par\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -252,7 +264,7 @@ }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_GET_NAMES \"@rx am1 param2 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRule ARGS_GET_NAMES \"@rx am1 param2 par\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -281,11 +293,13 @@ ] }, "expected":{ - "error_log": "0,6v149,6t:trim" + "error_log": "0,6v149,6t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_POST_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_POST_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -314,11 +328,13 @@ ] }, "expected":{ - "error_log":"o0,6v17,6t:trim" + "error_log":"o0,6v17,6t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -344,11 +360,13 @@ ] }, "expected":{ - "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim" + "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -374,11 +392,13 @@ ] }, "expected":{ - "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim" + "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -405,11 +425,13 @@ ] }, "expected":{ - "error_log":"o23,6v0,63t:trim" + "error_log":"o23,6v0,63t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_LINE \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_LINE \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -437,11 +459,13 @@ ] }, "expected":{ - "error_log":"o0,3v0,3t:trim" + "error_log":"o0,3v0,3t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_METHOD \"GET\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_METHOD \"GET\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -469,11 +493,13 @@ ] }, "expected":{ - "error_log":"o5,3v58,8t:trim" + "error_log":"o5,3v58,8t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_PROTOCOL \"1.1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_PROTOCOL \"1.1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -501,11 +527,13 @@ ] }, "expected":{ - "error_log":"o1,5v4,11t:trim" + "error_log":"o1,5v4,11t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule PATH_INFO \"index\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule PATH_INFO \"index\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -533,11 +561,13 @@ ] }, "expected":{ - "error_log":"o7,6v16,41t:trim" + "error_log":"o7,6v16,41t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule QUERY_STRING \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule QUERY_STRING \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -565,11 +595,13 @@ ] }, "expected":{ - "error_log":"o6,4v5,10t:trim" + "error_log":"o6,4v5,10t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_BASENAME \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_BASENAME \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -597,11 +629,13 @@ ] }, "expected":{ - "error_log":"o7,4v4,59t:trim" + "error_log":"o7,4v4,59t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_URI \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_URI \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -629,11 +663,14 @@ ] }, "expected":{ - "error_log":"o7,4v4,59t:trim" + "error_log":"o7,4v4,59t:trim", + "http_code": 403 + }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_URI_RAW \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_URI_RAW \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, @@ -661,11 +698,13 @@ ] }, "expected":{ - "error_log":"o0,9v89,9t:trim" + "error_log":"o0,9v89,9t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_HEADERS \"localhost\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_HEADERS \"localhost\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, @@ -693,11 +732,13 @@ ] }, "expected":{ - "error_log":"o14,3v163,33t:trim" + "error_log":"o14,3v163,33t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_HEADERS \"www\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_HEADERS \"www\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -724,11 +765,13 @@ ] }, "expected":{ - "error_log":"o0,5v162,5t:trim" + "error_log":"o0,5v162,5t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -755,11 +798,13 @@ ] }, "expected":{ - "error_log":"o0,5v79,5t:trim" + "error_log":"o0,5v79,5t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + "SecRuleEngine On", + "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops',deny\"" ] }, { @@ -786,11 +831,13 @@ ] }, "expected":{ - "error_log":"o0,4v64,13t:lowercase" + "error_log":"o0,4v64,13t:lowerCase", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_HEADERS_NAMES \"auth\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_HEADERS_NAMES \"auth\" \"id:1,phase:2,pass,t:lowerCase,msg:'ops',deny\"" ] }, { @@ -818,11 +865,13 @@ ] }, "expected":{ - "error_log":"o1,2v216,3t:lowercase" + "error_log":"o1,2v216,3t:lowerCase", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_COOKIES \"es\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_COOKIES \"es\" \"id:1,phase:2,pass,t:lowerCase,msg:'ops',deny\"" ] }, { @@ -850,11 +899,13 @@ ] }, "expected":{ - "error_log":"o0,1v223,1t:lowercase" + "error_log":"o0,1v223,1t:lowerCase", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_COOKIES \"z\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_COOKIES \"z\" \"id:1,phase:2,pass,t:lowerCase,msg:'ops',deny\"" ] }, { @@ -882,11 +933,13 @@ ] }, "expected":{ - "error_log":"o0,1v228,1t:lowercase" + "error_log":"o0,1v228,1t:lowerCase", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_COOKIES \"b\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_COOKIES \"b\" \"id:1,phase:2,pass,t:lowerCase,msg:'ops',deny\"" ] }, { @@ -914,11 +967,13 @@ ] }, "expected":{ - "error_log":"o0,1v226,1" + "error_log":"o0,1v226,1", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_COOKIES_NAMES \"t\" \"id:1,phase:2,pass,msg:'ops'\"" + "SecRuleEngine On", + "SecRule REQUEST_COOKIES_NAMES \"t\" \"id:1,phase:2,pass,msg:'ops',deny\"" ] }, { @@ -956,11 +1011,12 @@ ] }, "expected":{ - "error_log":"o0,7v198,30t:trim" + "error_log":"o0,7v198,30t:trim", + "http_code":403 }, "rules":[ "SecRuleEngine On", - "SecRule REMOTE_USER \"Aladdin\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule REMOTE_USER \"Aladdin\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1005,11 +1061,13 @@ ] }, "expected":{ - "error_log":"o45,30v193,516t:trim" + "error_log":"o45,30v193,516t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1054,11 +1112,13 @@ ] }, "expected":{ - "error_log":"o45,30v193,516t:trim" + "error_log":"o45,30v193,516t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1103,11 +1163,13 @@ ] }, "expected":{ - "error_log":"v193,516t:trim" + "error_log":"v193,516t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_BODY_LENGTH \"@gt 5\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_BODY_LENGTH \"@gt 5\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1152,11 +1214,13 @@ ] }, "expected":{ - "error_log":"o6,5v5,11t:trim" + "error_log":"o6,5v5,11t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_FILENAME \"/file\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"/file\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1201,11 +1265,13 @@ ] }, "expected":{ - "error_log":"o6,8v5,23t:trim" + "error_log":"o6,8v5,23t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1250,11 +1316,13 @@ ] }, "expected":{ - "error_log":"o6,8v5,23t:trim" + "error_log":"o6,8v5,23t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1299,11 +1367,13 @@ ] }, "expected":{ - "error_log":"o0,4v306,4t:trim" + "error_log":"o0,4v306,4t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS \"test\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule ARGS \"test\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1352,11 +1422,13 @@ ] }, "expected":{ - "error_log":"o0,5v402,5t:trim" + "error_log":"o0,5v402,5t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule ARGS \"test2\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule ARGS \"test2\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1405,11 +1477,13 @@ ] }, "expected":{ - "error_log":"o0,16v680,20t:trim" + "error_log":"o0,16v680,20t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES \"small_text_file2\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES \"small_text_file2\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1458,11 +1532,13 @@ ] }, "expected":{ - "error_log":"o0,16v512,20t:trim" + "error_log":"o0,16v512,20t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES \"small_text_file1\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES \"small_text_file1\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1511,11 +1587,13 @@ ] }, "expected":{ - "error_log":"o0,8o0,8v491,8t:trimo0,16o0,16v709,16t:trim" + "error_log":"o0,8o0,8v491,8t:trimo0,16o0,16v709,16t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES_NAMES \"(fiasdfasdfledata|filedata)\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES_NAMES \"(fiasdfasdfledata|filedata)\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1564,11 +1642,13 @@ ] }, "expected":{ - "error_log":"v560,32t:trim" + "error_log":"v560,32t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES_SIZES:filedata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES_SIZES:filedata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1617,11 +1697,13 @@ ] }, "expected":{ - "error_log":"v754,38t:trim" + "error_log":"v754,38t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES_SIZES:fiasdfasdfledata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES_SIZES:fiasdfasdfledata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1670,11 +1752,13 @@ ] }, "expected":{ - "error_log":"v560,32v754,38t:trim" + "error_log":"v560,32v754,38t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", - "SecRule FILES_COMBINED_SIZE \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRuleEngine On", + "SecRule FILES_COMBINED_SIZE \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1723,13 +1807,15 @@ ] }, "expected":{ - "error_log":"o8,7v754,38t:trim" + "error_log":"o8,7v754,38t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", "SecUploadKeepFiles On", + "SecRuleEngine On", "SecUploadDir /tmp", - "SecRule FILES_TMP_CONTENT \"another\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule FILES_TMP_CONTENT \"another\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1778,13 +1864,15 @@ ] }, "expected":{ - "error_log":"o15,5v560,32t:trim" + "error_log":"o15,5v560,32t:trim", + "http_code": 403 }, "rules":[ "SecRequestBodyAccess On", "SecUploadKeepFiles On", + "SecRuleEngine On", "SecUploadDir /tmp", - "SecRule FILES_TMP_CONTENT:small_text_file1.txt \"small\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule FILES_TMP_CONTENT:small_text_file1.txt \"small\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1833,13 +1921,15 @@ ] }, "expected":{ - "error_log":"o6,4v5,23t:trim" + "error_log":"o6,4v5,23t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", "SecUploadKeepFiles On", + "SecRuleEngine On", "SecUploadDir /tmp", - "SecRule PATH_INFO \"/f i\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule PATH_INFO \"/f i\" \"id:1,phase:3,t:trim,msg:'s',deny\"" ] }, { @@ -1888,13 +1978,15 @@ ] }, "expected":{ - "error_log":"o0,20v680,20t:trim" + "error_log":"o0,20v680,20t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", "SecUploadKeepFiles On", + "SecRuleEngine On", "SecUploadDir /tmp", - "SecRule MULTIPART_FILENAME \"small_text_file2.txt\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule MULTIPART_FILENAME \"small_text_file2.txt\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] }, { @@ -1943,13 +2035,15 @@ ] }, "expected":{ - "error_log":"o0,16v709,16t:trim" + "error_log":"o0,16v709,16t:trim", + "http_code":403 }, "rules":[ "SecRequestBodyAccess On", "SecUploadKeepFiles On", + "SecRuleEngine On", "SecUploadDir /tmp", - "SecRule MULTIPART_NAME \"fiasdfasdfledata\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + "SecRule MULTIPART_NAME \"fiasdfasdfledata\" \"id:1,phase:3,pass,t:trim,msg:'s',deny\"" ] } ] diff --git a/test/test-cases/regression/operator-rx.json b/test/test-cases/regression/operator-rx.json index d6b9839fe5..e077157341 100644 --- a/test/test-cases/regression/operator-rx.json +++ b/test/test-cases/regression/operator-rx.json @@ -79,11 +79,12 @@ }, "expected":{ "debug_log":"Executing operator \"Rx\" with param \"\\^0\\$\"", - "error_log":"Matched \"Operator `Rx' with parameter `\\^0\\$'" + "error_log":"Matched \"Operator `Rx' with parameter `\\^0\\$'", + "http_code": 403 }, "rules":[ "SecRuleEngine On", - "SecRule REQUEST_HEADERS:Content-Length \"!^0$\" \"id:1,phase:2,pass,t:trim,block\"" + "SecRule REQUEST_HEADERS:Content-Length \"!^0$\" \"id:1,phase:2,pass,t:trim,deny\"" ] } ] diff --git a/test/test-cases/regression/rule-920274.json b/test/test-cases/regression/rule-920274.json index 4eb0fd6fa1..e9349bd11a 100644 --- a/test/test-cases/regression/rule-920274.json +++ b/test/test-cases/regression/rule-920274.json @@ -38,6 +38,47 @@ "SecDefaultAction \"phase:2,deny,block,status:400,log\"", "SecRule REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent|!REQUEST_HEADERS:Referer|!REQUEST_HEADERS:Cookie \"@validateByteRange 32,34,38,42-59,61,65-90,95,97-122\" \"id:920274,phase:2,block,t:none,t:urlDecodeUni,msg:'Invalid character in request headers (outside of very strict set)',logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-protocol',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',tag:'paranoia-level/4',ver:'OWASP_CRS/3.1.0',severity:'CRITICAL',setvar:'tx.msg=%{rule.msg}',setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}',setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{MATCHED_VAR_NAME}=%{MATCHED_VAR}'\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Byte ranges :: OWASP CRS id:920274 - II", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent": "ThisIsATest%60 II", + "User-Agent2": "ThisIsATest%60 II" + }, + "uri":"/", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "http_code":400, + "debug_log":"Invalid character in request headers" + }, + "rules":[ + "SecRuleEngine On", + "SecDefaultAction \"phase:2,deny,block,status:400,log\"", + "SecRule REQUEST_HEADERS|!REQUEST_HEADERS:'/User-Agent.*2/'|!REQUEST_HEADERS:Referer|!REQUEST_HEADERS:Cookie \"@validateByteRange 32,34,38,42-59,61,65-90,95,97-122\" \"id:920274,phase:2,block,t:none,t:urlDecodeUni,msg:'Invalid character in request headers (outside of very strict set)',logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-protocol',tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',tag:'paranoia-level/4',ver:'OWASP_CRS/3.1.0',severity:'CRITICAL',setvar:'tx.msg=%{rule.msg}',setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}',setvar:'tx.%{rule.id}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{MATCHED_VAR_NAME}=%{MATCHED_VAR}'\"" + ] } ] diff --git a/test/test-cases/regression/tempCodeRunnerFile.json b/test/test-cases/regression/tempCodeRunnerFile.json new file mode 100644 index 0000000000..7437a22fda --- /dev/null +++ b/test/test-cases/regression/tempCodeRunnerFile.json @@ -0,0 +1,38 @@ + + "enabled":1, + "version_min":300000, + "title":"Testing allow action (1/3)", + "expected":{ + "debug_log": "Skipped rule id 'action-allow.json:3' as request trough the utilization of an `allow' action", + "http_code": 200 + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "User-Agent":"My sweet little browser", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120" + }, + "uri":"/?key=value&key=other_value", + "method":"GET" + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRuleEngine On", + "SecAction \"phase:1,allow,msg:'ALLOWED',id:500065\"", + "SecAction \"phase:1,deny,msg:'DENIED',id:500066\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing allow action (2/3)", + "expected":{ \ No newline at end of file diff --git a/test/test-cases/regression/transformations.json b/test/test-cases/regression/transformations.json index dcb328f16c..d49ae43427 100644 --- a/test/test-cases/regression/transformations.json +++ b/test/test-cases/regression/transformations.json @@ -107,12 +107,12 @@ }, "expected": { "audit_log": "", - "debug_log": "lowercase: \"test", + "debug_log": "lowerCase: \"test", "error_log": "" }, "rules": [ "SecRuleEngine On", - "SecRule ARGS \"@contains test \" \"id:1,pass,t:trim,t:lowercase\"" + "SecRule ARGS \"@contains test \" \"id:1,pass,t:trim,t:lowerCase\"" ] } ] diff --git a/test/test-suite.sh b/test/test-suite.sh index e242c7baf8..ce03c244e1 100755 --- a/test/test-suite.sh +++ b/test/test-suite.sh @@ -30,10 +30,10 @@ else RET=$? if [ $RET -eq 127 ] then - echo ":test-result: SKIP: json is not enabled. (unit/$RET) ../$FILE" + echo ":test-result: SKIP: json is not enabled. (unit/$RET) ../$FILE:$i" elif [ $RET -ne 0 ] then - echo ":test-result: FAIL possible segfault: (unit/$RET) ../$FILE" + echo ":test-result: FAIL possible segfault: (unit/$RET) ../$FILE:$i" fi fi diff --git a/test/unit/unit.cc b/test/unit/unit.cc index f610a21ebf..40b47dfb30 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -90,8 +90,14 @@ void perform_unit_test(ModSecurityTest *test, UnitTest *t, } delete op; } else if (t->type == "tfn") { + modsecurity::ModSecString in; + modsecurity::ModSecString out; + std::string ret; + in.assign(t->input.c_str(), t->input.size()); Transformation *tfn = Transformation::instantiate("t:" + t->name); - std::string ret = tfn->evaluate(t->input, NULL); + tfn->execute(NULL, in, out); + ret.assign(out.c_str(), out.size()); + t->obtained = 1; t->obtainedOutput = ret; if (ret != t->output) { diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index 91d78d841d..fb3108d12b 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -91,6 +91,7 @@ int main(int argc, char **argv) { if (err.empty() == false) { std::cerr << " " << err << std::endl; } + rules->dump(); next: args++; }