From 3ee2cb707002f755e4bda3f75285caa0cb36c214 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Wed, 15 Apr 2026 15:35:59 +0200
Subject: x509/email-verify: call fallback DN fallback

A comment was inaccurately referring to DN email field fallback
as CN fallback.
Rename a few things as well to match x509/hostname-verify more closely.

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 lib/x509/email-verify.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

From 3ee2cb707002f755e4bda3f75285caa0cb36c214 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Wed, 15 Apr 2026 15:35:59 +0200
Subject: [PATCH] x509/email-verify: call fallback DN fallback

A comment was inaccurately referring to DN email field fallback
as CN fallback.
Rename a few things as well to match x509/hostname-verify more closely.

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 lib/x509/email-verify.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

From 01a4fd98b5b85f6736333aa0381bb56c9aa8dbb9 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Wed, 15 Apr 2026 18:02:31 +0200
Subject: [PATCH] tests/cert-tests: add tests for #1825

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
 .../cert-tests/email-certs/oversized-san.pem  | 16 +++++++++
 tests/cert-tests/email.sh                     | 11 ++++++
 tests/hostname-check.c                        | 34 +++++++++++++++++++
 3 files changed, 61 insertions(+)
 create mode 100644 tests/cert-tests/email-certs/oversized-san.pem

Index: gnutls-3.8.10/lib/x509/email-verify.c
===================================================================
--- gnutls-3.8.10.orig/lib/x509/email-verify.c
+++ gnutls-3.8.10/lib/x509/email-verify.c
@@ -42,7 +42,7 @@ unsigned gnutls_x509_crt_check_email(gnu
 {
 	char rfc822name[MAX_CN];
 	size_t rfc822namesize;
-	int found_rfc822name = 0;
+	bool dn_fallback_allowed = true;
 	int ret = 0;
 	int i = 0;
 	char *a_email;
@@ -75,8 +75,22 @@ unsigned gnutls_x509_crt_check_email(gnu
 		ret = gnutls_x509_crt_get_subject_alt_name(
 			cert, i, rfc822name, &rfc822namesize, NULL);
 
+		if (ret < 0) {
+			if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+				/* oversized SAN; proceed without DN fallback */
+				_gnutls_debug_log("oversized SAN ignored, "
+						  "disabling DN fallback\n");
+				dn_fallback_allowed = false;
+				ret = 0;
+				continue;
+			}
+			if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+				gnutls_assert();
+			break;
+		}
+
 		if (ret == GNUTLS_SAN_RFC822NAME) {
-			found_rfc822name = 1;
+			dn_fallback_allowed = false;
 
 			if (memchr(rfc822name, '\0', rfc822namesize)) {
 				_gnutls_debug_log(
@@ -102,12 +116,10 @@ unsigned gnutls_x509_crt_check_email(gnu
 		}
 	}
 
-	if (!found_rfc822name) {
-		/* did not get the necessary extension, use CN instead
-		 */
+	if (dn_fallback_allowed) {
+		/* did not get the necessary extension, use DN email instead */
 
-		/* enforce the RFC6125 (§1.8) requirement that only
-		 * a single CN must be present */
+		/* only a single one must be present */
 		rfc822namesize = sizeof(rfc822name);
 		ret = gnutls_x509_crt_get_dn_by_oid(cert,
 						    GNUTLS_OID_PKCS9_EMAIL, 1,
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
@@ -213,6 +213,20 @@ hostname_fallback:
 		ret = gnutls_x509_crt_get_subject_alt_name(cert, i, dnsname,
 							   &dnsnamesize, NULL);
 
+		if (ret < 0) {
+			if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+				/* oversized SAN; proceed without CN fallback */
+				_gnutls_debug_log("oversized SAN ignored, "
+						  "disabling CN fallback\n");
+				cn_fallback_allowed = false;
+				ret = 0;
+				continue;
+			}
+			if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+				gnutls_assert();
+			break;
+		}
+
 		if (PRECLUDES_CN_FALLBACK(ret))
 			cn_fallback_allowed = false;
 
Index: gnutls-3.8.10/tests/cert-tests/email-certs/oversized-san.pem
===================================================================
--- /dev/null
+++ gnutls-3.8.10/tests/cert-tests/email-certs/oversized-san.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICezCCAi2gAwIBAgIUWECpllJihTypDAKZQgEJeM02fG8wBQYDK2VwMDcxFDAS
+BgNVBAMTC2V4YW1wbGUuY29tMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUu
+Y29tMB4XDTI2MDQxNTE1NTE1MloXDTI3MDQxNTE1NTE1MlowNzEUMBIGA1UEAxML
+ZXhhbXBsZS5jb20xHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wKjAF
+BgMrZXADIQCn95fhASNNgr5I/qAX+kiY8SiwPJcTVy1ugWJdX3d4uqOCAUkwggFF
+MA8GA1UdEwEB/wQFMAMBAf8wggERBgNVHREEggEIMIIBBIGCAQBhYWFhYWFhYWFh
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
+YWFhYWFhMB0GA1UdDgQWBBTeT2MAM29EwVLvTom8wGN05B7QhDAFBgMrZXADQQAQ
+zTZqdt4LXX21VFce7S99k6XX+N+xPAUo4beursVrlaesdVsfvDtEk2t+0b5WLbtW
+7UI9PxB9CN4hULrxrI8N
+-----END CERTIFICATE-----
Index: gnutls-3.8.10/tests/cert-tests/email.sh
===================================================================
--- gnutls-3.8.10.orig/tests/cert-tests/email.sh
+++ gnutls-3.8.10/tests/cert-tests/email.sh
@@ -95,5 +95,16 @@ if test "${rc}" != "1"; then
 	exit 1
 fi
 
+# #1825: oversized SAN does not preclude fallback to DN email
+${VALGRIND} "${CERTTOOL}" \
+	--infile "${srcdir}/email-certs/oversized-san.pem" \
+	--load-ca-certificate "${srcdir}/email-certs/oversized-san.pem" \
+	--verify --verify-email test@example.com
+rc=$?
+
+if test "${rc}" != "1"; then
+	echo "email test 9 failed"
+	exit 1
+fi
 
 exit 0
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
@@ -897,6 +897,25 @@ char srv_and_cn[] =
 	"p9Nnj64WFIqbTLoqM3nt7+zqFZDvwh+8ZEVcE1MazHOYhDQj1uU3jqIq/sZE8w==\n"
 	"-----END CERTIFICATE-----\n";
 
+char pem_1825_oversized_san[] =
+	"ca\n"
+	"cn = example.com\n"
+	"dns_name = <'a' * 256>\n"
+	"-----BEGIN CERTIFICATE-----\n"
+	"MIICOTCCAeugAwIBAgIURFygaiK3EBmc5AMZToFitMMikhcwBQYDK2VwMBYxFDAS\n"
+	"BgNVBAMTC2V4YW1wbGUuY29tMB4XDTI2MDQxNTE2MDYwMFoXDTI3MDQxNTE2MDYw\n"
+	"MFowFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wKjAFBgMrZXADIQBHqgbjhT1zZ3h9\n"
+	"okSrhd2+0Lr0Uj1q81sqHrcCEdqVpaOCAUkwggFFMA8GA1UdEwEB/wQFMAMBAf8w\n"
+	"ggERBgNVHREEggEIMIIBBIKCAQBhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
+	"YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
+	"YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
+	"YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
+	"YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
+	"YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhMB0GA1UdDgQWBBT+\n"
+	"/oWt1Lrfz7Awk9h8yDoz1TKyHjAFBgMrZXADQQBfR5ByQyxpLEsVM5+ihYjSbmYF\n"
+	"1pOFndq0UIKPkWsRqBpitzDIVrVTLlIcY0fQpsxITNgdoIU68WynLGVrRHIF\n"
+	"-----END CERTIFICATE-----\n";
+
 void doit(void)
 {
 	gnutls_x509_crt_t x509;
@@ -1315,6 +1334,21 @@ void doit(void)
 		fail("%d: Hostname incorrectly falls back to CN (%d)\n",
 		     __LINE__, ret);
 
+	if (debug)
+		success("Testing oversized SAN (#1825)...\n");
+	data.data = (unsigned char *)pem_1825_oversized_san;
+	data.size = strlen(pem_1825_oversized_san);
+
+	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.com");
+	if (ret)
+		fail("%d: Hostname incorrectly falls back to CN "
+		     "with oversized SAN (%d)\n",
+		     __LINE__, ret);
+
 	gnutls_x509_crt_deinit(x509);
 
 	gnutls_global_deinit();
