aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/be-secure-openssl.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2015-07-28 21:39:32 +0200
committerAndres Freund <andres@anarazel.de>2015-07-28 22:06:31 +0200
commit426746b93093a0fef53b23ce4b6421bed28e5c60 (patch)
treeb4f53a6f5660b2856a7a177826cbb81efa85d75c /src/backend/libpq/be-secure-openssl.c
parent01f6bb4b2dcc571ad0cc6a404595de4b03157534 (diff)
downloadpostgresql-426746b93093a0fef53b23ce4b6421bed28e5c60.tar.gz
postgresql-426746b93093a0fef53b23ce4b6421bed28e5c60.zip
Remove ssl renegotiation support.
While postgres' use of SSL renegotiation is a good idea in theory, it turned out to not work well in practice. The specification and openssl's implementation of it have lead to several security issues. Postgres' use of renegotiation also had its share of bugs. Additionally OpenSSL has a bunch of bugs around renegotiation, reported and open for years, that regularly lead to connections breaking with obscure error messages. We tried increasingly complex workarounds to get around these bugs, but we didn't find anything complete. Since these connection breakages often lead to hard to debug problems, e.g. spuriously failing base backups and significant latency spikes when synchronous replication is used, we have decided to change the default setting for ssl renegotiation to 0 (disabled) in the released backbranches and remove it entirely in 9.5 and master. Author: Andres Freund Discussion: 20150624144148.GQ4797@alap3.anarazel.de Backpatch: 9.5 and master, 9.0-9.4 get a different patch
Diffstat (limited to 'src/backend/libpq/be-secure-openssl.c')
-rw-r--r--src/backend/libpq/be-secure-openssl.c70
1 files changed, 2 insertions, 68 deletions
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index f0774fe8c95..e9bc282d2e7 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -16,12 +16,8 @@
* backend can restart automatically, it is important that
* we select an algorithm that continues to provide confidentiality
* even if the attacker has the server's private key. Ephemeral
- * DH (EDH) keys provide this, and in fact provide Perfect Forward
- * Secrecy (PFS) except for situations where the session can
- * be hijacked during a periodic handshake/renegotiation.
- * Even that backdoor can be closed if client certificates
- * are used (since the imposter will be unable to successfully
- * complete renegotiation).
+ * DH (EDH) keys provide this and more (Perfect Forward Secrecy
+ * aka PFS).
*
* N.B., the static private key should still be protected to
* the largest extent possible, to minimize the risk of
@@ -37,12 +33,6 @@
* session. In this case you'll need to temporarily disable
* EDH by commenting out the callback.
*
- * ...
- *
- * Because the risk of cryptanalysis increases as large
- * amounts of data are sent with the same session key, the
- * session keys are periodically renegotiated.
- *
*-------------------------------------------------------------------------
*/
@@ -92,9 +82,6 @@ static const char *SSLerrmessage(void);
static char *X509_NAME_to_cstring(X509_NAME *name);
-/* are we in the middle of a renegotiation? */
-static bool in_ssl_renegotiation = false;
-
static SSL_CTX *SSL_context = NULL;
/* ------------------------------------------------------------ */
@@ -570,37 +557,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
ssize_t n;
int err;
- /*
- * If SSL renegotiations are enabled and we're getting close to the limit,
- * start one now; but avoid it if there's one already in progress.
- * Request the renegotiation 1kB before the limit has actually expired.
- */
- if (ssl_renegotiation_limit && !in_ssl_renegotiation &&
- port->count > (ssl_renegotiation_limit - 1) * 1024L)
- {
- in_ssl_renegotiation = true;
-
- /*
- * The way we determine that a renegotiation has completed is by
- * observing OpenSSL's internal renegotiation counter. Make sure we
- * start out at zero, and assume that the renegotiation is complete
- * when the counter advances.
- *
- * OpenSSL provides SSL_renegotiation_pending(), but this doesn't seem
- * to work in testing.
- */
- SSL_clear_num_renegotiations(port->ssl);
-
- /* without this, renegotiation fails when a client cert is used */
- 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 failure during renegotiation start")));
- }
-
errno = 0;
n = SSL_write(port->ssl, ptr, len);
err = SSL_get_error(port->ssl, n);
@@ -646,28 +602,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
break;
}
- if (n >= 0)
- {
- /* is renegotiation complete? */
- if (in_ssl_renegotiation &&
- SSL_num_renegotiations(port->ssl) >= 1)
- {
- in_ssl_renegotiation = false;
- port->count = 0;
- }
-
- /*
- * if renegotiation is still ongoing, and we've gone beyond the limit,
- * kill the connection now -- continuing to use it can be considered a
- * security problem.
- */
- if (in_ssl_renegotiation &&
- port->count > ssl_renegotiation_limit * 1024L)
- ereport(FATAL,
- (errcode(ERRCODE_PROTOCOL_VIOLATION),
- errmsg("SSL failed to renegotiate connection before limit expired")));
- }
-
return n;
}