mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
Revert "Replace PostmasterRandom() with a stronger way of generating randomness."
This reverts commit 9e083fd468
. That was a
few bricks shy of a load:
* Query cancel stopped working
* Buildfarm member pademelon stopped working, because the box doesn't have
/dev/urandom nor /dev/random.
This clearly needs some more discussion, and a quite different patch, so
revert for now.
This commit is contained in:
247
contrib/pgcrypto/random.c
Normal file
247
contrib/pgcrypto/random.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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 <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
Reference in New Issue
Block a user