Merge pull request #798 from bunkerity/dev
Update ModSecurity version to v3.0.11
This commit is contained in:
commit
2ee63c0dd8
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
@ -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()); }
|
||||
|
|
|
@ -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) + "\"]");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() \
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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}'\""
|
||||
]
|
||||
}
|
||||
]
|
|
@ -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\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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\""
|
||||
]
|
||||
},
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue