Skip to content

Commit

Permalink
Support expirevar for in-memory collection
Browse files Browse the repository at this point in the history
  • Loading branch information
martinhsv committed Sep 29, 2023
1 parent 135d1fa commit a8d535b
Show file tree
Hide file tree
Showing 23 changed files with 5,171 additions and 5,061 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_id.json
TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json
TESTS+=test/test-cases/regression/action-disruptive.json
TESTS+=test/test-cases/regression/action-exec.json
TESTS+=test/test-cases/regression/action-expirevar.json
TESTS+=test/test-cases/regression/action-id.json
TESTS+=test/test-cases/regression/action-initcol.json
TESTS+=test/test-cases/regression/action-msg.json
Expand Down
20 changes: 18 additions & 2 deletions headers/modsecurity/collection/collection.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
* Copyright (c) 2015 - 2023 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
Expand All @@ -16,7 +16,6 @@

#ifdef __cplusplus
#include <string>
#include <iostream>
#include <unordered_map>
#include <list>
#include <vector>
Expand Down Expand Up @@ -56,6 +55,8 @@ class Collection {

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

virtual void setExpiry(const std::string& key, int32_t expiry_seconds) = 0;

virtual std::unique_ptr<std::string> resolveFirst(
const std::string& var) = 0;

Expand Down Expand Up @@ -129,6 +130,21 @@ class Collection {
}


/* setExpiry */
virtual void setExpiry(const std::string& key, std::string compartment,
int32_t expiry_seconds) {
std::string nkey = compartment + "::" + key;
setExpiry(nkey, expiry_seconds);
}


virtual void setExpiry(const std::string& key, std::string compartment,
std::string compartment2, int32_t expiry_seconds) {
std::string nkey = compartment + "::" + compartment2 + "::" + key;
setExpiry(nkey, expiry_seconds);
}


/* resolveFirst */
virtual std::unique_ptr<std::string> resolveFirst(const std::string& var,
std::string compartment) {
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ ACTIONS = \
actions/disruptive/redirect.cc \
actions/disruptive/pass.cc \
actions/exec.cc \
actions/expire_var.cc \
actions/init_col.cc \
actions/log.cc \
actions/log_data.cc \
Expand Down Expand Up @@ -259,6 +260,7 @@ UTILS = \

COLLECTION = \
collection/collections.cc \
collection/backend/collection_data.cc \
collection/backend/in_memory-per_process.cc \
collection/backend/lmdb.cc

Expand Down
95 changes: 95 additions & 0 deletions src/actions/expire_var.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2023 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 "src/actions/expire_var.h"

#include <string>

#include "modsecurity/rules_set.h"
#include "modsecurity/transaction.h"
#include "modsecurity/rule.h"
#include "src/utils/string.h"
#include "src/variables/global.h"
#include "src/variables/ip.h"
#include "src/variables/resource.h"
#include "src/variables/session.h"
#include "src/variables/user.h"
#include "src/variables/variable.h"

namespace modsecurity {
namespace actions {


bool ExpireVar::init(std::string *error) {
return true;
}


bool ExpireVar::evaluate(RuleWithActions *rule, Transaction *t) {

std::string expireExpressionExpanded(m_string->evaluate(t));

std::string fully_qualified_var;
int expirySeconds = 0;
size_t posEquals = expireExpressionExpanded.find("=");
if (posEquals == std::string::npos) {
fully_qualified_var = expireExpressionExpanded;
} else {
fully_qualified_var = expireExpressionExpanded.substr(0, posEquals);
std::string expiry = expireExpressionExpanded.substr(posEquals+1);
if (expiry.find_first_not_of("0123456789") == std::string::npos) {
expirySeconds = atoi(expiry.c_str());
} else {
ms_dbg_a(t, 5, "Non-numeric expiry seconds found in expirevar expression.");
return true;
}
}

size_t posDot = fully_qualified_var.find(".");
if (posDot == std::string::npos) {
ms_dbg_a(t, 5, "No collection found in expirevar expression.");
return true;
}

std::string collection = fully_qualified_var.substr(0, posDot);
std::string variable_name = fully_qualified_var.substr(posDot+1);
std::unique_ptr<RunTimeString> runTimeString(new RunTimeString());
runTimeString->appendText(fully_qualified_var);

if (collection == "ip") {
std::unique_ptr<modsecurity::variables::Ip_DynamicElement> ip_dynamicElement(new modsecurity::variables::Ip_DynamicElement(std::move(runTimeString)));
ip_dynamicElement->setExpiry(t, variable_name, expirySeconds);
} else if (collection == "global") {
std::unique_ptr<modsecurity::variables::Global_DynamicElement> global_dynamicElement(new modsecurity::variables::Global_DynamicElement(std::move(runTimeString)));
global_dynamicElement->setExpiry(t, variable_name, expirySeconds);
} else if (collection == "resource") {
std::unique_ptr<modsecurity::variables::Resource_DynamicElement> resource_dynamicElement(new modsecurity::variables::Resource_DynamicElement(std::move(runTimeString)));
resource_dynamicElement->setExpiry(t, variable_name, expirySeconds);
} else if (collection == "session") {
std::unique_ptr<modsecurity::variables::Session_DynamicElement> session_dynamicElement(new modsecurity::variables::Session_DynamicElement(std::move(runTimeString)));
session_dynamicElement->setExpiry(t, variable_name, expirySeconds);
} else if (collection == "user") {
std::unique_ptr<modsecurity::variables::User_DynamicElement> user_dynamicElement(new modsecurity::variables::User_DynamicElement(std::move(runTimeString)));
user_dynamicElement->setExpiry(t, variable_name, expirySeconds);
} else {
ms_dbg_a(t, 5, "Invalid collection found in expirevar expression: collection must be `ip', `global', `resource', `user' or `session'");
}
ms_dbg_a(t, 9, "Setting variable `" + variable_name + "' to expire in " + std::to_string(expirySeconds) + " seconds.");

return true;
}

} // namespace actions
} // namespace modsecurity
54 changes: 54 additions & 0 deletions src/actions/expire_var.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2023 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 <memory>
#include <string>
#include <utility>

#include "modsecurity/actions/action.h"
#include "src/run_time_string.h"

#ifndef SRC_ACTIONS_EXPIRE_VAR_H_
#define SRC_ACTIONS_EXPIRE_VAR_H_

class Transaction;

namespace modsecurity {
class Transaction;
class RuleWithOperator;

namespace actions {

class ExpireVar : public Action {
public:
explicit ExpireVar(const std::string &action) : Action(action) { }

explicit ExpireVar(std::unique_ptr<RunTimeString> z)
: Action("expirevar", RunTimeOnlyIfMatchKind),
m_string(std::move(z)) { }

bool evaluate(RuleWithActions *rule, Transaction *transaction) override;
bool init(std::string *error) override;

private:

std::unique_ptr<RunTimeString> m_string;
};

} // namespace actions
} // namespace modsecurity


#endif // SRC_ACTIONS_EXPIRE_VAR_H_
41 changes: 41 additions & 0 deletions src/collection/backend/collection_data.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2023 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 "src/collection/backend/collection_data.h"


namespace modsecurity {
namespace collection {
namespace backend {


bool CollectionData::isExpired() const {
if (m_hasExpiryTime == false) {
return false;
}
auto now = std::chrono::system_clock::now();
return (now >= m_expiryTime);
}


void CollectionData::setExpiry(int32_t seconds_until_expiry) {
m_expiryTime = std::chrono::system_clock::now() + std::chrono::seconds(seconds_until_expiry);
m_hasExpiryTime = true;
}


} // namespace backend
} // namespace collection
} // namespace modsecurity
68 changes: 68 additions & 0 deletions src/collection/backend/collection_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2023 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.
*
*/


#ifdef __cplusplus
#include <string>
#include <memory>
#include <chrono>
#endif


#include "modsecurity/collection/collection.h"

#ifndef SRC_COLLECTION_DATA_H_
#define SRC_COLLECTION_DATA_H_

#ifdef __cplusplus
namespace modsecurity {
namespace collection {
namespace backend {

class CollectionData {
public:
CollectionData() :
m_hasValue(false),
m_hasExpiryTime(false) { }

CollectionData(const std::string &value) :
m_hasValue(true),
m_hasExpiryTime(false),
m_value(value) { }

void setValue(const std::string &value) {
m_value = value;
m_hasValue = true;
}
bool hasValue() const { return m_hasValue;}
const std::string& getValue() const { return m_value;}

void setExpiry(int32_t seconds_until_expiry);
bool hasExpiry() const { return m_hasExpiryTime;}
bool isExpired() const;

private:
bool m_hasValue;
bool m_hasExpiryTime;
std::string m_value;
std::chrono::system_clock::time_point m_expiryTime;
};

} // namespace backend
} // namespace collection
} // namespace modsecurity
#endif

#endif // SRC_COLLECTION_DATA_H_
Loading

0 comments on commit a8d535b

Please sign in to comment.