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 <br...@momjian.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.gq79...@perrin.int.nxad.com

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


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to