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);
}
}
}