From 1a070a1ac821c8eda4d3a2856e2721b2fa97aaa1 Mon Sep 17 00:00:00 2001
From: Jacob Champion <pchampion@vmware.com>
Date: Wed, 5 Jan 2022 15:47:03 -0800
Subject: [PATCH v10 3/3] squash! libpq: allow IP address SANs in server certs

Per review, provide a pg_inet_pton() interface for IPv6 and refactor the
internals accordingly. IPv4 is not yet implemented. The call sites that
just want standard addresses without a CIDR mask have been updated to
use the new function.

Internally, the IPv6 parser now takes an allow_cidr boolean. I've
plumbed that all the way down to getbits() in order to minimize the
amount of code touched, at the expense of an unnecessary function call
in the failing case.
---
 src/include/port.h                       |  1 +
 src/interfaces/libpq/fe-secure-common.c  |  7 +--
 src/interfaces/libpq/fe-secure-openssl.c |  2 +-
 src/port/inet_net_pton.c                 | 66 ++++++++++++++++++------
 4 files changed, 52 insertions(+), 24 deletions(-)

diff --git a/src/include/port.h b/src/include/port.h
index 2852e5b58b..fd046f4c24 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -517,6 +517,7 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits,
 
 /* port/inet_net_pton.c */
 extern int	pg_inet_net_pton(int af, const char *src, void *dst, size_t size);
+extern int	pg_inet_pton(int af, const char *src, void *dst);
 
 /* port/pg_strong_random.c */
 extern void pg_strong_random_init(void);
diff --git a/src/interfaces/libpq/fe-secure-common.c b/src/interfaces/libpq/fe-secure-common.c
index 2c0af62afe..9c408df369 100644
--- a/src/interfaces/libpq/fe-secure-common.c
+++ b/src/interfaces/libpq/fe-secure-common.c
@@ -211,12 +211,7 @@ pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
 
 		family = PGSQL_AF_INET6;
 
-		/*
-		 * pg_inet_net_pton() will accept CIDR masks, which we don't want to
-		 * match, so skip the comparison if the host string contains a slash.
-		 */
-		if (!strchr(host, '/')
-			&& pg_inet_net_pton(PGSQL_AF_INET6, host, addr, -1) == 128)
+		if (pg_inet_pton(PGSQL_AF_INET6, host, addr) == 1)
 		{
 			if (memcmp(ipdata, addr, iplen) == 0)
 				match = 1;
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 7656c3a75e..b70bd2eb19 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -555,7 +555,7 @@ is_ip_address(const char *host)
 	unsigned char	dummy6[16];
 
 	return inet_aton(host, &dummy4)
-		|| (pg_inet_net_pton(PGSQL_AF_INET6, host, dummy6, -1) == 128);
+		|| (pg_inet_pton(PGSQL_AF_INET6, host, dummy6) == 1);
 }
 
 /*
-- 
2.25.1

