Thread: libpq seed PRNG for SSL support

libpq seed PRNG for SSL support

From
Jon Marks
Date:
Greetings to the PostgreSQL development team!

PostgreSQL is a wonderful product, and I couldn't begin to express
adequate gratitude for the opportunity to enjoy the fruits of the
postgreSQL development team's efforts!

I use postgreSQL on Sparc/Solaris 8 and RS6000/AIX 4.3.3 platforms,
which by default lack a /dev/urandom mechanism. The only attempt that
openssl makes to initialize the pseudorandom number generator (PRNG)
seeks this file as a source of randomness. According to OpenSSL, it is an
application's responsibility to make any other arrangements for seeding
the PRNG prior to using the SSL libraries. OpenSSL refuses to operate
when this is not the case. On these platforms, applications will fail
if they don't try to seed the PRNG with some alternate mechanism.

The psql command line utility (and presumably the others, since they'd
be using libpq for client connectivity) cannot be used with SSL on these
platforms since they don't perform the PRNG initialization explicitly.
They could each be individually augmented to do so, but that requires
modifying every client using libpq. Also, the other uses of libpq may
not be able to do this at all. For instance, I'm using the perl DBD::Pg
interface and having the same error. In my perl program, I try to seed
the PRNG with calls directly into Net::SSLeay(::RAND_*). Although the
calls succeed, the DBD library (using libpq) doesn't seem to "notice".
I'm not an expert in the structure of any of the libraries involved,
but I suspect libpq instantiates its own SSL PRNG that I can't touch
from within perl.

The best solution seems to be building more flexible PRNG initialization
into libpq itself. This has the additional benefit of keeping all the
SSL know-how buried beneath the libpq interface so an application
programmer doesn't need to know about it.  The attached patch is a simple
modification which gives libpq the capability to make explicit attempts
to seed the PRNG just before the OpenSSL context is created. The intended
behavior imitates the OpenSSL command-line tools:

1) If $RANDFILE is set in the environment, it's contents are taken as
   the path to a file providing random data

2) If $RANDFILE is not set, the path ${HOME}/.rnd is assumed. This
   behavior [(1) and (2)] is provided by a standard OpenSSL routine
   RAND_file_name();

3) The file is first considered as a socket provided by an Entropy
   Gathering Daemon. [i.e. RAND_egd() is called on it.]

4) If it's not an EGD socket, it's treated as a regular file with
   "random" contents. [i.e. RAND_load_file() is called on it.]

5) If it's a regular file, an attempt is made to overwrite the file
   with new random data to provide a new seed for next time.
   [i.e. RAND_write_file() is called on it.]

The attached patch against the postgresql-7.1.3 release modifies
fe-connect.c and libpq-fe.h. It's just a few lines of code, but solves
the issue. I've tested it on Solaris 8 and AIX 4.3.3. The only platform-
specific issue I can imagine has to do with "#include <limits.h>" and the
use of the PATH_MAX macro it brings. It ought to work in linux, too. Of
course, I'll freely admit I have no idea what interaction that'll have
with M$ Window$. The patch was generated with GNU 'diff -urN'.

Sun has released a patch adding a /dev/(u)random mechanism, but it's
not generally available I've heard. Solaris 9 and presumably other
commercial systems may start shipping with this out-of-the-box. But
that doesn't help users of older systems (like all of us right now :)
I think this modification could be useful for lots of people who
need libpq and SSL. It's also necessary just to get libpq to work at
all without /dev/urandom (as far as I can tell).

Thanks again, and I hope you and others might find this small
patch useful!
--
Jonathan Marks

Systems Administrator, Production Systems Group
Computing and Communication Services Office
University of Illinois at Urbana-Champaign



Attachment

Re: libpq seed PRNG for SSL support

From
Tom Lane
Date:
Jon Marks <j-marks@uiuc.edu> writes:
> The best solution seems to be building more flexible PRNG initialization
> into libpq itself.

The thing that sticks in my craw about OpenSSL's approach to this is
that they assume application programmers (or database interface library
programmers, in this case) know more about how to find a suitable source
of randomness than the OpenSSL library does.  That strikes me as
completely wrong, not to say an abdication of responsibility for correct
operation of their library.  If it's a hard problem, why do they think
that application programmers (who presumably know little about crypto)
are more likely to get it right than they are?

I have heard that the next release of OpenSSL is going to fix this
problem, and so I'm not inclined to patch around it in our code.

            regards, tom lane