From 539f4ea99bd7040045b83d58fe279a5db7dd213d Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 15 Mar 2017 22:06:12 +0900 Subject: [PATCH 2/4] Refactor frontend-side random number generation pg_frontend_random() is moved into its own file in src/common/ to give other portions of the code the ability to generate random numbers. This will be used for the SCRAM verifier generation from clients. --- src/common/Makefile | 3 +- src/common/frontend_random.c | 86 ++++++++++++++++++++++++++++++++++++ src/include/common/frontend_random.h | 17 +++++++ src/interfaces/libpq/.gitignore | 1 + src/interfaces/libpq/Makefile | 4 +- src/interfaces/libpq/fe-auth-scram.c | 59 +------------------------ src/tools/msvc/Mkvcbuild.pm | 2 +- 7 files changed, 110 insertions(+), 62 deletions(-) create mode 100644 src/common/frontend_random.c create mode 100644 src/include/common/frontend_random.h diff --git a/src/common/Makefile b/src/common/Makefile index 971ddd5ea7..b516ec43f1 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -50,7 +50,8 @@ else OBJS_COMMON += sha2.o endif -OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o file_utils.o restricted_token.o +OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o file_utils.o frontend_random.c \ + restricted_token.o OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o) diff --git a/src/common/frontend_random.c b/src/common/frontend_random.c new file mode 100644 index 0000000000..7ecc7d5fdf --- /dev/null +++ b/src/common/frontend_random.c @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------- + * + * frontend_random.c + * Frontend random number generation routine. + * + * pg_frontend_random() function fills a buffer with random bytes. Normally, + * it is just a thin wrapper around pg_strong_random(), but when compiled + * with --disable-strong-random, there is a built-in implementation. + * + * The built-in implementation uses the standard erand48 algorithm, with + * a seed calculated using the process ID and a timestamp. + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/frontend_random.c + * + *------------------------------------------------------------------------- + */ + +#ifndef FRONTEND +#error "This file is not expected to be compiled for backend code" +#endif + +#include "postgres_fe.h" +#include "common/frontend_random.h" + +/* These are needed for getpid(), in the fallback implementation */ +#ifndef HAVE_STRONG_RANDOM +#include +#include +#endif + +/* + * Random number generator. + */ +bool +pg_frontend_random(char *dst, int len) +{ +#ifdef HAVE_STRONG_RANDOM + return pg_strong_random(dst, len); +#else + int i; + char *end = dst + len; + + static unsigned short seed[3]; + static int mypid = 0; + + pglock_thread(); + + if (mypid != getpid()) + { + struct timeval now; + + gettimeofday(&now, NULL); + + seed[0] = now.tv_sec ^ getpid(); + seed[1] = (unsigned short) (now.tv_usec); + seed[2] = (unsigned short) (now.tv_usec >> 16); + } + + for (i = 0; dst < end; i++) + { + uint32 r; + int j; + + /* + * pg_jrand48 returns a 32-bit integer. Fill the next 4 bytes from + * it. + */ + r = (uint32) pg_jrand48(seed); + + for (j = 0; j < 4 && dst < end; j++) + { + *(dst++) = (char) (r & 0xFF); + r >>= 8; + } + } + + pgunlock_thread(); + + return true; +#endif +} diff --git a/src/include/common/frontend_random.h b/src/include/common/frontend_random.h new file mode 100644 index 0000000000..600c55ace9 --- /dev/null +++ b/src/include/common/frontend_random.h @@ -0,0 +1,17 @@ +/*------------------------------------------------------------------------- + * + * frontend_random.h + * Declarations for frontend random number generation + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group + * + * src/include/common/frontend_random.h + * + *------------------------------------------------------------------------- + */ +#ifndef FRONTEND_RANDOM_H +#define FRONTEND_RANDOM_H + +extern bool pg_frontend_random(char *dst, int len); + +#endif /* FRONTEND_RANDOM_H */ diff --git a/src/interfaces/libpq/.gitignore b/src/interfaces/libpq/.gitignore index 2224ada731..f84bc35706 100644 --- a/src/interfaces/libpq/.gitignore +++ b/src/interfaces/libpq/.gitignore @@ -2,6 +2,7 @@ /base64.c /chklocale.c /crypt.c +/frontend_random.c /getaddrinfo.c /getpeereid.c /inet_aton.c diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index 792232db49..757a702a37 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -49,7 +49,7 @@ endif # src/backend/utils/mb OBJS += encnames.o wchar.o # src/common -OBJS += base64.o ip.o md5.o scram-common.o +OBJS += base64.o frontend_random.o ip.o md5.o scram-common.o ifeq ($(with_openssl),yes) OBJS += fe-secure-openssl.o sha2_openssl.o @@ -111,7 +111,7 @@ ip.c md5.c: % : $(top_srcdir)/src/common/% encnames.c wchar.c: % : $(backend_src)/utils/mb/% rm -f $@ && $(LN_S) $< . -base64.c scram-common.c sha2.c sha2_openssl.c: % : $(top_srcdir)/src/common/% +base64.c frontend_random.c scram-common.c sha2.c sha2_openssl.c: % : $(top_srcdir)/src/common/% rm -f $@ && $(LN_S) $< . diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index a7bb30a141..6390ccf30d 100644 --- a/src/interfaces/libpq/fe-auth-scram.c +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -15,14 +15,10 @@ #include "postgres_fe.h" #include "common/base64.h" +#include "common/frontend_random.h" #include "common/scram-common.h" #include "fe-auth.h" -/* These are needed for getpid(), in the fallback implementation */ -#ifndef HAVE_STRONG_RANDOM -#include -#include -#endif /* * Status of exchange messages used for SCRAM authentication via the @@ -73,7 +69,6 @@ static bool verify_server_proof(fe_scram_state *state); static void calculate_client_proof(fe_scram_state *state, const char *client_final_message_without_proof, uint8 *result); -static bool pg_frontend_random(char *dst, int len); /* * Initialize SCRAM exchange status. @@ -586,55 +581,3 @@ verify_server_proof(fe_scram_state *state) return true; } - -/* - * Random number generator. - */ -static bool -pg_frontend_random(char *dst, int len) -{ -#ifdef HAVE_STRONG_RANDOM - return pg_strong_random(dst, len); -#else - int i; - char *end = dst + len; - - static unsigned short seed[3]; - static int mypid = 0; - - pglock_thread(); - - if (mypid != getpid()) - { - struct timeval now; - - gettimeofday(&now, NULL); - - seed[0] = now.tv_sec ^ getpid(); - seed[1] = (unsigned short) (now.tv_usec); - seed[2] = (unsigned short) (now.tv_usec >> 16); - } - - for (i = 0; dst < end; i++) - { - uint32 r; - int j; - - /* - * pg_jrand48 returns a 32-bit integer. Fill the next 4 bytes from - * it. - */ - r = (uint32) pg_jrand48(seed); - - for (j = 0; j < 4 && dst < end; j++) - { - *(dst++) = (char) (r & 0xFF); - r >>= 8; - } - } - - pgunlock_thread(); - - return true; -#endif -} diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 12f73f344c..615c769483 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -125,7 +125,7 @@ sub mkvcbuild our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c file_utils.c - restricted_token.c)); + frontend_random.c restricted_token.c)); our @pgcommonbkndfiles = @pgcommonallfiles; -- 2.12.0