since-v4.diff.txt
text/plain
Filename: since-v4.diff.txt
Type: text/plain
Part: 0
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);
+ }
}
}
}