{"thread":{"id":"66288","subject":"[PATCH 0/3] imap-send: future proofing and two correctness fixes","startedAt":"2026-09-07T21:15:57Z","lastAt":"2026-09-23T12:32:38Z","messageCount":11,"participants":["Beat Bolli","Junio C Hamano","brian m. carlson","Patrick Steinhardt"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"552168","messageId":"20260907211210.2621693-1-dev+git@drbeat.li","threadId":"66288","inReplyTo":null,"subject":"[PATCH 0/3] imap-send: future proofing and two correctness fixes","fromName":"Beat Bolli","fromEmail":"dev+git@drbeat.li","sentAt":"2026-09-07T21:12:07Z","receivedAt":"2026-09-07T21:15:57Z","isPatch":true,"body":"Hi!\n\nPatch 1 future-proofs against a renamed ASN1_STRING function.\n\nPatch 2 fixes an incorrect assumption about NUL-termination of\nASN1_STRINGs.\n\nPatch 3 only checks the certificate subject common name if no DNS\nsubject alternative names are available, as defined by RFC 6125.\n\n\nBeat Bolli (3):\n  imap-send: prepare for OpenSSL 4.1\n  imap-send: don't expect an ASN1_STRING to be NUL-terminated\n  imap-send: only check the CN if no SAN DNS names are present\n\n imap-send.c | 33 ++++++++++++++++++++++++---------\n 1 file changed, 24 insertions(+), 9 deletions(-)\n\n-- \n2.53.0\n\n"},{"id":"552169","messageId":"20260907211210.2621693-4-dev+git@drbeat.li","threadId":"66288","inReplyTo":"20260907211210.2621693-1-dev+git@drbeat.li","subject":"[PATCH 3/3] imap-send: only check the CN if no SAN DNS names are present","fromName":"Beat Bolli","fromEmail":"dev+git@drbeat.li","sentAt":"2026-09-07T21:12:10Z","receivedAt":"2026-09-07T21:16:17Z","isPatch":true,"body":"Checking the certificate subject's common name may only be done if the\nsubjectAltNames extension contains no DNS entries. If no SAN DNS name\nmatches, there's no match.\n\nPer RFC 6125 section 6.4.4[1]:\n\n    As noted, a client MUST NOT seek a match for a reference identifier\n    of CN-ID if the presented identifiers include a DNS-ID, SRV-ID,\n    URI-ID, or any application-specific identifier types supported by the\n    client.\n\nThis change was inspired by a similar commit in the HAProxy project[2].\n\n[1]: https://datatracker.ietf.org/doc/html/rfc6125#section-6.4.4\n[2]: https://github.com/haproxy/haproxy/commit/75129aaacb7a7b172f4e5334db71d6c1c50a3dbf\n\nSigned-off-by: Beat Bolli <dev+git@drbeat.li>\n---\n imap-send.c | 13 +++++++++----\n 1 file changed, 9 insertions(+), 4 deletions(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex 9a807cdde8..66d3dbfaa5 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -256,11 +256,11 @@ static int verify_hostname(X509 *cert, const char *hostname)\n #endif\n \tconst X509_NAME_ENTRY *cname_entry;\n \tconst ASN1_STRING *cname;\n-\tint i, found;\n+\tint i, found, has_san_dns;\n \tSTACK_OF(GENERAL_NAME) *subj_alt_names;\n \n \t/* try the DNS subjectAltNames */\n-\tfound = 0;\n+\tfound = has_san_dns = 0;\n \tif ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) {\n \t\tint num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names);\n \t\tfor (i = 0; !found && i < num_subj_alt_names; i++) {\n@@ -268,13 +268,18 @@ static int verify_hostname(X509 *cert, const char *hostname)\n \t\t\tGENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);\n \t\t\tASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);\n \n-\t\t\tif (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))\n-\t\t\t\tfound = 1;\n+\t\t\tif (ntype == GEN_DNS) {\n+\t\t\t\thas_san_dns = 1;\n+\t\t\t\tif (host_matches(hostname, subj_alt_str))\n+\t\t\t\t\tfound = 1;\n+\t\t\t}\n \t\t}\n \t\tsk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);\n \t}\n \tif (found)\n \t\treturn 0;\n+\tif (has_san_dns)\n+\t\treturn error(\"none of the subjectAltNames matches hostname '%s'\", hostname);\n \n \t/* try the common name */\n \tif (!(subj = X509_get_subject_name(cert)))\n-- \n2.53.0\n\n"},{"id":"552170","messageId":"20260907211210.2621693-3-dev+git@drbeat.li","threadId":"66288","inReplyTo":"20260907211210.2621693-1-dev+git@drbeat.li","subject":"[PATCH 2/3] imap-send: don't expect an ASN1_STRING to be NUL-terminated","fromName":"Beat Bolli","fromEmail":"dev+git@drbeat.li","sentAt":"2026-09-07T21:12:09Z","receivedAt":"2026-09-07T21:23:04Z","isPatch":true,"body":"As highlighted by a recent OpenSSL commit[1], ASN1_STRINGs were never\ndocumented to be terminated by a NUL byte, but our code treats the\npattern as such in the strcasecmp() call.\n\nMake a NUL-terminated copy to avoid Undefined Behavior.\n\n[1]: https://github.com/openssl/openssl/commit/4b581a4666c3e470a01a7323801b2ba8ccfa478c\n     (Add a migration entry for ASN1_STRINGs, 2026-08-06)\n\nSigned-off-by: Beat Bolli <dev+git@drbeat.li>\n---\n imap-send.c | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex 977d78005c..9a807cdde8 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -226,20 +226,25 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,\n \n static int host_matches(const char *host, const ASN1_STRING *asn1_str)\n {\n-\tconst char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);\n+\tint ret = 0;\n+\tsize_t len = ASN1_STRING_get_length(asn1_str);\n+\tchar *pattern = xmemdupz(ASN1_STRING_get0_data(asn1_str), len);\n \n \t/* embedded NUL characters may open a security hole */\n-\tif (memchr(pattern, '\\0', ASN1_STRING_get_length(asn1_str)))\n-\t    return 0;\n+\tif (memchr(pattern, '\\0', len))\n+\t    goto out;\n \n \tif (pattern[0] == '*' && pattern[1] == '.') {\n \t\tpattern += 2;\n \t\tif (!(host = strchr(host, '.')))\n-\t\t\treturn 0;\n+\t\t\tgoto out;\n \t\thost++;\n \t}\n \n-\treturn *host && *pattern && !strcasecmp(host, pattern);\n+\tret = *host && *pattern && !strcasecmp(host, pattern);\n+out:\n+\tfree(pattern);\n+\treturn ret;\n }\n \n static int verify_hostname(X509 *cert, const char *hostname)\n-- \n2.53.0\n\n"},{"id":"552171","messageId":"20260907211210.2621693-2-dev+git@drbeat.li","threadId":"66288","inReplyTo":"20260907211210.2621693-1-dev+git@drbeat.li","subject":"[PATCH 1/3] imap-send: prepare for OpenSSL 4.1","fromName":"Beat Bolli","fromEmail":"dev+git@drbeat.li","sentAt":"2026-09-07T21:12:08Z","receivedAt":"2026-09-07T21:23:10Z","isPatch":true,"body":"OpenSSL master (to be v4.1 after the release) renamed the function\nASN1_STRING_length() to ASN1_STRING_get_length(). Map the new name to\nthe old one if we're compiling with a pre-4.1 version.\n\nSigned-off-by: Beat Bolli <dev+git@drbeat.li>\n---\n imap-send.c | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex 0d16d02029..977d78005c 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -219,12 +219,17 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,\n \n #else\n \n+#if (OPENSSL_VERSION_NUMBER < 0x40100000L)\n+// map to the pre-4.1 name\n+#define ASN1_STRING_get_length(s) ASN1_STRING_length(s)\n+#endif\n+\n static int host_matches(const char *host, const ASN1_STRING *asn1_str)\n {\n \tconst char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);\n \n \t/* embedded NUL characters may open a security hole */\n-\tif (memchr(pattern, '\\0', ASN1_STRING_length(asn1_str)))\n+\tif (memchr(pattern, '\\0', ASN1_STRING_get_length(asn1_str)))\n \t    return 0;\n \n \tif (pattern[0] == '*' && pattern[1] == '.') {\n-- \n2.53.0\n\n"},{"id":"552174","messageId":"xmqqwlswzgmq.fsf@gitster.g","threadId":"66288","inReplyTo":"20260907211210.2621693-3-dev+git@drbeat.li","subject":"Re: [PATCH 2/3] imap-send: don't expect an ASN1_STRING to be NUL-terminated","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-08T01:17:01Z","receivedAt":"2026-09-08T01:17:03Z","isPatch":true,"body":"Beat Bolli <dev+git@drbeat.li> writes:\n\n> -\tconst char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);\n> +\tint ret = 0;\n> +\tsize_t len = ASN1_STRING_get_length(asn1_str);\n> +\tchar *pattern = xmemdupz(ASN1_STRING_get0_data(asn1_str), len);\n>  \n>  \t/* embedded NUL characters may open a security hole */\n> -\tif (memchr(pattern, '\\0', ASN1_STRING_get_length(asn1_str)))\n> -\t    return 0;\n> +\tif (memchr(pattern, '\\0', len))\n> +\t    goto out;\n>  \n>  \tif (pattern[0] == '*' && pattern[1] == '.') {\n>  \t\tpattern += 2;\n>  \t\tif (!(host = strchr(host, '.')))\n> -\t\t\treturn 0;\n> +\t\t\tgoto out;\n>  \t\thost++;\n>  \t}\n>  \n> -\treturn *host && *pattern && !strcasecmp(host, pattern);\n> +\tret = *host && *pattern && !strcasecmp(host, pattern);\n> +out:\n> +\tfree(pattern);\n\nThere is a code path that increments the \"pattern\" variable by 2.\nRunning free() on it would not have a pleasant outcome.\n\nThe pattern we often employ in our codebase is to have a separate\nvariable \"char *pattern_to_free\" and have it used only for a call\nto free().\n\n\n> +\treturn ret;\n>  }\n>  \n>  static int verify_hostname(X509 *cert, const char *hostname)\n"},{"id":"552175","messageId":"ap9kv-ORyzzeUiqb@fruit.crustytoothpaste.net","threadId":"66288","inReplyTo":"20260907211210.2621693-4-dev+git@drbeat.li","subject":"Re: [PATCH 3/3] imap-send: only check the CN if no SAN DNS names are present","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-09-08T01:28:32Z","receivedAt":"2026-09-08T01:28:34Z","isPatch":true,"body":"On 2026-09-07 at 21:12:10, Beat Bolli wrote:\n> Checking the certificate subject's common name may only be done if the\n> subjectAltNames extension contains no DNS entries. If no SAN DNS name\n> matches, there's no match.\n> \n> Per RFC 6125 section 6.4.4[1]:\n> \n>     As noted, a client MUST NOT seek a match for a reference identifier\n>     of CN-ID if the presented identifiers include a DNS-ID, SRV-ID,\n>     URI-ID, or any application-specific identifier types supported by the\n>     client.\n> \n> This change was inspired by a similar commit in the HAProxy project[2].\n\nTLS is not supposed to use the CN at all these days and Go's\nimplementation completely ignores it.  subjectAltName is supposed to be\nused in all cases.\n\n> diff --git a/imap-send.c b/imap-send.c\n> index 9a807cdde8..66d3dbfaa5 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -256,11 +256,11 @@ static int verify_hostname(X509 *cert, const char *hostname)\n>  #endif\n>  \tconst X509_NAME_ENTRY *cname_entry;\n>  \tconst ASN1_STRING *cname;\n> -\tint i, found;\n> +\tint i, found, has_san_dns;\n>  \tSTACK_OF(GENERAL_NAME) *subj_alt_names;\n>  \n>  \t/* try the DNS subjectAltNames */\n> -\tfound = 0;\n> +\tfound = has_san_dns = 0;\n>  \tif ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) {\n>  \t\tint num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names);\n>  \t\tfor (i = 0; !found && i < num_subj_alt_names; i++) {\n> @@ -268,13 +268,18 @@ static int verify_hostname(X509 *cert, const char *hostname)\n>  \t\t\tGENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);\n>  \t\t\tASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);\n>  \n> -\t\t\tif (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))\n> -\t\t\t\tfound = 1;\n> +\t\t\tif (ntype == GEN_DNS) {\n> +\t\t\t\thas_san_dns = 1;\n> +\t\t\t\tif (host_matches(hostname, subj_alt_str))\n> +\t\t\t\t\tfound = 1;\n> +\t\t\t}\n\nThis handles certificates with DNS names but not IP addresses.  So, for\ninstance, this match wouldn't work for the certificates for 1.1.1.1\n(assuming they had public IMAP service).\n\n>  \t\t}\n>  \t\tsk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);\n>  \t}\n>  \tif (found)\n>  \t\treturn 0;\n> +\tif (has_san_dns)\n> +\t\treturn error(\"none of the subjectAltNames matches hostname '%s'\", hostname);\n\nI know OpenSSL has built-in hostname verification that can be used as of\nOpenSSL 1.0.2[0].  Is there a reason we're still doing this by hand?\n\nRelying on OpenSSL's verification would mean that (a) we would not have\nto worry about getting verification wrong in a security-sensitive way\nand (b) OpenSSL would handle the policy and standards compliance\nfunctionality.\n\n[0] https://wiki.openssl.org/index.php/Hostname_validation\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"552182","messageId":"xmqqfqzkz8aq.fsf@gitster.g","threadId":"66288","inReplyTo":"20260907211210.2621693-2-dev+git@drbeat.li","subject":"Re: [PATCH 1/3] imap-send: prepare for OpenSSL 4.1","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-08T04:17:01Z","receivedAt":"2026-09-08T04:17:03Z","isPatch":true,"body":"Beat Bolli <dev+git@drbeat.li> writes:\n\n> OpenSSL master (to be v4.1 after the release) renamed the function\n> ASN1_STRING_length() to ASN1_STRING_get_length(). Map the new name to\n> the old one if we're compiling with a pre-4.1 version.\n>\n> Signed-off-by: Beat Bolli <dev+git@drbeat.li>\n> ---\n>  imap-send.c | 7 ++++++-\n>  1 file changed, 6 insertions(+), 1 deletion(-)\n>\n> diff --git a/imap-send.c b/imap-send.c\n> index 0d16d02029..977d78005c 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -219,12 +219,17 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,\n>  \n>  #else\n>  \n> +#if (OPENSSL_VERSION_NUMBER < 0x40100000L)\n> +// map to the pre-4.1 name\n\nStyle?\n\n> +#define ASN1_STRING_get_length(s) ASN1_STRING_length(s)\n> +#endif\n> +\n>  static int host_matches(const char *host, const ASN1_STRING *asn1_str)\n>  {\n>  \tconst char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);\n>  \n>  \t/* embedded NUL characters may open a security hole */\n> -\tif (memchr(pattern, '\\0', ASN1_STRING_length(asn1_str)))\n> +\tif (memchr(pattern, '\\0', ASN1_STRING_get_length(asn1_str)))\n>  \t    return 0;\n>  \n>  \tif (pattern[0] == '*' && pattern[1] == '.') {\n"},{"id":"552189","messageId":"ap_GvB8Lonkn0nEy@pks.im","threadId":"66288","inReplyTo":"20260907211210.2621693-2-dev+git@drbeat.li","subject":"Re: [PATCH 1/3] imap-send: prepare for OpenSSL 4.1","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-09-08T08:26:36Z","receivedAt":"2026-09-08T08:26:42Z","isPatch":true,"body":"On Mon, Sep 07, 2026 at 11:12:08PM +0200, Beat Bolli wrote:\n> OpenSSL master (to be v4.1 after the release) renamed the function\n> ASN1_STRING_length() to ASN1_STRING_get_length(). Map the new name to\n> the old one if we're compiling with a pre-4.1 version.\n\nI can see [1] that the new functions indeed exist now. But it doesn't\nsay anything about the old functions, they still exist and don't seem to\nbe deprecated. So why do we even have to switch to the new function?\n\nPatrick\n\n[1]: https://docs.openssl.org/master/man3/ASN1_STRING_length/\n"},{"id":"552190","messageId":"ap_Gwx4g7t0vjsj2@pks.im","threadId":"66288","inReplyTo":"20260907211210.2621693-3-dev+git@drbeat.li","subject":"Re: [PATCH 2/3] imap-send: don't expect an ASN1_STRING to be NUL-terminated","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-09-08T08:26:43Z","receivedAt":"2026-09-08T08:26:47Z","isPatch":true,"body":"On Mon, Sep 07, 2026 at 11:12:09PM +0200, Beat Bolli wrote:\n> diff --git a/imap-send.c b/imap-send.c\n> index 977d78005c..9a807cdde8 100644\n> --- a/imap-send.c\n> +++ b/imap-send.c\n> @@ -226,20 +226,25 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,\n>  \n>  static int host_matches(const char *host, const ASN1_STRING *asn1_str)\n>  {\n> -\tconst char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);\n> +\tint ret = 0;\n> +\tsize_t len = ASN1_STRING_get_length(asn1_str);\n> +\tchar *pattern = xmemdupz(ASN1_STRING_get0_data(asn1_str), len);\n>  \n>  \t/* embedded NUL characters may open a security hole */\n> -\tif (memchr(pattern, '\\0', ASN1_STRING_get_length(asn1_str)))\n> -\t    return 0;\n> +\tif (memchr(pattern, '\\0', len))\n> +\t    goto out;\n>  \n>  \tif (pattern[0] == '*' && pattern[1] == '.') {\n>  \t\tpattern += 2;\n>  \t\tif (!(host = strchr(host, '.')))\n> -\t\t\treturn 0;\n> +\t\t\tgoto out;\n>  \t\thost++;\n>  \t}\n>  \n> -\treturn *host && *pattern && !strcasecmp(host, pattern);\n> +\tret = *host && *pattern && !strcasecmp(host, pattern);\n> +out:\n> +\tfree(pattern);\n> +\treturn ret;\n>  }\n\nI don't quite see a reason why we even have to memdup the string. We\nalready use memchr, which is bounded by the length of the string. We do\nhave two other sites though:\n\n  - We use strchr, but that can be adapted to use memchr.\n\n  - Likewise, we use strcasecmp, but that can be adapted to use\n    strncasecmp.\n\nSo with that, all calls that inspect the string would be bounded by the\nlength of the encoded string, and that means we don't have to copy the\nstring first, do we?\n\nPatrick\n"},{"id":"552685","messageId":"872286d0-7786-46cc-b26f-16f6d487e608@drbeat.li","threadId":"66288","inReplyTo":"ap_GvB8Lonkn0nEy@pks.im","subject":"Re: [PATCH 1/3] imap-send: prepare for OpenSSL 4.1","fromName":"Beat Bolli","fromEmail":"dev+git@drbeat.li","sentAt":"2026-09-14T09:10:36Z","receivedAt":"2026-09-14T09:23:40Z","isPatch":true,"body":"Hi Patrick\n\nOn 08.09.2026 10:26, Patrick Steinhardt wrote:\n> On Mon, Sep 07, 2026 at 11:12:08PM +0200, Beat Bolli wrote:\n>> OpenSSL master (to be v4.1 after the release) renamed the function\n>> ASN1_STRING_length() to ASN1_STRING_get_length(). Map the new name to\n>> the old one if we're compiling with a pre-4.1 version.\n> \n> I can see [1] that the new functions indeed exist now. But it doesn't\n> say anything about the old functions, they still exist and don't seem to\n> be deprecated. So why do we even have to switch to the new function?\n> \n\nThe very page you give below contains this text:\n\n---- 8< ----\nThe following functions have been deprecated since OpenSSL 4.1, and can \nbe hidden entirely by defining OPENSSL_API_COMPAT with a suitable \nversion value, see openssl_user_macros(7):\n\nint ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);\nint ASN1_STRING_length(ASN1_STRING *x);\n---- 8< ----\n\nWe also don't define any compatibility macros for OpenSSL, and the build \nfailed because of the deprecation warning that was turned into an error \nbecause of DEVELOPER=1.\n\nSo I still think this patch is needed.\n\nBeat\n\n> [1]: https://docs.openssl.org/master/man3/ASN1_STRING_length/\n\n"},{"id":"553043","messageId":"arPG2yDxeVTPwpTg@pks.im","threadId":"66288","inReplyTo":"872286d0-7786-46cc-b26f-16f6d487e608@drbeat.li","subject":"Re: [PATCH 1/3] imap-send: prepare for OpenSSL 4.1","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-09-23T12:32:27Z","receivedAt":"2026-09-23T12:32:38Z","isPatch":true,"body":"On Mon, Sep 14, 2026 at 11:10:36AM +0200, Beat Bolli wrote:\n> Hi Patrick\n> \n> On 08.09.2026 10:26, Patrick Steinhardt wrote:\n> > On Mon, Sep 07, 2026 at 11:12:08PM +0200, Beat Bolli wrote:\n> > > OpenSSL master (to be v4.1 after the release) renamed the function\n> > > ASN1_STRING_length() to ASN1_STRING_get_length(). Map the new name to\n> > > the old one if we're compiling with a pre-4.1 version.\n> > \n> > I can see [1] that the new functions indeed exist now. But it doesn't\n> > say anything about the old functions, they still exist and don't seem to\n> > be deprecated. So why do we even have to switch to the new function?\n> > \n> \n> The very page you give below contains this text:\n> \n> ---- 8< ----\n> The following functions have been deprecated since OpenSSL 4.1, and can be\n> hidden entirely by defining OPENSSL_API_COMPAT with a suitable version\n> value, see openssl_user_macros(7):\n> \n> int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);\n> int ASN1_STRING_length(ASN1_STRING *x);\n> ---- 8< ----\n> \n> We also don't define any compatibility macros for OpenSSL, and the build\n> failed because of the deprecation warning that was turned into an error\n> because of DEVELOPER=1.\n\nAh, I missed the part about OPENSSL_API_COMPAT. I think it would make\nsense to explicitly point that out in the commit message. Thanks!\n\nPatrick\n"}]}