From 73c4d691744b9bb2317670eddcc8d783ac565117 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Tue, 1 Nov 2016 14:59:06 -0300 Subject: [PATCH] Moves string related functions from `utils' to `utils/string' --- src/Makefile.am | 3 +- src/actions/allow.cc | 5 +- src/actions/ctl/rule_remove_target_by_id.cc | 6 +- src/actions/ctl/rule_remove_target_by_tag.cc | 5 +- src/actions/phase.cc | 6 +- src/actions/set_var.cc | 6 +- src/actions/severity.cc | 6 +- .../backend/in_memory-per_process.cc | 8 +- src/collection/collections.cc | 111 ++++++----- src/macro_expansion.cc | 5 +- src/parser/seclang-parser.yy | 5 +- src/parser/seclang-scanner.ll | 5 +- src/request_body_processor/multipart.cc | 9 +- src/rule.cc | 13 +- src/rules_exceptions.cc | 7 +- src/transaction.cc | 40 ++-- src/utils.cc | 118 ------------ src/utils.h | 11 -- src/utils/mbedtls/mbed-tls-config.h | 2 +- src/utils/msc_string.cc | 175 ++++++++++++++++++ src/utils/msc_string.h | 47 +++++ src/variables/rule.cc | 7 +- src/variables/variable.cc | 28 +-- test/unit/unit.cc | 4 +- test/unit/unit_test.cc | 7 +- 25 files changed, 403 insertions(+), 236 deletions(-) create mode 100644 src/utils/msc_string.cc create mode 100644 src/utils/msc_string.h diff --git a/src/Makefile.am b/src/Makefile.am index 60ca9423..79ae6655 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -219,7 +219,8 @@ UTILS = \ utils/md5.cc \ utils/msc_tree.cc \ utils/regex.cc \ - utils/sha1.cc + utils/sha1.cc \ + utils/msc_string.cc COLLECTION = \ collection/collections.cc \ diff --git a/src/actions/allow.cc b/src/actions/allow.cc index ba5daff1..44020db4 100644 --- a/src/actions/allow.cc +++ b/src/actions/allow.cc @@ -21,13 +21,16 @@ #include "modsecurity/transaction.h" #include "modsecurity/rule.h" #include "src/utils.h" +#include "utils/msc_string.h" #include "modsecurity/modsecurity.h" +using modsecurity::utils::String; + namespace modsecurity { namespace actions { bool Allow::init(std::string *error) { - std::string a = tolower(m_parser_payload); + std::string a = String::tolower(m_parser_payload); if (a == "phase") { m_allowType = PhaseAllowType; diff --git a/src/actions/ctl/rule_remove_target_by_id.cc b/src/actions/ctl/rule_remove_target_by_id.cc index 929304d9..28746ba8 100644 --- a/src/actions/ctl/rule_remove_target_by_id.cc +++ b/src/actions/ctl/rule_remove_target_by_id.cc @@ -20,6 +20,10 @@ #include #include "modsecurity/transaction.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace actions { @@ -28,7 +32,7 @@ namespace ctl { bool RuleRemoveTargetById::init(std::string *error) { std::string what(m_parser_payload, 21, m_parser_payload.size() - 21); - std::vector param = split(what, ';'); + std::vector param = String::split(what, ';'); if (param.size() < 2) { error->assign(what + " is not a valid `ID;VARIABLE'"); diff --git a/src/actions/ctl/rule_remove_target_by_tag.cc b/src/actions/ctl/rule_remove_target_by_tag.cc index 198adabd..693303d7 100644 --- a/src/actions/ctl/rule_remove_target_by_tag.cc +++ b/src/actions/ctl/rule_remove_target_by_tag.cc @@ -20,6 +20,9 @@ #include #include "modsecurity/transaction.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; namespace modsecurity { namespace actions { @@ -28,7 +31,7 @@ namespace ctl { bool RuleRemoveTargetByTag::init(std::string *error) { std::string what(m_parser_payload, 22, m_parser_payload.size() - 22); - std::vector param = split(what, ';'); + std::vector param = String::split(what, ';'); if (param.size() < 2) { error->assign(what + " is not a valid `TAG;VARIABLE'"); diff --git a/src/actions/phase.cc b/src/actions/phase.cc index 624b047b..24ff5b9c 100644 --- a/src/actions/phase.cc +++ b/src/actions/phase.cc @@ -22,12 +22,16 @@ #include "modsecurity/rule.h" #include "src/utils.h" #include "modsecurity/modsecurity.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace actions { bool Phase::init(std::string *error) { - std::string a = tolower(m_parser_payload); + std::string a = String::tolower(m_parser_payload); m_phase = -1; try { diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 496455dd..81c5ecbd 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -22,6 +22,10 @@ #include "modsecurity/rule.h" #include "src/macro_expansion.h" #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace actions { @@ -49,7 +53,7 @@ bool SetVar::init(std::string *error) { pos = m_parser_payload.find("."); if (pos != std::string::npos) { m_collectionName = std::string(m_parser_payload, 0, pos); - m_collectionName = toupper(m_collectionName); + m_collectionName = String::toupper(m_collectionName); } else { error->assign("Missing the collection and/or variable name"); return false; diff --git a/src/actions/severity.cc b/src/actions/severity.cc index 0e823bde..0cbfbde3 100644 --- a/src/actions/severity.cc +++ b/src/actions/severity.cc @@ -22,13 +22,17 @@ #include "modsecurity/transaction.h" #include "modsecurity/rule.h" #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace actions { bool Severity::init(std::string *error) { - std::string a = tolower(m_parser_payload); + std::string a = String::tolower(m_parser_payload); if (a == "emergency") { m_severity = 0; return true; diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index dc17b148..248e2d44 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -26,6 +26,10 @@ #include "modsecurity/collection/variable.h" #include "src/utils.h" #include "src/utils/regex.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace collection { @@ -99,8 +103,8 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, if (x.first.at(keySize) != ':') { continue; } - std::string fu = toupper(x.first); - std::string fvar = toupper(var); + std::string fu = String::toupper(x.first); + std::string fvar = String::toupper(var); if (fu.compare(0, keySize, fvar) != 0) { continue; } diff --git a/src/collection/collections.cc b/src/collection/collections.cc index d1e322f1..01f5095e 100644 --- a/src/collection/collections.cc +++ b/src/collection/collections.cc @@ -28,6 +28,10 @@ #include "modsecurity/collection/collection.h" #include "src/collection/backend/in_memory-per_process.h" #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; + namespace modsecurity { namespace collection { @@ -60,28 +64,28 @@ Collections::~Collections() { void Collections::storeOrUpdateFirst(const std::string& collectionName, const std::string& variableName, const std::string& targetValue) { - if (tolower(collectionName) == "ip" + if (String::tolower(collectionName) == "ip" && !m_ip_collection_key.empty()) { m_ip_collection->storeOrUpdateFirst(collectionName + ":" + variableName, m_ip_collection_key, targetValue); return; } - if (tolower(collectionName) == "global" + if (String::tolower(collectionName) == "global" && !m_global_collection_key.empty()) { m_global_collection->storeOrUpdateFirst(collectionName + ":" + variableName, m_global_collection_key, targetValue); return; } - if (tolower(collectionName) == "resource" + if (String::tolower(collectionName) == "resource" && !m_resource_collection_key.empty()) { m_resource_collection->storeOrUpdateFirst(collectionName + ":" + variableName, m_resource_collection_key, targetValue); return; } - if (tolower(collectionName) == "session" + if (String::tolower(collectionName) == "session" && !m_session_collection_key.empty()) { m_session_collection->storeOrUpdateFirst(collectionName + ":" + variableName, m_session_collection_key, targetValue); @@ -132,7 +136,8 @@ std::string* Collections::resolveFirst(const std::string& var) { } for (auto &a : *this) { - std::string *res = a.second->resolveFirst(toupper(a.first) + ":" + var); + std::string *res = a.second->resolveFirst( + String::toupper(a.first) + ":" + var); if (res != NULL) { return res; } @@ -144,33 +149,38 @@ std::string* Collections::resolveFirst(const std::string& var) { std::string* Collections::resolveFirst(const std::string& collectionName, const std::string& var) { - if (tolower(collectionName) == "ip" + if (String::tolower(collectionName) == "ip" && !m_ip_collection_key.empty()) { - return m_ip_collection->resolveFirst(toupper(collectionName) - + ":" + var, m_ip_collection_key); + return m_ip_collection->resolveFirst( + String::toupper(collectionName) + + ":" + var, m_ip_collection_key); } - if (tolower(collectionName) == "global" + if (String::tolower(collectionName) == "global" && !m_global_collection_key.empty()) { - return m_global_collection->resolveFirst(toupper(collectionName) - + ":" + var, m_global_collection_key); + return m_global_collection->resolveFirst( + String::toupper(collectionName) + + ":" + var, m_global_collection_key); } - if (tolower(collectionName) == "resource" + if (String::tolower(collectionName) == "resource" && !m_resource_collection_key.empty()) { - return m_resource_collection->resolveFirst(toupper(collectionName) - + ":" + var, m_resource_collection_key); + return m_resource_collection->resolveFirst( + String::toupper(collectionName) + + ":" + var, m_resource_collection_key); } - if (tolower(collectionName) == "session" + if (String::tolower(collectionName) == "session" && !m_session_collection_key.empty()) { - return m_session_collection->resolveFirst(toupper(collectionName) - + ":" + var, m_session_collection_key); + return m_session_collection->resolveFirst( + String::toupper(collectionName) + + ":" + var, m_session_collection_key); } for (auto &a : *this) { - if (tolower(a.first) == tolower(collectionName)) { - std::string *res = a.second->resolveFirst(toupper(a.first) + if (String::tolower(a.first) == String::tolower(collectionName)) { + std::string *res = a.second->resolveFirst( + String::toupper(a.first) + ":" + var); if (res != NULL) { return res; @@ -190,7 +200,7 @@ std::string Collections::resolveFirstCopy(const std::string& var) { } for (auto &a : *this) { - std::string res = a.second->resolveFirstCopy(toupper(a.first) + + std::string res = a.second->resolveFirstCopy(String::toupper(a.first) + ":" + var); if (res.empty() == false) { return res; @@ -203,37 +213,38 @@ std::string Collections::resolveFirstCopy(const std::string& var) { std::string Collections::resolveFirstCopy(const std::string& collectionName, const std::string& var) { - if (tolower(collectionName) == "ip" + if (String::tolower(collectionName) == "ip" && !m_ip_collection_key.empty()) { - return m_ip_collection->resolveFirstCopy(toupper(collectionName) - + ":" + var, m_ip_collection_key); + return m_ip_collection->resolveFirstCopy( + String::toupper(collectionName) + + ":" + var, m_ip_collection_key); } - if (tolower(collectionName) == "global" + if (String::tolower(collectionName) == "global" && !m_global_collection_key.empty()) { return m_global_collection->resolveFirstCopy( - toupper(collectionName) + ":" + var, + String::toupper(collectionName) + ":" + var, m_global_collection_key); } - if (tolower(collectionName) == "resource" + if (String::tolower(collectionName) == "resource" && !m_resource_collection_key.empty()) { return m_resource_collection->resolveFirstCopy( - toupper(collectionName) + ":" + var, + String::toupper(collectionName) + ":" + var, m_resource_collection_key); } - if (tolower(collectionName) == "session" + if (String::tolower(collectionName) == "session" && !m_session_collection_key.empty()) { return m_session_collection->resolveFirstCopy( - toupper(collectionName) + ":" + var, + String::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 (String::tolower(a.first) == String::tolower(collectionName)) { + std::string res = a.second->resolveFirstCopy( + String::toupper(a.first) + ":" + var); if (res.empty() == false) { return res; } @@ -255,27 +266,27 @@ void Collections::resolveSingleMatch(const std::string& var, const std::string& collection, std::vector *l) { - if (tolower(collection) == "ip" + if (String::tolower(collection) == "ip" && !m_ip_collection_key.empty()) { m_ip_collection->resolveSingleMatch(var, m_ip_collection_key, l); return; } - if (tolower(collection) == "global" + if (String::tolower(collection) == "global" && !m_global_collection_key.empty()) { m_global_collection->resolveSingleMatch(var, m_global_collection_key, l); return; } - if (tolower(collection) == "resource" + if (String::tolower(collection) == "resource" && !m_resource_collection_key.empty()) { m_resource_collection->resolveSingleMatch(var, m_resource_collection_key, l); return; } - if (tolower(collection) == "session" + if (String::tolower(collection) == "session" && !m_session_collection_key.empty()) { m_session_collection->resolveSingleMatch(var, m_session_collection_key, l); @@ -297,27 +308,27 @@ void Collections::resolveMultiMatches(const std::string& var, void Collections::resolveMultiMatches(const std::string& var, const std::string& collection, std::vector *l) { - if (tolower(collection) == "ip" + if (String::tolower(collection) == "ip" && !m_ip_collection_key.empty()) { m_ip_collection->resolveMultiMatches(var, m_ip_collection_key, l); return; } - if (tolower(collection) == "global" + if (String::tolower(collection) == "global" && !m_global_collection_key.empty()) { m_global_collection->resolveMultiMatches(var, m_global_collection_key, l); return; } - if (tolower(collection) == "resource" + if (String::tolower(collection) == "resource" && !m_resource_collection_key.empty()) { m_resource_collection->resolveMultiMatches(var, m_resource_collection_key, l); return; } - if (tolower(collection) == "session" + if (String::tolower(collection) == "session" && !m_session_collection_key.empty()) { m_session_collection->resolveMultiMatches(var, m_session_collection_key, l); @@ -338,30 +349,34 @@ void Collections::resolveRegularExpression(const std::string& var, void Collections::resolveRegularExpression(const std::string& var, const std::string& collection, std::vector *l) { - if (tolower(collection) == "ip" + if (String::tolower(collection) == "ip" && !m_ip_collection_key.empty()) { - m_ip_collection->resolveRegularExpression(toupper(collection) + m_ip_collection->resolveRegularExpression( + String::toupper(collection) + ":" + var, m_ip_collection_key, l); return; } - if (tolower(collection) == "global" + if (String::tolower(collection) == "global" && !m_global_collection_key.empty()) { - m_global_collection->resolveRegularExpression(toupper(collection) + m_global_collection->resolveRegularExpression( + String::toupper(collection) + ":" + var, m_global_collection_key, l); return; } - if (tolower(collection) == "resource" + if (String::tolower(collection) == "resource" && !m_resource_collection_key.empty()) { - m_resource_collection->resolveRegularExpression(toupper(collection) + m_resource_collection->resolveRegularExpression( + String::toupper(collection) + ":" + var, m_resource_collection_key, l); return; } - if (tolower(collection) == "session" + if (String::tolower(collection) == "session" && !m_session_collection_key.empty()) { - m_session_collection->resolveRegularExpression(toupper(collection) + m_session_collection->resolveRegularExpression( + String::toupper(collection) + ":" + var, m_session_collection_key, l); return; } diff --git a/src/macro_expansion.cc b/src/macro_expansion.cc index 2d8bbd8a..2e151dd1 100644 --- a/src/macro_expansion.cc +++ b/src/macro_expansion.cc @@ -20,8 +20,11 @@ #include "src/variables/tx.h" #include "src/variables/highest_severity.h" #include "src/utils.h" +#include "utils/msc_string.h" +using modsecurity::utils::String; + namespace modsecurity { MacroExpansion::MacroExpansion() { } @@ -73,7 +76,7 @@ std::string MacroExpansion::expand(const std::string& input, std::string var = std::string(variable, collection + 1, variable.length() - (collection + 1)); - if (toupper(col) == "RULE") { + if (String::toupper(col) == "RULE") { if (rule == NULL) { transaction->debug(9, "macro expansion: cannot resolve " \ "RULE variable without the Rule object"); diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index fabd42f4..3d1a3ef3 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -56,6 +56,7 @@ class Driver; #include "operators/operator.h" #include "utils.h" #include "utils/geo_lookup.h" +#include "utils/msc_string.h" #include "variables/xml.h" #include "variables/duration.h" #include "variables/env.h" @@ -121,7 +122,7 @@ using modsecurity::actions::Ver; using modsecurity::actions::transformations::None; using modsecurity::actions::transformations::Transformation; using modsecurity::operators::Operator; -using modsecurity::removeBracketsIfNeeded; +using modsecurity::utils::String; @@ -577,7 +578,7 @@ expression: } | CONFIG_DIR_SEC_MARKER { - driver.addSecMarker(removeBracketsIfNeeded($1)); + driver.addSecMarker(String::removeBracketsIfNeeded($1)); } | CONFIG_DIR_RULE_ENG CONFIG_VALUE_OFF { diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 8863a806..e16c74bc 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -8,10 +8,11 @@ #include "seclang-parser.hh" #include "utils/https_client.h" #include "src/utils.h" +#include "utils/msc_string.h" using modsecurity::Parser::Driver; using modsecurity::Utils::HttpsClient; -using modsecurity::split; +using modsecurity::utils::String; typedef yy::seclang_parser p; @@ -436,7 +437,7 @@ VAR_FREE_TEXT_SPACE_COMMA [^, \t\"]+ std::string key; std::string url; - std::vector conf = split(yytext, ' '); + std::vector conf = String::split(yytext, ' '); key = conf[1]; url = conf[2]; c.setKey(key); diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index 3304c561..7c52425b 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -29,6 +29,9 @@ #include "modsecurity/collection/collections.h" #include "modsecurity/rules.h" #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; namespace modsecurity { namespace RequestBodyProcessor { @@ -716,7 +719,7 @@ int Multipart::process_part_header(std::string *error) { } new_value = std::string(data); - chomp(&new_value); + String::chomp(&new_value); /* update the header value in the table */ header_value = m_mpp->m_headers.at(m_mpp->m_last_header_name); @@ -766,7 +769,7 @@ int Multipart::process_part_header(std::string *error) { data++; } header_value = std::string(data); - chomp(&header_value); + String::chomp(&header_value); /* error if the name already exists */ if (m_mpp->m_headers.count(header_name) > 0) { @@ -1036,7 +1039,7 @@ int Multipart::multipart_complete(std::string *error) { int Multipart::count_boundary_params(const std::string& str_header_value) { - std::string lower = tolower(str_header_value); + std::string lower = String::tolower(str_header_value); const char *header_value = lower.c_str(); char *duplicate = NULL; char *s = NULL; diff --git a/src/rule.cc b/src/rule.cc index 59be808a..51d3e7d2 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -31,11 +31,13 @@ #include "actions/tag.h" #include "variables/variations/exclusion.h" #include "src/utils.h" +#include "utils/msc_string.h" #include "modsecurity/rules.h" #include "src/macro_expansion.h" using modsecurity::Variables::Variations::Exclusion; +using modsecurity::utils::String; namespace modsecurity { @@ -426,8 +428,9 @@ bool Rule::evaluate(Transaction *trasn) { } #ifndef NO_LOGS - trasn->debug(9, "Target value: \"" + limitTo(80, - toHexIfNeeded(value)) + "\" (Variable: " + v->m_key + ")"); + trasn->debug(9, "Target value: \"" + String::limitTo(80, + String::toHexIfNeeded(value)) \ + + "\" (Variable: " + v->m_key + ")"); #endif ret = this->op->evaluateInternal(trasn, value); @@ -450,10 +453,10 @@ bool Rule::evaluate(Transaction *trasn) { if (this->op->m_match_message.empty() == true) { ruleMessage->m_match = "Matched \"Operator `" + this->op->m_op + "' with parameter `" + - limitTo(200, this->op->m_param) + + String::limitTo(200, this->op->m_param) + "' against variable `" + v->m_key + "' (Value: `" + - limitTo(100, toHexIfNeeded(value)) + "' ) \" at " + - v->m_key; + String::limitTo(100, String::toHexIfNeeded(value)) + + "' ) \" at " + v->m_key; } else { ruleMessage->m_match = this->op->m_match_message; } diff --git a/src/rules_exceptions.cc b/src/rules_exceptions.cc index ae9e5efb..b5d92ac7 100644 --- a/src/rules_exceptions.cc +++ b/src/rules_exceptions.cc @@ -18,14 +18,17 @@ #include #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; namespace modsecurity { bool RulesExceptions::load(const std::string &a, std::string *error) { - std::vector toRemove = modsecurity::split(a, ' '); + std::vector toRemove = String::split(a, ' '); for (std::string &a : toRemove) { - std::string b = removeBracketsIfNeeded(a); + std::string b = String::removeBracketsIfNeeded(a); size_t dash = b.find('-'); if (dash != std::string::npos) { diff --git a/src/transaction.cc b/src/transaction.cc index 73874568..8b17b072 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -42,6 +42,7 @@ #include "audit_log/audit_log.h" #include "src/unique_id.h" #include "src/utils.h" +#include "utils/msc_string.h" #include "modsecurity/rule.h" #include "modsecurity/rules_properties.h" #include "src/actions/allow.h" @@ -50,6 +51,7 @@ using modsecurity::actions::Action; using modsecurity::RequestBodyProcessor::Multipart; using modsecurity::RequestBodyProcessor::XML; +using modsecurity::utils::String; namespace modsecurity { @@ -245,7 +247,7 @@ int Transaction::processConnection(const char *client, int cPort, bool Transaction::extractArguments(const std::string &orig, const std::string& buf) { char sep1 = '&'; - std::vector key_value_sets = split(buf, sep1); + std::vector key_value_sets = String::split(buf, sep1); for (std::string t : key_value_sets) { char sep2 = '='; @@ -257,7 +259,7 @@ bool Transaction::extractArguments(const std::string &orig, std::string key; std::string value; - std::vector key_value = split(t, sep2); + std::vector key_value = String::split(t, sep2); for (auto& a : key_value) { if (i == 0) { key = a; @@ -492,16 +494,16 @@ int Transaction::addRequestHeader(const std::string& key, this->m_collections.store("REQUEST_HEADERS:" + key, value); - std::string keyl = tolower(key); + std::string keyl = String::tolower(key); if (keyl == "authorization") { - std::vector type = split(value, ' '); + std::vector type = String::split(value, ' '); this->m_collections.store("AUTH_TYPE", type[0]); } if (keyl == "cookie") { - std::vector cookies = split(value, ';'); + std::vector cookies = String::split(value, ';'); while (cookies.empty() == false) { - std::vector s = split(cookies.back(), '='); + std::vector s = String::split(cookies.back(), '='); if (s.size() > 1) { if (s[0].at(0) == ' ') { s[0].erase(0, 1); @@ -523,7 +525,7 @@ int Transaction::addRequestHeader(const std::string& key, if (keyl == "content-type") { std::string multipart("multipart/form-data"); - std::string l = tolower(value); + std::string l = String::tolower(value); if (l.compare(0, multipart.length(), multipart) == 0) { this->m_requestBodyType = MultiPartRequestBody; m_collections.store("REQBODY_PROCESSOR", "MULTIPART"); @@ -536,7 +538,7 @@ int Transaction::addRequestHeader(const std::string& key, } if (keyl == "host") { - std::vector host = split(value, ':'); + std::vector host = String::split(value, ':'); m_collections.store("SERVER_NAME", host[0]); } return 1; @@ -941,7 +943,7 @@ int Transaction::addResponseHeader(const std::string& key, this->m_collections.store("RESPONSE_HEADERS:" + key, value); - if (tolower(key) == "content-type") { + if (String::tolower(key) == "content-type") { this->m_responseContentType->assign(value); } return 1; @@ -1300,14 +1302,16 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); - ss << dash_if_empty( + ss << String::dash_if_empty( this->m_collections.resolveFirst("REQUEST_HEADERS:Host")) << " "; - ss << dash_if_empty(this->m_clientIpAddress) << " "; + ss << String::dash_if_empty(this->m_clientIpAddress) << " "; /** TODO: Check variable */ - ss << dash_if_empty(this->m_collections.resolveFirst("REMOTE_USER")); + ss << String::dash_if_empty( + this->m_collections.resolveFirst("REMOTE_USER")); ss << " "; /** TODO: Check variable */ - ss << dash_if_empty(this->m_collections.resolveFirst("LOCAL_USER")); + ss << String::dash_if_empty( + this->m_collections.resolveFirst("LOCAL_USER")); ss << " "; ss << tstr << " "; @@ -1320,14 +1324,16 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, ss << this->m_httpCodeReturned << " "; ss << this->m_responseBody.tellp(); /** TODO: Check variable */ - ss << dash_if_empty(this->m_collections.resolveFirst("REFERER")) << " "; + ss << String::dash_if_empty( + this->m_collections.resolveFirst("REFERER")) << " "; ss << "\""; - ss << dash_if_empty( + ss << String::dash_if_empty( this->m_collections.resolveFirst("REQUEST_HEADERS:User-Agent")); ss << "\" "; ss << this->m_id << " "; /** TODO: Check variable */ - ss << dash_if_empty(this->m_collections.resolveFirst("REFERER")) << " "; + ss << String::dash_if_empty( + this->m_collections.resolveFirst("REFERER")) << " "; ss << filename << " "; ss << "0" << " "; @@ -1424,7 +1430,7 @@ std::string Transaction::toJSON(int parts) { const unsigned char *buf; size_t len; yajl_gen g = NULL; - std::string ts = ascTime(&m_timeStamp).c_str(); + std::string ts = String::ascTime(&m_timeStamp).c_str(); std::string uniqueId = UniqueId::uniqueId(); g = yajl_gen_alloc(NULL); diff --git a/src/utils.cc b/src/utils.cc index 029c6fdc..01b947e5 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -133,28 +133,6 @@ int urldecode_nonstrict_inplace(unsigned char *input, } -std::string removeBracketsIfNeeded(std::string a) { - if ((a.at(0) == '"') && (a.at(a.length()-1) == '"')) { - a.pop_back(); - a.erase(0, 1); - } - return a; -} - - -std::vector split(std::string str, char delimiter) { - std::vector internal; - std::stringstream ss(str); // Turn the string into a stream. - std::string tok; - - while (getline(ss, tok, delimiter)) { - internal.push_back(tok); - } - - return internal; -} - - double random_number(const double from, const double to) { std::random_device rd; std::mt19937 mt(rd()); @@ -164,22 +142,6 @@ double random_number(const double from, const double to) { } -std::string dash_if_empty(const std::string *str) { - if (str == NULL || str->empty()) { - return "-"; - } - - return *str; -} - - -std::string dash_if_empty(const char *str) { - if (str == NULL || strlen(str) == 0) { - return "-"; - } - - return std::string(str); -} double generate_transaction_unique_id() { @@ -187,44 +149,6 @@ double generate_transaction_unique_id() { } -std::string ascTime(time_t *t) { - std::string ts = std::ctime(t); - ts.pop_back(); - return ts; -} - - -void chomp(std::string *str) { - std::string::size_type pos = str->find_last_not_of("\n\r"); - if (pos != std::string::npos) { - str->erase(pos+1, str->length()-pos-1); - } -} - - -std::string tolower(std::string str) { - std::string value; - value.resize(str.length()); - - std::transform(str.begin(), - str.end(), - value.begin(), - ::tolower); - - return value; -} - -std::string toupper(std::string str) { - std::locale loc; - std::string value; - - for (std::string::size_type i=0; i < str.length(); ++i) { - value.assign(value + std::toupper(str[i], loc)); - } - - return value; -} - const char SAFE[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -678,48 +602,6 @@ unsigned char *c2x(unsigned what, unsigned char *where) { } -std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - return output; -} - - -std::string limitTo(int amount, const std::string &str) { - std::string ret; - - if (str.length() > amount) { - ret.assign(str, 0, amount); - ret = ret + " (" + std::to_string(str.length() - amount) + " " \ - "characters omitted)"; - return ret; - } - - return str; -} - -std::string toHexIfNeeded(const std::string &str) { - std::stringstream res; - - for (int i = 0; i < str.size(); i++) { - int c = str.at(i); - if (c < 32 || c > 126) { - res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; - } else { - res << str.at(i); - } - } - - return res.str(); -} std::vector expandEnv(const std::string& var, int flags) { diff --git a/src/utils.h b/src/utils.h index ae57435d..1ad29273 100644 --- a/src/utils.h +++ b/src/utils.h @@ -30,19 +30,12 @@ namespace modsecurity { - std::vector split(std::string str, char delimiter); int urldecode_nonstrict_inplace(unsigned char *input, uint64_t input_len, int *invalid_count, int *changed); double random_number(const double from, const double to); double generate_transaction_unique_id(); - std::string ascTime(time_t *t); void createDir(std::string dir, int mode); - std::string dash_if_empty(const std::string *str); - std::string dash_if_empty(const char *str); - void chomp(std::string *str); std::string uri_decode(const std::string & sSrc); - std::string tolower(std::string str); - std::string toupper(std::string str); double cpu_seconds(void); int js_decode_nonstrict_inplace(unsigned char *input, int64_t input_len); unsigned char x2c(unsigned char *what); @@ -52,16 +45,12 @@ namespace modsecurity { int html_entities_decode_inplace(unsigned char *input, int input_len); int normalize_path_inplace(unsigned char *input, int input_len, int win, int *changed); - std::string string_to_hex(const std::string& input); int urldecode_uni_nonstrict_inplace_ex(Transaction *transaction, unsigned char *input, int64_t input_len, int *changed); std::string phase_name(int x); - std::string limitTo(int amount, const std::string &str); - std::string toHexIfNeeded(const std::string &str); std::vector expandEnv(const std::string& var, int flags); std::string find_resource(const std::string& file, const std::string& param); - std::string removeBracketsIfNeeded(std::string a); } // namespace modsecurity diff --git a/src/utils/mbedtls/mbed-tls-config.h b/src/utils/mbedtls/mbed-tls-config.h index d1db0d82..ad564cfc 100644 --- a/src/utils/mbedtls/mbed-tls-config.h +++ b/src/utils/mbedtls/mbed-tls-config.h @@ -869,7 +869,7 @@ * * Enable the checkup functions (*_self_test). */ -#define MBEDTLS_SELF_TEST +//#define MBEDTLS_SELF_TEST /** * \def MBEDTLS_SHA256_SMALLER diff --git a/src/utils/msc_string.cc b/src/utils/msc_string.cc new file mode 100644 index 00000000..d183435b --- /dev/null +++ b/src/utils/msc_string.cc @@ -0,0 +1,175 @@ +/* + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined _MSC_VER +#include +#elif defined __GNUC__ +#include +#include +#endif + +#include "modsecurity/modsecurity.h" + +#include "utils/msc_string.h" + + +namespace modsecurity { +namespace utils { + + +std::string String::ascTime(time_t *t) { + std::string ts = std::ctime(t); + ts.pop_back(); + return ts; +} + + +std::string String::dash_if_empty(const std::string *str) { + if (str == NULL || str->empty()) { + return "-"; + } + + return *str; +} + + +std::string String::dash_if_empty(const char *str) { + if (str == NULL || strlen(str) == 0) { + return "-"; + } + + return std::string(str); +} + + +std::string String::limitTo(int amount, const std::string &str) { + std::string ret; + + if (str.length() > amount) { + ret.assign(str, 0, amount); + ret = ret + " (" + std::to_string(str.length() - amount) + " " \ + "characters omitted)"; + return ret; + } + + return str; +} + + +std::string String::removeBracketsIfNeeded(std::string a) { + if ((a.at(0) == '"') && (a.at(a.length()-1) == '"')) { + a.pop_back(); + a.erase(0, 1); + } + return a; +} + + +std::string String::string_to_hex(const std::string& input) { + static const char* const lut = "0123456789ABCDEF"; + size_t len = input.length(); + + std::string output; + output.reserve(2 * len); + for (size_t i = 0; i < len; ++i) { + const unsigned char c = input[i]; + output.push_back(lut[c >> 4]); + output.push_back(lut[c & 15]); + } + return output; +} + + +std::string String::toHexIfNeeded(const std::string &str) { + std::stringstream res; + + for (int i = 0; i < str.size(); i++) { + int c = str.at(i); + if (c < 32 || c > 126) { + res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; + } else { + res << str.at(i); + } + } + + return res.str(); +} + + +std::string String::tolower(std::string str) { + std::string value; + value.resize(str.length()); + + std::transform(str.begin(), + str.end(), + value.begin(), + ::tolower); + + return value; +} + + +std::string String::toupper(std::string str) { + std::locale loc; + std::string value; + + for (std::string::size_type i=0; i < str.length(); ++i) { + value.assign(value + std::toupper(str[i], loc)); + } + + return value; +} + + +std::vector String::split(std::string str, char delimiter) { + std::vector internal; + std::stringstream ss(str); // Turn the string into a stream. + std::string tok; + + while (getline(ss, tok, delimiter)) { + internal.push_back(tok); + } + + return internal; +} + + +void String::chomp(std::string *str) { + std::string::size_type pos = str->find_last_not_of("\n\r"); + if (pos != std::string::npos) { + str->erase(pos+1, str->length()-pos-1); + } +} + + +} // namespace utils +} // namespace modsecurity diff --git a/src/utils/msc_string.h b/src/utils/msc_string.h new file mode 100644 index 00000000..0abe85f8 --- /dev/null +++ b/src/utils/msc_string.h @@ -0,0 +1,47 @@ +/* + * 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. + * + */ + +#include +#include +#include +#include + +#ifndef SRC_UTILS_MSC_STRING_H_ +#define SRC_UTILS_MSC_STRING_H_ + +namespace modsecurity { +namespace utils { + + +class String { + public: + static std::string ascTime(time_t *t); + static std::string dash_if_empty(const char *str); + static std::string dash_if_empty(const std::string *str); + static std::string limitTo(int amount, const std::string &str); + static std::string removeBracketsIfNeeded(std::string a); + static std::string string_to_hex(const std::string& input); + static std::string toHexIfNeeded(const std::string &str); + static std::string tolower(std::string str); + static std::string toupper(std::string str); + static std::vector split(std::string str, char delimiter); + static void chomp(std::string *str); +}; + + +} // namespace utils +} // namespace modsecurity + +#endif // SRC_UTILS_MSC_STRING_H_ diff --git a/src/variables/rule.cc b/src/variables/rule.cc index 20a0134e..04e79f16 100644 --- a/src/variables/rule.cc +++ b/src/variables/rule.cc @@ -45,6 +45,9 @@ #include "src/actions/log_data.h" #include "src/actions/msg.h" #include "src/utils.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; namespace modsecurity { namespace Variables { @@ -53,7 +56,7 @@ void Rule::evaluateInternal(Transaction *t, modsecurity::Rule *rule, std::vector *l) { std::map envs; - std::string m_name_upper = toupper(m_name); + std::string m_name_upper = String::toupper(m_name); // id envs.insert(std::pair("RULE:id", @@ -95,7 +98,7 @@ void Rule::evaluateInternal(Transaction *t, } for (auto& x : envs) { - std::string xup = toupper(x.first); + std::string xup = String::toupper(x.first); if ((xup.substr(0, m_name_upper.size() + 1) .compare(m_name_upper + ":") != 0) && (xup != m_name_upper)) { diff --git a/src/variables/variable.cc b/src/variables/variable.cc index ae35f13e..c21410f0 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -23,7 +23,9 @@ #include "modsecurity/transaction.h" #include "variations/exclusion.h" #include "src/utils.h" +#include "utils/msc_string.h" +using modsecurity::utils::String; using modsecurity::Variables::Variations::Exclusion; namespace modsecurity { @@ -36,7 +38,8 @@ Variable::Variable(std::string name) m_isExclusion(false), m_isCount(false) { if (m_name.find(":") != std::string::npos) { - std::string col = toupper(std::string(m_name, 0, m_name.find(":"))); + std::string col = String::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" @@ -52,19 +55,19 @@ Variable::Variable(std::string name) m_type = MultipleMatches; } - if (tolower(m_name) == "tx") { + if (String::tolower(m_name) == "tx") { m_collectionName = "TX"; m_type = MultipleMatches; - } else if (tolower(m_name) == "ip") { + } else if (String::tolower(m_name) == "ip") { m_collectionName = "IP"; m_type = MultipleMatches; - } else if (tolower(m_name) == "global") { + } else if (String::tolower(m_name) == "global") { m_collectionName = "GLOBAL"; m_type = MultipleMatches; - } else if (tolower(m_name) == "resource") { + } else if (String::tolower(m_name) == "resource") { m_collectionName = "RESOURCE"; m_type = MultipleMatches; - } else if (tolower(m_name) == "session") { + } else if (String::tolower(m_name) == "session") { m_collectionName = "SESSION"; m_type = MultipleMatches; } else if (m_name.find(".") != std::string::npos) { @@ -83,7 +86,8 @@ Variable::Variable(std::string name, VariableKind kind) m_isExclusion(false), m_isCount(false) { if (m_name.find(":") != std::string::npos) { - std::string col = toupper(std::string(m_name, 0, m_name.find(":"))); + std::string col = String::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" @@ -99,19 +103,19 @@ Variable::Variable(std::string name, VariableKind kind) m_type = MultipleMatches; } - if (tolower(m_name) == "tx") { + if (String::tolower(m_name) == "tx") { m_collectionName = "TX"; m_type = MultipleMatches; - } else if (tolower(m_name) == "ip") { + } else if (String::tolower(m_name) == "ip") { m_collectionName = "IP"; m_type = MultipleMatches; - } else if (tolower(m_name) == "global") { + } else if (String::tolower(m_name) == "global") { m_collectionName = "GLOBAL"; m_type = MultipleMatches; - } else if (tolower(m_name) == "resource") { + } else if (String::tolower(m_name) == "resource") { m_collectionName = "RESOURCE"; m_type = MultipleMatches; - } else if (tolower(m_name) == "session") { + } else if (String::tolower(m_name) == "session") { m_collectionName = "SESSION"; m_type = MultipleMatches; } else if (m_name.find(".") != std::string::npos) { diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 558b7d07..9653ed2b 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -29,7 +29,9 @@ #include "common/colors.h" #include "unit/unit_test.h" #include "src/utils.h" +#include "utils/msc_string.h" +using modsecurity::utils::String; using modsecurity_test::UnitTest; using modsecurity_test::ModSecurityTest; using modsecurity_test::ModSecurityTestResults; @@ -89,7 +91,7 @@ void perform_unit_test(ModSecurityTest *test, UnitTest *t, if (test->m_automake_output) { std::cout << t->name << " " - << modsecurity::toHexIfNeeded(t->input) << std::endl; + << String::toHexIfNeeded(t->input) << std::endl; } } diff --git a/test/unit/unit_test.cc b/test/unit/unit_test.cc index 02e63f0e..c1325ea9 100644 --- a/test/unit/unit_test.cc +++ b/test/unit/unit_test.cc @@ -25,6 +25,9 @@ #include "common/colors.h" #include "src/utils.h" #include "src/utils/regex.h" +#include "utils/msc_string.h" + +using modsecurity::utils::String; namespace modsecurity_test { @@ -108,9 +111,9 @@ std::string UnitTest::print() { i << this->obtained << "\"" << std::endl; } if (this->output != this->obtainedOutput) { - i << "Expecting: \"" << modsecurity::toHexIfNeeded(this->output); + i << "Expecting: \"" << String::toHexIfNeeded(this->output); i << "\" - returned: \""; - i << modsecurity::toHexIfNeeded(this->obtainedOutput) << "\""; + i << String::toHexIfNeeded(this->obtainedOutput) << "\""; i << std::endl; }