I think this block is better written as:
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 in renegotiate")));
else { int handshake;
do { handshake = SSL_do_handshake(port->ssl); if (handshake <= 0)
ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("SSL renegotiation failure in handshake, retrying"))); } while (handshake <= 0);
if (port->ssl->state != SSL_ST_OK) ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("SSL failed to send renegotiation request")));
else port->count = 0; } }
In other words, retry the SSL_do_handshake() until it reports OK, but
not more than that; this seems to give better results in my (admittedly
crude) experiments. I am unsure about checking port->ssl->state after
the handshake; it's probably pointless, really.
In any case, the old code was calling SSL_do_handshake() even if
SSL_renegotiate() failed; and it was resetting the port->count even if
the handshake failed. Both of these smell like bugs to me.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services