Merge pull request #798 from bunkerity/dev

Update ModSecurity version to v3.0.11
This commit is contained in:
Théophile Diot 2023-12-07 13:53:57 +00:00 committed by GitHub
commit 2ee63c0dd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 5841 additions and 5439 deletions

View File

@ -1,5 +1,10 @@
# Changelog
## v1.5.5 - YYYY/MM/DD
- [FEATURE] Add Anonymous reporting feature
- [MISC] Updated ModSecurity to v3.0.11
## v1.5.4 - 2023/12/04
- [UI] Add an optional setup wizard for the web UI

View File

@ -15,9 +15,9 @@
},
{
"id": "modsecurity",
"name": "ModSecurity v3.0.10",
"name": "ModSecurity v3.0.11",
"url": "https://github.com/SpiderLabs/ModSecurity.git",
"commit": "ccc2d9b53632fb5088673bbaafedf0d8d4b5f1d8",
"commit": "bbde9381cbccb49ea73f6194b08b478adc53f3bc",
"post_install": "patch --forward src/deps/src/modsecurity/configure.ac src/deps/misc/modsecurity.patch && rm -rf src/deps/src/modsecurity/others/libinjection"
},
{

View File

@ -9,7 +9,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04]
os: [ubuntu-22.04]
platform: [x32, x64]
compiler: [gcc, clang]
configure:
@ -24,7 +24,6 @@ jobs:
steps:
- name: Setup Dependencies
run: |
sudo add-apt-repository --yes ppa:maxmind/ppa
sudo apt-get update -y -qq
sudo apt-get install -y libfuzzy-dev libyajl-dev libgeoip-dev liblua5.2-dev liblmdb-dev cppcheck libmaxminddb-dev libcurl4-openssl-dev libpcre2-dev pcre2-utils
- uses: actions/checkout@v2

View File

@ -1,3 +1,23 @@
v3.0.11 - 2023-Dec-06
---------------------
- Add WRDE_NOCMD to wordexp call
[Issue #3024 - @sahruldotid, @martinhsv]
- Fix: validateDTD compile fails if when libxml2 not installed
[Issue #3014 - @zangobot, @martinhsv]
- Fix memory leak of validateDTD's dtd object
[Issue #3008 - @martinhsv, @zimmerle]
- Fix memory leaks in ValidateSchema
[Issue #3005 - @martinhsv, @zimmerle]
- Add support for expirevar action
[Issue #1803, #3001 - @martinhsv]
- Fix: lmdb regex match on non-null terminated string
[Issue #2985 - @martinhsv]
- Fix memory leaks in lmdb code (new'd strings)
[Issue #2983 - @martinhsv]
- Configure: add additional name to pcre2 pkg-config list
[Issue #2939 - @agebhar1, @fzipi, @martinhsv]
v3.0.10 - 2023-Jul-25
---------------------
@ -116,7 +136,7 @@ v3.0.7 - 2022-May-30
v3.0.6 - 2021-Nov-19
-------------------------------------
--------------------
- Support configurable limit on depth of JSON parsing
[@theMiddleBlue, @martinhsv]

View File

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

View File

@ -4,7 +4,7 @@ dnl CHECK_PCRE2(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
AC_DEFUN([PROG_PCRE2], [
# Possible names for the pcre2 library/package (pkg-config)
PCRE2_POSSIBLE_LIB_NAMES="pcre2 pcre2-8"
PCRE2_POSSIBLE_LIB_NAMES="pcre2 pcre2-8 libpcre2-8"
# Possible extensions for the library
PCRE2_POSSIBLE_EXTENSIONS="so so0 la sl dll dylib so.0.0.0"

View File

@ -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
@ -47,7 +47,7 @@ class AnchoredSetVariableTranslationProxy {
VariableValue *newVariableValue = new VariableValue(name, &l->at(i)->getKey(), &l->at(i)->getKey());
const VariableValue *oldVariableValue = l->at(i);
l->at(i) = newVariableValue;
for (auto &oldOrigin : oldVariableValue->getOrigin()) {
for (const auto &oldOrigin : oldVariableValue->getOrigin()) {
std::unique_ptr<VariableOrigin> newOrigin(new VariableOrigin);
newOrigin->m_length = oldVariableValue->getKey().size();
newOrigin->m_offset = oldOrigin->m_offset - oldVariableValue->getKey().size() - 1;

View File

@ -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
@ -16,7 +16,6 @@
#ifdef __cplusplus
#include <string>
#include <iostream>
#include <unordered_map>
#include <list>
#include <vector>
@ -46,7 +45,6 @@ class Collection {
public:
explicit Collection(const std::string &a) : m_name(a) { }
virtual ~Collection() { }
virtual void store(std::string key, std::string value) = 0;
virtual bool storeOrUpdateFirst(const std::string &key,
const std::string &value) = 0;
@ -56,6 +54,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;
@ -69,21 +69,6 @@ class Collection {
variables::KeyExclusions &ke) = 0;
/* store */
virtual void store(std::string key, std::string compartment,
std::string value) {
std::string nkey = compartment + "::" + key;
store(nkey, value);
}
virtual void store(std::string key, std::string compartment,
std::string compartment2, std::string value) {
std::string nkey = compartment + "::" + compartment2 + "::" + key;
store(nkey, value);
}
/* storeOrUpdateFirst */
virtual bool storeOrUpdateFirst(const std::string &key,
std::string compartment, const std::string &value) {
@ -129,6 +114,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) {

View File

@ -190,7 +190,7 @@ namespace modsecurity {
#define MODSECURITY_MAJOR "3"
#define MODSECURITY_MINOR "0"
#define MODSECURITY_PATCHLEVEL "10"
#define MODSECURITY_PATCHLEVEL "11"
#define MODSECURITY_TAG ""
#define MODSECURITY_TAG_NUM "100"
@ -198,7 +198,7 @@ namespace modsecurity {
MODSECURITY_MINOR "." MODSECURITY_PATCHLEVEL \
MODSECURITY_TAG
#define MODSECURITY_VERSION_NUM 30100100
#define MODSECURITY_VERSION_NUM 30110100
#define MODSECURITY_CHECK_VERSION(a) (MODSECURITY_VERSION_NUM <= a)

View File

@ -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
@ -62,7 +62,7 @@ class VariableValue {
m_keyWithCollection(o->m_keyWithCollection),
m_value(o->m_value)
{
for (auto &i : o->m_orign) {
for (const auto &i : o->m_orign) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset;
origin->m_length = i->m_length;

View File

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

View File

@ -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
@ -30,7 +30,7 @@ bool RuleRemoveById::init(std::string *error) {
std::string what(m_parser_payload, 15, m_parser_payload.size() - 15);
bool added = false;
std::vector<std::string> toRemove = utils::string::ssplit(what, ' ');
for (std::string &a : toRemove) {
for (const std::string &a : toRemove) {
std::string b = modsecurity::utils::string::parserSanitizer(a);
if (b.size() == 0) {
continue;

View File

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

View File

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

View File

@ -53,9 +53,7 @@ void AnchoredSetVariable::unset() {
void AnchoredSetVariable::set(const std::string &key,
const std::string &value, size_t offset, size_t len) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
std::string *v = new std::string(value);
VariableValue *var = new VariableValue(&m_name, &key, v);
delete v;
VariableValue *var = new VariableValue(&m_name, &key, &value);
origin->m_offset = offset;
origin->m_length = len;
@ -68,9 +66,7 @@ void AnchoredSetVariable::set(const std::string &key,
void AnchoredSetVariable::set(const std::string &key,
const std::string &value, size_t offset) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
std::string *v = new std::string(value);
VariableValue *var = new VariableValue(&m_name, &key, v);
delete v;
VariableValue *var = new VariableValue(&m_name, &key, &value);
origin->m_offset = offset;
origin->m_length = value.size();

View File

@ -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
@ -289,7 +289,7 @@ bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) {
return true;
}
for (RuleMessage &i : transaction->m_rulesMessages) {
for (const RuleMessage &i : transaction->m_rulesMessages) {
if (i.m_noAuditLog == false) {
saveAnyway = true;
break;

View File

@ -0,0 +1,140 @@
/*
* 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;
}
std::string CollectionData::getSerialized() const {
std::string serialized;
if (hasValue()) {
serialized.reserve(30 + 10 + getValue().size());
} else {
serialized.reserve(16+10);
}
serialized.assign("{");
if (hasExpiry()) {
serialized.append("\"__expire_\":");
uint64_t expiryEpochSeconds = std::chrono::duration_cast<std::chrono::seconds>(m_expiryTime.time_since_epoch()).count();
serialized.append(std::to_string(expiryEpochSeconds));
if (hasValue()) {
serialized.append(",");
}
}
if (hasValue()) {
serialized.append("\"__value_\":\"");
serialized.append(getValue());
serialized.append("\"");
}
serialized.append("}");
return serialized;
}
void CollectionData::setFromSerialized(const char* serializedData, size_t length) {
const static std::string expiryPrefix("\"__expire_\":");
const static std::string valuePrefix("\"__value_\":\"");
m_hasValue = false;
m_hasExpiryTime = false;
std::string serializedString(serializedData, length);
if ((serializedString.find("{") == 0) && (serializedString.substr(serializedString.length()-1) == "}")) {
size_t currentPos = 1;
uint64_t expiryEpochSeconds = 0;
bool invalidSerializedFormat = false;
bool doneParsing = false;
// Extract the expiry time, if it exists
if (serializedString.find(expiryPrefix, currentPos) == currentPos) {
currentPos += expiryPrefix.length();
std::string expiryDigits = serializedString.substr(currentPos, 10);
if (expiryDigits.find_first_not_of("0123456789") == std::string::npos) {
expiryEpochSeconds = strtoll(expiryDigits.c_str(), NULL, 10);
} else {
invalidSerializedFormat = true;
}
currentPos += 10;
}
if ((!invalidSerializedFormat) && (expiryEpochSeconds > 0)) {
if (serializedString.find(",", currentPos) == currentPos) {
currentPos++;
} else if (currentPos == serializedString.length()-1) {
doneParsing = true;
} else {
invalidSerializedFormat = true;
}
}
if ((!invalidSerializedFormat) && (!doneParsing)) {
// Extract the value
if ((serializedString.find(valuePrefix, currentPos) == currentPos)) {
currentPos += valuePrefix.length();
size_t expectedCloseQuotePos = serializedString.length() - 2;
if ((serializedString.substr(expectedCloseQuotePos, 1) == "\"") && (expectedCloseQuotePos >= currentPos)) {
m_value = serializedString.substr(currentPos);
m_value.resize(m_value.length()-2);
m_hasValue = true;
} else {
invalidSerializedFormat = true;
}
} else {
invalidSerializedFormat = true;
}
}
// Set the object's expiry time, if we found one
if ((!invalidSerializedFormat) && (expiryEpochSeconds > 0)) {
std::chrono::seconds expiryDuration(expiryEpochSeconds);
std::chrono::system_clock::time_point expiryTimePoint(expiryDuration);
m_expiryTime = expiryTimePoint;
m_hasExpiryTime = true;
}
if (!invalidSerializedFormat) {
return;
}
}
// this is the residual case; the entire string is a simple value (not JSON-ish encoded)
// the foreseen case here is lmdb content from prior to the serialization support
m_value.assign(serializedData, length);
m_hasValue = true;
return;
}
} // namespace backend
} // namespace collection
} // namespace modsecurity

View File

@ -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 <chrono>
#endif
#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;
std::string getSerialized() const;
void setFromSerialized(const char* serializedData, size_t length);
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_

View File

@ -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
@ -15,6 +15,7 @@
#include "src/collection/backend/in_memory-per_process.h"
#include "src/collection/backend/collection_data.h"
#ifdef __cplusplus
#include <string>
@ -69,7 +70,7 @@ bool InMemoryPerProcess::updateFirst(const std::string &key,
auto range = this->equal_range(key);
for (auto it = range.first; it != range.second; ++it) {
it->second = value;
it->second.setValue(value);
pthread_mutex_unlock(&m_lock);
return true;
}
@ -84,13 +85,49 @@ void InMemoryPerProcess::del(const std::string& key) {
pthread_mutex_unlock(&m_lock);
}
void InMemoryPerProcess::delIfExpired(const std::string& key) {
pthread_mutex_lock(&m_lock);
// Double check the status while within the mutex
auto iter = this->find(key);
if ((iter != this->end()) && (iter->second.isExpired())) {
this->erase(key);
}
pthread_mutex_unlock(&m_lock);
}
void InMemoryPerProcess::setExpiry(const std::string& key, int32_t expiry_seconds) {
pthread_mutex_lock(&m_lock);
auto range = this->equal_range(key);
for (auto it = range.first; it != range.second; ++it) {
it->second.setExpiry(expiry_seconds);
pthread_mutex_unlock(&m_lock);
return;
}
// We allow an expiry value to be set for a key that has not (yet) had a value set.
auto iter = this->emplace(key, CollectionData());
iter->second.setExpiry(expiry_seconds);
pthread_mutex_unlock(&m_lock);
}
void InMemoryPerProcess::resolveSingleMatch(const std::string& var,
std::vector<const VariableValue *> *l) {
std::list<std::string> expiredVars;
auto range = this->equal_range(var);
for (auto it = range.first; it != range.second; ++it) {
l->push_back(new VariableValue(&m_name, &it->first, &it->second));
if (it->second.isExpired()) {
expiredVars.push_back(it->first);
} else if (it->second.hasValue() == false) {
// No-op. A non-expired expiry exists for the key but there is no actual value
} else {
l->push_back(new VariableValue(&m_name, &it->first, &it->second.getValue()));
}
}
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
}
@ -99,14 +136,21 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var,
std::vector<const VariableValue *> *l, variables::KeyExclusions &ke) {
size_t keySize = var.size();
l->reserve(15);
std::list<std::string> expiredVars;
if (keySize == 0) {
for (auto &i : *this) {
if (ke.toOmit(i.first)) {
continue;
}
l->insert(l->begin(), new VariableValue(&m_name, &i.first,
&i.second));
if (i.second.isExpired()) {
expiredVars.push_back(i.first);
} else if (i.second.hasValue() == false) {
// No-op. A non-expired expiry exists for the key but there is no actual value
} else {
l->insert(l->begin(), new VariableValue(&m_name, &i.first,
&i.second.getValue()));
}
}
} else {
auto range = this->equal_range(var);
@ -114,10 +158,19 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var,
if (ke.toOmit(var)) {
continue;
}
l->insert(l->begin(), new VariableValue(&m_name, &var,
&it->second));
if (it->second.isExpired()) {
expiredVars.push_back(it->first);
} else if (it->second.hasValue() == false) {
// No-op. A non-expired expiry exists for the key but there is no actual value
} else {
l->insert(l->begin(), new VariableValue(&m_name, &var,
&it->second.getValue()));
}
}
}
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
}
@ -135,6 +188,7 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var,
// var.size() - var.find(":") - 3);
//size_t keySize = col.size();
Utils::Regex r(var, true);
std::list<std::string> expiredVars;
for (const auto& x : *this) {
//if (x.first.size() <= keySize + 1) {
@ -155,7 +209,16 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var,
if (ke.toOmit(x.first)) {
continue;
}
l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second));
if (x.second.isExpired()) {
expiredVars.push_back(x.first);
} else if (x.second.hasValue() == false) {
// No-op. A non-expired expiry exists for the key but there is no actual value
} else {
l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second.getValue()));
}
}
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
}
@ -164,7 +227,13 @@ std::unique_ptr<std::string> InMemoryPerProcess::resolveFirst(
const std::string& var) {
auto range = equal_range(var);
for (auto it = range.first; it != range.second; ++it) {
return std::unique_ptr<std::string>(new std::string(it->second));
if (it->second.isExpired()) {
delIfExpired(it->second.getValue());
} else if (it->second.hasValue() == false) {
// No-op. A non-expired expiry exists for the key but there is no actual value
} else {
return std::unique_ptr<std::string>(new std::string(it->second.getValue()));
}
}
return NULL;

View File

@ -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
@ -18,6 +18,7 @@
#include <string>
#include <iostream>
#include <unordered_map>
#include <chrono>
#include <list>
#include <vector>
#include <algorithm>
@ -27,6 +28,7 @@
#include "modsecurity/variable_value.h"
#include "modsecurity/collection/collection.h"
#include "src/collection/backend/collection_data.h"
#include "src/variables/variable.h"
#ifndef SRC_COLLECTION_BACKEND_IN_MEMORY_PER_PROCESS_H_
@ -68,13 +70,13 @@ struct MyHash{
};
class InMemoryPerProcess :
public std::unordered_multimap<std::string, std::string,
public std::unordered_multimap<std::string, CollectionData,
/*std::hash<std::string>*/MyHash, MyEqual>,
public Collection {
public:
explicit InMemoryPerProcess(const std::string &name);
~InMemoryPerProcess();
void store(std::string key, std::string value) override;
void store(std::string key, std::string value);
bool storeOrUpdateFirst(const std::string &key,
const std::string &value) override;
@ -84,6 +86,10 @@ class InMemoryPerProcess :
void del(const std::string& key) override;
void delIfExpired(const std::string& key);
void setExpiry(const std::string& key, int32_t expiry_seconds) override;
std::unique_ptr<std::string> resolveFirst(const std::string& var) override;
void resolveSingleMatch(const std::string& var,
@ -95,6 +101,20 @@ class InMemoryPerProcess :
std::vector<const VariableValue *> *l,
variables::KeyExclusions &ke) override;
/* store */
virtual void store(std::string key, std::string compartment,
std::string value) {
std::string nkey = compartment + "::" + key;
store(nkey, value);
}
virtual void store(std::string key, std::string compartment,
std::string compartment2, std::string value) {
std::string nkey = compartment + "::" + compartment2 + "::" + key;
store(nkey, value);
}
private:
pthread_mutex_t m_lock;
};

View File

@ -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
@ -15,6 +15,7 @@
#include "src/collection/backend/lmdb.h"
#include "src/collection/backend/collection_data.h"
#include <sys/types.h>
#include <unistd.h>
@ -158,6 +159,7 @@ std::unique_ptr<std::string> LMDB::resolveFirst(const std::string& var) {
MDB_val mdb_value_ret;
std::unique_ptr<std::string> ret = NULL;
MDB_txn *txn = NULL;
CollectionData collectionData;
string2val(var, &mdb_key);
@ -172,17 +174,125 @@ std::unique_ptr<std::string> LMDB::resolveFirst(const std::string& var) {
goto end_get;
}
ret = std::unique_ptr<std::string>(new std::string(
reinterpret_cast<char *>(mdb_value_ret.mv_data),
mdb_value_ret.mv_size));
collectionData.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
if ((!collectionData.isExpired()) && (collectionData.hasValue())) {
ret = std::unique_ptr<std::string>(new std::string(collectionData.getValue()));
}
end_get:
mdb_txn_abort(txn);
end_txn:
// The read-only transaction is complete. Now we can do a delete if the item was expired.
if (collectionData.isExpired()) {
delIfExpired(var);
}
return ret;
}
void LMDB::setExpiry(const std::string &key, int32_t expiry_seconds) {
int rc;
MDB_txn *txn;
MDB_val mdb_key;
MDB_val mdb_value;
MDB_val mdb_value_ret;
CollectionData previous_data;
CollectionData new_data;
std::string serializedData;
string2val(key, &mdb_key);
rc = txn_begin(0, &txn);
lmdb_debug(rc, "txn", "setExpiry");
if (rc != 0) {
goto end_txn;
}
rc = mdb_get(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "get", "setExpiry");
if (rc == 0) {
previous_data.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
rc = mdb_del(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "del", "setExpiry");
if (rc != 0) {
goto end_del;
}
}
if (previous_data.hasValue()) {
new_data = previous_data;
};
new_data.setExpiry(expiry_seconds);
serializedData = new_data.getSerialized();
string2val(serializedData, &mdb_value);
rc = mdb_put(txn, m_dbi, &mdb_key, &mdb_value, 0);
lmdb_debug(rc, "put", "setExpiry");
if (rc != 0) {
goto end_put;
}
rc = mdb_txn_commit(txn);
lmdb_debug(rc, "commit", "setExpiry");
if (rc != 0) {
goto end_commit;
}
end_put:
end_del:
if (rc != 0) {
mdb_txn_abort(txn);
}
end_commit:
end_txn:
return;
}
void LMDB::delIfExpired(const std::string& key) {
MDB_txn *txn;
MDB_val mdb_key;
MDB_val mdb_value_ret;
CollectionData collectionData;
int rc = txn_begin(0, &txn);
lmdb_debug(rc, "txn", "del");
if (rc != 0) {
goto end_txn;
}
string2val(key, &mdb_key);
rc = mdb_get(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "get", "del");
if (rc != 0) {
goto end_get;
}
collectionData.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
if (collectionData.isExpired()) {
rc = mdb_del(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "del", "del");
if (rc != 0) {
goto end_del;
}
}
rc = mdb_txn_commit(txn);
lmdb_debug(rc, "commit", "del");
if (rc != 0) {
goto end_commit;
}
end_del:
end_get:
if (rc != 0) {
mdb_txn_abort(txn);
}
end_commit:
end_txn:
return;
}
bool LMDB::storeOrUpdateFirst(const std::string &key,
const std::string &value) {
int rc;
@ -190,9 +300,11 @@ bool LMDB::storeOrUpdateFirst(const std::string &key,
MDB_val mdb_key;
MDB_val mdb_value;
MDB_val mdb_value_ret;
CollectionData previous_data;
CollectionData new_data;
std::string serializedData;
string2val(key, &mdb_key);
string2val(value, &mdb_value);
rc = txn_begin(0, &txn);
lmdb_debug(rc, "txn", "storeOrUpdateFirst");
@ -203,6 +315,7 @@ bool LMDB::storeOrUpdateFirst(const std::string &key,
rc = mdb_get(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "get", "storeOrUpdateFirst");
if (rc == 0) {
previous_data.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
rc = mdb_del(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "del", "storeOrUpdateFirst");
if (rc != 0) {
@ -210,6 +323,13 @@ bool LMDB::storeOrUpdateFirst(const std::string &key,
}
}
if (previous_data.hasExpiry()) {
new_data = previous_data;
};
new_data.setValue(value);
serializedData = new_data.getSerialized();
string2val(serializedData, &mdb_value);
rc = mdb_put(txn, m_dbi, &mdb_key, &mdb_value, 0);
lmdb_debug(rc, "put", "storeOrUpdateFirst");
if (rc != 0) {
@ -241,6 +361,8 @@ void LMDB::resolveSingleMatch(const std::string& var,
MDB_val mdb_value;
MDB_val mdb_value_ret;
MDB_cursor *cursor;
CollectionData collectionData;
std::list<std::string> expiredVars;
rc = txn_begin(MDB_RDONLY, &txn);
lmdb_debug(rc, "txn", "resolveSingleMatch");
@ -253,53 +375,24 @@ void LMDB::resolveSingleMatch(const std::string& var,
mdb_cursor_open(txn, m_dbi, &cursor);
while ((rc = mdb_cursor_get(cursor, &mdb_key,
&mdb_value_ret, MDB_NEXT_DUP)) == 0) {
std::string *a = new std::string(
reinterpret_cast<char *>(mdb_value_ret.mv_data),
mdb_value_ret.mv_size);
VariableValue *v = new VariableValue(&var, a);
collectionData.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
if (collectionData.isExpired()) {
expiredVars.push_back(std::string(reinterpret_cast<char *>(mdb_key.mv_data), mdb_key.mv_size));
continue;
}
if (!collectionData.hasValue()) {
continue;
}
VariableValue *v = new VariableValue(&var, &collectionData.getValue());
l->push_back(v);
}
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
end_txn:
return;
}
void LMDB::store(std::string key, std::string value) {
MDB_val mdb_key, mdb_data;
MDB_txn *txn = NULL;
int rc;
MDB_stat mst;
rc = txn_begin(0, &txn);
lmdb_debug(rc, "txn", "store");
if (rc != 0) {
goto end_txn;
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
string2val(key, &mdb_key);
string2val(value, &mdb_data);
rc = mdb_put(txn, m_dbi, &mdb_key, &mdb_data, 0);
lmdb_debug(rc, "put", "store");
if (rc != 0) {
goto end_put;
}
rc = mdb_txn_commit(txn);
lmdb_debug(rc, "commit", "store");
if (rc != 0) {
goto end_commit;
}
end_put:
end_dbi:
if (rc != 0) {
mdb_txn_abort(txn);
}
end_commit:
end_txn:
return;
}
@ -311,6 +404,9 @@ bool LMDB::updateFirst(const std::string &key,
MDB_val mdb_key;
MDB_val mdb_value;
MDB_val mdb_value_ret;
CollectionData previous_data;
CollectionData new_data;
std::string serializedData;
rc = txn_begin(0, &txn);
lmdb_debug(rc, "txn", "updateFirst");
@ -319,7 +415,6 @@ bool LMDB::updateFirst(const std::string &key,
}
string2val(key, &mdb_key);
string2val(value, &mdb_value);
rc = mdb_get(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "get", "updateFirst");
@ -327,12 +422,20 @@ bool LMDB::updateFirst(const std::string &key,
goto end_get;
}
previous_data.setFromSerialized(reinterpret_cast<char *>(mdb_value_ret.mv_data), mdb_value_ret.mv_size);
rc = mdb_del(txn, m_dbi, &mdb_key, &mdb_value_ret);
lmdb_debug(rc, "del", "updateFirst");
if (rc != 0) {
goto end_del;
}
if (previous_data.hasExpiry()) {
new_data = previous_data;
};
new_data.setValue(value);
serializedData = new_data.getSerialized();
string2val(serializedData, &mdb_value);
rc = mdb_put(txn, m_dbi, &mdb_key, &mdb_value, 0);
lmdb_debug(rc, "put", "updateFirst");
if (rc != 0) {
@ -402,7 +505,6 @@ end_txn:
return;
}
void LMDB::resolveMultiMatches(const std::string& var,
std::vector<const VariableValue *> *l,
variables::KeyExclusions &ke) {
@ -412,6 +514,8 @@ void LMDB::resolveMultiMatches(const std::string& var,
MDB_stat mst;
size_t keySize = var.size();
MDB_cursor *cursor;
CollectionData collectionData;
std::list<std::string> expiredVars;
rc = txn_begin(MDB_RDONLY, &txn);
lmdb_debug(rc, "txn", "resolveMultiMatches");
@ -427,23 +531,36 @@ void LMDB::resolveMultiMatches(const std::string& var,
if (keySize == 0) {
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
collectionData.setFromSerialized(reinterpret_cast<char *>(data.mv_data), data.mv_size);
if (collectionData.isExpired()) {
expiredVars.push_back(std::string(reinterpret_cast<char *>(key.mv_data), key.mv_size));
continue;
}
if (!collectionData.hasValue()) {
continue;
}
std::string key_to_insert(reinterpret_cast<char *>(key.mv_data), key.mv_size);
l->insert(l->begin(), new VariableValue(
&m_name,
new std::string(reinterpret_cast<char *>(key.mv_data),
key.mv_size),
new std::string(reinterpret_cast<char *>(data.mv_data),
data.mv_size)));
&m_name, &key_to_insert, &collectionData.getValue()));
}
} else {
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
collectionData.setFromSerialized(reinterpret_cast<char *>(data.mv_data), data.mv_size);
if (collectionData.isExpired()) {
expiredVars.push_back(std::string(reinterpret_cast<char *>(key.mv_data), key.mv_size));
continue;
}
if (!collectionData.hasValue()) {
continue;
}
char *a = reinterpret_cast<char *>(key.mv_data);
if (strncmp(var.c_str(), a, keySize) == 0) {
l->insert(l->begin(), new VariableValue(
&m_name,
new std::string(reinterpret_cast<char *>(key.mv_data),
key.mv_size),
new std::string(reinterpret_cast<char *>(data.mv_data),
data.mv_size)));
std::string key_to_insert(reinterpret_cast<char *>(key.mv_data), key.mv_size);
l->insert(l->begin(), new VariableValue(&m_name, &key_to_insert, &collectionData.getValue()));
}
}
}
@ -452,6 +569,9 @@ void LMDB::resolveMultiMatches(const std::string& var,
end_cursor_open:
mdb_txn_abort(txn);
end_txn:
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
return;
}
@ -464,6 +584,8 @@ void LMDB::resolveRegularExpression(const std::string& var,
int rc;
MDB_stat mst;
MDB_cursor *cursor;
CollectionData collectionData;
std::list<std::string> expiredVars;
Utils::Regex r(var, true);
@ -480,21 +602,26 @@ void LMDB::resolveRegularExpression(const std::string& var,
}
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
char *a = reinterpret_cast<char *>(key.mv_data);
int ret = Utils::regex_search(a, r);
if (ret <= 0) {
collectionData.setFromSerialized(reinterpret_cast<char *>(data.mv_data), data.mv_size);
if (collectionData.isExpired()) {
expiredVars.push_back(std::string(reinterpret_cast<char *>(key.mv_data), key.mv_size));
continue;
}
if (ke.toOmit(std::string(reinterpret_cast<char *>(key.mv_data),
key.mv_size))) {
if (!collectionData.hasValue()) {
continue;
}
VariableValue *v = new VariableValue(
new std::string(reinterpret_cast<char *>(key.mv_data),
key.mv_size),
new std::string(reinterpret_cast<char *>(data.mv_data),
data.mv_size));
std::string key_to_insert(reinterpret_cast<char *>(key.mv_data), key.mv_size);
int ret = Utils::regex_search(key_to_insert, r);
if (ret <= 0) {
continue;
}
if (ke.toOmit(key_to_insert)) {
continue;
}
VariableValue *v = new VariableValue(&key_to_insert, &collectionData.getValue());
l->insert(l->begin(), v);
}
@ -502,6 +629,9 @@ void LMDB::resolveRegularExpression(const std::string& var,
end_cursor_open:
mdb_txn_abort(txn);
end_txn:
for (const auto& expiredVar : expiredVars) {
delIfExpired(expiredVar);
}
return;
}

View File

@ -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
@ -98,7 +98,6 @@ class LMDB :
public Collection {
public:
explicit LMDB(const std::string &name);
void store(std::string key, std::string value) override;
bool storeOrUpdateFirst(const std::string &key,
const std::string &value) override;
@ -108,6 +107,8 @@ class LMDB :
void del(const std::string& key) override;
void setExpiry(const std::string& key, int32_t expiry_seconds) override;
std::unique_ptr<std::string> resolveFirst(const std::string& var) override;
void resolveSingleMatch(const std::string& var,
@ -124,6 +125,8 @@ class LMDB :
void string2val(const std::string& str, MDB_val *val);
void inline lmdb_debug(int rc, const std::string &op, const std::string &scope);
void delIfExpired(const std::string& key);
MDB_env *m_env;
MDB_dbi m_dbi;
bool isOpen;

View File

@ -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
@ -43,25 +43,24 @@ bool ValidateDTD::init(const std::string &file, std::string *error) {
}
bool ValidateDTD::evaluate(Transaction *t, const std::string &str) {
xmlValidCtxtPtr cvp;
bool ValidateDTD::evaluate(Transaction *transaction, const std::string &str) {
m_dtd = xmlParseDTD(NULL, (const xmlChar *)m_resource.c_str());
if (m_dtd == NULL) {
XmlDtdPtrManager dtd(xmlParseDTD(NULL, (const xmlChar *)m_resource.c_str()));
if (dtd.get() == NULL) {
std::string err = std::string("XML: Failed to load DTD: ") \
+ m_resource;
ms_dbg_a(t, 4, err);
ms_dbg_a(transaction, 4, err);
return true;
}
if (t->m_xml->m_data.doc == NULL) {
ms_dbg_a(t, 4, "XML document tree could not "\
if (transaction->m_xml->m_data.doc == NULL) {
ms_dbg_a(transaction, 4, "XML document tree could not "\
"be found for DTD validation.");
return true;
}
if (t->m_xml->m_data.well_formed != 1) {
ms_dbg_a(t, 4, "XML: DTD validation failed because " \
if (transaction->m_xml->m_data.well_formed != 1) {
ms_dbg_a(transaction, 4, "XML: DTD validation failed because " \
"content is not well formed.");
return true;
}
@ -76,24 +75,24 @@ bool ValidateDTD::evaluate(Transaction *t, const std::string &str) {
}
#endif
cvp = xmlNewValidCtxt();
xmlValidCtxtPtr cvp = xmlNewValidCtxt();
if (cvp == NULL) {
ms_dbg_a(t, 4, "XML: Failed to create a validation context.");
ms_dbg_a(transaction, 4, "XML: Failed to create a validation context.");
return true;
}
/* Send validator errors/warnings to msr_log */
cvp->error = (xmlSchemaValidityErrorFunc)error_runtime;
cvp->warning = (xmlSchemaValidityErrorFunc)warn_runtime;
cvp->userData = t;
cvp->userData = transaction;
if (!xmlValidateDtd(cvp, t->m_xml->m_data.doc, m_dtd)) {
ms_dbg_a(t, 4, "XML: DTD validation failed.");
if (!xmlValidateDtd(cvp, transaction->m_xml->m_data.doc, dtd.get())) {
ms_dbg_a(transaction, 4, "XML: DTD validation failed.");
xmlFreeValidCtxt(cvp);
return true;
}
ms_dbg_a(t, 4, std::string("XML: Successfully validated " \
ms_dbg_a(transaction, 4, std::string("XML: Successfully validated " \
"payload against DTD: ") + m_resource);
xmlFreeValidCtxt(cvp);

View File

@ -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
@ -33,18 +33,31 @@
namespace modsecurity {
namespace operators {
#ifdef WITH_LIBXML2
class XmlDtdPtrManager {
public:
/** @ingroup ModSecurity_Operator */
explicit XmlDtdPtrManager(xmlDtdPtr dtd)
: m_dtd(dtd) { }
~XmlDtdPtrManager() {
if (m_dtd != NULL) {
xmlFreeDtd(m_dtd);
m_dtd = NULL;
}
}
xmlDtdPtr get() const {return m_dtd;}
private:
xmlDtdPtr m_dtd; // The resource being managed
};
#endif
class ValidateDTD : public Operator {
public:
/** @ingroup ModSecurity_Operator */
explicit ValidateDTD(std::unique_ptr<RunTimeString> param)
: Operator("ValidateDTD", std::move(param)) { }
#ifdef WITH_LIBXML2
~ValidateDTD() {
if (m_dtd != NULL) {
xmlFreeDtd(m_dtd);
m_dtd = NULL;
}
}
~ValidateDTD() { }
bool evaluate(Transaction *transaction, const std::string &str) override;
bool init(const std::string &file, std::string *error) override;
@ -89,7 +102,6 @@ class ValidateDTD : public Operator {
private:
std::string m_resource;
xmlDtdPtr m_dtd = NULL;
#endif
};

View File

@ -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
@ -39,12 +39,23 @@ bool ValidateSchema::init(const std::string &file, std::string *error) {
}
bool ValidateSchema::evaluate(Transaction *t,
bool ValidateSchema::evaluate(Transaction *transaction,
const std::string &str) {
int rc;
m_parserCtx = xmlSchemaNewParserCtxt(m_resource.c_str());
if (m_parserCtx == NULL) {
if (transaction->m_xml->m_data.doc == NULL) {
ms_dbg_a(transaction, 4, "XML document tree could not be found for " \
"schema validation.");
return true;
}
if (transaction->m_xml->m_data.well_formed != 1) {
ms_dbg_a(transaction, 4, "XML: Schema validation failed because " \
"content is not well formed.");
return true;
}
xmlSchemaParserCtxtPtr parserCtx = xmlSchemaNewParserCtxt(m_resource.c_str());
if (parserCtx == NULL) {
std::stringstream err;
err << "XML: Failed to load Schema from file: ";
err << m_resource;
@ -52,22 +63,22 @@ bool ValidateSchema::evaluate(Transaction *t,
if (m_err.empty() == false) {
err << m_err;
}
ms_dbg_a(t, 4, err.str());
ms_dbg_a(transaction, 4, err.str());
return true;
}
xmlSchemaSetParserErrors(m_parserCtx,
xmlSchemaSetParserErrors(parserCtx,
(xmlSchemaValidityErrorFunc)error_load,
(xmlSchemaValidityWarningFunc)warn_load, &m_err);
xmlThrDefSetGenericErrorFunc(m_parserCtx,
xmlThrDefSetGenericErrorFunc(parserCtx,
null_error);
xmlSetGenericErrorFunc(m_parserCtx,
xmlSetGenericErrorFunc(parserCtx,
null_error);
m_schema = xmlSchemaParse(m_parserCtx);
if (m_schema == NULL) {
xmlSchemaPtr schema = xmlSchemaParse(parserCtx);
if (schema == NULL) {
std::stringstream err;
err << "XML: Failed to load Schema: ";
err << m_resource;
@ -75,61 +86,41 @@ bool ValidateSchema::evaluate(Transaction *t,
if (m_err.empty() == false) {
err << " " << m_err;
}
ms_dbg_a(t, 4, err.str());
xmlSchemaFreeParserCtxt(m_parserCtx);
ms_dbg_a(transaction, 4, err.str());
xmlSchemaFreeParserCtxt(parserCtx);
return true;
}
m_validCtx = xmlSchemaNewValidCtxt(m_schema);
if (m_validCtx == NULL) {
xmlSchemaValidCtxtPtr validCtx = xmlSchemaNewValidCtxt(schema);
if (validCtx == NULL) {
std::stringstream err("XML: Failed to create validation context.");
if (m_err.empty() == false) {
err << " " << m_err;
}
ms_dbg_a(t, 4, err.str());
ms_dbg_a(transaction, 4, err.str());
xmlSchemaFree(schema);
xmlSchemaFreeParserCtxt(parserCtx);
return true;
}
/* Send validator errors/warnings to msr_log */
xmlSchemaSetValidErrors(m_validCtx,
xmlSchemaSetValidErrors(validCtx,
(xmlSchemaValidityErrorFunc)error_runtime,
(xmlSchemaValidityWarningFunc)warn_runtime, t);
(xmlSchemaValidityWarningFunc)warn_runtime, transaction);
if (t->m_xml->m_data.doc == NULL) {
ms_dbg_a(t, 4, "XML document tree could not be found for " \
"schema validation.");
return true;
}
int rc = xmlSchemaValidateDoc(validCtx, transaction->m_xml->m_data.doc);
if (t->m_xml->m_data.well_formed != 1) {
ms_dbg_a(t, 4, "XML: Schema validation failed because " \
"content is not well formed.");
return true;
}
/* Make sure there were no other generic processing errors */
/*
if (msr->msc_reqbody_error) {
ms_dbg_a(t, 4, "XML: Schema validation could not proceed due to previous"
" processing errors.");
return true;
}
*/
rc = xmlSchemaValidateDoc(m_validCtx, t->m_xml->m_data.doc);
xmlSchemaFreeValidCtxt(validCtx);
xmlSchemaFree(schema);
xmlSchemaFreeParserCtxt(parserCtx);
if (rc != 0) {
ms_dbg_a(t, 4, "XML: Schema validation failed.");
xmlSchemaFree(m_schema);
xmlSchemaFreeParserCtxt(m_parserCtx);
ms_dbg_a(transaction, 4, "XML: Schema validation failed.");
return true; /* No match. */
} else {
ms_dbg_a(transaction, 4, "XML: Successfully validated payload against " \
"Schema: " + m_resource);
return false;
}
ms_dbg_a(t, 4, "XML: Successfully validated payload against " \
"Schema: " + m_resource);
xmlSchemaFree(m_schema);
xmlSchemaFreeParserCtxt(m_parserCtx);
return false;
}
#endif

View File

@ -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
@ -36,27 +36,10 @@ namespace operators {
class ValidateSchema : public Operator {
public:
/** @ingroup ModSecurity_Operator */
#ifndef WITH_LIBXML2
explicit ValidateSchema(std::unique_ptr<RunTimeString> param)
: Operator("ValidateSchema", std::move(param)) { }
#else
explicit ValidateSchema(std::unique_ptr<RunTimeString> param)
: Operator("ValidateSchema", std::move(param)),
m_parserCtx(NULL),
m_validCtx(NULL),
m_schema(NULL) { }
~ValidateSchema() {
/*
if (m_schema != NULL) {
xmlSchemaFree(m_schema);
m_schema = NULL;
}
*/
if (m_validCtx != NULL) {
xmlSchemaFreeValidCtxt(m_validCtx);
m_validCtx = NULL;
}
}
~ValidateSchema() { }
#ifdef WITH_LIBXML2
bool evaluate(Transaction *transaction, const std::string &str) override;
bool init(const std::string &file, std::string *error) override;
@ -129,9 +112,6 @@ class ValidateSchema : public Operator {
}
private:
xmlSchemaParserCtxtPtr m_parserCtx;
xmlSchemaValidCtxtPtr m_validCtx;
xmlSchemaPtr m_schema;
std::string m_resource;
std::string m_err;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -83,6 +83,7 @@ class Driver;
#include "src/actions/disruptive/redirect.h"
#include "src/actions/init_col.h"
#include "src/actions/exec.h"
#include "src/actions/expire_var.h"
#include "src/actions/log_data.h"
#include "src/actions/log.h"
#include "src/actions/maturity.h"
@ -354,7 +355,7 @@ using namespace modsecurity::operators;
a = std::move(c);
#line 358 "seclang-parser.hh"
#line 359 "seclang-parser.hh"
# include <cassert>
# include <cstdlib> // std::abort
@ -494,7 +495,7 @@ using namespace modsecurity::operators;
#endif
namespace yy {
#line 498 "seclang-parser.hh"
#line 499 "seclang-parser.hh"
@ -8069,7 +8070,7 @@ switch (yykind)
/// Constants.
enum
{
yylast_ = 3372, ///< Last index in yytable_.
yylast_ = 3373, ///< Last index in yytable_.
yynnts_ = 16, ///< Number of nonterminal symbols.
yyfinal_ = 341 ///< Termination state number.
};
@ -8731,7 +8732,7 @@ switch (yykind)
} // yy
#line 8735 "seclang-parser.hh"
#line 8736 "seclang-parser.hh"

View File

@ -44,6 +44,7 @@ class Driver;
#include "src/actions/disruptive/redirect.h"
#include "src/actions/init_col.h"
#include "src/actions/exec.h"
#include "src/actions/expire_var.h"
#include "src/actions/log_data.h"
#include "src/actions/log.h"
#include "src/actions/maturity.h"
@ -2744,10 +2745,9 @@ act:
{
ACTION_CONTAINER($$, new actions::Exec($1));
}
| ACTION_EXPIRE_VAR
| ACTION_EXPIRE_VAR run_time_string
{
//ACTION_NOT_SUPPORTED("ExpireVar", @0);
ACTION_CONTAINER($$, new actions::Action($1));
ACTION_CONTAINER($$, new actions::ExpireVar(std::move($2)));
}
| ACTION_ID
{

File diff suppressed because it is too large Load Diff

View File

@ -545,10 +545,7 @@ EQUALS_MINUS (?i:=\-)
{ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG}[=]{REMOVE_RULE_BY} { return p::make_ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG(yytext, *driver.loc.back()); }
{ACTION_EXEC}:'{VAR_FREE_TEXT_QUOTE}' { return p::make_ACTION_EXEC(yytext, *driver.loc.back()); }
{ACTION_EXEC}:{VAR_FREE_TEXT_SPACE_COMMA} { return p::make_ACTION_EXEC(yytext, *driver.loc.back()); }
{ACTION_EXPIRE_VAR}:'{VAR_FREE_TEXT_QUOTE}={VAR_FREE_TEXT_QUOTE}' { return p::make_ACTION_EXPIRE_VAR(yytext, *driver.loc.back()); }
{ACTION_EXPIRE_VAR}:'{VAR_FREE_TEXT_QUOTE}' { return p::make_ACTION_EXPIRE_VAR(yytext, *driver.loc.back()); }
{ACTION_EXPIRE_VAR}:{VAR_FREE_TEXT_SPACE_COMMA} { return p::make_ACTION_EXPIRE_VAR(yytext, *driver.loc.back()); }
{ACTION_EXPIRE_VAR}:{VAR_FREE_TEXT_SPACE}={VAR_FREE_TEXT_SPACE_COMMA} { return p::make_ACTION_EXPIRE_VAR(yytext, *driver.loc.back()); }
{ACTION_EXPIRE_VAR}: { BEGIN(EXPECTING_ACTION_PREDICATE); return p::make_ACTION_EXPIRE_VAR(yytext, *driver.loc.back()); }
{ACTION_INITCOL}:{COL_NAME}= { BEGIN(EXPECTING_ACTION_PREDICATE); return p::make_ACTION_INITCOL(yytext, *driver.loc.back()); }
{ACTION_MATURITY}:'{FREE_TEXT_QUOTE}' { return p::make_ACTION_MATURITY(yytext, *driver.loc.back()); }
{ACTION_MATURITY}:{FREE_TEXT_QUOTE} { return p::make_ACTION_MATURITY(yytext, *driver.loc.back()); }

View File

@ -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
@ -38,7 +38,7 @@ std::string RuleMessage::_details(const RuleMessage *rm) {
msg.append(" [maturity \"" + std::to_string(rm->m_maturity) + "\"]");
msg.append(" [accuracy \"" + std::to_string(rm->m_accuracy) + "\"]");
for (auto &a : rm->m_tags) {
for (const auto &a : rm->m_tags) {
msg.append(" [tag \"" + utils::string::toHexIfNeeded(a, true) + "\"]");
}

View File

@ -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
@ -228,7 +228,7 @@ bool RuleWithOperator::evaluate(Transaction *trans,
// FIXME: Make a class runTimeException to handle this cases.
for (auto &i : trans->m_ruleRemoveById) {
for (const auto &i : trans->m_ruleRemoveById) {
if (m_ruleId != i) {
continue;
}
@ -236,7 +236,7 @@ bool RuleWithOperator::evaluate(Transaction *trans,
" was skipped due to a ruleRemoveById action...");
return true;
}
for (auto &i : trans->m_ruleRemoveByIdRange) {
for (const auto &i : trans->m_ruleRemoveByIdRange) {
if (!(i.first <= m_ruleId && i.second >= m_ruleId)) {
continue;
}

View File

@ -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
@ -122,7 +122,7 @@ bool RulesExceptions::loadUpdateTargetById(double id,
bool RulesExceptions::load(const std::string &a, std::string *error) {
bool added = false;
std::vector<std::string> toRemove = utils::string::ssplit(a, ' ');
for (std::string &r : toRemove) {
for (const std::string &r : toRemove) {
std::string b = modsecurity::utils::string::parserSanitizer(r);
if (b.size() == 0) {
continue;

View File

@ -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
@ -162,7 +162,7 @@ int RulesSet::evaluate(int phase, Transaction *t) {
}
bool remove_rule = false;
if (ruleWithActions && m_exceptions.m_remove_rule_by_msg.empty() == false) {
for (auto &z : m_exceptions.m_remove_rule_by_msg) {
for (const auto &z : m_exceptions.m_remove_rule_by_msg) {
if (ruleWithActions->containsMsg(z, t) == true) {
ms_dbg_a(t, 9, "Skipped rule id '" \
+ ruleWithActions->getReference() \
@ -177,7 +177,7 @@ int RulesSet::evaluate(int phase, Transaction *t) {
}
if (ruleWithActions && m_exceptions.m_remove_rule_by_tag.empty() == false) {
for (auto &z : m_exceptions.m_remove_rule_by_tag) {
for (const auto &z : m_exceptions.m_remove_rule_by_tag) {
if (ruleWithActions->containsTag(z, t) == true) {
ms_dbg_a(t, 9, "Skipped rule id '" \
+ ruleWithActions->getReference() \
@ -193,7 +193,7 @@ int RulesSet::evaluate(int phase, Transaction *t) {
if (ruleWithActions) {
for (auto &z : t->m_ruleRemoveByTag) {
for (const auto &z : t->m_ruleRemoveByTag) {
if (ruleWithActions->containsTag(z, t) == true) {
ms_dbg_a(t, 9, "Skipped rule id '" \
+ ruleWithActions->getReference() \

View File

@ -1242,7 +1242,7 @@ int Transaction::processResponseBody() {
return true;
}
std::set<std::string> &bi = \
const std::set<std::string> &bi = \
m_rules->m_responseBodyTypeToBeInspected.m_value;
auto t = bi.find(m_variableResponseContentType.m_value);
if (t == bi.end()

View File

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

View File

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

View File

@ -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
@ -130,6 +130,7 @@ std::list<std::string> expandEnv(const std::string& var, int flags) {
for (char** exp = p.gl_pathv; *exp; ++exp) {
#else
wordexp_t p;
flags = flags | WRDE_NOCMD;
if (wordexp(var.c_str(), &p, flags) == false) {
if (p.we_wordc) {
for (char** exp = p.we_wordv; *exp; ++exp) {

View File

@ -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
@ -13,7 +13,6 @@
*
*/
#include <iostream>
#include <list>
#include <memory>
#include <string>
@ -106,6 +105,12 @@ class Global_DynamicElement : public Variable {
t->m_rules->m_secWebAppId.m_value);
}
static void setExpiry(Transaction *t, const std::string &k, int32_t expiry_seconds) {
t->m_collections.m_global_collection->setExpiry(k,
t->m_collections.m_global_collection_key,
t->m_rules->m_secWebAppId.m_value, expiry_seconds);
}
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
const std::string &value) {
t->m_collections.m_global_collection->storeOrUpdateFirst(

View File

@ -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
@ -13,7 +13,6 @@
*
*/
#include <iostream>
#include <list>
#include <memory>
#include <string>
@ -105,6 +104,12 @@ class Ip_DynamicElement : public Variable {
t->m_rules->m_secWebAppId.m_value);
}
static void setExpiry(Transaction *t, const std::string &k, int32_t expiry_seconds) {
t->m_collections.m_ip_collection->setExpiry(k,
t->m_collections.m_ip_collection_key,
t->m_rules->m_secWebAppId.m_value, expiry_seconds);
}
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
const std::string &value) {
t->m_collections.m_ip_collection->storeOrUpdateFirst(

View File

@ -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
@ -69,7 +69,7 @@ void RemoteUser::evaluate(Transaction *transaction,
var = new VariableValue(&l2->at(0)->getKeyWithCollection(),
&transaction->m_variableRemoteUser);
for (auto &i : l2->at(0)->getOrigin()) {
for (const auto &i : l2->at(0)->getOrigin()) {
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
origin->m_offset = i->m_offset;
origin->m_length = i->m_length;

View File

@ -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
@ -13,7 +13,6 @@
*
*/
#include <iostream>
#include <list>
#include <memory>
#include <string>
@ -105,6 +104,13 @@ class Resource_DynamicElement : public Variable {
t->m_rules->m_secWebAppId.m_value);
}
static void setExpiry(Transaction *t, const std::string &k, int32_t expiry_seconds) {
t->m_collections.m_resource_collection->setExpiry(k,
t->m_collections.m_resource_collection_key,
t->m_rules->m_secWebAppId.m_value, expiry_seconds);
}
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
const std::string &value) {
t->m_collections.m_resource_collection->storeOrUpdateFirst(

View File

@ -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
@ -13,7 +13,6 @@
*
*/
#include <iostream>
#include <list>
#include <memory>
#include <string>
@ -105,6 +104,12 @@ class Session_DynamicElement : public Variable {
t->m_collections.m_ip_collection_key);
}
static void setExpiry(Transaction *t, const std::string &k, int32_t expiry_seconds) {
t->m_collections.m_session_collection->setExpiry(k,
t->m_collections.m_session_collection_key,
t->m_rules->m_secWebAppId.m_value, expiry_seconds);
}
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
const std::string &value) {
t->m_collections.m_session_collection->storeOrUpdateFirst(

View File

@ -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
@ -13,7 +13,6 @@
*
*/
#include <iostream>
#include <list>
#include <memory>
#include <string>
@ -105,6 +104,12 @@ class User_DynamicElement : public Variable {
t->m_rules->m_secWebAppId.m_value);
}
static void setExpiry(Transaction *t, const std::string &k, int32_t expiry_seconds) {
t->m_collections.m_user_collection->setExpiry(k,
t->m_collections.m_user_collection_key,
t->m_rules->m_secWebAppId.m_value, expiry_seconds);
}
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
const std::string &value) {
t->m_collections.m_user_collection->storeOrUpdateFirst(

View File

@ -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
@ -83,7 +83,7 @@ std::string operator+(const std::string &a, Variable *v) {
std::string operator+(const std::string &a, Variables *v) {
std::string test;
for (auto &b : *v) {
for (const auto &b : *v) {
if (test.empty()) {
test = std::string("") + b;
} else {

View File

@ -49,7 +49,6 @@ functionStatic:src/operators/geo_lookup.h:35
duplicateBreak:src/operators/validate_utf8_encoding.cc
syntaxError:src/transaction.cc:62
noConstructor:src/variables/variable.h:152
duplicateBranch:src/request_body_processor/multipart.cc:93
danglingTempReference:src/modsecurity.cc:206
knownConditionTrueFalse:src/operators/validate_url_encoding.cc:77
knownConditionTrueFalse:src/operators/verify_svnr.cc:87
@ -74,10 +73,13 @@ variableScope:src/operators/rx_global.cc
noExplicitConstructor:seclang-parser.hh
constParameter:seclang-parser.hh
accessMoved:seclang-parser.hh
returnTempReference:seclang-parser.hh
unreadVariable:src/operators/rx.cc
unreadVariable:src/operators/rx_global.cc
noExplicitConstructor:src/collection/backend/collection_data.h
stlIfStrFind:src/collection/backend/collection_data.cc
unusedFunction
missingIncludeSystem
@ -94,7 +96,6 @@ cstyleCast
functionStatic
shadowFunction
constVariable
stlcstrConstructor
stlcstrStream
uselessCallsSubstr

View File

@ -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
@ -114,8 +114,8 @@ int main(int argc, char **argv) {
}
std::cout << " Operators" << std::endl;
for (auto &z : operators) {
auto &s = z.second;
for (const auto &z : operators) {
const auto &s = z.second;
std::cout << " " << std::left << std::setw(20) << z.first;
std::cout << std::right << std::setw(4) << s;
std::cout << std::endl;

View File

@ -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
@ -540,7 +540,7 @@ int main(int argc, char **argv) {
}
ModSecurityTestResults<RegressionTestResult> res;
for (std::string &a : keyList) {
for (const std::string &a : keyList) {
test_number++;
if ((test.m_test_number == 0)
|| (test_number == test.m_test_number)) {

View File

@ -0,0 +1,126 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing expirevar action (1/x) - ip, expire later",
"expected":{
"debug_log": "Saving msg: mycount1 is 100"
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*"
},
"uri":"/?key=value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecAction \"initcol:ip='127.0.0.1',id:5000,phase:1\"",
"SecRule ARGS \"@rx value\" \"id:'5001',phase:2,setvar:ip.mycount1=100,expirevar:ip.mycount1=60,pass\"",
"SecRule &IP:mycount1 \"@eq 1\" \"id:'5002',phase:2,pass,log,msg:'mycount1 is %{ip.mycount1}'\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing expirevar action (2/x) - ip, expire immediately",
"expected":{
"debug_log": "Saving msg: mycount1 is "
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*"
},
"uri":"/?key=value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecAction \"initcol:ip='127.0.0.1',id:5010,phase:1\"",
"SecRule ARGS \"@rx value\" \"id:'5011',phase:2,setvar:ip.mycount1=100,expirevar:ip.mycount1=0,pass\"",
"SecRule &IP:mycount1 \"@eq 0\" \"id:'5012',phase:2,pass,log,msg:'mycount1 is %{ip.mycount1}'\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing expirevar action (3/x) session, expire later",
"expected":{
"debug_log": "Saving msg: mycount1 is 12"
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*"
},
"uri":"/?key=value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@rx .\" \"id:5150,phase:2,pass,setsid:sess1234\"",
"SecRule ARGS \"@rx value\" \"id:5151,phase:2,pass,setvar:session.mycount1=12,expirevar:session.mycount1=30\"",
"SecRule &SESSION:mycount1 \"@eq 1\" \"id:'5152',phase:2,pass,log,msg:'mycount1 is %{session.mycount1}'\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing expirevar action (4/x) session, expire immediately",
"expected":{
"debug_log": "Saving msg: mycount1 is"
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*"
},
"uri":"/?key=value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@rx .\" \"id:5150,phase:2,pass,setsid:sess1234\"",
"SecRule ARGS \"@rx value\" \"id:5151,phase:2,pass,setvar:session.mycount1=12,expirevar:session.mycount1=0\"",
"SecRule &SESSION:mycount1 \"@eq 0\" \"id:'5152',phase:2,pass,log,msg:'mycount1 is %{session.mycount1}'\""
]
}
]

View File

@ -25,7 +25,7 @@
"Pragma":"no-cache",
"Cache-Control":"no-cache"
},
"uri":"\/test.pl?id_a= test &id_b=test2&nah=nops",
"uri":"\/test.pl?id_a=test&nah=nops",
"method":"GET",
"http_version":1.1,
"body":""
@ -48,12 +48,15 @@
},
"expected":{
"audit_log":"",
"debug_log":"T \\(0\\) t:lowercase: \"test2\"",
"error_log":""
"debug_log":"Saving variable: IP:nah with value: nops",
"error_log":"",
"http_code":200
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS:/^id_/ \"@contains nops\" \"id:1,t:lowercase,block,status:404\""
"SecRule ARGS:/^id_/ \"@contains test\" \"id:1,phase:2,t:lowercase,initcol:ip=%{REMOTE_ADDR}\"",
"SecRule ARGS:/^id_/ \"@contains test\" \"id:2,phase:2,t:lowercase,setvar:IP.nah=nops\"",
"SecRule IP:/id_a$/ \"rx .\" \"id:3,phase:2,deny,status:403\""
]
},
{
@ -82,7 +85,7 @@
"Pragma":"no-cache",
"Cache-Control":"no-cache"
},
"uri":"\/test.pl?id_a= test &id_b=test2&nah=nops",
"uri":"\/test.pl?id_a=test&nah=nops",
"method":"GET",
"http_version":1.1,
"body":""
@ -105,15 +108,14 @@
},
"expected":{
"audit_log":"",
"debug_log":"Saving variable: IP:nah with value: nops",
"error_log":""
"debug_log":"Saving variable: IP:id_a with value: nops",
"http_code":403
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS:/^id_/ \"@contains test\" \"id:1,t:lowercase,initcol:ip=%{REMOTE_ADDR},setvar:IP.id_a=test\"",
"SecRule ARGS:/^id_/ \"@contains test\" \"id:3,t:lowercase,setvar:IP.nah=nops\"",
"SecRule IP:/^id_/ \"@contains test\" \"id:2,t:lowercase,initcol:ip=%{REMOTE_ADDR}\"",
"SecRule IP:/^id_/ \"@contains nops\" \"id:4,t:lowercase,block,status:404\""
"SecRule ARGS:/^id_/ \"@contains test\" \"id:11,phase:2,t:lowercase,initcol:ip=%{REMOTE_ADDR}\"",
"SecRule ARGS:/^id_/ \"@contains test\" \"id:12,phase:2,t:lowercase,setvar:IP.id_a=nops\"",
"SecRule IP:/id_a$/ \"@contains nops\" \"id:13,phase:2,deny,status:403\""
]
}
]

View File

@ -73,7 +73,7 @@
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS:Content-Type \"^(?:application(?:/soap\+|/)|text/)xml\" \"id:500005,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
"SecRule REQUEST_HEADERS:Content-Type \"^(?:application(?:/soap\\+|/)|text/)xml\" \"id:500005,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
"SecRule REQBODY_PROCESSOR \"@contains test\" \"id:1,pass,phase:2,t:trim\""
]
},

View File

@ -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
@ -168,7 +168,7 @@ int main(int argc, char **argv) {
if (r.size() == 0) {
std::cout << KGRN << "0 tests failed.";
} else {
for (auto &i : r) {
for (const auto &i : r) {
if (i->skipped == true) {
skp++;
}
@ -203,7 +203,7 @@ int main(int argc, char **argv) {
std::cout << KGRN << "All tests passed" << RESET << std::endl;
} else {
int skp = 0;
for (auto &i : results) {
for (const auto &i : results) {
if (i->skipped == true) {
skp++;
}