Hi,
According to microsoft documentation at:
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
The function CryptGenRandom is deprecated, and may can be removed in future
release.
Considering that postgres only supports windows versions that have the new API,
it would be good to make the replace.
BCryptGenRandom apparently works without having to set up an environment before
calling it, allowing a simplification in the file that makes the call.
The drawback, its change causes need to link to bcrypt.lib.
On exec.c, have two memory leaks, and a possible access beyond heap bounds, the
patch tries to fix them.
According to documentation at:
https://en.cppreference.com/w/c/experimental/dynamic/strdup
"The returned pointer must be passed to free to avoid a memory leak. "
* memory leak fix to src/common/exec.c
* CryptGenRandom change by BCryptGenRandom to src/port/pg_strong_random.c
* link bcrypt.lib to src/tools/msvc/Mkvcbuild.pm
regards,
Ranier Vilela
diff --git a/src/common/exec.c b/src/common/exec.c
index 92dc3134a1..88a27cec78 100644
--- a/src/common/exec.c
+++ b/src/common/exec.c
@@ -72,14 +72,15 @@ validate_exec(const char *path)
int is_x;
#ifdef WIN32
- char path_exe[MAXPGPATH + sizeof(".exe") - 1];
+ char path_exe[MAXPGPATH + sizeof(".exe")];
+ int path_len;
/* Win32 requires a .exe suffix for stat() */
- if (strlen(path) >= strlen(".exe") &&
- pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
+ path_len = strlen(path);
+ if (path_len >= (sizeof(".exe") - 1) &&
+ pg_strcasecmp(path + path_len - (sizeof(".exe") - 1), ".exe") != 0)
{
- strlcpy(path_exe, path, sizeof(path_exe) - 4);
- strcat(path_exe, ".exe");
+ snprintf(path_exe, sizeof(path_exe) - 5, "%s.exe", path);
path = path_exe;
}
#endif
@@ -600,8 +601,10 @@ set_pglocale_pgservice(const char *argv0, const char *app)
snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path);
canonicalize_path(env_path + 12);
dup_path = strdup(env_path);
- if (dup_path)
- putenv(dup_path);
+ if (dup_path) {
+ putenv(dup_path);
+ free(dup_path);
+ }
}
#endif
@@ -613,8 +616,10 @@ set_pglocale_pgservice(const char *argv0, const char *app)
snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path);
canonicalize_path(env_path + 13);
dup_path = strdup(env_path);
- if (dup_path)
- putenv(dup_path);
+ if (dup_path) {
+ putenv(dup_path);
+ free(dup_path);
+ }
}
}
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index 6be5874cbf..6d075eaf1a 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -28,17 +28,13 @@
#include <openssl/rand.h>
#endif
#ifdef USE_WIN32_RANDOM
-#include <wincrypt.h>
+#include <bcrypt.h>
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
-
-#ifdef USE_WIN32_RANDOM
-/*
- * Cache a global crypto provider that only gets freed when the process
- * exits, in case we need random numbers more than once.
- */
-static HCRYPTPROV hProvider = 0;
#endif
+
#if defined(USE_DEV_URANDOM)
/*
* Read (random) bytes from a file.
@@ -85,7 +81,7 @@ random_from_file(const char *filename, void *buf, size_t len)
* We support a number of sources:
*
* 1. OpenSSL's RAND_bytes()
- * 2. Windows' CryptGenRandom() function
+ * 2. Windows' BCryptGenRandom() function
* 3. /dev/urandom
*
* The configure script will choose which one to use, and set
@@ -140,28 +136,8 @@ pg_strong_random(void *buf, size_t len)
* Windows has CryptoAPI for strong cryptographic numbers.
*/
#elif defined(USE_WIN32_RANDOM)
- if (hProvider == 0)
- {
- if (!CryptAcquireContext(&hProvider,
- NULL,
- MS_DEF_PROV,
- PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- {
- /*
- * On failure, set back to 0 in case the value was for some reason
- * modified.
- */
- hProvider = 0;
- }
- }
- /* Re-check in case we just retrieved the provider */
- if (hProvider != 0)
- {
- if (CryptGenRandom(hProvider, len, buf))
- return true;
- }
- return false;
+ return (BCryptGenRandom(NULL, buf, len,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS);
/*
* Read /dev/urandom ourselves.
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 275f3bb699..9e1ac51507 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -65,7 +65,7 @@ my @frontend_uselibpgcommon = (
my $frontend_extralibs = {
'initdb' => ['ws2_32.lib'],
'pg_restore' => ['ws2_32.lib'],
- 'pgbench' => ['ws2_32.lib'],
+ 'pgbench' => ['ws2_32.lib', 'bcrypt.lib'],
'psql' => ['ws2_32.lib']
};
my $frontend_extraincludes = {
@@ -184,6 +184,7 @@ sub mkvcbuild
$postgres->AddFiles('src/backend/utils/adt', 'jsonpath_scan.l',
'jsonpath_gram.y');
$postgres->AddDefine('BUILDING_DLL');
+ $postgres->AddLibrary('bcrypt.lib');
$postgres->AddLibrary('secur32.lib');
$postgres->AddLibrary('ws2_32.lib');
$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
@@ -246,6 +247,7 @@ sub mkvcbuild
$libpq->AddDefine('FRONTEND');
$libpq->AddDefine('UNSAFE_STAT_OK');
$libpq->AddIncludeDir('src/port');
+ $libpq->AddLibrary('bcrypt.lib');
$libpq->AddLibrary('secur32.lib');
$libpq->AddLibrary('ws2_32.lib');
$libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});