Skip to content

schannel: fix ALPN erroneously disabled - #22746

Closed
jay wants to merge 1 commit into
curl:masterfrom
jay:win32_version_fix
Closed

jay wants to merge 1 commit into
curl:masterfrom
jay:win32_version_fix

Conversation

@jay

@jay jay commented Aug 30, 2026

Copy link
Copy Markdown
Member
  • In easy.c global_init, initialize win32 before ssl.

Schannel SSL init depends on win32 initialization.

Prior to this change applications with no compatibility manifest using a libcurl with Schannel had ALPN erroneously disabled. During Schannel init there is a version info check so that ALPN is only enabled for Windows 8.1 or later (>= NT 6.3), but since win32 was not yet initialized the version check would fail even if the OS was more recent.

This change ensures that the pointer to function RtlVerifyVersionInfo is initialized before SSL initialization so that version checks during SSL initialization do not use VerifyVersionInfo as a fallback.

On Windows RtlVerifyVersionInfo compares against the actual OS version info whereas VerifyVersionInfo has behavior that varies depending on whether the application (eg curl tool) has a compatibility manifest. If there is no manifest, VerifyVersionInfo treats the OS version to compare against as Windows 8 (NT 6.2) even on later versions.

So basically NT 6.2 < NT 6.3 caused ALPN to be erroneously disabled.

Reported-by: Jay Satiro

Ref: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-verifyversioninfoa

Fixes #22739 (comment)
Closes #xxxx

- In easy.c global_init, initialize win32 before ssl.

Schannel SSL init depends on win32 initialization.

Prior to this change applications with no compatibility manifest using a
libcurl with Schannel had ALPN erroneously disabled. During Schannel
init there is a version info check so that ALPN is only enabled for
Windows 8.1 or later (>= NT 6.3), but since win32 was not yet
initialized the version check would fail even if the OS was more recent.

This change ensures that the pointer to function RtlVerifyVersionInfo
is initialized before SSL initialization so that version checks during
SSL initialization do not use VerifyVersionInfo as a fallback.

On Windows RtlVerifyVersionInfo compares against the actual OS version
info whereas VerifyVersionInfo has behavior that varies depending on
whether the application (eg curl tool) has a compatibility manifest. If
there is no manifest, VerifyVersionInfo treats the OS version to compare
against as Windows 8 (NT 6.2) even on later versions.

So basically NT 6.2 < NT 6.3 caused ALPN to be erroneously disabled.

Ref: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-verifyversioninfoa

Fixes curl#22739 (comment)
Closes #xxxx

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes Schannel ALPN detection by initializing Windows version APIs before TLS initialization.

Changes:

  • Moves Win32 initialization ahead of SSL initialization.
  • Ensures Schannel checks the actual Windows version.
File summaries
File Description
lib/easy.c Reorders global Win32 initialization.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/easy.c
Comment on lines +139 to +142
if(Curl_win32_init(flags)) {
DEBUGF(curl_mfprintf(stderr, "Error: win32_init failed\n"));
goto fail;
}

@vszakats vszakats Aug 30, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general issue is valid, but the actual case is theoretical,
and a non-issue in practice, according to in-source comments:
In supported Windows versions winsock.dll is always present
and its version is always 2.2+. Perhaps this check (and the
failure modes) could be dropped for clarity.

edit: this can still make init fail due to InitSecurityInterface()
failing via Curl_sspi_global_init().

Ref: https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup

@vszakats vszakats Aug 30, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out WSA init can also fail due to network subsystem not yet initialized or internal limits reached,
so an init failure cannot be completely ruled out unfortunately.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempt to fix this and some other related cases: #22756

@vszakats

Copy link
Copy Markdown
Member

Thanks @jay, merged now!

@jay
jay deleted the win32_version_fix branch September 1, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

3 participants