Refactoring: Makes transformations to work with new execute signature

This commit is contained in:
Felipe Zimmerle 2019-02-26 15:39:27 -03:00
parent eacbbf89e7
commit d196bec0bc
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
94 changed files with 914 additions and 720 deletions

View File

@ -39,6 +39,7 @@ namespace actions {
class Action { class Action {
public: public:
explicit Action(const std::string& _action) explicit Action(const std::string& _action)
: m_isNone(false), : m_isNone(false),
temporaryAction(false), temporaryAction(false),
@ -81,6 +82,17 @@ class Action {
RuleMessage &ruleMessage) { RuleMessage &ruleMessage) {
return execute(rule, transaction); 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 init(std::string *error) { return true; }
virtual bool isDisruptive() { return false; } virtual bool isDisruptive() { return false; }

View File

@ -26,14 +26,15 @@
#include "modsecurity/transaction.h" #include "modsecurity/transaction.h"
#include "modsecurity/rule.h" #include "modsecurity/rule.h"
#include "modsecurity/rule_with_operator.h"
#ifdef __cplusplus #ifdef __cplusplus
namespace modsecurity { namespace modsecurity {
namespace actions {
class Tag;
};
class RuleWithActions;
class RuleMessage { class RuleMessage {
public: public:
@ -110,108 +111,22 @@ class RuleMessage {
static std::string _details(const RuleMessage *rm); static std::string _details(const RuleMessage *rm);
static std::string _errorLogTail(const RuleMessage *rm); static std::string _errorLogTail(const RuleMessage *rm);
RuleWithActions *getRule() const { RuleWithActions *getRule() const;
return m_rule; void setRule(RuleWithActions *rule);
} bool isSettle() const;
int getRuleId() const;
void setRule(RuleWithActions *rule) { int getPhase() const;
m_rule = rule; std::string getFileName() const;
} int getLineNumber() const;
std::string getRev() const;
bool isSettle() const { std::string getVer() const;
return m_rule != nullptr; int getMaturity() const;
} int getAccuracy() const;
std::string getClientIpAddress() const;
int getRuleId() const { std::string getServerIpAddress() const;
if (m_rule) { std::string getRequestId() const;
return m_rule->getId(); std::string getUri() const;
} bool isDisruptive() const;
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;
}
int m_severity; int m_severity;
std::list<std::string> m_tags; std::list<std::string> m_tags;

View File

@ -49,9 +49,6 @@ class Transformation;
} }
} }
using TransformationResult = std::pair<std::shared_ptr<std::string>,
std::shared_ptr<std::string>>;
using TransformationResults = std::list<TransformationResult>;
using Transformation = actions::transformations::Transformation; using Transformation = actions::transformations::Transformation;
using Transformations = std::vector<std::shared_ptr<Transformation> >; using Transformations = std::vector<std::shared_ptr<Transformation> >;
using TransformationsPtr = std::vector<Transformation *>; using TransformationsPtr = std::vector<Transformation *>;
@ -67,6 +64,43 @@ using MatchActionsPtr = std::vector<actions::Action *>;
using XmlNSs = std::vector<std::shared_ptr<actions::XmlNS> >; using XmlNSs = std::vector<std::shared_ptr<actions::XmlNS> >;
using XmlNSsPtr = std::vector<actions::XmlNS *>; using XmlNSsPtr = std::vector<actions::XmlNS *>;
using ModSecStackString = std::basic_string<char, std::char_traits<char>, std::allocator<char> >;
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<TransformationResult>;
class RuleWithActions : public Rule { class RuleWithActions : public Rule {
public: public:
@ -167,18 +201,21 @@ class RuleWithActions : public Rule {
bool context); bool context);
static void executeTransformation(
Transaction *transaction,
TransformationsResults *ret,
Transformation *transformation);
static void executeTransformation(
Transaction *transaction,
ModSecStackString in,
TransformationsResults *ret,
Transformation *transformation);
void executeTransformations( void executeTransformations(
Transaction *transaction, Transaction *transaction,
const std::string &value, const std::string &value,
TransformationResults &ret); TransformationsResults &results);
inline void executeTransformation(
actions::transformations::Transformation *a,
std::shared_ptr<std::string> *value,
Transaction *trans,
TransformationResults *ret,
std::string *path) const;
void addAction(actions::Action *a); void addAction(actions::Action *a);
void addTransformation(std::shared_ptr<actions::transformations::Transformation> t) { void addTransformation(std::shared_ptr<actions::transformations::Transformation> t) {

View File

@ -35,6 +35,7 @@
namespace modsecurity { namespace modsecurity {
using TransformationsResults = std::list<TransformationResult>;
class RuleWithOperator : public RuleWithActions { class RuleWithOperator : public RuleWithActions {
public: public:

View File

@ -32,11 +32,12 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Base64Decode::execute(const std::string &value, void Base64Decode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
std::string value(in.c_str(), in.size());
std::string ret = Utils::Base64::decode(value); std::string ret = Utils::Base64::decode(value);
out.assign(ret.c_str(), ret.size());
return ret;
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class Base64Decode : public Transformation { class Base64Decode : public Transformation {
public: public:
explicit Base64Decode(const std::string &action) : Transformation(action) { } explicit Base64Decode(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,11 +32,11 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Base64DecodeExt::execute(const std::string &value, void Base64DecodeExt::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret = Utils::Base64::decode_forgiven(value); ModSecStackString &out) {
std::string ret = Utils::Base64::decode_forgiven(in.c_str());
return ret; out.assign(ret.c_str(), ret.size());
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class Base64DecodeExt : public Transformation { class Base64DecodeExt : public Transformation {
public: public:
explicit Base64DecodeExt(const std::string &action) : Transformation(action) { } explicit Base64DecodeExt(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,11 +32,12 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Base64Encode::execute(const std::string &value, void Base64Encode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret = Utils::Base64::encode(value); ModSecStackString &out) {
std::string ret = Utils::Base64::encode(
return ret; std::string(in.c_str(), in.size()));
out.assign(ret.c_str(), ret.size());
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class Base64Encode : public Transformation { class Base64Encode : public Transformation {
public: public:
explicit Base64Encode(const std::string &action) : Transformation(action) { } explicit Base64Encode(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,12 +31,12 @@ namespace actions {
namespace transformations { namespace transformations {
std::string CmdLine::execute(const std::string &value, void CmdLine::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
int space = 0; int space = 0;
for (auto& a : value) { for (auto& a : in) {
switch (a) { switch (a) {
/* remove some characters */ /* remove some characters */
case '"': case '"':
@ -53,7 +53,7 @@ std::string CmdLine::execute(const std::string &value,
case '\r': case '\r':
case '\n': case '\n':
if (space == 0) { if (space == 0) {
ret.append(" "); out.append(" ");
space++; space++;
} }
break; break;
@ -62,22 +62,20 @@ std::string CmdLine::execute(const std::string &value,
case '/': case '/':
case '(': case '(':
if (space) { if (space) {
ret.pop_back(); out.pop_back();
} }
space = 0; space = 0;
ret.append(&a, 1); out.append(&a, 1);
break; break;
/* copy normal characters */ /* copy normal characters */
default : default :
char b = std::tolower(a); char b = std::tolower(a);
ret.append(&b, 1); out.append(&b, 1);
space = 0; space = 0;
break; break;
} }
} }
return ret;
} }

View File

@ -30,11 +30,12 @@ namespace transformations {
class CmdLine : public Transformation { class CmdLine : public Transformation {
public: public:
explicit CmdLine(const std::string &action) explicit CmdLine(const std::string &action)
: Transformation(action) { } : Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -30,37 +30,32 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
CompressWhitespace::CompressWhitespace(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string CompressWhitespace::execute(const std::string &value, void CompressWhitespace::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
std::string a;
int inWhiteSpace = 0; int inWhiteSpace = 0;
int i = 0; size_t i = 0;
out.reserve(in.size());
while (i < value.size()) { while (i < in.size()) {
if (isspace(value[i])) { if (isspace(in[i])) {
if (inWhiteSpace) { if (inWhiteSpace) {
i++; i++;
continue; continue;
} else { } else {
inWhiteSpace = 1; inWhiteSpace = 1;
a.append(" ", 1); out.append(" ", 1);
} }
} else { } else {
inWhiteSpace = 0; inWhiteSpace = 0;
a.append(&value.at(i), 1); out.append(&in.at(i), 1);
} }
i++; i++;
} }
return a;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,10 +30,12 @@ namespace transformations {
class CompressWhitespace : public Transformation { class CompressWhitespace : public Transformation {
public: public:
explicit CompressWhitespace(const std::string &action) ; explicit CompressWhitespace(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -34,20 +34,19 @@ namespace actions {
namespace transformations { namespace transformations {
std::string CssDecode::execute(const std::string &value, void CssDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
char *tmp = reinterpret_cast<char *>( char *tmp = reinterpret_cast<char *>(
malloc(sizeof(char) * value.size() + 1)); malloc(sizeof(char) * in.size() + 1));
memcpy(tmp, value.c_str(), value.size() + 1); memcpy(tmp, in.c_str(), in.size() + 1);
tmp[value.size()] = '\0'; tmp[in.size()] = '\0';
CssDecode::css_decode_inplace(reinterpret_cast<unsigned char *>(tmp), CssDecode::css_decode_inplace(reinterpret_cast<unsigned char *>(tmp),
value.size()); in.size());
std::string ret(tmp, 0, value.size()); out.assign(tmp, 0, in.size());
free(tmp); free(tmp);
return ret;
} }

View File

@ -31,10 +31,12 @@ namespace transformations {
class CssDecode : public Transformation { class CssDecode : public Transformation {
public: public:
explicit CssDecode(const std::string &action) explicit CssDecode(const std::string &action)
: Transformation(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); static int css_decode_inplace(unsigned char *input, int64_t input_len);
}; };

View File

@ -31,11 +31,6 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { 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 EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input,
int input_len) { 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, void EscapeSeqDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
unsigned char *tmp = (unsigned char *) malloc(sizeof(char) unsigned char *tmp = (unsigned char *) malloc(sizeof(char)
* value.size() + 1); * in.size() + 1);
memcpy(tmp, value.c_str(), value.size() + 1); memcpy(tmp, in.c_str(), in.size() + 1);
tmp[value.size()] = '\0'; tmp[in.size()] = '\0';
int size = ansi_c_sequences_decode_inplace(tmp, value.size()); int size = ansi_c_sequences_decode_inplace(tmp, in.size());
out.assign(reinterpret_cast<char *>(tmp), size);
std::string ret("");
ret.assign(reinterpret_cast<char *>(tmp), size);
free(tmp); free(tmp);
return ret;
} }
} // namespace transformations } // namespace transformations

View File

@ -30,9 +30,13 @@ namespace transformations {
class EscapeSeqDecode : public Transformation { class EscapeSeqDecode : public Transformation {
public: public:
explicit EscapeSeqDecode(const std::string &action) ; explicit EscapeSeqDecode(const std::string &action)
std::string execute(const std::string &exp, : Transformation(action) { }
Transaction *transaction) override;
void execute(Transaction *t,
ModSecStackString &in,
ModSecStackString &out) override;
static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); static int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len);
}; };

View File

@ -32,27 +32,25 @@ namespace actions {
namespace transformations { namespace transformations {
std::string HexDecode::execute(const std::string &value, void HexDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
int size = 0; int size = 0;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), size); out.assign(reinterpret_cast<char *>(input), size);
free(input); free(input);
return ret;
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class HexDecode : public Transformation { class HexDecode : public Transformation {
public: public:
explicit HexDecode(const std::string &action) : Transformation(action) { } explicit HexDecode(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static int inplace(unsigned char *data, int len); static int inplace(unsigned char *data, int len);
}; };

View File

@ -31,23 +31,20 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { 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; std::stringstream result;
for (std::size_t i=0; i < value.length(); i++) { for (std::size_t i=0; i < in.length(); i++) {
unsigned int ii = (unsigned char)(value[i]); int ii = reinterpret_cast<char>(in[i]);
result << std::setw(2) << std::setfill('0') << std::hex << ii; result << std::setw(2) << std::setfill('0') << std::hex << ii;
} }
return result.str(); out.assign(result.str().c_str());
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,10 +30,13 @@ namespace transformations {
class HexEncode : public Transformation { class HexEncode : public Transformation {
public: 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 } // namespace transformations

View File

@ -33,26 +33,24 @@ namespace actions {
namespace transformations { namespace transformations {
std::string HtmlEntityDecode::execute(const std::string &value, void HtmlEntityDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), i); out.assign(reinterpret_cast<char *>(input), i);
free(input); free(input);
return ret;
} }

View File

@ -36,8 +36,9 @@ class HtmlEntityDecode : public Transformation {
explicit HtmlEntityDecode(const std::string &action) explicit HtmlEntityDecode(const std::string &action)
: Transformation(action) { } : Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static int inplace(unsigned char *input, uint64_t input_len); static int inplace(unsigned char *input, uint64_t input_len);
}; };

View File

@ -34,26 +34,24 @@ namespace actions {
namespace transformations { namespace transformations {
std::string JsDecode::execute(const std::string &value, void JsDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), i); out.assign(reinterpret_cast<char *>(input), i);
free(input); free(input);
return ret;
} }

View File

@ -33,8 +33,10 @@ class JsDecode : public Transformation {
explicit JsDecode(const std::string &action) explicit JsDecode(const std::string &action)
: Transformation(action) { } : Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static int inplace(unsigned char *input, uint64_t input_len); static int inplace(unsigned char *input, uint64_t input_len);
}; };

View File

@ -30,15 +30,11 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
Length::Length(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string Length::execute(const std::string &value, void Length::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
return std::to_string(value.size()); out.assign(std::to_string(in.size()).c_str());
} }
} // namespace transformations } // namespace transformations

View File

@ -30,10 +30,12 @@ namespace transformations {
class Length : public Transformation { class Length : public Transformation {
public: public:
explicit Length(const std::string &action); explicit Length(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -27,22 +27,17 @@ namespace actions {
namespace transformations { namespace transformations {
LowerCase::LowerCase(const std::string &a) void LowerCase::execute(Transaction *t,
: Transformation(a) { ModSecStackString &in,
} ModSecStackString &out) {
std::string LowerCase::execute(const std::string &val,
Transaction *transaction) {
std::locale loc; std::locale loc;
std::string value(val); out.resize(in.size());
for (std::string::size_type i=0; i < in.size(); ++i) {
for (std::string::size_type i=0; i < value.length(); ++i) { out[i] = std::tolower(in[i], loc);
value[i] = std::tolower(value[i], loc);
} }
return value;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -32,9 +32,12 @@ namespace transformations {
class LowerCase : public Transformation { class LowerCase : public Transformation {
public: public:
explicit LowerCase(const std::string &action); explicit LowerCase(const std::string &action)
std::string execute(const std::string &exp, : Transformation(action) { };
Transaction *transaction) override;
void execute(Transaction *t,
ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,11 +31,12 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Md5::execute(const std::string &value, void Md5::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret = Utils::Md5::digest(value); ModSecStackString &out) {
std::string ret = Utils::Md5::digest(std::string(in.c_str(), in.size()));
return ret; out.assign(ret.c_str(), ret.size());
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class Md5 : public Transformation { class Md5 : public Transformation {
public: public:
explicit Md5(const std::string &action) : Transformation(action) { } explicit Md5(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,10 +31,9 @@ namespace actions {
namespace transformations { namespace transformations {
std::string None::execute(const std::string &value, void None::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
return value; ModSecStackString &out) { }
}
} // namespace transformations } // namespace transformations

View File

@ -34,8 +34,9 @@ class None : public Transformation {
: Transformation(action) : Transformation(action)
{ m_isNone = true; } { m_isNone = true; }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,28 +32,22 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
NormalisePath::NormalisePath(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string NormalisePath::execute(const std::string &value, void NormalisePath::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int changed = 0; int changed = 0;
char *tmp = reinterpret_cast<char *>( char *tmp = reinterpret_cast<char *>(
malloc(sizeof(char) * value.size() + 1)); malloc(sizeof(char) * in.size() + 1));
memcpy(tmp, value.c_str(), value.size() + 1); memcpy(tmp, in.c_str(), in.size() + 1);
tmp[value.size()] = '\0'; tmp[in.size()] = '\0';
int i = normalize_path_inplace((unsigned char *)tmp, int i = normalize_path_inplace((unsigned char *)tmp,
value.size(), 0, &changed); in.size(), 0, &changed);
std::string ret(""); out.assign(tmp, i);
ret.assign(tmp, i);
free(tmp); free(tmp);
return ret;
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class NormalisePath : public Transformation { class NormalisePath : public Transformation {
public: public:
explicit NormalisePath(const std::string &action); explicit NormalisePath(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static int normalize_path_inplace(unsigned char *input, int input_len, static int normalize_path_inplace(unsigned char *input, int input_len,
int win, int *changed); int win, int *changed);

View File

@ -34,24 +34,22 @@ namespace actions {
namespace transformations { namespace transformations {
std::string NormalisePathWin::execute(const std::string &value, void NormalisePathWin::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int changed; int changed;
char *tmp = reinterpret_cast<char *>( char *tmp = reinterpret_cast<char *>(
malloc(sizeof(char) * value.size() + 1)); malloc(sizeof(char) * in.size() + 1));
memcpy(tmp, value.c_str(), value.size() + 1); memcpy(tmp, in.c_str(), in.size() + 1);
tmp[value.size()] = '\0'; tmp[in.size()] = '\0';
int i = NormalisePath::normalize_path_inplace( int i = NormalisePath::normalize_path_inplace(
reinterpret_cast<unsigned char *>(tmp), reinterpret_cast<unsigned char *>(tmp),
value.size(), 1, &changed); in.size(), 1, &changed);
std::string ret(""); out.assign(tmp, i);
ret.assign(tmp, i);
free(tmp); free(tmp);
return ret;
} }

View File

@ -33,8 +33,9 @@ class NormalisePathWin : public Transformation {
explicit NormalisePathWin(const std::string &action) explicit NormalisePathWin(const std::string &action)
: Transformation(action) { } : Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,28 +32,27 @@ namespace actions {
namespace transformations { namespace transformations {
std::string ParityEven7bit::execute(const std::string &value, void ParityEven7bit::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), value.length()); out.assign(reinterpret_cast<char *>(input), in.length());
free(input); free(input);
return ret;
} }
bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) {
uint64_t i; uint64_t i;
@ -76,7 +75,6 @@ bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) {
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,9 +30,13 @@ namespace transformations {
class ParityEven7bit : public Transformation { class ParityEven7bit : public Transformation {
public: 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); static bool inplace(unsigned char *input, uint64_t input_len);
}; };

View File

@ -32,28 +32,27 @@ namespace actions {
namespace transformations { namespace transformations {
std::string ParityOdd7bit::execute(const std::string &value, void ParityOdd7bit::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), value.length()); out.assign(reinterpret_cast<char *>(input), in.length());
free(input); free(input);
return ret;
} }
bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) { bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) {
uint64_t i; uint64_t i;

View File

@ -30,9 +30,13 @@ namespace transformations {
class ParityOdd7bit : public Transformation { class ParityOdd7bit : public Transformation {
public: 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); static bool inplace(unsigned char *input, uint64_t input_len);
}; };

View File

@ -32,26 +32,24 @@ namespace actions {
namespace transformations { namespace transformations {
std::string ParityZero7bit::execute(const std::string &value, void ParityZero7bit::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), value.length()); out.assign(reinterpret_cast<char *>(input), in.length());
free(input); free(input);
return ret;
} }

View File

@ -30,9 +30,13 @@ namespace transformations {
class ParityZero7bit : public Transformation { class ParityZero7bit : public Transformation {
public: 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); static bool inplace(unsigned char *input, uint64_t input_len);
}; };

View File

@ -33,15 +33,17 @@ PhpArgsNames::PhpArgsNames(const std::string &a)
} }
std::string PhpArgsNames::execute(const std::string &val, void PhpArgsNames::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &val,
ModSecStackString &out) {
//Took the logic from php src code: //Took the logic from php src code:
//https://github.com/php/php-src/blob/master/main/php_variables.c //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) //Function call PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *track_vars_array)
std::string value(val); std::string value(val);
std::string ret = ""; std::string ret = "";
if(value[0] == '[' || value[0] == '=') { if(value[0] == '[' || value[0] == '=') {
return ret; out.assign(ret);
return;
} }
std::string::size_type i = 0; std::string::size_type i = 0;
while(value[i] == ' ') { while(value[i] == ' ') {
@ -74,7 +76,8 @@ std::string PhpArgsNames::execute(const std::string &val,
char *tmp = &value[i]; char *tmp = &value[i];
char *close_bra = strchr(tmp, ']'); char *close_bra = strchr(tmp, ']');
if(close_bra == NULL) { if(close_bra == NULL) {
return ret; out.assign(ret);
return;
} }
int array_size = (int)(close_bra - start) + 1; int array_size = (int)(close_bra - start) + 1;
if(array_size - i == 3 && value[i+1] == ' ') { if(array_size - i == 3 && value[i+1] == ' ') {
@ -85,11 +88,13 @@ std::string PhpArgsNames::execute(const std::string &val,
ret += value[i]; ret += value[i];
} }
if(i >= val_size || value[i] != '[') { if(i >= val_size || value[i] != '[') {
return ret; out.assign(ret);
return;
} }
} }
} }
return ret; out.assign(ret);
return;
} }

View File

@ -34,8 +34,9 @@ class PhpArgsNames : public Transformation {
public: public:
explicit PhpArgsNames(const std::string &action); explicit PhpArgsNames(const std::string &action);
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,21 +32,21 @@ namespace actions {
namespace transformations { namespace transformations {
std::string RemoveComments::execute(const std::string &value, void RemoveComments::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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; uint64_t i, j, incomment;
i = j = incomment = 0; i = j = incomment = 0;
@ -100,10 +100,8 @@ std::string RemoveComments::execute(const std::string &value,
input[j++] = ' '; input[j++] = ' ';
} }
ret.assign(reinterpret_cast<char *>(input), j); out.assign(reinterpret_cast<char *>(input), j);
free(input); free(input);
return ret;
} }

View File

@ -31,10 +31,12 @@ namespace transformations {
class RemoveComments : public Transformation { class RemoveComments : public Transformation {
public: public:
explicit RemoveComments(const std::string &action) : Transformation(action) { } explicit RemoveComments(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;;
}; };

View File

@ -30,48 +30,45 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
RemoveCommentsChar::RemoveCommentsChar(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string RemoveCommentsChar::execute(const std::string &val, void RemoveCommentsChar::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int64_t i; int64_t i;
std::string value(val); out = in;
i = 0; i = 0;
while (i < value.size()) { while (i < out.size()) {
if (value.at(i) == '/' if (out.at(i) == '/'
&& (i+1 < value.size()) && value.at(i+1) == '*') { && (i+1 < out.size()) && out.at(i+1) == '*') {
value.erase(i, 2); out.erase(i, 2);
} else if (value.at(i) == '*' } else if (out.at(i) == '*'
&& (i+1 < value.size()) && value.at(i+1) == '/') { && (i+1 < out.size()) && out.at(i+1) == '/') {
value.erase(i, 2); out.erase(i, 2);
} else if (value.at(i) == '<' } else if (out.at(i) == '<'
&& (i+1 < value.size()) && (i+1 < out.size())
&& value.at(i+1) == '!' && out.at(i+1) == '!'
&& (i+2 < value.size()) && (i+2 < out.size())
&& value.at(i+2) == '-' && out.at(i+2) == '-'
&& (i+3 < value.size()) && (i+3 < out.size())
&& value.at(i+3) == '-') { && out.at(i+3) == '-') {
value.erase(i, 4); out.erase(i, 4);
} else if (value.at(i) == '-' } else if (out.at(i) == '-'
&& (i+1 < value.size()) && value.at(i+1) == '-' && (i+1 < out.size()) && out.at(i+1) == '-'
&& (i+2 < value.size()) && value.at(i+2) == '>') { && (i+2 < out.size()) && out.at(i+2) == '>') {
value.erase(i, 3); out.erase(i, 3);
} else if (value.at(i) == '-' } else if (out.at(i) == '-'
&& (i+1 < value.size()) && value.at(i+1) == '-') { && (i+1 < out.size()) && out.at(i+1) == '-') {
value.erase(i, 2); out.erase(i, 2);
} else if (value.at(i) == '#') { } else if (out.at(i) == '#') {
value.erase(i, 1); out.erase(i, 1);
} else { } else {
i++; i++;
} }
} }
return value;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,10 +30,12 @@ namespace transformations {
class RemoveCommentsChar : public Transformation { class RemoveCommentsChar : public Transformation {
public: public:
explicit RemoveCommentsChar(const std::string &action); explicit RemoveCommentsChar(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -33,21 +33,20 @@ namespace actions {
namespace transformations { namespace transformations {
std::string RemoveNulls::execute(const std::string &val, void RemoveNulls::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int64_t i; int64_t i;
std::string value(val); out = in;
i = 0; i = 0;
while (i < value.size()) { while (i < out.size()) {
if (value.at(i) == '\0') { if (out.at(i) == '\0') {
value.erase(i, 1); out.erase(i, 1);
} else { } else {
i++; i++;
} }
} }
return value;
} }

View File

@ -33,8 +33,9 @@ class RemoveNulls : public Transformation {
explicit RemoveNulls(const std::string &action) explicit RemoveNulls(const std::string &action)
: Transformation(action) { } : Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,23 +31,19 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { 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; int64_t i = 0;
char nonBreakingSpaces = 0xa0; char nonBreakingSpaces = 0xa0;
// loop through all the chars // loop through all the chars
while (i < value.size()) { while (i < out.size()) {
// remove whitespaces and non breaking spaces (NBSP) // remove whitespaces and non breaking spaces (NBSP)
if (isspace(value[i]) || (value[i] == nonBreakingSpaces)) { if (isspace(out[i]) || (out[i] == nonBreakingSpaces)) {
value.erase(i, 1); out.erase(i, 1);
} else { } else {
/* if the space is not a whitespace char, increment counter /* if the space is not a whitespace char, increment counter
counter should not be incremented if a character is erased because counter should not be incremented if a character is erased because
@ -55,10 +51,9 @@ std::string RemoveWhitespace::execute(const std::string &val,
i++; i++;
} }
} }
return value;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,10 +30,12 @@ namespace transformations {
class RemoveWhitespace : public Transformation { class RemoveWhitespace : public Transformation {
public: public:
explicit RemoveWhitespace(const std::string &action); explicit RemoveWhitespace(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,24 +31,21 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
ReplaceComments::ReplaceComments(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string ReplaceComments::execute(const std::string &value, void ReplaceComments::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
uint64_t i, j, incomment; uint64_t i, j, incomment;
char *input = reinterpret_cast<char *>( char *input = reinterpret_cast<char *>(
malloc(sizeof(char) * value.size() + 1)); malloc(sizeof(char) * in.size() + 1));
memcpy(input, value.c_str(), value.size() + 1); memcpy(input, in.c_str(), in.size() + 1);
input[value.size()] = '\0'; input[in.size()] = '\0';
i = j = incomment = 0; i = j = incomment = 0;
while (i < value.size()) { while (i < in.size()) {
if (incomment == 0) { if (incomment == 0) {
if ((input[i] == '/') && (i + 1 < value.size()) if ((input[i] == '/') && (i + 1 < in.size())
&& (input[i + 1] == '*')) { && (input[i + 1] == '*')) {
incomment = 1; incomment = 1;
i += 2; i += 2;
@ -58,7 +55,7 @@ std::string ReplaceComments::execute(const std::string &value,
j++; j++;
} }
} else { } else {
if ((input[i] == '*') && (i + 1 < value.size()) if ((input[i] == '*') && (i + 1 < in.size())
&& (input[i + 1] == '/')) { && (input[i + 1] == '/')) {
incomment = 0; incomment = 0;
i += 2; i += 2;
@ -74,13 +71,9 @@ std::string ReplaceComments::execute(const std::string &value,
input[j++] = ' '; input[j++] = ' ';
} }
out.append(reinterpret_cast<char *>(input), j);
std::string resp;
resp.append(reinterpret_cast<char *>(input), j);
free(input); free(input);
return resp;
} }
} // namespace transformations } // namespace transformations

View File

@ -30,10 +30,12 @@ namespace transformations {
class ReplaceComments : public Transformation { class ReplaceComments : public Transformation {
public: public:
explicit ReplaceComments(const std::string &action) ; explicit ReplaceComments(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -30,29 +30,25 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
ReplaceNulls::ReplaceNulls(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string ReplaceNulls::execute(const std::string &val, void ReplaceNulls::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int64_t i; int64_t i;
std::string value(val); out = in;
i = 0; i = 0;
while (i < value.size()) { while (i < out.size()) {
if (value.at(i) == '\0') { if (out.at(i) == '\0') {
value.erase(i, 1); out.erase(i, 1);
value.insert(i, " ", 1); out.insert(i, " ", 1);
} else { } else {
i++; i++;
} }
} }
return value;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -30,10 +30,12 @@ namespace transformations {
class ReplaceNulls : public Transformation { class ReplaceNulls : public Transformation {
public: public:
explicit ReplaceNulls(const std::string &action) ; explicit ReplaceNulls(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,16 +31,18 @@ namespace modsecurity {
namespace actions { namespace actions {
namespace transformations { namespace transformations {
Sha1::Sha1(const std::string &action)
: Transformation(action) { void Sha1::execute(Transaction *t,
this->action_kind = 1; 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 transformations
} // namespace actions } // namespace actions

View File

@ -30,10 +30,12 @@ namespace transformations {
class Sha1 : public Transformation { class Sha1 : public Transformation {
public: public:
explicit Sha1(const std::string &action) ; explicit Sha1(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -41,27 +41,25 @@ namespace transformations {
#define ISODIGIT(X) ((X >= '0') && (X <= '7')) #define ISODIGIT(X) ((X >= '0') && (X <= '7'))
#endif #endif
std::string SqlHexDecode::execute(const std::string &value, void SqlHexDecode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
int size = 0; int size = 0;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), size); out.assign(reinterpret_cast<char *>(input), size);
free(input); free(input);
return ret;
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class SqlHexDecode : public Transformation { class SqlHexDecode : public Transformation {
public: public:
explicit SqlHexDecode(const std::string &action) : Transformation(action) { } explicit SqlHexDecode(const std::string &action)
: Transformation(action) { }
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static int inplace(unsigned char *data, int len); static int inplace(unsigned char *data, int len);

View File

@ -70,11 +70,6 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Transformation::execute(const std::string &value,
Transaction *transaction) {
return value;
}
Transformation* Transformation::instantiate(std::string a) { Transformation* Transformation::instantiate(std::string a) {
IF_MATCH(base64DecodeExt) { return new Base64DecodeExt(a); } IF_MATCH(base64DecodeExt) { return new Base64DecodeExt(a); }
IF_MATCH(base64Decode) { return new Base64Decode(a); } IF_MATCH(base64Decode) { return new Base64Decode(a); }

View File

@ -32,11 +32,12 @@ class Transformation : public Action {
explicit Transformation(const std::string& _action) explicit Transformation(const std::string& _action)
: Action(_action, RunTimeBeforeMatchAttemptKind) { } : Action(_action, RunTimeBeforeMatchAttemptKind) { }
Transformation(const std::string& _action, int kind) void execute(Transaction *t,
: Action(_action, kind) { } ModSecStackString &in,
ModSecStackString &out) override {
std::string execute(const std::string &exp, // FIXME: this should be remove as soon as #1974 got fixed.
Transaction *transaction) override; out.assign(in.c_str(), in.length());
}
static Transformation* instantiate(std::string a); static Transformation* instantiate(std::string a);
}; };

View File

@ -31,47 +31,38 @@ namespace actions {
namespace transformations { namespace transformations {
std::string *Trim::ltrim(std::string *s) { void Trim::ltrim(ModSecStackString *s) {
s->erase( s->erase(
s->begin(), s->begin(),
std::find_if(s->begin(), s->end(), [](unsigned char c) { std::find_if(s->begin(), s->end(), [](unsigned char c) {
return !std::isspace(c); return !std::isspace(c);
}) })
); );
return s;
} }
std::string *Trim::rtrim(std::string *s) { void Trim::rtrim(ModSecStackString *s) {
s->erase( s->erase(
std::find_if(s->rbegin(), s->rend(), [](unsigned char c) { std::find_if(s->rbegin(), s->rend(), [](unsigned char c) {
return !std::isspace(c); return !std::isspace(c);
}).base(), }).base(),
s->end() s->end()
); );
return s;
} }
std::string *Trim::trim(std::string *s) { void Trim::trim(ModSecStackString *s) {
return ltrim(rtrim(s)); rtrim(s);
ltrim(s);
} }
Trim::Trim(const std::string &action) void Trim::execute(Transaction *t,
: Transformation(action) { ModSecStackString &in,
this->action_kind = 1; ModSecStackString &out) {
} out = in;
trim(&out);
};
std::string
Trim::execute(const std::string &val,
Transaction *transaction) {
std::string value(val);
return *this->trim(&value);
}
} // namespace transformations } // namespace transformations

View File

@ -30,14 +30,16 @@ namespace transformations {
class Trim : public Transformation { class Trim : public Transformation {
public: public:
explicit Trim(const std::string &action) ; explicit Trim(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
std::string *ltrim(std::string *s); static void ltrim(ModSecStackString *s);
std::string *rtrim(std::string *s); static void rtrim(ModSecStackString *s);
std::string *trim(std::string *s); static void trim(ModSecStackString *s);
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,17 +32,13 @@ namespace actions {
namespace transformations { 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 transformations
} // namespace actions } // namespace actions

View File

@ -31,10 +31,12 @@ namespace transformations {
class TrimLeft : public Trim { class TrimLeft : public Trim {
public: public:
explicit TrimLeft(const std::string &action) ; explicit TrimLeft(const std::string &action)
: Trim(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -31,16 +31,13 @@ namespace actions {
namespace transformations { namespace transformations {
TrimRight::TrimRight(const std::string &action) void TrimRight::execute(Transaction *t,
: Trim(action) { ModSecStackString &in,
this->action_kind = 1; 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 transformations
} // namespace actions } // namespace actions

View File

@ -31,10 +31,12 @@ namespace transformations {
class TrimRight : public Trim { class TrimRight : public Trim {
public: public:
explicit TrimRight(const std::string &action) ; explicit TrimRight(const std::string &action)
: Trim(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -27,22 +27,17 @@ namespace actions {
namespace transformations { namespace transformations {
UpperCase::UpperCase(const std::string &a) void UpperCase::execute(Transaction *t,
: Transformation(a) { ModSecStackString &in,
} ModSecStackString &out) {
std::string UpperCase::execute(const std::string &val,
Transaction *transaction) {
std::string value(val);
std::locale loc; std::locale loc;
out.reserve(in.size());
for (std::string::size_type i=0; i < value.length(); ++i) { for (std::string::size_type i=0; i < in.size(); ++i) {
value[i] = std::toupper(value[i], loc); out += std::toupper(in[i], loc);
} }
return value;
} }
} // namespace transformations } // namespace transformations
} // namespace actions } // namespace actions
} // namespace modsecurity } // namespace modsecurity

View File

@ -32,10 +32,12 @@ namespace transformations {
class UpperCase : public Transformation { class UpperCase : public Transformation {
public: public:
explicit UpperCase(const std::string &action) ; explicit UpperCase(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -32,30 +32,22 @@ namespace actions {
namespace transformations { namespace transformations {
UrlDecode::UrlDecode(const std::string &action) void UrlDecode::execute(Transaction *t,
: Transformation(action) { ModSecStackString &in,
this->action_kind = 1; ModSecStackString &out) {
}
std::string UrlDecode::execute(const std::string &value,
Transaction *transaction) {
unsigned char *val(NULL); unsigned char *val(NULL);
int invalid_count = 0; int invalid_count = 0;
int changed; int changed;
val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); val = (unsigned char *) malloc(sizeof(char) * in.size() + 1);
memcpy(val, value.c_str(), value.size() + 1); memcpy(val, in.c_str(), in.size() + 1);
val[value.size()] = '\0'; 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); &invalid_count, &changed);
std::string out;
out.append((const char *)val, size); out.append((const char *)val, size);
free(val); free(val);
return out;
} }

View File

@ -32,10 +32,12 @@ namespace transformations {
class UrlDecode : public Transformation { class UrlDecode : public Transformation {
public: public:
explicit UrlDecode(const std::string &action) ; explicit UrlDecode(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
}; };
} // namespace transformations } // namespace transformations

View File

@ -38,26 +38,24 @@ namespace actions {
namespace transformations { namespace transformations {
std::string UrlDecodeUni::execute(const std::string &value, void UrlDecodeUni::execute(Transaction *t,
Transaction *t) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(input), i); out.assign(reinterpret_cast<char *>(input), i);
free(input); free(input);
return ret;
} }

View File

@ -31,9 +31,13 @@ namespace transformations {
class UrlDecodeUni : public Transformation { class UrlDecodeUni : public Transformation {
public: 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, static int inplace(unsigned char *input, uint64_t input_len,
Transaction *transaction); Transaction *transaction);
}; };

View File

@ -31,12 +31,6 @@ namespace actions {
namespace transformations { namespace transformations {
UrlEncode::UrlEncode(const std::string &action)
: Transformation(action) {
this->action_kind = 1;
}
std::string UrlEncode::url_enc(const char *input, std::string UrlEncode::url_enc(const char *input,
unsigned int input_len, int *changed) { unsigned int input_len, int *changed) {
char *rval, *d; char *rval, *d;
@ -87,13 +81,13 @@ std::string UrlEncode::url_enc(const char *input,
} }
std::string UrlEncode::execute(const std::string &value, void UrlEncode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
ModSecStackString &out) {
int changed; int changed;
std::string ret = url_enc(value.c_str(), value.size(), &changed); std::string ret = url_enc(in.c_str(), in.size(), &changed);
out.assign(ret.c_str(), ret.size());
return ret;
} }

View File

@ -30,10 +30,12 @@ namespace transformations {
class UrlEncode : public Transformation { class UrlEncode : public Transformation {
public: public:
explicit UrlEncode(const std::string &action) ; explicit UrlEncode(const std::string &action)
: Transformation(action) { };
std::string execute(const std::string &exp, void execute(Transaction *t,
Transaction *transaction) override; ModSecStackString &in,
ModSecStackString &out) override;
static std::string url_enc(const char *input, static std::string url_enc(const char *input,
unsigned int input_len, int *changed); unsigned int input_len, int *changed);

View File

@ -33,31 +33,31 @@ namespace actions {
namespace transformations { namespace transformations {
std::string Utf8ToUnicode::execute(const std::string &value, void Utf8ToUnicode::execute(Transaction *t,
Transaction *transaction) { ModSecStackString &in,
std::string ret; ModSecStackString &out) {
unsigned char *input; unsigned char *input;
int changed = 0; int changed = 0;
char *out; char *out2;
input = reinterpret_cast<unsigned char *> input = reinterpret_cast<unsigned char *>
(malloc(sizeof(char) * value.length()+1)); (malloc(sizeof(char) * in.length()+1));
if (input == NULL) { 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<char *>(out2),
strlen(reinterpret_cast<char *>(out2)));
free(out2);
}
free(input); free(input);
if (out != NULL) {
ret.assign(reinterpret_cast<char *>(out),
strlen(reinterpret_cast<char *>(out)));
free(out);
}
return ret;
} }

View File

@ -35,10 +35,13 @@ namespace transformations {
class Utf8ToUnicode : public Transformation { class Utf8ToUnicode : public Transformation {
public: 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, static char *inplace(unsigned char *input, uint64_t input_len,
int *changed); int *changed);

View File

@ -439,7 +439,11 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t,
"t:" + std::string(name)); "t:" + std::string(name));
// FIXME: transformation is not yet returning null. // FIXME: transformation is not yet returning null.
if (tfn) { 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 { } else {
ms_dbg_a(t, 1, ms_dbg_a(t, 1,
"SecRuleScript: Invalid transformation function: " \ "SecRuleScript: Invalid transformation function: " \
@ -461,7 +465,11 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t,
// FIXME: transformation is not yet returning null. // FIXME: transformation is not yet returning null.
if (tfn) { 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; delete tfn;
} else { } else {
ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \

View File

@ -307,7 +307,9 @@ int ModSecurity::processContentOffset(const char *content, size_t len,
while (!trans.empty()) { while (!trans.empty()) {
modsecurity::actions::transformations::Transformation *t; modsecurity::actions::transformations::Transformation *t;
std::string varValueRes; ModSecStackString in;
ModSecStackString out;
yajl_gen_map_open(g); yajl_gen_map_open(g);
yajl_gen_string(g, yajl_gen_string(g,
reinterpret_cast<const unsigned char*>("transformation"), reinterpret_cast<const unsigned char*>("transformation"),
@ -319,8 +321,9 @@ int ModSecurity::processContentOffset(const char *content, size_t len,
t = modsecurity::actions::transformations::Transformation::instantiate( t = modsecurity::actions::transformations::Transformation::instantiate(
trans.back().str().c_str()); trans.back().str().c_str());
varValueRes = t->execute(varValue, NULL); in.assign(varValue.c_str());
varValue.assign(varValueRes); t->execute(NULL, in, out);
varValue.assign(out.c_str());
trans.pop_back(); trans.pop_back();
yajl_gen_string(g, reinterpret_cast<const unsigned char*>("value"), yajl_gen_string(g, reinterpret_cast<const unsigned char*>("value"),

View File

@ -19,6 +19,9 @@
#include "modsecurity/modsecurity.h" #include "modsecurity/modsecurity.h"
#include "modsecurity/transaction.h" #include "modsecurity/transaction.h"
#include "src/utils/string.h" #include "src/utils/string.h"
#include "src/actions/tag.h"
#include "modsecurity/rule_with_actions.h"
namespace modsecurity { 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

View File

@ -360,62 +360,35 @@ void RuleWithActions::executeAction(Transaction *trans,
} }
inline void RuleWithActions::executeTransformation(
actions::transformations::Transformation *a,
std::shared_ptr<std::string> *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<std::string> 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( void RuleWithActions::executeTransformations(
Transaction *trans, Transaction *trans,
const std::string &in, const std::string &in,
TransformationResults &ret) { TransformationsResults &results) {
int none = 0; int none = 0;
ModSecStackString ssin;
ssin.assign(in.c_str());
TransformationResult a = TransformationResult(&ssin);
results.push_back(a);
std::string path(""); std::string path("");
std::shared_ptr<std::string> value = std::shared_ptr<std::string> value =
std::shared_ptr<std::string>(new std::string(in)); std::shared_ptr<std::string>(new std::string(in));
if (hasMultimatchAction()) {
/* keep the original value */
ret.push_back(std::make_pair(
std::shared_ptr<std::string>(new std::string(*value)),
std::shared_ptr<std::string>(new std::string(path))));
}
for (Action *a : getTransformationPtr()) { for (Action *action : getTransformationPtr()) {
if (a->m_isNone) { if (action->m_isNone) {
none++; none++;
} }
} }
for (Transformation *a : getTransformationPtr()) { for (Transformation *t : getTransformationPtr()) {
if (none == 0) { if (none == 0) {
executeTransformation(a, &value, trans, &ret, &path); executeTransformation(trans, &results, t);
} }
if (a->m_isNone) { if (t->m_isNone) {
none--; none--;
} }
} }
@ -427,8 +400,8 @@ void RuleWithActions::executeTransformations(
if (m_ruleId != b.first) { if (m_ruleId != b.first) {
continue; continue;
} }
Transformation *a = dynamic_cast<Transformation*>(b.second.get()); Transformation *t = dynamic_cast<Transformation*>(b.second.get());
if (a->m_isNone) { if (t->m_isNone) {
none++; none++;
} }
} }
@ -438,26 +411,61 @@ void RuleWithActions::executeTransformations(
if (m_ruleId != b.first) { if (m_ruleId != b.first) {
continue; continue;
} }
Transformation *a = dynamic_cast<Transformation*>(b.second.get()); Transformation *t = dynamic_cast<Transformation*>(b.second.get());
if (none == 0) { if (none == 0) {
executeTransformation(a, &value, trans, &ret, &path); executeTransformation(trans, &results, t);
} }
if (a->m_isNone) { if (t->m_isNone) {
none--; none--;
} }
} }
if (m_containsMultiMatchAction == true) { /*
if (hasMultimatchAction() == true) {
ms_dbg_a(trans, 9, "multiMatch is enabled. " \ ms_dbg_a(trans, 9, "multiMatch is enabled. " \
+ std::to_string(ret.size()) + \ + std::to_string(results.size()) + \
" values to be tested."); " 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<std::string>(new std::string(*value)), void RuleWithActions::executeTransformation(
std::shared_ptr<std::string>(new std::string(path)))); 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()
)
);
} }

View File

@ -291,15 +291,22 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
continue; 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; 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) { if (ret == true) {
trans->messageGetLast()->m_match = m_operator->resolveMatchMessage(trans, trans->messageGetLast()->m_match = m_operator->resolveMatchMessage(trans,
@ -308,14 +315,28 @@ bool RuleWithOperator::evaluate(Transaction *trans) {
for (auto &i : v->getOrigin()) { for (auto &i : v->getOrigin()) {
trans->messageGetLast()->m_reference.append(i->toText()); 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); executeActionsIndependentOfChainedRuleResult(trans);
globalRet = true; globalRet = true;
} }
delete valueAfterTrans;
iter++;
} }
delete v; delete v;
v = NULL; v = NULL;

84
src/rules.cc Normal file
View File

@ -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<int64_t> &ids, std::ostringstream *err) {
size_t j = 0;
for (; j < from->size(); j++) {
RuleWithActions *rule = dynamic_cast<RuleWithActions*>(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> rule) {
return insert(rule, nullptr, nullptr);
}
bool Rules::insert(std::shared_ptr<Rule> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
RuleWithActions*r = dynamic_cast<RuleWithActions*>(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<Rule> Rules::operator[](int index) {
return m_rules[index];
}
std::shared_ptr<Rule> 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

View File

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

View File

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

View File

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

View File

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

View File

@ -933,7 +933,7 @@
] ]
}, },
"expected":{ "expected":{
"error_log":"o0,1v228,1t:lowercase,t:trim", "error_log":"o0,1v228,1t:lowercaset:trim",
"http_code": 403 "http_code": 403
}, },
"rules":[ "rules":[

View File

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

View File

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

View File

@ -90,8 +90,14 @@ void perform_unit_test(ModSecurityTest<UnitTest> *test, UnitTest *t,
} }
delete op; delete op;
} else if (t->type == "tfn") { } 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); 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->obtained = 1;
t->obtainedOutput = ret; t->obtainedOutput = ret;
if (ret != t->output) { if (ret != t->output) {