diff --git a/SMBLibrary/Server/ConnectionState/ProcessStateObject.cs b/SMBLibrary/Server/ConnectionState/ProcessStateObject.cs index 03b2d24..0d00bef 100644 --- a/SMBLibrary/Server/ConnectionState/ProcessStateObject.cs +++ b/SMBLibrary/Server/ConnectionState/ProcessStateObject.cs @@ -13,12 +13,12 @@ namespace SMBLibrary.Server internal class ProcessStateObject { public ushort SubcommandID; + public uint MaxDataCount; // The maximum number of TransactionData bytes that the client accepts in the transaction response public string Name; // The pathname of the [..] named pipe to which the transaction subcommand applies, or a client-supplied [..] name for the transaction. public byte[] TransactionSetup; public byte[] TransactionParameters; public byte[] TransactionData; public int TransactionParametersReceived; // length in bytes public int TransactionDataReceived; // length in bytes - public uint MaxDataCount; } } diff --git a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs b/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs index bfff0de..0c53aff 100644 --- a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs +++ b/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs @@ -189,6 +189,13 @@ namespace SMBLibrary.Server return false; } + public ProcessStateObject CreateProcessState(uint processID) + { + ProcessStateObject processState = new ProcessStateObject(); + m_processStateList[processID] = processState; + return processState; + } + public ProcessStateObject GetProcessState(uint processID) { if (m_processStateList.ContainsKey(processID)) @@ -201,34 +208,9 @@ namespace SMBLibrary.Server } } - /// - /// Get or Create process state - /// - public ProcessStateObject ObtainProcessState(uint processID) + public void RemoveProcessState(uint processID) { - if (m_processStateList.ContainsKey(processID)) - { - return m_processStateList[processID]; - } - else - { - ProcessStateObject processState = new ProcessStateObject(); - m_processStateList[processID] = processState; - return processState; - } - } - - public uint? GetMaxDataCount(uint processID) - { - ProcessStateObject processState = GetProcessState(processID); - if (processState != null) - { - return processState.MaxDataCount; - } - else - { - return null; - } + m_processStateList.Remove(processID); } } } diff --git a/SMBLibrary/Server/SMB1/NTTransactHelper.cs b/SMBLibrary/Server/SMB1/NTTransactHelper.cs index 0a6f8f6..bd64f36 100644 --- a/SMBLibrary/Server/SMB1/NTTransactHelper.cs +++ b/SMBLibrary/Server/SMB1/NTTransactHelper.cs @@ -22,9 +22,10 @@ namespace SMBLibrary.Server.SMB1 if (request.TransParameters.Length < request.TotalParameterCount || request.TransData.Length < request.TotalDataCount) { - ProcessStateObject processState = state.ObtainProcessState(header.PID); // A secondary transaction request is pending + ProcessStateObject processState = state.CreateProcessState(header.PID); processState.SubcommandID = (ushort)request.Function; + processState.MaxDataCount = request.MaxDataCount; processState.TransactionSetup = request.Setup; processState.TransactionParameters = new byte[request.TotalParameterCount]; processState.TransactionData = new byte[request.TotalDataCount]; @@ -37,7 +38,7 @@ namespace SMBLibrary.Server.SMB1 else { // We have a complete command - return GetCompleteNTTransactResponse(header, request.Function, request.Setup, request.TransParameters, request.TransData, share, state); + return GetCompleteNTTransactResponse(header, request.MaxDataCount, request.Function, request.Setup, request.TransParameters, request.TransData, share, state); } } @@ -65,11 +66,12 @@ namespace SMBLibrary.Server.SMB1 else { // We have a complete command - return GetCompleteNTTransactResponse(header, (NTTransactSubcommandName)processState.SubcommandID, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); + state.RemoveProcessState(header.PID); + return GetCompleteNTTransactResponse(header, processState.MaxDataCount, (NTTransactSubcommandName)processState.SubcommandID, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); } } - internal static List GetCompleteNTTransactResponse(SMB1Header header, NTTransactSubcommandName subcommandName, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) + internal static List GetCompleteNTTransactResponse(SMB1Header header, uint maxDataCount, NTTransactSubcommandName subcommandName, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) { NTTransactSubcommand subcommand = NTTransactSubcommand.GetSubcommandRequest(subcommandName, requestSetup, requestParameters, requestData, header.UnicodeFlag); NTTransactSubcommand subcommandResponse = null; @@ -80,7 +82,7 @@ namespace SMBLibrary.Server.SMB1 } else if (subcommand is NTTransactIOCTLRequest) { - subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand, share, state); + subcommandResponse = GetSubcommandResponse(header, maxDataCount, (NTTransactIOCTLRequest)subcommand, share, state); } else if (subcommand is NTTransactSetSecurityDescriptor) { @@ -112,7 +114,7 @@ namespace SMBLibrary.Server.SMB1 return GetNTTransactResponse(responseSetup, responseParameters, responseData, state.MaxBufferSize); } - private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state) + private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, uint maxDataCount, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); NTTransactIOCTLResponse response = new NTTransactIOCTLResponse(); @@ -124,7 +126,7 @@ namespace SMBLibrary.Server.SMB1 header.Status = NTStatus.STATUS_INVALID_HANDLE; return null; } - int maxOutputLength = UInt16.MaxValue; + int maxOutputLength = (int)maxDataCount; byte[] output; header.Status = share.FileStore.DeviceIOControl(openFile.Handle, subcommand.FunctionCode, subcommand.Data, out output, maxOutputLength); if (header.Status != NTStatus.STATUS_SUCCESS) diff --git a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs index f372000..eff7a77 100644 --- a/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs +++ b/SMBLibrary/Server/SMB1/Transaction2SubcommandHelper.cs @@ -15,7 +15,7 @@ namespace SMBLibrary.Server.SMB1 { internal class Transaction2SubcommandHelper { - internal static Transaction2FindFirst2Response GetSubcommandResponse(SMB1Header header, Transaction2FindFirst2Request subcommand, ISMBShare share, SMB1ConnectionState state) + internal static Transaction2FindFirst2Response GetSubcommandResponse(SMB1Header header, uint maxDataCount, Transaction2FindFirst2Request subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); string fileNamePattern = subcommand.FileName; @@ -56,7 +56,7 @@ namespace SMBLibrary.Server.SMB1 bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); List segment = entries.GetRange(0, entriesToReturn); - int maxLength = (int)state.GetMaxDataCount(header.PID).Value; + int maxLength = (int)maxDataCount; FindInformationList findInformationList; try { @@ -92,7 +92,7 @@ namespace SMBLibrary.Server.SMB1 return response; } - internal static Transaction2FindNext2Response GetSubcommandResponse(SMB1Header header, Transaction2FindNext2Request subcommand, ISMBShare share, SMB1ConnectionState state) + internal static Transaction2FindNext2Response GetSubcommandResponse(SMB1Header header, uint maxDataCount, Transaction2FindNext2Request subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); OpenSearch openSearch = session.GetOpenSearch(subcommand.SID); @@ -103,7 +103,7 @@ namespace SMBLibrary.Server.SMB1 } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; - int maxLength = (int)state.GetMaxDataCount(header.PID).Value; + int maxLength = (int)maxDataCount; int maxCount = Math.Min(openSearch.Entries.Count - openSearch.EnumerationLocation, subcommand.SearchCount); List segment = openSearch.Entries.GetRange(openSearch.EnumerationLocation, maxCount); FindInformationList findInformationList; diff --git a/SMBLibrary/Server/SMB1/TransactionHelper.cs b/SMBLibrary/Server/SMB1/TransactionHelper.cs index 0ac0f2b..fde7b7a 100644 --- a/SMBLibrary/Server/SMB1/TransactionHelper.cs +++ b/SMBLibrary/Server/SMB1/TransactionHelper.cs @@ -22,13 +22,12 @@ namespace SMBLibrary.Server.SMB1 /// internal static List GetTransactionResponse(SMB1Header header, TransactionRequest request, ISMBShare share, SMB1ConnectionState state) { - ProcessStateObject processState = state.ObtainProcessState(header.PID); - processState.MaxDataCount = request.MaxDataCount; - if (request.TransParameters.Length < request.TotalParameterCount || request.TransData.Length < request.TotalDataCount) { // A secondary transaction request is pending + ProcessStateObject processState = state.CreateProcessState(header.PID); + processState.MaxDataCount = request.MaxDataCount; processState.Name = request.Name; processState.TransactionSetup = request.Setup; processState.TransactionParameters = new byte[request.TotalParameterCount]; @@ -51,11 +50,11 @@ namespace SMBLibrary.Server.SMB1 // We have a complete command if (request is Transaction2Request) { - return GetCompleteTransaction2Response(header, request.Setup, request.TransParameters, request.TransData, share, state); + return GetCompleteTransaction2Response(header, request.MaxDataCount, request.Setup, request.TransParameters, request.TransData, share, state); } else { - return GetCompleteTransactionResponse(header, request.Name, request.Setup, request.TransParameters, request.TransData, share, state); + return GetCompleteTransactionResponse(header, request.MaxDataCount, request.Name, request.Setup, request.TransParameters, request.TransData, share, state); } } } @@ -85,18 +84,19 @@ namespace SMBLibrary.Server.SMB1 else { // We have a complete command + state.RemoveProcessState(header.PID); if (request is Transaction2SecondaryRequest) { - return GetCompleteTransaction2Response(header, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); + return GetCompleteTransaction2Response(header, processState.MaxDataCount, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); } else { - return GetCompleteTransactionResponse(header, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); + return GetCompleteTransactionResponse(header, processState.MaxDataCount, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state); } } } - internal static List GetCompleteTransactionResponse(SMB1Header header, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) + internal static List GetCompleteTransactionResponse(SMB1Header header, uint maxDataCount, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) { if (String.Equals(name, @"\pipe\lanman", StringComparison.InvariantCultureIgnoreCase)) { @@ -140,7 +140,7 @@ namespace SMBLibrary.Server.SMB1 } else if (subcommand is TransactionTransactNamedPipeRequest) { - subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, (TransactionTransactNamedPipeRequest)subcommand, share, state); + subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, maxDataCount, (TransactionTransactNamedPipeRequest)subcommand, share, state); } else if (subcommand is TransactionRawWriteNamedPipeRequest) { @@ -178,7 +178,7 @@ namespace SMBLibrary.Server.SMB1 return GetTransactionResponse(false, responseSetup, responseParameters, responseData, state.MaxBufferSize); } - internal static List GetCompleteTransaction2Response(SMB1Header header, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) + internal static List GetCompleteTransaction2Response(SMB1Header header, uint maxDataCount, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state) { Transaction2Subcommand subcommand; try @@ -194,11 +194,11 @@ namespace SMBLibrary.Server.SMB1 if (subcommand is Transaction2FindFirst2Request) { - subcommandResponse = Transaction2SubcommandHelper.GetSubcommandResponse(header, (Transaction2FindFirst2Request)subcommand, share, state); + subcommandResponse = Transaction2SubcommandHelper.GetSubcommandResponse(header, maxDataCount, (Transaction2FindFirst2Request)subcommand, share, state); } else if (subcommand is Transaction2FindNext2Request) { - subcommandResponse = Transaction2SubcommandHelper.GetSubcommandResponse(header, (Transaction2FindNext2Request)subcommand, share, state); + subcommandResponse = Transaction2SubcommandHelper.GetSubcommandResponse(header, maxDataCount, (Transaction2FindNext2Request)subcommand, share, state); } else if (subcommand is Transaction2QueryFSInformationRequest) { diff --git a/SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs b/SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs index 9273953..64f4459 100644 --- a/SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs +++ b/SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs @@ -16,7 +16,7 @@ namespace SMBLibrary.Server.SMB1 { internal class TransactionSubcommandHelper { - internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, TransactionTransactNamedPipeRequest subcommand, ISMBShare share, SMB1ConnectionState state) + internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, uint maxDataCount, TransactionTransactNamedPipeRequest subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID); @@ -26,7 +26,7 @@ namespace SMBLibrary.Server.SMB1 return null; } - int maxOutputLength = UInt16.MaxValue; + int maxOutputLength = (int)maxDataCount; byte[] output; header.Status = share.FileStore.DeviceIOControl(openFile.Handle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, subcommand.WriteData, out output, maxOutputLength); if (header.Status != NTStatus.STATUS_SUCCESS)