threads / patch / 65207

patch, 4 partsimap-send: remove two string length checks

Subject: [PATCH 3/4] imap-send: remove two string length checks

## tl;dr

14 messages between Mar 11, 2026 and Mar 12, 2026. Diffs are folded; open one to read it.

replies: 13people: 3as markdown or json

Beat Bolli· Mar 11, 2026, 12:11 UTC · lore

[PATCH 0/4] imap-send: modernize the OpenSSL API

OpenSSL recently released version 4.0.0-alpha1 [1]. Compiling with this version revealed some erroneous and deprecated code.

This series aims to update this code to use the documented OpenSSL APIs. All of the newly used APIs have existed since OpenSSL 1.1.0, the latest version of which was released in September 2019 [2]. IMHO there is no need to support even older OpenSSL versions.

- The first two commits are needed to make imap-send.c compile against
  OpenSSL 4.0 (and older!).
- The remaining two are follow-up cleanups that are not strictly
  necessary.
Cc-ing Oswald as the original author of the affected code.

[1] https://github.com/openssl/openssl/tree/openssl-4.0.0-alpha1 [2] https://openssl-library.org/source/old/1.1.0/index.html

Beat Bolli (4):
  imap-send: use the OpenSSL API to access the subject alternative names
  imap-send: use the OpenSSL API to access the subject common name
  imap-send: remove two string length checks
  imap-send: refactor function host_matches()
 imap-send.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 12:11 UTC · re: Beat Bolli · lore

At this point, these two checks verify that the ASN1_STRINGs are internally consistent. This may have been ok when the fields were accessed directly, but now that the API is used, is unnecessary.

Remove the two checks.
Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
Show changes to imap-send.c +1 −4
diff --git a/imap-send.c b/imap-send.c
index 2a904314dd..2bb0003f08 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -253,8 +253,6 @@ static int verify_hostname(X509 *cert, const char *hostname)
 			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
 
 			if (ntype == GEN_DNS &&
-			    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;
 		}
@@ -270,8 +268,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
 	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
-	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
+	if (host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
 		     ASN1_STRING_get0_data(cname), hostname);
-- 
2.51.0
Oswald Buddenhagen· Mar 11, 2026, 13:41 UTC · re: Beat Bolli · lore

Re: [PATCH 3/4] imap-send: remove two string length checks

On Wed, Mar 11, 2026 at 01:11:06PM +0100, Beat Bolli wrote:
>At this point, these two checks verify that the ASN1_STRINGs are
>internally consistent. This may have been ok when the fields were
>accessed directly, but now that the API is used, is unnecessary.
>

that argumentation makes no sense. the purpose of this check is to ensure that there are no embedded nulls, which the matcher would be unable to deal with, which may be a security hole.

Beat Bolli· Mar 11, 2026, 21:49 UTC · re: Oswald Buddenhagen · lore

Re: [PATCH 3/4] imap-send: remove two string length checks

Hi Oswald
On 11.03.2026 14:41, Oswald Buddenhagen wrote:
Show 9 quoted lines
> On Wed, Mar 11, 2026 at 01:11:06PM +0100, Beat Bolli wrote:
>> At this point, these two checks verify that the ASN1_STRINGs are
>> internally consistent. This may have been ok when the fields were
>> accessed directly, but now that the API is used, is unnecessary.
>>
> that argumentation makes no sense.
> the purpose of this check is to ensure that there are no embedded nulls, 
> which the matcher would be unable to deal with, which may be a security 
> hole.
Thanks for the clarification; this was the piece that I was missing.
I'll send a v2 shortly that removes this change.
Cheers, Beat
Junio C Hamano· Mar 11, 2026, 18:55 UTC · re: Beat Bolli · lore

Re: [PATCH 3/4] imap-send: remove two string length checks

Beat Bolli <dev+git@drbeat.li> writes:
Show 5 quoted lines
> At this point, these two checks verify that the ASN1_STRINGs are
> internally consistent. This may have been ok when the fields were
> accessed directly, but now that the API is used, is unnecessary.
>
> Remove the two checks.
Oswald already gave a similar comment, but
 * I am not sure what you meant by "ok" in "may have been ok".  Do
   you mean "with raw access to the fields, it may have been made
   send to ensure validity of ASN1_STRING"?
 * I am also not sure what you meant by "now that the API is used".
   Who in the code uses which API function so that we do not have to
   do our sanity checking?
   The call to host_matches() that these extra checks protect are
   still passing raw "const char *" in this step, and the change to
   pass ASN1_STRING does not happen until [4/4], so you did not mean
   host_matches().  I am not sure what it is.
   
Thanks.
Show 29 quoted lines
>
> Signed-off-by: Beat Bolli <dev+git@drbeat.li>
> ---
>  imap-send.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/imap-send.c b/imap-send.c
> index 2a904314dd..2bb0003f08 100644
> --- a/imap-send.c
> +++ b/imap-send.c
> @@ -253,8 +253,6 @@ static int verify_hostname(X509 *cert, const char *hostname)
>  			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
>  
>  			if (ntype == GEN_DNS &&
> -			    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;
>  		}
> @@ -270,8 +268,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
>  	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
>  	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
>  		return error("cannot get certificate common name");
> -	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
> -	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
> +	if (host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
>  		return 0;
>  	return error("certificate owner '%s' does not match hostname '%s'",
>  		     ASN1_STRING_get0_data(cname), hostname);
Beat Bolli· Mar 11, 2026, 22:00 UTC · re: Junio C Hamano · lore

Re: [PATCH 3/4] imap-send: remove two string length checks

Hi Junio
On 11.03.2026 19:55, Junio C Hamano wrote:
Show 24 quoted lines
> Beat Bolli <dev+git@drbeat.li> writes:
> 
>> At this point, these two checks verify that the ASN1_STRINGs are
>> internally consistent. This may have been ok when the fields were
>> accessed directly, but now that the API is used, is unnecessary.
>>
>> Remove the two checks.
> 
> Oswald already gave a similar comment, but
> 
>   * I am not sure what you meant by "ok" in "may have been ok".  Do
>     you mean "with raw access to the fields, it may have been made
>     send to ensure validity of ASN1_STRING"?
> 
>   * I am also not sure what you meant by "now that the API is used".
>     Who in the code uses which API function so that we do not have to
>     do our sanity checking?
> 
>     The call to host_matches() that these extra checks protect are
>     still passing raw "const char *" in this step, and the change to
>     pass ASN1_STRING does not happen until [4/4], so you did not mean
>     host_matches().  I am not sure what it is.
>     
> Thanks.

I didn't realize that the strlen() comparison was meant to check for embedded NULs. I'll send v2 shortly that keeps this check.

Cheers, Beat
Show 28 quoted lines
>> Signed-off-by: Beat Bolli <dev+git@drbeat.li>
>> ---
>>   imap-send.c | 5 +----
>>   1 file changed, 1 insertion(+), 4 deletions(-)
>>
>> diff --git a/imap-send.c b/imap-send.c
>> index 2a904314dd..2bb0003f08 100644
>> --- a/imap-send.c
>> +++ b/imap-send.c
>> @@ -253,8 +253,6 @@ static int verify_hostname(X509 *cert, const char *hostname)
>>   			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
>>   
>>   			if (ntype == GEN_DNS &&
>> -			    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;
>>   		}
>> @@ -270,8 +268,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
>>   	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
>>   	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
>>   		return error("cannot get certificate common name");
>> -	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
>> -	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
>> +	if (host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
>>   		return 0;
>>   	return error("certificate owner '%s' does not match hostname '%s'",
>>   		     ASN1_STRING_get0_data(cname), hostname);
Beat Bolli· Mar 11, 2026, 12:11 UTC · re: Beat Bolli · lore

[PATCH 4/4] imap-send: refactor function host_matches()

Move the ASN1_STRING access and the associated cast into host_matches() to simplify both callers.

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
Show changes to imap-send.c +4 −4
diff --git a/imap-send.c b/imap-send.c
index 2bb0003f08..789055d7fd 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -219,8 +219,9 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,
 
 #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);
 	if (pattern[0] == '*' && pattern[1] == '.') {
 		pattern += 2;
 		if (!(host = strchr(host, '.')))
@@ -252,8 +253,7 @@ 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, (const char *)ASN1_STRING_get0_data(subj_alt_str)))
+			if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))
 				found = 1;
 		}
 		sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
@@ -268,7 +268,7 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
 	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
+	if (host_matches(hostname, cname))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
 		     ASN1_STRING_get0_data(cname), hostname);
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 12:11 UTC · re: Beat Bolli · lore

[PATCH 2/4] imap-send: use the OpenSSL API to access the subject common name

The OpenSSL 4.0 branch has deprecated the X509_NAME_get_text_by_NID function. Use the recommended replacement APIs instead. They have existed since OpenSSL 1.1.0.

Pre-4.0 versions of X509_get_subject_name() return a non-const pointer and more importantly only accept a non-const pointer in X509_NAME_get_index_by_NID(), so we need a version check to handle both cases.

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
Show changes to imap-send.c +12 −5
diff --git a/imap-send.c b/imap-send.c
index 1c934c2487..2a904314dd 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -233,9 +233,13 @@ static int host_matches(const char *host, const char *pattern)
 
 static int verify_hostname(X509 *cert, const char *hostname)
 {
-	int len;
+#if (OPENSSL_VERSION_NUMBER >= 0x40000000L)
+	const X509_NAME *subj;
+#else
 	X509_NAME *subj;
-	char cname[1000];
+#endif
+	const X509_NAME_ENTRY *cname_entry;
+	const ASN1_STRING *cname;
 	int i, found;
 	STACK_OF(GENERAL_NAME) *subj_alt_names;
 
@@ -262,12 +266,15 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	/* try the common name */
 	if (!(subj = X509_get_subject_name(cert)))
 		return error("cannot get certificate subject");
-	if ((len = X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname))) < 0)
+	if ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1)) < 0 ||
+	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
+	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (strlen(cname) == (size_t)len && host_matches(hostname, cname))
+	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
+	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
-		     cname, hostname);
+		     ASN1_STRING_get0_data(cname), hostname);
 }
 
 static int ssl_socket_connect(struct imap_socket *sock,
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 12:11 UTC · re: Beat Bolli · lore

[PATCH 1/4] imap-send: use the OpenSSL API to access the subject alternative names

The OpenSSL 4.0 branch has made the ASN1_STRING structure opaque, forbidding access to its internal fields. Use the official accessor functions instead. They have existed since OpenSSL 1.1.0.

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Show changes to imap-send.c +7 −3
diff --git a/imap-send.c b/imap-send.c
index 26dda7f328..1c934c2487 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -244,10 +244,14 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	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++) {
+			int ntype;
 			GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
-			if (subj_alt_name->type == GEN_DNS &&
-			    strlen((const char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length &&
-			    host_matches(hostname, (const char *)(subj_alt_name->d.ia5->data)))
+			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
+
+			if (ntype == GEN_DNS &&
+			    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;
 		}
 		sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 22:10 UTC · re: Beat Bolli · lore

[PATCH v2 1/3] imap-send: use the OpenSSL API to access the subject alternative names

The OpenSSL 4.0 master branch has made the ASN1_STRING structure opaque, forbidding access to its internal fields. Use the official accessor functions instead. They have existed since OpenSSL v1.1.0.

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Show changes to imap-send.c +7 −3
diff --git a/imap-send.c b/imap-send.c
index 26dda7f328..1c934c2487 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -244,10 +244,14 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	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++) {
+			int ntype;
 			GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
-			if (subj_alt_name->type == GEN_DNS &&
-			    strlen((const char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length &&
-			    host_matches(hostname, (const char *)(subj_alt_name->d.ia5->data)))
+			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
+
+			if (ntype == GEN_DNS &&
+			    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;
 		}
 		sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 22:10 UTC · re: Beat Bolli · lore

[PATCH v2 0/3] imap-send: modernize the OpenSSL API

OpenSSL recently released version 4.0.0-alpha1 [1]. Compiling with this version revealed some erroneous and deprecated code.

This series aims to update this code to use the documented OpenSSL APIs. All of the newly used APIs have existed since OpenSSL 1.1.0, the latest version of which was released in September 2019 [2]. IMHO there is no need to support even older OpenSSL versions.

Cc-ing Oswald as the original author of the affected code.

[1] https://github.com/openssl/openssl/tree/openssl-4.0.0-alpha1 [2] https://openssl-library.org/source/old/1.1.0/index.html

Beat Bolli (3):
  imap-send: use the OpenSSL API to access the subject alternative names
  imap-send: use the OpenSSL API to access the subject common name
  imap-send: move common code into function host_matches()
 imap-send.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)
---
Changes vs v1:
- keep the check for embedded NUL characters
-- 
2.51.0
Junio C Hamano· Mar 12, 2026, 00:25 UTC · re: Beat Bolli · lore

Re: [PATCH v2 0/3] imap-send: modernize the OpenSSL API

Beat Bolli <dev+git@drbeat.li> writes:
> Changes vs v1:
> - keep the check for embedded NUL characters

... which amounts to this difference, which is a lot more explicit way to express what is going on. I like it.

Thanks.
Show changes to imap-send.c +5 −0
diff --git a/imap-send.c b/imap-send.c
index 789055d7fd..af02c6a689 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -222,6 +222,11 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,
 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] == '.') {
 		pattern += 2;
 		if (!(host = strchr(host, '.')))
Beat Bolli· Mar 11, 2026, 22:10 UTC · re: Beat Bolli · lore

[PATCH v2 3/3] 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>
---
 imap-send.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
Show changes to imap-send.c +9 −7
diff --git a/imap-send.c b/imap-send.c
index 2a904314dd..af02c6a689 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -219,8 +219,14 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,
 
 #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] == '.') {
 		pattern += 2;
 		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);
 			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
 
-			if (ntype == GEN_DNS &&
-			    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)))
+			if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))
 				found = 1;
 		}
 		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 = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
-	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
+	if (host_matches(hostname, cname))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
 		     ASN1_STRING_get0_data(cname), hostname);
-- 
2.51.0
Beat Bolli· Mar 11, 2026, 22:10 UTC · re: Beat Bolli · lore

[PATCH v2 2/3] imap-send: use the OpenSSL API to access the subject common name

The OpenSSL 4.0 master branch has deprecated the X509_NAME_get_text_by_NID function. Use the recommended replacement APIs instead. They have existed since OpenSSL v1.1.0.

Take care to get the constness right for pre-4.0 versions.
Signed-off-by: Beat Bolli <dev+git@drbeat.li>
---
 imap-send.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
Show changes to imap-send.c +12 −5
diff --git a/imap-send.c b/imap-send.c
index 1c934c2487..2a904314dd 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -233,9 +233,13 @@ static int host_matches(const char *host, const char *pattern)
 
 static int verify_hostname(X509 *cert, const char *hostname)
 {
-	int len;
+#if (OPENSSL_VERSION_NUMBER >= 0x40000000L)
+	const X509_NAME *subj;
+#else
 	X509_NAME *subj;
-	char cname[1000];
+#endif
+	const X509_NAME_ENTRY *cname_entry;
+	const ASN1_STRING *cname;
 	int i, found;
 	STACK_OF(GENERAL_NAME) *subj_alt_names;
 
@@ -262,12 +266,15 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	/* try the common name */
 	if (!(subj = X509_get_subject_name(cert)))
 		return error("cannot get certificate subject");
-	if ((len = X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname))) < 0)
+	if ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1)) < 0 ||
+	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
+	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (strlen(cname) == (size_t)len && host_matches(hostname, cname))
+	if (strlen((const char *)ASN1_STRING_get0_data(cname)) == ASN1_STRING_length(cname) &&
+	    host_matches(hostname, (const char *)ASN1_STRING_get0_data(cname)))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
-		     cname, hostname);
+		     ASN1_STRING_get0_data(cname), hostname);
 }
 
 static int ssl_socket_connect(struct imap_socket *sock,
-- 
2.51.0

← back to recent threads