Skip to content

Fix incorrect buffer reallocation in AcceptSecurityContext #72184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 14, 2022

Conversation

filipnavara
Copy link
Member

Fixes #72152

@ghost ghost added area-System.Net.Security community-contribution Indicates that the PR has been added by a community member labels Jul 14, 2022
@ghost
Copy link

ghost commented Jul 14, 2022

Tagging subscribers to this area: @dotnet/ncl, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #72152

Author: filipnavara
Assignees: -
Labels:

area-System.Net.Security

Milestone: -

@filipnavara filipnavara requested a review from stephentoub July 14, 2022 14:23
@stephentoub
Copy link
Member

Can you help me understand what the issue was and why this fixes it? Thanks!

@filipnavara
Copy link
Member Author

filipnavara commented Jul 14, 2022

Can you help me understand what the issue was and why this fixes it?

There are multiple implementation of AcceptSecurityContext in Windows API.

The one used in TLS negotiations ("Schannel" in the MSDN documentation) gets empty buffers to start with and a flag that tells the native code to allocate all the buffers with appropriate size. You get back the allocated buffers. These have to be copied and returned as new byte[] array to caller.

When doing Negotiate authentication through the AcceptSecurityContext API it behaves differently. The caller provides a pre-allocated buffer and the same buffer is echoed in the output along with the actual length of the data that was written into the buffer.

There's only single managed wrapper for AcceptSecurityContext that handles both situations. In the context of Negotiate authentication it incorrectly ignored the allocation flag and created a copy of the data in the output buffer into a new byte[] array. The size of this array matches the size of the first authentication token.

There was an assumption that on Windows the subsequent call to AcceptSecurityContext from NegotiateAuthentication will reuse the same buffer that is guaranteed to be big enough. This assumption was broken because the buffer was incorrectly replaced with the newly allocated buffer containing the first token. If the next authentication token was bigger than the first one then the server-side of the authentication failed with an exception.

@filipnavara
Copy link
Member Author

FWIW I think this mess is consequence of mixing Schannel interop bindings with the SSPI ones. Similarly, the mixing of Unix and Windows code for the NegotiateAuthentication internals is a bit of a mess since they handle buffer allocations differently. I would like to clean it up but I run short on time for .NET 7. The necessary prerequisite was to get the current API shape of NegotiateAuthentication approved to migrate all uses in the FX to reference System.Net.Security through public API. That would allow moving code out of Common and reshaping it into more readable structure.

@stephentoub
Copy link
Member

Thanks. Very helpful explanation. Given "This assumption was broken because the buffer was incorrectly replaced with the newly allocated buffer containing the first token. If the next authentication token was bigger than the first one then the server-side of the authentication failed with an exception.", is there a way to trigger this in some way in a test?

@filipnavara
Copy link
Member Author

filipnavara commented Jul 14, 2022

is there a way to trigger this in some way in a test?

It's tricky given the infrastructure and system dependencies. I have an open PR that tests the Unix version of the code path. I cannot think of an easy test for Windows right now but I will definitely give it a second thought. What I can do with little effort is add Debug.Assert to catch validity of the assumptions early on.

@stephentoub
Copy link
Member

Sounds good, thanks!

@stephentoub stephentoub added this to the 7.0.0 milestone Jul 14, 2022
@wfurt
Copy link
Member

wfurt commented Jul 14, 2022

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@wfurt wfurt left a comment

Choose a reason for hiding this comment

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

LGTM

@wfurt
Copy link
Member

wfurt commented Jul 14, 2022

It seems like there is enough difference in Windows 11 / Server 2022 that it may be worth of adding at least one of them to "normal" PR test run. It is easy to miss the runtime-extra-platforms. any thought on that @danmoseley ?

@danmoseley
Copy link
Member

danmoseley commented Jul 14, 2022

It seems like there is enough difference in Windows 11 / Server 2022 that it may be worth of adding at least one of them to "normal" PR test run. It is easy to miss the runtime-extra-platforms. any thought on that @danmoseley ?

Can we switch one of the default pipelines over instead?

I find it hard to figure out from the yml what the default pipelines use, but I thought Windows 11 was in the mix. Eg., here? Didn't we do that last fall?
https://github.com/danmoseley/runtime/blob/d18554c73e7ee2f95240ade2ef1fee8a59c99772/eng/pipelines/libraries/helix-queues-setup.yml#L140

@wfurt
Copy link
Member

wfurt commented Jul 17, 2022

can you please try back-port it to P7 @rzikm?

@rzikm
Copy link
Member

rzikm commented Jul 17, 2022

I think that ship has sailed already, but I can try tomorrow morning

@filipnavara
Copy link
Member Author

/backport to release/7.0-preview7

@github-actions
Copy link
Contributor

Started backporting to release/7.0-preview7: https://github.com/dotnet/runtime/actions/runs/2685763716

@filipnavara
Copy link
Member Author

(I doubt I have the appropriate GitHub Actions rights but it should work for you, I can fill in the template if necessary)

@github-actions
Copy link
Contributor

@filipnavara an error occurred while backporting to release/7.0-preview7, please check the run log for details!

Error: @filipnavara is not a repo collaborator, backporting is not allowed. If you're a collaborator please make sure your dotnet team membership visibility is set to Public on https://github.com/orgs/dotnet/people?query=filipnavara

@filipnavara
Copy link
Member Author

/backport to release/7.0-preview7

@github-actions
Copy link
Contributor

Started backporting to release/7.0-preview7: https://github.com/dotnet/runtime/actions/runs/2685774511

@filipnavara
Copy link
Member Author

So, yeah, funnily enough I can trigger the backport but I cannot edit the top comment :-)

@ghost ghost locked as resolved and limited conversation to collaborators Aug 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net.Security community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lots of NegotiateStream tests failing locally on Win11
5 participants