Bläddra i källkod

NTAuthentication: Will use ComputeNTLMv2Proof (instead of ComputeNTLMv2Response) to improve compatibility with clients

Xubuntu 16.04 will not add the necessary padding to
ClientChallengeStructure
Tal Aloni 8 år sedan
förälder
incheckning
4bd6bbd882

+ 5 - 6
SMBLibrary/Authentication/NTAuthentication.cs

@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  * 
  * You can redistribute this program and/or modify it under the terms of
  * the GNU Lesser Public License as published by the Free Software Foundation,
@@ -48,18 +48,17 @@ namespace SMBLibrary.Authentication
         }
 
         /// <summary>
-        /// [MS-NLMP] page 60
-        /// 'temp' is the same as ClientChallengeStructure with 4 zero bytes padding
+        /// [MS-NLMP] https://msdn.microsoft.com/en-us/library/cc236700.aspx
         /// </summary>
-        public static byte[] ComputeNTLMv2Response(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain)
+        /// <param name="clientChallengeStructurePadded">ClientChallengeStructure with 4 zero bytes padding, a.k.a. temp</param>
+        public static byte[] ComputeNTLMv2Proof(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain)
         {
             byte[] key = NTOWFv2(password, user, domain);
             byte[] temp = clientChallengeStructurePadded;
 
             HMACMD5 hmac = new HMACMD5(key);
             byte[] _NTProof = hmac.ComputeHash(ByteUtils.Concatenate(serverChallenge, temp), 0, serverChallenge.Length + temp.Length);
-
-            return ByteUtils.Concatenate(_NTProof, temp);
+            return _NTProof;
         }
 
         /// <summary>

+ 4 - 4
SMBLibrary/Server/IndependentUserCollection.cs

@@ -98,11 +98,11 @@ namespace SMBLibrary.Server
 
                     if (ntlmResponse.Length > 24)
                     {
-                        NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(ntlmResponse, 16);
-                        byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
-                        byte[] expectedNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth);
+                        byte[] clientNTProof = ByteReader.ReadBytes(ntlmResponse, 0, 16);
+                        byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntlmResponse, 16, ntlmResponse.Length - 16);
+                        byte[] expectedNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth);
 
-                        if (ByteUtils.AreByteArraysEqual(expectedNTLMv2Response, ntlmResponse))
+                        if (ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof))
                         {
                             return this[index];
                         }

+ 6 - 6
SMBLibrary/Tests/AuthenticationTests.cs

@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  * 
  * You can redistribute this program and/or modify it under the terms of
  * the GNU Lesser Public License as published by the Free Software Foundation,
@@ -76,11 +76,10 @@ namespace SMBLibrary
             DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
             NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server");
             byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
-            byte[] response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
+            byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
 
-            byte[] expectedHash = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c };
-            byte[] expected = ByteUtils.Concatenate(expectedHash, clientChallengeStructurePadded);
-            bool success = ByteUtils.AreByteArraysEqual(response, expected);
+            byte[] expectedNTProof = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c };
+            bool success = ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof);
             return success;
         }
 
@@ -135,6 +134,7 @@ namespace SMBLibrary
             DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
             NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server");
             byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
+            byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
             
             AuthenticateMessage message = new AuthenticateMessage();
             message.EncryptedRandomSessionKey = sessionKey;
@@ -144,7 +144,7 @@ namespace SMBLibrary
             message.WorkStation = "COMPUTER";
             message.UserName = "User";
             message.LmChallengeResponse = NTAuthentication.ComputeLMv2Response(serverChallenge, clientChallenge, "Password", "User", "Domain");
-            message.NtChallengeResponse = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
+            message.NtChallengeResponse = ByteUtils.Concatenate(clientNTProof, clientChallengeStructurePadded);
             
             byte[] messageBytes = message.GetBytes();
             // The payload entries may be distributed differently so we use cmp.GetBytes()

+ 4 - 4
SMBLibrary/Win32/Win32UserCollection.cs

@@ -100,10 +100,10 @@ namespace SMBLibrary.Server.Win32
 
                 if (message.NtChallengeResponse.Length > 24)
                 {
-                    NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(message.NtChallengeResponse, 16);
-                    byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
-                    byte[] emptyPasswordNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
-                    if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv2Response, message.NtChallengeResponse))
+                    byte[] clientNTProof = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
+                    byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(message.NtChallengeResponse, 16, message.NtChallengeResponse.Length - 16);
+                    byte[] emptyPasswordNTProof = NTAuthentication.ComputeNTLMv2Proof(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
+                    if (ByteUtils.AreByteArraysEqual(clientNTProof, emptyPasswordNTProof))
                     {
                         return true;
                     }