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.
This commit is contained in:
Eduardo Arias 2024-04-23 17:40:24 -03:00
parent 50c35345ed
commit 50e78331b1

View File

@ -25,9 +25,15 @@
#include <utility>
#include <map>
#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));
}
}