From f5a2ba03675725adcd95faa48b1ece1bb5b4c0dd Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Wed, 17 Feb 2021 11:15:40 +0100
Subject: [PATCH] Disallow SSL compression

SSL compression has been disabled in OpenSSL since version 1.1.0, and
was disabled in many distros long before that.  The most recent TLS
version, TLSv1.3, also disallows compression at the protocol level.
PostgreSQL disabled compression by default years ago and recommended
against using it, this finally removes the feaure

Discussion:  https://www.postgresql.org/message-id/flat/595cf3b1-4ffe-7f05-6f72-f72b7afa7993%402ndquadrant.com
---
 .../postgres_fdw/expected/postgres_fdw.out    |  3 +-
 contrib/postgres_fdw/sql/postgres_fdw.sql     |  1 -
 doc/src/sgml/libpq.sgml                       | 36 -------------------
 src/backend/libpq/be-secure-openssl.c         |  3 ++
 src/interfaces/libpq/fe-connect.c             |  6 ----
 src/interfaces/libpq/fe-secure-openssl.c      |  7 ++--
 src/interfaces/libpq/libpq-int.h              |  1 -
 7 files changed, 6 insertions(+), 51 deletions(-)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 0649b6b81c..c2565dfc70 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -163,7 +163,6 @@ ALTER SERVER testserver1 OPTIONS (
 	keepalives_interval 'value',
 	tcp_user_timeout 'value',
 	-- requiressl 'value',
-	sslcompression 'value',
 	sslmode 'value',
 	sslcert 'value',
 	sslkey 'value',
@@ -8946,7 +8945,7 @@ DO $d$
     END;
 $d$;
 ERROR:  invalid option "password"
-HINT:  Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, sslcrldir, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size
+HINT:  Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcert, sslkey, sslrootcert, sslcrl, sslcrldir, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size
 CONTEXT:  SQL statement "ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw')"
 PL/pgSQL function inline_code_block line 3 at EXECUTE
 -- If we add a password for our user mapping instead, we should get a different
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 2b525ea44a..a143a70406 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -177,7 +177,6 @@ ALTER SERVER testserver1 OPTIONS (
 	keepalives_interval 'value',
 	tcp_user_timeout 'value',
 	-- requiressl 'value',
-	sslcompression 'value',
 	sslmode 'value',
 	sslcert 'value',
 	sslkey 'value',
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 5e25f20843..594100fa4d 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1616,32 +1616,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       </listitem>
      </varlistentry>
 
-     <varlistentry id="libpq-connect-sslcompression" xreflabel="sslcompression">
-      <term><literal>sslcompression</literal></term>
-      <listitem>
-       <para>
-        If set to 1, data sent over SSL connections will be compressed.  If
-        set to 0, compression will be disabled.  The default is 0.  This
-        parameter is ignored if a connection without SSL is made.
-       </para>
-
-       <para>
-        SSL compression is nowadays considered insecure and its use is no
-        longer recommended.  <productname>OpenSSL</productname> 1.1.0 disables
-        compression by default, and many operating system distributions
-        disable it in prior versions as well, so setting this parameter to on
-        will not have any effect if the server does not accept compression.
-       </para>
-
-       <para>
-        If security is not a primary concern, compression can improve
-        throughput if the network is the bottleneck.  Disabling compression
-        can improve response time and throughput if CPU performance is the
-        limiting factor.
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry id="libpq-connect-sslcert" xreflabel="sslcert">
       <term><literal>sslcert</literal></term>
       <listitem>
@@ -7155,16 +7129,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
      </para>
     </listitem>
 
-    <listitem>
-     <para>
-      <indexterm>
-       <primary><envar>PGSSLCOMPRESSION</envar></primary>
-      </indexterm>
-      <envar>PGSSLCOMPRESSION</envar> behaves the same as the <xref
-      linkend="libpq-connect-sslcompression"/> connection parameter.
-     </para>
-    </listitem>
-
     <listitem>
      <para>
       <indexterm>
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 4c4f025eb1..b4800bb147 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -245,6 +245,9 @@ be_tls_init(bool isServerStart)
 	/* disallow SSL session caching, too */
 	SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);
 
+	/* disallow SSL compression */
+	SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
+
 	/* set up ephemeral DH and ECDH keys */
 	if (!initialize_dh(context, isServerStart))
 		goto error;
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index db71fea169..3c9862d7c4 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -293,10 +293,6 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"SSL-Mode", "", 12,		/* sizeof("verify-full") == 12 */
 	offsetof(struct pg_conn, sslmode)},
 
-	{"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
-		"SSL-Compression", "", 1,
-	offsetof(struct pg_conn, sslcompression)},
-
 	{"sslcert", "PGSSLCERT", NULL, NULL,
 		"SSL-Client-Cert", "", 64,
 	offsetof(struct pg_conn, sslcert)},
@@ -4004,8 +4000,6 @@ freePGconn(PGconn *conn)
 		free(conn->sslcrl);
 	if (conn->sslcrldir)
 		free(conn->sslcrldir);
-	if (conn->sslcompression)
-		free(conn->sslcompression);
 	if (conn->requirepeer)
 		free(conn->requirepeer);
 	if (conn->ssl_min_protocol_version)
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0fa10a23b4..bee0226552 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1258,12 +1258,9 @@ initialize_SSL(PGconn *conn)
 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
 
 	/*
-	 * Set compression option if necessary.
+	 * Disable SSL compression
 	 */
-	if (conn->sslcompression && conn->sslcompression[0] == '0')
-		SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
-	else
-		SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
+	SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
 
 	return 0;
 }
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index ce36aabd25..78cd5bc647 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -356,7 +356,6 @@ struct pg_conn
 	char	   *keepalives_count;	/* maximum number of TCP keepalive
 									 * retransmits */
 	char	   *sslmode;		/* SSL mode (require,prefer,allow,disable) */
-	char	   *sslcompression; /* SSL compression (0 or 1) */
 	char	   *sslkey;			/* client key filename */
 	char	   *sslcert;		/* client certificate filename */
 	char	   *sslpassword;	/* client key file password */
-- 
2.21.1 (Apple Git-122.3)

