libpq: Allow IP address SANs in server certificates

The current implementation supports exactly one IP address in a server
certificate's Common Name, which is brittle (the strings must match
exactly).  This patch adds support for IPv4 and IPv6 addresses in a
server's Subject Alternative Names.

Per discussion on-list:

- If the client's expected host is an IP address, we allow fallback to
  the Subject Common Name if an iPAddress SAN is not present, even if
  a dNSName is present.  This matches the behavior of NSS, in
  violation of the relevant RFCs.

- We also, counter-intuitively, match IP addresses embedded in dNSName
  SANs.  From inspection this appears to have been the behavior since
  the SAN matching feature was introduced in acd08d76.

- Unlike NSS, we don't map IPv4 to IPv6 addresses, or vice-versa.

Author: Jacob Champion <pchampion@vmware.com>
Co-authored-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://www.postgresql.org/message-id/flat/9f5f20974cd3a4091a788cf7f00ab663d5fcdffe.camel@vmware.com
This commit is contained in:
Peter Eisentraut 2022-04-01 15:41:44 +02:00
parent fa25bebb82
commit c1932e5428
22 changed files with 636 additions and 18 deletions

2
configure vendored
View File

@ -15982,7 +15982,7 @@ fi
LIBS_including_readline="$LIBS" LIBS_including_readline="$LIBS"
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink syncfs sync_file_range uselocale wcstombs_l writev for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit inet_pton kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink syncfs sync_file_range uselocale wcstombs_l writev
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

View File

@ -1787,6 +1787,7 @@ AC_CHECK_FUNCS(m4_normalize([
getifaddrs getifaddrs
getpeerucred getpeerucred
getrlimit getrlimit
inet_pton
kqueue kqueue
mbstowcs_l mbstowcs_l
memset_s memset_s

View File

@ -8356,16 +8356,31 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
<para> <para>
In <literal>verify-full</literal> mode, the host name is matched against the In <literal>verify-full</literal> mode, the host name is matched against the
certificate's Subject Alternative Name attribute(s), or against the certificate's Subject Alternative Name attribute(s) (SAN), or against the
Common Name attribute if no Subject Alternative Name of type <literal>dNSName</literal> is Common Name attribute if no SAN of type <literal>dNSName</literal> is
present. If the certificate's name attribute starts with an asterisk present. If the certificate's name attribute starts with an asterisk
(<literal>*</literal>), the asterisk will be treated as (<literal>*</literal>), the asterisk will be treated as
a wildcard, which will match all characters <emphasis>except</emphasis> a dot a wildcard, which will match all characters <emphasis>except</emphasis> a dot
(<literal>.</literal>). This means the certificate will not match subdomains. (<literal>.</literal>). This means the certificate will not match subdomains.
If the connection is made using an IP address instead of a host name, the If the connection is made using an IP address instead of a host name, the
IP address will be matched (without doing any DNS lookups). IP address will be matched (without doing any DNS lookups) against SANs of
type <literal>iPAddress</literal> or <literal>dNSName</literal>. If no
<literal>iPAddress</literal> SAN is present and no
matching <literal>dNSName</literal> SAN is present, the host IP address is
matched against the Common Name attribute.
</para> </para>
<note>
<para>
For backward compatibility with earlier versions of PostgreSQL, the host
IP address is verified in a manner different
from <ulink url="https://tools.ietf.org/html/rfc6125">RFC 6125</ulink>.
The host IP address is always matched against <literal>dNSName</literal>
SANs as well as <literal>iPAddress</literal> SANs, and can be matched
against the Common Name attribute if no relevant SANs exist.
</para>
</note>
<para> <para>
To allow server certificate verification, one or more root certificates To allow server certificate verification, one or more root certificates
must be placed in the file <filename>~/.postgresql/root.crt</filename> must be placed in the file <filename>~/.postgresql/root.crt</filename>

View File

@ -283,6 +283,9 @@
/* Define to 1 if you have the `inet_aton' function. */ /* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON #undef HAVE_INET_ATON
/* Define to 1 if you have the `inet_pton' function. */
#undef HAVE_INET_PTON
/* Define to 1 if the system has the type `int64'. */ /* Define to 1 if the system has the type `int64'. */
#undef HAVE_INT64 #undef HAVE_INT64

View File

@ -19,6 +19,8 @@
#include "postgres_fe.h" #include "postgres_fe.h"
#include <arpa/inet.h>
#include "fe-secure-common.h" #include "fe-secure-common.h"
#include "libpq-int.h" #include "libpq-int.h"
@ -144,6 +146,108 @@ pq_verify_peer_name_matches_certificate_name(PGconn *conn,
return result; return result;
} }
/*
* Check if an IP address from a server's certificate matches the peer's
* hostname (which must itself be an IPv4/6 address).
*
* Returns 1 if the address matches, and 0 if it does not. On error, returns
* -1, and sets the libpq error message.
*
* A string representation of the certificate's IP address is returned in
* *store_name. The caller is responsible for freeing it.
*/
int
pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
const unsigned char *ipdata,
size_t iplen,
char **store_name)
{
char *addrstr;
int match = 0;
char *host = conn->connhost[conn->whichhost].host;
int family;
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
char sebuf[PG_STRERROR_R_BUFLEN];
*store_name = NULL;
if (!(host && host[0] != '\0'))
{
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
return -1;
}
/*
* The data from the certificate is in network byte order. Convert our
* host string to network-ordered bytes as well, for comparison. (The host
* string isn't guaranteed to actually be an IP address, so if this
* conversion fails we need to consider it a mismatch rather than an
* error.)
*/
if (iplen == 4)
{
/* IPv4 */
struct in_addr addr;
family = AF_INET;
/*
* 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))
{
if (memcmp(ipdata, &addr.s_addr, iplen) == 0)
match = 1;
}
}
/*
* If they don't have inet_pton(), skip this. Then, an IPv6 address in a
* certificate will cause an error.
*/
#ifdef HAVE_INET_PTON
else if (iplen == 16)
{
/* IPv6 */
struct in6_addr addr;
family = AF_INET6;
if (inet_pton(AF_INET6, host, &addr) == 1)
{
if (memcmp(ipdata, &addr.s6_addr, iplen) == 0)
match = 1;
}
}
#endif
else
{
/*
* Not IPv4 or IPv6. We could ignore the field, but leniency seems
* wrong given the subject matter.
*/
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate contains IP address with invalid length %lu\n"),
(unsigned long) iplen);
return -1;
}
/* Generate a human-readable representation of the certificate's IP. */
addrstr = pg_inet_net_ntop(family, ipdata, 8 * iplen, tmp, sizeof(tmp));
if (!addrstr)
{
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not convert certificate's IP address to string: %s\n"),
strerror_r(errno, sebuf, sizeof(sebuf)));
return -1;
}
*store_name = strdup(addrstr);
return match;
}
/* /*
* Verify that the server certificate matches the hostname we connected to. * Verify that the server certificate matches the hostname we connected to.
* *

View File

@ -21,6 +21,10 @@
extern int pq_verify_peer_name_matches_certificate_name(PGconn *conn, extern int pq_verify_peer_name_matches_certificate_name(PGconn *conn,
const char *namedata, size_t namelen, const char *namedata, size_t namelen,
char **store_name); char **store_name);
extern int pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
const unsigned char *addrdata,
size_t addrlen,
char **store_name);
extern bool pq_verify_peer_name_matches_certificate(PGconn *conn); extern bool pq_verify_peer_name_matches_certificate(PGconn *conn);
#endif /* FE_SECURE_COMMON_H */ #endif /* FE_SECURE_COMMON_H */

View File

@ -72,6 +72,9 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx);
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
ASN1_STRING *name, ASN1_STRING *name,
char **store_name); char **store_name);
static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
ASN1_OCTET_STRING *addr_entry,
char **store_name);
static void destroy_ssl_system(void); static void destroy_ssl_system(void);
static int initialize_SSL(PGconn *conn); static int initialize_SSL(PGconn *conn);
static PostgresPollingStatusType open_client_SSL(PGconn *); static PostgresPollingStatusType open_client_SSL(PGconn *);
@ -509,6 +512,56 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name); return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name);
} }
/*
* OpenSSL-specific wrapper around
* pq_verify_peer_name_matches_certificate_ip(), converting the
* ASN1_OCTET_STRING into a plain C string.
*/
static int
openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
ASN1_OCTET_STRING *addr_entry,
char **store_name)
{
int len;
const unsigned char *addrdata;
/* Should not happen... */
if (addr_entry == NULL)
{
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL certificate's address entry is missing\n"));
return -1;
}
/*
* GEN_IPADD is an OCTET STRING containing an IP address in network byte
* order.
*/
#ifdef HAVE_ASN1_STRING_GET0_DATA
addrdata = ASN1_STRING_get0_data(addr_entry);
#else
addrdata = ASN1_STRING_data(addr_entry);
#endif
len = ASN1_STRING_length(addr_entry);
return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
}
static bool
is_ip_address(const char *host)
{
struct in_addr dummy4;
#ifdef HAVE_INET_PTON
struct in6_addr dummy6;
#endif
return inet_aton(host, &dummy4)
#ifdef HAVE_INET_PTON
|| (inet_pton(AF_INET6, host, &dummy6) == 1)
#endif
;
}
/* /*
* Verify that the server certificate matches the hostname we connected to. * Verify that the server certificate matches the hostname we connected to.
* *
@ -522,6 +575,36 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
STACK_OF(GENERAL_NAME) * peer_san; STACK_OF(GENERAL_NAME) * peer_san;
int i; int i;
int rc = 0; int rc = 0;
char *host = conn->connhost[conn->whichhost].host;
int host_type;
bool check_cn = true;
Assert(host && host[0]); /* should be guaranteed by caller */
/*
* We try to match the NSS behavior here, which is a slight departure from
* the spec but seems to make more intuitive sense:
*
* If connhost contains a DNS name, and the certificate's SANs contain any
* dNSName entries, then we'll ignore the Subject Common Name entirely;
* otherwise, we fall back to checking the CN. (This behavior matches the
* RFC.)
*
* If connhost contains an IP address, and the SANs contain iPAddress
* entries, we again ignore the CN. Otherwise, we allow the CN to match,
* EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
* client MUST NOT seek a match for a reference identifier of CN-ID if the
* presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
* application-specific identifier types supported by the client.")
*
* NOTE: Prior versions of libpq did not consider iPAddress entries at
* all, so this new behavior might break a certificate that has different
* IP addresses in the Subject CN and the SANs.
*/
if (is_ip_address(host))
host_type = GEN_IPADD;
else
host_type = GEN_DNS;
/* /*
* First, get the Subject Alternative Names (SANs) from the certificate, * First, get the Subject Alternative Names (SANs) from the certificate,
@ -537,38 +620,62 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
for (i = 0; i < san_len; i++) for (i = 0; i < san_len; i++)
{ {
const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i); const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
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) if (name->type == GEN_DNS)
{ {
char *alt_name;
(*names_examined)++; (*names_examined)++;
rc = openssl_verify_peer_name_matches_certificate_name(conn, rc = openssl_verify_peer_name_matches_certificate_name(conn,
name->d.dNSName, name->d.dNSName,
&alt_name); &alt_name);
if (alt_name)
{
if (!*first_name)
*first_name = alt_name;
else
free(alt_name);
}
} }
else if (name->type == GEN_IPADD)
{
(*names_examined)++;
rc = openssl_verify_peer_name_matches_certificate_ip(conn,
name->d.iPAddress,
&alt_name);
}
if (alt_name)
{
if (!*first_name)
*first_name = alt_name;
else
free(alt_name);
}
if (rc != 0) if (rc != 0)
{
/*
* Either we hit an error or a match, and either way we should
* not fall back to the CN.
*/
check_cn = false;
break; break;
}
} }
sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free); sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
} }
/* /*
* If there is no subjectAltName extension of type dNSName, check the * If there is no subjectAltName extension of the matching type, check the
* Common Name. * Common Name.
* *
* (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
* dNSName is present, the CN must be ignored.) * dNSName is present, the CN must be ignored. We break this rule if host
* is an IP address; see the comment above.)
*/ */
if (*names_examined == 0) if (check_cn)
{ {
X509_NAME *subject_name; X509_NAME *subject_name;
@ -581,10 +688,20 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
NID_commonName, -1); NID_commonName, -1);
if (cn_index >= 0) if (cn_index >= 0)
{ {
char *common_name = NULL;
(*names_examined)++; (*names_examined)++;
rc = openssl_verify_peer_name_matches_certificate_name(conn, rc = openssl_verify_peer_name_matches_certificate_name(conn,
X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)), 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);
}
} }
} }
} }

View File

@ -0,0 +1,24 @@
# An OpenSSL format CSR config file for creating a server certificate.
#
# This certificate contains a CN and SANs for both IPv4 and IPv6.
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
# Note: According to RFC 2818 and 6125, the CN is ignored, when DNS names are
# present in the SANs. But they are silent on whether the CN is checked when IP
# addresses are present.
CN = common-name.pg-ssltest.test
OU = PostgreSQL test suite
# For Subject Alternative Names
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 192.0.2.1
IP.2 = 2001:DB8::1

View File

@ -0,0 +1,19 @@
# An OpenSSL format CSR config file for creating a server certificate.
#
# This certificate has a two IP-address SANs, and no CN.
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
OU = PostgreSQL test suite
# For Subject Alternative Names
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 192.0.2.1
IP.2 = 2001:DB8::1

View File

@ -0,0 +1,21 @@
# An OpenSSL format CSR config file for creating a server certificate.
#
# This certificate contains both a CN and SANs in IP address format.
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
CN = 192.0.2.1
OU = PostgreSQL test suite
# For Subject Alternative Names
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 192.0.2.2
IP.2 = 2001:DB8::1

View File

@ -0,0 +1,21 @@
# An OpenSSL format CSR config file for creating a server certificate.
#
# This certificate contains both a CN and SANs in IP address format.
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
CN = 192.0.2.1
OU = PostgreSQL test suite
# For Subject Alternative Names
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = dns1.alt-name.pg-ssltest.test
DNS.2 = dns2.alt-name.pg-ssltest.test

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDLzCCAhegAwIBAgIIICERKRE1UQAwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UE
Aww3VGVzdCBDQSBmb3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNl
cnZlciBjZXJ0czAeFw0yMTExMjkxOTM1NTFaFw00OTA0MTYxOTM1NTFaMEYxHjAc
BgNVBAsMFVBvc3RncmVTUUwgdGVzdCBzdWl0ZTEkMCIGA1UEAwwbY29tbW9uLW5h
bWUucGctc3NsdGVzdC50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA6+8IYKAFnZ7V+fDo1cyMpbGBLzCfJOQ/1o2jOGP4+GjpsZgv6S6UT2MheC8M
iiEFrYwdsSIZyYc3jEZrluy/UuR0bCGtqU92BCqa0iBLhvHOgjR588u253eLxQtQ
8iJn11QPrKMk35nMkmY8GfHt4sGFbvBL6+GpipHq7a6cde3Z+v4kCB5dKMYDUDtm
3mJmviuGNAu5wOqItk2Yi5dwJs1054007KNH0Il43urxiOfnkLS0cG5kehboPf86
vxBt3iHByrU/9/DY5IvQCfSXVNa6rb5w5/pGja9aCei6Mv1jQY/V8SMQTga+MOsA
0WB9akxMi2NxwS2+BQ4k/McPlwIDAQABoyUwIzAhBgNVHREEGjAYhwTAAAIBhxAg
AQ24AAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQAQLo2RzC07dG9p+J3A
W6C0p3Y+Os/YE2D9wfp4TIDTZxcRUQZ0S6ahF1N6sp8l9KHBJHPU1cUpRAU1oD+Y
SqmnP/VJRRDTTj9Ytdc/Vuo2jeLpSYhVKrCqtjqIrCwYJFoYRmMoxTtJGlwA0hSd
kwo3XYrALPUQWUErTYPvNfDNIuUwqUXNfS0CXuIOVN3LJ+shegg6Pwbh9B5T9NHx
kH+HswajhdpdnZIgh0FYTlTCPILDrB49aOWwqLa54AUA6WXa35hPsP8SoqL9Eucq
ifPhBYyadsjOb+70N8GbbAsDPN1jCX9L8RuNcEkxSCKCYx91cWXh7K5KMPuGlzB7
j8xB
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA6+8IYKAFnZ7V+fDo1cyMpbGBLzCfJOQ/1o2jOGP4+GjpsZgv
6S6UT2MheC8MiiEFrYwdsSIZyYc3jEZrluy/UuR0bCGtqU92BCqa0iBLhvHOgjR5
88u253eLxQtQ8iJn11QPrKMk35nMkmY8GfHt4sGFbvBL6+GpipHq7a6cde3Z+v4k
CB5dKMYDUDtm3mJmviuGNAu5wOqItk2Yi5dwJs1054007KNH0Il43urxiOfnkLS0
cG5kehboPf86vxBt3iHByrU/9/DY5IvQCfSXVNa6rb5w5/pGja9aCei6Mv1jQY/V
8SMQTga+MOsA0WB9akxMi2NxwS2+BQ4k/McPlwIDAQABAoIBAQCuNFKVNdKvrUYF
RLJGmsAG3+eo9lern7TbML2ht39vu9dBwEMwA6qSa3mdCfBSVUuh9uE9lxY/TU3g
j2aFi81A4VptNPjLGNblAKhMGnhp7UUzspeRQYuNoSFcnpxoDKtrvK/OIq/pQeBh
AIfECHRDh+yEG32Tb44FuPQkB1eTYl8xbMEImrhNUaSjJk7tTsmydHy0DjmqHVKX
HUj0TREfDBDOBiHtY0XV6Pu3bnqDH/TKLTfUf3UdfTuay3Yai9aEcRPWp9GrMO7G
axsKCifTz6177gyr6Fv8HLeMZMh9rMZRn3e0zfaF6vrH1QnZZOts5jpUa0KugSCd
//uC0iNxAoGBAPXVc3b+o3hY5gcwwpaW6JtsarDrmNRxrizqIDG7NgpqwdFXgTi6
6q0t2pjv81ATqij69IcPkNSissyR4OEKnu/OFJWzreg8yLi75WHKi0E/6msHpwRk
d1yP0Zgd05ots/yOjDSp593RagaPVvHBxMECZ/Tm3B+Tq55Azudd/zvLAoGBAPWw
xf0oUEJl6NdUZD6K7eFc6jf8yrpD85dldeko6LeN8x0XlKKWvUDJ2+3oizXoQvCm
8by6KOYEIo4MrtXuy9MmtPWfNvRBr+hsUHchIj7IgFa9bKXyK2FnJqu/8CbEymli
eZu7hoOhelurhnFy1zSqwNO4GC+kw60Y/BO3Z1nlAoGAVOyYJtNwxXJwhKtjjYI0
ePzLHrNE6J8c/Ick+AkkchTPP/JqwZ5Q0+KzUYITG+avMdkAAGhwMATEn8cFWLjC
jzUyB0U7Hq9g5/CBHXdLBA+Ae9j46ZuLYH6OeW5UWz7OnsDfzpGjeA2QAxQhhQLb
ZZHfN8tI39+zucfJskPWmGECgYEAg9guF1Fn6InJrqwR82IYj6SN6CeXHufSM392
C/4xDDd3rDf4QlwECV2J0RzGf9I5Ae2EshNwWScE6Be0RweTh6cw2tJq6h7J6D8f
2x4Dw49TF7klMdRIJUf2f5pLpHJccLswqTqzz7V69PCSABVxmUi8m6EiEYconp5W
v7nfE2UCgYALrEqzncuSIX3q6TVAjnzT7gO4h8h2TUekIWdHQFldFx8R7Kncggnd
48gQqhewchNR83UCcd7pPsCcTqu6UR1QRdq/DV5P6J3xdZ2iS/2gCM6hvWIvKZEv
/ClnkyFCOW7zX6RKIXtRYZTV1kz3TajApi34RTIeIMTieaCarnBJbA==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIIICERKREEUAAwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UE
Aww3VGVzdCBDQSBmb3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNl
cnZlciBjZXJ0czAeFw0yMTExMjkxOTA0NTBaFw00OTA0MTYxOTA0NTBaMCAxHjAc
BgNVBAsMFVBvc3RncmVTUUwgdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAOM8yB6aVWb17ujr3ayU62mxHQoqn4CvG9yXlJvGOGv/ursW
Vs0UYJdc96LsNZN1szdm9ayNzCIw3eja+ULsjxCi6+3LM4pO76IORL/XFamlTPYb
BZ4pHdZVB0nnZAAnWCZPyXdnjOKQ5+8unVXkfibkjj8UELBJ2snehsOa+CTkOBez
zxYMqxAgbywLIYsW448brun7UXpWmqbGK+SsdGaIZ5Sb7Zezc5lt6CrLemTZTHHK
7l4WZFCCEi4t3sgO8o1vDELD/IE5G8lyXvIdgJg6t8ssper7iCw6S8x+okhjiSjT
vDLU2g4AanqZRZB49aPwTo0QUcJA2BCJxL9xLy8CAwEAAaMlMCMwIQYDVR0RBBow
GIcEwAACAYcQIAENuAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAwZJ+
8KpABTlMEgKnHIYb35ItGhtFiTLQta9RkXx7vaeDwpOdPP/IvuvpjpQZkobRgBsk
bNM0KuJpd2mSTphQAt6eKQIdcPrkzvc/Yh9OK3YNLUAbu/ZhBUnBvFnUL4wn2f1U
mfO+m8P/LxybwqKx7r1mbaB+tP3RTxxLcIMvm9ECPQEoBntfEL325Wdoj+WuQH5Y
IvcM6FaCTkQsNIPbaBD5l5MhMLHRULZujbDjXqGSvRMQfns6np/biMjNdQA8NZ5z
STeUFvkQbCxoA0YYLgoSHL5KhZjXrg2g+T+2TUyCTR/91xf9OoOjBZdixR0S0DzJ
B1+5vnUjZaCfnSEA7A==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA4zzIHppVZvXu6OvdrJTrabEdCiqfgK8b3JeUm8Y4a/+6uxZW
zRRgl1z3ouw1k3WzN2b1rI3MIjDd6Nr5QuyPEKLr7cszik7vog5Ev9cVqaVM9hsF
nikd1lUHSedkACdYJk/Jd2eM4pDn7y6dVeR+JuSOPxQQsEnayd6Gw5r4JOQ4F7PP
FgyrECBvLAshixbjjxuu6ftRelaapsYr5Kx0ZohnlJvtl7NzmW3oKst6ZNlMccru
XhZkUIISLi3eyA7yjW8MQsP8gTkbyXJe8h2AmDq3yyyl6vuILDpLzH6iSGOJKNO8
MtTaDgBqeplFkHj1o/BOjRBRwkDYEInEv3EvLwIDAQABAoIBACp3uY6+mSdc3wF4
0zzlt/lQuHSl8plCIJrhWUyjhvfoGyXLzv0Uydh/72frbTfZz1yTSWauOXBKYa6a
/eqb+0DIsf8G8uLuTaqjsAWKVOoXkoKMGkistn7P9UTCkdXVhIvkbWp7V8EgA7iX
pZ/fzBPIsyzmuxe3NcR0ags0cxuxkNuu+YXDv1oTedmT2wS3CZq1d/T1Y/EOVIf8
Iznd2aOverlsnt6iiQ3ZWdG/W5F8FhnrR/rrBdYsdCv6TH/KUYexnDOUYpayjDbu
oAKnifPp6UqiOM4SuBL83OAz19jptp5vpF370BEVRs3eK0q+zo/mETjv9HsXdolZ
lfoXA0ECgYEA/7nb2azbq/2muvXCh1ZxCEbn3mt8KXoJP/xkx/v9eEc/cc5Q9e0V
2oGfjC2hSE+bjOWMwiUMD6uU+iRjhz5A3IvUxnoSdoL7H9p0hTqLMyP7dTDkoVF5
aEuLMaiI5YEnfAFu9L5h8ZKieoQTBoscT06wnGjh9pBV9bthfTKA7ksCgYEA43sb
55m9WL4kWCPwOAp3vdEAFyxzmZHlO26sEQOU/m5aN01pumYybBruziEXMI96yfTj
VmXKReeYb6XUiCcs3fLSipD/+8/8CsjO4uMORtxWumXe8AbKZfysGFzL7wJlByGT
38AGQwIG/XD8cKnaiEMX4E/3Owbcoxwixo3WZC0CgYEAovaqJ9mEU+Jc8h/TS7PG
bGPjN1Z/1V6zrlcFUnw/Vvrwb3HvHglsN8cLCaW6df5lPjC6tq4tNX8+fPnbg0Ak
zWc+vQzl3ygxKGdqgcyBEKIJiPETgcoN+GzL02V3d+oKY3f2YXlBqVSsvi6UgUL9
U3zuB36/IQVyAhrbUZFxoGkCgYEAnaFAO+Nvrp/LhXwZyGuQf+rkmipGTIMpil5t
QzjtNMV5JFszSWPpyrl7A0Ew1YiG+I0GP2c3m+sY2TzbIiGrWH0b4cMKbw63Qy3V
FqlpyjaCrpVKv56k/7jv883RzuQk56Uf1+szK5mrCFITy2oXsVZ0pA4lbjSaDTjA
7D968V0CgYEA+qKqXKL98+c5CMPnpf+0B1x2zgyUym1ouPfon2x5fhK84T53zDMA
zfdUJ/SOZw6/c9vRF7RL8h+ZfFdIyoAXv4Tt6mIiZe7P+AUVg6XgJ0ce2MUSeWjI
W8D4WdSi0jyqr99TuVBWhbTZJviMB3pHqKaHQ07hnd/lPtvzsiH12qk=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDHTCCAgWgAwIBAgIIICIBBBQ2MQAwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UE
Aww3VGVzdCBDQSBmb3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNl
cnZlciBjZXJ0czAeFw0yMjAxMDQyMjM2MzFaFw00OTA1MjIyMjM2MzFaMDQxHjAc
BgNVBAsMFVBvc3RncmVTUUwgdGVzdCBzdWl0ZTESMBAGA1UEAwwJMTkyLjAuMi4x
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwmqTdQJfs2Ti9tPitYp2
27I0HvL/kNSgA6egFr0foRo0BorwJNIzdbV0+EnsfiBNTWL5It26gqO7UP3ms8t2
vHD5gkXfT+f6ts0lVJEcIOkUD/8ws4Ic9Y4uPqb4gN+pUKqcxtmLW1TYk84MBK59
Xz4yPPS6N+G/DMMeFHTNkM9EQwn/+DC3fDsWdGYM2GRWDTJGg1A5tSUcF+seu7i1
Vg7XajBfsvgAUAsrAxV+X/sLZh94HY+paD6wfaI99mY2OXVc/XW/z1r9WQznor65
ZkonNCaPfavqPG5vqnab9AyQcqPqmX8hf/xrniASBAkqNCctbASrFCIYvCJfGfmX
EQIDAQABoyUwIzAhBgNVHREEGjAYhwTAAAIChxAgAQ24AAAAAAAAAAAAAAABMA0G
CSqGSIb3DQEBCwUAA4IBAQBf7kmYfRYfnWk1OUfY3N1kaNg9piBBlFr9g+OQn9KU
zirkN7s0ZQbCGxV1uJQBKS58NyE414Vorau77379emgYDcCBpDIYpkLiNujVrIOr
ggRFKsFRgxu4/mw0BSgCcV8RPe9SWHZ90Mos7TMCnW/PdxOCD1wD0YMkcs0rwB3l
0Kzc7jDnfOEvmgw/Ysm7v67ps+05Uq5VskQ6WrpSAw6kPD/QMuuBAX8ATPczIaox
zAMyncq1IiSIwG93f3EoQQThdQ70C6G9vLcu9TtL6JAsEMFEzR99gt1Wsqvmgl9W
kStzj1yjIWeo5gIsa4Jgcke1lZviWyrTxHDfyunYE5i5
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwmqTdQJfs2Ti9tPitYp227I0HvL/kNSgA6egFr0foRo0Borw
JNIzdbV0+EnsfiBNTWL5It26gqO7UP3ms8t2vHD5gkXfT+f6ts0lVJEcIOkUD/8w
s4Ic9Y4uPqb4gN+pUKqcxtmLW1TYk84MBK59Xz4yPPS6N+G/DMMeFHTNkM9EQwn/
+DC3fDsWdGYM2GRWDTJGg1A5tSUcF+seu7i1Vg7XajBfsvgAUAsrAxV+X/sLZh94
HY+paD6wfaI99mY2OXVc/XW/z1r9WQznor65ZkonNCaPfavqPG5vqnab9AyQcqPq
mX8hf/xrniASBAkqNCctbASrFCIYvCJfGfmXEQIDAQABAoIBAB6GgVST5NbT9lbu
+d+rN/JSzqA1Yy8oU19/iEFJvJec96I3WnFNl8rZjN4XLUy4YarO6XMyAUDV2Gll
FD4Sqjf4PRTZR7DSKaleGIhoqFP6hK3mUY091rIves9XhBkoBPunbipCqgDTF5ZN
edGaXBECQP0VJ8/yX/7u++AWXthnjDis9X0taZfFg/PYbV7SCJ1Hg1O/wEsgXlnC
7mbL6wkCW0f6700B0x1kKbZqJY95xRqp6Ipq2lIQbJDdGywoj0WzKqNltf9cer+r
cXl8WjeiMvvvpl4uGhckAbzUifUzxN6A3f1fu/XKtOmabMi9t7J4MRfgOgedgtQB
0jaZGSkCgYEA+lBLnNY6M48HX2mdtr86+n41gh69v8Z7oNikJFDZkodrvI8uqE0i
0XwnYPFddt8NbmuUhhuzI2M8RKhGLgdlbKpkSSVafnMfcxRmX2EAtWQgdvX1Iult
752LWdBgSuw2vlzvy3T/GYnjMrXSCGput4amqojMEbvUGvIdSUMdHGMCgYEAxtU1
WixKPL6aEnYy1f4bybzcNgGtl8PBRz9xw+P46g+ijOPoaG9O73Tr7An11AO003Ot
DHhMW+b8yHLyxoKwS2sU2cN/lKB8xNQYZc1D61RNJlzgnHMXnA0lcH0I3M35fqKr
/71pD1ZP40SSJS+od/KEjW80XzuOdyiXg8q81vsCgYEAnUPLbbsuj+whzrFVlFZr
IKwgxCK6Rn3WeIUEA4kEWUpZxvsSbk0gPgtJ1l9uwFt9Xc2bX/KRRv93Aw/SH+Mn
tvEK1uXwCBgePzgm5W/VeSFyQCthm1CbcHtD7Oa9SPVFo65SPjrAd3QpWVfgoMb1
zrp7hhMyW0XuCgvpmHjhFk8CgYEAxq/thXM2p+bLLWGhwQcRG5G299zLbBl4PUsf
0uEvLi17gJCKADoiRdSvoAn/9eHSQ26XYRuhKkDzHxcGlOmpY2PYzRa3mXyZ0VIk
Iy5wDWwLQCeVZ6D22cClRfgb8BF/nFTPzVmn72SPpgoyhChQj7PvUynpyrRH07jj
VxYziBsCgYAFr37Xbl0VnXVK+XU+vMwUZjcF4jpoCr7SFZqgRbW2GbYSUoMuPXns
RnJh+Fvi1NUei+E5s1H4P1pVq4p0jFxP4GvH/qvNjnIn/Er3bbqvpox6dWUJXprq
qTQSDIeoDC/V8cyRoIfqPvTVqY8Rgew6GEkv0bAImdxhoSng7vIseg==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDQzCCAiugAwIBAgIIICIBBBQ2MQEwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UE
Aww3VGVzdCBDQSBmb3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNl
cnZlciBjZXJ0czAeFw0yMjAxMDQyMjM2MzFaFw00OTA1MjIyMjM2MzFaMDQxHjAc
BgNVBAsMFVBvc3RncmVTUUwgdGVzdCBzdWl0ZTESMBAGA1UEAwwJMTkyLjAuMi4x
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8xddbo/x2TOSIa/br8BN
o/URdTr9+l2R5YojiZKDuLxiQVkgC30PJ2/CNFKIh2nHhRrzknI6sETVtrxZ+9V2
qRc1yShVu462u0DHPRMIZnZIOZg3hlNB0cRWbOglUKlttIARNEQUcTUyPOtyo4/v
+u0Ej5NTNcHFbFT01vdD9MjQiCO3jKdAwPIb14jTg4C71EpZ+LuelDo4DzF2/XgG
WqUTrgD/XnBU/60PU9Iy3G0nVpx21q6ppn9G7a9R+i8FjBcwW1T+cfsBDWhAv+bi
RmSAkENf8L8TwOlDQUwROkfz3Hz36vuJjdkreQJsiqL0HnrnH5T5G9UzJO86FvZQ
5wIDAQABo0swSTBHBgNVHREEQDA+gh1kbnMxLmFsdC1uYW1lLnBnLXNzbHRlc3Qu
dGVzdIIdZG5zMi5hbHQtbmFtZS5wZy1zc2x0ZXN0LnRlc3QwDQYJKoZIhvcNAQEL
BQADggEBAF+mfaw6iBPzpCgqq830pHRa3Yzm1aezt8SkeRohUYHNv/yCnDSRaqtj
xbENih3lJMSTBL3g0wtTOHfH8ViC/h+lvYELHzXKic7gkjV7H5XETKGr0ZsjBBT2
4cZQKbD9e0x0HrENXMYgGpBf747qL6uTOVJdG0s15hwpLq47bY5WUjXathejbpxW
prmF8F+xaC52N9P/1VnqguQB909F4x1pyOK7D7tjFu+Y8Je7PHKbb6WY5K6xAv6t
R17CY0749/FotlphquElUR2bs5Zzv5YrjUHPTcbwKvcH5cdNi93/u6NJt2xNAoYf
aZERhX5TA9DYk4gC8OY0yGaYCIj3Dd4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA8xddbo/x2TOSIa/br8BNo/URdTr9+l2R5YojiZKDuLxiQVkg
C30PJ2/CNFKIh2nHhRrzknI6sETVtrxZ+9V2qRc1yShVu462u0DHPRMIZnZIOZg3
hlNB0cRWbOglUKlttIARNEQUcTUyPOtyo4/v+u0Ej5NTNcHFbFT01vdD9MjQiCO3
jKdAwPIb14jTg4C71EpZ+LuelDo4DzF2/XgGWqUTrgD/XnBU/60PU9Iy3G0nVpx2
1q6ppn9G7a9R+i8FjBcwW1T+cfsBDWhAv+biRmSAkENf8L8TwOlDQUwROkfz3Hz3
6vuJjdkreQJsiqL0HnrnH5T5G9UzJO86FvZQ5wIDAQABAoIBAGv0BFoFMrHyZQLw
xe7Wx6P4QTh+aiu1QgVdw0pk9nojrr62hbSUZRZuWyBBRsBcCW7i+Sgf8lA1QXNV
UeC0e228EPa0It6YEi42JkTJHwHhpVFud7n/X0t4lajnryqTE1UFSp6bXTipFxZW
uSJJ2ZjliRD5rApDcxkY4WJVjKg3aEt7P/DiM8iKGfyE6stq72VjEbJjdViMEcOP
BNf0TiREZz5Mp7jAVWhpen0ebbLOBVWV4/ONNcL+yqR4mCEDUSFGewrTVX4zHL0A
hYk198C5F8sFvEDnFkPco9sXMVanmLoI8sbhP4IIz9g4+GU6kFuj7fUKp11Azqv+
3WQDKYECgYEA/XG4mmG/g8FG44y42mfZpUXWi1pwU4CQIrhkoU5j7EPQrvRboOOE
Rv95jSwyZu4vCqjyI5FN1jCGTdhmt++R1e//zH6Hqa9Smo+jw7DtAFrCYd1JnCf1
ToOwsYPHv4P7A8q8kc5vCNIv+AQSlP/wqdVNo3grdf7cGXkMtEY4F9UCgYEA9Yrq
zWdnNGPATuSBqL6TSjQ37oR+dBD6WnGsiDenQkOzyDPFZ3CT1DjJghjEtxc8EfNf
Oo8dMMR2q+5FZQo7WuqONEgyzKePiNR8RK2gOYpgdjN9bih1sAhHR10D26cpwlDJ
bx7D5ZzENLbdZmfEiWwKswnaIhN4yMalgE0mP8sCgYAhzJy12ftUct4lUosEdX0N
EXc/NlxshmSyfKzO5kllJNYbvvLJTg5B+agYL6C5IWKcpVNFcwdSXT5L+2QXe5eT
VGJkvysQchUuD6HjYyD4PyJVMtGyRZHtWpqh0dU9sTg0lUD4oPMl1gIXrVNdE5Tg
0VV9S3VgUxC/ROlw0TyB0QKBgGsVE0NS9hJF8mc1hko2GnwA++d8Rr2NbfElo+2f
/8SJTA1ibpOm6AFkZpTjAl8qtdrKPVyHb16GP47Jkd/3r1z979hjKCxSYul0aWF2
KusNKvZBjFEPOgv0AEniCb2wUCjbHI3mZ95qGLM4kKOJW4/m21+rS0MTJNjCsQic
HLMzAoGAeCsY09d3m8xGeU+DuTPC6GH7Sgy/NBYqS5VaVNjb2jnuZlW2SSW2oiID
4tXTi4ruKmHC898BfyFxhSMqub+tg3pVqIYADC71rnJLrVyc1SzoWzL7yMT3qFj7
C7ZYZYmfG9agcZb5NkqKPTfCxkBhWbdgTTgBKVO/xQst8EUgko8=
-----END RSA PRIVATE KEY-----

View File

@ -22,8 +22,12 @@
# key/certificate pair will be generated for you, signed by the appropriate CA. # key/certificate pair will be generated for you, signed by the appropriate CA.
# #
SERVERS := server-cn-and-alt-names \ SERVERS := server-cn-and-alt-names \
server-cn-and-ip-alt-names \
server-cn-only \ server-cn-only \
server-ip-alt-names \
server-ip-cn-only \ server-ip-cn-only \
server-ip-cn-and-alt-names \
server-ip-cn-and-dns-alt-names \
server-ip-in-dnsname \ server-ip-in-dnsname \
server-single-alt-name \ server-single-alt-name \
server-multiple-alt-names \ server-multiple-alt-names \

View File

@ -305,6 +305,64 @@ $node->connect_fails(
qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/ qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/
); );
SKIP:
{
skip 'IPv6 addresses in certificates not support on this platform', 1
unless check_pg_config('#define HAVE_INET_PTON 1');
# Test certificate with IP addresses in the SANs.
switch_server_cert($node, certfile => 'server-ip-alt-names');
$node->connect_ok("$common_connstr host=192.0.2.1",
"host matching an IPv4 address (Subject Alternative Name 1)");
$node->connect_ok(
"$common_connstr host=192.000.002.001",
"host matching an IPv4 address in alternate form (Subject Alternative Name 1)"
);
$node->connect_fails(
"$common_connstr host=192.0.2.2",
"host not matching an IPv4 address (Subject Alternative Name 1)",
expected_stderr =>
qr/\Qserver certificate for "192.0.2.1" (and 1 other name) does not match host name "192.0.2.2"\E/
);
$node->connect_fails(
"$common_connstr host=192.0.2.1/32",
"IPv4 host with CIDR mask does not match",
expected_stderr =>
qr/\Qserver certificate for "192.0.2.1" (and 1 other name) does not match host name "192.0.2.1\/32"\E/
);
$node->connect_ok("$common_connstr host=2001:DB8::1",
"host matching an IPv6 address (Subject Alternative Name 2)");
$node->connect_ok(
"$common_connstr host=2001:db8:0:0:0:0:0:1",
"host matching an IPv6 address in alternate form (Subject Alternative Name 2)"
);
$node->connect_ok(
"$common_connstr host=2001:db8::0.0.0.1",
"host matching an IPv6 address in mixed form (Subject Alternative Name 2)"
);
$node->connect_fails(
"$common_connstr host=::1",
"host not matching an IPv6 address (Subject Alternative Name 2)",
expected_stderr =>
qr/\Qserver certificate for "192.0.2.1" (and 1 other name) does not match host name "::1"\E/
);
$node->connect_fails(
"$common_connstr host=2001:DB8::1/128",
"IPv6 host with CIDR mask does not match",
expected_stderr =>
qr/\Qserver certificate for "192.0.2.1" (and 1 other name) does not match host name "2001:DB8::1\/128"\E/
);
}
# Test server certificate with a CN and DNS SANs. Per RFCs 2818 and 6125, the CN # Test server certificate with a CN and DNS SANs. Per RFCs 2818 and 6125, the CN
# should be ignored when the certificate has both. # should be ignored when the certificate has both.
switch_server_cert($node, certfile => 'server-cn-and-alt-names'); switch_server_cert($node, certfile => 'server-cn-and-alt-names');
@ -323,6 +381,46 @@ $node->connect_fails(
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/
); );
SKIP:
{
skip 'IPv6 addresses in certificates not support on this platform', 1
unless check_pg_config('#define HAVE_INET_PTON 1');
# But we will fall back to check the CN if the SANs contain only IP addresses.
switch_server_cert($node, certfile => 'server-cn-and-ip-alt-names');
$node->connect_ok(
"$common_connstr host=common-name.pg-ssltest.test",
"certificate with both a CN and IP SANs matches CN");
$node->connect_ok("$common_connstr host=192.0.2.1",
"certificate with both a CN and IP SANs matches SAN 1");
$node->connect_ok("$common_connstr host=2001:db8::1",
"certificate with both a CN and IP SANs matches SAN 2");
# And now the same tests, but with IP addresses and DNS names swapped.
switch_server_cert($node, certfile => 'server-ip-cn-and-alt-names');
$node->connect_ok("$common_connstr host=192.0.2.2",
"certificate with both an IP CN and IP SANs 1");
$node->connect_ok("$common_connstr host=2001:db8::1",
"certificate with both an IP CN and IP SANs 2");
$node->connect_fails(
"$common_connstr host=192.0.2.1",
"certificate with both an IP CN and IP SANs ignores CN",
expected_stderr =>
qr/\Qserver certificate for "192.0.2.2" (and 1 other name) does not match host name "192.0.2.1"\E/
);
}
switch_server_cert($node, certfile => 'server-ip-cn-and-dns-alt-names');
$node->connect_ok("$common_connstr host=192.0.2.1",
"certificate with both an IP CN and DNS SANs matches CN");
$node->connect_ok("$common_connstr host=dns1.alt-name.pg-ssltest.test",
"certificate with both an IP CN and DNS SANs matches SAN 1");
$node->connect_ok("$common_connstr host=dns2.alt-name.pg-ssltest.test",
"certificate with both an IP CN and DNS SANs matches SAN 2");
# Finally, test a server certificate that has no CN or SANs. Of course, that's # Finally, test a server certificate that has no CN or SANs. Of course, that's
# not a very sensible certificate, but libpq should handle it gracefully. # not a very sensible certificate, but libpq should handle it gracefully.
switch_server_cert($node, certfile => 'server-no-names'); switch_server_cert($node, certfile => 'server-no-names');

View File

@ -288,6 +288,7 @@ sub GenerateFiles
HAVE_HISTORY_TRUNCATE_FILE => undef, HAVE_HISTORY_TRUNCATE_FILE => undef,
HAVE_IFADDRS_H => undef, HAVE_IFADDRS_H => undef,
HAVE_INET_ATON => undef, HAVE_INET_ATON => undef,
HAVE_INET_PTON => 1,
HAVE_INT_TIMEZONE => 1, HAVE_INT_TIMEZONE => 1,
HAVE_INT64 => undef, HAVE_INT64 => undef,
HAVE_INT8 => undef, HAVE_INT8 => undef,