From 5916955b802d0b0d717df0cb4c60cf9e4284b677 Mon Sep 17 00:00:00 2001 From: Alhuda Khan Date: Wed, 14 Oct 2026 14:44:31 +0530 Subject: [PATCH 1/2] zncstring: generate RandomString with a CSPRNG instead of rand() --- src/ZNCString.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ZNCString.cpp b/src/ZNCString.cpp index c30469b9..04a32987 100644 --- a/src/ZNCString.cpp +++ b/src/ZNCString.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include using std::stringstream; @@ -998,12 +999,18 @@ CString CString::RandomString(unsigned int uLength) { "0123456789!?.,:;/*-+_()"; // -1 because sizeof() includes the trailing '\0' byte const size_t len = sizeof(chars) / sizeof(chars[0]) - 1; - size_t p; CString sRet; + sRet.reserve(uLength); + + // Draw from the system CSPRNG rather than rand(): this feeds web session + // ids (CWebSock::GetSession) and password salts (CUtils::GetSalt), and + // rand()'s stream is fully determined by the process seed set in + // seedPRNG() (startup time xored with the pid). + std::random_device rd; + std::uniform_int_distribution distr(0, len - 1); for (unsigned int a = 0; a < uLength; a++) { - p = (size_t)(len * (rand() / (RAND_MAX + 1.0))); - sRet += chars[p]; + sRet += chars[distr(rd)]; } return sRet; From 71dd0e0f8886b2fd8bf5fb6021e1538f8ad77af7 Mon Sep 17 00:00:00 2001 From: Alhuda Khan Date: Sun, 18 Oct 2026 12:22:56 +0530 Subject: [PATCH 2/2] zncstring: use openssl RAND_bytes for RandomString when available --- src/ZNCString.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/ZNCString.cpp b/src/ZNCString.cpp index 04a32987..80093c0e 100644 --- a/src/ZNCString.cpp +++ b/src/ZNCString.cpp @@ -22,6 +22,10 @@ #include #include +#ifdef HAVE_LIBSSL +#include +#endif + using std::stringstream; static constexpr unsigned char XX = 0xff; @@ -1002,12 +1006,26 @@ CString CString::RandomString(unsigned int uLength) { CString sRet; sRet.reserve(uLength); - // Draw from the system CSPRNG rather than rand(): this feeds web session - // ids (CWebSock::GetSession) and password salts (CUtils::GetSalt), and - // rand()'s stream is fully determined by the process seed set in - // seedPRNG() (startup time xored with the pid). - std::random_device rd; std::uniform_int_distribution distr(0, len - 1); +#ifdef HAVE_LIBSSL + // OpenSSL's DRBG is seeded once and doesn't go back to the kernel for + // every call, unlike std::random_device. + struct { + using result_type = unsigned int; + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return ~0u; } + result_type operator()() { + result_type r; + if (RAND_bytes(reinterpret_cast(&r), sizeof(r)) != + 1) { + r = std::random_device()(); + } + return r; + } + } rd; +#else + std::random_device rd; +#endif for (unsigned int a = 0; a < uLength; a++) { sRet += chars[distr(rd)];