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 81b98f3e0c
commit d329d52cc3
93 changed files with 917 additions and 722 deletions

View File

@ -39,7 +39,8 @@ namespace actions {
class Action {
public:
Action(const std::string& _action, int kind = RunTimeOnlyIfMatchKind)
explicit Action(const std::string& _action, int kind = RunTimeOnlyIfMatchKind)
: m_isNone(false),
temporaryAction(false),
action_kind(kind),
@ -73,6 +74,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; }

View File

@ -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:
@ -122,108 +123,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<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 Transformations = std::vector<std::shared_ptr<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 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 {
public:
@ -171,18 +205,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<std::string> *value,
Transaction *trans,
TransformationResults *ret,
std::string *path) const;
TransformationsResults &results);
void addAction(actions::Action *a);
void addTransformation(std::shared_ptr<actions::transformations::Transformation> t) {

View File

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

View File

@ -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());
}

View File

@ -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

View File

@ -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);
out.assign(ret.c_str(), ret.size());
}

View File

@ -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

View File

@ -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());
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<char *>(
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<unsigned char *>(tmp),
value.size());
in.size());
std::string ret(tmp, 0, value.size());
out.assign(tmp, 0, in.size());
free(tmp);
return ret;
}

View File

@ -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);
};

View File

@ -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<char *>(tmp), size);
int size = ansi_c_sequences_decode_inplace(tmp, in.size());
out.assign(reinterpret_cast<char *>(tmp), size);
free(tmp);
return ret;
}
} // namespace transformations

View File

@ -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);
};

View File

@ -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<unsigned char *>
(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<char *>(input), size);
out.assign(reinterpret_cast<char *>(input), size);
free(input);
return ret;
}

View File

@ -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);
};

View File

@ -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<char>(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

View File

@ -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

View File

@ -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<unsigned char *>
(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<char *>(input), i);
out.assign(reinterpret_cast<char *>(input), i);
free(input);
return ret;
}

View File

@ -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);
};

View File

@ -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<unsigned char *>
(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<char *>(input), i);
out.assign(reinterpret_cast<char *>(input), i);
free(input);
return ret;
}

View File

@ -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);
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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());
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -32,28 +32,22 @@ 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<char *>(
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;
}

View File

@ -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);

View File

@ -34,24 +34,22 @@ 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<char *>(
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<unsigned char *>(tmp),
value.size(), 1, &changed);
in.size(), 1, &changed);
std::string ret("");
ret.assign(tmp, i);
out.assign(tmp, i);
free(tmp);
return ret;
}

View File

@ -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

View File

@ -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<unsigned char *>
(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<char *>(input), value.length());
out.assign(reinterpret_cast<char *>(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

View File

@ -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);
};

View File

@ -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<unsigned char *>
(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<char *>(input), value.length());
out.assign(reinterpret_cast<char *>(input), in.length());
free(input);
return ret;
}
bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) {
uint64_t i;

View File

@ -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);
};

View File

@ -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<unsigned char *>
(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<char *>(input), value.length());
out.assign(reinterpret_cast<char *>(input), in.length());
free(input);
return ret;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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

View File

@ -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<unsigned char *>
(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<char *>(input), j);
out.assign(reinterpret_cast<char *>(input), j);
free(input);
return ret;
}

View File

@ -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;;
};

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -30,26 +30,22 @@ 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;
const char nonBreakingSpaces = 0xa0;
const char nonBreakingSpaces2 = 0xc2;
// loop through all the chars
while (i < value.size()) {
while (i < out.size()) {
// remove whitespaces and non breaking spaces (NBSP)
if (std::isspace(static_cast<unsigned char>(value[i]))
|| (value[i] == nonBreakingSpaces)
|| value[i] == nonBreakingSpaces2) {
value.erase(i, 1);
if (std::isspace(static_cast<unsigned char>(out[i]))
|| (out[i] == nonBreakingSpaces)
|| out[i] == nonBreakingSpaces2) {
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
@ -57,10 +53,9 @@ std::string RemoveWhitespace::execute(const std::string &val,
i++;
}
}
return value;
}
} // namespace transformations
} // namespace actions
} // namespace modsecurity

View File

@ -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

View File

@ -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<char *>(
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<char *>(input), j);
out.append(reinterpret_cast<char *>(input), j);
free(input);
return resp;
}
} // namespace transformations

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<unsigned char *>
(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<char *>(input), size);
out.assign(reinterpret_cast<char *>(input), size);
free(input);
return ret;
}

View File

@ -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);

View File

@ -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); }

View File

@ -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);
};

View File

@ -31,47 +31,39 @@ 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(), [](unsigned char c) {
return !std::isspace(c);
})
);
return s;
}
std::string *Trim::rtrim(std::string *s) {
void Trim::rtrim(ModSecStackString *s) {
s->erase(
std::find_if(s->rbegin(), s->rend(), [](unsigned char c) {
return !std::isspace(c);
}).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

View File

@ -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);
static void ltrim(ModSecStackString *s);
static void rtrim(ModSecStackString *s);
static void trim(ModSecStackString *s);
};
} // namespace transformations

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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<unsigned char *>
(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<char *>(input), i);
out.assign(reinterpret_cast<char *>(input), i);
free(input);
return ret;
}

View File

@ -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);
};

View File

@ -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());
}

View File

@ -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);

View File

@ -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<unsigned char *>
(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<char *>(out2),
strlen(reinterpret_cast<char *>(out2)));
free(out2);
}
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 {
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);

View File

@ -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: " \

View File

@ -307,7 +307,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<const unsigned char*>("transformation"),
@ -319,8 +321,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<const unsigned char*>("value"),

View File

@ -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

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(
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<std::string> value =
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()) {
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<Transformation*>(b.second.get());
if (a->m_isNone) {
Transformation *t = dynamic_cast<Transformation*>(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<Transformation*>(b.second.get());
Transformation *t = dynamic_cast<Transformation*>(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<std::string>(new std::string(*value)),
std::shared_ptr<std::string>(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) + "\"");
ret->push_back(
TransformationResult(
&out,
transformation->m_name.get()
)
);
}

View File

@ -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;

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": {
"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
},

View File

@ -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
},

View File

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

View File

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

View File

@ -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",

View File

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

View File

@ -90,8 +90,14 @@ void perform_unit_test(ModSecurityTest<UnitTest> *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) {