On 2026-09-07 at 21:12:10, Beat Bolli wrote: > Checking the certificate subject's common name may only be done if the > subjectAltNames extension contains no DNS entries. If no SAN DNS name > matches, there's no match. > > Per RFC 6125 section 6.4.4[1]: > > As noted, 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. > > This change was inspired by a similar commit in the HAProxy project[2]. TLS is not supposed to use the CN at all these days and Go's implementation completely ignores it. subjectAltName is supposed to be used in all cases. > diff --git a/imap-send.c b/imap-send.c > index 9a807cdde8..66d3dbfaa5 100644 > --- a/imap-send.c > +++ b/imap-send.c > @@ -256,11 +256,11 @@ static int verify_hostname(X509 *cert, const char *hostname) > #endif > const X509_NAME_ENTRY *cname_entry; > const ASN1_STRING *cname; > - int i, found; > + int i, found, has_san_dns; > STACK_OF(GENERAL_NAME) *subj_alt_names; > > /* try the DNS subjectAltNames */ > - found = 0; > + found = has_san_dns = 0; > if ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) { > int num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names); > for (i = 0; !found && i < num_subj_alt_names; i++) { > @@ -268,13 +268,18 @@ static int verify_hostname(X509 *cert, const char *hostname) > GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); > ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype); > > - if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str)) > - found = 1; > + if (ntype == GEN_DNS) { > + has_san_dns = 1; > + if (host_matches(hostname, subj_alt_str)) > + found = 1; > + } This handles certificates with DNS names but not IP addresses. So, for instance, this match wouldn't work for the certificates for 1.1.1.1 (assuming they had public IMAP service). > } > sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free); > } > if (found) > return 0; > + if (has_san_dns) > + return error("none of the subjectAltNames matches hostname '%s'", hostname); I know OpenSSL has built-in hostname verification that can be used as of OpenSSL 1.0.2[0]. Is there a reason we're still doing this by hand? Relying on OpenSSL's verification would mean that (a) we would not have to worry about getting verification wrong in a security-sensitive way and (b) OpenSSL would handle the policy and standards compliance functionality. [0] https://wiki.openssl.org/index.php/Hostname_validation -- brian m. carlson (they/them) Toronto, Ontario, CA