Skip to content

Commit

Permalink
Docs: clarify TLS cert name verification
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Harris committed Apr 22, 2023
1 parent 4d90301 commit 3768831
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 6 deletions.
3 changes: 2 additions & 1 deletion doc/doc-docbook/spec.xfpt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/src/tls-gnu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/src/tls-openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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))
Expand Down
16 changes: 12 additions & 4 deletions src/src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,21 +670,24 @@ Subject otherwise.
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");
}
}

Expand All @@ -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;
Expand Down

0 comments on commit 3768831

Please sign in to comment.