From 8dcc6a1f48945997666ac9f10896819edd01a03b Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Fri, 13 Mar 2026 17:02:07 +0100
Subject: x509/hostname-verify: make URI/SRV SAN preclude CN fallback

URI/SRV SAN did not suppress CN fallback as required by RFC 6125 6.4.4:
 > 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.

With this change, certificates containing URI or SRV SAN
no longer pass DNS hostname checks via CN fallback
to avoid potential misuse of such certificates
beyond their original purpose.

Reported-by: Oleh Konko <security@1seal.org>
Fixes: #1802
Fixes: CVE-2026-42012
Fixes: GNUTLS-SA-2026-04-29-7
CVSS: 6.5 Medium CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 lib/x509/hostname-verify.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

From 6133fb459b74a9dcfa2d0ff010a4e03c56822d39 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Fri, 13 Mar 2026 17:00:03 +0100
Subject: [PATCH] x509/hostname-verify: refactor and simplify CN fallback logic

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 lib/x509/hostname-verify.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

From 5cc003b9688378f6c7934b1df0aa147e80006be4 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Fri, 13 Mar 2026 17:41:33 +0100
Subject: [PATCH] x509: add bare-bones awareness of SRV virtual SAN

There's no support for constraints, no certtool support, no nothing.
Just added what's easy to add because I needed a virtual SAN for them.

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 lib/includes/gnutls/gnutls.h.in |  4 +++-
 lib/x509/common.h               |  1 +
 lib/x509/name_constraints.c     |  3 ++-
 lib/x509/output.c               |  6 ++++++
 lib/x509/virt-san.c             | 23 +++++++++++++++++++++++
 lib/x509/x509.c                 |  3 ++-
 6 files changed, 37 insertions(+), 3 deletions(-)

From b39429d77d4ba022f8597c99b84bbd0a073c815b Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Fri, 13 Mar 2026 17:54:56 +0100
Subject: [PATCH] tests/hostname-check: extend to exercise no-CN-fallback

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 tests/hostname-check.c | 140 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

Index: gnutls-3.8.10/lib/x509/virt-san.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/virt-san.c
+++ gnutls-3.8.10/lib/x509/virt-san.c
@@ -45,6 +45,9 @@ static int san_othername_to_virtual(cons
 			 memcmp(oid, MSUSER_PRINCIPAL_NAME_OID,
 				sizeof(MSUSER_PRINCIPAL_NAME_OID) - 1) == 0)
 			return GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL;
+		else if ((unsigned)size == (sizeof(SRV_OID) - 1) &&
+			 memcmp(oid, SRV_OID, sizeof(SRV_OID) - 1) == 0)
+			return GNUTLS_SAN_OTHERNAME_SRV;
 	}
 
 	return GNUTLS_SAN_OTHERNAME;
@@ -59,6 +62,8 @@ static const char *virtual_to_othername_
 		return KRB5_PRINCIPAL_OID;
 	case GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL:
 		return MSUSER_PRINCIPAL_NAME_OID;
+	case GNUTLS_SAN_OTHERNAME_SRV:
+		return SRV_OID;
 	default:
 		return NULL;
 	}
@@ -108,11 +113,8 @@ int _gnutls_alt_name_assign_virt_type(st
 			if (ret < 0)
 				return gnutls_assert_val(ret);
 
-			name->type = GNUTLS_SAN_OTHERNAME;
 			name->san.data = encoded.data;
 			name->san.size = encoded.size;
-			name->othername_oid.data = (void *)gnutls_strdup(oid);
-			name->othername_oid.size = strlen(oid);
 			break;
 
 		case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
@@ -120,15 +122,29 @@ int _gnutls_alt_name_assign_virt_type(st
 							    &name->san);
 			if (ret < 0)
 				return gnutls_assert_val(ret);
+			break;
 
-			name->othername_oid.data = (void *)gnutls_strdup(oid);
-			name->othername_oid.size = strlen(oid);
-			name->type = GNUTLS_SAN_OTHERNAME;
+		case GNUTLS_SAN_OTHERNAME_SRV:
+			ret = _gnutls_x509_encode_string(ASN1_ETYPE_IA5_STRING,
+							 san->data, san->size,
+							 &encoded);
+			if (ret < 0)
+				return gnutls_assert_val(ret);
+			name->san.data = encoded.data;
+			name->san.size = encoded.size;
 			break;
 
 		default:
 			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 		}
+		ret = _gnutls_set_strdatum(&name->othername_oid, oid,
+					   strlen(oid));
+		if (ret < 0) {
+			gnutls_assert();
+			_gnutls_free_datum(&name->san);
+			return ret;
+		}
+		name->type = GNUTLS_SAN_OTHERNAME;
 
 		gnutls_free(san->data);
 	}
@@ -187,6 +203,15 @@ int gnutls_x509_othername_to_virtual(con
 						 othername->data,
 						 othername->size, virt, 0);
 		if (ret < 0) {
+			gnutls_assert();
+			return ret;
+		}
+		return 0;
+	case GNUTLS_SAN_OTHERNAME_SRV:
+		ret = _gnutls_x509_decode_string(ASN1_ETYPE_IA5_STRING,
+						 othername->data,
+						 othername->size, virt, 0);
+		if (ret < 0) {
 			gnutls_assert();
 			return ret;
 		}
Index: gnutls-3.8.10/lib/includes/gnutls/gnutls.h.in
===================================================================
--- gnutls-3.8.10.orig/lib/includes/gnutls/gnutls.h.in
+++ gnutls-3.8.10/lib/includes/gnutls/gnutls.h.in
@@ -2688,6 +2688,7 @@ void gnutls_psk_set_server_params_functi
  * @GNUTLS_SAN_OTHERNAME_XMPP: Virtual SAN, used by certain functions for convenience.
  * @GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL: Virtual SAN, used by certain functions for convenience.
  * @GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL: Virtual SAN, used by certain functions for convenience.
+ * @GNUTLS_SAN_OTHERNAME_SRV: Virtual SAN, used by certain functions for convenience.
  *
  * Enumeration of different subject alternative names types.
  */
@@ -2705,7 +2706,8 @@ typedef enum gnutls_x509_subject_alt_nam
 	   Used by gnutls_x509_crt_get_subject_alt_othername_oid.  */
 	GNUTLS_SAN_OTHERNAME_XMPP = 1000,
 	GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL,
-	GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL
+	GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL,
+	GNUTLS_SAN_OTHERNAME_SRV
 } gnutls_x509_subject_alt_name_t;
 
 struct gnutls_openpgp_crt_int;
Index: gnutls-3.8.10/lib/x509/common.h
===================================================================
--- gnutls-3.8.10.orig/lib/x509/common.h
+++ gnutls-3.8.10/lib/x509/common.h
@@ -107,6 +107,7 @@
 #define XMPP_OID "1.3.6.1.5.5.7.8.5"
 #define KRB5_PRINCIPAL_OID "1.3.6.1.5.2.2"
 #define MSUSER_PRINCIPAL_NAME_OID "1.3.6.1.4.1.311.20.2.3"
+#define SRV_OID "1.3.6.1.5.5.7.8.7"
 #define PKIX1_RSA_PSS_MGF1_OID "1.2.840.113549.1.1.8"
 #define PKIX1_RSA_OAEP_P_SPECIFIED_OID "1.9"
 
Index: gnutls-3.8.10/lib/x509/name_constraints.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/name_constraints.c
+++ gnutls-3.8.10/lib/x509/name_constraints.c
@@ -516,7 +516,8 @@ static int validate_name_constraints_nod
 	if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME &&
 	    type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI &&
 	    type != GNUTLS_SAN_IPADDRESS &&
-	    type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL) {
+	    type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL &&
+	    type != GNUTLS_SAN_OTHERNAME_SRV) {
 		return gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
 	}
 
Index: gnutls-3.8.10/lib/x509/output.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/output.c
+++ gnutls-3.8.10/lib/x509/output.c
@@ -121,6 +121,7 @@ static void print_name(gnutls_buffer_st
 	if ((type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_OTHERNAME_XMPP ||
 	     type == GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL ||
 	     type == GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL ||
+	     type == GNUTLS_SAN_OTHERNAME_SRV ||
 	     type == GNUTLS_SAN_RFC822NAME || type == GNUTLS_SAN_URI) &&
 	    sname != NULL && strlen(sname) != name->size) {
 		adds(str, _("warning: SAN contains an embedded NUL, "
@@ -180,6 +181,11 @@ static void print_name(gnutls_buffer_st
 		     name->size, NON_NULL(name->data));
 		break;
 
+	case GNUTLS_SAN_OTHERNAME_SRV:
+		addf(str, _("%sSRVName: %.*s\n"), prefix, name->size,
+		     NON_NULL(name->data));
+		break;
+
 	default:
 		addf(str, _("%sUnknown name: "), prefix);
 		_gnutls_buffer_hexprint(str, name->data, name->size);
Index: gnutls-3.8.10/lib/x509/x509.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/x509.c
+++ gnutls-3.8.10/lib/x509/x509.c
@@ -1562,7 +1562,8 @@ inline static int is_type_printable(int
 {
 	if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME ||
 	    type == GNUTLS_SAN_URI || type == GNUTLS_SAN_OTHERNAME_XMPP ||
-	    type == GNUTLS_SAN_OTHERNAME || type == GNUTLS_SAN_REGISTERED_ID)
+	    type == GNUTLS_SAN_OTHERNAME_SRV || type == GNUTLS_SAN_OTHERNAME ||
+	    type == GNUTLS_SAN_REGISTERED_ID)
 		return 1;
 	else
 		return 0;
Index: gnutls-3.8.10/lib/x509/hostname-verify.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/hostname-verify.c
+++ gnutls-3.8.10/lib/x509/hostname-verify.c
@@ -108,8 +108,9 @@ unsigned gnutls_x509_crt_check_ip(gnutls
  * that we do not fallback to CN-ID if we encounter a supported name
  * type.
  */
-#define IS_SAN_SUPPORTED(san) \
-	(san == GNUTLS_SAN_DNSNAME || san == GNUTLS_SAN_IPADDRESS)
+#define PRECLUDES_CN_FALLBACK(san)                                   \
+	(san == GNUTLS_SAN_DNSNAME || san == GNUTLS_SAN_IPADDRESS || \
+	 san == GNUTLS_SAN_URI || san == GNUTLS_SAN_OTHERNAME_SRV)
 
 /**
  * gnutls_x509_crt_check_hostname2:
@@ -151,13 +152,12 @@ unsigned gnutls_x509_crt_check_hostname2
 {
 	char dnsname[MAX_CN];
 	size_t dnsnamesize;
-	int found_dnsname = 0;
 	int ret = 0;
 	int i = 0;
 	struct in_addr ipv4;
 	char *p = NULL;
 	char *a_hostname;
-	unsigned have_other_addresses = 0;
+	bool cn_fallback_allowed = true;
 	gnutls_datum_t out;
 
 	/* check whether @hostname is an ip address */
@@ -213,9 +213,10 @@ hostname_fallback:
 		ret = gnutls_x509_crt_get_subject_alt_name(cert, i, dnsname,
 							   &dnsnamesize, NULL);
 
-		if (ret == GNUTLS_SAN_DNSNAME) {
-			found_dnsname = 1;
+		if (PRECLUDES_CN_FALLBACK(ret))
+			cn_fallback_allowed = false;
 
+		if (ret == GNUTLS_SAN_DNSNAME) {
 			if (memchr(dnsname, '\0', dnsnamesize)) {
 				_gnutls_debug_log(
 					"certificate has %s with embedded null in name\n",
@@ -236,13 +237,10 @@ hostname_fallback:
 				ret = 1;
 				goto cleanup;
 			}
-		} else {
-			if (IS_SAN_SUPPORTED(ret))
-				have_other_addresses = 1;
 		}
 	}
 
-	if (!have_other_addresses && !found_dnsname &&
+	if (cn_fallback_allowed &&
 	    _gnutls_check_key_purpose(cert, GNUTLS_KP_TLS_WWW_SERVER, 0) != 0) {
 		/* did not get the necessary extension, use CN instead, if the
 		 * certificate would have been acceptable for a TLS WWW server purpose.
Index: gnutls-3.8.10/tests/hostname-check.c
===================================================================
--- gnutls-3.8.10.orig/tests/hostname-check.c
+++ gnutls-3.8.10/tests/hostname-check.c
@@ -804,6 +804,99 @@ char txt_ip_in_cn[] =
 	"f0+Un2eHAxFcRZPWdPy1/mn83NUMnjquuA/HHcju+pcoZrEwAI3PPQHgsGQ=\n"
 	"-----END CERTIFICATE-----\n";
 
+char dns_uri_and_cn[] =
+	"organization = GnuTLS test\n"
+	"cn = example.org\n"
+	"expiration_days = 365\n"
+	"tls_www_server\n"
+	"dns_name = alt.example.org\n"
+	"uri = http://example.org/\n"
+	"-----BEGIN CERTIFICATE-----\n"
+	"MIIEWzCCAsOgAwIBAgIUZ2rP89A5RbTdVMCQ86E9qWLSZz4wDQYJKoZIhvcNAQEL\n"
+	"BQAwLDEUMBIGA1UEChMLR251VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3Jn\n"
+	"MB4XDTI2MDMxMzE1NDIwNVoXDTI3MDMxMzE1NDIwNVowLDEUMBIGA1UEChMLR251\n"
+	"VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3JnMIIBojANBgkqhkiG9w0BAQEF\n"
+	"AAOCAY8AMIIBigKCAYEArEgcC7WDqNJCpO0J3UfCraRWzmwk7soTg7pMmCv1FHWP\n"
+	"ywxfXxbl0jvRK/Owyv7q5QRdfcxSYhxydrloCOdWXhGQejgzcpgLu/Y3Ij0CjIzr\n"
+	"C38vMSS7yUjAuzB4IYtZsgyuB+bCfGH2Y227ntuniIjEnuekA18gfFemRUQ8PDao\n"
+	"EzNAPn8Q3cFlHh5Kr3gkDUduQlRhZdK0ryU/XaAUxz9G9TminIKCl4h1bKNT2pXN\n"
+	"08Cg3eOEi3Bl8lCCA7ufODl5frfrDcjNkxqRKN99zMa9A9hcRzYNF9/asX+BXFyh\n"
+	"7qbypKXAHBi6xi055+CRIBTxFC960qAluv2cOlo1tzZ0Nta75GhWCqLaVZgI0D0n\n"
+	"6SPZPEknVjGPQx1vSnq3ZNdNDdG83yw4QjFtujXdKrflcJafCg3D6LCvEyDPBdYC\n"
+	"reTJ9xWNCdsxdzlTdDk11CbxdIz4jA7qA/forbY9Dv7l0iC9d2zWmn4DOv23QIki\n"
+	"Uw46/ymnpeFaUTyNyyNHAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAwLwYDVR0RBCgw\n"
+	"JoIPYWx0LmV4YW1wbGUub3JnhhNodHRwOi8vZXhhbXBsZS5vcmcvMBMGA1UdJQQM\n"
+	"MAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSXBONihYHHlbM9mrezDF7o607tFTANBgkq\n"
+	"hkiG9w0BAQsFAAOCAYEAHk3bGPAl8YvQE84KZnCnVWBfayFeHKXlN/o/MvpYtPb2\n"
+	"y9cnD8IMmruW3A/UL+md2xx24V+pQWmugB2e879N/Q3QVsSbHFlzPei4tieK5VVd\n"
+	"gLC2iG7N8YjQ0SNRDF22A1QQDcVzdCXOggivs4MelF1zaGfY3ywHOhiHXt0jDj1o\n"
+	"2bP5OflElDFVF7m38RDwdeGokb+raW/2lOJZe4oKpdmllyUtLvrQhdwpogwnbpvH\n"
+	"7ln5Tq4wDNIcxM+Y4MQwe6m0AEELdFZjBmfsZthmaGrbppLTbp14rzC6kKqZ9ay/\n"
+	"zG06DhPalDCR+Bqvmh2Qp25xgqThv9AX8JQU6W8avnkfyxFZwBEJZ0lNoOyLZV2Z\n"
+	"4vmflZyOih9ccGUaYXWXzyc+vxNZjFQwjWNss2vynVvp4+5DUeMWeAj/unvjrxy2\n"
+	"HOsI4FrD94g5PchhXyKXRmeJk4mcr0jtE5ycbmiDU3sXz6xM7hsdBeNFyr47L2nj\n"
+	"OfWEK8ArBc3uTEgp2tIA\n"
+	"-----END CERTIFICATE-----\n";
+
+char uri_and_cn[] =
+	"organization = GnuTLS test\n"
+	"expiration_days = 365\n"
+	"tls_www_server\n"
+	"uri = http://example.org/\n"
+	"cn = example.org\n"
+	"-----BEGIN CERTIFICATE-----\n"
+	"MIIESjCCArKgAwIBAgIUNC/WOkhQZc6stg6RSrVPaUHRmLwwDQYJKoZIhvcNAQEL\n"
+	"BQAwLDEUMBIGA1UEChMLR251VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3Jn\n"
+	"MB4XDTI2MDMxMzE1NTAwNVoXDTI3MDMxMzE1NTAwNVowLDEUMBIGA1UEChMLR251\n"
+	"VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3JnMIIBojANBgkqhkiG9w0BAQEF\n"
+	"AAOCAY8AMIIBigKCAYEArEgcC7WDqNJCpO0J3UfCraRWzmwk7soTg7pMmCv1FHWP\n"
+	"ywxfXxbl0jvRK/Owyv7q5QRdfcxSYhxydrloCOdWXhGQejgzcpgLu/Y3Ij0CjIzr\n"
+	"C38vMSS7yUjAuzB4IYtZsgyuB+bCfGH2Y227ntuniIjEnuekA18gfFemRUQ8PDao\n"
+	"EzNAPn8Q3cFlHh5Kr3gkDUduQlRhZdK0ryU/XaAUxz9G9TminIKCl4h1bKNT2pXN\n"
+	"08Cg3eOEi3Bl8lCCA7ufODl5frfrDcjNkxqRKN99zMa9A9hcRzYNF9/asX+BXFyh\n"
+	"7qbypKXAHBi6xi055+CRIBTxFC960qAluv2cOlo1tzZ0Nta75GhWCqLaVZgI0D0n\n"
+	"6SPZPEknVjGPQx1vSnq3ZNdNDdG83yw4QjFtujXdKrflcJafCg3D6LCvEyDPBdYC\n"
+	"reTJ9xWNCdsxdzlTdDk11CbxdIz4jA7qA/forbY9Dv7l0iC9d2zWmn4DOv23QIki\n"
+	"Uw46/ymnpeFaUTyNyyNHAgMBAAGjZDBiMAwGA1UdEwEB/wQCMAAwHgYDVR0RBBcw\n"
+	"FYYTaHR0cDovL2V4YW1wbGUub3JnLzATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNV\n"
+	"HQ4EFgQUlwTjYoWBx5WzPZq3swxe6OtO7RUwDQYJKoZIhvcNAQELBQADggGBAE6w\n"
+	"uGfQy1pi+VbvHFc64QZJhf6r0FQl8Y5kWPu7OI2o+M5/FmY9hXmXxJzAfGH3ecE8\n"
+	"PL/bnR9zRCHTi1ONogukPKPmm/x3AQehn54hvgjZXGFOMxGBB5wSbsEzjCQxgKOO\n"
+	"uzUKZ0zgJin5YEi9g3DGKYi1qDNceNB9LjsWq372FKze0y2zZT7U2xiQcXlKgIZ6\n"
+	"KEcRBQVDygKNeU8ux0Q+lSaymsT9dhs6uahmGUTbbLcsKxsPhJjfC3IWTH+vK3tV\n"
+	"yjjnHcfcITAYSYHOM8+2+5EMOCZmGxCqv3unDkJRYY2xrp3+kXyGXXKRw+yNs4MT\n"
+	"Zc9zymseS+rB+9SDYO4DHDIV+jMJPMcqjJSlglMhs53Z4HFuWcuYJ6FzbRyM7hky\n"
+	"X4El+DWVaajh10QZApiWnRTTafJzJTbYljbpdZVgDX6chAyQRTKj6Di7YrrXmlYZ\n"
+	"iPKiHBqRUnCnxe8HYoBeK5Dw1lzCmgqXp5wjRqo5UHaemgZQTjdlPiWeovEiVg==\n"
+	"-----END CERTIFICATE-----\n";
+
+char srv_and_cn[] =
+	"-----BEGIN CERTIFICATE-----\n"
+	"MIIESjCCArKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMRQwEgYDVQQKEwtHbnVU\n"
+	"TFMgdGVzdDEUMBIGA1UEAxMLZXhhbXBsZS5vcmcwHhcNMjYwMzEzMTY0OTU5WhcN\n"
+	"MjcwMzEzMTY0OTU5WjAsMRQwEgYDVQQKEwtHbnVUTFMgdGVzdDEUMBIGA1UEAxML\n"
+	"ZXhhbXBsZS5vcmcwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCsSBwL\n"
+	"tYOo0kKk7QndR8KtpFbObCTuyhODukyYK/UUdY/LDF9fFuXSO9Er87DK/urlBF19\n"
+	"zFJiHHJ2uWgI51ZeEZB6ODNymAu79jciPQKMjOsLfy8xJLvJSMC7MHghi1myDK4H\n"
+	"5sJ8YfZjbbue26eIiMSe56QDXyB8V6ZFRDw8NqgTM0A+fxDdwWUeHkqveCQNR25C\n"
+	"VGFl0rSvJT9doBTHP0b1OaKcgoKXiHVso1Palc3TwKDd44SLcGXyUIIDu584OXl+\n"
+	"t+sNyM2TGpEo333Mxr0D2FxHNg0X39qxf4FcXKHupvKkpcAcGLrGLTnn4JEgFPEU\n"
+	"L3rSoCW6/Zw6WjW3NnQ21rvkaFYKotpVmAjQPSfpI9k8SSdWMY9DHW9Kerdk100N\n"
+	"0bzfLDhCMW26Nd0qt+Vwlp8KDcPosK8TIM8F1gKt5Mn3FY0J2zF3OVN0OTXUJvF0\n"
+	"jPiMDuoD9+ittj0O/uXSIL13bNaafgM6/bdAiSJTDjr/Kael4VpRPI3LI0cCAwEA\n"
+	"AaN3MHUwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E\n"
+	"FgQUlwTjYoWBx5WzPZq3swxe6OtO7RUwMQYDVR0RBCowKKAmBggrBgEFBQcIB6Aa\n"
+	"FhhfeG1wcC1jbGllbnQuZXhhbXBsZS5vcmcwDQYJKoZIhvcNAQELBQADggGBAI0B\n"
+	"WAylO7fWCLtWJqfMrHa3JFH2rkQRf5WV+Z5JqcxlP47m6220+xBiV/iIZT0V6Un/\n"
+	"Z/4Je+jrx6vFIAxtTR1gmyfLo8TfzkEmwPT+uHb16RFkJbi5ik47Mm+31VOrq2G/\n"
+	"s1FP0oNCG6LAnVN1a3Np5uorbUJlTkrd9MxymIvbZMQ56pZvI8TeNgescxD3xY96\n"
+	"/yQXFBy3wu8PIJblG/7r5vPSY8BrEqpRZ0Dch4EoU2RVybE0vXUUTL2moripnHzF\n"
+	"4+mm4Fa8mNb6nII8RjmFDJJzKCQlpmm4R8iNaCvULv8jVO899XUwDSL8+hHt6jZK\n"
+	"aU0pWVCorxpUmgQiQmBAIYvreSM4nKtljSwT2+SBaMna+MaZk2vfBDO15tZH0LWW\n"
+	"OYpnqQQkihP9my4jESvn8FE4NtF5x44XuJVKTVSas1o49XLXq/94fT4DZGa6rdSx\n"
+	"p9Nnj64WFIqbTLoqM3nt7+zqFZDvwh+8ZEVcE1MazHOYhDQj1uU3jqIq/sZE8w==\n"
+	"-----END CERTIFICATE-----\n";
+
 void doit(void)
 {
 	gnutls_x509_crt_t x509;
@@ -1175,6 +1268,53 @@ void doit(void)
 	if (ret)
 		fail("%d: Hostname incorrectly matches (%d)\n", __LINE__, ret);
 
+	if (debug)
+		success("Testing not falling back to CN with DNS+URI SAN...\n");
+	data.data = (unsigned char *)dns_uri_and_cn;
+	data.size = strlen(dns_uri_and_cn);
+
+	ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
+	if (ret < 0)
+		fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
+
+	ret = gnutls_x509_crt_check_hostname(x509, "example.org");
+	if (ret)
+		fail("%d: Hostname incorrectly falls back to CN (%d)\n",
+		     __LINE__, ret);
+
+	ret = gnutls_x509_crt_check_hostname(x509, "alt.example.org");
+	if (!ret)
+		fail("%d: Hostname does not match a valid DNS SAN (%d)\n",
+		     __LINE__, ret);
+
+	if (debug)
+		success("Testing not falling back to CN with URI SAN...\n");
+	data.data = (unsigned char *)uri_and_cn;
+	data.size = strlen(uri_and_cn);
+
+	ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
+	if (ret < 0)
+		fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
+
+	ret = gnutls_x509_crt_check_hostname(x509, "example.org");
+	if (ret)
+		fail("%d: Hostname incorrectly falls back to CN (%d)\n",
+		     __LINE__, ret);
+
+	if (debug)
+		success("Testing not falling back to CN with SRV SAN...\n");
+	data.data = (unsigned char *)srv_and_cn;
+	data.size = strlen(srv_and_cn);
+
+	ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
+	if (ret < 0)
+		fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
+
+	ret = gnutls_x509_crt_check_hostname(x509, "example.org");
+	if (ret)
+		fail("%d: Hostname incorrectly falls back to CN (%d)\n",
+		     __LINE__, ret);
+
 	gnutls_x509_crt_deinit(x509);
 
 	gnutls_global_deinit();
