Skip to content

Commit 43f8aee

Browse files
committed
Splits Rule class into: Rule, RuleBase, RuleMarker
1 parent fda03c0 commit 43f8aee

File tree

18 files changed

+949
-852
lines changed

18 files changed

+949
-852
lines changed

headers/modsecurity/rule.h

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define HEADERS_MODSECURITY_RULE_H_
2727

2828
#include "modsecurity/transaction.h"
29+
#include "modsecurity/modsecurity.h"
2930
#include "modsecurity/variable_value.h"
3031

3132

@@ -63,19 +64,94 @@ using Tags = std::vector<actions::Tag *>;
6364
using SetVars = std::vector<actions::SetVar *>;
6465
using MatchActions = std::vector<actions::Action *>;
6566

66-
class Rule {
67+
class RuleBase {
68+
public:
69+
RuleBase(std::unique_ptr<std::string> fileName, int lineNumber)
70+
: m_fileName(std::move(fileName)),
71+
m_lineNumber(lineNumber),
72+
m_phase(modsecurity::Phases::RequestHeadersPhase) {
73+
}
74+
75+
virtual bool evaluate(Transaction *transaction,
76+
std::shared_ptr<RuleMessage> rm) = 0;
77+
78+
std::shared_ptr<std::string> getFileName() const {
79+
return m_fileName;
80+
}
81+
82+
int getLineNumber() const {
83+
return m_lineNumber;
84+
}
85+
86+
int getPhase() const { return m_phase; }
87+
void setPhase(int phase) { m_phase = phase; }
88+
89+
virtual std::string getReference() {
90+
return *m_fileName + ":" + std::to_string(m_lineNumber);
91+
}
92+
93+
94+
virtual bool isMarker() { return false; }
95+
96+
private:
97+
std::shared_ptr<std::string> m_fileName;
98+
int m_lineNumber;
99+
// FIXME: phase may not be neede to SecMarker.
100+
int m_phase;
101+
};
102+
103+
104+
class RuleMarker : public RuleBase {
105+
public:
106+
RuleMarker(
107+
const std::string &name,
108+
std::unique_ptr<std::string> fileName,
109+
int lineNumber)
110+
: RuleBase(std::move(fileName), lineNumber),
111+
m_name(std::make_shared<std::string>(name)) { }
112+
113+
114+
virtual bool evaluate(Transaction *transaction,
115+
std::shared_ptr<RuleMessage> rm) override {
116+
117+
if (transaction->isInsideAMarker()) {
118+
if (*transaction->getCurrentMarker() == *m_name) {
119+
transaction->removeMarker();
120+
// FIXME: Move this to .cc
121+
// ms_dbg_a(transaction, 4, "Out of a SecMarker " + *m_name);
122+
}
123+
}
124+
125+
return true;
126+
};
127+
128+
129+
std::shared_ptr<std::string> getName() const {
130+
return m_name;
131+
}
132+
133+
bool isMarker() override { return true; }
134+
135+
private:
136+
std::shared_ptr<std::string> m_name;
137+
};
138+
139+
140+
class Rule : public RuleBase {
67141
public:
68142
Rule(operators::Operator *op,
69143
variables::Variables *variables,
70144
std::vector<actions::Action *> *actions,
71145
Transformations *transformations,
72146
std::unique_ptr<std::string> fileName,
73147
int lineNumber);
74-
explicit Rule(const std::string &marker);
148+
explicit Rule(const std::string &marker,
149+
std::unique_ptr<std::string> fileName,
150+
int lineNumber);
75151
virtual ~Rule();
76152

77153
virtual bool evaluate(Transaction *transaction,
78-
std::shared_ptr<RuleMessage> rm);
154+
std::shared_ptr<RuleMessage> rm) override;
79155

80156
void organizeActions(std::vector<actions::Action *> *actions);
81157
void cleanUpActions();
@@ -119,8 +195,6 @@ class Rule {
119195

120196
inline bool isUnconditional() const { return m_operator == NULL; }
121197

122-
virtual bool isMarker() { return m_isSecMarker; }
123-
124198
inline bool isChained() const { return m_isChained == true; }
125199
inline bool hasCaptureAction() const { return m_containsCaptureAction == true; }
126200
inline void setChained(bool b) { m_isChained = b; }
@@ -133,23 +207,23 @@ class Rule {
133207
std::string msg(Transaction *t);
134208
inline bool hasSeverity() const { return m_severity != NULL; }
135209
int severity() const;
136-
int getPhase() const { return m_phase; }
137-
void setPhase(int phase) { m_phase = phase; }
138210

139211
std::string getOperatorName() const;
140212

141213
int64_t m_ruleId;
214+
215+
virtual std::string getReference() override {
216+
return std::to_string(m_ruleId);
217+
}
218+
142219
std::unique_ptr<Rule> m_chainedRuleChild;
143220
Rule *m_chainedRuleParent;
144221

145-
std::shared_ptr<std::string> m_fileName;
146-
147222
std::string m_marker;
148223
std::string m_rev;
149224
std::string m_ver;
150225
int m_accuracy;
151226
int m_maturity;
152-
int m_lineNumber;
153227

154228
private:
155229
modsecurity::variables::Variables *m_variables;
@@ -174,7 +248,7 @@ class Rule {
174248
bool m_isSecMarker:1;
175249
bool m_unconditional:1;
176250

177-
int m_phase;
251+
178252

179253
};
180254

headers/modsecurity/rule_message.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ class RuleMessage {
5555
m_reference(""),
5656
m_rev(rule->m_rev),
5757
m_rule(rule),
58-
m_ruleFile(rule->m_fileName),
58+
m_ruleFile(rule->getFileName()),
5959
m_ruleId(rule->m_ruleId),
60-
m_ruleLine(rule->m_lineNumber),
60+
m_ruleLine(rule->getLineNumber()),
6161
m_saveMessage(true),
6262
m_serverIpAddress(trans->m_serverIpAddress),
6363
m_severity(0),

headers/modsecurity/rules.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ class Rules {
4040
public:
4141
void dump() const {
4242
for (int j = 0; j < m_rules.size(); j++) {
43-
std::cout << " Rule ID: " << std::to_string(m_rules.at(j)->m_ruleId);
43+
std::cout << " Rule ID: " << m_rules.at(j)->getReference();
4444
std::cout << "--" << m_rules.at(j) << std::endl;
4545
}
4646
}
4747

4848
int append(Rules *from, const std::vector<int64_t> &ids, std::ostringstream *err) {
4949
size_t j = 0;
5050
for (; j < from->size(); j++) {
51-
Rule *rule = from->at(j).get();
52-
if (std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) {
51+
Rule *rule = dynamic_cast<Rule *>(from->at(j).get());
52+
if (rule && std::binary_search(ids.begin(), ids.end(), rule->m_ruleId)) {
5353
if (err != NULL) {
5454
*err << "Rule id: " << std::to_string(rule->m_ruleId) \
5555
<< " is duplicated" << std::endl;
@@ -61,28 +61,28 @@ class Rules {
6161
return j;
6262
}
6363

64-
bool insert(std::shared_ptr<Rule> rule) {
64+
bool insert(std::shared_ptr<RuleBase> rule) {
6565
return insert(rule, nullptr, nullptr);
6666
}
6767

68-
bool insert(std::shared_ptr<Rule> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
69-
if (ids != nullptr && std::binary_search(ids->begin(), ids->end(), rule->m_ruleId)) {
68+
bool insert(std::shared_ptr<RuleBase> rule, const std::vector<int64_t> *ids, std::ostringstream *err) {
69+
Rule *r = dynamic_cast<Rule *>(rule.get());
70+
if (ids != nullptr && std::binary_search(ids->begin(), ids->end(), r->m_ruleId)) {
7071
if (err != nullptr) {
71-
*err << "Rule id: " << std::to_string(rule->m_ruleId) \
72+
*err << "Rule id: " << std::to_string(r->m_ruleId) \
7273
<< " is duplicated" << std::endl;
7374
}
7475
return false;
7576
}
76-
7777
m_rules.push_back(rule);
7878
return true;
7979
}
8080

8181
size_t size() const { return m_rules.size(); }
82-
std::shared_ptr<Rule> operator[](int index) const { return m_rules[index]; }
83-
std::shared_ptr<Rule> at(int index) const { return m_rules[index]; }
82+
std::shared_ptr<RuleBase> operator[](int index) const { return m_rules[index]; }
83+
std::shared_ptr<RuleBase> at(int index) const { return m_rules[index]; }
8484

85-
std::vector<std::shared_ptr<Rule> > m_rules;
85+
std::vector<std::shared_ptr<RuleBase> > m_rules;
8686
};
8787

8888

headers/modsecurity/rules_set_phases.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Rule;
4040
class RulesSetPhases {
4141
public:
4242

43-
bool insert(std::shared_ptr<Rule> rule);
43+
bool insert(std::shared_ptr<RuleBase> rule);
4444

4545
int append(RulesSetPhases *from, std::ostringstream *err);
4646
void dump() const;

headers/modsecurity/transaction.h

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <utility>
2727
#include <vector>
2828
#include <memory>
29+
#include <stack>
2930
#endif
3031

3132
#include <stdlib.h>
@@ -48,6 +49,7 @@ typedef struct Rules_t RulesSet;
4849
#include "modsecurity/collection/collection.h"
4950
#include "modsecurity/variable_origin.h"
5051

52+
5153
#ifndef NO_LOGS
5254
#define ms_dbg(b, c) \
5355
do { \
@@ -284,9 +286,38 @@ class TransactionAnchoredVariables {
284286
int m_variableOffset;
285287
};
286288

289+
class TransactionSecMarkerManagement {
290+
public:
291+
bool isInsideAMarker() const {
292+
if (m_marker) {
293+
return true;
294+
}
295+
296+
return false;
297+
}
298+
299+
std::shared_ptr<std::string> getCurrentMarker() const {
300+
if (m_marker) {
301+
return m_marker;
302+
} else {
303+
throw;
304+
}
305+
}
306+
307+
void removeMarker() {
308+
m_marker.reset();
309+
}
310+
311+
void addMarker(std::shared_ptr<std::string> name) {
312+
m_marker = name;
313+
}
314+
315+
private:
316+
std::shared_ptr<std::string> m_marker;
317+
};
287318

288319
/** @ingroup ModSecurity_CPP_API */
289-
class Transaction : public TransactionAnchoredVariables {
320+
class Transaction : public TransactionAnchoredVariables, public TransactionSecMarkerManagement {
290321
public:
291322
Transaction(ModSecurity *transaction, RulesSet *rules, void *logCbData);
292323
Transaction(ModSecurity *transaction, RulesSet *rules, char *id,
@@ -518,12 +549,6 @@ class Transaction : public TransactionAnchoredVariables {
518549
*/
519550
std::shared_ptr<std::string> m_id;
520551

521-
/**
522-
* Holds the SecMarker name that this transaction should wait to perform
523-
* rules evaluation again.
524-
*/
525-
std::string m_marker;
526-
527552
/**
528553
* Holds the amount of rules that should be skipped. If bigger than 0 the
529554
* current rule should be skipped and the number needs to be decreased.

src/actions/skip_after.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ namespace actions {
2828

2929

3030
bool SkipAfter::evaluate(Rule *rule, Transaction *transaction) {
31-
ms_dbg_a(transaction, 5, "Setting skipAfter for: " + m_parser_payload);
32-
transaction->m_marker = m_parser_payload;
31+
ms_dbg_a(transaction, 5, "Setting skipAfter for: " + *m_skipName);
32+
transaction->addMarker(m_skipName);
3333
return true;
3434
}
3535

src/actions/skip_after.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
#include <string>
17+
#include <memory>
1718

1819
#include "modsecurity/actions/action.h"
1920

@@ -30,9 +31,12 @@ namespace actions {
3031
class SkipAfter : public Action {
3132
public:
3233
explicit SkipAfter(const std::string &action)
33-
: Action(action, RunTimeOnlyIfMatchKind) { }
34+
: Action(action, RunTimeOnlyIfMatchKind),
35+
m_skipName(std::make_shared<std::string>(m_parser_payload)) { }
3436

3537
bool evaluate(Rule *rule, Transaction *transaction) override;
38+
private:
39+
std::shared_ptr<std::string> m_skipName;
3640
};
3741

3842

src/parser/driver.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ Driver::~Driver() {
4141
}
4242

4343

44-
int Driver::addSecMarker(std::string marker) {
44+
int Driver::addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber) {
45+
// FIXME: we might move this to the parser.
4546
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
46-
std::unique_ptr<Rule> rule(new Rule(marker));
47+
RuleMarker *r = new RuleMarker(marker, std::move(fileName), lineNumber);
48+
std::unique_ptr<RuleMarker> rule(std::move(r));
4749
rule->setPhase(i);
4850
m_rulesSetPhases.insert(std::move(rule));
4951
}
@@ -58,7 +60,6 @@ int Driver::addSecAction(std::unique_ptr<Rule> rule) {
5860
return false;
5961
}
6062

61-
6263
m_rulesSetPhases.insert(std::move(rule));
6364

6465
return true;
@@ -99,15 +100,16 @@ int Driver::addSecRule(std::unique_ptr<Rule> r) {
99100
*/
100101
if (rule->m_ruleId == 0) {
101102
m_parserError << "Rules must have an ID. File: ";
102-
m_parserError << rule->m_fileName << " at line: ";
103-
m_parserError << std::to_string(rule->m_lineNumber) << std::endl;
103+
m_parserError << rule->getFileName() << " at line: ";
104+
m_parserError << std::to_string(rule->getLineNumber()) << std::endl;
104105
return false;
105106
}
106107

107108
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
108109
Rules *rules = m_rulesSetPhases[i];
109110
for (int j = 0; j < rules->size(); j++) {
110-
if (rules->at(j)->m_ruleId == rule->m_ruleId) {
111+
Rule *lr = dynamic_cast<Rule *>(rules->at(j).get());
112+
if (lr && lr->m_ruleId == rule->m_ruleId) {
111113
m_parserError << "Rule id: " << std::to_string(rule->m_ruleId) \
112114
<< " is duplicated" << std::endl;
113115
return false;

src/parser/driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class Driver : public RulesSetProperties {
6868

6969
int addSecRule(std::unique_ptr<Rule> rule);
7070
int addSecAction(std::unique_ptr<Rule> rule);
71-
int addSecMarker(std::string marker);
71+
int addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber);
7272
int addSecRuleScript(std::unique_ptr<RuleScript> rule);
7373

7474
bool scan_begin();

0 commit comments

Comments
 (0)