Skip to content
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

Improve interoperability of NTLM encryption/decryption and authentication #71373

Merged
merged 11 commits into from
Jun 30, 2022

Conversation

filipnavara
Copy link
Member

@filipnavara filipnavara commented Jun 28, 2022

Best reviewed commit by commit.

Firstly, it fixes an interoperability scenario for non-encrypted NTLM communication passed through NegotiateStream between Unix and Windows. It updates the NegotiateStreamPal.Encrypt/Decrypt Unix implementation to have the same quirk as the Windows implementation has.

Secondly, it fixes a bunch of bugs in the SmtpClient GSSAPI authentication and adds a loopback server test. This was also tested against a real Microsoft Exchange server to ensure that it works properly and that the encryption/decryption is applied correctly in context of NTLM authentication.

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Jun 28, 2022
@ghost
Copy link

ghost commented Jun 28, 2022

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

Issue Details

Built on top of #71280, best reviewed commit by commit.

Firstly, it fixes an interoperability scenario for non-encrypted NTLM communication passed through NegotiateStream between Unix and Windows. It updates the NegotiateStreamPal.Encrypt/Decrypt Unix implementation to have the same quirk as the Windows implementation has.

Secondly, it fixes a bunch of bugs in the SmtpClient GSSAPI authentication and adds a loopback server test. This was also tested against a real Microsoft Exchange server to ensure that it works properly and that the encryption/decryption is applied correctly in context of NTLM authentication.

Author: filipnavara
Assignees: -
Labels:

area-System.Net.Security, community-contribution

Milestone: -

NegotiateStream on non-encrypted connections with NTLM sends the
messages in a special `<signature token><plain text message>` format.
That's not something that gss_wrap/gss_unwrap would produce. It can be
produced through gss_get_mic/gss_verify_mic calls though so let's do
that.
The method names were misleading since they wrapped the EncryptMessage
and DecryptMessage native APIs and not the MakeSignature/VerifySignature
APIs that also exist.
…/Decrypt

The SSPI / GSSAPI providers keep track of the sequence numbers
themselves.
This maps directly to the semantics of gss_wrap/gss_unwrap methods
that are used in many specifications. It replaces the misleading name
which in SSPI API is an equivalent of gss_get_mic/gss_verify_mic.
It also fixes the declaration to actually decode the buffers both
on Windows and Unix. In NTLM the content of the message is sealed
and needs to be decoded.

Note that previously on Unix the VerifySignature API didn't decode the
content. On Windows it did decode the content inside a buffer that was
passed as ReadOnlySpan<byte> but it didn't communicate back the offset
of the decoded data.

The SMTP GSSAPI authentication code was thus reading incorrect data.
In case the underlying authentication was Kerberos the data were
not encrypted and they were located at the beginning of the buffer
so it was not an issue. In case the underlying authentication was
NTLM it was looking at the NTLM signature token which luckily
happens to always start with the bytes 01 00 00 00. That exactly
matched the expected value by accident.
The last token in the GSSAPI SASL authentication mechanism is a bit
mask that specifies the supported security protections offered by the
server and the maximum token size. The client is supposed to choose
one of the protections and reply back. Relax the check to actually
support servers that offer anything but "no protection". As long
as the server also offers no protection we can choose it.
Updated the managed NTLM implementation and the fake servers to
implement the specification quirk:

MS-SPNG section 3.2.5.1 NTLM RC4 Key State for MechListMIC and First
Signed Message specifies that the RC4 sealing keys are reset back to
the initial state for the first message.

Since the managed implementation doesn't expose encryption yet it
didn't affect any observable behavior. Likewise the fake servers
didn't need this code path yet.
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.
cc: @SteveSyfuhs for any thoughts on the GSSAPI/SSPI changes.

@wfurt
Copy link
Member

wfurt commented Jun 29, 2022

contributes to #19436

@wfurt wfurt merged commit ac9e1f9 into dotnet:main Jun 30, 2022
@karelz karelz added this to the 7.0.0 milestone Jul 19, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Aug 18, 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.

3 participants