From 12f326a496de53b4c162e7fbf21975ae00289774 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Wed, 17 Feb 2021 11:15:40 +0100
Subject: [PATCH v2] 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 while leaving the
parameter to keep applications from breaking.

Discussion:  https://postgr.es/m/595cf3b1-4ffe-7f05-6f72-f72b7afa7993%402ndquadrant.com
Discussion:  https://postgr.es/m/7E384D48-11C5-441B-9EC3-F7DB1F8518F6@yesql.se
---
 doc/src/sgml/libpq.sgml                  | 33 ++----------------------
 src/backend/libpq/be-secure-openssl.c    |  8 +++---
 src/interfaces/libpq/fe-connect.c        |  6 ++++-
 src/interfaces/libpq/fe-secure-openssl.c | 13 +++++-----
 src/interfaces/libpq/libpq-int.h         |  2 +-
 5 files changed, 19 insertions(+), 43 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 5e25f20843..4e5de7a75c 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1620,24 +1620,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       <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.
+        Ignored (formerly, this specified whether to attempt SSL compression).
        </para>
       </listitem>
      </varlistentry>
@@ -2488,9 +2471,7 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
          <term><literal>compression</literal></term>
           <listitem>
            <para>
-            If SSL compression is in use, returns the name of the compression
-            algorithm, or "on" if compression is used but the algorithm is
-            not known. If compression is not in use, returns "off".
+            Compression is no longer supported, always returns "off".
            </para>
           </listitem>
          </varlistentry>
@@ -7155,16 +7136,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..118ec8dfa2 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;
@@ -1185,10 +1188,7 @@ be_tls_get_cipher_bits(Port *port)
 bool
 be_tls_get_compression(Port *port)
 {
-	if (port->ssl)
-		return (SSL_get_current_compression(port->ssl) != NULL);
-	else
-		return false;
+	return false;
 }
 
 const char *
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index db71fea169..a89be0d9d3 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -293,8 +293,12 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"SSL-Mode", "", 12,		/* sizeof("verify-full") == 12 */
 	offsetof(struct pg_conn, sslmode)},
 
+	/*
+	 * "sslcompression" is no longer used, but keep it present for backwards
+	 * compatibility.
+	 */
 	{"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
-		"SSL-Compression", "", 1,
+		"SSL-Compression", "D", 1,
 	offsetof(struct pg_conn, sslcompression)},
 
 	{"sslcert", "PGSSLCERT", NULL, NULL,
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 0fa10a23b4..bc58cdcd47 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;
 }
@@ -1553,8 +1550,12 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
 	if (strcmp(attribute_name, "cipher") == 0)
 		return SSL_get_cipher(conn->ssl);
 
+	/*
+	 * SSL compression is disabled, so even if connecting to an older server
+	 * which still supports it, it wont be active.
+	 */
 	if (strcmp(attribute_name, "compression") == 0)
-		return SSL_get_current_compression(conn->ssl) ? "on" : "off";
+		return "off";
 
 	if (strcmp(attribute_name, "protocol") == 0)
 		return SSL_get_version(conn->ssl);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index ce36aabd25..66cb24b001 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -356,7 +356,7 @@ 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	   *sslcompression; /* SSL compression (OBSOLETE, NOT USED) */
 	char	   *sslkey;			/* client key filename */
 	char	   *sslcert;		/* client certificate filename */
 	char	   *sslpassword;	/* client key file password */
-- 
2.21.1 (Apple Git-122.3)

