Jelajahi Sumber

Improved FID (File ID) allocation mechanism

Tal Aloni 8 tahun lalu
induk
melakukan
c11b987320

+ 1 - 0
SMBLibrary/Enums/NTStatus.cs

@@ -26,6 +26,7 @@ namespace SMBLibrary
         STATUS_MEDIA_WRITE_PROTECTED = 0xC00000A2,
         STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
         STATUS_NOT_SUPPORTED = 0xC00000BB,
+        STATUS_TOO_MANY_OPENED_FILES = 0xC000011F,
         STATUS_CANNOT_DELETE = 0xC0000121,
         STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,
         

+ 21 - 11
SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs

@@ -178,33 +178,43 @@ namespace SMBLibrary.Server
         /// The value 0xFFFF MUST NOT be used as a valid FID. All other possible values for FID, including zero (0x0000) are valid.
         /// </summary>
         /// <returns></returns>
-        private ushort AllocateFileID()
+        private ushort? AllocateFileID()
         {
-            while (m_openedFiles.ContainsKey(m_nextFID) || m_nextFID == 0 || m_nextFID == 0xFFFF)
+            for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
             {
-                m_nextFID++;
+                ushort fileID = (ushort)(m_nextFID + offset);
+                if (fileID == 0 || fileID == 0xFFFF)
+                {
+                    continue;
+                }
+                if (!m_openedFiles.ContainsKey(fileID))
+                {
+                    m_nextFID = (ushort)(fileID + 1);
+                    return fileID;
+                }
             }
-            ushort fileID = m_nextFID;
-            m_nextFID++;
-            return fileID;
+            return null;
         }
 
         /// <param name="relativePath">Should include the path relative to the file system</param>
         /// <returns>FileID</returns>
-        public ushort AddOpenedFile(string relativePath)
+        public ushort? AddOpenedFile(string relativePath)
         {
             return AddOpenedFile(relativePath, null);
         }
 
-        public ushort AddOpenedFile(string relativePath, Stream stream)
+        public ushort? AddOpenedFile(string relativePath, Stream stream)
         {
             return AddOpenedFile(relativePath, stream, false);
         }
 
-        public ushort AddOpenedFile(string relativePath, Stream stream, bool deleteOnClose)
+        public ushort? AddOpenedFile(string relativePath, Stream stream, bool deleteOnClose)
         {
-            ushort fileID = AllocateFileID();
-            m_openedFiles.Add(fileID, new OpenedFileObject(relativePath, stream, deleteOnClose));
+            ushort? fileID = AllocateFileID();
+            if (fileID.HasValue)
+            {
+                m_openedFiles.Add(fileID.Value, new OpenedFileObject(relativePath, stream, deleteOnClose));
+            }
             return fileID;
         }
 

+ 16 - 6
SMBLibrary/Server/SMB1/NTCreateHelper.cs

@@ -25,14 +25,19 @@ namespace SMBLibrary.Server.SMB1
                 RemoteService service = ((NamedPipeShare)share).GetService(path);
                 if (service != null)
                 {
-                    ushort fileID = state.AddOpenedFile(path);
+                    ushort? fileID = state.AddOpenedFile(path);
+                    if (!fileID.HasValue)
+                    {
+                        header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
+                        return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
+                    }
                     if (isExtended)
                     {
-                        return CreateResponseExtendedForNamedPipe(fileID);
+                        return CreateResponseExtendedForNamedPipe(fileID.Value);
                     }
                     else
                     {
-                        return CreateResponseForNamedPipe(fileID);
+                        return CreateResponseForNamedPipe(fileID.Value);
                     }
                 }
 
@@ -294,10 +299,15 @@ namespace SMBLibrary.Server.SMB1
                     }
                 }
 
-                ushort fileID = state.AddOpenedFile(path, stream, deleteOnClose);
+                ushort? fileID = state.AddOpenedFile(path, stream, deleteOnClose);
+                if (!fileID.HasValue)
+                {
+                    header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
+                    return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
+                }
                 if (isExtended)
                 {
-                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID);
+                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID.Value);
                     if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                     {
                         response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
@@ -306,7 +316,7 @@ namespace SMBLibrary.Server.SMB1
                 }
                 else
                 {
-                    NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID);
+                    NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID.Value);
                     if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                     {
                         response.OpLockLevel = OpLockLevel.BatchOpLockGranted;

+ 16 - 6
SMBLibrary/Server/SMB1/OpenAndXHelper.cs

@@ -25,14 +25,19 @@ namespace SMBLibrary.Server.SMB1
                 RemoteService service = ((NamedPipeShare)share).GetService(path);
                 if (service != null)
                 {
-                    ushort fileID = state.AddOpenedFile(path);
+                    ushort? fileID = state.AddOpenedFile(path);
+                    if (!fileID.HasValue)
+                    {
+                        header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
+                        return new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX);
+                    }
                     if (isExtended)
                     {
-                        return CreateResponseExtendedForNamedPipe(fileID);
+                        return CreateResponseExtendedForNamedPipe(fileID.Value);
                     }
                     else
                     {
-                        return CreateResponseForNamedPipe(fileID);
+                        return CreateResponseForNamedPipe(fileID.Value);
                     }
                 }
 
@@ -128,14 +133,19 @@ namespace SMBLibrary.Server.SMB1
                         stream = new PrefetchedStream(stream);
                     }
                 }
-                ushort fileID = state.AddOpenedFile(path, stream);
+                ushort? fileID = state.AddOpenedFile(path, stream);
+                if (!fileID.HasValue)
+                {
+                    header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
+                    return new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX);
+                }
                 if (isExtended)
                 {
-                    return CreateResponseExtendedFromFileSystemEntry(entry, fileID, openResult);
+                    return CreateResponseExtendedFromFileSystemEntry(entry, fileID.Value, openResult);
                 }
                 else
                 {
-                    return CreateResponseFromFileSystemEntry(entry, fileID, openResult);
+                    return CreateResponseFromFileSystemEntry(entry, fileID.Value, openResult);
                 }
             }
         }