since-v4.diff.txt

text/plain

Filename: since-v4.diff.txt
Type: text/plain
Part: 0
Message: Re: [PATCH] Accept IP addresses in server certificate SANs
commit 8c427e3289a28cb683eff5d05b2e8770c3c07662
Author: Jacob Champion <pchampion@vmware.com>
Date:   Tue Feb 8 16:26:27 2022 -0800

    squash! libpq: allow IP address SANs in server certs

diff --git a/src/interfaces/libpq/fe-secure-common.c b/src/interfaces/libpq/fe-secure-common.c
index cfdde58e67..4d78715756 100644
--- a/src/interfaces/libpq/fe-secure-common.c
+++ b/src/interfaces/libpq/fe-secure-common.c
@@ -160,7 +160,8 @@ pq_verify_peer_name_matches_certificate_name(PGconn *conn,
  */
 int
 pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
-										   const char *ipdata, size_t iplen,
+										   const unsigned char *ipdata,
+										   size_t iplen,
 										   char **store_name)
 {
 	char	   *addrstr;
@@ -193,8 +194,9 @@ pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
 		family = PGSQL_AF_INET;
 
 		/*
-		 * The use of inet_aton() instead of inet_pton() is deliberate; the
-		 * latter cannot handle alternate IPv4 notations ("numbers-and-dots").
+		 * The use of inet_aton() is deliberate; we accept alternative IPv4
+		 * address notations that are accepted by inet_aton() but not
+		 * inet_pton() as server addresses.
 		 */
 		if (inet_aton(host, &addr))
 		{
diff --git a/src/interfaces/libpq/fe-secure-common.h b/src/interfaces/libpq/fe-secure-common.h
index 4316c3d1b7..20ff9ba5db 100644
--- a/src/interfaces/libpq/fe-secure-common.h
+++ b/src/interfaces/libpq/fe-secure-common.h
@@ -23,7 +23,8 @@ extern int	pq_verify_peer_name_matches_certificate_name(PGconn *conn,
 														 const char *namedata, size_t namelen,
 														 char **store_name);
 extern int	pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
-													   const char *addrdata, size_t addrlen,
+													   const unsigned char *addrdata,
+													   size_t addrlen,
 													   char **store_name);
 extern bool pq_verify_peer_name_matches_certificate(PGconn *conn);
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 7173ea0d73..00e297db17 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -544,8 +544,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
 #endif
 	len = ASN1_STRING_length(addr_entry);
 
-	/* OK to cast from unsigned to plain char, since it's all ASCII. */
-	return pq_verify_peer_name_matches_certificate_ip(conn, (const char *) addrdata, len, store_name);
+	return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
 }
 
 static bool
@@ -619,7 +618,13 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 			char	   *alt_name = NULL;
 
 			if (name->type == host_type)
+			{
+				/*
+				 * This SAN is of the same type (IP or DNS) as our host name, so
+				 * don't allow a fallback check of the CN.
+				 */
 				check_cn = false;
+			}
 
 			if (name->type == GEN_DNS)
 			{
@@ -671,10 +676,20 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
 												  NID_commonName, -1);
 			if (cn_index >= 0)
 			{
+				char   *common_name = NULL;
+
 				(*names_examined)++;
 				rc = openssl_verify_peer_name_matches_certificate_name(conn,
 																	   X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
-																	   first_name);
+																	   &common_name);
+
+				if (common_name)
+				{
+					if (!*first_name)
+						*first_name = common_name;
+					else
+						free(common_name);
+				}
 			}
 		}
 	}