diff --git a/SMBLibrary/Enums/NTStatus.cs b/SMBLibrary/Enums/NTStatus.cs index 7cd50be..4c7e1e3 100644 --- a/SMBLibrary/Enums/NTStatus.cs +++ b/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, diff --git a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs b/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs index fb67928..822c9b5 100644 --- a/SMBLibrary/Server/ConnectionState/SMB1ConnectionState.cs +++ b/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. /// /// - 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; } /// Should include the path relative to the file system /// FileID - 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; } diff --git a/SMBLibrary/Server/SMB1/NTCreateHelper.cs b/SMBLibrary/Server/SMB1/NTCreateHelper.cs index e5d1fd4..7d4167b 100644 --- a/SMBLibrary/Server/SMB1/NTCreateHelper.cs +++ b/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; diff --git a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs b/SMBLibrary/Server/SMB1/OpenAndXHelper.cs index 487b0c1..fa1d7dd 100644 --- a/SMBLibrary/Server/SMB1/OpenAndXHelper.cs +++ b/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); } } }