Skip to content

Commit f214014

Browse files
committed
Add test for the NegotiateSeal flag
1 parent b5aaafb commit f214014

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

src/libraries/Common/tests/System/Net/Security/FakeNtlmServer.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ public FakeNtlmServer(NetworkCredential expectedCredential)
3737
public bool TargetIsServer { get; set; } = false;
3838
public bool PreferUnicode { get; set; } = true;
3939
public bool ForceNegotiateVersion { get; set; } = true;
40+
public bool SupportsEncryption { get; set; } = true;
4041

4142
// Negotiation results
4243
public bool IsAuthenticated { get; private set; }
4344
public bool IsMICPresent { get; private set; }
4445
public string? ClientSpecifiedSpn { get; private set; }
46+
public Flags InitialClientFlags { get; private set; }
47+
public Flags NegotiatedFlags => _negotiatedFlags;
4548

4649
private NetworkCredential _expectedCredential;
4750

@@ -83,7 +86,7 @@ private enum MessageType : uint
8386
}
8487

8588
[Flags]
86-
private enum Flags : uint
89+
public enum Flags : uint
8790
{
8891
NegotiateUnicode = 0x00000001,
8992
NegotiateOEM = 0x00000002,
@@ -177,17 +180,17 @@ private static ReadOnlySpan<byte> GetField(ReadOnlySpan<byte> payload, int field
177180
case MessageType.Negotiate:
178181
// We don't negotiate, we just verify
179182
Assert.True(incomingBlob.Length >= 32);
180-
Flags flags = (Flags)BinaryPrimitives.ReadUInt32LittleEndian(incomingBlob.AsSpan(12, 4));
181-
Assert.Equal(_requiredFlags, (flags & _requiredFlags));
182-
Assert.True((flags & (Flags.NegotiateOEM | Flags.NegotiateUnicode)) != 0);
183-
if (flags.HasFlag(Flags.NegotiateDomainSupplied))
183+
InitialClientFlags = (Flags)BinaryPrimitives.ReadUInt32LittleEndian(incomingBlob.AsSpan(12, 4));
184+
Assert.Equal(_requiredFlags, (InitialClientFlags & _requiredFlags));
185+
Assert.True((InitialClientFlags & (Flags.NegotiateOEM | Flags.NegotiateUnicode)) != 0);
186+
if (InitialClientFlags.HasFlag(Flags.NegotiateDomainSupplied))
184187
{
185188
string domain = Encoding.ASCII.GetString(GetField(incomingBlob, 16));
186189
Assert.Equal(_expectedCredential.Domain, domain);
187190
}
188191
_expectedMessageType = MessageType.Authenticate;
189192
_negotiateMessage = incomingBlob;
190-
return _challengeMessage = GenerateChallenge(flags);
193+
return _challengeMessage = GenerateChallenge(InitialClientFlags);
191194

192195
case MessageType.Authenticate:
193196
// Validate the authentication!
@@ -230,6 +233,10 @@ private byte[] GenerateChallenge(Flags flags)
230233
{
231234
flags |= Flags.NegotiateVersion;
232235
}
236+
if (!SupportsEncryption)
237+
{
238+
flags &= ~Flags.NegotiateSeal;
239+
}
233240
// Remove any unsupported flags here
234241
flags &= Flags.AllSupported;
235242

src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,52 @@ public void NtlmIncorrectExchangeTest()
211211
Assert.False(fakeNtlmServer.IsAuthenticated);
212212
}
213213

214+
[ConditionalTheory(nameof(IsNtlmAvailable))]
215+
[InlineData(true)]
216+
[InlineData(false)]
217+
public void NtlmEncryptionTest(bool serverSupportsEncryption)
218+
{
219+
using FakeNtlmServer fakeNtlmServer = new FakeNtlmServer(s_testCredentialRight);
220+
fakeNtlmServer.SupportsEncryption = serverSupportsEncryption;
221+
222+
NegotiateAuthentication ntAuth = new NegotiateAuthentication(
223+
new NegotiateAuthenticationClientOptions
224+
{
225+
Package = "NTLM",
226+
Credential = s_testCredentialRight,
227+
TargetName = "HTTP/foo",
228+
RequiredProtectionLevel = ProtectionLevel.EncryptAndSign
229+
});
230+
231+
NegotiateAuthenticationStatusCode statusCode;
232+
byte[]? negotiateBlob = ntAuth.GetOutgoingBlob((byte[])null, out statusCode);
233+
Assert.Equal(NegotiateAuthenticationStatusCode.ContinueNeeded, statusCode);
234+
Assert.NotNull(negotiateBlob);
235+
236+
byte[]? challengeBlob = fakeNtlmServer.GetOutgoingBlob(negotiateBlob);
237+
Assert.NotNull(challengeBlob);
238+
// Validate that the client sent NegotiateSeal flag
239+
Assert.Equal(FakeNtlmServer.Flags.NegotiateSeal, (fakeNtlmServer.InitialClientFlags & FakeNtlmServer.Flags.NegotiateSeal));
240+
241+
byte[]? authenticateBlob = ntAuth.GetOutgoingBlob(challengeBlob, out statusCode);
242+
243+
if (serverSupportsEncryption)
244+
{
245+
Assert.Equal(NegotiateAuthenticationStatusCode.Completed, statusCode);
246+
Assert.NotNull(authenticateBlob);
247+
// Validate that the NegotiateSeal flag survived the full exchange
248+
Assert.Equal(FakeNtlmServer.Flags.NegotiateSeal, (fakeNtlmServer.NegotiatedFlags & FakeNtlmServer.Flags.NegotiateSeal));
249+
250+
byte[]? empty = fakeNtlmServer.GetOutgoingBlob(authenticateBlob);
251+
Assert.Null(empty);
252+
Assert.True(fakeNtlmServer.IsAuthenticated);
253+
}
254+
else
255+
{
256+
Assert.Equal(NegotiateAuthenticationStatusCode.QopNotSupported, statusCode);
257+
}
258+
}
259+
214260
[ConditionalFact(nameof(IsNtlmAvailable))]
215261
public void NtlmSignatureTest()
216262
{

0 commit comments

Comments
 (0)