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)