From 6f8baee4ef5fbc0b7d4b2a352b7667f70d1e0c31 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Fri, 7 Apr 2017 10:24:44 +0900 Subject: [PATCH 3/5] Refactor frontend-side random number generation pg_frontend_random() is moved into its own file in libpq/ to give other portions of the libpq code the ability to generate random numbers. This will be used for the SCRAM verifier generation from clients. --- src/interfaces/libpq/Makefile | 2 +- src/interfaces/libpq/fe-auth-scram.c | 53 ----------------------- src/interfaces/libpq/libpq-int.h | 1 + src/interfaces/libpq/libpq-random.c | 84 ++++++++++++++++++++++++++++++++++++ src/interfaces/libpq/libpq-random.h | 17 ++++++++ src/tools/msvc/Install.pm | 2 +- 6 files changed, 104 insertions(+), 55 deletions(-) create mode 100644 src/interfaces/libpq/libpq-random.c create mode 100644 src/interfaces/libpq/libpq-random.h diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index 36b57268a7..1d20ae9ac2 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -33,7 +33,7 @@ LIBS := $(LIBS:-lpgport=) # OBJS from this file. OBJS= fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ fe-protocol2.o fe-protocol3.o pqexpbuffer.o fe-secure.o \ - libpq-events.o + libpq-events.o libpq-random.o # libpgport C files we always use OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \ thread.o diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index 818ade4993..e6661a6524 100644 --- a/src/interfaces/libpq/fe-auth-scram.c +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -73,7 +73,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 +585,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/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index b8ec3418c5..6b72a17a75 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -22,6 +22,7 @@ /* We assume libpq-fe.h has already been included. */ #include "libpq-events.h" +#include "libpq-random.h" #include #ifndef WIN32 diff --git a/src/interfaces/libpq/libpq-random.c b/src/interfaces/libpq/libpq-random.c new file mode 100644 index 0000000000..5e788dc821 --- /dev/null +++ b/src/interfaces/libpq/libpq-random.c @@ -0,0 +1,84 @@ +/*------------------------------------------------------------------------- + * + * libpq-random.c + * Frontend random number generation routine for libpq. + * + * 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/interfaces/libpq/libpq-random.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "libpq-fe.h" +#include "libpq-int.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/interfaces/libpq/libpq-random.h b/src/interfaces/libpq/libpq-random.h new file mode 100644 index 0000000000..054998b8d9 --- /dev/null +++ b/src/interfaces/libpq/libpq-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/interfaces/libpq/libpq-random.h + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_RANDOM_H +#define LIBPQ_RANDOM_H + +extern bool pg_frontend_random(char *dst, int len); + +#endif /* LIBPQ_RANDOM_H */ diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm index 35ad5b8a44..4acd6592ad 100644 --- a/src/tools/msvc/Install.pm +++ b/src/tools/msvc/Install.pm @@ -601,7 +601,7 @@ sub CopyIncludeFiles CopyFiles( 'Libpq internal headers', $target . '/include/internal/', - 'src/interfaces/libpq/', 'libpq-int.h', 'pqexpbuffer.h'); + 'src/interfaces/libpq/', 'libpq-int.h', 'libpq-random.h', 'pqexpbuffer.h'); CopyFiles( 'Internal headers', -- 2.12.2