[exim-cvs] Docs: clarify TLS cert name verification

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List via exim-cvs
Date:  
To: exim-cvs
CC: Exim Git Commits Mailing List
Subject: [exim-cvs] Docs: clarify TLS cert name verification
Gitweb: https://git.exim.org/exim.git/commitdiff/37688315a566d2bfaeae040ee1cbaae3102efced
Commit:     37688315a566d2bfaeae040ee1cbaae3102efced
Parent:     4d90301f3b4ae47da4e9db483102b1e1fe83d33a
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sat Apr 22 00:21:25 2023 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sat Apr 22 16:26:47 2023 +0100


    Docs: clarify TLS cert name verification
---
 doc/doc-docbook/spec.xfpt |  3 ++-
 src/src/tls-gnu.c         |  2 +-
 src/src/tls-openssl.c     |  5 +++++
 src/src/tls.c             | 16 ++++++++++++----
 4 files changed, 20 insertions(+), 6 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index d2d40728b..b8f6f939d 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -26161,7 +26161,8 @@ This option give a list of hosts for which,
while verifying the server certificate,
checks will be included on the host name
(note that this will generally be the result of a DNS MX lookup)
-versus Subject and Subject-Alternate-Name fields. Wildcard names are permitted
+versus the Subject-Alternate-Name (or, if none, Subject-Name) fields.
+Wildcard names are permitted,
limited to being the initial component of a 3-or-more component FQDN.

 There is no equivalent checking on client certificates.
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index f3f70d2e0..76176a64e 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -2620,7 +2620,7 @@ else
      )
     {
     DEBUG(D_tls)
-      debug_printf("TLS certificate verification failed: cert name mismatch\n");
+      debug_printf("TLS certificate verification failed: cert name mismatch (per GnuTLS)\n");
     if (state->verify_requirement >= VERIFY_REQUIRED)
       goto badcert;
     return TRUE;
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 9d0ab2fdf..cd715cc18 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1192,6 +1192,8 @@ else
     uschar * name;
     int rc;
     while ((name = string_nextinlist(&list, &sep, NULL, 0)))
+      {
+      DEBUG(D_tls|D_lookup) debug_printf_indent("%s suitable for cert, per OpenSSL?", name);
       if ((rc = X509_check_host(cert, CCS name, 0,
           X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
           | X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS,
@@ -1203,8 +1205,11 @@ else
         tlsp == &tls_out ? deliver_host_address : sender_host_address);
       name = NULL;
       }
+    DEBUG(D_tls|D_lookup) debug_printf_indent("  yes\n");
     break;
     }
+      else DEBUG(D_tls|D_lookup) debug_printf_indent("  no\n");
+      }
     if (!name)
 #else
     if (!tls_is_name_for_cert(verify_cert_hostnames, cert))
diff --git a/src/src/tls.c b/src/src/tls.c
index 825313a9a..8f4344c6c 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -670,21 +670,24 @@ Returns:
 BOOL
 tls_is_name_for_cert(const uschar * namelist, void * cert)
 {
-uschar * altnames = tls_cert_subject_altname(cert, US"dns");
-uschar * subjdn;
-uschar * certname;
+uschar * altnames, * subjdn, * certname, * cmpname;
 int cmp_sep = 0;
-uschar * cmpname;


 if ((altnames = tls_cert_subject_altname(cert, US"dns")))
   {
   int alt_sep = '\n';
+  DEBUG(D_tls|D_lookup) debug_printf_indent("cert has SAN\n");
   while ((cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)))
     {
     const uschar * an = altnames;
+    DEBUG(D_tls|D_lookup) debug_printf_indent(" %s in SANs?", cmpname);
     while ((certname = string_nextinlist(&an, &alt_sep, NULL, 0)))
       if (is_name_match(cmpname, certname))
+    {
+    DEBUG(D_tls|D_lookup) debug_printf_indent("  yes (matched %s)\n", certname);
     return TRUE;
+    }
+    DEBUG(D_tls|D_lookup) debug_printf_indent(" no (end of SAN list)\n");
     }
   }


@@ -696,13 +699,18 @@ else if ((subjdn = tls_cert_subject(cert, NULL)))
   while ((cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)))
     {
     const uschar * sn = subjdn;
+    DEBUG(D_tls|D_lookup) debug_printf_indent(" %s in SN?", cmpname);
     while ((certname = string_nextinlist(&sn, &sn_sep, NULL, 0)))
       if (  *certname++ == 'C'
      && *certname++ == 'N'
      && *certname++ == '='
      && is_name_match(cmpname, certname)
      )
+    {
+    DEBUG(D_tls|D_lookup) debug_printf_indent("  yes (matched %s)\n", certname);
     return TRUE;
+    }
+    DEBUG(D_tls|D_lookup) debug_printf_indent(" no (end of CN)\n");
     }
   }
 return FALSE;


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/