Skip to content

Commit ca28411

Browse files
authored
Fix calculation of channel bindings hash in managed NTLM implementation (#102565)
1 parent cff625b commit ca28411

File tree

3 files changed

+24
-11
lines changed

3 files changed

+24
-11
lines changed

src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.ManagedNtlm.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,23 @@ private unsafe void WriteChannelBindingHash(Span<byte> hashBuffer)
416416
{
417417
if (_channelBinding != null)
418418
{
419-
IntPtr cbtData = _channelBinding.DangerousGetHandle();
420-
int cbtDataSize = _channelBinding.Size;
421-
int written = MD5.HashData(new Span<byte>((void*)cbtData, cbtDataSize), hashBuffer);
422-
Debug.Assert(written == MD5.HashSizeInBytes);
419+
int appDataOffset = sizeof(SecChannelBindings);
420+
IntPtr cbtData = (nint)_channelBinding.DangerousGetHandle() + appDataOffset;
421+
int cbtDataSize = _channelBinding.Size - appDataOffset;
422+
423+
// Channel bindings are calculated according to RFC 4121, section 4.1.1.2,
424+
// so we need to include zeroed initiator fields and length prefix for the
425+
// application data.
426+
Span<byte> prefix = stackalloc byte[sizeof(uint) * 5];
427+
prefix.Clear();
428+
BinaryPrimitives.WriteInt32LittleEndian(prefix.Slice(sizeof(uint) * 4), cbtDataSize);
429+
using (var md5 = IncrementalHash.CreateHash(HashAlgorithmName.MD5))
430+
{
431+
md5.AppendData(prefix);
432+
md5.AppendData(new Span<byte>((void*)cbtData, cbtDataSize));
433+
int written = md5.GetHashAndReset(hashBuffer);
434+
Debug.Assert(written == MD5.HashSizeInBytes);
435+
}
423436
}
424437
else
425438
{

src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Unix.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ Interop.NetSecurityNative.Status status
551551
}
552552
}
553553

554-
private NegotiateAuthenticationStatusCode InitializeSecurityContext(
554+
private unsafe NegotiateAuthenticationStatusCode InitializeSecurityContext(
555555
ref SafeGssCredHandle credentialsHandle,
556556
ref SafeGssContextHandle? contextHandle,
557557
ref SafeGssNameHandle? targetNameHandle,
@@ -594,7 +594,7 @@ private NegotiateAuthenticationStatusCode InitializeSecurityContext(
594594
{
595595
// If a TLS channel binding token (cbt) is available then get the pointer
596596
// to the application specific data.
597-
int appDataOffset = Marshal.SizeOf<SecChannelBindings>();
597+
int appDataOffset = sizeof(SecChannelBindings);
598598
Debug.Assert(appDataOffset < channelBinding.Size);
599599
IntPtr cbtAppData = channelBinding.DangerousGetHandle() + appDataOffset;
600600
int cbtAppDataSize = channelBinding.Size - appDataOffset;

src/libraries/System.Net.Security/src/System/Net/Security/Pal.Managed/SafeChannelBindingHandle.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace System.Net.Security
1111
internal sealed class SafeChannelBindingHandle : ChannelBinding
1212
{
1313
private const int CertHashMaxSize = 128;
14-
private static readonly int s_secChannelBindingSize = Marshal.SizeOf<SecChannelBindings>();
14+
private static unsafe int SecChannelBindingSize => sizeof(SecChannelBindings);
1515

1616
private readonly int _cbtPrefixByteArraySize;
1717
internal int Length { get; private set; }
@@ -36,8 +36,8 @@ internal unsafe SafeChannelBindingHandle(ChannelBindingKind kind)
3636
"tls-unique:"u8;
3737

3838
_cbtPrefixByteArraySize = cbtPrefix.Length;
39-
handle = Marshal.AllocHGlobal(s_secChannelBindingSize + _cbtPrefixByteArraySize + CertHashMaxSize);
40-
IntPtr cbtPrefixPtr = handle + s_secChannelBindingSize;
39+
handle = Marshal.AllocHGlobal(SecChannelBindingSize + _cbtPrefixByteArraySize + CertHashMaxSize);
40+
IntPtr cbtPrefixPtr = handle + SecChannelBindingSize;
4141
cbtPrefix.CopyTo(new Span<byte>((byte*)cbtPrefixPtr, cbtPrefix.Length));
4242
CertHashPtr = cbtPrefixPtr + _cbtPrefixByteArraySize;
4343
Length = CertHashMaxSize;
@@ -46,12 +46,12 @@ internal unsafe SafeChannelBindingHandle(ChannelBindingKind kind)
4646
internal void SetCertHashLength(int certHashLength)
4747
{
4848
int cbtLength = _cbtPrefixByteArraySize + certHashLength;
49-
Length = s_secChannelBindingSize + cbtLength;
49+
Length = SecChannelBindingSize + cbtLength;
5050

5151
SecChannelBindings channelBindings = new SecChannelBindings()
5252
{
5353
ApplicationDataLength = cbtLength,
54-
ApplicationDataOffset = s_secChannelBindingSize
54+
ApplicationDataOffset = SecChannelBindingSize
5555
};
5656
Marshal.StructureToPtr(channelBindings, handle, true);
5757
}

0 commit comments

Comments
 (0)