some reading on the subject.
1) PostgreSQL uses ephemeral keying, for its connections (good thing)
2) PostgreSQL doesn't set the cipher list that it allows (bad thing,
fixed)
3) PostgreSQL's renegotiation code wasn't text book correct (could be
bad, fixed)
4) The rate of renegotiating was insanely low (as Tom pointed out, set
to a more reasonable level)
I haven't checked around much to see if there are any other SSL bits
that need some review, but I'm doing some OpenSSL work right now
and'll send patches for improvements along the way (if I find them).
At the very least, the changes in this patch will make security folks
happier for sure. The constant renegotiation of sessions was likely a
boon to systems that had bad entropy gathering means (read: Slowaris
/dev/rand|/dev/urand != ANDIrand). The new limit for renegotiations
is 512MB which should be much more reasonable.
Sean Chittenden
Win32 port is now called 'win32' rather than 'win'
add -lwsock32 on Win32
make gethostname() be only used when kerberos4 is enabled
use /port/getopt.c
new /port/opendir.c routines
disable GUC unix_socket_group on Win32
convert some keywords.c symbols to KEYWORD_P to prevent conflict
create new FCNTL_NONBLOCK macro to turn off socket blocking
create new /include/port.h file that has /port prototypes, move
out of c.h
new /include/port/win32_include dir to hold missing include files
work around ERROR being defined in Win32 includes
typing error in src/backend/libpq/be-secure.c ???
Long Description
In src/backend/libpq/be-secure.c: secure_write
on SSL_ERROR_WANT_WRITE call secure_read instead
secure_write again. May be is this a typing error?
Sergey N. Yatskevich (syatskevich@n21lab.gosniias.msk.ru)
believe I didn't notice this before -- once 64k was sent to/from the
server the client would crash. Basicly, in 7.3 the server SSL code set
the initial state to "about to renegotiate" without actually starting
the renegotiation. In addition, the server and client didn't properly
handle the SSL_ERROR_WANT_(READ|WRITE) error. This is fixed in the
second patch.
Nathan Mueller
first, that I missed when checking over 7.3.1, was that the client
method was switched to SSLv23 along with the server. The SSLv23 client
method does SSLv2 by default, but can also understand SSLv3. In our
situation the SSLv2 backwords compatibility is really only needed on the
server. This is the first patch.
The last thing is that I found a way for the server to understand SSLv2
HELLO messages (sent by pre-7.3 clients) but then get them to talk
SSLv3. This is the last one.
Nathan Mueller
"SSLv23_method(void), SSLv23_server_method(void), SSLv23_client_method(void)
A TLS/SSL connection established with these methods will understand the SSLv2,
SSLv3, and TLSv1 protocol. A client will send out SSLv2 client hello messages
and will indicate that it also understands SSLv3 and TLSv1. A server will
understand SSLv2, SSLv3, and TLSv1 client hello messages. This is the best
choice when compatibility is a concern."
This will maintain backwards compatibility for those us that don't use
TLS connections ...
on the server, if DebugLvl >= 2.
The patch also includes a late addition to the last patch
(X509_check_private_key()). I'm not sure why it the currect
revision wasn't tagged.
Bear Giles
If the user has certificates in $HOME/.postgresql/postgresql.crt
and $HOME/.postgresql/postgresql.key exist, they are provided
to the server. The certificate used to sign this cert must be
known to the server, in $DataDir/root.crt. If successful, the
cert's "common name" is logged.
Client certs are not used for authentication, but they could be
via the port->peer (X509 *), port->peer_dn (char *) or
port->peer_cn (char *) fields. Or any other function could be
used, e.g., many sites like the issuer + serial number hash.
Bear Giles
In order to reduce the risk of cryptanalysis during extended
sessions (or brief ones involving a substantial amount of data),
this patch renegotiates the session key after 64kib has been
transferred.
Bear Giles
As the comment headers in be-secure.c discusses, EPH preserves
confidentiality even if the static private key (which is usually
kept unencrypted) is compromised.
Because of the value of this, common default values are hard-coded
to protect the confidentiality of the data even if an attacker
successfully deletes or modifies the external file.
Bear Giles
Attached are a revised set of SSL patches. Many of these patches
are motivated by security concerns, it's not just bug fixes. The key
differences (from stock 7.2.1) are:
*) almost all code that directly uses the OpenSSL library is in two
new files,
src/interfaces/libpq/fe-ssl.c
src/backend/postmaster/be-ssl.c
in the long run, it would be nice to merge these two files.
*) the legacy code to read and write network data have been
encapsulated into read_SSL() and write_SSL(). These functions
should probably be renamed - they handle both SSL and non-SSL
cases.
the remaining code should eliminate the problems identified
earlier, albeit not very cleanly.
*) both front- and back-ends will send a SSL shutdown via the
new close_SSL() function. This is necessary for sessions to
work properly.
(Sessions are not yet fully supported, but by cleanly closing
the SSL connection instead of just sending a TCP FIN packet
other SSL tools will be much happier.)
*) The client certificate and key are now expected in a subdirectory
of the user's home directory. Specifically,
- the directory .postgresql must be owned by the user, and
allow no access by 'group' or 'other.'
- the file .postgresql/postgresql.crt must be a regular file
owned by the user.
- the file .postgresql/postgresql.key must be a regular file
owned by the user, and allow no access by 'group' or 'other'.
At the current time encrypted private keys are not supported.
There should also be a way to support multiple client certs/keys.
*) the front-end performs minimal validation of the back-end cert.
Self-signed certs are permitted, but the common name *must*
match the hostname used by the front-end. (The cert itself
should always use a fully qualified domain name (FDQN) in its
common name field.)
This means that
psql -h eris db
will fail, but
psql -h eris.example.com db
will succeed. At the current time this must be an exact match;
future patches may support any FQDN that resolves to the address
returned by getpeername(2).
Another common "problem" is expiring certs. For now, it may be
a good idea to use a very-long-lived self-signed cert.
As a compile-time option, the front-end can specify a file
containing valid root certificates, but it is not yet required.
*) the back-end performs minimal validation of the client cert.
It allows self-signed certs. It checks for expiration. It
supports a compile-time option specifying a file containing
valid root certificates.
*) both front- and back-ends default to TLSv1, not SSLv3/SSLv2.
*) both front- and back-ends support DSA keys. DSA keys are
moderately more expensive on startup, but many people consider
them preferable than RSA keys. (E.g., SSH2 prefers DSA keys.)
*) if /dev/urandom exists, both client and server will read 16k
of randomization data from it.
*) the server can read empheral DH parameters from the files
$DataDir/dh512.pem
$DataDir/dh1024.pem
$DataDir/dh2048.pem
$DataDir/dh4096.pem
if none are provided, the server will default to hardcoded
parameter files provided by the OpenSSL project.
Remaining tasks:
*) the select() clauses need to be revisited - the SSL abstraction
layer may need to absorb more of the current code to avoid rare
deadlock conditions. This also touches on a true solution to
the pg_eof() problem.
*) the SIGPIPE signal handler may need to be revisited.
*) support encrypted private keys.
*) sessions are not yet fully supported. (SSL sessions can span
multiple "connections," and allow the client and server to avoid
costly renegotiations.)
*) makecert - a script that creates back-end certs.
*) pgkeygen - a tool that creates front-end certs.
*) the whole protocol issue, SASL, etc.
*) certs are fully validated - valid root certs must be available.
This is a hassle, but it means that you *can* trust the identity
of the server.
*) the client library can handle hardcoded root certificates, to
avoid the need to copy these files.
*) host name of server cert must resolve to IP address, or be a
recognized alias. This is more liberal than the previous
iteration.
*) the number of bytes transferred is tracked, and the session
key is periodically renegotiated.
*) basic cert generation scripts (mkcert.sh, pgkeygen.sh). The
configuration files have reasonable defaults for each type
of use.
Bear Giles