On 03.06.21 20:14, Tom Lane wrote:
I wrote:
It looks like the immediate problem can be resolved by just adding
a check for conn->pghost not being NULL,

... scratch that.  There's another problem here, which is that this
code should not be looking at conn->pghost AT ALL.  That will do the
wrong thing with a multi-element host list.  The right thing to be
looking at is conn->connhost[conn->whichhost].host --- with a test
to make sure it's not NULL or an empty string.  (I didn't stop to
study this code close enough to see if it'll ignore an empty
string without help.)

Patch attached. Empty host string was handled implicitly by the IP detection expression, but I added an explicit check for sanity. (I wasn't actually able to get an empty string to this point, but it's clearly better to be prepared for it.)

From 095bb64fc735c54d0ebf17ba6c13e0de5af44a36 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 7 Jun 2021 11:50:01 +0200
Subject: [PATCH] libpq: Fix SNI host handling

Fix handling of NULL host name (possibly by using hostaddr).  It
previously crashed.  Also, we should look at connhost, not pghost, to
handle multi-host specifications.

Reported-by: Jacob Champion <pchamp...@vmware.com>
Discussion: 
https://www.postgresql.org/message-id/504c276ab6eee000bb23d571ea9b0ced4250774e.ca...@vmware.com
---
 src/interfaces/libpq/fe-secure-openssl.c | 27 ++++++++++++++----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/interfaces/libpq/fe-secure-openssl.c 
b/src/interfaces/libpq/fe-secure-openssl.c
index 00d43f3eff..36fec96ef1 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1087,20 +1087,25 @@ initialize_SSL(PGconn *conn)
         * Per RFC 6066, do not set it if the host is a literal IP address (IPv4
         * or IPv6).
         */
-       if (conn->sslsni && conn->sslsni[0] &&
-               !(strspn(conn->pghost, "0123456789.") == strlen(conn->pghost) ||
-                 strchr(conn->pghost, ':')))
+       if (conn->sslsni && conn->sslsni[0])
        {
-               if (SSL_set_tlsext_host_name(conn->ssl, conn->pghost) != 1)
+               const char *host = conn->connhost[conn->whichhost].host;
+
+               if (host && host[0] &&
+                       !(strspn(host, "0123456789.") == strlen(host) ||
+                         strchr(host, ':')))
                {
-                       char       *err = SSLerrmessage(ERR_get_error());
+                       if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
+                       {
+                               char       *err = 
SSLerrmessage(ERR_get_error());
 
-                       appendPQExpBuffer(&conn->errorMessage,
-                                                         libpq_gettext("could 
not set SSL Server Name Indication (SNI): %s\n"),
-                                                         err);
-                       SSLerrfree(err);
-                       SSL_CTX_free(SSL_context);
-                       return -1;
+                               appendPQExpBuffer(&conn->errorMessage,
+                                                                 
libpq_gettext("could not set SSL Server Name Indication (SNI): %s\n"),
+                                                                 err);
+                               SSLerrfree(err);
+                               SSL_CTX_free(SSL_context);
+                               return -1;
+                       }
                }
        }
 
-- 
2.31.1

Reply via email to