From e79b44e65f15b47475b02dd4ac3347942badb2d1 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Tue, 24 Mar 2026 13:15:49 +0200 Subject: [PATCH 1/7] Client: IndependentNTLMAuthenticationProvider: Extracted virtual CreateChallengeMessage method --- .../NTLM/IndependentNTLMAuthenticationProvider.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/SMBLibrary/Authentication/NTLM/IndependentNTLMAuthenticationProvider.cs b/SMBLibrary/Authentication/NTLM/IndependentNTLMAuthenticationProvider.cs index 2a4cea30..73367f89 100644 --- a/SMBLibrary/Authentication/NTLM/IndependentNTLMAuthenticationProvider.cs +++ b/SMBLibrary/Authentication/NTLM/IndependentNTLMAuthenticationProvider.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2020 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2026 Tal Aloni . 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, @@ -78,6 +78,13 @@ public override NTStatus GetChallengeMessage(out object context, byte[] negotiat byte[] serverChallenge = GenerateServerChallenge(); context = new AuthContext(serverChallenge); + ChallengeMessage challengeMessage = CreateChallengeMessage(negotiateMessage, serverChallenge); + challengeMessageBytes = challengeMessage.GetBytes(); + return NTStatus.SEC_I_CONTINUE_NEEDED; + } + + protected virtual ChallengeMessage CreateChallengeMessage(NegotiateMessage negotiateMessage, byte[] serverChallenge) + { ChallengeMessage challengeMessage = new ChallengeMessage(); // https://msdn.microsoft.com/en-us/library/cc236691.aspx challengeMessage.NegotiateFlags = NegotiateFlags.TargetTypeServer | @@ -147,8 +154,7 @@ public override NTStatus GetChallengeMessage(out object context, byte[] negotiat challengeMessage.ServerChallenge = serverChallenge; challengeMessage.TargetInfo = AVPairUtils.GetAVPairSequence(Environment.MachineName, Environment.MachineName); challengeMessage.Version = NTLMVersion.Server2003; - challengeMessageBytes = challengeMessage.GetBytes(); - return NTStatus.SEC_I_CONTINUE_NEEDED; + return challengeMessage; } public override NTStatus Authenticate(object context, byte[] authenticateMessageBytes) From d886658f88f42ba6ee2f3b4eb6ddaf6fa68dfee7 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Tue, 24 Mar 2026 13:27:06 +0200 Subject: [PATCH 2/7] SMBLibrary 1.5.6.2 --- SMBLibrary/SMBLibrary.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SMBLibrary/SMBLibrary.csproj b/SMBLibrary/SMBLibrary.csproj index 138a16e7..6c6655cb 100644 --- a/SMBLibrary/SMBLibrary.csproj +++ b/SMBLibrary/SMBLibrary.csproj @@ -3,7 +3,7 @@ net20;net40;netstandard2.0 SMBLibrary - 1.5.6.1 + 1.5.6.2 1573;1591 SMBLibrary false From 49f5131daf4ceda60f48451a98727031215b9872 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Wed, 25 Mar 2026 10:23:19 +0200 Subject: [PATCH 3/7] NTLMCryptography: Marked ComputeSignKey and ComputeSealKey as public --- SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs b/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs index 4c7e55f2..0e2d8eff 100644 --- a/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs +++ b/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs @@ -284,7 +284,7 @@ public static byte[] ComputeServerSignKey(byte[] exportedSessionKey) return ComputeSignKey(exportedSessionKey, false); } - private static byte[] ComputeSignKey(byte[] exportedSessionKey, bool isClient) + public static byte[] ComputeSignKey(byte[] exportedSessionKey, bool isClient) { // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/524cdccb-563e-4793-92b0-7bc321fce096 string str; @@ -312,7 +312,7 @@ public static byte[] ComputeServerSealKey(byte[] exportedSessionKey) return ComputeSealKey(exportedSessionKey, false); } - private static byte[] ComputeSealKey(byte[] exportedSessionKey, bool isClient) + public static byte[] ComputeSealKey(byte[] exportedSessionKey, bool isClient) { // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/524cdccb-563e-4793-92b0-7bc321fce096 string str; From 1c79bcc2f0fa121cff4cd8631621c6b39c4bf2b8 Mon Sep 17 00:00:00 2001 From: aled Date: Thu, 2 Apr 2026 18:19:34 +0100 Subject: [PATCH 4/7] Use a temporary directory for NTDirectoryFileSystem tests, rather than a hardcoded path. --- SMBLibrary.Tests/NTFileStore/NTDirectoryFileSystemTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SMBLibrary.Tests/NTFileStore/NTDirectoryFileSystemTests.cs b/SMBLibrary.Tests/NTFileStore/NTDirectoryFileSystemTests.cs index 591572b5..de064818 100644 --- a/SMBLibrary.Tests/NTFileStore/NTDirectoryFileSystemTests.cs +++ b/SMBLibrary.Tests/NTFileStore/NTDirectoryFileSystemTests.cs @@ -14,7 +14,7 @@ namespace SMBLibrary.Tests [TestClass] public class NTDirectoryFileSystemTests : NTFileStoreTests { - private static readonly string TestDirectoryPath = @"C:\Tests"; + private static readonly string TestDirectoryPath = Path.Combine(Path.GetTempPath(), "SMBLibraryTests"); static NTDirectoryFileSystemTests() { From c8225756b085258de9e602b91cda45d72c4dc503 Mon Sep 17 00:00:00 2001 From: aled Date: Thu, 2 Apr 2026 18:20:42 +0100 Subject: [PATCH 5/7] Get different port numbers for tests that are run at the same instant in time. --- SMBLibrary.Tests/Client/SMB2ClientTests.cs | 32 +++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/SMBLibrary.Tests/Client/SMB2ClientTests.cs b/SMBLibrary.Tests/Client/SMB2ClientTests.cs index 40e88b3e..a597d695 100644 --- a/SMBLibrary.Tests/Client/SMB2ClientTests.cs +++ b/SMBLibrary.Tests/Client/SMB2ClientTests.cs @@ -10,6 +10,7 @@ using System.Diagnostics; using System.Net; using System.Net.Sockets; +using System.Security.Cryptography; using System.Threading; namespace SMBLibrary.Tests.Client @@ -20,11 +21,40 @@ public class SMB2ClientTests private int m_serverPort; private TcpListener m_tcpListener; private bool m_clientConnected; + + // ensure that multiple tests run at the same instant in time receive different port numbers + // by using a random number generator that is NOT seeded solely by current time + private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); + + private int GetRandomPortNumber(int lowerBound, int upperBound) + { + if (lowerBound < 0) + { + throw new ArgumentOutOfRangeException(nameof(lowerBound), "lowerBound must be greater than 0"); + } + + if (upperBound < lowerBound || upperBound > 65535) + { + throw new ArgumentOutOfRangeException(nameof(upperBound), "upperBound must be greater-or-equal to lowerBound and less than 65536"); + } + + // rejection sampling is overkill for this application, but whatever, at least the tests pass now. + // use 2 bytes to generate a random number in the range 0 to 65535 + var bytes = new byte[2]; + int portNumber; + do + { + rng.GetBytes(bytes); + portNumber = BitConverter.ToUInt16(bytes, 0); + } while (portNumber < lowerBound || portNumber > upperBound); + return portNumber; + } + [TestInitialize] public void Initialize() { - m_serverPort = 1000 + new Random().Next(50000); + m_serverPort = GetRandomPortNumber(1025, 65535); m_tcpListener = new TcpListener(IPAddress.Loopback, m_serverPort); m_tcpListener.Start(); } From d80959f1f0456cb2526d03e566c477d2fd36143d Mon Sep 17 00:00:00 2001 From: aled Date: Sat, 4 Apr 2026 17:27:44 +0100 Subject: [PATCH 6/7] Ensure a new port number is used for each test by incrementing the port number each time. --- SMBLibrary.Tests/Client/SMB2ClientTests.cs | 41 +++++++--------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/SMBLibrary.Tests/Client/SMB2ClientTests.cs b/SMBLibrary.Tests/Client/SMB2ClientTests.cs index a597d695..94b1995d 100644 --- a/SMBLibrary.Tests/Client/SMB2ClientTests.cs +++ b/SMBLibrary.Tests/Client/SMB2ClientTests.cs @@ -17,45 +17,30 @@ namespace SMBLibrary.Tests.Client { [TestClass] public class SMB2ClientTests - { - private int m_serverPort; + { + // ensure that multiple tests run at the same instant in time receive different port numbers + // by incrementing the port number for each test + private static readonly int minPort = 1025; + private static readonly int maxPort = 65535; + private static int m_serverPort = minPort + new Random().Next(maxPort - minPort); + private TcpListener m_tcpListener; private bool m_clientConnected; - // ensure that multiple tests run at the same instant in time receive different port numbers - // by using a random number generator that is NOT seeded solely by current time - private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); - - private int GetRandomPortNumber(int lowerBound, int upperBound) + private static int GetNextPortNumber() { - if (lowerBound < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowerBound), "lowerBound must be greater than 0"); - } + Interlocked.Increment(ref m_serverPort); - if (upperBound < lowerBound || upperBound > 65535) - { - throw new ArgumentOutOfRangeException(nameof(upperBound), "upperBound must be greater-or-equal to lowerBound and less than 65536"); - } - - // rejection sampling is overkill for this application, but whatever, at least the tests pass now. - // use 2 bytes to generate a random number in the range 0 to 65535 - var bytes = new byte[2]; - int portNumber; - do - { - rng.GetBytes(bytes); - portNumber = BitConverter.ToUInt16(bytes, 0); - } while (portNumber < lowerBound || portNumber > upperBound); + if (m_serverPort > maxPort) + m_serverPort = minPort; - return portNumber; + return m_serverPort; } [TestInitialize] public void Initialize() { - m_serverPort = GetRandomPortNumber(1025, 65535); - m_tcpListener = new TcpListener(IPAddress.Loopback, m_serverPort); + m_tcpListener = new TcpListener(IPAddress.Loopback, GetNextPortNumber()); m_tcpListener.Start(); } From dd57ecdf93a516b3ddf0bb6bd9ff5fa277f4ceb8 Mon Sep 17 00:00:00 2001 From: aled Date: Sat, 4 Apr 2026 18:27:58 +0100 Subject: [PATCH 7/7] Use return value from Increment method --- SMBLibrary.Tests/Client/SMB2ClientTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SMBLibrary.Tests/Client/SMB2ClientTests.cs b/SMBLibrary.Tests/Client/SMB2ClientTests.cs index 94b1995d..a081a307 100644 --- a/SMBLibrary.Tests/Client/SMB2ClientTests.cs +++ b/SMBLibrary.Tests/Client/SMB2ClientTests.cs @@ -29,12 +29,12 @@ public class SMB2ClientTests private static int GetNextPortNumber() { - Interlocked.Increment(ref m_serverPort); + var next = Interlocked.Increment(ref m_serverPort); - if (m_serverPort > maxPort) - m_serverPort = minPort; + if (next > maxPort) + next = minPort; - return m_serverPort; + return next; } [TestInitialize]