Uh oh!
There was an error while loading. Please reload this page.
Work around Schannel TLS resume disable race on older Windows - #126693
Conversation
On Windows Server 2022 (build 20348) and older, ApplyControlToken with SSL_SESSION_DISABLE_RECONNECTS races with Schannel's internal session cache. ISC's LookupCacheByName finds a fresh resumable entry and embeds the session ID in the ClientHello before ApplyControlToken can expire it. Work around by following the pattern used by Schannel's own webcli.c test and http.sys: after ApplyControlToken, delete the security context and retry InitializeSecurityContext with a null context so the new ClientHello is generated without a stale session ID. The workaround is conditioned on build < 22000 (pre-Windows 11), since newer Schannel builds correctly prevent cache population when ApplyControlToken is used. Also re-enables the ClientDisableTlsResume_Succeeds test that was disabled due to this issue. Fixesdotnet#103449 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones |
There was a problem hiding this comment.
Pull request overview
Works around a Schannel race on older Windows builds where disabling TLS resumption via ApplyControlToken(SSL_SESSION_DISABLE_RECONNECTS) can still result in a resumable session ID being embedded into the initial ClientHello, causing unexpected resumption.
Changes:
- Add a Windows build-gated workaround that disposes the security context after
ApplyControlTokenand retriesInitializeSecurityContextto regenerateClientHellowithout a stale session ID. - Re-enable the previously disabled
ClientDisableTlsResume_Succeedstest on Windows by removing theActiveIssueannotation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs | Implements the context-delete + retry workaround for pre-22000 Windows builds after ApplyControlToken succeeds. |
src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAllowTlsResumeTests.cs | Removes the Windows ActiveIssue guard to run the TLS resume disable test again. |
Uh oh!
There was an error while loading. Please reload this page.
Move the ApplyControlToken/workaround block before the consumed/ SECBUFFER_EXTRA check so both the normal and retry paths share it. Reuse the original inputBuffers for the retry since this only runs on the very first ISC call (newContext == true) where the input is empty and the buffers are unmodified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
ApplyControlToken takes 'ref context' which makes the compiler lose the null-state guarantee from the outer 'context != null' check. Use context?.Dispose() to satisfy nullable analysis. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rzikm
commented
Apr 13, 2026
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
wfurt
left a comment
There was a problem hiding this comment.
nice. I'm glad we are able to make it stable (hopefully)
rzikm
commented
Apr 14, 2026
/ba-g test failures are unrelated |
Summary
On Windows Server 2022 (build 20348) and older,
ApplyControlToken(SSL_SESSION_DISABLE_RECONNECTS)races with Schannel's internal session cache —InitializeSecurityContext's internalLookupCacheByNamefinds a fresh resumable entry and embeds the session ID in theClientHellobeforeApplyControlTokencan expire it.Workaround
After
ApplyControlToken, delete the security context and retryInitializeSecurityContextwith a null context so the newClientHellois generated without a stale session ID. This follows the same pattern used by Schannel's ownwebcli.ctest andhttp.sys.The workaround is conditioned on
Environment.OSVersion.Version.Build < 22000(pre-Windows 11), since newer Schannel builds correctly prevent cache population whenApplyControlTokenis used.Also re-enables the
ClientDisableTlsResume_Succeedstest that was disabled due to this issue.Fixes#103449