Skip to content

Fix ntlm feature broken by libcurl 8.20's NTLM opt-in flip - #665

Open
ns-ylambert wants to merge 1 commit into
sagebind:mainfrom
ns-ylambert:fix-ntlm-enable
Open

ns-ylambert wants to merge 1 commit into
sagebind:mainfrom
ns-ylambert:fix-ntlm-enable

Conversation

@ns-ylambert

@ns-ylambert ns-ylambert commented Oct 1, 2026 •

Copy link
Copy Markdown

Summary

libcurl 8.20 (released 2026-04-29) flipped NTLM from opt-out to opt-in behind CURL_ENABLE_NTLM (curl/curl#20698, commit cc0c83c5f853). curl-sys picked up the libcurl bump in #649 (2026-05-01) but didn't propagate the opt-in contract: the ntlm cargo feature (introduced by #428, commit f0bbf37241e2) still only compiles the NTLM source files. From curl-sys 0.4.90+curl-8.20.0 onward, --features curl-sys/ntlm builds cleanly but exports zero NTLM symbols: the feature silently does nothing at runtime.

Fix

curl-sys/build.rs, inside the if cfg!(feature = "ntlm") { ... } block:

  • Add .define("CURL_ENABLE_NTLM", None): the macro libcurl now requires to activate NTLM.
  • Drop the else-branch defining CURL_DISABLE_NTLM: same curl PR that flipped the gate removed every reference to that macro from libcurl's source, docs, cmake, and configure logic; it's dead.

Cross-platform (not target-scoped): whoever activates curl-sys/ntlm opts in on any platform.

Also adds a regression test in src/lib.rs's mod tests: is_ntlm_support_activated asserts Version::feature_ntlm() == true when the crate's ntlm feature is enabled. Fails on any curl-sys 0.4.90+curl-8.20.0 or later without this fix.

Verification

  • cargo check -p curl-sys --features static-curl,ntlm --target x86_64-pc-windows-msvc succeeds; the resulting binary now contains NTLM symbols.
  • cargo test --features static-curl,ntlm --target x86_64-pc-windows-msvc is_ntlm_support_activated → test tests::is_ntlm_support_activated ... ok.
  • Existing CI matrix passes unchanged.

Note on CI coverage of the regression test

ci/run.sh currently compiles the new test in the --no-run pass at line 36 (cargo test --no-run --features static-curl,protocol-ftp,ntlm) but does not execute it. No line in the if [ -z "$NO_RUN" ] block enables --features ntlm. Adding

cargo test --target $TARGET --features static-curl,ntlm $features

around line 41 would promote the test from a compile-verified reproducer to a CI-executed guard against future regressions of the same class. Kept out of this PR to keep the diff minimal; happy to add if desired.

Related

  • Fixes the modern manifestation of NTLM authentication on Windows does not work #359 ("NTLM authentication on Windows does not work"). Original cause in 2023 was different — the reporter hadn't enabled --features ntlm at all — but the same runtime error ("A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision") now hits users who correctly enable the feature but are on curl-sys 0.4.90+curl-8.20.0 or later.
  • Regression landed in Update curl to 8.20.0 #649 (2026-05-01, the curl 8.20 bump). The PR body flagged NTLM's uncertain future ("the next release will likely remove NTLM") but missed that 8.20 itself had already flipped the gate to opt-in.

libcurl 8.20 (released 2026-04-29) flipped NTLM to opt-in behind
`CURL_ENABLE_NTLM` (curl/curl#20698, commit [`cc0c83c5f853`]).
In `lib/curl_setup.h`:

    /* Single point where USE_NTLM definition might be defined */
   -#ifndef CURL_DISABLE_NTLM
   +#ifdef CURL_ENABLE_NTLM

The change was security-driven (weak auth, no HTTP/2/3 support). Same PR also
removed every reference to `CURL_DISABLE_NTLM` from libcurl's source, docs,
CMake, and configure logic. **The old opt-out symbol was retired entirely**.

curl-sys did not propagate the change downstream: the `ntlm` cargo feature
(sagebind#428, commit [`f0bbf37241e2`]) still only compiles NTLM
source files. Else-branch defines `CURL_DISABLE_NTLM`, which is now dead code.
The `.define("CURL_ENABLE_NTLM", None)` that the opt-in contract now requires
was never added.

Result: from curl-sys 0.4.90+curl-8.20.0 onward (released 2026-05-01),
`--features curl-sys/ntlm` compiles the NTLM sources but exports zero NTLM
symbols, so the feature does nothing.

Two edits, cross-platform (whoever activates `curl-sys/ntlm` opts in on any
platform):

- Add `.define("CURL_ENABLE_NTLM", None)` alongside the existing NTLM
  `.file(...)` calls so the feature does what it advertises again.

- Drop the now-dead `else { cfg.define("CURL_DISABLE_NTLM", None); }` branch.

Plus, a regression test in `src/lib.rs`'s `mod tests` asserting that
`Version::feature_ntlm()` is `true` when the `ntlm` feature is enabled.

[`cc0c83c5f853`]: curl/curl@cc0c83c5f853
[`f0bbf37241e2`]: sagebind@f0bbf37241e2
@ns-ylambert

Copy link
Copy Markdown
Author

Rebased onto current main (curl 8.22.0); CI green. This is the first of a four-part series (#665, #666, #667, #668) fixing windows-static-ssl and restoring SSPI on non-Schannel backends (each PR is kept independent from others).

Ready for review whenever you have a moment, happy to restructure if a different split is easier.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant