From 925a4bac34ac72243fd80ad0d5f6ee735e91cb22 Mon Sep 17 00:00:00 2001 From: ns-ylambert Date: Wed, 30 Sep 2026 17:27:20 +0200 Subject: [PATCH 1/2] curl-sys: fix spnego + rustls compile error on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upstream `spnego` feature defined `USE_SPNEGO` unconditionally on all platforms, including Windows. On Windows, `USE_SPNEGO` activates code in `http_negotiate.c` that references `struct negotiatedata::context` (a field only defined when `USE_WINDOWS_SSPI` is present). Under the `rustls` or `windows-static-ssl` TLS backends, `USE_WINDOWS_SSPI` is not defined, causing `C2039 'context' is not a member of 'negotiatedata'` errors. Fix: guard the `USE_SPNEGO` define to non-Windows only. On Windows, `curl_setup.h` auto-defines `USE_SPNEGO` from `USE_WINDOWS_SSPI` whenever that is set. `http_negotiate.c` is still compiled on Windows when `spnego` is requested (it contains valid stub paths for non-SSPI builds), but without `USE_SPNEGO` the `context`-field access at line 203 is inside a dead `#ifdef` block. `spnego_sspi.c` genuinely requires `USE_WINDOWS_SSPI` to compile (it is a Windows-SSPI-specific file). Introduce `windows_sspi` — true when `ssl` / Schannel is the active backend on Windows — and gate `spnego_sspi.c` exclusively on it. Summary of SPNEGO source gating after this commit: - `USE_SPNEGO` define: non-Windows `spnego` only. - `http_negotiate.c`: `windows_sspi` OR `spnego` (any platform/backend). - `spnego_sspi.c`: `windows_sspi` only. Also removes the duplicate `http_negotiate.c` / `spnego_sspi.c` / `vauth.c` entries from the Schannel per-backend block (`vauth.c` is already in the unconditional base source set). --- curl-sys/build.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/curl-sys/build.rs b/curl-sys/build.rs index 7d028d410..3e93f3bff 100644 --- a/curl-sys/build.rs +++ b/curl-sys/build.rs @@ -342,12 +342,6 @@ fn main() { cfg.include(path); } - if cfg!(feature = "spnego") { - cfg.define("USE_SPNEGO", None) - .file("curl/lib/http_negotiate.c") - .file("curl/lib/vauth/vauth.c"); - } - // Configure TLS backend. Since Cargo does not support mutually exclusive // features, make sure we only compile one vtls. if cfg!(feature = "rustls") { @@ -382,12 +376,9 @@ fn main() { // Please see definition of USE_SPNEGO in curl_setup.h for more info. cfg.define("USE_WINDOWS_SSPI", None) .define("USE_SCHANNEL", None) - .file("curl/lib/http_negotiate.c") .file("curl/lib/curl_sspi.c") .file("curl/lib/socks_sspi.c") .file("curl/lib/vauth/krb5_sspi.c") - .file("curl/lib/vauth/spnego_sspi.c") - .file("curl/lib/vauth/vauth.c") .file("curl/lib/vtls/schannel.c") .file("curl/lib/vtls/schannel_verify.c") .file("curl/lib/vtls/x509asn1.c"); @@ -407,6 +398,25 @@ fn main() { } } + // `USE_WINDOWS_SSPI` unconditionally triggers `USE_SPNEGO` in + // `curl_setup.h`, which causes `http.c` (always compiled) to reference + // symbols from `http_negotiate.c` and `spnego_sspi.c`. Those files must + // therefore be compiled whenever `windows_sspi` is true, regardless of + // whether the `spnego` cargo feature was explicitly requested. + let windows_sspi = windows + && cfg!(feature = "ssl") + && !cfg!(any(feature = "rustls", feature = "windows-static-ssl")); + + if !windows && cfg!(feature = "spnego") { + cfg.define("USE_SPNEGO", None); + } + if windows_sspi || cfg!(feature = "spnego") { + cfg.file("curl/lib/http_negotiate.c"); + } + if windows_sspi { + cfg.file("curl/lib/vauth/spnego_sspi.c"); + } + // Configure platform-specific details. if windows { cfg.define("HAVE_CONFIG_H", None) @@ -421,10 +431,6 @@ fn main() { .file("curl/lib/curlx/multibyte.c") .file("curl/lib/curlx/version_win32.c") .file("curl/lib/curlx/winapi.c"); - - if cfg!(feature = "spnego") { - cfg.file("curl/lib/vauth/spnego_sspi.c"); - } } else { cfg.define("RECV_TYPE_ARG1", "int") .define("HAVE_PTHREAD_H", None) From e18f765ff0878747c9956c03b92cce62f9a5e7c7 Mon Sep 17 00:00:00 2001 From: ns-ylambert Date: Wed, 30 Sep 2026 17:28:42 +0200 Subject: [PATCH 2/2] curl-sys: compile Windows SSPI in the rustls/windows-static-ssl branches The SSPI infrastructure (`curl_sspi.c`, `socks_sspi.c`, `vauth/krb5_sspi.c`) and `USE_WINDOWS_SSPI` are compiled only under `feature = "ssl"` on Windows, which also enables Schannel. A `rustls` (curl+rustls-ffi) or `windows-static-ssl` (curl+OpenSSL) build therefore silently loses libcurl's SSPI-backed integrated Windows authentication (NTLM-SSO / Negotiate-SSO), even though SSPI is TLS-backend-independent at the C level. Add `USE_WINDOWS_SSPI` and the same three SSPI infrastructure files to the `rustls` / `windows-static-ssl` branches on Windows, without `USE_SCHANNEL` or the Schannel-only sources (`schannel.c`, `schannel_verify.c`). Also widen the `windows_sspi` guard (introduced by the companion "fix spnego + rustls" commit) from `ssl`-only to cover both `rustls` and `windows-static-ssl`, so the shared SPNEGO sources (`http_negotiate.c`, `vauth/spnego_sspi.c`) are compiled for all three Windows TLS backends (OpenSSL / Rustls / Schannel). --- curl-sys/build.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/curl-sys/build.rs b/curl-sys/build.rs index 3e93f3bff..b4ad9707d 100644 --- a/curl-sys/build.rs +++ b/curl-sys/build.rs @@ -374,11 +374,7 @@ fn main() { if windows { // For windows, spnego feature is auto on in case ssl feature is on. // Please see definition of USE_SPNEGO in curl_setup.h for more info. - cfg.define("USE_WINDOWS_SSPI", None) - .define("USE_SCHANNEL", None) - .file("curl/lib/curl_sspi.c") - .file("curl/lib/socks_sspi.c") - .file("curl/lib/vauth/krb5_sspi.c") + cfg.define("USE_SCHANNEL", None) .file("curl/lib/vtls/schannel.c") .file("curl/lib/vtls/schannel_verify.c") .file("curl/lib/vtls/x509asn1.c"); @@ -398,14 +394,19 @@ fn main() { } } + // Compile Windows SSPI alongside any TLS backend so libcurl's integrated + // Windows authentication (NTLM/Negotiate) stays available. // `USE_WINDOWS_SSPI` unconditionally triggers `USE_SPNEGO` in // `curl_setup.h`, which causes `http.c` (always compiled) to reference // symbols from `http_negotiate.c` and `spnego_sspi.c`. Those files must // therefore be compiled whenever `windows_sspi` is true, regardless of // whether the `spnego` cargo feature was explicitly requested. let windows_sspi = windows - && cfg!(feature = "ssl") - && !cfg!(any(feature = "rustls", feature = "windows-static-ssl")); + && cfg!(any( + feature = "ssl", + feature = "rustls", + feature = "windows-static-ssl" + )); if !windows && cfg!(feature = "spnego") { cfg.define("USE_SPNEGO", None); @@ -414,7 +415,11 @@ fn main() { cfg.file("curl/lib/http_negotiate.c"); } if windows_sspi { - cfg.file("curl/lib/vauth/spnego_sspi.c"); + cfg.define("USE_WINDOWS_SSPI", None) + .file("curl/lib/curl_sspi.c") + .file("curl/lib/socks_sspi.c") + .file("curl/lib/vauth/krb5_sspi.c") + .file("curl/lib/vauth/spnego_sspi.c"); } // Configure platform-specific details.