commit 8c427e3289a28cb683eff5d05b2e8770c3c07662 Author: Jacob Champion 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); + } } } }