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 `<schannel.h>`.

- 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](ded93581f1 (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+](fbb9a1f997)
  each inclusion does the `#undef`, in 3.0.x (and earlier) only
  the first inclusion did. Initially fixed in
  [0.9.6d](1955b87423)
- LibreSSL [2.3.0+](0fa826d34f):
  not affected, though to suppress another warning 3.8.2+ and
  a [define](e7fe6caab2)
  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 4c46c829f5 #9110
Follow-up to fbe07c6829 #5669 #5857

Closes #20567
This commit is contained in:
Viktor Szakats 2026-02-12 00:33:20 +01:00
parent 208b2e8975
commit 2a92c39a21
No known key found for this signature in database
3 changed files with 26 additions and 41 deletions

View file

@ -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 <wincrypt.h>
/* Undefine wincrypt conflicting symbols for BoringSSL. */
#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
# include <winldap.h>
/* Undefine indirect <wincrypt.h> 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 <winldap.h>
# include <winber.h>
#else
# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */

View file

@ -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 <wincrypt.h>
/* Undefine wincrypt conflicting symbols for BoringSSL. */
/* If <wincrypt.h> is included directly, or indirectly via <schannel.h>,
* <winldap.h>, <iphlpapi.h>, or something else, <wincrypt.h> does this:
* #define X509_NAME ((LPCSTR)7)
*
* And in BoringSSL/AWC-LC's <openssl/base.h> there is:
* typedef struct X509_name_st X509_NAME;
* etc.
*
* The redefined symbols break these OpenSSL headers when included after
* <wincrypt.h>.
* 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 <wincrypt.h> include and the first
* OpenSSL include.
*
* OpenSSL does this in <openssl/ssl.h> and <openssl/x509v3.h>, but it
* also does the #undef by including <openssl/ossl_typ.h>. <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

View file

@ -28,43 +28,12 @@
#ifdef USE_SCHANNEL
/* Wincrypt must be included before anything that could include OpenSSL. */
#ifdef USE_WIN32_CRYPTO
#include <wincrypt.h>
/* 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 <schannel.h>
#include "../curl_sspi.h"
#include "../cfilters.h"
#include "../urldata.h"
/* <wincrypt.h> has been included via the above <schannel.h>.
* Or in case of ldap.c, it was included via <winldap.h>.
* And since <wincrypt.h> has this:
* #define X509_NAME ((LPCSTR)7)
*
* And in BoringSSL's <openssl/base.h> there is:
* typedef struct X509_name_st X509_NAME;
* etc.
*
* this will cause all kinds of C-preprocessing paste errors in
* BoringSSL's <openssl/x509.h>: 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);