From 50e78331b1b79d907fd77204e9b3a8bb26a8dab6 Mon Sep 17 00:00:00 2001 From: Eduardo Arias Date: Tue, 23 Apr 2024 17:40:24 -0300 Subject: [PATCH] Updated Env::evaluate to support case-insensitive environment variable names in Windows - Env::evaluate - Environment variable names in Windows are case-insensitive, so in the Windows build we use strcasecmp to ignore case when matching variables in transaction->m_variableEnvs. - If the variable is found, we use the expected variable name to create the VariableValue instance, as further rule processing will look for the variable using case-sensitive comparisons. - This code is not limited to Windows to avoid another #ifdef block because for other platforms, because the env variable names are case-sensitive the value from either x.first and m_name will be the same. - In Windows build, avoid redefining environ, already defined by including stdlib.h. --- src/variables/env.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/variables/env.cc b/src/variables/env.cc index dfb2c3f0..bf40954a 100644 --- a/src/variables/env.cc +++ b/src/variables/env.cc @@ -25,9 +25,15 @@ #include #include +#ifdef WIN32 +#include "src/compat/msvc.h" +#endif + #include "modsecurity/transaction.h" +#ifndef WIN32 extern char **environ; +#endif namespace modsecurity { namespace variables { @@ -47,12 +53,20 @@ void Env::evaluate(Transaction *transaction, transaction->m_variableEnvs.insert(a); } + const auto hasName = m_name.length() > 0; for (auto& x : transaction->m_variableEnvs) { - if (x.first != m_name && m_name.length() > 0) { +#ifndef WIN32 + if (hasName && x.first != m_name) { +#else + if (hasName && strcasecmp(x.first.c_str(), m_name.c_str()) != 0) { +#endif continue; } - if (!m_keyExclusion.toOmit(x.first)) { - l->push_back(new VariableValue(&m_collectionName, &x.first, + // (Windows) we need to keep the case from the rule in case that from + // the environment differs. + const auto &key = hasName ? m_name : x.first; + if (!m_keyExclusion.toOmit(key)) { + l->push_back(new VariableValue(&m_collectionName, &key, &x.second)); } }