From c0b60ea1a341366330b226513b8efe6778defcb2 Mon Sep 17 00:00:00 2001 From: jens Date: Wed, 1 Apr 2026 22:29:18 +0200 Subject: [PATCH 1/8] Upgrade to mbedtls v4.1 --- others/mbedtls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/others/mbedtls b/others/mbedtls index 2ca6c285a0..0fe989b6b5 160000 --- a/others/mbedtls +++ b/others/mbedtls @@ -1 +1 @@ -Subproject commit 2ca6c285a0dd3f33982dd57299012dacab1ff206 +Subproject commit 0fe989b6b514192783c469039edd325fd0989806 From c43e0c8a32a1696bf54651731e9b8ecaa2c41d03 Mon Sep 17 00:00:00 2001 From: Easton97-Jens <66330090+Easton97-Jens@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:02:24 +0200 Subject: [PATCH 2/8] Refactor and improve SHA1 digest handling and mbedtls integration - Migrate to TF-PSA-Crypto layout - Fix include and linkage issues - Harden runtime checks - Improve error and exception handling - Refactor digest helper and buffer usage --- Makefile.am | 3 +- build/win32/CMakeLists.txt | 30 +++++++++++++-- configure.ac | 3 +- others/Makefile.am | 25 +++++++----- src/Makefile.am | 3 +- src/utils/md5.h | 5 +-- src/utils/sha1.h | 79 +++++++++++++++++++++++--------------- 7 files changed, 96 insertions(+), 52 deletions(-) diff --git a/Makefile.am b/Makefile.am index 7ac184b504..460303cb7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,7 @@ cppcheck: --enable=warning,style,performance,portability,unusedFunction,missingInclude \ --inconclusive \ --template="warning: {file},{line},{severity},{id},{message}" \ - -I headers -I . -I $(top_srcdir)/others -I $(top_srcdir)/src -I $(top_srcdir)/others/mbedtls/include \ + -I headers -I . -I $(top_srcdir)/others -I $(top_srcdir)/src -I $(top_srcdir)/others/mbedtls/include -I $(top_srcdir)/others/mbedtls/tf-psa-crypto/include -I $(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/include \ --error-exitcode=1 \ -i "src/parser/seclang-parser.cc" -i "src/parser/seclang-scanner.cc" \ -i others \ @@ -99,4 +99,3 @@ pkgconfig_DATA = modsecurity.pc EXTRA_DIST = modsecurity.pc.in \ modsecurity.conf-recommended \ unicode.mapping - diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index fbf39f08d9..8dad8ba8ce 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -51,10 +51,32 @@ target_compile_definitions(libinjection PRIVATE LIBINJECTION_VERSION="${LIBINJEC project(mbedcrypto C) set(MBEDTLS_DIR ${BASE_DIR}/others/mbedtls) +set(TF_PSA_CRYPTO_DIR ${MBEDTLS_DIR}/tf-psa-crypto) + +add_library(mbedcrypto STATIC + ${TF_PSA_CRYPTO_DIR}/utilities/base64.c + ${TF_PSA_CRYPTO_DIR}/utilities/constant_time.c + ${TF_PSA_CRYPTO_DIR}/platform/platform_util.c + ${TF_PSA_CRYPTO_DIR}/extras/md.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/md5.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/sha1.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/sha256.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/sha512.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/sha3.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/ripemd160.c + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src/psa_util_internal.c +) -add_library(mbedcrypto STATIC ${MBEDTLS_DIR}/library/base64.c ${MBEDTLS_DIR}/library/sha1.c ${MBEDTLS_DIR}/library/md5.c ${MBEDTLS_DIR}/library/platform_util.c ${MBEDTLS_DIR}/library/constant_time.c) - -target_include_directories(mbedcrypto PRIVATE ${MBEDTLS_DIR}/include) +target_include_directories(mbedcrypto PRIVATE + ${MBEDTLS_DIR}/include + ${TF_PSA_CRYPTO_DIR}/include + ${TF_PSA_CRYPTO_DIR}/core + ${TF_PSA_CRYPTO_DIR}/extras + ${TF_PSA_CRYPTO_DIR}/library + ${TF_PSA_CRYPTO_DIR}/utilities + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/include + ${TF_PSA_CRYPTO_DIR}/drivers/builtin/src +) # get mbedtls version with git describe execute_process( @@ -137,7 +159,7 @@ file(GLOB_RECURSE libModSecuritySources ${BASE_DIR}/src/*.cc) add_library(libModSecurity SHARED ${libModSecuritySources}) target_compile_definitions(libModSecurity PRIVATE WITH_PCRE2) -target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others ${MBEDTLS_DIR}/include) +target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others ${MBEDTLS_DIR}/include ${TF_PSA_CRYPTO_DIR}/include ${TF_PSA_CRYPTO_DIR}/drivers/builtin/include) target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 libinjection mbedcrypto Poco::Poco Iphlpapi.lib) macro(add_package_dependency project compile_definition link_library flag) diff --git a/configure.ac b/configure.ac index 03295be063..7bdcca6bc4 100644 --- a/configure.ac +++ b/configure.ac @@ -84,7 +84,7 @@ AC_DEFUN([LIBINJECTION_VERSION], m4_esyscmd_s(cd "others/libinjection" && git de AC_SUBST([LIBINJECTION_VERSION]) # Check for Mbed TLS -if ! test -f "${srcdir}/others/mbedtls/library/base64.c"; then +if ! test -f "${srcdir}/others/mbedtls/tf-psa-crypto/utilities/base64.c"; then AC_MSG_ERROR([\ @@ -532,4 +532,3 @@ if test "$aflFuzzer" = "true"; then echo " $ export CC=afl-clang-fast " echo " " fi - diff --git a/others/Makefile.am b/others/Makefile.am index b102a0330c..8ad042cdeb 100644 --- a/others/Makefile.am +++ b/others/Makefile.am @@ -15,19 +15,24 @@ noinst_HEADERS = \ libinjection/src/libinjection_sqli.h \ libinjection/src/libinjection_sqli_data.h \ libinjection/src/libinjection_xss.h \ - mbedtls/include/mbedtls/base64.h \ - mbedtls/include/mbedtls/check_config.h \ + mbedtls/tf-psa-crypto/include/mbedtls/base64.h \ mbedtls/include/mbedtls/mbedtls_config.h \ - mbedtls/include/mbedtls/md5.h \ - mbedtls/include/mbedtls/platform.h \ - mbedtls/include/mbedtls/sha1.h + mbedtls/tf-psa-crypto/include/mbedtls/md.h \ + mbedtls/tf-psa-crypto/include/mbedtls/platform.h libmbedtls_la_SOURCES = \ - mbedtls/library/base64.c \ - mbedtls/library/md5.c \ - mbedtls/library/sha1.c \ - mbedtls/library/platform_util.c + mbedtls/tf-psa-crypto/utilities/base64.c \ + mbedtls/tf-psa-crypto/utilities/constant_time.c \ + mbedtls/tf-psa-crypto/platform/platform_util.c \ + mbedtls/tf-psa-crypto/extras/md.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/md5.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha1.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha256.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha512.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha3.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ripemd160.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_util_internal.c -libmbedtls_la_CFLAGS = -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" -I$(top_srcdir)/others/mbedtls/include +libmbedtls_la_CFLAGS = -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" -I$(top_srcdir)/others/mbedtls/include -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/include -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/core -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/extras -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/library -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/utilities -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/include -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/src libmbedtls_la_CPPFLAGS = libmbedtls_la_LIBADD = diff --git a/src/Makefile.am b/src/Makefile.am index 14c26697b5..48515500e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,6 +296,8 @@ libmodsecurity_la_CPPFLAGS = \ -g \ -I$(top_srcdir)/others \ -I$(top_srcdir)/others/mbedtls/include \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/include \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/include \ -fPIC \ -O3 \ -I$(top_srcdir)/headers \ @@ -343,4 +345,3 @@ libmodsecurity_la_LIBADD = \ $(MAXMIND_LDADD) \ $(SSDEEP_LDADD) \ $(YAJL_LDADD) - diff --git a/src/utils/md5.h b/src/utils/md5.h index 68f5d748e4..85c21bf1fd 100644 --- a/src/utils/md5.h +++ b/src/utils/md5.h @@ -17,16 +17,15 @@ #define SRC_UTILS_MD5_H_ #include "src/utils/sha1.h" -#include "mbedtls/md5.h" #include namespace modsecurity::Utils { -class Md5 : public DigestImpl<&mbedtls_md5, 16> { +class Md5 : public DigestImpl { }; } // namespace modsecurity::Utils -#endif // SRC_UTILS_MD5_H_ \ No newline at end of file +#endif // SRC_UTILS_MD5_H_ diff --git a/src/utils/sha1.h b/src/utils/sha1.h index a40d7fa1c8..2bb5774c59 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -3,7 +3,7 @@ * Copyright (c) 2015 - 2021 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 + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -16,60 +16,79 @@ #ifndef SRC_UTILS_SHA1_H_ #define SRC_UTILS_SHA1_H_ +#include +#include #include -#include +#include #include "src/utils/string.h" -#include "mbedtls/sha1.h" +#include "mbedtls/md.h" namespace modsecurity::Utils { +class DigestCalculationException : public std::exception { + public: + explicit DigestCalculationException(const char *message) noexcept + : m_message(message) { } -using DigestOp = int (*)(const unsigned char *, size_t, unsigned char []); + const char *what() const noexcept override { + return m_message; + } + private: + const char *m_message; +}; -template + +template class DigestImpl { public: - static std::string digest(const std::string& input) { - return digestHelper(input, [](const auto digest) { - return std::string(digest); - }); + const auto digestBytes = calculateDigest(input); + return std::string(digestBytes.begin(), digestBytes.end()); } static void digestReplace(std::string& value) { - digestHelper(value, [&value](const auto digest) mutable { - value = digest; - }); + const auto digestBytes = calculateDigest(value); + value.assign(digestBytes.begin(), digestBytes.end()); } - static std::string hexdigest(const std::string &input) { - return digestHelper(input, [](const auto digest) { - return utils::string::string_to_hex(digest); - }); + static std::string hexdigest(const std::string& input) { + const auto digestBytes = calculateDigest(input); + const std::string digestString(digestBytes.begin(), digestBytes.end()); + return utils::string::string_to_hex(digestString); } -private: - - template - static auto digestHelper(const std::string &input, - ConvertOp convertOp) -> auto { - char digest[DigestSize]; - - const auto ret = (*digestOp)(reinterpret_cast(input.c_str()), - input.size(), reinterpret_cast(digest)); - assert(ret == 0); - - return convertOp(std::string_view(digest, DigestSize)); + private: + static std::array calculateDigest( + std::string_view input) { + std::array digestBytes = {}; + + const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(DigestType); + if (mdInfo == nullptr) { + throw DigestCalculationException( + "mbedtls_md_info_from_type() returned nullptr"); + } + + const auto *inputBytes = + static_cast(static_cast(input.data())); + + if (const int ret = mbedtls_md( + mdInfo, + inputBytes, + input.size(), + digestBytes.data()); ret != 0) { + throw DigestCalculationException("mbedtls_md() failed"); + } + + return digestBytes; } }; -class Sha1 : public DigestImpl<&mbedtls_sha1, 20> { +class Sha1 : public DigestImpl { }; - } // namespace modsecurity::Utils #endif // SRC_UTILS_SHA1_H_ From 6afa94ba1ee76ba060858143fc64b6915a7b0762 Mon Sep 17 00:00:00 2001 From: Easton97-Jens Date: Sat, 18 Apr 2026 18:19:12 +0200 Subject: [PATCH 3/8] Update Makefile.am --- others/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/others/Makefile.am b/others/Makefile.am index 3235e067e7..3217fd7af8 100644 --- a/others/Makefile.am +++ b/others/Makefile.am @@ -16,8 +16,8 @@ noinst_HEADERS = \ libinjection/src/libinjection_sqli_data.h \ libinjection/src/libinjection_xss.h \ libinjection/src/libinjection_error.h \ - mbedtls/include/mbedtls/base64.h \ - mbedtls/include/mbedtls/check_config.h \ + mbedtls/tf-psa-crypto/include/mbedtls/base64.h \ + mbedtls/tf-psa-crypto/core/check_crypto_config.h \ mbedtls/include/mbedtls/mbedtls_config.h \ mbedtls/tf-psa-crypto/include/mbedtls/md.h \ mbedtls/tf-psa-crypto/include/mbedtls/platform.h From d713740a808c2f8d650d420629d625daf04c7318 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 18 Apr 2026 18:48:46 +0200 Subject: [PATCH 4/8] sha1/md5: fix exception safety, remove copy, and own exception message sha1/md5: fix exception safety, remove copy, and own exception message sha1/md5: fix exception safety, remove copy, and own exception message sha1/md5: fix exception safety, remove copy, and own exception message sha1/md5: fix exception safety, remove copy, and own exception message win update win update --- build/win32/CMakeLists.txt | 2 +- build/win32/conanfile.txt | 14 ++++++------ build/win32/docker/Dockerfile | 6 ++--- src/utils/sha1.h | 43 +++++++++++++++++++++++++++-------- src/utils/string.h | 24 +++++++++++++++++++ 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index 7ddd41cc73..399d4727c1 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -94,7 +94,7 @@ message("-- Detecting Mbed TLS version - ${MBEDTLS_VERSION}") project(libModSecurity VERSION - 3.0.12 + 3.0.14 LANGUAGES CXX ) diff --git a/build/win32/conanfile.txt b/build/win32/conanfile.txt index b8f9721d0a..29dbde4aa4 100644 --- a/build/win32/conanfile.txt +++ b/build/win32/conanfile.txt @@ -1,13 +1,13 @@ [requires] yajl/2.1.0 -pcre2/10.42 -libxml2/2.12.6 -lua/5.4.6 -libcurl/8.6.0 -lmdb/0.9.31 -libmaxminddb/1.9.1 +pcre2/10.44 +libxml2/2.15.2 +lua/5.5.0 +libcurl/8.19.0 +lmdb/0.9.32 +libmaxminddb/1.12.2 dirent/1.24 -poco/1.13.3 +poco/1.14.2 [generators] CMakeDeps diff --git a/build/win32/docker/Dockerfile b/build/win32/docker/Dockerfile index e01897904c..b81e0b85f6 100644 --- a/build/win32/docker/Dockerfile +++ b/build/win32/docker/Dockerfile @@ -24,7 +24,7 @@ RUN C:\TEMP\InstallBuildTools.cmd C:\TEMP\vs_buildtools.exe --quiet --wait --nor --installPath C:\BuildTools # download & install GIT -ARG GIT_VERSION=2.44.0 +ARG GIT_VERSION=2.53.0 ARG GIT_BINARY=Git-${GIT_VERSION}-64-bit.exe ARG GIT_URL=https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/${GIT_BINARY} @@ -35,7 +35,7 @@ RUN %INSTALLER% /SP- /VERYSILENT /SUPPRESSMSGBOXES /NOCANCEL ` /NORESTART /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /LOADINF=git.inf # download & setup conan -ARG CONAN_VERSION=2.10.2 +ARG CONAN_VERSION=2.27.1 ARG CONAN_BINARY=conan-${CONAN_VERSION}-windows-x86_64-installer.exe ARG CONAN_URL=https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/${CONAN_BINARY} @@ -87,7 +87,7 @@ RUN cmd.exe /C copy "C:\Program Files\GIT\usr\bin" \bin > NUL RUN cmd.exe /C copy "C:\Program Files\GIT\usr\bin\echo.exe" \bin\echo > NUL # disable tests that don't work on windows -ARG JQ_VERSION=1.7.1 +ARG JQ_VERSION=1.8.1 ARG JQ_BINARY=jq-windows-amd64.exe ARG JQ_URL=https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/${JQ_BINARY} diff --git a/src/utils/sha1.h b/src/utils/sha1.h index 2bb5774c59..8a7a853112 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -17,6 +17,8 @@ #define SRC_UTILS_SHA1_H_ #include +#include +#include #include #include #include @@ -28,15 +30,15 @@ namespace modsecurity::Utils { class DigestCalculationException : public std::exception { public: - explicit DigestCalculationException(const char *message) noexcept + explicit DigestCalculationException(const char *message) : m_message(message) { } const char *what() const noexcept override { - return m_message; + return m_message.c_str(); } private: - const char *m_message; + std::string m_message; }; @@ -44,19 +46,40 @@ template class DigestImpl { public: static std::string digest(const std::string& input) { - const auto digestBytes = calculateDigest(input); - return std::string(digestBytes.begin(), digestBytes.end()); + try { + const auto digestBytes = calculateDigest(input); + return std::string(digestBytes.begin(), digestBytes.end()); + } catch (const DigestCalculationException&) { + assert(false); + return std::string(DigestSize, '\0'); + } } static void digestReplace(std::string& value) { - const auto digestBytes = calculateDigest(value); - value.assign(digestBytes.begin(), digestBytes.end()); + try { + const auto digestBytes = calculateDigest(value); + value.assign(digestBytes.begin(), digestBytes.end()); + } catch (const DigestCalculationException&) { + assert(false); + value.assign(DigestSize, '\0'); + } } static std::string hexdigest(const std::string& input) { - const auto digestBytes = calculateDigest(input); - const std::string digestString(digestBytes.begin(), digestBytes.end()); - return utils::string::string_to_hex(digestString); + try { + const auto digestBytes = calculateDigest(input); + const auto *digestByteData = + static_cast(static_cast(digestBytes.data())); + return utils::string::string_to_hex( + digestByteData, digestBytes.size()); + } catch (const DigestCalculationException&) { + assert(false); + const std::array digestBytes = {}; + const auto *digestByteData = + static_cast(static_cast(digestBytes.data())); + return utils::string::string_to_hex( + digestByteData, digestBytes.size()); + } } private: diff --git a/src/utils/string.h b/src/utils/string.h index ca2967aa5f..ac3264aeab 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -16,6 +16,7 @@ #ifndef SRC_UTILS_STRING_H_ #define SRC_UTILS_STRING_H_ +#include #include #include #include @@ -241,6 +242,29 @@ inline unsigned char *c2x(unsigned what, unsigned char *where) { } +inline std::string string_to_hex(const std::byte *input, size_t size) { + static const char* const lut = "0123456789abcdef"; + + std::string a(size*2, 0); + char *d = a.data(); + + for (size_t i = 0; i < size; ++i) { + const std::byte b = input[i]; + *d++ = lut[std::to_integer(b >> 4)]; + *d++ = lut[std::to_integer(b & std::byte{0x0F})]; + } + + return a; +} + + +inline std::string string_to_hex(const unsigned char *input, size_t size) { + return string_to_hex( + static_cast(static_cast(input)), + size); +} + + inline std::string string_to_hex(std::string_view input) { static const char* const lut = "0123456789abcdef"; From 969c7d995de81e73e9171d7bbb2e26af1e94dac8 Mon Sep 17 00:00:00 2001 From: Easton97-Jens <66330090+Easton97-Jens@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:58:49 +0200 Subject: [PATCH 5/8] Harden Base64 error handling and add hash/base64 unit coverage --- src/actions/transformations/base64_decode.cc | 10 ++- .../transformations/base64_decode_ext.cc | 10 ++- src/actions/transformations/base64_encode.cc | 10 ++- src/actions/transformations/md5.cc | 3 +- src/actions/transformations/sha1.cc | 3 +- src/audit_log/writer/parallel.cc | 24 ++++- src/unique_id.cc | 8 +- src/utils/base64.cc | 73 +++++++++++---- src/utils/base64.h | 8 +- src/utils/sha1.h | 90 ++++++++----------- src/variables/remote_user.cc | 12 ++- .../unit/transformation-hash-base64.json | 37 ++++++++ test/test-suite.in | 1 + 13 files changed, 205 insertions(+), 84 deletions(-) create mode 100644 test/test-cases/unit/transformation-hash-base64.json diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index fe910e5012..e71f81350a 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -17,13 +17,21 @@ #include "src/utils/base64.h" +#include + namespace modsecurity::actions::transformations { bool Base64Decode::transform(std::string &value, const Transaction *trans) const { if (value.empty()) return false; - value = Utils::Base64::decode(value); + + std::string transformedValue; + if (!Utils::Base64::decode(value, &transformedValue)) { + return false; + } + + value = std::move(transformedValue); return true; } diff --git a/src/actions/transformations/base64_decode_ext.cc b/src/actions/transformations/base64_decode_ext.cc index e6c13987f6..0053358973 100644 --- a/src/actions/transformations/base64_decode_ext.cc +++ b/src/actions/transformations/base64_decode_ext.cc @@ -17,13 +17,21 @@ #include "src/utils/base64.h" +#include + namespace modsecurity::actions::transformations { bool Base64DecodeExt::transform(std::string &value, const Transaction *trans) const { if (value.empty()) return false; - value = Utils::Base64::decode_forgiven(value); + + std::string transformedValue; + if (!Utils::Base64::decode_forgiven(value, &transformedValue)) { + return false; + } + + value = std::move(transformedValue); return true; } diff --git a/src/actions/transformations/base64_encode.cc b/src/actions/transformations/base64_encode.cc index bf802a1e8d..24751b1910 100644 --- a/src/actions/transformations/base64_encode.cc +++ b/src/actions/transformations/base64_encode.cc @@ -17,13 +17,21 @@ #include "src/utils/base64.h" +#include + namespace modsecurity::actions::transformations { bool Base64Encode::transform(std::string &value, const Transaction *trans) const { if (value.empty()) return false; - value = Utils::Base64::encode(value); + + std::string transformedValue; + if (!Utils::Base64::encode(value, &transformedValue)) { + return false; + } + + value = std::move(transformedValue); return true; } diff --git a/src/actions/transformations/md5.cc b/src/actions/transformations/md5.cc index b1cdc93ece..dbd67061e1 100644 --- a/src/actions/transformations/md5.cc +++ b/src/actions/transformations/md5.cc @@ -21,8 +21,7 @@ namespace modsecurity::actions::transformations { bool Md5::transform(std::string &value, const Transaction *trans) const { - value = Utils::Md5::digest(value); - return true; + return Utils::Md5::digestReplace(&value); } diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index 388633455c..b8b71389ad 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -22,8 +22,7 @@ namespace modsecurity::actions::transformations { bool Sha1::transform(std::string &value, const Transaction *trans) const { - value = Utils::Sha1::digest(value); - return true; + return Utils::Sha1::digestReplace(&value); } diff --git a/src/audit_log/writer/parallel.cc b/src/audit_log/writer/parallel.cc index 5f3055f4c7..fdbc3f0277 100644 --- a/src/audit_log/writer/parallel.cc +++ b/src/audit_log/writer/parallel.cc @@ -163,8 +163,14 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) { if (m_audit->m_path1.empty() == false && m_audit->m_path2.empty() == false) { + std::string logMd5; + if (!Utils::Md5::hexdigest(log, &logMd5)) { + error->assign("Failed to calculate audit log MD5 digest"); + return false; + } + std::string msg = transaction->toOldAuditLogFormatIndex(fileName, - log.length(), Utils::Md5::hexdigest(log)); + log.length(), logMd5); ret = utils::SharedFiles::getInstance().write(m_audit->m_path2, msg, error); if (ret == false) { @@ -173,8 +179,14 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) { } if (m_audit->m_path1.empty() == false && m_audit->m_path2.empty() == true) { + std::string logMd5; + if (!Utils::Md5::hexdigest(log, &logMd5)) { + error->assign("Failed to calculate audit log MD5 digest"); + return false; + } + std::string msg = transaction->toOldAuditLogFormatIndex(fileName, - log.length(), Utils::Md5::hexdigest(log)); + log.length(), logMd5); ret = utils::SharedFiles::getInstance().write(m_audit->m_path1, msg, error); if (ret == false) { @@ -183,8 +195,14 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) { } if (m_audit->m_path1.empty() == true && m_audit->m_path2.empty() == false) { + std::string logMd5; + if (!Utils::Md5::hexdigest(log, &logMd5)) { + error->assign("Failed to calculate audit log MD5 digest"); + return false; + } + std::string msg = transaction->toOldAuditLogFormatIndex(fileName, - log.length(), Utils::Md5::hexdigest(log)); + log.length(), logMd5); ret = utils::SharedFiles::getInstance().write(m_audit->m_path2, msg, error); if (ret == false) { diff --git a/src/unique_id.cc b/src/unique_id.cc index 890188e990..c2e47e2032 100644 --- a/src/unique_id.cc +++ b/src/unique_id.cc @@ -55,6 +55,7 @@ #include #endif #include +#include #include "src/utils/sha1.h" @@ -72,7 +73,12 @@ void UniqueId::fillUniqueId() { data = macAddress + name; - this->uniqueId_str = Utils::Sha1::hexdigest(data); + std::string uniqueIdHex; + if (Utils::Sha1::hexdigest(data, &uniqueIdHex)) { + this->uniqueId_str = std::move(uniqueIdHex); + } else { + this->uniqueId_str.clear(); + } } // Based on: diff --git a/src/utils/base64.cc b/src/utils/base64.cc index e27cace943..ecd0de398a 100644 --- a/src/utils/base64.cc +++ b/src/utils/base64.cc @@ -18,54 +18,97 @@ #include #include -#include -#include +#include #include "mbedtls/base64.h" -template -inline std::string base64Helper(const char *data, const unsigned int len, Operation op) { // cppcheck-suppress syntaxError ; false positive +namespace { +using Base64MbedtlsOperation = int(*)(unsigned char *, size_t, size_t *, + const unsigned char *, size_t); + +bool base64HelperMbedtls(const char *data, const unsigned int len, + Base64MbedtlsOperation op, std::string *output) { + if (output == nullptr) { + return false; + } + + size_t out_len = 0; + + const int sizingRet = op(nullptr, 0, &out_len, + reinterpret_cast(data), len); + + if (sizingRet != 0 && sizingRet != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { + return false; + } + + std::string ret(out_len, {}); + if (out_len > 0) { + const int retCode = op(reinterpret_cast(ret.data()), + ret.size(), &out_len, + reinterpret_cast(data), len); + if (retCode != 0) { + return false; + } + + ret.resize(out_len); + } + + *output = std::move(ret); + return true; +} + +using Base64ForgivenOperation = void(*)(unsigned char *, size_t, size_t *, + const unsigned char *, size_t); + +bool base64HelperForgiven(const char *data, const unsigned int len, + Base64ForgivenOperation op, std::string *output) { + if (output == nullptr) { + return false; + } + size_t out_len = 0; op(nullptr, 0, &out_len, reinterpret_cast(data), len); std::string ret(out_len, {}); - if(out_len > 0) { + if (out_len > 0) { op(reinterpret_cast(ret.data()), ret.size(), &out_len, reinterpret_cast(data), len); ret.resize(out_len); } - return ret; + *output = std::move(ret); + return true; } +} // namespace namespace modsecurity { namespace Utils { -std::string Base64::encode(const std::string& data) { - return base64Helper(data.c_str(), data.size(), mbedtls_base64_encode); +bool Base64::encode(const std::string& data, std::string *output) { + return base64HelperMbedtls(data.c_str(), data.size(), mbedtls_base64_encode, output); } -std::string Base64::decode(const std::string& data, bool forgiven) { +bool Base64::decode(const std::string& data, std::string *output, bool forgiven) { if (forgiven) { - return decode_forgiven(data); + return decode_forgiven(data, output); } - return decode(data); + return decode(data, output); } -std::string Base64::decode(const std::string& data) { - return base64Helper(data.c_str(), strlen(data.c_str()), mbedtls_base64_decode); +bool Base64::decode(const std::string& data, std::string *output) { + return base64HelperMbedtls(data.c_str(), strlen(data.c_str()), mbedtls_base64_decode, output); } -std::string Base64::decode_forgiven(const std::string& data) { - return base64Helper(data.c_str(), data.size(), decode_forgiven_engine); +bool Base64::decode_forgiven(const std::string& data, std::string *output) { + return base64HelperForgiven(data.c_str(), data.size(), decode_forgiven_engine, output); } diff --git a/src/utils/base64.h b/src/utils/base64.h index 97639a5413..b57beb86bb 100644 --- a/src/utils/base64.h +++ b/src/utils/base64.h @@ -26,11 +26,11 @@ class Base64 { public: Base64() { } - static std::string encode(const std::string& data); + static bool encode(const std::string& data, std::string *output); - static std::string decode(const std::string& data, bool forgiven); - static std::string decode(const std::string& data); - static std::string decode_forgiven(const std::string& data); + static bool decode(const std::string& data, std::string *output, bool forgiven); + static bool decode(const std::string& data, std::string *output); + static bool decode_forgiven(const std::string& data, std::string *output); static void decode_forgiven_engine(unsigned char *plain_text, size_t plain_text_size, size_t *aiming_size, diff --git a/src/utils/sha1.h b/src/utils/sha1.h index 8a7a853112..d827d7f656 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -17,9 +17,7 @@ #define SRC_UTILS_SHA1_H_ #include -#include #include -#include #include #include @@ -28,69 +26,59 @@ namespace modsecurity::Utils { -class DigestCalculationException : public std::exception { - public: - explicit DigestCalculationException(const char *message) - : m_message(message) { } - - const char *what() const noexcept override { - return m_message.c_str(); - } - - private: - std::string m_message; -}; - template class DigestImpl { public: - static std::string digest(const std::string& input) { - try { - const auto digestBytes = calculateDigest(input); - return std::string(digestBytes.begin(), digestBytes.end()); - } catch (const DigestCalculationException&) { - assert(false); - return std::string(DigestSize, '\0'); + static bool digest(const std::string& input, std::string *output) { + if (output == nullptr) { + return false; + } + + std::array digestBytes; + if (!calculateDigest(input, &digestBytes)) { + return false; } + + output->assign(digestBytes.begin(), digestBytes.end()); + return true; } - static void digestReplace(std::string& value) { - try { - const auto digestBytes = calculateDigest(value); - value.assign(digestBytes.begin(), digestBytes.end()); - } catch (const DigestCalculationException&) { - assert(false); - value.assign(DigestSize, '\0'); + static bool digestReplace(std::string *value) { + if (value == nullptr) { + return false; } + + return digest(*value, value); } - static std::string hexdigest(const std::string& input) { - try { - const auto digestBytes = calculateDigest(input); - const auto *digestByteData = - static_cast(static_cast(digestBytes.data())); - return utils::string::string_to_hex( - digestByteData, digestBytes.size()); - } catch (const DigestCalculationException&) { - assert(false); - const std::array digestBytes = {}; - const auto *digestByteData = - static_cast(static_cast(digestBytes.data())); - return utils::string::string_to_hex( - digestByteData, digestBytes.size()); + static bool hexdigest(const std::string& input, std::string *output) { + if (output == nullptr) { + return false; + } + + std::array digestBytes; + if (!calculateDigest(input, &digestBytes)) { + return false; } + + const auto *digestByteData = + static_cast(static_cast(digestBytes.data())); + + output->assign(utils::string::string_to_hex(digestByteData, digestBytes.size())); + return true; } private: - static std::array calculateDigest( - std::string_view input) { - std::array digestBytes = {}; + static bool calculateDigest(std::string_view input, + std::array *output) { + if (output == nullptr) { + return false; + } const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(DigestType); if (mdInfo == nullptr) { - throw DigestCalculationException( - "mbedtls_md_info_from_type() returned nullptr"); + return false; } const auto *inputBytes = @@ -100,11 +88,11 @@ class DigestImpl { mdInfo, inputBytes, input.size(), - digestBytes.data()); ret != 0) { - throw DigestCalculationException("mbedtls_md() failed"); + output->data()); ret != 0) { + return false; } - return digestBytes; + return true; } }; diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index 550294c70e..cce7db1ef0 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -54,10 +54,16 @@ void RemoteUser::evaluate(Transaction *transaction, base64 = std::string(header, 6, header.length()); } - base64 = Utils::Base64::decode(base64); + std::string decodedAuthorization; + if (!Utils::Base64::decode(base64, &decodedAuthorization)) { + for (auto &a : l2) { + delete a; + } + return; + } - if (const auto pos{base64.find(":")}; pos != std::string::npos) { - transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); + if (const auto pos{decodedAuthorization.find(":")}; pos != std::string::npos) { + transaction->m_variableRemoteUser.assign(std::string(decodedAuthorization, 0, pos)); auto var = std::make_unique(&v->getKeyWithCollection(), &transaction->m_variableRemoteUser); diff --git a/test/test-cases/unit/transformation-hash-base64.json b/test/test-cases/unit/transformation-hash-base64.json new file mode 100644 index 0000000000..6082fd5ca0 --- /dev/null +++ b/test/test-cases/unit/transformation-hash-base64.json @@ -0,0 +1,37 @@ +[ + { + "type": "tfn", + "name": "sha1", + "input": "abc", + "ret": 1, + "output": "\\xa9\\x99\\x3e\\x36\\x47\\x06\\x81\\x6a\\xba\\x3e\\x25\\x71\\x78\\x50\\xc2\\x6c\\x9c\\xd0\\xd8\\x9d" + }, + { + "type": "tfn", + "name": "md5", + "input": "abc", + "ret": 1, + "output": "\\x90\\x01\\x50\\x98\\x3c\\xd2\\x4f\\xb0\\xd6\\x96\\x3f\\x7d\\x28\\xe1\\x7f\\x72" + }, + { + "type": "tfn", + "name": "base64Encode", + "input": "hello", + "ret": 1, + "output": "aGVsbG8=" + }, + { + "type": "tfn", + "name": "base64Decode", + "input": "aGVsbG8=", + "ret": 1, + "output": "hello" + }, + { + "type": "tfn", + "name": "base64Decode", + "input": "!!!!", + "ret": 1, + "output": "!!!!" + } +] diff --git a/test/test-suite.in b/test/test-suite.in index c667bf677f..ebda49fb81 100644 --- a/test/test-suite.in +++ b/test/test-suite.in @@ -199,6 +199,7 @@ TESTS+=test/test-cases/secrules-language-tests/operators/containsWord.json TESTS+=test/test-cases/secrules-language-tests/operators/detectSQLi.json TESTS+=test/test-cases/secrules-language-tests/operators/detectXSS.json TESTS+=test/test-cases/unit/operator-libinjection-error.json +TESTS+=test/test-cases/unit/transformation-hash-base64.json TESTS+=test/test-cases/secrules-language-tests/operators/endsWith.json TESTS+=test/test-cases/secrules-language-tests/operators/eq.json TESTS+=test/test-cases/secrules-language-tests/operators/ge.json From bfb8b19c67f4dab1a041e7ba2c936e83ebead062 Mon Sep 17 00:00:00 2001 From: Easton97-Jens <66330090+Easton97-Jens@users.noreply.github.com> Date: Sat, 25 Apr 2026 17:13:08 +0200 Subject: [PATCH 6/8] Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update dependencies in README for Windows build Update lmdb version to 0.9.32 in README Update README.md Update README.md --- README.md | 158 +++++++++++++++++++++++++++++++++++------- build/win32/README.md | 20 +++--- 2 files changed, 144 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 50b8833319..7bb6a0aa95 100644 --- a/README.md +++ b/README.md @@ -47,36 +47,51 @@ Keeping these connectors separated allows each project to have different release # Compilation -Before starting the compilation process, make sure that you have all the -dependencies in place. Read the subsection “Dependencies” for further -information. +Before starting the compilation process, make sure that all required dependencies are installed. +See the [Dependencies](#dependencies) and [Git submodules](#Git-submodules) section for further information. -After the compilation make sure that there are no issues on your -build/platform. We strongly recommend the utilization of the unit tests and -regression tests. These test utilities are located under the subfolder ‘tests’. +After compilation, make sure that there are no issues on your build/platform. +We strongly recommend running the unit tests and regression tests. These test utilities are located in the [`tests/`](#testing-your-patch) subfolder. -As a dynamic library, don’t forget that libmodsecurity must be installed to a location (folder) where you OS will be looking for dynamic libraries. +As a dynamic library, `libmodsecurity` must be installed in a location where your operating system can find dynamic libraries. +### Unix (Linux, macOS, FreeBSD, …) +On Unix-like systems, the project uses autotools for the compilation process. -### Unix (Linux, MacOS, FreeBSD, …) +If you are working with a git checkout, make sure to clone the repository recursively or initialize all submodules before building. +See also the [Git submodules](#git-submodules) section. -On unix the project uses autotools to help the compilation process. Please note that if you are working with `git`, don't forget to initialize and update the submodules. Here's a quick how-to: -```shell -$ git clone --recursive https://github.com/owasp-modsecurity/ModSecurity ModSecurity -$ cd ModSecurity +```sh +git clone https://github.com/owasp-modsecurity/ModSecurity ModSecurity +cd ModSecurity +```` + +This repository uses git submodules. After cloning, make sure to initialize and fetch all submodules: + +```sh +git submodule update --init --recursive +``` + +You can verify that all submodules are properly initialized with: + +```sh +git submodule status ``` +Submodules that are correctly initialized show a commit hash. +A leading `-` indicates that the submodule has not been initialized. + You can then start the build process: -```shell -$ ./build.sh -$ ./configure -$ make -$ sudo make install +```sh +./build.sh +./configure +make +sudo make install ``` -Details on distribution specific builds can be found in our Wiki: +Details on distribution-specific builds can be found in our Wiki: [Compilation Recipes](https://github.com/owasp-modsecurity/ModSecurity/wiki/Compilation-recipes) ### Windows @@ -85,15 +100,110 @@ Windows build information can be found [here](build/win32/README.md). ## Dependencies -This library is written in C++ using the C++17 standards. It also uses Flex -and Yacc to produce the “Sec Rules Language” parser. Other, mandatory dependencies include YAJL, as ModSecurity uses JSON for producing logs and its testing framework, libpcre (not yet mandatory) for processing regular expressions in SecRules, and libXML2 (not yet mandatory) which is used for parsing XML requests. +* This library is written in C++ using the C++17 standard. +* It uses Flex and Bison (Yacc) to produce the “Sec Rules Language” parser. +* Mandatory dependencies include YAJL, as ModSecurity uses JSON for logging and its testing framework. +* libXML2 (optional) is used for parsing XML requests. + +### Regular expression engine (PCRE2 / PCRE) + +* Regular expression processing in SecRules is implemented via the `Regex` utility (`src/utils/regex.*`). +* By default, ModSecurity uses **PCRE2** for regex handling. +* This is used by operators such as `@rx`, `@rxGlobal`, and `@verifyCC`. +* Build-time behavior: + + * **Default:** PCRE2 is detected and used. + * **Fallback:** legacy PCRE can be used if `--with-pcre` is explicitly provided (`WITH_PCRE`). +* In other words, current builds expect PCRE2 unless explicitly configured otherwise. + +All other dependencies are related to operators specified within SecRules or configuration directives and may not be required for compilation. + +### Operator-related dependencies + +* `libinjection` is required for the operators `@detectXSS` and `@detectSQL`. +* `curl` is required for the directive `SecRemoteRules`. + +If those libraries are missing, ModSecurity will be compiled without support for the respective operators or directives. + +### Git-submodules + +The repository includes the following submodules: + +* `others/libinjection` – used by `@detectSQLi` and `@detectXSS` operators. + +* `others/mbedtls` (TF-PSA-Crypto subset) – used for cryptographic functions and helpers (e.g. hashing, base64). + + **Note:** The newer mbedTLS v4 layout is not compatible with the older v3 structure. + The internal structure has changed significantly, and many components have been moved into submodules (e.g. TF-PSA-Crypto). + + After merging PR #3532, it is required to run: + + ```sh + git submodule update --init --recursive + ``` + + This ensures that all required submodules are fetched. Without this step, the project will not build successfully. + + You can verify that all submodules are properly initialized with: + + ```sh + git submodule status + ``` + + Example output: + + ```sh + bc625d5... bindings/python + 2117822... others/libinjection (v4.0.0) + 0fe989b... others/mbedtls (v4.1.0) + a3d4405... test/test-cases/secrules-language-tests + ``` + + If a submodule is missing, it will be shown with a leading `-`, for example: + + ```sh + -bc625d5... bindings/python + ``` + + A leading `-` indicates that the submodule has not been initialized or fetched. + +* `test/test-cases/secrules-language-tests` – shared SecRules conformance and regression test suite used by `make check`. + +* `bindings/python` – Python bindings for ModSecurity (not required for core library compilation). + +`others/libinjection` and `others/mbedtls` are effectively required for source builds and must be initialized before building. + +### Optional external dependencies + +Several external libraries are optional and enable additional features, including: + +* `libcurl` – required for `SecRemoteRules` + +* LMDB – persistent storage support + +* Lua – scripting support + +* XML libraries – extended XML processing + +* **GeoIP (legacy) / MaxMind** + + The legacy **GeoIP C API** (libGeoIP) is **deprecated and no longer maintained** by MaxMind. + The upstream repository has been archived and should not be used for new deployments. + + Instead, ModSecurity supports the modern **MaxMind DB API (libmaxminddb)**, which is actively maintained. + + During configuration you may see something like: + + ```sh + + GeoIP/MaxMind ....found + * (MaxMind) v1.12.2 + -lmaxminddb , -I/usr/include/x86_64-linux-gnu + ``` -All others dependencies are related to operators specified within SecRules or configuration directives and may not be required for compilation. A short list of such dependencies is as follows: + This indicates that **libmaxminddb** is being used (recommended). -* libinjection is needed for the operator @detectXSS and @detectSQL -* curl is needed for the directive SecRemoteRules. + It is strongly recommended to use MaxMind DB instead of the legacy GeoIP library. -If those libraries are missing ModSecurity will be compiled without the support for the operator @detectXSS and the configuration directive SecRemoteRules. # Library documentation diff --git a/build/win32/README.md b/build/win32/README.md index 2c9c11d06f..becabe23c3 100644 --- a/build/win32/README.md +++ b/build/win32/README.md @@ -18,15 +18,15 @@ The Windows build of libModSecurity uses Build Tools for Visual Studio 2022 (for * Windows SDK * CMake * Address Sanitizer - * [Conan package manager 2.10.2](https://github.com/conan-io/conan/releases/download/2.10.2/conan-2.10.2-windows-x86_64-installer.exe) + * [Conan package manager 2.27.1](https://github.com/conan-io/conan/releases/download/2.27.1/conan-2.27.1-windows-x86_64-installer.exe) * Install and then setup the default Conan profile to use the MSVC C++ compiler: 1. Open a command-prompt and set the MSVC C++ compiler environment by executing: `C:\BuildTools\VC\Auxiliary\Build\vcvars64.bat` 2. Execute: `conan profile detect --force` - * [Git for Windows 2.44.0](https://github.com/git-for-windows/git/releases/download/v2.44.0.windows.1/Git-2.44.0-64-bit.exe) + * [Git for Windows 2.53.0](https://github.com/git-for-windows/git/releases/download/v2.53.0.windows.1/Git-2.53.0-64-bit.exe) * To clone the libModSecurity repository. - * NOTE: Make sure to initialize and update submodules (to get `libinjection` and regression tests) - * `git submodule init` - * `git submodule update` + * NOTE: Make sure to initialize and update submodules (to get `libinjection`, `mbedtls` and regression tests) + * `git submodule update --init --recursive` + * `git submodule status` ## Build @@ -65,11 +65,11 @@ NOTE: When building a different configuration, it's recommended to reset: By default the following all the following features are enabled by including the associated third-party library through a Conan package: - * libxml2 2.12.6 for XML processing support - * libcurl 8.6.0 to support http requests from rules - * libmaxminddb 1.9.1 to support reading MaxMind DB files. - * LUA 5.4.6 to enable rules to run scripts in this language for extensibility - * lmdb 0.9.31 in-memory database + * libxml2 2.15.2 for XML processing support + * libcurl 8.19.0 to support http requests from rules + * libmaxminddb 1.12.2 to support reading MaxMind DB files. + * LUA 5.5.0 to enable rules to run scripts in this language for extensibility + * lmdb 0.9.32 in-memory database Each of these can be turned off by updating the associated `HAVE_xxx` variable (setting it to zero) in the beginning of the libModSecurity section of `CMakeLists.txt`. From 120f017caac3d3ccf5bfe0e06dfb89097eb89972 Mon Sep 17 00:00:00 2001 From: Easton97-Jens <66330090+Easton97-Jens@users.noreply.github.com> Date: Sat, 25 Apr 2026 19:26:05 +0200 Subject: [PATCH 7/8] Update remote_user.cc --- src/variables/remote_user.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index cce7db1ef0..216bde4b6a 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -42,6 +42,11 @@ void RemoteUser::evaluate(Transaction *transaction, std::vector l2; transaction->m_variableRequestHeaders.resolve("authorization", &l2); + std::vector> l2Owners; + l2Owners.reserve(l2.size()); + for (const auto &a : l2) { + l2Owners.emplace_back(a); + } if (!l2.empty()) { const auto *v = l2[0]; @@ -56,9 +61,6 @@ void RemoteUser::evaluate(Transaction *transaction, std::string decodedAuthorization; if (!Utils::Base64::decode(base64, &decodedAuthorization)) { - for (auto &a : l2) { - delete a; - } return; } @@ -75,9 +77,6 @@ void RemoteUser::evaluate(Transaction *transaction, l->push_back(var.release()); } - for (auto &a : l2) { - delete a; - } } } From f1c22168daa1fb709de762cdd4bda2bebccf3655 Mon Sep 17 00:00:00 2001 From: Easton97-Jens <66330090+Easton97-Jens@users.noreply.github.com> Date: Sat, 25 Apr 2026 19:26:52 +0200 Subject: [PATCH 8/8] Refactor base64 helper functions for cleaner syntax --- src/utils/base64.cc | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/utils/base64.cc b/src/utils/base64.cc index ecd0de398a..bb859625e4 100644 --- a/src/utils/base64.cc +++ b/src/utils/base64.cc @@ -23,9 +23,7 @@ #include "mbedtls/base64.h" namespace { -using Base64MbedtlsOperation = int(*)(unsigned char *, size_t, size_t *, - const unsigned char *, size_t); - +template bool base64HelperMbedtls(const char *data, const unsigned int len, Base64MbedtlsOperation op, std::string *output) { if (output == nullptr) { @@ -34,19 +32,18 @@ bool base64HelperMbedtls(const char *data, const unsigned int len, size_t out_len = 0; - const int sizingRet = op(nullptr, 0, &out_len, - reinterpret_cast(data), len); - - if (sizingRet != 0 && sizingRet != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { + if (const int sizingRet = op(nullptr, 0, &out_len, + reinterpret_cast(data), len); + sizingRet != 0 && sizingRet != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { return false; } std::string ret(out_len, {}); if (out_len > 0) { - const int retCode = op(reinterpret_cast(ret.data()), - ret.size(), &out_len, - reinterpret_cast(data), len); - if (retCode != 0) { + if (const int retCode = op(reinterpret_cast(ret.data()), + ret.size(), &out_len, + reinterpret_cast(data), len); + retCode != 0) { return false; } @@ -57,9 +54,7 @@ bool base64HelperMbedtls(const char *data, const unsigned int len, return true; } -using Base64ForgivenOperation = void(*)(unsigned char *, size_t, size_t *, - const unsigned char *, size_t); - +template bool base64HelperForgiven(const char *data, const unsigned int len, Base64ForgivenOperation op, std::string *output) { if (output == nullptr) {