From 9e083fd4683294f41544e6d0d72f6e258ff3a77c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 17 Oct 2016 11:52:50 +0300 Subject: [PATCH] Replace PostmasterRandom() with a stronger way of generating randomness. This adds a new routine, pg_strong_random() for generating random bytes, for use in both frontend and backend. At the moment, it's only used in the backend, but the upcoming SCRAM authentication patches need strong random numbers in libpq as well. pg_strong_random() is based on, and replaces, the existing implementation in pgcrypto. It can acquire strong random numbers from a number of sources, depending on what's available: - OpenSSL RAND_bytes(), if built with OpenSSL - On Windows, the native cryptographic functions are used - /dev/urandom - /dev/random Original patch by Magnus Hagander, with further work by Michael Paquier and me. Discussion: --- contrib/pgcrypto/Makefile | 2 +- contrib/pgcrypto/internal.c | 40 +++-- contrib/pgcrypto/random.c | 247 ---------------------------- src/backend/libpq/auth.c | 27 ++- src/backend/postmaster/postmaster.c | 153 +++++------------ src/include/port.h | 3 + src/port/Makefile | 2 +- src/port/pg_strong_random.c | 148 +++++++++++++++++ src/tools/msvc/Mkvcbuild.pm | 6 +- 9 files changed, 244 insertions(+), 384 deletions(-) delete mode 100644 contrib/pgcrypto/random.c create mode 100644 src/port/pg_strong_random.c diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index 805db7626b..76c2f1aa17 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -1,7 +1,7 @@ # contrib/pgcrypto/Makefile INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \ - fortuna.c random.c pgp-mpi-internal.c imath.c + fortuna.c pgp-mpi-internal.c imath.c INT_TESTS = sha2 OSSL_SRCS = openssl.c pgp-mpi-openssl.c diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c index 02ff976c25..ad942f733a 100644 --- a/contrib/pgcrypto/internal.c +++ b/contrib/pgcrypto/internal.c @@ -626,8 +626,6 @@ static time_t check_time = 0; static void system_reseed(void) { - uint8 buf[1024]; - int n; time_t t; int skip = 1; @@ -642,24 +640,34 @@ system_reseed(void) else if (check_time == 0 || (t - check_time) > SYSTEM_RESEED_CHECK_TIME) { + uint8 buf; + check_time = t; /* roll dice */ - px_get_random_bytes(buf, 1); - skip = buf[0] >= SYSTEM_RESEED_CHANCE; - } - /* clear 1 byte */ - px_memset(buf, 0, sizeof(buf)); - - if (skip) - return; - - n = px_acquire_system_randomness(buf); - if (n > 0) - fortuna_add_entropy(buf, n); + px_get_random_bytes(&buf, 1); + skip = (buf >= SYSTEM_RESEED_CHANCE); - seed_time = t; - px_memset(buf, 0, sizeof(buf)); + /* clear 1 byte */ + px_memset(&buf, 0, sizeof(buf)); + } + if (!skip) + { + /* + * fortuna_add_entropy passes the input to SHA-256, so there's no + * point in giving it more than 256 bits of input to begin with. + */ + uint8 buf[32]; + + if (!pg_strong_random(buf, sizeof(buf))) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("could not acquire random data"))); + fortuna_add_entropy(buf, sizeof(buf)); + + seed_time = t; + px_memset(buf, 0, sizeof(buf)); + } } int diff --git a/contrib/pgcrypto/random.c b/contrib/pgcrypto/random.c deleted file mode 100644 index d72679e412..0000000000 --- a/contrib/pgcrypto/random.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * random.c - * Acquire randomness from system. For seeding RNG. - * - * Copyright (c) 2001 Marko Kreen - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * contrib/pgcrypto/random.c - */ - -#include "postgres.h" - -#include "px.h" -#include "utils/memdebug.h" - -/* how many bytes to ask from system random provider */ -#define RND_BYTES 32 - -/* - * Try to read from /dev/urandom or /dev/random on these OS'es. - * - * The list can be pretty liberal, as the device not existing - * is expected event. - */ -#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ - || defined(__NetBSD__) || defined(__DragonFly__) \ - || defined(__darwin__) || defined(__SOLARIS__) \ - || defined(__hpux) || defined(__HPUX__) \ - || defined(__CYGWIN__) || defined(_AIX) - -#define TRY_DEV_RANDOM - -#include -#include - -static int -safe_read(int fd, void *buf, size_t count) -{ - int done = 0; - char *p = buf; - int res; - - while (count) - { - res = read(fd, p, count); - if (res <= 0) - { - if (errno == EINTR) - continue; - return PXE_DEV_READ_ERROR; - } - p += res; - done += res; - count -= res; - } - return done; -} - -static uint8 * -try_dev_random(uint8 *dst) -{ - int fd; - int res; - - fd = open("/dev/urandom", O_RDONLY, 0); - if (fd == -1) - { - fd = open("/dev/random", O_RDONLY, 0); - if (fd == -1) - return dst; - } - res = safe_read(fd, dst, RND_BYTES); - close(fd); - if (res > 0) - dst += res; - return dst; -} -#endif - -/* - * Try to find randomness on Windows - */ -#ifdef WIN32 - -#define TRY_WIN32_GENRAND -#define TRY_WIN32_PERFC - -#include -#include - -/* - * this function is from libtomcrypt - * - * try to use Microsoft crypto API - */ -static uint8 * -try_win32_genrand(uint8 *dst) -{ - int res; - HCRYPTPROV h = 0; - - res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, - (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)); - if (!res) - res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET); - if (!res) - return dst; - - res = CryptGenRandom(h, RND_BYTES, dst); - if (res == TRUE) - dst += RND_BYTES; - - CryptReleaseContext(h, 0); - return dst; -} - -static uint8 * -try_win32_perfc(uint8 *dst) -{ - int res; - LARGE_INTEGER time; - - res = QueryPerformanceCounter(&time); - if (!res) - return dst; - - memcpy(dst, &time, sizeof(time)); - return dst + sizeof(time); -} -#endif /* WIN32 */ - - -/* - * If we are not on Windows, then hopefully we are - * on a unix-like system. Use the usual suspects - * for randomness. - */ -#ifndef WIN32 - -#define TRY_UNIXSTD - -#include -#include -#include -#include - -/* - * Everything here is predictible, only needs some patience. - * - * But there is a chance that the system-specific functions - * did not work. So keep faith and try to slow the attacker down. - */ -static uint8 * -try_unix_std(uint8 *dst) -{ - pid_t pid; - int x; - PX_MD *md; - struct timeval tv; - int res; - - /* process id */ - pid = getpid(); - memcpy(dst, (uint8 *) &pid, sizeof(pid)); - dst += sizeof(pid); - - /* time */ - gettimeofday(&tv, NULL); - memcpy(dst, (uint8 *) &tv, sizeof(tv)); - dst += sizeof(tv); - - /* pointless, but should not hurt */ - x = random(); - memcpy(dst, (uint8 *) &x, sizeof(x)); - dst += sizeof(x); - - /* hash of uninitialized stack and heap allocations */ - res = px_find_digest("sha1", &md); - if (res >= 0) - { - uint8 *ptr; - uint8 stack[8192]; - int alloc = 32 * 1024; - - VALGRIND_MAKE_MEM_DEFINED(stack, sizeof(stack)); - px_md_update(md, stack, sizeof(stack)); - ptr = px_alloc(alloc); - VALGRIND_MAKE_MEM_DEFINED(ptr, alloc); - px_md_update(md, ptr, alloc); - px_free(ptr); - - px_md_finish(md, dst); - px_md_free(md); - - dst += 20; - } - - return dst; -} -#endif - -/* - * try to extract some randomness for initial seeding - * - * dst should have room for 1024 bytes. - */ -unsigned -px_acquire_system_randomness(uint8 *dst) -{ - uint8 *p = dst; - -#ifdef TRY_DEV_RANDOM - p = try_dev_random(p); -#endif -#ifdef TRY_WIN32_GENRAND - p = try_win32_genrand(p); -#endif -#ifdef TRY_WIN32_PERFC - p = try_win32_perfc(p); -#endif -#ifdef TRY_UNIXSTD - p = try_unix_std(p); -#endif - return p - dst; -} diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 0ba8530114..44b2212b1d 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -45,6 +45,12 @@ static void auth_failed(Port *port, int status, char *logdetail); static char *recv_password_packet(Port *port); static int recv_and_check_password_packet(Port *port, char **logdetail); +/*---------------------------------------------------------------- + * MD5 authentication + *---------------------------------------------------------------- + */ +static int CheckMD5Auth(Port *port, char **logdetail); + /*---------------------------------------------------------------- * Ident authentication @@ -535,9 +541,7 @@ ClientAuthentication(Port *port) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled"))); - /* include the salt to use for computing the response */ - sendAuthRequest(port, AUTH_REQ_MD5, port->md5Salt, 4); - status = recv_and_check_password_packet(port, &logdetail); + status = CheckMD5Auth(port, &logdetail); break; case uaPassword: @@ -692,10 +696,25 @@ recv_password_packet(Port *port) /*---------------------------------------------------------------- - * MD5 authentication + * MD5 and password authentication *---------------------------------------------------------------- */ +static int +CheckMD5Auth(Port *port, char **logdetail) +{ + /* include the salt to use for computing the response */ + if (!pg_strong_random(port->md5Salt, sizeof(port->md5Salt))) + { + *logdetail = psprintf(_("Could not generate random salt")); + return STATUS_ERROR; + } + + sendAuthRequest(port, AUTH_REQ_MD5, port->md5Salt, 4); + return recv_and_check_password_packet(port, logdetail); +} + + /* * Called when we have sent an authorization request for a password. * Get the response and check it. diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 2d43506cd0..4420138673 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -358,14 +358,6 @@ static volatile bool avlauncher_needs_signal = false; static volatile bool StartWorkerNeeded = true; static volatile bool HaveCrashedWorker = false; -/* - * State for assigning random salts and cancel keys. - * Also, the global MyCancelKey passes the cancel key assigned to a given - * backend from the postmaster to that backend (via fork). - */ -static unsigned int random_seed = 0; -static struct timeval random_start_time; - #ifdef USE_BONJOUR static DNSServiceRef bonjour_sdref = NULL; #endif @@ -403,8 +395,6 @@ static void processCancelRequest(Port *port, void *pkt); static int initMasks(fd_set *rmask); static void report_fork_failure_to_client(Port *port, int errnum); static CAC_state canAcceptConnections(void); -static long PostmasterRandom(void); -static void RandomSalt(char *salt, int len); static void signal_child(pid_t pid, int signal); static bool SignalSomeChildren(int signal, int targets); static void TerminateChildren(int signal); @@ -579,9 +569,11 @@ PostmasterMain(int argc, char *argv[]) * Initialize random(3) so we don't get the same values in every run. * * Note: the seed is pretty predictable from externally-visible facts such - * as postmaster start time, so avoid using random() for security-critical - * random values during postmaster startup. At the time of first - * connection, PostmasterRandom will select a hopefully-more-random seed. + * as postmaster start time, so don't use random() for security-critical + * random values (use pg_strong_random() instead). Backends select a + * somewhat more random seed after forking, in BackendRun(), based on the + * PID and session start timestamp, but that is still not suitable for + * security-critical values. */ srandom((unsigned int) (MyProcPid ^ MyStartTime)); @@ -1292,8 +1284,6 @@ PostmasterMain(int argc, char *argv[]) * Remember postmaster startup time */ PgStartTime = GetCurrentTimestamp(); - /* PostmasterRandom wants its own copy */ - gettimeofday(&random_start_time, NULL); /* * We're ready to rock and roll... @@ -2343,15 +2333,6 @@ ConnCreate(int serverFd) return NULL; } - /* - * Precompute password salt values to use for this connection. It's - * slightly annoying to do this long in advance of knowing whether we'll - * need 'em or not, but we must do the random() calls before we fork, not - * after. Else the postmaster's random sequence won't get advanced, and - * all backends would end up using the same salt... - */ - RandomSalt(port->md5Salt, sizeof(port->md5Salt)); - /* * Allocate GSSAPI specific state struct */ @@ -3904,7 +3885,12 @@ BackendStartup(Port *port) * backend will have its own copy in the forked-off process' value of * MyCancelKey, so that it can transmit the key to the frontend. */ - MyCancelKey = PostmasterRandom(); + if (!pg_strong_random(&MyCancelKey, sizeof(MyCancelKey))) + { + ereport(LOG, + (errmsg("could not generate random query cancel key"))); + return STATUS_ERROR; + } bn->cancel_key = MyCancelKey; /* Pass down canAcceptConnections state */ @@ -4212,13 +4198,6 @@ BackendRun(Port *port) int usecs; int i; - /* - * Don't want backend to be able to see the postmaster random number - * generator state. We have to clobber the static random_seed *and* start - * a new random sequence in the random() library function. - */ - random_seed = 0; - random_start_time.tv_usec = 0; /* slightly hacky way to convert timestamptz into integers */ TimestampDifference(0, port->SessionStartTime, &secs, &usecs); srandom((unsigned int) (MyProcPid ^ (usecs << 12) ^ secs)); @@ -5066,66 +5045,6 @@ StartupPacketTimeoutHandler(void) } -/* - * RandomSalt - */ -static void -RandomSalt(char *salt, int len) -{ - long rand; - int i; - - /* - * We use % 255, sacrificing one possible byte value, so as to ensure that - * all bits of the random() value participate in the result. While at it, - * add one to avoid generating any null bytes. - */ - for (i = 0; i < len; i++) - { - rand = PostmasterRandom(); - salt[i] = (rand % 255) + 1; - } -} - -/* - * PostmasterRandom - * - * Caution: use this only for values needed during connection-request - * processing. Otherwise, the intended property of having an unpredictable - * delay between random_start_time and random_stop_time will be broken. - */ -static long -PostmasterRandom(void) -{ - /* - * Select a random seed at the time of first receiving a request. - */ - if (random_seed == 0) - { - do - { - struct timeval random_stop_time; - - gettimeofday(&random_stop_time, NULL); - - /* - * We are not sure how much precision is in tv_usec, so we swap - * the high and low 16 bits of 'random_stop_time' and XOR them - * with 'random_start_time'. On the off chance that the result is - * 0, we loop until it isn't. - */ - random_seed = random_start_time.tv_usec ^ - ((random_stop_time.tv_usec << 16) | - ((random_stop_time.tv_usec >> 16) & 0xffff)); - } - while (random_seed == 0); - - srandom(random_seed); - } - - return random(); -} - /* * Count up number of child processes of specified types (dead_end chidren * are always excluded). @@ -5303,31 +5222,37 @@ StartAutovacuumWorker(void) * we'd better have something random in the field to prevent * unfriendly people from sending cancels to them. */ - MyCancelKey = PostmasterRandom(); - bn->cancel_key = MyCancelKey; + if (pg_strong_random(&MyCancelKey, sizeof(MyCancelKey))) + { + bn->cancel_key = MyCancelKey; - /* Autovac workers are not dead_end and need a child slot */ - bn->dead_end = false; - bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); - bn->bgworker_notify = false; + /* Autovac workers are not dead_end and need a child slot */ + bn->dead_end = false; + bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); + bn->bgworker_notify = false; - bn->pid = StartAutoVacWorker(); - if (bn->pid > 0) - { - bn->bkend_type = BACKEND_TYPE_AUTOVAC; - dlist_push_head(&BackendList, &bn->elem); + bn->pid = StartAutoVacWorker(); + if (bn->pid > 0) + { + bn->bkend_type = BACKEND_TYPE_AUTOVAC; + dlist_push_head(&BackendList, &bn->elem); #ifdef EXEC_BACKEND - ShmemBackendArrayAdd(bn); + ShmemBackendArrayAdd(bn); #endif - /* all OK */ - return; + /* all OK */ + return; + } + + /* + * fork failed, fall through to report -- actual error message + * was logged by StartAutoVacWorker + */ + (void) ReleasePostmasterChildSlot(bn->child_slot); } + else + ereport(LOG, + (errmsg("could not generate random query cancel key"))); - /* - * fork failed, fall through to report -- actual error message was - * logged by StartAutoVacWorker - */ - (void) ReleasePostmasterChildSlot(bn->child_slot); free(bn); } else @@ -5615,7 +5540,11 @@ assign_backendlist_entry(RegisteredBgWorker *rw) * have something random in the field to prevent unfriendly people from * sending cancels to them. */ - MyCancelKey = PostmasterRandom(); + if (!pg_strong_random(&MyCancelKey, sizeof(MyCancelKey))) + { + rw->rw_crashed_at = GetCurrentTimestamp(); + return false; + } bn->cancel_key = MyCancelKey; bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); diff --git a/src/include/port.h b/src/include/port.h index b81fa4a89e..4bb9feeb01 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -454,6 +454,9 @@ extern int pg_codepage_to_encoding(UINT cp); extern char *inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size); +/* port/pg_strong_random.c */ +extern bool pg_strong_random(void *buf, size_t len); + /* port/pgcheckdir.c */ extern int pg_check_dir(const char *dir); diff --git a/src/port/Makefile b/src/port/Makefile index bc9b63add0..d34f409ee9 100644 --- a/src/port/Makefile +++ b/src/port/Makefile @@ -32,7 +32,7 @@ LIBS += $(PTHREAD_LIBS) OBJS = $(LIBOBJS) $(PG_CRC32C_OBJS) chklocale.o erand48.o inet_net_ntop.o \ noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \ - pgstrcasecmp.o pqsignal.o \ + pg_strong_random.o pgstrcasecmp.o pqsignal.o \ qsort.o qsort_arg.o quotes.o sprompt.o tar.o thread.o # foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c new file mode 100644 index 0000000000..a404111d74 --- /dev/null +++ b/src/port/pg_strong_random.c @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------------- + * + * pg_strong_random.c + * pg_strong_random() function to return a strong random number + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/port/pg_strong_random.c + * + *------------------------------------------------------------------------- + */ + +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#include +#include + +#ifdef USE_SSL +#include +#endif +#ifdef WIN32 +#include +#endif + +static bool random_from_file(char *filename, void *buf, size_t len); + +#ifdef WIN32 +/* + * 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 + +/* + * Read (random) bytes from a file. + */ +static bool +random_from_file(char *filename, void *buf, size_t len) +{ + int f; + char *p = buf; + ssize_t res; + + f = open(filename, O_RDONLY, 0); + if (f == -1) + return false; + + while (len) + { + res = read(f, p, len); + if (res <= 0) + { + if (errno == EINTR) + continue; /* interrupted by signal, just retry */ + + close(f); + return false; + } + + p += res; + len -= res; + } + + close(f); + return true; +} + +/* + * pg_strong_random + * + * Generate requested number of random bytes. The bytes are + * cryptographically strong random, suitable for use e.g. in key + * generation. + * + * The bytes can be acquired from a number of sources, depending + * on what's available. We try the following, in this order: + * + * 1. OpenSSL's RAND_bytes() + * 2. Windows' CryptGenRandom() function + * 3. /dev/urandom + * 4. /dev/random + * + * Returns true on success, and false if none of the sources + * were available. NB: It is important to check the return value! + * Proceeding with key generation when no random data was available + * would lead to predictable keys and security issues. + */ +bool +pg_strong_random(void *buf, size_t len) +{ +#ifdef USE_SSL + + /* + * When built with OpenSSL, first try the random generation function from + * there. + */ + if (RAND_bytes(buf, len) == 1) + return true; +#endif + +#ifdef WIN32 + + /* + * Windows has CryptoAPI for strong cryptographic numbers. + */ + 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; + } +#endif + + /* + * If there is no OpenSSL and no CryptoAPI (or they didn't work), then + * fall back on reading /dev/urandom or even /dev/random. + */ + if (random_from_file("/dev/urandom", buf, len)) + return true; + if (random_from_file("/dev/random", buf, len)) + return true; + + /* None of the sources were available. */ + return false; +} diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index de764dd4d4..e6c4aef99f 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -92,7 +92,7 @@ sub mkvcbuild srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c - mkdtemp.c qsort.c qsort_arg.c quotes.c system.c + mkdtemp.c pg_strong_random.c qsort.c qsort_arg.c quotes.c system.c sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c win32env.c win32error.c win32security.c win32setlocale.c); @@ -425,8 +425,8 @@ sub mkvcbuild 'sha1.c', 'sha2.c', 'internal.c', 'internal-sha2.c', 'blf.c', 'rijndael.c', - 'fortuna.c', 'random.c', - 'pgp-mpi-internal.c', 'imath.c'); + 'fortuna.c', 'pgp-mpi-internal.c', + 'imath.c'); } $pgcrypto->AddReference($postgres); $pgcrypto->AddLibrary('ws2_32.lib'); -- 2.40.0