SSL renegotiation

From: Alvaro Herrera <alvherre(at)2ndquadrant(dot)com>
To: Pg Hackers <pgsql-hackers(at)postgresql(dot)org>
Cc: Sean Chittenden <sean(at)chittenden(dot)org>
Subject: SSL renegotiation
Date: 2013-07-10 21:20:17
Message-ID: 20130710212017.GB4941@eldon.alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-committers pgsql-hackers

Hi,

I'm having a look at the SSL support code, because one of our customers
reported it behaves unstably when the network is unreliable. I have yet
to reproduce the exact problem they're having, but while reading the
code I notice this in be-secure.c:secure_write() :

if (ssl_renegotiation_limit && port->count > ssl_renegotiation_limit * 1024L)
{
SSL_set_session_id_context(port->ssl, (void *) &SSL_context,
sizeof(SSL_context));
if (SSL_renegotiate(port->ssl) <= 0)
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("SSL renegotiation failure")));
if (SSL_do_handshake(port->ssl) <= 0)
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("SSL renegotiation failure")));
if (port->ssl->state != SSL_ST_OK)
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("SSL failed to send renegotiation request")));
port->ssl->state |= SSL_ST_ACCEPT;
SSL_do_handshake(port->ssl);
if (port->ssl->state != SSL_ST_OK)
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("SSL renegotiation failure")));
port->count = 0;
}

I call your attention to the fact that we're calling SSL_do_handshake
twice here; and what's more, we're messing with the internal
port->ssl->state variable by setting the SSL_ST_ACCEPT bit. According
to the commit message that introduces this[1], this is "text book
correct", but I'm unable to find the text book that specifies that this
is correct. Is it? I have gone through the OpenSSL documentation and
can find not a single bit on this; and I have also gone through the
OpenSSL mailing list archives and as far as I can tell they say you have
to call SSL_renegotiate() and then SSL_do_handshake() once, and that's
it. (You can call SSL_renegotiate_pending() afterwards to verify that
the renegotiation completed successfully, which is something we don't
do.)

I have found in our archives several reports of people that get "SSL
renegotiation failed" error messages in the log, and no explanation has
ever been found. I instrumented that block, and I have observed that
after the second handshake call, ssl->state is 0x2111, 0x21c0, 0x21a0
and other values; never SSL_ST_OK. (0x2000 is SSL_ST_ACCEPT which is
the bit we added; SSL_ST_OK is 0x03). If I remove the second
SSL_do_handshake() call and the changes to port->ssl->state, everything
appears to work perfectly well and there's no extra log spam (and
ssl->state is SSL_ST_OK by the time things are finished). So apparently
renegotiation is not actually failing, but we're just adding a confusing
error message for no apparent reason.

Thoughts?

I have still to find where the actual problems are happening in
unreliable networks ...

[1] commit 17386ac45345fe38a10caec9d6e63afa3ce31bb9
Author: Bruce Momjian <bruce(at)momjian(dot)us>
Date: Wed Jun 11 15:05:50 2003 +0000

patch by Sean Chittenden (in CC), posted as [2]

[2] http://www.postgresql.org/message-id/20030419190821.GQ79923@perrin.int.nxad.com

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Responses

Browse pgsql-committers by date

  From Date Subject
Next Message Alvaro Herrera 2013-07-10 22:34:44 Re: SSL renegotiation
Previous Message Peter Eisentraut 2013-07-10 01:13:17 pgsql: Add coverage/ to .gitignore

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2013-07-10 21:33:18 Re: changeset generation v5-01 - Patches & git tree
Previous Message Kevin Grittner 2013-07-10 19:21:23 Re: changeset generation v5-01 - Patches & git tree