From b6ae0585cde36cb93db3a5b6bf4ff53ed95ad686 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Thu, 29 Oct 2015 12:39:09 -0300 Subject: [PATCH] Refactoring: Place m_variables inside Collections --- headers/modsecurity/assay.h | 9 +- headers/modsecurity/transaction/collections.h | 83 +++++++++ headers/modsecurity/transaction/variables.h | 19 +- src/Makefile.am | 1 + src/actions/capture.cc | 3 +- src/actions/set_var.cc | 5 +- src/assay.cc | 175 ++++++++---------- src/macro_expansion.cc | 4 +- src/operators/geo_lookup.cc | 22 +-- src/rule.cc | 24 +-- src/variables.cc | 165 +++++------------ src/variables/variable.cc | 2 +- src/variables/variations/exclusion.cc | 2 +- 13 files changed, 253 insertions(+), 261 deletions(-) create mode 100644 headers/modsecurity/transaction/collections.h diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index 31bf7424..12e57704 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -41,6 +41,7 @@ typedef struct Rules_t Rules; #include "modsecurity/intervention.h" #include "modsecurity/transaction/variable.h" #include "modsecurity/transaction/variables.h" +#include "modsecurity/transaction/collections.h" #define LOGFY_ADD(a, b) \ yajl_gen_string(g, reinterpret_cast(a), strlen(a)); \ @@ -68,6 +69,7 @@ namespace ModSecurity { class ModSecurity; class Assay; class Rules; +class Collections; namespace actions { class Action; } @@ -140,15 +142,10 @@ class Assay { void cleanup(); - void setCollection(const std::string& collectionName, - const std::string& variableName, - const std::string& targetValue); - const char *getResponseBody(); int getResponseBodyLenth(); - transaction::Variables m_variables; - std::unordered_map collections; + transaction::Collections m_collections; #ifndef NO_LOGS void debug(int, std::string); #endif diff --git a/headers/modsecurity/transaction/collections.h b/headers/modsecurity/transaction/collections.h new file mode 100644 index 00000000..02119ed9 --- /dev/null +++ b/headers/modsecurity/transaction/collections.h @@ -0,0 +1,83 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "modsecurity/transaction/variables.h" +#include "modsecurity/transaction/variable.h" + +#ifndef HEADERS_MODSECURITY_TRANSACTION_COLLECTIONS_H_ +#define HEADERS_MODSECURITY_TRANSACTION_COLLECTIONS_H_ + +#ifndef __cplusplus +typedef struct Variable_t Variable; +#endif + +#ifdef __cplusplus +namespace ModSecurity { +namespace transaction { + +class Collections : + public std::unordered_map { + public: + Collections(); + ~Collections(); + + void store(std::string key, std::string value); + void storeOrUpdateFirst(const std::string& collectionName, + const std::string& variableName, + const std::string& targetValue); + bool storeOrUpdateFirst(const std::string &key, const std::string &value); + bool updateFirst(const std::string &key, const std::string &value); + void del(const std::string& key); + std::string* resolveFirst(const std::string& var); + std::string* resolveFirst(const std::string& collectionName, + const std::string& var); + + void resolve(const std::string& var, + std::list *l); + std::list *resolve(const std::string& var); + + + /** + * This is a special collection to host the transaction variables. + * + * It exists independent of initialization and it is only valid during a transaction. + * + * Notice that it is not the TX collection. + */ + transaction::Variables m_transient; +}; + +} // namespace transaction +} // namespace ModSecurity +#endif + + +#endif // HEADERS_MODSECURITY_TRANSACTION_COLLECTIONS_H_ + + diff --git a/headers/modsecurity/transaction/variables.h b/headers/modsecurity/transaction/variables.h index e9292e94..9911a63c 100644 --- a/headers/modsecurity/transaction/variables.h +++ b/headers/modsecurity/transaction/variables.h @@ -38,8 +38,6 @@ namespace transaction { class Variables : public std::unordered_multimap { public: - std::unordered_map *m_collections; - Variables(); void store(std::string key, std::string value); @@ -50,27 +48,14 @@ class Variables : void del(const std::string& key); - std::list - resolveInt(const std::string& key, - std::list *l); - - std::list - resolveInt(const std::string& key); - - std::string* resolveFirst(const std::string& var); - std::string* resolveFirst(const std::string& collectionName, const std::string& var); - void setCollections(std::unordered_map *c); + std::list resolve(const std::string& key); - std::list * - resolve(const std::string& var); - - void resolve(const std::string& var, + std::list resolve(const std::string& var, std::list *l); }; diff --git a/src/Makefile.am b/src/Makefile.am index a5039bdf..8895ff6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -172,6 +172,7 @@ libmodsecurity_la_SOURCES = \ modsecurity.cc \ rules.cc \ utils.cc \ + collections.cc \ variables.cc \ debug_log.cc \ debug_log_writer.cc \ diff --git a/src/actions/capture.cc b/src/actions/capture.cc index 06c68d16..8b8e1a33 100644 --- a/src/actions/capture.cc +++ b/src/actions/capture.cc @@ -61,7 +61,8 @@ bool Capture::evaluate(Rule *rule, Assay *assay) { int i = 0; while (match->empty() == false) { - assay->setCollection("TX", std::to_string(i), match->back()); + assay->m_collections.storeOrUpdateFirst("TX", + std::to_string(i), match->back()); match->pop_back(); i++; } diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 2e2182ad..96e93e00 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -121,7 +121,7 @@ bool SetVar::evaluate(Rule *rule, Assay *assay) { try { std::string *resolvedValue = - assay->m_variables.resolveFirst(collectionName, + assay->m_collections.resolveFirst(collectionName, variableNameExpanded); if (resolvedValue == NULL) { value = 0; @@ -146,7 +146,8 @@ bool SetVar::evaluate(Rule *rule, Assay *assay) { assay->debug(8, "Saving variable: " + collectionName + ":" + \ variableNameExpanded + " with value: " + targetValue); #endif - assay->setCollection(collectionName, variableNameExpanded, targetValue); + assay->m_collections.storeOrUpdateFirst(collectionName, + variableNameExpanded, targetValue); return true; } diff --git a/src/assay.cc b/src/assay.cc index 35547ee9..f7170744 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -111,23 +111,21 @@ Assay::Assay(ModSecurity *ms, Rules *rules, void *logCbData) std::to_string(generate_assay_unique_id()); m_rules->incrementReferenceCount(); - m_variables.store("ARGS_COMBINED_SIZE", std::string("0")); - m_ARGScombinedSizeStr = m_variables.resolveFirst("ARGS_COMBINED_SIZE"); - m_variables.store("ARGS_NAMES", std::string("")); - this->m_namesArgs = m_variables.resolveFirst("ARGS_NAMES"); - m_variables.store("ARGS_POST_NAMES", std::string("")); - this->m_namesArgsPost = m_variables.resolveFirst("ARGS_POST_NAMES"); - m_variables.store("ARGS_GET_NAMES", std::string("")); - this->m_namesArgsGet = m_variables.resolveFirst("ARGS_GET_NAMES"); - m_variables.store("REQUEST_HEADERS_NAMES", std::string("")); - this->m_requestHeadersNames = m_variables.resolveFirst( + m_collections.store("ARGS_COMBINED_SIZE", std::string("0")); + m_ARGScombinedSizeStr = m_collections.resolveFirst("ARGS_COMBINED_SIZE"); + m_collections.store("ARGS_NAMES", std::string("")); + this->m_namesArgs = m_collections.resolveFirst("ARGS_NAMES"); + m_collections.store("ARGS_POST_NAMES", std::string("")); + this->m_namesArgsPost = m_collections.resolveFirst("ARGS_POST_NAMES"); + m_collections.store("ARGS_GET_NAMES", std::string("")); + this->m_namesArgsGet = m_collections.resolveFirst("ARGS_GET_NAMES"); + m_collections.store("REQUEST_HEADERS_NAMES", std::string("")); + this->m_requestHeadersNames = m_collections.resolveFirst( "REQUEST_HEADERS_NAMES"); - m_variables.store("RESPONSE_HEADERS_NAMES", std::string("")); - this->m_responseHeadersNames = m_variables.resolveFirst( + m_collections.store("RESPONSE_HEADERS_NAMES", std::string("")); + this->m_responseHeadersNames = m_collections.resolveFirst( "RESPONSE_HEADERS_NAMES"); - m_variables.setCollections(&collections); - collections.emplace("TX", new transaction::Variables()); #ifndef NO_LOGS this->debug(4, "Initialising transaction"); #endif @@ -141,7 +139,7 @@ Assay::~Assay() { m_requestBody.str(std::string()); m_requestBody.clear(); - for (auto &a : collections) { + for (auto &a : m_collections) { delete a.second; } @@ -202,12 +200,14 @@ int Assay::processConnection(const char *client, int cPort, const char *server, debug(4, "Starting phase CONNECTION. (SecRules 0)"); #endif - this->m_variables.store("REMOTE_HOST", m_clientIpAddress); - this->m_variables.store("UNIQUE_ID", id); - this->m_variables.store("REMOTE_ADDR", m_clientIpAddress); - this->m_variables.store("SERVER_ADDR", m_serverIpAddress); - this->m_variables.store("SERVER_PORT", std::to_string(this->m_serverPort)); - this->m_variables.store("REMOTE_PORT", std::to_string(this->m_clientPort)); + this->m_collections.store("REMOTE_HOST", m_clientIpAddress); + this->m_collections.store("UNIQUE_ID", id); + this->m_collections.store("REMOTE_ADDR", m_clientIpAddress); + this->m_collections.store("SERVER_ADDR", m_serverIpAddress); + this->m_collections.store("SERVER_PORT", + std::to_string(this->m_serverPort)); + this->m_collections.store("REMOTE_PORT", + std::to_string(this->m_clientPort)); this->m_rules->evaluate(ModSecurity::ConnectionPhase, this); return true; } @@ -252,11 +252,11 @@ int Assay::processURI(const char *uri, const char *protocol, size_t pos = m_uri_decoded.find("?"); size_t pos_raw = uri_s.find("?"); - m_variables.store("REQUEST_LINE", std::string(protocol) + " " + + m_collections.store("REQUEST_LINE", std::string(protocol) + " " + std::string(uri) + " HTTP/" + std::string(http_version)); if (pos_raw != std::string::npos) { - m_variables.store("QUERY_STRING", std::string(uri_s, pos_raw + 1, + m_collections.store("QUERY_STRING", std::string(uri_s, pos_raw + 1, uri_s.length() - (pos_raw + 1))); } @@ -266,19 +266,20 @@ int Assay::processURI(const char *uri, const char *protocol, } else { path_info = std::string(m_uri_decoded, 0, pos); } - m_variables.store("PATH_INFO", path_info); - m_variables.store("REQUEST_FILENAME", path_info); + m_collections.store("PATH_INFO", path_info); + m_collections.store("REQUEST_FILENAME", path_info); size_t offset = path_info.find_last_of("/\\"); if (offset != std::string::npos) { std::string basename = std::string(path_info, offset, path_info.length() - offset); - m_variables.store("REQUEST_BASENAME", basename); + m_collections.store("REQUEST_BASENAME", basename); } - m_variables.store("REQUEST_METHOD", protocol); - m_variables.store("REQUEST_PROTOCOL", "HTTP/" + std::string(http_version)); - m_variables.store("REQUEST_URI", uri); - m_variables.store("REQUEST_URI_RAW", uri); + m_collections.store("REQUEST_METHOD", protocol); + m_collections.store("REQUEST_PROTOCOL", + "HTTP/" + std::string(http_version)); + m_collections.store("REQUEST_URI", uri); + m_collections.store("REQUEST_URI_RAW", uri); if (pos != std::string::npos && (m_uri_decoded.length() - pos) > 2) { /** @@ -317,8 +318,8 @@ int Assay::processURI(const char *uri, const char *protocol, i--; } - m_variables.store("ARGS:" + key, value); - m_variables.store("ARGS_GET:" + key, value); + m_collections.store("ARGS:" + key, value); + m_collections.store("ARGS_GET:" + key, value); if (m_namesArgs->empty()) { m_namesArgs->assign(key); @@ -398,11 +399,11 @@ int Assay::addRequestHeader(const std::string& key, const std::string& value) { m_requestHeadersNames->assign(*m_requestHeadersNames + " " + key); - this->m_variables.store("REQUEST_HEADERS:" + key, value); + this->m_collections.store("REQUEST_HEADERS:" + key, value); if (tolower(key) == tolower("Authorization")) { std::vector type = split(value, ' '); - this->m_variables.store("AUTH_TYPE", type[0]); + this->m_collections.store("AUTH_TYPE", type[0]); } if (tolower(key) == "cookie") { @@ -413,8 +414,10 @@ int Assay::addRequestHeader(const std::string& key, if (s[0].at(0) == ' ') { s[0].erase(0, 1); } - this->m_variables.store("REQUEST_COOKIES:" + s[0], s[1]); - this->m_variables.store("REQUEST_COOKIES_NAMES:" + s[0], s[0]); + this->m_collections.store("REQUEST_COOKIES:" + + s[0], s[1]); + this->m_collections.store("REQUEST_COOKIES_NAMES:" + + s[0], s[0]); } cookies.pop_back(); } @@ -527,8 +530,8 @@ int Assay::processRequestBody() { return true; } - if (m_variables.resolveFirst("INBOUND_DATA_ERROR") == NULL) { - m_variables.store("INBOUND_DATA_ERROR", "0"); + if (m_collections.resolveFirst("INBOUND_DATA_ERROR") == NULL) { + m_collections.store("INBOUND_DATA_ERROR", "0"); } /* @@ -541,7 +544,7 @@ int Assay::processRequestBody() { */ if (m_requestBodyType == MultiPartRequestBody) { - std::string *a = m_variables.resolveFirst( + std::string *a = m_collections.resolveFirst( "REQUEST_HEADERS:Content-Type"); if (a != NULL) { Multipart m(*a, this); @@ -549,19 +552,19 @@ int Assay::processRequestBody() { if (m.init() == true) { m.process(m_requestBody.str()); for (auto &a : m.variables) { - m_variables.store(a.first, a.second); + m_collections.store(a.first, a.second); } if (m.crlf && m.lf) { - m_variables.store("MULTIPART_CRLF_LF_LINES", "1"); + m_collections.store("MULTIPART_CRLF_LF_LINES", "1"); } else { - m_variables.store("MULTIPART_CRLF_LF_LINES", "0"); + m_collections.store("MULTIPART_CRLF_LF_LINES", "0"); } if (m.boundaryStartsWithWhiteSpace) { #ifndef NO_LOGS debug(9, "Multipart: Boundary starts with white space, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } if (m.boundaryIsQuoted) { @@ -570,7 +573,7 @@ int Assay::processRequestBody() { debug(9, "Multipart: Boundary is quoted, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } if (m.containsDataAfter) { @@ -578,18 +581,18 @@ int Assay::processRequestBody() { debug(9, "Multipart: There is data after the boundary, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); - m_variables.store("MULTIPART_UNMATCHED_BOUNDARY", "1"); + m_collections.store("MULTIPART_UNMATCHED_BOUNDARY", "1"); } else { - m_variables.store("MULTIPART_UNMATCHED_BOUNDARY", "0"); + m_collections.store("MULTIPART_UNMATCHED_BOUNDARY", "0"); } if (m.containsDataBefore) { #ifndef NO_LOGS debug(9, "Multipart: There is data before the boundary, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } if (m.lf) { @@ -597,7 +600,7 @@ int Assay::processRequestBody() { debug(9, "Multipart: Lines are LF-terminated, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } if (m.missingSemicolon) { @@ -605,7 +608,7 @@ int Assay::processRequestBody() { debug(9, "Multipart: Boundary missing semicolon, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } if (m.invalidQuote) { @@ -613,7 +616,7 @@ int Assay::processRequestBody() { debug(9, "Multipart: Invalid quote, " \ "setting MULTIPART_STRICT_ERROR to 1"); #endif - m_variables.storeOrUpdateFirst( + m_collections.storeOrUpdateFirst( "MULTIPART_STRICT_ERROR", "1"); } } @@ -647,8 +650,8 @@ int Assay::processRequestBody() { char sep2 = '='; std::vector key_value = split(t, sep2); - m_variables.store("ARGS:" + key_value[0], key_value[1]); - m_variables.store("ARGS_POST:" + key_value[0], key_value[1]); + m_collections.store("ARGS:" + key_value[0], key_value[1]); + m_collections.store("ARGS_POST:" + key_value[0], key_value[1]); if (m_namesArgs->empty()) { m_namesArgs->assign(key_value[0]); @@ -674,7 +677,7 @@ int Assay::processRequestBody() { */ std::string fullRequest; std::list l; - m_variables.resolve("REQUEST_HEADERS", &l); + m_collections.resolve("REQUEST_HEADERS", &l); for (auto &a : l) { fullRequest = fullRequest + \ std::string(a->m_key, 16, a->m_key.length() - 16) + ": " \ @@ -682,13 +685,13 @@ int Assay::processRequestBody() { } fullRequest = fullRequest + "\n\n"; fullRequest = fullRequest + m_requestBody.str(); - m_variables.store("FULL_REQUEST", fullRequest); - m_variables.store("FULL_REQUEST_LENGTH", + m_collections.store("FULL_REQUEST", fullRequest); + m_collections.store("FULL_REQUEST_LENGTH", std::to_string(fullRequest.size())); if (m_requestBody.tellp() > 0) { - m_variables.store("REQUEST_BODY", m_requestBody.str()); - m_variables.store("REQUEST_BODY_LENGTH", + m_collections.store("REQUEST_BODY", m_requestBody.str()); + m_collections.store("REQUEST_BODY_LENGTH", std::to_string(m_requestBody.str().size())); } @@ -759,7 +762,7 @@ int Assay::appendRequestBody(const unsigned char *buf, size_t len) { if (this->m_rules->requestBodyLimit > 0 && this->m_rules->requestBodyLimit < len + current_size) { - m_variables.store("INBOUND_DATA_ERROR", "1"); + m_collections.store("INBOUND_DATA_ERROR", "1"); #ifndef NO_LOGS debug(5, "Request body is bigger than the maximum expected."); #endif @@ -846,10 +849,10 @@ int Assay::addResponseHeader(const std::string& key, const std::string& value) { m_responseHeadersNames->assign(*m_responseHeadersNames + " " + key); - this->m_variables.store("RESPONSE_HEADERS:" + key, value); + this->m_collections.store("RESPONSE_HEADERS:" + key, value); if (tolower(key) == "content-type") { - this->m_variables.store("RESPONSE_CONTENT_TYPE", value); + this->m_collections.store("RESPONSE_CONTENT_TYPE", value); } return 1; } @@ -940,12 +943,12 @@ int Assay::processResponseBody() { return true; } - if (m_variables.resolveFirst("OUTBOUND_DATA_ERROR") == NULL) { - m_variables.store("OUTBOUND_DATA_ERROR", "0"); + if (m_collections.resolveFirst("OUTBOUND_DATA_ERROR") == NULL) { + m_collections.store("OUTBOUND_DATA_ERROR", "0"); } - m_variables.store("RESPONSE_BODY", m_responseBody.str()); - m_variables.store("RESPONSE_CONTENT_LENGTH", + m_collections.store("RESPONSE_BODY", m_responseBody.str()); + m_collections.store("RESPONSE_CONTENT_LENGTH", std::to_string(m_responseBody.str().size())); this->m_rules->evaluate(ModSecurity::ResponseBodyPhase, this); @@ -982,7 +985,7 @@ int Assay::appendResponseBody(const unsigned char *buf, size_t len) { if (this->m_rules->responseBodyLimit > 0 && this->m_rules->responseBodyLimit < len + current_size) { - m_variables.store("OUTBOUND_DATA_ERROR", "1"); + m_collections.store("OUTBOUND_DATA_ERROR", "1"); #ifndef NO_LOGS debug(5, "Response body is bigger than the maximum expected."); #endif @@ -1195,12 +1198,14 @@ std::string Assay::toOldAuditLogFormatIndex(const std::string &filename, strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); ss << dash_if_empty( - *this->m_variables.resolveFirst("REQUEST_HEADERS:Host")) << " "; + *this->m_collections.resolveFirst("REQUEST_HEADERS:Host")) << " "; ss << dash_if_empty(this->m_clientIpAddress) << " "; /** TODO: Check variable */ - ss << dash_if_empty(*this->m_variables.resolveFirst("REMOTE_USER")) << " "; + ss << dash_if_empty(*this->m_collections.resolveFirst("REMOTE_USER")); + ss << " "; /** TODO: Check variable */ - ss << dash_if_empty(*this->m_variables.resolveFirst("LOCAL_USER")) << " "; + ss << dash_if_empty(*this->m_collections.resolveFirst("LOCAL_USER")); + ss << " "; ss << tstr << " "; ss << "\""; @@ -1212,14 +1217,14 @@ std::string Assay::toOldAuditLogFormatIndex(const std::string &filename, ss << this->httpCodeReturned << " "; ss << this->m_responseBody.tellp(); /** TODO: Check variable */ - ss << dash_if_empty(*this->m_variables.resolveFirst("REFERER")) << " "; + ss << dash_if_empty(*this->m_collections.resolveFirst("REFERER")) << " "; ss << "\""; ss << dash_if_empty( - *this->m_variables.resolveFirst("REQUEST_HEADERS:User-Agent")); + *this->m_collections.resolveFirst("REQUEST_HEADERS:User-Agent")); ss << "\" "; ss << this->id << " "; /** TODO: Check variable */ - ss << dash_if_empty(*this->m_variables.resolveFirst("REFERER")) << " "; + ss << dash_if_empty(*this->m_collections.resolveFirst("REFERER")) << " "; ss << filename << " "; ss << "0" << " "; @@ -1253,7 +1258,7 @@ std::string Assay::toOldAuditLogFormat(int parts, const std::string &trailer) { audit_log << this->m_protocol << " " << this->m_uri << " " << "HTTP/"; audit_log << this->m_httpVersion << std::endl; - for (auto h : m_variables) { + for (auto h : m_collections.m_transient) { std::string filter = "REQUEST_HEADERS:"; std::string a = h.first; std::string b = h.second; @@ -1280,7 +1285,7 @@ std::string Assay::toOldAuditLogFormat(int parts, const std::string &trailer) { } if (parts & AuditLog::FAuditLogPart) { audit_log << "--" << trailer << "-" << "F--" << std::endl; - for (auto h : m_variables) { + for (auto h : m_collections.m_transient) { std::string filter = "RESPONSE_HEADERS:"; std::string a = h.first; std::string b = h.second; @@ -1369,7 +1374,7 @@ std::string Assay::to_json(int parts) { strlen("headers")); yajl_gen_map_open(g); - for (auto h : m_variables) { + for (auto h : m_collections.m_transient) { std::string filter = "REQUEST_HEADERS:"; std::string a = h.first; std::string b = h.second; @@ -1404,7 +1409,7 @@ std::string Assay::to_json(int parts) { strlen("headers")); yajl_gen_map_open(g); - for (auto h : m_variables) { + for (auto h : m_collections.m_transient) { std::string filter = "RESPONSE_HEADERS:"; std::string a = h.first; std::string b = h.second; @@ -1474,24 +1479,6 @@ void Assay::serverLog(const std::string& msg) { } -void Assay::setCollection(const std::string& collectionName, - const std::string& variableName, - const std::string& targetValue) { - - try { - transaction::Variables *collection; - collection = collections.at(collectionName); - collection->storeOrUpdateFirst(collectionName + ":" - + variableName, targetValue); - } catch (...) { -#ifndef NO_LOGS - debug(9, "don't know any collection named: " - + collectionName + ". it was created?"); -#endif - return; - } -} - /** * @name msc_new_assay * @brief Create a new assay for a given configuration and ModSecurity core. diff --git a/src/macro_expansion.cc b/src/macro_expansion.cc index 83ca6014..40b8feb8 100644 --- a/src/macro_expansion.cc +++ b/src/macro_expansion.cc @@ -53,12 +53,12 @@ std::string MacroExpansion::expand(const std::string& input, Assay *assay) { std::string *variableValue; size_t collection = variable.find("."); if (collection == std::string::npos) { - variableValue = assay->m_variables.resolveFirst(variable); + variableValue = assay->m_collections.resolveFirst(variable); } else { std::string col = std::string(variable, 0, collection); std::string var = std::string(variable, collection + 1, variable.length() - (collection + 1)); - variableValue = assay->m_variables.resolveFirst(col, var); + variableValue = assay->m_collections.resolveFirst(col, var); } res.erase(start, end - start + 2); diff --git a/src/operators/geo_lookup.cc b/src/operators/geo_lookup.cc index 6f55c3e6..4f45063c 100644 --- a/src/operators/geo_lookup.cc +++ b/src/operators/geo_lookup.cc @@ -44,42 +44,42 @@ bool GeoLookup::evaluate(Assay *assay, const std::string &exp) { } if (ret && gir) { if (gir->country_code) { - assay->m_variables.store("GEO:COUNTRY_CODE", gir->country_code); + assay->m_collections.store("GEO:COUNTRY_CODE", gir->country_code); } if (gir->country_code3) { - assay->m_variables.store("GEO:COUNTRY_CODE3", gir->country_code3); + assay->m_collections.store("GEO:COUNTRY_CODE3", gir->country_code3); } if (gir->country_name) { - assay->m_variables.store("GEO:COUNTRY_NAME", gir->country_name); + assay->m_collections.store("GEO:COUNTRY_NAME", gir->country_name); } if (gir->continent_code) { - assay->m_variables.store("GEO:COUNTRY_CONTINENT", + assay->m_collections.store("GEO:COUNTRY_CONTINENT", gir->continent_code); } if (gir->country_code && gir->region) { - assay->m_variables.store("GEO:REGION", + assay->m_collections.store("GEO:REGION", GeoIP_region_name_by_code(gir->country_code, gir->region)); } if (gir->city) { - assay->m_variables.store("GEO:CITY", gir->city); + assay->m_collections.store("GEO:CITY", gir->city); } if (gir->postal_code) { - assay->m_variables.store("GEO:POSTAL_CODE", gir->postal_code); + assay->m_collections.store("GEO:POSTAL_CODE", gir->postal_code); } if (gir->latitude) { - assay->m_variables.store("GEO:LATITUDE", + assay->m_collections.store("GEO:LATITUDE", std::to_string(gir->latitude)); } if (gir->longitude) { - assay->m_variables.store("GEO:LONGITUDE", + assay->m_collections.store("GEO:LONGITUDE", std::to_string(gir->longitude)); } if (gir->metro_code) { - assay->m_variables.store("GEO:DMA_CODE", + assay->m_collections.store("GEO:DMA_CODE", std::to_string(gir->metro_code)); } if (gir->area_code) { - assay->m_variables.store("GEO:AREA_CODE", + assay->m_collections.store("GEO:AREA_CODE", std::to_string(gir->area_code)); } diff --git a/src/rule.cc b/src/rule.cc index 770fcc2d..5237c845 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -402,22 +402,24 @@ bool Rule::evaluate(Assay *assay) { #ifndef NO_LOGS assay->debug(4, "Executing chained rule."); #endif - if (assay->m_variables.storeOrUpdateFirst("MATCHED_VAR", + if (assay->m_collections.storeOrUpdateFirst("MATCHED_VAR", value) == false) { - assay->m_variables.store("MATCHED_VAR", value); + assay->m_collections.store("MATCHED_VAR", value); } - if (assay->m_variables.storeOrUpdateFirst( + if (assay->m_collections.storeOrUpdateFirst( "MATCHED_VAR_NAME", v->m_key) == false) { - assay->m_variables.store("MATCHED_VAR_NAME", v->m_key); + assay->m_collections.store("MATCHED_VAR_NAME", + v->m_key); } - assay->m_variables.store("MATCHED_VARS:" + v->m_key, value); - assay->m_variables.store("MATCHED_VARS_NAMES:" + v->m_key, - v->m_key); + assay->m_collections.store("MATCHED_VARS:" + + v->m_key, value); + assay->m_collections.store("MATCHED_VARS_NAMES:" + + v->m_key, v->m_key); chainResult = this->chainedRule->evaluate(assay); - assay->m_variables.storeOrUpdateFirst("MATCHED_VAR", ""); - assay->m_variables.del("MATCHED_VARS:" + v->m_key); - assay->m_variables.del("MATCHED_VARS_NAMES:" + v->m_key); - assay->m_variables.del("MATCHED_VARS_NAME"); + assay->m_collections.storeOrUpdateFirst("MATCHED_VAR", ""); + assay->m_collections.del("MATCHED_VARS:" + v->m_key); + assay->m_collections.del("MATCHED_VARS_NAMES:" + v->m_key); + assay->m_collections.del("MATCHED_VARS_NAME"); } if (this->chained && chainResult == true || !this->chained) { for (Action *a : diff --git a/src/variables.cc b/src/variables.cc index 8ccacd31..8494b2ba 100644 --- a/src/variables.cc +++ b/src/variables.cc @@ -30,152 +30,87 @@ namespace ModSecurity { namespace transaction { -Variables::Variables() : - m_collections(NULL) { +Variables::Variables() { this->reserve(1000); } -void Variables::setCollections(std::unordered_map *c) { - m_collections = c; -} void Variables::store(std::string key, std::string value) { - this->emplace(key, value); - } + this->emplace(key, value); +} bool Variables::storeOrUpdateFirst(const std::string &key, - const std::string &value) { - if (updateFirst(key, value) == false) { - store(key, value); - } - return true; + const std::string &value) { + if (updateFirst(key, value) == false) { + store(key, value); } + return true; +} bool Variables::updateFirst(const std::string &key, const std::string &value) { - auto range = this->equal_range(key); + auto range = this->equal_range(key); - for (auto it = range.first; it != range.second; ++it) { - it->second = value; - return true; - } - return false; + for (auto it = range.first; it != range.second; ++it) { + it->second = value; + return true; } + return false; +} void Variables::del(const std::string& key) { - this->erase(key); + this->erase(key); +} + + +std::list Variables::resolve(const std::string& key, + std::list *l) { + auto range = this->equal_range(key); + + for (auto it = range.first; it != range.second; ++it) { + l->push_back(new transaction::Variable(key, it->second)); } - -std::list - Variables::resolveInt(const std::string& key, - std::list *l) { - auto range = this->equal_range(key); - - for (auto it = range.first; it != range.second; ++it) { - l->push_back(new transaction::Variable(key, it->second)); - } - - if (key.find(":") == std::string::npos && l->size() == 0) { - size_t keySize = key.size() + 1; - for (auto& x : *this) { - if (x.first.size() <= keySize) { - continue; - } - if (x.first.at(keySize - 1) != ':') { - continue; - } - if (x.first.compare(0, keySize, key + ":") != 0) { - continue; - } - // auto range = this->equal_range(x.first); - - // for (auto it = range.first; it != range.second; ++it) { - l->push_back(new transaction::Variable(x.first, x.second)); - // } + if (key.find(":") == std::string::npos && l->size() == 0) { + size_t keySize = key.size() + 1; + for (auto& x : *this) { + if (x.first.size() <= keySize) { + continue; } + if (x.first.at(keySize - 1) != ':') { + continue; + } + if (x.first.compare(0, keySize, key + ":") != 0) { + continue; + } + // auto range = this->equal_range(x.first); + + // for (auto it = range.first; it != range.second; ++it) { + l->push_back(new transaction::Variable(x.first, x.second)); + // } } - - return *l; } + return *l; +} -std::list - Variables::resolveInt(const std::string& key) { - std::list l; - return resolveInt(key, &l); - } +std::list Variables::resolve(const std::string& key) { + std::list l; + return resolve(key, &l); +} std::string* Variables::resolveFirst(const std::string& var) { - auto range = equal_range(var); + auto range = equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - return &it->second; - } - - if (m_collections == NULL) { - return NULL; - } - - for (auto &a : *m_collections) { - auto range = a.second->equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - return &it->second; - } - } - - return NULL; + for (auto it = range.first; it != range.second; ++it) { + return &it->second; } - -std::string* Variables::resolveFirst(const std::string& collectionName, - const std::string& var) { - if (m_collections == NULL) { - return NULL; - } - - for (auto &a : *m_collections) { - if (tolower(a.first) == tolower(collectionName)) { - auto range = a.second->equal_range(toupper(collectionName) - + ":" + var); - for (auto it = range.first; it != range.second; ++it) { - return &it->second; - } - } - } - - return NULL; - } - - -void Variables::resolve(const std::string& var, - std::list *l) { - - resolveInt(var, l); - - if (m_collections == NULL) { - return; - } - - /* It may be a collection */ - for (auto &a : *m_collections) { - a.second->resolveInt(var, l); - } -} - -std::list * - Variables::resolve(const std::string& var) { - std::list *l = - new std::list(); - - resolve(var, l); - - return l; + return NULL; } diff --git a/src/variables/variable.cc b/src/variables/variable.cc index d86cd1b0..bde944a3 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -32,7 +32,7 @@ std::list * Variable::evaluate(Assay *assay) { std::list *l = new std::list(); - assay->m_variables.resolve(this->name, l); + assay->m_collections.resolve(this->name, l); return l; } diff --git a/src/variables/variations/exclusion.cc b/src/variables/variations/exclusion.cc index cd015ffc..b7327e64 100644 --- a/src/variables/variations/exclusion.cc +++ b/src/variables/variations/exclusion.cc @@ -33,7 +33,7 @@ std::list * Exclusion::evaluate(Assay *assay) { std::list *l = new std::list(); - assay->m_variables.resolve(this->name, l); + assay->m_collections.resolve(this->name, l); return l; }