Skip to content

Commit 426746b

Browse files
committed
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
1 parent 01f6bb4 commit 426746b

File tree

6 files changed

+2
-121
lines changed

6 files changed

+2
-121
lines changed

doc/src/sgml/config.sgml

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,35 +1034,6 @@ include_dir 'conf.d'
10341034
</listitem>
10351035
</varlistentry>
10361036

1037-
<varlistentry id="guc-ssl-renegotiation-limit" xreflabel="ssl_renegotiation_limit">
1038-
<term><varname>ssl_renegotiation_limit</varname> (<type>integer</type>)
1039-
<indexterm>
1040-
<primary><varname>ssl_renegotiation_limit</> configuration parameter</primary>
1041-
</indexterm>
1042-
</term>
1043-
<listitem>
1044-
<para>
1045-
Specifies how much data can flow over an <acronym>SSL</>-encrypted
1046-
connection before renegotiation of the session keys will take
1047-
place. Renegotiation decreases an attacker's chances of doing
1048-
cryptanalysis when large amounts of traffic can be examined, but it
1049-
also carries a large performance penalty. The sum of sent and received
1050-
traffic is used to check the limit. If this parameter is set to 0,
1051-
renegotiation is disabled. The default is <literal>512MB</>.
1052-
</para>
1053-
<note>
1054-
<para>
1055-
SSL libraries from before November 2009 are insecure when using SSL
1056-
renegotiation, due to a vulnerability in the SSL protocol. As a
1057-
stop-gap fix for this vulnerability, some vendors shipped SSL
1058-
libraries incapable of doing renegotiation. If any such libraries
1059-
are in use on the client or server, SSL renegotiation should be
1060-
disabled.
1061-
</para>
1062-
</note>
1063-
</listitem>
1064-
</varlistentry>
1065-
10661037
<varlistentry id="guc-ssl-ciphers" xreflabel="ssl_ciphers">
10671038
<term><varname>ssl_ciphers</varname> (<type>string</type>)
10681039
<indexterm>

src/backend/libpq/be-secure-openssl.c

Lines changed: 2 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@
1616
* backend can restart automatically, it is important that
1717
* we select an algorithm that continues to provide confidentiality
1818
* even if the attacker has the server's private key. Ephemeral
19-
* DH (EDH) keys provide this, and in fact provide Perfect Forward
20-
* Secrecy (PFS) except for situations where the session can
21-
* be hijacked during a periodic handshake/renegotiation.
22-
* Even that backdoor can be closed if client certificates
23-
* are used (since the imposter will be unable to successfully
24-
* complete renegotiation).
19+
* DH (EDH) keys provide this and more (Perfect Forward Secrecy
20+
* aka PFS).
2521
*
2622
* N.B., the static private key should still be protected to
2723
* the largest extent possible, to minimize the risk of
@@ -37,12 +33,6 @@
3733
* session. In this case you'll need to temporarily disable
3834
* EDH by commenting out the callback.
3935
*
40-
* ...
41-
*
42-
* Because the risk of cryptanalysis increases as large
43-
* amounts of data are sent with the same session key, the
44-
* session keys are periodically renegotiated.
45-
*
4636
*-------------------------------------------------------------------------
4737
*/
4838

@@ -92,9 +82,6 @@ static const char *SSLerrmessage(void);
9282

9383
static char *X509_NAME_to_cstring(X509_NAME *name);
9484

95-
/* are we in the middle of a renegotiation? */
96-
static bool in_ssl_renegotiation = false;
97-
9885
static SSL_CTX *SSL_context = NULL;
9986

10087
/* ------------------------------------------------------------ */
@@ -570,37 +557,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
570557
ssize_t n;
571558
int err;
572559

573-
/*
574-
* If SSL renegotiations are enabled and we're getting close to the limit,
575-
* start one now; but avoid it if there's one already in progress.
576-
* Request the renegotiation 1kB before the limit has actually expired.
577-
*/
578-
if (ssl_renegotiation_limit && !in_ssl_renegotiation &&
579-
port->count > (ssl_renegotiation_limit - 1) * 1024L)
580-
{
581-
in_ssl_renegotiation = true;
582-
583-
/*
584-
* The way we determine that a renegotiation has completed is by
585-
* observing OpenSSL's internal renegotiation counter. Make sure we
586-
* start out at zero, and assume that the renegotiation is complete
587-
* when the counter advances.
588-
*
589-
* OpenSSL provides SSL_renegotiation_pending(), but this doesn't seem
590-
* to work in testing.
591-
*/
592-
SSL_clear_num_renegotiations(port->ssl);
593-
594-
/* without this, renegotiation fails when a client cert is used */
595-
SSL_set_session_id_context(port->ssl, (void *) &SSL_context,
596-
sizeof(SSL_context));
597-
598-
if (SSL_renegotiate(port->ssl) <= 0)
599-
ereport(COMMERROR,
600-
(errcode(ERRCODE_PROTOCOL_VIOLATION),
601-
errmsg("SSL failure during renegotiation start")));
602-
}
603-
604560
errno = 0;
605561
n = SSL_write(port->ssl, ptr, len);
606562
err = SSL_get_error(port->ssl, n);
@@ -646,28 +602,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
646602
break;
647603
}
648604

649-
if (n >= 0)
650-
{
651-
/* is renegotiation complete? */
652-
if (in_ssl_renegotiation &&
653-
SSL_num_renegotiations(port->ssl) >= 1)
654-
{
655-
in_ssl_renegotiation = false;
656-
port->count = 0;
657-
}
658-
659-
/*
660-
* if renegotiation is still ongoing, and we've gone beyond the limit,
661-
* kill the connection now -- continuing to use it can be considered a
662-
* security problem.
663-
*/
664-
if (in_ssl_renegotiation &&
665-
port->count > ssl_renegotiation_limit * 1024L)
666-
ereport(FATAL,
667-
(errcode(ERRCODE_PROTOCOL_VIOLATION),
668-
errmsg("SSL failed to renegotiate connection before limit expired")));
669-
}
670-
671605
return n;
672606
}
673607

src/backend/libpq/be-secure.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ char *ssl_key_file;
4343
char *ssl_ca_file;
4444
char *ssl_crl_file;
4545

46-
/*
47-
* How much data can be sent across a secure connection
48-
* (total in both directions) before we require renegotiation.
49-
* Set to 0 to disable renegotiation completely.
50-
*/
51-
int ssl_renegotiation_limit;
52-
5346
#ifdef USE_SSL
5447
bool ssl_loaded_verify_locations = false;
5548
#endif

src/backend/utils/misc/guc.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,17 +2577,6 @@ static struct config_int ConfigureNamesInt[] =
25772577
NULL, assign_tcp_keepalives_interval, show_tcp_keepalives_interval
25782578
},
25792579

2580-
{
2581-
{"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SECURITY,
2582-
gettext_noop("Set the amount of traffic to send and receive before renegotiating the encryption keys."),
2583-
NULL,
2584-
GUC_UNIT_KB,
2585-
},
2586-
&ssl_renegotiation_limit,
2587-
512 * 1024, 0, MAX_KILOBYTES,
2588-
NULL, NULL, NULL
2589-
},
2590-
25912580
{
25922581
{"tcp_keepalives_count", PGC_USERSET, CLIENT_CONN_OTHER,
25932582
gettext_noop("Maximum number of TCP keepalive retransmits."),

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
# (change requires restart)
8484
#ssl_prefer_server_ciphers = on # (change requires restart)
8585
#ssl_ecdh_curve = 'prime256v1' # (change requires restart)
86-
#ssl_renegotiation_limit = 512MB # amount of data between renegotiations
8786
#ssl_cert_file = 'server.crt' # (change requires restart)
8887
#ssl_key_file = 'server.key' # (change requires restart)
8988
#ssl_ca_file = '' # (change requires restart)

src/include/libpq/libpq-be.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,6 @@ typedef struct
9292
} pg_gssinfo;
9393
#endif
9494

95-
/*
96-
* SSL renegotiations
97-
*/
98-
extern int ssl_renegotiation_limit;
99-
10095
/*
10196
* This is used by the postmaster in its communication with frontends. It
10297
* contains all state information needed during this communication before the

0 commit comments

Comments
 (0)