Re: [PATCH 3/3] imap-send: only check the CN if no SAN DNS names are present
- From
brian m. carlson <sandals@crustytoothpaste.net>
- Date
- Sep 8, 2026, 01:28 UTC
- Message-ID
- <ap9kv-ORyzzeUiqb@fruit.crustytoothpaste.net>
- In-Reply-To
- <20260907211210.2621693-4-dev+git@drbeat.li>
On 2026-09-07 at 21:12:10, Beat Bolli wrote:
Show 12 quoted lines
> 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.
Show 29 quoted lines
> 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).
Show 7 quoted lines
> }
> 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