imap-send: move common code into function host_matches()

Move the ASN1_STRING access, the associated cast and the check for
embedded NUL bytes into host_matches() to simplify both callers.

Reformulate the NUL check using memchr() and add a comment to make it
more obvious what it is about.

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Beat Bolli 2026-03-11 23:10:27 +01:00 committed by Junio C Hamano
parent 08fd302fc4
commit 6392a0b75d
1 changed files with 9 additions and 7 deletions

View File

@ -219,8 +219,14 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,


#else #else


static int host_matches(const char *host, const char *pattern) static int host_matches(const char *host, const ASN1_STRING *asn1_str)
{ {
const char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);

/* embedded NUL characters may open a security hole */
if (memchr(pattern, '\0', ASN1_STRING_length(asn1_str)))
return 0;

if (pattern[0] == '*' && pattern[1] == '.') { if (pattern[0] == '*' && pattern[1] == '.') {
pattern += 2; pattern += 2;
if (!(host = strchr(host, '.'))) if (!(host = strchr(host, '.')))
@ -252,10 +258,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); 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); ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);


if (ntype == GEN_DNS && if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))
strlen((const char *)ASN1_STRING_get0_data(subj_alt_str)) ==
ASN1_STRING_length(subj_alt_str) &&
host_matches(hostname, (const char *)ASN1_STRING_get0_data(subj_alt_str)))
found = 1; found = 1;
} }
sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free); sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
@ -270,8 +273,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
(cname_entry = X509_NAME_get_entry(subj, i)) == NULL || (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
(cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL) (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
return error("cannot get certificate common name"); return error("cannot get certificate common name");
if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) && if (host_matches(hostname, cname))
host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
return 0; return 0;
return error("certificate owner '%s' does not match hostname '%s'", return error("certificate owner '%s' does not match hostname '%s'",
ASN1_STRING_get0_data(cname), hostname); ASN1_STRING_get0_data(cname), hostname);