diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index 1f143e31..2b458768 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -39,6 +39,7 @@ namespace actions { class Action { public: + explicit Action(const std::string& _action) : m_isNone(false), temporaryAction(false), @@ -81,6 +82,17 @@ class Action { RuleMessage &ruleMessage) { return execute(rule, transaction); } + + /** + * This method is meant to be used by transformations — a particular + * type of action. + * + */ + virtual void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + }; + virtual bool init(std::string *error) { return true; } virtual bool isDisruptive() { return false; } diff --git a/headers/modsecurity/rule_message.h b/headers/modsecurity/rule_message.h index 61eeecea..ee778b6b 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: @@ -112,108 +113,22 @@ class RuleMessage { static std::string _details(const RuleMessage *rm); static std::string _errorLogTail(const RuleMessage *rm); - RuleWithActions *getRule() const { - return m_rule; - } - - void setRule(RuleWithActions *rule) { - m_rule = rule; - } - - bool isSettle() const { - return m_rule != nullptr; - } - - int getRuleId() const { - if (m_rule) { - return m_rule->getId(); - } - return -1; - } - - int getPhase() const { - if (m_rule) { - return m_rule->getPhase(); - } - return 0; - } - - std::string getFileName() const { - if (m_rule) { - return *m_rule->getFileName().get(); - } - return ""; - } - - int getLineNumber() const { - if (m_rule) { - return m_rule->getLineNumber(); - } - return 0; - } - - std::string getRev() const { - if (m_rule) { - return m_rule->getRevision(); - } - return ""; - } - - std::string getVer() const { - if (m_rule) { - return m_rule->getVersion(); - } - return ""; - } - - int getMaturity() const { - if (m_rule) { - return m_rule->getMaturity(); - } - return 0; - } - - int getAccuracy() const { - if (m_rule) { - return m_rule->getAccuracy(); - } - return 0; - } - - std::string getClientIpAddress() const { - if (m_transaction) { - return *m_transaction->m_clientIpAddress.get(); - } - return ""; - } - - std::string getServerIpAddress() const { - if (m_transaction) { - return *m_transaction->m_serverIpAddress.get(); - } - return ""; - } - - std::string getRequestId() const { - if (m_transaction) { - return *m_transaction->m_id.get(); - } - return ""; - } - - std::string getUri() const { - if (m_transaction) { - return *m_transaction->m_uri_no_query_string_decoded.get(); - } - return ""; - } - - bool isDisruptive() const { - if (m_rule) { - return m_rule->hasDisruptiveAction(); - } - return 0; - } + RuleWithActions *getRule() const; + void setRule(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; int m_severity; std::list m_tags; diff --git a/headers/modsecurity/rule_with_actions.h b/headers/modsecurity/rule_with_actions.h index 50435847..d71ffeea 100644 --- a/headers/modsecurity/rule_with_actions.h +++ b/headers/modsecurity/rule_with_actions.h @@ -49,9 +49,6 @@ class Transformation; } } -using TransformationResult = std::pair, - std::shared_ptr>; -using TransformationResults = std::list; using Transformation = actions::transformations::Transformation; using Transformations = std::vector >; using TransformationsPtr = std::vector; @@ -67,6 +64,43 @@ using MatchActionsPtr = std::vector; using XmlNSs = std::vector >; using XmlNSsPtr = std::vector; +using ModSecStackString = std::basic_string, std::allocator >; + +class TransformationResult { + public: + TransformationResult( + ModSecStackString *after, + std::string *transformation) + : m_after(*after), + m_transformation(transformation) { }; + + explicit TransformationResult( + ModSecStackString *after) + : m_after(*after), + m_transformation(nullptr) { }; + + TransformationResult(const TransformationResult &t2) + : m_after(t2.m_after), + m_transformation(t2.m_transformation) { }; + + + ModSecStackString *getAfter() { + return &m_after; + } + + + std::string *getTransformationName() { + return m_transformation; + } + + + private: + ModSecStackString m_after; + std::string *m_transformation; +}; + +using TransformationsResults = std::list; + class RuleWithActions : public Rule { public: @@ -183,18 +217,21 @@ class RuleWithActions : public Rule { bool context); + static void executeTransformation( + Transaction *transaction, + TransformationsResults *ret, + Transformation *transformation); + + static void executeTransformation( + Transaction *transaction, + ModSecStackString in, + TransformationsResults *ret, + Transformation *transformation); + void executeTransformations( Transaction *transaction, const std::string &value, - TransformationResults &ret); - - inline void executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path) const; - + TransformationsResults &results); void addAction(actions::Action *a); void addTransformation(std::shared_ptr t) { diff --git a/headers/modsecurity/rule_with_operator.h b/headers/modsecurity/rule_with_operator.h index f476ec1e..71da6ddf 100644 --- a/headers/modsecurity/rule_with_operator.h +++ b/headers/modsecurity/rule_with_operator.h @@ -35,6 +35,7 @@ namespace modsecurity { +using TransformationsResults = std::list; class RuleWithOperator : public RuleWithActions { public: diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index e062439e..08d72f11 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -32,11 +32,12 @@ namespace actions { namespace transformations { -std::string Base64Decode::execute(const std::string &value, - Transaction *transaction) { +void Base64Decode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 4354a5f2..55e172a4 100644 --- a/src/actions/transformations/base64_decode.h +++ b/src/actions/transformations/base64_decode.h @@ -30,10 +30,12 @@ namespace transformations { class Base64Decode : public Transformation { public: - explicit Base64Decode(const std::string &action) : Transformation(action) { } + explicit Base64Decode(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/base64_decode_ext.cc b/src/actions/transformations/base64_decode_ext.cc index a03ab634..07a77ad0 100644 --- a/src/actions/transformations/base64_decode_ext.cc +++ b/src/actions/transformations/base64_decode_ext.cc @@ -32,11 +32,11 @@ namespace actions { namespace transformations { -std::string Base64DecodeExt::execute(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode_forgiven(value); - - return ret; +void Base64DecodeExt::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 30dcce3d..ed9edf78 100644 --- a/src/actions/transformations/base64_decode_ext.h +++ b/src/actions/transformations/base64_decode_ext.h @@ -30,10 +30,12 @@ namespace transformations { class Base64DecodeExt : public Transformation { public: - explicit Base64DecodeExt(const std::string &action) : Transformation(action) { } + explicit Base64DecodeExt(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/base64_encode.cc b/src/actions/transformations/base64_encode.cc index ed6f3860..4bc7871a 100644 --- a/src/actions/transformations/base64_encode.cc +++ b/src/actions/transformations/base64_encode.cc @@ -32,11 +32,12 @@ namespace actions { namespace transformations { -std::string Base64Encode::execute(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::encode(value); - - return ret; +void Base64Encode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 9a3e0db1..2c816d6b 100644 --- a/src/actions/transformations/base64_encode.h +++ b/src/actions/transformations/base64_encode.h @@ -30,10 +30,12 @@ namespace transformations { class Base64Encode : public Transformation { public: - explicit Base64Encode(const std::string &action) : Transformation(action) { } + explicit Base64Encode(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/cmd_line.cc b/src/actions/transformations/cmd_line.cc index 9306fab1..acb572ac 100644 --- a/src/actions/transformations/cmd_line.cc +++ b/src/actions/transformations/cmd_line.cc @@ -31,12 +31,12 @@ namespace actions { namespace transformations { -std::string CmdLine::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void CmdLine::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { int space = 0; - for (auto& a : value) { + for (auto& a : in) { switch (a) { /* remove some characters */ case '"': @@ -53,7 +53,7 @@ std::string CmdLine::execute(const std::string &value, case '\r': case '\n': if (space == 0) { - ret.append(" "); + out.append(" "); space++; } break; @@ -62,22 +62,20 @@ std::string CmdLine::execute(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 f56b488a..a853ad83 100644 --- a/src/actions/transformations/cmd_line.h +++ b/src/actions/transformations/cmd_line.h @@ -30,11 +30,12 @@ namespace transformations { class CmdLine : public Transformation { public: - explicit CmdLine(const std::string &action) + explicit CmdLine(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 1e4926bc..a11c6ea4 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -30,37 +30,32 @@ namespace modsecurity { namespace actions { namespace transformations { -CompressWhitespace::CompressWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string CompressWhitespace::execute(const std::string &value, - Transaction *transaction) { - - std::string a; +void CompressWhitespace::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 e11efe47..11d7b120 100644 --- a/src/actions/transformations/compress_whitespace.h +++ b/src/actions/transformations/compress_whitespace.h @@ -30,10 +30,12 @@ namespace transformations { class CompressWhitespace : public Transformation { public: - explicit CompressWhitespace(const std::string &action) ; + explicit CompressWhitespace(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index fdef694d..05485d75 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -34,20 +34,19 @@ namespace actions { namespace transformations { -std::string CssDecode::execute(const std::string &value, - Transaction *transaction) { - +void CssDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; + malloc(sizeof(char) * in.size() + 1)); + memcpy(tmp, in.c_str(), in.size() + 1); + tmp[in.size()] = '\0'; CssDecode::css_decode_inplace(reinterpret_cast(tmp), - value.size()); + in.size()); - std::string ret(tmp, 0, value.size()); + out.assign(tmp, 0, in.size()); free(tmp); - return ret; } diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index 707bd131..112b3391 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -31,10 +31,12 @@ namespace transformations { class CssDecode : public Transformation { public: - explicit CssDecode(const std::string &action) + explicit CssDecode(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static int css_decode_inplace(unsigned char *input, int64_t input_len); }; diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index 322adbc0..b81f5d72 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -31,11 +31,6 @@ 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 +135,17 @@ int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, } -std::string EscapeSeqDecode::execute(const std::string &value, - Transaction *transaction) { - +void EscapeSeqDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { unsigned char *tmp = (unsigned char *) malloc(sizeof(char) - * value.size() + 1); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; + * in.size() + 1); + memcpy(tmp, in.c_str(), in.size() + 1); + tmp[in.size()] = '\0'; - int size = ansi_c_sequences_decode_inplace(tmp, value.size()); - - std::string ret(""); - ret.assign(reinterpret_cast(tmp), size); + int size = ansi_c_sequences_decode_inplace(tmp, in.size()); + out.assign(reinterpret_cast(tmp), size); free(tmp); - - return ret; } } // namespace transformations diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index 3d25955c..f8c27fe1 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -30,9 +30,13 @@ namespace transformations { class EscapeSeqDecode : public Transformation { public: - explicit EscapeSeqDecode(const std::string &action) ; - std::string execute(const std::string &exp, - Transaction *transaction) override; + explicit EscapeSeqDecode(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; + static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); }; diff --git a/src/actions/transformations/hex_decode.cc b/src/actions/transformations/hex_decode.cc index 7a00e143..13538a0e 100644 --- a/src/actions/transformations/hex_decode.cc +++ b/src/actions/transformations/hex_decode.cc @@ -32,27 +32,25 @@ namespace actions { namespace transformations { -std::string HexDecode::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void HexDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { unsigned char *input; int size = 0; 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); - size = inplace(input, value.length()); + size = inplace(input, in.length()); - ret.assign(reinterpret_cast(input), size); + out.assign(reinterpret_cast(input), size); free(input); - - return ret; } diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index 5d79c41b..3501f138 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -30,10 +30,12 @@ namespace transformations { class HexDecode : public Transformation { public: - explicit HexDecode(const std::string &action) : Transformation(action) { } + explicit HexDecode(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static int inplace(unsigned char *data, int len); }; diff --git a/src/actions/transformations/hex_encode.cc b/src/actions/transformations/hex_encode.cc index 2684c9f4..751970c5 100644 --- a/src/actions/transformations/hex_encode.cc +++ b/src/actions/transformations/hex_encode.cc @@ -31,23 +31,20 @@ namespace modsecurity { namespace actions { namespace transformations { -HexEncode::HexEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string HexEncode::execute(const std::string &value, - Transaction *transaction) { +void HexEncode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 bd07ed73..2f8414e5 100644 --- a/src/actions/transformations/hex_encode.h +++ b/src/actions/transformations/hex_encode.h @@ -30,10 +30,13 @@ namespace transformations { class HexEncode : public Transformation { public: - explicit HexEncode(const std::string &action); + explicit HexEncode(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string execute(const std::string &exp, - Transaction *transaction) override; }; } // namespace transformations diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index f184f6e7..080f0c75 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -33,26 +33,24 @@ namespace actions { namespace transformations { -std::string HtmlEntityDecode::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void HtmlEntityDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); - size_t i = inplace(input, value.length()); + size_t i = inplace(input, in.length()); - ret.assign(reinterpret_cast(input), i); + out.assign(reinterpret_cast(input), i); free(input); - - return ret; } diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 0f7d2af7..b2b39a7d 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -36,8 +36,9 @@ class HtmlEntityDecode : public Transformation { explicit HtmlEntityDecode(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static int inplace(unsigned char *input, uint64_t input_len); }; diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 2bb8852f..268e0321 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -34,26 +34,24 @@ namespace actions { namespace transformations { -std::string JsDecode::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void JsDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); - size_t i = inplace(input, value.length()); + size_t i = inplace(input, in.length()); - ret.assign(reinterpret_cast(input), i); + out.assign(reinterpret_cast(input), i); free(input); - - return ret; } diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index 652a19c0..013e4d92 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -33,8 +33,10 @@ class JsDecode : public Transformation { explicit JsDecode(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; + static int inplace(unsigned char *input, uint64_t input_len); }; diff --git a/src/actions/transformations/length.cc b/src/actions/transformations/length.cc index 1bfe6a2a..d620de31 100644 --- a/src/actions/transformations/length.cc +++ b/src/actions/transformations/length.cc @@ -30,15 +30,11 @@ namespace modsecurity { namespace actions { namespace transformations { -Length::Length(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string Length::execute(const std::string &value, - Transaction *transaction) { - - return std::to_string(value.size()); +void Length::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 e8faea95..bd643005 100644 --- a/src/actions/transformations/length.h +++ b/src/actions/transformations/length.h @@ -30,10 +30,12 @@ namespace transformations { class Length : public Transformation { public: - explicit Length(const std::string &action); + explicit Length(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 10b3d69c..fb974794 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -27,22 +27,17 @@ namespace actions { namespace transformations { -LowerCase::LowerCase(const std::string &a) - : Transformation(a) { -} - -std::string LowerCase::execute(const std::string &val, - Transaction *transaction) { +void LowerCase::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); + out.resize(in.size()); + for (std::string::size_type i=0; i < in.size(); ++i) { + out[i] = std::tolower(in[i], loc); } - - return value; } + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 2869c8ac..2f885914 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -32,9 +32,12 @@ namespace transformations { class LowerCase : public Transformation { public: - explicit LowerCase(const std::string &action); - std::string execute(const std::string &exp, - Transaction *transaction) override; + explicit LowerCase(const std::string &action) + : Transformation(action) { }; + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/md5.cc b/src/actions/transformations/md5.cc index 371f3039..3996645a 100644 --- a/src/actions/transformations/md5.cc +++ b/src/actions/transformations/md5.cc @@ -31,11 +31,12 @@ namespace actions { namespace transformations { -std::string Md5::execute(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Md5::digest(value); +void Md5::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 5241a23b..c822eecf 100644 --- a/src/actions/transformations/md5.h +++ b/src/actions/transformations/md5.h @@ -30,10 +30,12 @@ namespace transformations { class Md5 : public Transformation { public: - explicit Md5(const std::string &action) : Transformation(action) { } + explicit Md5(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/none.cc b/src/actions/transformations/none.cc index 5264b927..f093c550 100644 --- a/src/actions/transformations/none.cc +++ b/src/actions/transformations/none.cc @@ -31,10 +31,9 @@ namespace actions { namespace transformations { -std::string None::execute(const std::string &value, - Transaction *transaction) { - return value; -} +void None::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { } } // namespace transformations diff --git a/src/actions/transformations/none.h b/src/actions/transformations/none.h index 1dc29f51..e69c3b07 100644 --- a/src/actions/transformations/none.h +++ b/src/actions/transformations/none.h @@ -34,8 +34,9 @@ class None : public Transformation { : Transformation(action) { m_isNone = true; } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index dc9b58cf..16290e34 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -32,28 +32,23 @@ namespace modsecurity { namespace actions { namespace transformations { -NormalisePath::NormalisePath(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string NormalisePath::execute(const std::string &value, - Transaction *transaction) { +void NormalisePath::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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'; + malloc(sizeof(char) * in.size() + 1)); + memcpy(tmp, in.c_str(), in.size() + 1); + tmp[in.size()] = '\0'; int i = normalize_path_inplace((unsigned char *)tmp, - value.size(), 0, &changed); + in.size(), 0, &changed); std::string ret(""); - ret.assign(tmp, i); + out.assign(tmp, i); free(tmp); - - return ret; } diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index a9ee6523..a5667f13 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -30,10 +30,12 @@ namespace transformations { class NormalisePath : public Transformation { public: - explicit NormalisePath(const std::string &action); + explicit NormalisePath(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static int normalize_path_inplace(unsigned char *input, int input_len, int win, int *changed); diff --git a/src/actions/transformations/normalise_path_win.cc b/src/actions/transformations/normalise_path_win.cc index 8d56e9cf..7b0541f7 100644 --- a/src/actions/transformations/normalise_path_win.cc +++ b/src/actions/transformations/normalise_path_win.cc @@ -34,24 +34,23 @@ namespace actions { namespace transformations { -std::string NormalisePathWin::execute(const std::string &value, - Transaction *transaction) { +void NormalisePathWin::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { int changed; char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; + malloc(sizeof(char) * in.size() + 1)); + memcpy(tmp, in.c_str(), in.size() + 1); + tmp[in.size()] = '\0'; int i = NormalisePath::normalize_path_inplace( reinterpret_cast(tmp), - value.size(), 1, &changed); + in.size(), 1, &changed); std::string ret(""); - ret.assign(tmp, i); + out.assign(tmp, i); free(tmp); - - return ret; } diff --git a/src/actions/transformations/normalise_path_win.h b/src/actions/transformations/normalise_path_win.h index 507ce1bd..48be406b 100644 --- a/src/actions/transformations/normalise_path_win.h +++ b/src/actions/transformations/normalise_path_win.h @@ -33,8 +33,9 @@ class NormalisePathWin : public Transformation { explicit NormalisePathWin(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/parity_even_7bit.cc b/src/actions/transformations/parity_even_7bit.cc index bcc96c11..2e8c874f 100644 --- a/src/actions/transformations/parity_even_7bit.cc +++ b/src/actions/transformations/parity_even_7bit.cc @@ -32,28 +32,27 @@ namespace actions { namespace transformations { -std::string ParityEven7bit::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void ParityEven7bit::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { unsigned char *input; input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); + (malloc(sizeof(char) * in.length()+1)); if (input == NULL) { - return ""; + return; } - std::memcpy(input, value.c_str(), value.length()+1); + std::memcpy(input, in.c_str(), in.length()+1); - inplace(input, value.length()); + inplace(input, in.length()); - ret.assign(reinterpret_cast(input), value.length()); + out.assign(reinterpret_cast(input), in.length()); free(input); - - return ret; } + bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { uint64_t i; @@ -76,7 +75,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 a77dbaa6..ac4f7ac6 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -30,9 +30,13 @@ namespace transformations { class ParityEven7bit : public Transformation { public: - explicit ParityEven7bit(const std::string &action) : Transformation(action) { } + explicit ParityEven7bit(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string execute(const std::string &exp, Transaction *transaction) override; static bool inplace(unsigned char *input, uint64_t input_len); }; diff --git a/src/actions/transformations/parity_odd_7bit.cc b/src/actions/transformations/parity_odd_7bit.cc index df7e0dc3..ca6946fe 100644 --- a/src/actions/transformations/parity_odd_7bit.cc +++ b/src/actions/transformations/parity_odd_7bit.cc @@ -32,28 +32,27 @@ namespace actions { namespace transformations { -std::string ParityOdd7bit::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void ParityOdd7bit::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); - inplace(input, value.length()); + inplace(input, in.length()); - ret.assign(reinterpret_cast(input), value.length()); + out.assign(reinterpret_cast(input), in.length()); free(input); - - return ret; } + 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 dcf168cd..a99a488d 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -30,9 +30,13 @@ namespace transformations { class ParityOdd7bit : public Transformation { public: - explicit ParityOdd7bit(const std::string &action) : Transformation(action) { } + explicit ParityOdd7bit(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string execute(const std::string &exp, Transaction *transaction) override; static bool inplace(unsigned char *input, uint64_t input_len); }; diff --git a/src/actions/transformations/parity_zero_7bit.cc b/src/actions/transformations/parity_zero_7bit.cc index 57bb1afb..d54e8e13 100644 --- a/src/actions/transformations/parity_zero_7bit.cc +++ b/src/actions/transformations/parity_zero_7bit.cc @@ -32,26 +32,24 @@ namespace actions { namespace transformations { -std::string ParityZero7bit::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void ParityZero7bit::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); - inplace(input, value.length()); + inplace(input, in.length()); - ret.assign(reinterpret_cast(input), value.length()); + out.assign(reinterpret_cast(input), in.length()); free(input); - - return ret; } diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index f5b17910..647c7fa2 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -30,9 +30,13 @@ namespace transformations { class ParityZero7bit : public Transformation { public: - explicit ParityZero7bit(const std::string &action) : Transformation(action) { } + explicit ParityZero7bit(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string execute(const std::string &exp, Transaction *transaction) override; static bool inplace(unsigned char *input, uint64_t input_len); }; diff --git a/src/actions/transformations/php_args_names.cc b/src/actions/transformations/php_args_names.cc index e445f6b4..41e79126 100644 --- a/src/actions/transformations/php_args_names.cc +++ b/src/actions/transformations/php_args_names.cc @@ -33,15 +33,17 @@ PhpArgsNames::PhpArgsNames(const std::string &a) } -std::string PhpArgsNames::execute(const std::string &val, - Transaction *transaction) { +void PhpArgsNames::execute(Transaction *t, + ModSecStackString &val, + ModSecStackString &out) { //Took the logic from php src code: //https://github.com/php/php-src/blob/master/main/php_variables.c //Function call PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *track_vars_array) std::string value(val); std::string ret = ""; if(value[0] == '[' || value[0] == '=') { - return ret; + out.assign(ret); + return; } std::string::size_type i = 0; while(value[i] == ' ') { @@ -74,7 +76,8 @@ std::string PhpArgsNames::execute(const std::string &val, char *tmp = &value[i]; char *close_bra = strchr(tmp, ']'); if(close_bra == NULL) { - return ret; + out.assign(ret); + return; } int array_size = (int)(close_bra - start) + 1; if(array_size - i == 3 && value[i+1] == ' ') { @@ -85,11 +88,13 @@ std::string PhpArgsNames::execute(const std::string &val, ret += value[i]; } if(i >= val_size || value[i] != '[') { - return ret; + out.assign(ret); + return; } } } - return ret; + out.assign(ret); + return; } diff --git a/src/actions/transformations/php_args_names.h b/src/actions/transformations/php_args_names.h index 22301713..bf1383ee 100644 --- a/src/actions/transformations/php_args_names.h +++ b/src/actions/transformations/php_args_names.h @@ -34,8 +34,9 @@ class PhpArgsNames : public Transformation { public: explicit PhpArgsNames(const std::string &action); - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/remove_comments.cc b/src/actions/transformations/remove_comments.cc index 9cc9c92d..44882e81 100644 --- a/src/actions/transformations/remove_comments.cc +++ b/src/actions/transformations/remove_comments.cc @@ -32,21 +32,21 @@ namespace actions { namespace transformations { -std::string RemoveComments::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void RemoveComments::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 +100,8 @@ std::string RemoveComments::execute(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 c1a4ea24..9fb33ea0 100644 --- a/src/actions/transformations/remove_comments.h +++ b/src/actions/transformations/remove_comments.h @@ -31,10 +31,12 @@ namespace transformations { class RemoveComments : public Transformation { public: - explicit RemoveComments(const std::string &action) : Transformation(action) { } + explicit RemoveComments(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override;; }; diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index edaab6a1..e1bbf42a 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -30,48 +30,45 @@ namespace modsecurity { namespace actions { namespace transformations { -RemoveCommentsChar::RemoveCommentsChar(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string RemoveCommentsChar::execute(const std::string &val, - Transaction *transaction) { +void RemoveCommentsChar::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 85d43ea0..31919925 100644 --- a/src/actions/transformations/remove_comments_char.h +++ b/src/actions/transformations/remove_comments_char.h @@ -30,10 +30,12 @@ namespace transformations { class RemoveCommentsChar : public Transformation { public: - explicit RemoveCommentsChar(const std::string &action); + explicit RemoveCommentsChar(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/remove_nulls.cc b/src/actions/transformations/remove_nulls.cc index 9bf5b19e..99f0ff14 100644 --- a/src/actions/transformations/remove_nulls.cc +++ b/src/actions/transformations/remove_nulls.cc @@ -33,21 +33,20 @@ namespace actions { namespace transformations { -std::string RemoveNulls::execute(const std::string &val, - Transaction *transaction) { +void RemoveNulls::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 d6efc38c..452c93cc 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -33,8 +33,9 @@ class RemoveNulls : public Transformation { explicit RemoveNulls(const std::string &action) : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index 1ab23492..19a30b97 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -31,22 +31,18 @@ namespace modsecurity { namespace actions { namespace transformations { -RemoveWhitespace::RemoveWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string RemoveWhitespace::execute(const std::string &val, - Transaction *transaction) { - std::string value(val); +void RemoveWhitespace::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + 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 +50,9 @@ std::string RemoveWhitespace::execute(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 e8784a07..f4a41007 100644 --- a/src/actions/transformations/remove_whitespace.h +++ b/src/actions/transformations/remove_whitespace.h @@ -30,10 +30,12 @@ namespace transformations { class RemoveWhitespace : public Transformation { public: - explicit RemoveWhitespace(const std::string &action); + explicit RemoveWhitespace(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index 8a6d9672..a4f19489 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -31,24 +31,21 @@ namespace modsecurity { namespace actions { namespace transformations { -ReplaceComments::ReplaceComments(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceComments::execute(const std::string &value, - Transaction *transaction) { +void ReplaceComments::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 +55,7 @@ std::string ReplaceComments::execute(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 +71,9 @@ std::string ReplaceComments::execute(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 5effa90e..80899cfe 100644 --- a/src/actions/transformations/replace_comments.h +++ b/src/actions/transformations/replace_comments.h @@ -30,10 +30,12 @@ namespace transformations { class ReplaceComments : public Transformation { public: - explicit ReplaceComments(const std::string &action) ; + explicit ReplaceComments(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index 3c25dfc9..5b54e24e 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -30,29 +30,25 @@ namespace modsecurity { namespace actions { namespace transformations { -ReplaceNulls::ReplaceNulls(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceNulls::execute(const std::string &val, - Transaction *transaction) { +void ReplaceNulls::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 73b3ab51..e9434a5c 100644 --- a/src/actions/transformations/replace_nulls.h +++ b/src/actions/transformations/replace_nulls.h @@ -30,10 +30,12 @@ namespace transformations { class ReplaceNulls : public Transformation { public: - explicit ReplaceNulls(const std::string &action) ; + explicit ReplaceNulls(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index 740a18be..17bcc0c2 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -31,16 +31,18 @@ namespace modsecurity { namespace actions { namespace transformations { -Sha1::Sha1(const std::string &action) - : Transformation(action) { - this->action_kind = 1; + +void Sha1::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + + auto a = Utils::Sha1::digest( + std::string(in.c_str(), in.size()) + ); + + out.assign(a.c_str(), a.size()); } -std::string Sha1::execute(const std::string &value, - Transaction *transaction) { - - return Utils::Sha1::digest(value); -} } // namespace transformations } // namespace actions diff --git a/src/actions/transformations/sha1.h b/src/actions/transformations/sha1.h index afd370d1..02377e43 100644 --- a/src/actions/transformations/sha1.h +++ b/src/actions/transformations/sha1.h @@ -30,10 +30,12 @@ namespace transformations { class Sha1 : public Transformation { public: - explicit Sha1(const std::string &action) ; + explicit Sha1(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index 49908f5a..1420451a 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -41,27 +41,25 @@ namespace transformations { #define ISODIGIT(X) ((X >= '0') && (X <= '7')) #endif -std::string SqlHexDecode::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void SqlHexDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { unsigned char *input; int size = 0; 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); - size = inplace(input, value.length()); + size = inplace(input, in.length()); - ret.assign(reinterpret_cast(input), size); + out.assign(reinterpret_cast(input), size); free(input); - - return ret; } diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index ca61d960..cb7617a6 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -30,10 +30,12 @@ namespace transformations { class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(const std::string &action) : Transformation(action) { } + explicit SqlHexDecode(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static int inplace(unsigned char *data, int len); diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index e5571b7b..aaa2f098 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -70,11 +70,6 @@ namespace actions { namespace transformations { -std::string Transformation::execute(const std::string &value, - Transaction *transaction) { - return value; -} - Transformation* Transformation::instantiate(std::string a) { IF_MATCH(base64DecodeExt) { return new Base64DecodeExt(a); } IF_MATCH(base64Decode) { return new Base64Decode(a); } diff --git a/src/actions/transformations/transformation.h b/src/actions/transformations/transformation.h index bf9b5266..8f11542d 100644 --- a/src/actions/transformations/transformation.h +++ b/src/actions/transformations/transformation.h @@ -32,11 +32,12 @@ class Transformation : public Action { explicit Transformation(const std::string& _action) : Action(_action, RunTimeBeforeMatchAttemptKind) { } - Transformation(const std::string& _action, int kind) - : Action(_action, kind) { } - - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override { + // FIXME: this should be remove as soon as #1974 got fixed. + out.assign(in.c_str(), in.length()); + } static Transformation* instantiate(std::string a); }; diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index 5649b1a6..dba82910 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -31,37 +31,30 @@ namespace actions { namespace transformations { -std::string *Trim::ltrim(std::string *s) { +void Trim::ltrim(ModSecStackString *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(ModSecStackString *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(ModSecStackString *s) { + rtrim(s); + ltrim(s); } -Trim::Trim(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - - -std::string -Trim::execute(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->trim(&value); -} +void Trim::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + out = in; + trim(&out); +}; } // namespace transformations diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index ee3e3482..bfb76160 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -30,14 +30,16 @@ namespace transformations { class Trim : public Transformation { public: - explicit Trim(const std::string &action) ; + explicit Trim(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string *ltrim(std::string *s); - std::string *rtrim(std::string *s); - std::string *trim(std::string *s); + void ltrim(ModSecStackString *s); + void rtrim(ModSecStackString *s); + void trim(ModSecStackString *s); }; } // namespace transformations diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index fa0223d4..3451389b 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -32,17 +32,13 @@ namespace actions { namespace transformations { +void TrimLeft::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + out = in; + ltrim(&out); +}; -TrimLeft::TrimLeft(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} - -std::string TrimLeft::execute(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 f9e04eba..91912921 100644 --- a/src/actions/transformations/trim_left.h +++ b/src/actions/transformations/trim_left.h @@ -31,10 +31,12 @@ namespace transformations { class TrimLeft : public Trim { public: - explicit TrimLeft(const std::string &action) ; + explicit TrimLeft(const std::string &action) + : Trim(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index e056c18a..ee968a90 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -31,16 +31,13 @@ namespace actions { namespace transformations { -TrimRight::TrimRight(const std::string &action) - : Trim(action) { - this->action_kind = 1; -} +void TrimRight::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + out = in; + rtrim(&out); +}; -std::string TrimRight::execute(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 635c65e4..7fa2d570 100644 --- a/src/actions/transformations/trim_right.h +++ b/src/actions/transformations/trim_right.h @@ -31,10 +31,12 @@ namespace transformations { class TrimRight : public Trim { public: - explicit TrimRight(const std::string &action) ; + explicit TrimRight(const std::string &action) + : Trim(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index 432d326f..99100df0 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -27,22 +27,17 @@ namespace actions { namespace transformations { -UpperCase::UpperCase(const std::string &a) - : Transformation(a) { -} - -std::string UpperCase::execute(const std::string &val, - Transaction *transaction) { - std::string value(val); +void UpperCase::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 15b8fb72..cf3de628 100644 --- a/src/actions/transformations/upper_case.h +++ b/src/actions/transformations/upper_case.h @@ -32,10 +32,12 @@ namespace transformations { class UpperCase : public Transformation { public: - explicit UpperCase(const std::string &action) ; + explicit UpperCase(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 87b7aad9..75ba798c 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -32,30 +32,22 @@ namespace actions { namespace transformations { -UrlDecode::UrlDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string UrlDecode::execute(const std::string &value, - Transaction *transaction) { +void UrlDecode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { unsigned char *val(NULL); 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'; + val = (unsigned char *) malloc(sizeof(char) * in.size() + 1); + memcpy(val, in.c_str(), in.size() + 1); + val[in.size()] = '\0'; - int size = utils::urldecode_nonstrict_inplace(val, value.size(), + int size = utils::urldecode_nonstrict_inplace(val, in.size(), &invalid_count, &changed); - std::string out; - out.append((const char *)val, size); free(val); - - return out; } diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index 726d46cf..b39707a4 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -32,10 +32,12 @@ namespace transformations { class UrlDecode : public Transformation { public: - explicit UrlDecode(const std::string &action) ; + explicit UrlDecode(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; }; } // namespace transformations diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index 509f5909..9855ae41 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -38,26 +38,24 @@ namespace actions { namespace transformations { -std::string UrlDecodeUni::execute(const std::string &value, - Transaction *t) { - std::string ret; +void UrlDecodeUni::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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); - size_t i = inplace(input, value.length(), t); + size_t i = inplace(input, in.length(), t); - ret.assign(reinterpret_cast(input), i); + out.assign(reinterpret_cast(input), i); free(input); - - return ret; } diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index 39569a36..4ffbcc6a 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -31,9 +31,13 @@ namespace transformations { class UrlDecodeUni : public Transformation { public: - explicit UrlDecodeUni(const std::string &action) : Transformation(action) { } + explicit UrlDecodeUni(const std::string &action) + : Transformation(action) { } + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; - std::string execute(const std::string &exp, Transaction *transaction) override; static int inplace(unsigned char *input, uint64_t input_len, Transaction *transaction); }; diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 7fb88b36..6bfc3463 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -31,12 +31,6 @@ 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 +81,13 @@ std::string UrlEncode::url_enc(const char *input, } -std::string UrlEncode::execute(const std::string &value, - Transaction *transaction) { +void UrlEncode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { 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 29317e34..85217bd4 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -30,10 +30,12 @@ namespace transformations { class UrlEncode : public Transformation { public: - explicit UrlEncode(const std::string &action) ; + explicit UrlEncode(const std::string &action) + : Transformation(action) { }; - std::string execute(const std::string &exp, - Transaction *transaction) override; + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static std::string url_enc(const char *input, unsigned int input_len, int *changed); diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index a16fd706..d979be38 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -33,31 +33,31 @@ namespace actions { namespace transformations { -std::string Utf8ToUnicode::execute(const std::string &value, - Transaction *transaction) { - std::string ret; +void Utf8ToUnicode::execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) { + unsigned char *input; int changed = 0; - char *out; + char *out2; 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); + memset(input, '\0', in.length()+1); + memcpy(input, in.c_str(), in.length()+1); - out = inplace(input, value.size() + 1, &changed); + out2 = inplace(input, in.size() + 1, &changed); + if (out2 != NULL) { + out.assign(reinterpret_cast(out2), + strlen(reinterpret_cast(out2))); + free(out2); + } free(input); - if (out != NULL) { - ret.assign(reinterpret_cast(out), - strlen(reinterpret_cast(out))); - free(out); - } - - return ret; } diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index c2ff8774..5bb9bd15 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -35,10 +35,13 @@ namespace transformations { class Utf8ToUnicode : public Transformation { public: - explicit Utf8ToUnicode(const std::string &action) : Transformation(action) { } + explicit Utf8ToUnicode(const std::string &action) + : Transformation(action) { } - std::string execute(const std::string &exp, - Transaction *transaction) override; + + void execute(Transaction *t, + ModSecStackString &in, + ModSecStackString &out) override; static char *inplace(unsigned char *input, uint64_t input_len, int *changed); diff --git a/src/engine/lua.cc b/src/engine/lua.cc index 2747c1e1..9a109554 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -439,7 +439,11 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->execute(newVar, t); + ModSecStackString in; + ModSecStackString out; + in.assign(newVar.c_str(), newVar.size()); + tfn->execute(t, in, out); + newVar.assign(out.c_str(), out.size()); } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ @@ -461,7 +465,11 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->execute(newVar, t); + ModSecStackString in; + ModSecStackString 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/modsecurity.cc b/src/modsecurity.cc index cb51543f..165cb3ba 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -305,7 +305,9 @@ int ModSecurity::processContentOffset(const char *content, size_t len, while (!trans.empty()) { modsecurity::actions::transformations::Transformation *t; - std::string varValueRes; + ModSecStackString in; + ModSecStackString out; + yajl_gen_map_open(g); yajl_gen_string(g, reinterpret_cast("transformation"), @@ -317,8 +319,9 @@ int ModSecurity::processContentOffset(const char *content, size_t len, t = modsecurity::actions::transformations::Transformation::instantiate( trans.back().str().c_str()); - varValueRes = t->execute(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"), diff --git a/src/rule_message.cc b/src/rule_message.cc index 40c505de..70712d4a 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 "modsecurity/rule_with_actions.h" + namespace modsecurity { @@ -94,4 +97,123 @@ std::string RuleMessage::log(const RuleMessage *rm, int props, int code) { } -} // namespace modsecurity +RuleWithActions *RuleMessage::getRule() const { + return m_rule; +} + + +void RuleMessage::setRule(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; +} + + +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->hasDisruptiveAction(); + } + return 0; +} + + +} // namespace modsecurity diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 795353d2..39e394a7 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -360,62 +360,35 @@ void RuleWithActions::executeAction(Transaction *trans, } -inline void RuleWithActions::executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path) const { - - std::string *oldValue = (*value).get(); - std::string newValue = a->execute(*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)); - } - *value = u; - } - - if (path->empty()) { - path->append(*a->m_name.get()); - } else { - path->append("," + *a->m_name.get()); - } - - ms_dbg_a(trans, 9, "Transformation " + \ - *a->m_name.get() + ": \"" + \ - utils::string::limitTo(80, newValue) + "\""); -} - void RuleWithActions::executeTransformations( Transaction *trans, const std::string &in, - TransformationResults &ret) { + TransformationsResults &results) { int none = 0; + + ModSecStackString ssin; + ssin.assign(in.c_str()); + + TransformationResult a = TransformationResult(&ssin); + results.push_back(a); + + std::string path(""); std::shared_ptr value = std::shared_ptr(new std::string(in)); - if (hasMultimatchAction()) { - /* keep the original value */ - ret.push_back(std::make_pair( - std::shared_ptr(new std::string(*value)), - std::shared_ptr(new std::string(path)))); - } - for (Action *a : getTransformationPtr()) { - if (a->m_isNone) { + for (Action *action : getTransformationPtr()) { + if (action->m_isNone) { none++; } } - for (Transformation *a : getTransformationPtr()) { + for (Transformation *t : getTransformationPtr()) { if (none == 0) { - executeTransformation(a, &value, trans, &ret, &path); + executeTransformation(trans, &results, t); } - if (a->m_isNone) { + if (t->m_isNone) { none--; } } @@ -427,8 +400,8 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); - if (a->m_isNone) { + Transformation *t = dynamic_cast(b.second.get()); + if (t->m_isNone) { none++; } } @@ -438,26 +411,61 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); + Transformation *t = dynamic_cast(b.second.get()); if (none == 0) { - executeTransformation(a, &value, trans, &ret, &path); + executeTransformation(trans, &results, t); } - if (a->m_isNone) { + if (t->m_isNone) { none--; } } - if (m_containsMultiMatchAction == true) { +/* + if (hasMultimatchAction() == true) { ms_dbg_a(trans, 9, "multiMatch is enabled. " \ - + std::to_string(ret.size()) + \ + + std::to_string(results.size()) + \ " values to be tested."); + } else { + results.pop_front(); + results.push_back(TransformationResult(&ssin)); } +*/ +} - 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 + ); +} + + +void RuleWithActions::executeTransformation( + Transaction *transaction, + ModSecStackString in, + TransformationsResults *ret, + Transformation *transformation) { + + ModSecStackString out; + transformation->execute(transaction, in, out); + + ms_dbg_a(transaction, 9, " T (" + std::to_string(ret->size() - 1) + ") " + \ + *transformation->m_name.get() + ": \"" + \ + utils::string::limitTo(80, out.c_str()) + "\""); + + ret->push_back( + TransformationResult( + &out, + transformation->m_name.get() + ) + ); } diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 5ccedb27..b56cf819 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -291,15 +291,22 @@ bool RuleWithOperator::evaluate(Transaction *trans) { continue; } - TransformationResults values; + TransformationsResults transformationsResults; - executeTransformations(trans, value, values); + executeTransformations(trans, value, transformationsResults); - for (const auto &valueTemp : values) { + auto iter = transformationsResults.begin(); + if (!hasMultimatchAction()) { + iter = transformationsResults.end(); + std::advance(iter, -1); + } + while (iter != transformationsResults.end()) { bool ret; - std::string valueAfterTrans = std::move(*valueTemp.first); + auto &valueTemp = *iter; + // FIXME: this copy is not necessary. + std::string *valueAfterTrans = new std::string(valueTemp.getAfter()->c_str()); - ret = executeOperatorAt(trans, key, valueAfterTrans); + ret = executeOperatorAt(trans, key, *valueAfterTrans); if (ret == true) { trans->messageGetLast()->m_match = m_operator->resolveMatchMessage(trans, @@ -308,14 +315,28 @@ bool RuleWithOperator::evaluate(Transaction *trans) { for (auto &i : v->getOrigin()) { trans->messageGetLast()->m_reference.append(i->toText()); } + auto iter2 = transformationsResults.begin(); + while (iter2 != transformationsResults.end()) { + if (iter2->getTransformationName()) { + trans->messageGetLast()->m_reference.append(*iter2->getTransformationName()); + } + /* + if (iter == iter2) { + break; + } else { + trans->messageGetLast()->m_reference.append("--"); + } + */ + iter2++; + } - trans->messageGetLast()->m_reference.append(*valueTemp.second); - - updateMatchedVars(trans, key, valueAfterTrans); + updateMatchedVars(trans, key, *valueAfterTrans); executeActionsIndependentOfChainedRuleResult(trans); globalRet = true; } + delete valueAfterTrans; + iter++; } delete v; v = NULL; diff --git a/src/rules.cc b/src/rules.cc new file mode 100644 index 00000000..4666deb0 --- /dev/null +++ b/src/rules.cc @@ -0,0 +1,84 @@ +/* + * 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, const std::vector &ids, std::ostringstream *err) { + size_t j = 0; + for (; j < from->size(); j++) { + RuleWithActions *rule = dynamic_cast(from->at(j).get()); + if (rule && std::binary_search(ids.begin(), ids.end(), rule->getId())) { + if (err != NULL) { + *err << "Rule id: " << std::to_string(rule->getId()) \ + << " is duplicated" << std::endl; + } + return -1; + } + } + m_rules.insert(m_rules.end(), from->m_rules.begin(), from->m_rules.end()); + return j; +} + + +bool Rules::insert(std::shared_ptr rule) { + return insert(rule, nullptr, nullptr); +} + + +bool Rules::insert(std::shared_ptr rule, const std::vector *ids, std::ostringstream *err) { + RuleWithActions*r = dynamic_cast(rule.get()); + if (r && ids != nullptr && err != nullptr + && std::binary_search(ids->begin(), ids->end(), r->getId())) { + if (err != NULL) { + *err << "Rule id: " << std::to_string(r->getId()) \ + << " is duplicated" << std::endl; + } + return false; + } + m_rules.push_back(rule); + return true; +} + + +size_t Rules::size() { + return m_rules.size(); +} + + +std::shared_ptr Rules::operator[](int index) { + return m_rules[index]; +} + + +std::shared_ptr Rules::at(int index) { + return m_rules[index]; +} + + +void Rules::dump() { + 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; + } +} + + +} // namespace modsecurity + diff --git a/test/test-cases/regression/actions.json b/test/test-cases/regression/actions.json index daa93c84..c69f1a7c 100644 --- a/test/test-cases/regression/actions.json +++ b/test/test-cases/regression/actions.json @@ -49,7 +49,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 403 }, @@ -109,7 +109,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 302, "redirect_url": "http://www.google.com" @@ -169,7 +169,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 306, "redirect_url": "http://www.google.com" @@ -229,7 +229,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 500 }, @@ -288,7 +288,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 500 }, @@ -347,7 +347,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 500 }, diff --git a/test/test-cases/regression/auditlog.json b/test/test-cases/regression/auditlog.json index 860ba0ef..33b61101 100644 --- a/test/test-cases/regression/auditlog.json +++ b/test/test-cases/regression/auditlog.json @@ -40,7 +40,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 403 }, @@ -97,7 +97,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 403 }, @@ -155,7 +155,7 @@ }, "expected": { "audit_log": "", - "debug_log": "\\[9\\] Transformation t:trim: \"test", + "debug_log": "\\[9\\] T \\(0\\) t:trim: \"test", "error_log": "", "http_code": 403 }, diff --git a/test/test-cases/regression/collection-regular_expression_selection.json b/test/test-cases/regression/collection-regular_expression_selection.json index 79f772b8..cde06ac7 100644 --- a/test/test-cases/regression/collection-regular_expression_selection.json +++ b/test/test-cases/regression/collection-regular_expression_selection.json @@ -48,7 +48,7 @@ }, "expected":{ "audit_log":"", - "debug_log":"Transformation t:lowercase: \"test2\"", + "debug_log":"T \\(0\\) t:lowercase: \"test2\"", "error_log":"" }, "rules":[ diff --git a/test/test-cases/regression/config-response_type.json b/test/test-cases/regression/config-response_type.json index c4ea1c49..621ab38a 100644 --- a/test/test-cases/regression/config-response_type.json +++ b/test/test-cases/regression/config-response_type.json @@ -31,7 +31,7 @@ ] }, "expected":{ - "debug_log":"Transformation t:trim: \"no need.\"" + "debug_log":"T \\(0\\) t:trim: \"no need.\"" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/variable-FILES.json b/test/test-cases/regression/variable-FILES.json index d7fd457e..7f0f4dcf 100644 --- a/test/test-cases/regression/variable-FILES.json +++ b/test/test-cases/regression/variable-FILES.json @@ -51,7 +51,7 @@ ] }, "expected":{ - "debug_log":"Transformation t:trim: \"small_text_file" + "debug_log":"T \\(0\\) t:trim: \"small_text_file" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/variable-FILES_NAMES.json b/test/test-cases/regression/variable-FILES_NAMES.json index 48c6dc21..fcf95ed9 100644 --- a/test/test-cases/regression/variable-FILES_NAMES.json +++ b/test/test-cases/regression/variable-FILES_NAMES.json @@ -51,7 +51,7 @@ ] }, "expected":{ - "debug_log":"Transformation t:trim: \"filedata" + "debug_log":"T \\(0\\) t:trim: \"filedata" }, "rules":[ "SecRuleEngine On", diff --git a/test/unit/unit.cc b/test/unit/unit.cc index dc029080..9973ca27 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::ModSecStackString in; + modsecurity::ModSecStackString out; + std::string ret; + in.assign(t->input.c_str(), t->input.size()); Transformation *tfn = Transformation::instantiate("t:" + t->name); - std::string ret = tfn->execute(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) {