From de8245d8f919918c356f75b00a71d36ab1536bb2 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Fri, 8 Jul 2016 15:36:34 -0300 Subject: [PATCH] in-memory backend: Adds support to select variables using regex --- .../backend/in_memory-per_process.cc | 33 ++++++++++++++++++- src/variables/variable.cc | 28 +++++++++------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index 85583d8d..de512e60 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -25,6 +25,7 @@ #include "modsecurity/collection/variable.h" #include "src/utils.h" +#include "src/utils/regex.h" namespace modsecurity { namespace collection { @@ -108,7 +109,37 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::vector *l) { - /* Not ready */ + + if (var.find(":") == std::string::npos) { + return; + } + if (var.size() < var.find(":") + 3) { + return; + } + std::string col = std::string(var, 0, var.find(":")); + std::string name = std::string(var, var.find(":") + 2, var.size() - var.find(":") - 3); + size_t keySize = col.size(); + Utils::Regex r = Utils::Regex(name); + + for (const auto& x : *this) { + if (x.first.size() <= keySize + 1) { + continue; + } + if (x.first.at(keySize) != ':') { + continue; + } + if (std::string(x.first, 0, keySize) != col) { + continue; + } + std::string content = std::string(x.first, keySize + 1, + x.first.size() - keySize - 1); + int ret = Utils::regex_search(content, r); + if (ret <= 0) { + continue; + } + + l->insert(l->begin(), new Variable(x.first, x.second)); + } } diff --git a/src/variables/variable.cc b/src/variables/variable.cc index 61eb743e..54804fc6 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -35,15 +35,18 @@ Variable::Variable(std::string name) m_collectionName(""), m_isExclusion(false), m_isCount(false) { - if (m_name.at(0) == '\\') { - m_type = RegularExpression; - } else if (m_name.find(":") != std::string::npos) { + if (m_name.find(":") != std::string::npos) { std::string col = toupper(std::string(m_name, 0, m_name.find(":"))); + std::string name = std::string(m_name, m_name.find(":") + 1, m_name.size()); if (col == "TX" || col == "IP" || col == "GLOBAL" || col == "RESOURCE" || col == "SESSION") { m_collectionName = col; } - m_type = SingleMatch; + if ((name.at(0) == '\\') || (name.at(0) == '/')) { + m_type = RegularExpression; + } else { + m_type = SingleMatch; + } } else { m_type = MultipleMatches; } @@ -78,15 +81,18 @@ Variable::Variable(std::string name, VariableKind kind) m_kind(kind), m_isExclusion(false), m_isCount(false) { - if (m_name.at(0) == '\\') { - m_type = RegularExpression; - } else if (m_name.find(":") != std::string::npos) { + if (m_name.find(":") != std::string::npos) { std::string col = toupper(std::string(m_name, 0, m_name.find(":"))); + std::string name = std::string(m_name, m_name.find(":") + 1, m_name.size()); if (col == "TX" || col == "IP" || col == "GLOBAL" || col == "RESOURCE" || col == "SESSION") { m_collectionName = col; } - m_type = SingleMatch; + if ((name.at(0) == '\\') || (name.at(0) == '/')) { + m_type = RegularExpression; + } else { + m_type = SingleMatch; + } } else { m_type = MultipleMatches; } @@ -127,8 +133,7 @@ void Variable::evaluateInternal(Transaction *transaction, if (m_kind == CollectionVarible && m_type == MultipleMatches) { transaction->m_collections.resolveMultiMatches(m_name, m_collectionName, l); - } else if (m_kind == CollectionVarible - && m_type == RegularExpression) { + } else if (m_type == RegularExpression) { transaction->m_collections.resolveRegularExpression(m_name, m_collectionName, l); } else { @@ -138,8 +143,7 @@ void Variable::evaluateInternal(Transaction *transaction, } else { if (m_kind == CollectionVarible && m_type == MultipleMatches) { transaction->m_collections.resolveMultiMatches(m_name, l); - } else if (m_kind == CollectionVarible - && m_type == RegularExpression) { + } else if (m_type == RegularExpression) { transaction->m_collections.resolveRegularExpression(m_name, l); } else { transaction->m_collections.resolveSingleMatch(m_name, l);