diff --git a/headers/modsecurity/collection/collection.h b/headers/modsecurity/collection/collection.h index 30bd5ff2..a89ad984 100644 --- a/headers/modsecurity/collection/collection.h +++ b/headers/modsecurity/collection/collection.h @@ -51,6 +51,7 @@ class Collection { virtual void del(const std::string& key) = 0; virtual std::string* resolveFirst(const std::string& var) = 0; + virtual std::string resolveFirstCopy(const std::string& var) = 0; virtual void resolveSingleMatch(const std::string& var, std::vector *l) = 0; @@ -89,6 +90,12 @@ class Collection { return resolveFirst(nkey); } + virtual std::string resolveFirstCopy(const std::string& var, + std::string compartment) { + std::string nkey = compartment + "::" + var; + return resolveFirstCopy(nkey); + } + virtual void resolveSingleMatch(const std::string& var, std::string compartment, std::vector *l) { std::string nkey = compartment + "::" + var; @@ -102,12 +109,10 @@ class Collection { } virtual void resolveRegularExpression(const std::string& var, - std::string compartment, - std::vector *l) { + std::string compartment, std::vector *l) { std::string nkey = compartment + "::" + var; resolveRegularExpression(nkey, l); } - }; } // namespace collection diff --git a/headers/modsecurity/collection/collections.h b/headers/modsecurity/collection/collections.h index 0cb408f7..b8657a4f 100644 --- a/headers/modsecurity/collection/collections.h +++ b/headers/modsecurity/collection/collections.h @@ -59,6 +59,9 @@ class Collections : std::string* resolveFirst(const std::string& var); std::string* resolveFirst(const std::string& collectionName, const std::string& var); + std::string resolveFirstCopy(const std::string& var); + std::string resolveFirstCopy(const std::string& collectionName, + const std::string& var); void resolveSingleMatch(const std::string& var, std::vector *l); diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 9598cee6..02738dd9 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -109,14 +109,14 @@ bool SetVar::evaluate(Rule *rule, Transaction *transm_parser_payload) { } try { - std::string *resolvedValue = - transm_parser_payload->m_collections.resolveFirst( + std::string resolvedValue = + transm_parser_payload->m_collections.resolveFirstCopy( m_collectionName, m_variableNameExpanded); - if (resolvedValue == NULL) { + if (resolvedValue.empty()) { value = 0; } else { - value = stoi(*resolvedValue); + value = stoi(resolvedValue); } } catch (...) { value = 0; diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index bffa1866..85583d8d 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -123,6 +123,17 @@ std::string* InMemoryPerProcess::resolveFirst(const std::string& var) { } +std::string InMemoryPerProcess::resolveFirstCopy(const std::string& var) { + auto range = equal_range(var); + + for (auto it = range.first; it != range.second; ++it) { + return it->second; + } + + return ""; +} + + } // namespace backend } // namespace collection } // namespace modsecurity diff --git a/src/collection/backend/in_memory-per_process.h b/src/collection/backend/in_memory-per_process.h index 7c9a6335..97b85c24 100644 --- a/src/collection/backend/in_memory-per_process.h +++ b/src/collection/backend/in_memory-per_process.h @@ -83,6 +83,7 @@ class InMemoryPerProcess : void del(const std::string& key) override; std::string* resolveFirst(const std::string& var) override; + std::string resolveFirstCopy(const std::string& var) override; void resolveSingleMatch(const std::string& var, std::vector *l) override; diff --git a/src/collection/backend/lmdb.cc b/src/collection/backend/lmdb.cc index 0142566d..da963368 100644 --- a/src/collection/backend/lmdb.cc +++ b/src/collection/backend/lmdb.cc @@ -155,6 +155,47 @@ void LMDB::lmdb_debug(int rc, std::string op, std::string scope) { #endif } + +std::string LMDB::resolveFirstCopy(const std::string& var) { + int rc; + MDB_val mdb_key; + MDB_val mdb_value; + MDB_val mdb_value_ret; + std::string ret; + MDB_txn *txn = NULL; + MDB_dbi dbi; + + string2val(var, &mdb_key); + + rc = mdb_txn_begin(m_env, NULL, 0, &txn); + lmdb_debug(rc, "txn", "resolveFirst"); + if (rc != 0) { + goto end_txn; + } + rc = mdb_dbi_open(txn, NULL, MDB_CREATE | MDB_DUPSORT, &dbi); + lmdb_debug(rc, "dbi", "resolveFirst"); + if (rc != 0) { + goto end_dbi; + } + rc = mdb_get(txn, dbi, &mdb_key, &mdb_value_ret); + lmdb_debug(rc, "get", "resolveFirst"); + if (rc != 0) { + goto end_get; + } + + ret.assign( + reinterpret_cast(mdb_value_ret.mv_data), + mdb_value_ret.mv_size); + +end_get: + mdb_dbi_close(m_env, dbi); +end_dbi: + mdb_txn_abort(txn); +end_txn: + return ret; +} + + std::string* LMDB::resolveFirst(const std::string& var) { int rc; MDB_val mdb_key; diff --git a/src/collection/backend/lmdb.h b/src/collection/backend/lmdb.h index 9e734c9c..2468baba 100644 --- a/src/collection/backend/lmdb.h +++ b/src/collection/backend/lmdb.h @@ -57,6 +57,7 @@ class LMDB : void del(const std::string& key) override; std::string* resolveFirst(const std::string& var) override; + std::string resolveFirstCopy(const std::string& var) override; void resolveSingleMatch(const std::string& var, std::vector *l) override; diff --git a/src/collection/collections.cc b/src/collection/collections.cc index d72c0277..71d3f7c8 100644 --- a/src/collection/collections.cc +++ b/src/collection/collections.cc @@ -183,6 +183,68 @@ std::string* Collections::resolveFirst(const std::string& collectionName, } +std::string Collections::resolveFirstCopy(const std::string& var) { + std::string transientVar = m_transient->resolveFirstCopy(var); + + if (transientVar.empty() == false) { + return transientVar; + } + + for (auto &a : *this) { + std::string res = a.second->resolveFirstCopy(toupper(a.first) + + ":" + var); + if (res.empty() == false) { + return res; + } + } + + return ""; +} + + +std::string Collections::resolveFirstCopy(const std::string& collectionName, + const std::string& var) { + if (tolower(collectionName) == "ip" + && !m_ip_collection_key.empty()) { + return m_ip_collection->resolveFirstCopy(toupper(collectionName) + + ":" + var, m_ip_collection_key); + } + + if (tolower(collectionName) == "global" + && !m_global_collection_key.empty()) { + return m_global_collection->resolveFirstCopy( + toupper(collectionName) + ":" + var, + m_global_collection_key); + } + + if (tolower(collectionName) == "resource" + && !m_resource_collection_key.empty()) { + return m_resource_collection->resolveFirstCopy( + toupper(collectionName) + ":" + var, + m_resource_collection_key); + } + + if (tolower(collectionName) == "session" + && !m_session_collection_key.empty()) { + return m_session_collection->resolveFirstCopy( + toupper(collectionName) + ":" + var, + m_session_collection_key); + } + + for (auto &a : *this) { + if (tolower(a.first) == tolower(collectionName)) { + std::string res = a.second->resolveFirstCopy(toupper(a.first) + + ":" + var); + if (res.empty() == false) { + return res; + } + } + } + + return ""; +} + + void Collections::resolveSingleMatch(const std::string& var, std::vector *l) {