Skip to content

Commit 118e1b3

Browse files
committed
Support expirevar for in-memory collection
1 parent 135d1fa commit 118e1b3

23 files changed

+5171
-5061
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_id.json
103103
TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json
104104
TESTS+=test/test-cases/regression/action-disruptive.json
105105
TESTS+=test/test-cases/regression/action-exec.json
106+
TESTS+=test/test-cases/regression/action-expirevar.json
106107
TESTS+=test/test-cases/regression/action-id.json
107108
TESTS+=test/test-cases/regression/action-initcol.json
108109
TESTS+=test/test-cases/regression/action-msg.json

headers/modsecurity/collection/collection.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* ModSecurity, http://www.modsecurity.org/
3-
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
3+
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
44
*
55
* You may not use this file except in compliance with
66
* the License. You may obtain a copy of the License at
@@ -16,7 +16,6 @@
1616

1717
#ifdef __cplusplus
1818
#include <string>
19-
#include <iostream>
2019
#include <unordered_map>
2120
#include <list>
2221
#include <vector>
@@ -56,6 +55,8 @@ class Collection {
5655

5756
virtual void del(const std::string& key) = 0;
5857

58+
virtual void setExpiry(const std::string& key, int32_t expiry_seconds) = 0;
59+
5960
virtual std::unique_ptr<std::string> resolveFirst(
6061
const std::string& var) = 0;
6162

@@ -129,6 +130,21 @@ class Collection {
129130
}
130131

131132

133+
/* setExpiry */
134+
virtual void setExpiry(const std::string& key, std::string compartment,
135+
int32_t expiry_seconds) {
136+
std::string nkey = compartment + "::" + key;
137+
setExpiry(nkey, expiry_seconds);
138+
}
139+
140+
141+
virtual void setExpiry(const std::string& key, std::string compartment,
142+
std::string compartment2, int32_t expiry_seconds) {
143+
std::string nkey = compartment + "::" + compartment2 + "::" + key;
144+
setExpiry(nkey, expiry_seconds);
145+
}
146+
147+
132148
/* resolveFirst */
133149
virtual std::unique_ptr<std::string> resolveFirst(const std::string& var,
134150
std::string compartment) {

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ ACTIONS = \
134134
actions/disruptive/redirect.cc \
135135
actions/disruptive/pass.cc \
136136
actions/exec.cc \
137+
actions/expire_var.cc \
137138
actions/init_col.cc \
138139
actions/log.cc \
139140
actions/log_data.cc \
@@ -259,6 +260,7 @@ UTILS = \
259260

260261
COLLECTION = \
261262
collection/collections.cc \
263+
collection/backend/collection_data.cc \
262264
collection/backend/in_memory-per_process.cc \
263265
collection/backend/lmdb.cc
264266

src/actions/expire_var.cc

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#include "src/actions/expire_var.h"
17+
18+
#include <string>
19+
20+
#include "modsecurity/rules_set.h"
21+
#include "modsecurity/transaction.h"
22+
#include "modsecurity/rule.h"
23+
#include "src/utils/string.h"
24+
#include "src/variables/global.h"
25+
#include "src/variables/ip.h"
26+
#include "src/variables/resource.h"
27+
#include "src/variables/session.h"
28+
#include "src/variables/user.h"
29+
#include "src/variables/variable.h"
30+
31+
namespace modsecurity {
32+
namespace actions {
33+
34+
35+
bool ExpireVar::init(std::string *error) {
36+
return true;
37+
}
38+
39+
40+
bool ExpireVar::evaluate(RuleWithActions *rule, Transaction *t) {
41+
42+
std::string expireExpressionExpanded(m_string->evaluate(t));
43+
44+
std::string fully_qualified_var;
45+
int expirySeconds = 0;
46+
size_t posEquals = expireExpressionExpanded.find("=");
47+
if (posEquals == std::string::npos) {
48+
fully_qualified_var = expireExpressionExpanded;
49+
} else {
50+
fully_qualified_var = expireExpressionExpanded.substr(0, posEquals);
51+
std::string expiry = expireExpressionExpanded.substr(posEquals+1);
52+
if (expiry.find_first_not_of("0123456789") == std::string::npos) {
53+
expirySeconds = atoi(expiry.c_str());
54+
} else {
55+
ms_dbg_a(t, 5, "Non-numeric expiry seconds found in expirevar expression.");
56+
return true;
57+
}
58+
}
59+
60+
size_t posDot = fully_qualified_var.find(".");
61+
if (posDot == std::string::npos) {
62+
ms_dbg_a(t, 5, "No collection found in expirevar expression.");
63+
return true;
64+
}
65+
66+
std::string collection = fully_qualified_var.substr(0, posDot);
67+
std::string variable_name = fully_qualified_var.substr(posDot+1);
68+
std::unique_ptr<RunTimeString> runTimeString(new RunTimeString());
69+
runTimeString->appendText(fully_qualified_var);
70+
71+
if (collection == "ip") {
72+
std::unique_ptr<modsecurity::variables::Ip_DynamicElement> ip_dynamicElement(new modsecurity::variables::Ip_DynamicElement(std::move(runTimeString)));
73+
ip_dynamicElement->setExpiry(t, variable_name, expirySeconds);
74+
} else if (collection == "global") {
75+
std::unique_ptr<modsecurity::variables::Global_DynamicElement> global_dynamicElement(new modsecurity::variables::Global_DynamicElement(std::move(runTimeString)));
76+
global_dynamicElement->setExpiry(t, variable_name, expirySeconds);
77+
} else if (collection == "resource") {
78+
std::unique_ptr<modsecurity::variables::Resource_DynamicElement> resource_dynamicElement(new modsecurity::variables::Resource_DynamicElement(std::move(runTimeString)));
79+
resource_dynamicElement->setExpiry(t, variable_name, expirySeconds);
80+
} else if (collection == "session") {
81+
std::unique_ptr<modsecurity::variables::Session_DynamicElement> session_dynamicElement(new modsecurity::variables::Session_DynamicElement(std::move(runTimeString)));
82+
session_dynamicElement->setExpiry(t, variable_name, expirySeconds);
83+
} else if (collection == "user") {
84+
std::unique_ptr<modsecurity::variables::User_DynamicElement> user_dynamicElement(new modsecurity::variables::User_DynamicElement(std::move(runTimeString)));
85+
user_dynamicElement->setExpiry(t, variable_name, expirySeconds);
86+
} else {
87+
ms_dbg_a(t, 5, "Invalid collection found in expirevar expression: collection must be `ip', `global', `resource', `user' or `session'");
88+
}
89+
ms_dbg_a(t, 9, "Setting variable `" + variable_name + "' to expire in " + std::to_string(expirySeconds) + " seconds.");
90+
91+
return true;
92+
}
93+
94+
} // namespace actions
95+
} // namespace modsecurity

src/actions/expire_var.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#include <memory>
17+
#include <string>
18+
#include <utility>
19+
20+
#include "modsecurity/actions/action.h"
21+
#include "src/run_time_string.h"
22+
23+
#ifndef SRC_ACTIONS_EXPIRE_VAR_H_
24+
#define SRC_ACTIONS_EXPIRE_VAR_H_
25+
26+
class Transaction;
27+
28+
namespace modsecurity {
29+
class Transaction;
30+
class RuleWithOperator;
31+
32+
namespace actions {
33+
34+
class ExpireVar : public Action {
35+
public:
36+
explicit ExpireVar(const std::string &action) : Action(action) { }
37+
38+
explicit ExpireVar(std::unique_ptr<RunTimeString> z)
39+
: Action("expirevar", RunTimeOnlyIfMatchKind),
40+
m_string(std::move(z)) { }
41+
42+
bool evaluate(RuleWithActions *rule, Transaction *transaction) override;
43+
bool init(std::string *error) override;
44+
45+
private:
46+
47+
std::unique_ptr<RunTimeString> m_string;
48+
};
49+
50+
} // namespace actions
51+
} // namespace modsecurity
52+
53+
54+
#endif // SRC_ACTIONS_EXPIRE_VAR_H_
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#include "src/collection/backend/collection_data.h"
17+
18+
19+
namespace modsecurity {
20+
namespace collection {
21+
namespace backend {
22+
23+
24+
bool CollectionData::isExpired() const {
25+
if (m_hasExpiryTime == false) {
26+
return false;
27+
}
28+
auto now = std::chrono::system_clock::now();
29+
return (now >= m_expiryTime);
30+
}
31+
32+
33+
void CollectionData::setExpiry(int32_t seconds_until_expiry) {
34+
m_expiryTime = std::chrono::system_clock::now() + std::chrono::seconds(seconds_until_expiry);
35+
m_hasExpiryTime = true;
36+
}
37+
38+
39+
} // namespace backend
40+
} // namespace collection
41+
} // namespace modsecurity
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
17+
#ifdef __cplusplus
18+
#include <string>
19+
#include <memory>
20+
#include <chrono>
21+
#endif
22+
23+
24+
#include "modsecurity/collection/collection.h"
25+
26+
#ifndef SRC_COLLECTION_DATA_H_
27+
#define SRC_COLLECTION_DATA_H_
28+
29+
#ifdef __cplusplus
30+
namespace modsecurity {
31+
namespace collection {
32+
namespace backend {
33+
34+
class CollectionData {
35+
public:
36+
CollectionData() :
37+
m_hasValue(false),
38+
m_hasExpiryTime(false) { }
39+
40+
CollectionData(const std::string &value) :
41+
m_hasValue(true),
42+
m_hasExpiryTime(false),
43+
m_value(value) { }
44+
45+
void setValue(const std::string &value) {
46+
m_value = value;
47+
m_hasValue = true;
48+
}
49+
bool hasValue() const { return m_hasValue;}
50+
const std::string& getValue() const { return m_value;}
51+
52+
void setExpiry(int32_t seconds_until_expiry);
53+
bool hasExpiry() const { return m_hasExpiryTime;}
54+
bool isExpired() const;
55+
56+
private:
57+
bool m_hasValue;
58+
bool m_hasExpiryTime;
59+
std::string m_value;
60+
std::chrono::system_clock::time_point m_expiryTime;
61+
};
62+
63+
} // namespace backend
64+
} // namespace collection
65+
} // namespace modsecurity
66+
#endif
67+
68+
#endif // SRC_COLLECTION_DATA_H_

0 commit comments

Comments
 (0)