瀏覽代碼

Pass TRANS_WAIT_NMPIPE requests to the underlying object store

Tal Aloni 7 年之前
父節點
當前提交
ab7398d3cd

+ 1 - 0
SMBLibrary/Server/ConnectionState/ProcessStateObject.cs

@@ -15,6 +15,7 @@ namespace SMBLibrary.Server
         public ushort SubcommandID;
         public uint MaxParameterCount; // The maximum number of Trans_Parameters bytes that the client accepts in the transaction response
         public uint MaxDataCount;      // The maximum number of Trans_Data bytes that the client accepts in the transaction response
+        public uint Timeout;
         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;

+ 5 - 4
SMBLibrary/Server/SMB1/TransactionHelper.cs

@@ -29,6 +29,7 @@ namespace SMBLibrary.Server.SMB1
                 ProcessStateObject processState = state.CreateProcessState(header.PID);
                 processState.MaxParameterCount = request.MaxParameterCount;
                 processState.MaxDataCount = request.MaxDataCount;
+                processState.Timeout = request.Timeout;
                 processState.Name = request.Name;
                 processState.TransactionSetup = request.Setup;
                 processState.TransactionParameters = new byte[request.TotalParameterCount];
@@ -55,7 +56,7 @@ namespace SMBLibrary.Server.SMB1
                 }
                 else
                 {
-                    return GetCompleteTransactionResponse(header, request.MaxDataCount, request.Name, request.Setup, request.TransParameters, request.TransData, share, state);
+                    return GetCompleteTransactionResponse(header, request.MaxDataCount, request.Timeout, request.Name, request.Setup, request.TransParameters, request.TransData, share, state);
                 }
             }
         }
@@ -92,12 +93,12 @@ namespace SMBLibrary.Server.SMB1
                 }
                 else
                 {
-                    return GetCompleteTransactionResponse(header, processState.MaxDataCount, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state);
+                    return GetCompleteTransactionResponse(header, processState.MaxDataCount, processState.Timeout, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state);
                 }
             }
         }
 
-        internal static List<SMB1Command> GetCompleteTransactionResponse(SMB1Header header, uint maxDataCount, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state)
+        internal static List<SMB1Command> GetCompleteTransactionResponse(SMB1Header header, uint maxDataCount, uint timeout, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state)
         {
             if (String.Equals(name, @"\pipe\lanman", StringComparison.InvariantCultureIgnoreCase))
             {
@@ -158,7 +159,7 @@ namespace SMBLibrary.Server.SMB1
             }
             else if (subcommand is TransactionWaitNamedPipeRequest)
             {
-                header.Status = NTStatus.STATUS_NOT_IMPLEMENTED;
+                TransactionSubcommandHelper.ProcessSubcommand(header, timeout, name, (TransactionWaitNamedPipeRequest)subcommand, share, state);
             }
             else if (subcommand is TransactionCallNamedPipeRequest)
             {

+ 27 - 0
SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs

@@ -39,5 +39,32 @@ namespace SMBLibrary.Server.SMB1
             response.ReadData = output;
             return response;
         }
+
+        internal static void ProcessSubcommand(SMB1Header header, uint timeout, string name, TransactionWaitNamedPipeRequest subcommand, ISMBShare share, SMB1ConnectionState state)
+        {
+            if (!name.StartsWith(@"\PIPE\", StringComparison.OrdinalIgnoreCase))
+            {
+                // [MS-CIFS] The name field MUST be set to the name of the pipe being waited for, in the format \PIPE\<pipename>
+                state.LogToServer(Severity.Verbose, "TransactWaitNamedPipe failed. Invalid pipe name: {0}.", name);
+                header.Status = NTStatus.STATUS_INVALID_SMB;
+            }
+
+            string pipeName = name.Substring(6);
+            PipeWaitRequest pipeWaitRequest = new PipeWaitRequest();
+            pipeWaitRequest.Timeout = timeout;
+            pipeWaitRequest.TimeSpecified = true;
+            pipeWaitRequest.Name = pipeName;
+            byte[] input = pipeWaitRequest.GetBytes();
+            byte[] output;
+            header.Status = share.FileStore.DeviceIOControl(null, (uint)IoControlCode.FSCTL_PIPE_WAIT, input, out output, 0);
+            if (header.Status != NTStatus.STATUS_SUCCESS)
+            {
+                state.LogToServer(Severity.Verbose, "TransactWaitNamedPipe failed. Pipe name: {0}. NTStatus: {1}.", pipeName, header.Status);
+            }
+            else
+            {
+                state.LogToServer(Severity.Verbose, "TransactWaitNamedPipe succeeded. Pipe name: {0}.", pipeName);
+            }
+        }
     }
 }