diff --git a/configure b/configure index 3e3fd389dc..dd64692345 100755 --- a/configure +++ b/configure @@ -18055,19 +18055,21 @@ $as_echo "#define USE_WIN32_SHARED_MEMORY 1" >>confdefs.h SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c" fi -# Select random number source -# -# You can override this logic by setting the appropriate USE_*RANDOM flag to 1 -# in the template or configure command line. - -# If not selected manually, try to select a source automatically. -if test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then - if test x"$with_openssl" = x"yes" ; then - USE_OPENSSL_RANDOM=1 - elif test "$PORTNAME" = "win32" ; then - USE_WIN32_RANDOM=1 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/urandom" >&5 +# Select random number source. If a TLS library is used then it will be the +# first choice, else the native platform sources (Windows API or /dev/urandom) +# will be used. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which random number source to use" >&5 +$as_echo_n "checking which random number source to use... " >&6; } +if test x"$with_openssl" = x"yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenSSL" >&5 +$as_echo "OpenSSL" >&6; } +elif test x"$PORTNAME" = x"win32" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows native" >&5 +$as_echo "Windows native" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5 +$as_echo "/dev/urandom" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/urandom" >&5 $as_echo_n "checking for /dev/urandom... " >&6; } if ${ac_cv_file__dev_urandom+:} false; then : $as_echo_n "(cached) " >&6 @@ -18087,36 +18089,11 @@ if test "x$ac_cv_file__dev_urandom" = xyes; then : fi - if test x"$ac_cv_file__dev_urandom" = x"yes" ; then - USE_DEV_URANDOM=1 - fi - fi -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which random number source to use" >&5 -$as_echo_n "checking which random number source to use... " >&6; } -if test x"$USE_OPENSSL_RANDOM" = x"1" ; then - -$as_echo "#define USE_OPENSSL_RANDOM 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenSSL" >&5 -$as_echo "OpenSSL" >&6; } -elif test x"$USE_WIN32_RANDOM" = x"1" ; then - -$as_echo "#define USE_WIN32_RANDOM 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows native" >&5 -$as_echo "Windows native" >&6; } -elif test x"$USE_DEV_URANDOM" = x"1" ; then - -$as_echo "#define USE_DEV_URANDOM 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5 -$as_echo "/dev/urandom" >&6; } -else - as_fn_error $? " + if test x"$ac_cv_file__dev_urandom" = x"no" ; then + as_fn_error $? " no source of strong random numbers was found -PostgreSQL can use OpenSSL or /dev/urandom as a source of random numbers." "$LINENO" 5 +PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers." "$LINENO" 5 + fi fi # If not set in template file, set bytes to use libc memset() diff --git a/configure.ac b/configure.ac index 8fee479fb7..748fb50236 100644 --- a/configure.ac +++ b/configure.ac @@ -2152,40 +2152,23 @@ else SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c" fi -# Select random number source -# -# You can override this logic by setting the appropriate USE_*RANDOM flag to 1 -# in the template or configure command line. - -# If not selected manually, try to select a source automatically. -if test x"$USE_OPENSSL_RANDOM" = x"" && test x"$USE_WIN32_RANDOM" = x"" && test x"$USE_DEV_URANDOM" = x"" ; then - if test x"$with_openssl" = x"yes" ; then - USE_OPENSSL_RANDOM=1 - elif test "$PORTNAME" = "win32" ; then - USE_WIN32_RANDOM=1 - else - AC_CHECK_FILE([/dev/urandom], [], []) - - if test x"$ac_cv_file__dev_urandom" = x"yes" ; then - USE_DEV_URANDOM=1 - fi - fi -fi - +# Select random number source. If a TLS library is used then it will be the +# first choice, else the native platform sources (Windows API or /dev/urandom) +# will be used. AC_MSG_CHECKING([which random number source to use]) -if test x"$USE_OPENSSL_RANDOM" = x"1" ; then - AC_DEFINE(USE_OPENSSL_RANDOM, 1, [Define to use OpenSSL for random number generation]) +if test x"$with_openssl" = x"yes" ; then AC_MSG_RESULT([OpenSSL]) -elif test x"$USE_WIN32_RANDOM" = x"1" ; then - AC_DEFINE(USE_WIN32_RANDOM, 1, [Define to use native Windows API for random number generation]) +elif test x"$PORTNAME" = x"win32" ; then AC_MSG_RESULT([Windows native]) -elif test x"$USE_DEV_URANDOM" = x"1" ; then - AC_DEFINE(USE_DEV_URANDOM, 1, [Define to use /dev/urandom for random number generation]) - AC_MSG_RESULT([/dev/urandom]) else - AC_MSG_ERROR([ + AC_MSG_RESULT([/dev/urandom]) + AC_CHECK_FILE([/dev/urandom], [], []) + + if test x"$ac_cv_file__dev_urandom" = x"no" ; then + AC_MSG_ERROR([ no source of strong random numbers was found -PostgreSQL can use OpenSSL or /dev/urandom as a source of random numbers.]) +PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers.]) + fi fi # If not set in template file, set bytes to use libc memset() diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index fb270df678..de8f838e53 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -862,9 +862,6 @@ /* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */ #undef USE_BSD_AUTH -/* Define to use /dev/urandom for random number generation */ -#undef USE_DEV_URANDOM - /* Define to build with ICU support. (--with-icu) */ #undef USE_ICU @@ -887,9 +884,6 @@ /* Define to build with OpenSSL support. (--with-openssl) */ #undef USE_OPENSSL -/* Define to use OpenSSL for random number generation */ -#undef USE_OPENSSL_RANDOM - /* Define to 1 to build with PAM support. (--with-pam) */ #undef USE_PAM @@ -914,9 +908,6 @@ /* Define to select unnamed POSIX semaphores. */ #undef USE_UNNAMED_POSIX_SEMAPHORES -/* Define to use native Windows API for random number generation */ -#undef USE_WIN32_RANDOM - /* Define to select Win32-style semaphores. */ #undef USE_WIN32_SEMAPHORES diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 6d85f50b7c..12bbd7fb08 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -24,107 +24,15 @@ #include #include -#ifdef USE_OPENSSL_RANDOM -#include -#endif -#ifdef USE_WIN32_RANDOM -#include -#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. - */ -static bool -random_from_file(const 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; -} -#endif - -/* - * pg_strong_random_init - * - * Initialize the randomness state of "strong" random numbers. This is invoked - * *after* forking a process, and should include initialization steps specific - * to the chosen random source to prove fork-safety. - */ -void -pg_strong_random_init(void) -{ -#if defined(USE_OPENSSL) - /* - * Make sure processes do not share OpenSSL randomness state. We need to - * call this even if pg_strong_random is implemented using another source - * for random numbers to ensure fork-safety in our TLS backend. This is no - * longer required in OpenSSL 1.1.1 and later versions, but until we drop - * support for version < 1.1.1 we need to do this. - */ - RAND_poll(); -#endif - -#if defined(USE_OPENSSL_RANDOM) - /* - * In case the backend is using the PRNG from OpenSSL without being built - * with support for OpenSSL, make sure to perform post-fork initialization. - * If the backend is using OpenSSL then we have already performed this - * step. The same version caveat as discussed in the comment above applies - * here as well. - */ -#ifndef USE_OPENSSL - RAND_poll(); -#endif - -#elif defined(USE_WIN32_RANDOM) - /* no initialization needed for WIN32 */ - -#elif defined(USE_DEV_URANDOM) - /* no initialization needed for /dev/urandom */ - -#else -#error no source of random numbers configured -#endif -} - -/* - * pg_strong_random + * pg_strong_random & pg_strong_random_init * * Generate requested number of random bytes. The returned bytes are * cryptographically secure, suitable for use e.g. in authentication. * + * Before pg_strong_random is called in any process, the generator must first + * be initialized by calling pg_strong_random_init(). + * * We rely on system facilities for actually generating the numbers. * We support a number of sources: * @@ -132,21 +40,32 @@ pg_strong_random_init(void) * 2. Windows' CryptGenRandom() function * 3. /dev/urandom * - * The configure script will choose which one to use, and set - * a USE_*_RANDOM flag accordingly. - * * 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. */ + + + +#ifdef USE_OPENSSL + +#include + +void +pg_strong_random_init(void) +{ + /* + * Make sure processes do not share OpenSSL randomness state. This is no + * longer required in OpenSSL 1.1.1 and later versions, but until we drop + * support for version < 1.1.1 we need to do this. + */ + RAND_poll(); +} + bool pg_strong_random(void *buf, size_t len) { - /* - * When built with OpenSSL, use OpenSSL's RAND_bytes function. - */ -#if defined(USE_OPENSSL_RANDOM) int i; /* @@ -174,11 +93,26 @@ pg_strong_random(void *buf, size_t len) if (RAND_bytes(buf, len) == 1) return true; return false; +} - /* - * Windows has CryptoAPI for strong cryptographic numbers. - */ -#elif defined(USE_WIN32_RANDOM) +#elif WIN32 + +#include +/* + * 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; + +void +pg_strong_random_init(void) +{ + /* No initialization needed on WIN32 */ +} + +bool +pg_strong_random(void *buf, size_t len) +{ if (hProvider == 0) { if (!CryptAcquireContext(&hProvider, @@ -201,17 +135,48 @@ pg_strong_random(void *buf, size_t len) return true; } return false; - - /* - * Read /dev/urandom ourselves. - */ -#elif defined(USE_DEV_URANDOM) - if (random_from_file("/dev/urandom", buf, len)) - return true; - return false; - -#else - /* The autoconf script should not have allowed this */ -#error no source of random numbers configured -#endif } + +#else /* not USE_OPENSSL or WIN32 */ + +/* + * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. + */ + +void +pg_strong_random_init(void) +{ + /* No initialization needed */ +} + +bool +pg_strong_random(void *buf, size_t len) +{ + int f; + char *p = buf; + ssize_t res; + + f = open("/dev/urandom", 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; +} +#endif diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 17e480546c..22d6abd367 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -475,7 +475,6 @@ sub GenerateFiles USE_ASSERT_CHECKING => $self->{options}->{asserts} ? 1 : undef, USE_BONJOUR => undef, USE_BSD_AUTH => undef, - USE_DEV_URANDOM => undef, USE_ICU => $self->{options}->{icu} ? 1 : undef, USE_LIBXML => undef, USE_LIBXSLT => undef, @@ -483,7 +482,6 @@ sub GenerateFiles USE_LLVM => undef, USE_NAMED_POSIX_SEMAPHORES => undef, USE_OPENSSL => undef, - USE_OPENSSL_RANDOM => undef, USE_PAM => undef, USE_SLICING_BY_8_CRC32C => undef, USE_SSE42_CRC32C => undef, @@ -492,7 +490,6 @@ sub GenerateFiles USE_SYSV_SEMAPHORES => undef, USE_SYSV_SHARED_MEMORY => undef, USE_UNNAMED_POSIX_SEMAPHORES => undef, - USE_WIN32_RANDOM => 1, USE_WIN32_SEMAPHORES => 1, USE_WIN32_SHARED_MEMORY => 1, WCSTOMBS_L_IN_XLOCALE => undef,