Kaynağa Gözat

Added DeviceIOControl to the INTFileStore interface, relevant functionality moved to the object store layer

Tal Aloni 8 yıl önce
ebeveyn
işleme
3e158fb855

+ 6 - 0
SMBLibrary/NTFileStore/Adapter/NTFileSystemAdapter.cs

@@ -370,6 +370,12 @@ namespace SMBLibrary
             return NTStatus.STATUS_SUCCESS;
         }
 
+        public NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength)
+        {
+            output = null;
+            return NTStatus.STATUS_NOT_SUPPORTED;
+        }
+
         public void Log(Severity severity, string message)
         {
             // To be thread-safe we must capture the delegate reference first

+ 22 - 0
SMBLibrary/NTFileStore/Enums/IoControlCode.cs

@@ -0,0 +1,22 @@
+
+namespace SMBLibrary
+{
+    public enum IoControlCode : uint
+    {
+        FSCTL_DFS_GET_REFERRALS = 0x00060194,            // SMB2-specific processing
+        FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0,         // SMB2-specific processing
+        FSCTL_SET_REPARSE_POINT = 0x000900A4,            // SMB2-specific processing
+        FSCTL_FILE_LEVEL_TRIM = 0x00098208,              // SMB2-specific processing
+        FSCTL_PIPE_WAIT = 0x00110018,                    // SMB2-specific processing
+        FSCTL_PIPE_PEEK = 0x0011400C,                    // SMB2-specific processing
+        FSCTL_PIPE_TRANSCEIVE = 0x0011C017,              // SMB2-specific processing
+        FSCTL_SRV_REQUEST_RESUME_KEY = 0x00140078,       // SMB2-specific processing
+        FSCTL_VALIDATE_NEGOTIATE_INFO = 0x00140204,      // SMB2-specific processing
+        FSCTL_LMR_REQUEST_RESILIENCY = 0x001401D4,       // SMB2-specific processing
+        FSCTL_QUERY_NETWORK_INTERFACE_INFO = 0x001401FC, // SMB2-specific processing
+        FSCTL_SRV_ENUMERATE_SNAPSHOTS = 0x00144064,      // SMB2-specific processing
+        FSCTL_SRV_COPYCHUNK = 0x001440F2,                // SMB2-specific processing
+        FSCTL_SRV_READ_HASH = 0x001441BB,                // SMB2-specific processing
+        FSCTL_SRV_COPYCHUNK_WRITE = 0x001480F2,          // SMB2-specific processing
+    }
+}

+ 2 - 0
SMBLibrary/NTFileStore/INTFileStore.cs

@@ -33,5 +33,7 @@ namespace SMBLibrary
         NTStatus SetFileInformation(object handle, FileInformation information);
 
         NTStatus GetFileSystemInformation(out FileSystemInformation result, FileSystemInformationClass informationClass);
+
+        NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength);
     }
 }

+ 22 - 0
SMBLibrary/NTFileStore/NamedPipeStore.cs

@@ -99,6 +99,28 @@ namespace SMBLibrary
             return NTStatus.STATUS_SUCCESS;
         }
 
+        public NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength)
+        {
+            output = null;
+            if (ctlCode == (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE)
+            {
+                int numberOfBytesWritten;
+                NTStatus writeStatus = WriteFile(out numberOfBytesWritten, handle, 0, input);
+                if (writeStatus != NTStatus.STATUS_SUCCESS)
+                {
+                    return writeStatus;
+                }
+                NTStatus readStatus = ReadFile(out output, handle, 0, maxOutputLength);
+                if (readStatus != NTStatus.STATUS_SUCCESS)
+                {
+                    return readStatus;
+                }
+                return NTStatus.STATUS_SUCCESS;
+            }
+
+            return NTStatus.STATUS_NOT_SUPPORTED;
+        }
+
         public NTStatus QueryDirectory(out List<QueryDirectoryFileInformation> result, object directoryHandle, string fileName, FileInformationClass informationClass)
         {
             result = null;

+ 1 - 0
SMBLibrary/SMBLibrary.csproj

@@ -93,6 +93,7 @@
     <Compile Include="NTFileStore\Enums\FileSystemInformation\FileSystemControlFlags.cs" />
     <Compile Include="NTFileStore\Enums\FileSystemInformation\FileSystemInformationClass.cs" />
     <Compile Include="NTFileStore\Enums\FileSystemInformation\SectorSizeInformationFlags.cs" />
+    <Compile Include="NTFileStore\Enums\IoControlCode.cs" />
     <Compile Include="NTFileStore\Enums\NtCreateFile\CreateDisposition.cs" />
     <Compile Include="NTFileStore\Enums\NtCreateFile\CreateOptions.cs" />
     <Compile Include="NTFileStore\Enums\NtCreateFile\FileStatus.cs" />

+ 14 - 11
SMBLibrary/Server/SMB1/NTTransactHelper.cs

@@ -80,7 +80,7 @@ namespace SMBLibrary.Server.SMB1
             }
             else if (subcommand is NTTransactIOCTLRequest)
             {
-                subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand);
+                subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand, share, state);
             }
             else if (subcommand is NTTransactSetSecurityDescriptor)
             {
@@ -112,25 +112,28 @@ namespace SMBLibrary.Server.SMB1
             return response;
         }
 
-        private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand)
+        private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state)
         {
-            const uint FSCTL_CREATE_OR_GET_OBJECT_ID = 0x900C0;
-
+            SMB1Session session = state.GetSession(header.UID);
             NTTransactIOCTLResponse response = new NTTransactIOCTLResponse();
             if (subcommand.IsFsctl)
             {
-                if (subcommand.FunctionCode == FSCTL_CREATE_OR_GET_OBJECT_ID)
+                OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID);
+                if (openFile == null)
                 {
-                    ObjectIDBufferType1 objectID = new ObjectIDBufferType1();
-                    objectID.ObjectId = Guid.NewGuid();
-                    response.Data = objectID.GetBytes();
-                    return response;
+                    header.Status = NTStatus.STATUS_INVALID_HANDLE;
+                    return null;
                 }
-                else
+                int maxOutputLength = UInt16.MaxValue;
+                byte[] output;
+                header.Status = share.FileStore.DeviceIOControl(openFile.Handle, subcommand.FunctionCode, subcommand.Data, out output, maxOutputLength);
+                if (header.Status != NTStatus.STATUS_SUCCESS)
                 {
-                    header.Status = NTStatus.STATUS_NOT_IMPLEMENTED;
                     return null;
                 }
+
+                response.Data = output;
+                return response;
             }
             else
             {

+ 1 - 8
SMBLibrary/Server/SMB1/TransactionHelper.cs

@@ -134,14 +134,7 @@ namespace SMBLibrary.Server.SMB1
             }
             else if (subcommand is TransactionTransactNamedPipeRequest)
             {
-                if (!(share is NamedPipeShare))
-                {
-                    // [MS-CIFS] If the pipe is not a message mode pipe, the Trans subsystem MUST fail the request with STATUS_INVALID_PARAMETER
-                    header.Status = NTStatus.STATUS_INVALID_PARAMETER;
-                    return new ErrorResponse(CommandName.SMB_COM_TRANSACTION);
-                }
-
-                subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, (TransactionTransactNamedPipeRequest)subcommand, (NamedPipeShare)share, state);
+                subcommandResponse = TransactionSubcommandHelper.GetSubcommandResponse(header, (TransactionTransactNamedPipeRequest)subcommand, share, state);
             }
             else if (subcommand is TransactionRawWriteNamedPipeRequest)
             {

+ 6 - 10
SMBLibrary/Server/SMB1/TransactionSubcommandHelper.cs

@@ -16,7 +16,7 @@ namespace SMBLibrary.Server.SMB1
 {
     public class TransactionSubcommandHelper
     {
-        internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, TransactionTransactNamedPipeRequest subcommand, NamedPipeShare share, SMB1ConnectionState state)
+        internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMB1Header header, TransactionTransactNamedPipeRequest subcommand, ISMBShare share, SMB1ConnectionState state)
         {
             SMB1Session session = state.GetSession(header.UID);
             OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID);
@@ -26,19 +26,15 @@ namespace SMBLibrary.Server.SMB1
                 return null;
             }
 
-            TransactionTransactNamedPipeResponse response = new TransactionTransactNamedPipeResponse();
-            int numberOfBytesWritten;
-            header.Status = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, 0, subcommand.WriteData);
-            if (header.Status != NTStatus.STATUS_SUCCESS)
-            {
-                return null;
-            }
-            int maxCount = UInt16.MaxValue;
-            header.Status = share.FileStore.ReadFile(out response.ReadData, openFile.Handle, 0, maxCount);
+            int maxOutputLength = UInt16.MaxValue;
+            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)
             {
                 return null;
             }
+            TransactionTransactNamedPipeResponse response = new TransactionTransactNamedPipeResponse();
+            response.ReadData = output;
             return response;
         }
     }

+ 11 - 25
SMBLibrary/Server/SMB2/IOCtlHelper.cs

@@ -14,14 +14,11 @@ namespace SMBLibrary.Server.SMB2
 {
     public class IOCtlHelper
     {
-        private const uint FSCTL_DFS_GET_REFERRALS = 0x00060194;
-        private const uint FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0;
-        private const uint FSCTL_PIPE_TRANSCEIVE = 0x0011C017;
-
         internal static SMB2Command GetIOCtlResponse(IOCtlRequest request, ISMBShare share, SMB2ConnectionState state)
         {
             SMB2Session session = state.GetSession(request.Header.SessionID);
-            if (request.CtlCode == FSCTL_DFS_GET_REFERRALS || request.CtlCode == FSCTL_DFS_GET_REFERRALS_EX)
+            if (request.CtlCode == (uint)IoControlCode.FSCTL_DFS_GET_REFERRALS ||
+                request.CtlCode == (uint)IoControlCode.FSCTL_DFS_GET_REFERRALS_EX)
             {
                 // [MS-SMB2] 3.3.5.15.2 Handling a DFS Referral Information Request
                 return new ErrorResponse(request.CommandName, NTStatus.STATUS_FS_DRIVER_REQUIRED);
@@ -33,29 +30,18 @@ namespace SMBLibrary.Server.SMB2
                 return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED);
             }
 
-            if (share is NamedPipeShare)
+            int maxOutputLength = (int)request.MaxOutputResponse;
+            byte[] output;
+            NTStatus status = share.FileStore.DeviceIOControl(openFile.Handle, request.CtlCode, request.Input, out output, maxOutputLength);
+            if (status != NTStatus.STATUS_SUCCESS)
             {
-                if (request.CtlCode == FSCTL_PIPE_TRANSCEIVE)
-                {
-                    IOCtlResponse response = new IOCtlResponse();
-                    response.CtlCode = request.CtlCode;
-                    int numberOfBytesWritten;
-                    NTStatus writeStatus = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, 0, request.Input);
-                    if (writeStatus != NTStatus.STATUS_SUCCESS)
-                    {
-                        return new ErrorResponse(request.CommandName, writeStatus);
-                    }
-                    int maxCount = (int)request.MaxOutputResponse;
-                    NTStatus readStatus = share.FileStore.ReadFile(out response.Output, openFile.Handle, 0, maxCount);
-                    if (readStatus != NTStatus.STATUS_SUCCESS)
-                    {
-                        return new ErrorResponse(request.CommandName, readStatus);
-                    }
-                    return response;
-                }
+                return new ErrorResponse(request.CommandName, status);
             }
 
-            return new ErrorResponse(request.CommandName, NTStatus.STATUS_NOT_SUPPORTED);
+            IOCtlResponse response = new IOCtlResponse();
+            response.CtlCode = request.CtlCode;
+            response.Output = output;
+            return response;
         }
     }
 }