From 6f294cd7d5f80188679215ca5736e61616454fba Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 21 Dec 2021 12:48:22 -0500 Subject: [PATCH] Always prefer the supplied domain over the TargetName or TargetInfo.DomainName Fixes https://github.com/jstedfast/MailKit/issues/582#issuecomment-998855650 --- MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs | 12 ++++++------ MailKit/Security/SaslMechanismNtlm.cs | 6 +++--- .../Security/Ntlm/NtlmAuthenticateMessageTests.cs | 10 +++++----- UnitTests/Security/SaslMechanismNtlmTests.cs | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs b/MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs index 89b2d84afd..07b83911e6 100644 --- a/MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs +++ b/MailKit/Security/Ntlm/NtlmAuthenticateMessage.cs @@ -38,7 +38,7 @@ class NtlmAuthenticateMessage : NtlmMessageBase readonly NtlmChallengeMessage challenge; byte[] clientChallenge; - public NtlmAuthenticateMessage (NtlmNegotiateMessage negotiate, NtlmChallengeMessage challenge, string userName, string password, string workstation) : base (3) + public NtlmAuthenticateMessage (NtlmNegotiateMessage negotiate, NtlmChallengeMessage challenge, string userName, string password, string domain, string workstation) : base (3) { if (negotiate == null) throw new ArgumentNullException (nameof (negotiate)); @@ -56,14 +56,14 @@ public NtlmAuthenticateMessage (NtlmNegotiateMessage negotiate, NtlmChallengeMes this.negotiate = negotiate; this.challenge = challenge; - if ((challenge.Flags & NtlmFlags.TargetTypeDomain) != 0) { + if (!string.IsNullOrEmpty (domain)) { + Domain = domain; + } else if ((challenge.Flags & NtlmFlags.TargetTypeDomain) != 0) { // The server is domain-joined, so the TargetName will be the domain. Domain = challenge.TargetName; - } else { + } else if (challenge.TargetInfo != null) { // The server is not domain-joined, so the TargetName will be the machine name of the server. - Domain = challenge.TargetInfo?.DomainName; - - // TODO: throw if TargetInfo is null? + Domain = challenge.TargetInfo.DomainName; } Workstation = workstation; diff --git a/MailKit/Security/SaslMechanismNtlm.cs b/MailKit/Security/SaslMechanismNtlm.cs index 36659834db..24d1cf6c04 100644 --- a/MailKit/Security/SaslMechanismNtlm.cs +++ b/MailKit/Security/SaslMechanismNtlm.cs @@ -273,7 +273,7 @@ protected override byte[] Challenge (byte[] token, int startIndex, int length, C break; case LoginState.Challenge: var password = Credentials.Password; - message = GetChallengeResponse (userName, password, token, startIndex, length); + message = GetChallengeResponse (domain, userName, password, token, startIndex, length); IsAuthenticated = true; break; } @@ -281,10 +281,10 @@ protected override byte[] Challenge (byte[] token, int startIndex, int length, C return message?.Encode (); } - NtlmAuthenticateMessage GetChallengeResponse (string userName, string password, byte[] token, int startIndex, int length) + NtlmAuthenticateMessage GetChallengeResponse (string domain, string userName, string password, byte[] token, int startIndex, int length) { var challenge = new NtlmChallengeMessage (token, startIndex, length); - var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, userName, password, Workstation) { + var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, userName, password, domain, Workstation) { ClientChallenge = Nonce, Timestamp = Timestamp }; diff --git a/UnitTests/Security/Ntlm/NtlmAuthenticateMessageTests.cs b/UnitTests/Security/Ntlm/NtlmAuthenticateMessageTests.cs index 3105f81eb5..f7ba594a08 100644 --- a/UnitTests/Security/Ntlm/NtlmAuthenticateMessageTests.cs +++ b/UnitTests/Security/Ntlm/NtlmAuthenticateMessageTests.cs @@ -40,12 +40,12 @@ public void TestArgumentExceptions () byte[] badMessageData = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00 }; var NtlmNegotiate = new NtlmNegotiateMessage (); var NtlmChallenge = new NtlmChallengeMessage (); - var NtlmAuthenticate = new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, "username", "password", "workstation"); + var NtlmAuthenticate = new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, "username", "password", "domain", "workstation"); - Assert.Throws (() => new NtlmAuthenticateMessage (null, NtlmChallenge, "username", "password", "workstation")); - Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, null, "username", "password", "workstation")); - Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, null, "password", "workstation")); - Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, "username", null, "workstation")); + Assert.Throws (() => new NtlmAuthenticateMessage (null, NtlmChallenge, "username", "password", "domain", "workstation")); + Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, null, "username", "password", "domain", "workstation")); + Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, null, "password", "domain", "workstation")); + Assert.Throws (() => new NtlmAuthenticateMessage (NtlmNegotiate, NtlmChallenge, "username", null, "domain", "workstation")); Assert.Throws (() => new NtlmAuthenticateMessage (null, 0, 16)); Assert.Throws (() => new NtlmAuthenticateMessage (new byte[8], 0, 8)); diff --git a/UnitTests/Security/SaslMechanismNtlmTests.cs b/UnitTests/Security/SaslMechanismNtlmTests.cs index 0fd25c0b8d..174ab094fc 100644 --- a/UnitTests/Security/SaslMechanismNtlmTests.cs +++ b/UnitTests/Security/SaslMechanismNtlmTests.cs @@ -386,7 +386,7 @@ public void TestNtlmAuthenticateMessageEncode () var nonce = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07 }; var negotiate = new NtlmNegotiateMessage (flags, null, null, new Version (10, 0, 19043)); var challenge = DecodeChallengeMessage (challenge2); - var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, "user", "password", "WORKSTATION") { + var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, "user", "password", null, "WORKSTATION") { ClientChallenge = nonce, Timestamp = timestamp }; @@ -511,7 +511,7 @@ static void AssertNtlmv2 (SaslMechanismNtlm sasl, string challenge1, string chal var negotiate = DecodeNegotiateMessage (challenge1); var challenge = DecodeChallengeMessage (challenge2); - var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, sasl.Credentials.UserName, sasl.Credentials.Password, sasl.Workstation) { + var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, sasl.Credentials.UserName, sasl.Credentials.Password, null, sasl.Workstation) { ClientChallenge = nonce, Timestamp = timestamp }; @@ -660,7 +660,7 @@ public void TestNtlmv2Example () //var expectedType3 = new NtlmAuthenticateMessage (ExampleNtlmV2AuthenticateMessage, 0, ExampleNtlmV2AuthenticateMessage.Length); //var expectedTargetInfo = GetNtChallengeResponseTargetInfo (expectedType3.NtChallengeResponse); - var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, "User", "Password", "COMPUTER") { + var authenticate = new NtlmAuthenticateMessage (negotiate, challenge, "User", "Password", null, "COMPUTER") { ClientChallenge = nonce, Timestamp = timestamp };