From 2a92c39a218713635768364f801fa13831a019e0 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 12 Feb 2026 00:33:20 +0100 Subject: [PATCH] windows: tidy up `wincrypt.h` / BoringSSL/AWS-LC coexist workaround - openssl: move and expand explanatory comment. - openssl: drop duplicate workaround. - schannel: drop workaround. Unnecessary, because OpenSSL headers are not included in or after schannel code. - schannel: drop explicit `wincrypt.h` include. It's indirectly included by system ``. - ldap: drop explicit `wincrypt.h` include. It isn't used there, and also not required for the workaround. `winldap.h` keeps including it indirectly. Tested with BoringSSL and AWS-LC (MultiSSL with Schannel), also LDAP enabled, and H3, unity and non-unity, and all tested cases build fine. In lib in general, the point is to have the `#undef`s between the first `wincrypt.h` include [1] and the first OpenSSL include [2], within a single compilation unit. For non-unity builds the only such source is `openssl.c`. For unity ones, depending on batch size, in theory we should `#undef` after each `wincrypt.h` include. In practice this is overkill and most cases are covered by `#undef`-fing _first_ in `vtls/openssl.c`, and `#undef` in `ldap.c`. It's not impossible that we need to add more undefs after further `wincrypt.h` includes to cover so far undiscovered build cases [3]. Though I could not find more with the current sources and source order. It's also an option to include OpenSSL first, then `wincrypt.h`, as done in libtests, but for lib and `vtls/openssl.c` it's more practical to do the opposite. [1] can be indirect, e.g. via `iphlpapi.h`, `schannel.h`, `winldap.h`. [2] in - BoringSSL/AWS-LC: any include (due to `openssl/base.h`). Original fix removed by BoringSSL in year [2014](https://github.com/google/boringssl/commit/ded93581f1674f81faa0dba4b15a842756066ab2#diff-878093ea6426091505b4c49c59b78924f42859af0eb4ce39b8089bda9577e013). - OpenSSL: `openssl/ssl.h`, `openssl/x509v3.h`, and some more affected, and including `openssl/ossl_typ.h` does the `#undef` automatically. Since [3.1.0+](https://github.com/openssl/openssl/commit/fbb9a1f99713b5277d5658963c1706069061e015) each inclusion does the `#undef`, in 3.0.x (and earlier) only the first inclusion did. Initially fixed in [0.9.6d](https://github.com/openssl/openssl/commit/1955b8742354a989650853412c27863f1644e81d) - LibreSSL [2.3.0+](https://github.com/libressl/portable/commit/0fa826d34f42ecd0932aaf48012ca9165ac1612b): not affected, though to suppress another warning 3.8.2+ and a [define](https://github.com/libressl/portable/commit/e7fe6caab2869a043514c297ce04e6995a65d79f) is necessary. [3] `lib/Makefile.inc` defines the order of unity sources. For libtests, the case is simpler: There is always one compilation unit, with a fixed order, and at the moment `cli_hx_download.c` is including OpenSSL first, then wincrypt, and in this order they don't bother each other. Also, at the moment `lib758.c` is the only other OpenSSL header user, but it's compiled after `cli_hx_download.c` so the include is skipped there. We may need to revisit this if either header gets included before it. All this said it'd be nice if BoringSSL/AWS-LC restored the built-in workaround to behave like LibreSSL and OpenSSL and not require local workarounds like these. Ref: https://github.com/curl/curl/pull/20556#issuecomment-3888425644 Follow-up to 4c46c829f5ed7c37b3313c67a6662b7332c1ff7f #9110 Follow-up to fbe07c6829ba8c5793c84c2856526e19e9029ab9 #5669 #5857 Closes #20567 --- lib/ldap.c | 11 +++-------- lib/vtls/openssl.c | 25 +++++++++++++++++++++++-- lib/vtls/schannel.h | 31 ------------------------------- 3 files changed, 26 insertions(+), 41 deletions(-) diff --git a/lib/ldap.c b/lib/ldap.c index 046fcd48e8..e0da4a0776 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -43,20 +43,15 @@ * OpenLDAP library versions, USE_OPENLDAP shall not be defined. */ -/* Wincrypt must be included before anything that could include OpenSSL. */ -#ifdef USE_WIN32_CRYPTO -#include -/* Undefine wincrypt conflicting symbols for BoringSSL. */ +#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ +# include +/* Undefine indirect symbols conflicting with BoringSSL. */ #undef X509_NAME #undef X509_EXTENSIONS #undef PKCS7_ISSUER_AND_SERIAL #undef PKCS7_SIGNER_INFO #undef OCSP_REQUEST #undef OCSP_RESPONSE -#endif - -#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */ -# include # include #else # define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index a632e80943..0834109ae7 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -29,10 +29,31 @@ #if defined(USE_QUICHE) || defined(USE_OPENSSL) -/* Wincrypt must be included before anything that could include OpenSSL. */ #ifdef USE_WIN32_CRYPTO #include -/* Undefine wincrypt conflicting symbols for BoringSSL. */ +/* If is included directly, or indirectly via , + * , , or something else, does this: + * #define X509_NAME ((LPCSTR)7) + * + * And in BoringSSL/AWC-LC's there is: + * typedef struct X509_name_st X509_NAME; + * etc. + * + * The redefined symbols break these OpenSSL headers when included after + * . + * The workaround is to undefine those defines here (and only here). + * + * For unity builds it may need to be repeated elsewhere too, e.g. in ldap.c, + * to apply to other sources using OpenSSL includes. Each compilation unit + * needs undefine them between the first include and the first + * OpenSSL include. + * + * OpenSSL does this in and , but it + * also does the #undef by including . <3.1.0 only does + * it on the first include. + * + * LibreSSL automatically undefines these symbols before using them. + */ #undef X509_NAME #undef X509_EXTENSIONS #undef PKCS7_ISSUER_AND_SERIAL diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h index c617233e08..78db502b9e 100644 --- a/lib/vtls/schannel.h +++ b/lib/vtls/schannel.h @@ -28,43 +28,12 @@ #ifdef USE_SCHANNEL -/* Wincrypt must be included before anything that could include OpenSSL. */ -#ifdef USE_WIN32_CRYPTO -#include -/* Undefine wincrypt conflicting symbols for BoringSSL. */ -#undef X509_NAME -#undef X509_EXTENSIONS -#undef PKCS7_ISSUER_AND_SERIAL -#undef PKCS7_SIGNER_INFO -#undef OCSP_REQUEST -#undef OCSP_RESPONSE -#endif - #include #include "../curl_sspi.h" #include "../cfilters.h" #include "../urldata.h" -/* has been included via the above . - * Or in case of ldap.c, it was included via . - * And since has this: - * #define X509_NAME ((LPCSTR)7) - * - * And in BoringSSL's there is: - * typedef struct X509_name_st X509_NAME; - * etc. - * - * this will cause all kinds of C-preprocessing paste errors in - * BoringSSL's : So just undefine those defines here - * (and only here). - */ -#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) -#undef X509_NAME -#undef X509_CERT_PAIR -#undef X509_EXTENSIONS -#endif - extern const struct Curl_ssl Curl_ssl_schannel; CURLcode Curl_verify_host(struct Curl_cfilter *cf, struct Curl_easy *data);