Skip to content

Comments

Fix ManagedNtlm on big-endian architectures#124598

Open
ShreyaLaxminarayan wants to merge 2 commits intodotnet:mainfrom
ShreyaLaxminarayan:ntlm
Open

Fix ManagedNtlm on big-endian architectures#124598
ShreyaLaxminarayan wants to merge 2 commits intodotnet:mainfrom
ShreyaLaxminarayan:ntlm

Conversation

@ShreyaLaxminarayan
Copy link
Contributor

Fixes multiple endianness bugs in ManagedNtlm that caused incorrect behavior on big-endian platforms.
Validated via existing Ntlm test cases.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Feb 19, 2026
@ShreyaLaxminarayan
Copy link
Contributor Author

@dotnet-policy-service
Copy link
Contributor

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

// Derive session base key
Span<byte> sessionBaseKey = stackalloc byte[HMACMD5.HashSizeInBytes];
int sessionKeyWritten = HMACMD5.HashData(ntlm2hash, responseAsSpan.Slice(response.NtChallengeResponse.PayloadOffset, 16), sessionBaseKey);
var payloadSlice = (BitConverter.IsLittleEndian) ? responseAsSpan.Slice(response.NtChallengeResponse.PayloadOffset, 16) : responseAsSpan.Slice(BinaryPrimitives.ReverseEndianness(response.NtChallengeResponse.PayloadOffset), 16);
Copy link
Member

Choose a reason for hiding this comment

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

I would probably get correct PayloadOffset value first instead of duplicating the whole Slice block. But that is mostly style and readability preference.

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 in general.

NtlmHeader.CopyTo(asBytes);
message.Header.MessageType = MessageType.Negotiate;
message.Flags = requiredFlags;
message.Flags = BitConverter.IsLittleEndian ? requiredFlags : (Flags)BinaryPrimitives.ReverseEndianness((uint)requiredFlags);
Copy link
Member

@rzikm rzikm Feb 20, 2026

Choose a reason for hiding this comment

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

I am not a big fan of those manual branches. For one, when you look at message.Flags using a debugger, the value will be misrepresented on BE systems, and if you miss one place, you end up with hard to debug bugs. Other questions arise from looking at the code like why do we reverse some properties and not others....

Can we modify the definition of NegotiateMessage to have setter/getter of those properties handle the endianness difference transparently to the caller?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Out of the fields that are set for NegotiateMessage, message.Header.MessageType is a byte and is represented the same in little-endian and big-endian. Flags is an uint and needs to be endian specific. Version is a struct with ProductBuild as ushort and the rest are bytes, and hence only ProductBuild needs to be reversed. I will implement it using getters and setters.

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

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