|
@@ -18,24 +18,14 @@ namespace SMBLibrary.Server
|
|
|
public bool LargeWrite;
|
|
|
|
|
|
// Key is UID
|
|
|
- private Dictionary<ushort, string> m_connectedUsers = new Dictionary<ushort, string>();
|
|
|
- private ushort m_nextUID = 1;
|
|
|
+ private Dictionary<ushort, SMB1Session> m_sessions = new Dictionary<ushort, SMB1Session>();
|
|
|
+ private ushort m_nextUID = 1; // UID MUST be unique within an SMB connection
|
|
|
+ private ushort m_nextTID = 1; // TID MUST be unique within an SMB connection
|
|
|
+ private ushort m_nextFID = 1; // FID MUST be unique within an SMB connection
|
|
|
|
|
|
- // Key is TID
|
|
|
- private Dictionary<ushort, ISMBShare> m_connectedTrees = new Dictionary<ushort, ISMBShare>();
|
|
|
- private ushort m_nextTID = 1;
|
|
|
-
|
|
|
- // Key is FID
|
|
|
- private Dictionary<ushort, OpenFileObject> m_openFiles = new Dictionary<ushort, OpenFileObject>();
|
|
|
- private ushort m_nextFID = 1;
|
|
|
-
|
|
|
- // Key is PID
|
|
|
+ // Key is PID (PID MUST be unique within an SMB connection)
|
|
|
private Dictionary<uint, ProcessStateObject> m_processStateList = new Dictionary<uint, ProcessStateObject>();
|
|
|
|
|
|
- private const int MaxSearches = 2048; // Windows servers initialize Server.MaxSearches to 2048.
|
|
|
- public Dictionary<ushort, List<FileSystemEntry>> OpenSearches = new Dictionary<ushort, List<FileSystemEntry>>();
|
|
|
- private ushort m_nextSearchHandle = 1;
|
|
|
-
|
|
|
public SMB1ConnectionState(ConnectionState state) : base(state)
|
|
|
{
|
|
|
}
|
|
@@ -44,7 +34,7 @@ namespace SMBLibrary.Server
|
|
|
/// An open UID MUST be unique within an SMB connection.
|
|
|
/// The value of 0xFFFE SHOULD NOT be used as a valid UID. All other possible values for a UID, excluding zero (0x0000), are valid.
|
|
|
/// </summary>
|
|
|
- private ushort? AllocateUserID()
|
|
|
+ public ushort? AllocateUserID()
|
|
|
{
|
|
|
for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
|
|
|
{
|
|
@@ -53,7 +43,7 @@ namespace SMBLibrary.Server
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- if (!m_connectedUsers.ContainsKey(userID))
|
|
|
+ if (!m_sessions.ContainsKey(userID))
|
|
|
{
|
|
|
m_nextUID = (ushort)(userID + 1);
|
|
|
return userID;
|
|
@@ -62,43 +52,41 @@ namespace SMBLibrary.Server
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public ushort? AddConnectedUser(string userName)
|
|
|
+ public SMB1Session CreateSession(ushort userID, string userName)
|
|
|
{
|
|
|
- ushort? userID = AllocateUserID();
|
|
|
- if (userID.HasValue)
|
|
|
- {
|
|
|
- m_connectedUsers.Add(userID.Value, userName);
|
|
|
- }
|
|
|
- return userID;
|
|
|
+ SMB1Session session = new SMB1Session(this, userID, userName);
|
|
|
+ m_sessions.Add(userID, session);
|
|
|
+ return session;
|
|
|
}
|
|
|
|
|
|
- public string GetConnectedUserName(ushort userID)
|
|
|
+ /// <returns>null if all UserID values have already been allocated</returns>
|
|
|
+ public SMB1Session CreateSession(string userName)
|
|
|
{
|
|
|
- if (m_connectedUsers.ContainsKey(userID))
|
|
|
- {
|
|
|
- return m_connectedUsers[userID];
|
|
|
- }
|
|
|
- else
|
|
|
+ ushort? userID = AllocateUserID();
|
|
|
+ if (userID.HasValue)
|
|
|
{
|
|
|
- return null;
|
|
|
+ return CreateSession(userID.Value, userName);
|
|
|
}
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- public bool IsAuthenticated(ushort userID)
|
|
|
+ public SMB1Session GetSession(ushort userID)
|
|
|
{
|
|
|
- return m_connectedUsers.ContainsKey(userID);
|
|
|
+ SMB1Session session;
|
|
|
+ m_sessions.TryGetValue(userID, out session);
|
|
|
+ return session;
|
|
|
}
|
|
|
|
|
|
- public void RemoveConnectedUser(ushort userID)
|
|
|
+ public void RemoveSession(ushort userID)
|
|
|
{
|
|
|
- m_connectedUsers.Remove(userID);
|
|
|
+ m_sessions.Remove(userID);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// An open TID MUST be unique within an SMB connection.
|
|
|
/// The value 0xFFFF MUST NOT be used as a valid TID. All other possible values for TID, including zero (0x0000), are valid.
|
|
|
/// </summary>
|
|
|
- private ushort? AllocateTreeID()
|
|
|
+ public ushort? AllocateTreeID()
|
|
|
{
|
|
|
for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
|
|
|
{
|
|
@@ -107,7 +95,7 @@ namespace SMBLibrary.Server
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- if (!m_connectedTrees.ContainsKey(treeID))
|
|
|
+ if (!IsTreeIDAllocated(treeID))
|
|
|
{
|
|
|
m_nextTID = (ushort)(treeID + 1);
|
|
|
return treeID;
|
|
@@ -116,72 +104,24 @@ namespace SMBLibrary.Server
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public ushort? AddConnectedTree(ISMBShare share)
|
|
|
- {
|
|
|
- ushort? treeID = AllocateTreeID();
|
|
|
- if (treeID.HasValue)
|
|
|
- {
|
|
|
- m_connectedTrees.Add(treeID.Value, share);
|
|
|
- }
|
|
|
- return treeID;
|
|
|
- }
|
|
|
-
|
|
|
- public ISMBShare GetConnectedTree(ushort treeID)
|
|
|
- {
|
|
|
- if (m_connectedTrees.ContainsKey(treeID))
|
|
|
- {
|
|
|
- return m_connectedTrees[treeID];
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void RemoveConnectedTree(ushort treeID)
|
|
|
- {
|
|
|
- m_connectedTrees.Remove(treeID);
|
|
|
- }
|
|
|
-
|
|
|
- public bool IsTreeConnected(ushort treeID)
|
|
|
- {
|
|
|
- return m_connectedTrees.ContainsKey(treeID);
|
|
|
- }
|
|
|
-
|
|
|
- public ProcessStateObject GetProcessState(uint processID)
|
|
|
- {
|
|
|
- if (m_processStateList.ContainsKey(processID))
|
|
|
- {
|
|
|
- return m_processStateList[processID];
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Get or Create process state
|
|
|
- /// </summary>
|
|
|
- public ProcessStateObject ObtainProcessState(uint processID)
|
|
|
+ private bool IsTreeIDAllocated(ushort treeID)
|
|
|
{
|
|
|
- if (m_processStateList.ContainsKey(processID))
|
|
|
+ foreach (SMB1Session session in m_sessions.Values)
|
|
|
{
|
|
|
- return m_processStateList[processID];
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ProcessStateObject processState = new ProcessStateObject();
|
|
|
- m_processStateList[processID] = processState;
|
|
|
- return processState;
|
|
|
+ if (session.GetConnectedTree(treeID) != null)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
+ /// A FID returned from an Open or Create operation MUST be unique within an SMB connection.
|
|
|
/// 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()
|
|
|
+ public ushort? AllocateFileID()
|
|
|
{
|
|
|
for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
|
|
|
{
|
|
@@ -190,7 +130,7 @@ namespace SMBLibrary.Server
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- if (!m_openFiles.ContainsKey(fileID))
|
|
|
+ if (!IsFileIDAllocated(fileID))
|
|
|
{
|
|
|
m_nextFID = (ushort)(fileID + 1);
|
|
|
return fileID;
|
|
@@ -199,33 +139,23 @@ namespace SMBLibrary.Server
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /// <param name="relativePath">Should include the path relative to the share</param>
|
|
|
- /// <returns>FileID</returns>
|
|
|
- public ushort? AddOpenFile(string relativePath)
|
|
|
- {
|
|
|
- return AddOpenFile(relativePath, null);
|
|
|
- }
|
|
|
-
|
|
|
- public ushort? AddOpenFile(string relativePath, Stream stream)
|
|
|
+ private bool IsFileIDAllocated(ushort fileID)
|
|
|
{
|
|
|
- return AddOpenFile(relativePath, stream, false);
|
|
|
- }
|
|
|
-
|
|
|
- public ushort? AddOpenFile(string relativePath, Stream stream, bool deleteOnClose)
|
|
|
- {
|
|
|
- ushort? fileID = AllocateFileID();
|
|
|
- if (fileID.HasValue)
|
|
|
+ foreach (SMB1Session session in m_sessions.Values)
|
|
|
{
|
|
|
- m_openFiles.Add(fileID.Value, new OpenFileObject(relativePath, stream, deleteOnClose));
|
|
|
+ if (session.GetOpenFileObject(fileID) != null)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
- return fileID;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- public OpenFileObject GetOpenFileObject(ushort fileID)
|
|
|
+ public ProcessStateObject GetProcessState(uint processID)
|
|
|
{
|
|
|
- if (m_openFiles.ContainsKey(fileID))
|
|
|
+ if (m_processStateList.ContainsKey(processID))
|
|
|
{
|
|
|
- return m_openFiles[fileID];
|
|
|
+ return m_processStateList[processID];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -233,15 +163,21 @@ namespace SMBLibrary.Server
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void RemoveOpenFile(ushort fileID)
|
|
|
+ /// <summary>
|
|
|
+ /// Get or Create process state
|
|
|
+ /// </summary>
|
|
|
+ public ProcessStateObject ObtainProcessState(uint processID)
|
|
|
{
|
|
|
- Stream stream = m_openFiles[fileID].Stream;
|
|
|
- if (stream != null)
|
|
|
+ if (m_processStateList.ContainsKey(processID))
|
|
|
{
|
|
|
- LogToServer(Severity.Verbose, "Closing file '{0}'", m_openFiles[fileID].Path);
|
|
|
- stream.Close();
|
|
|
+ return m_processStateList[processID];
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ProcessStateObject processState = new ProcessStateObject();
|
|
|
+ m_processStateList[processID] = processState;
|
|
|
+ return processState;
|
|
|
}
|
|
|
- m_openFiles.Remove(fileID);
|
|
|
}
|
|
|
|
|
|
public uint? GetMaxDataCount(uint processID)
|
|
@@ -256,31 +192,5 @@ namespace SMBLibrary.Server
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- public ushort? AllocateSearchHandle()
|
|
|
- {
|
|
|
- for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
|
|
|
- {
|
|
|
- ushort searchHandle = (ushort)(m_nextSearchHandle + offset);
|
|
|
- if (searchHandle == 0 || searchHandle == 0xFFFF)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (!OpenSearches.ContainsKey(searchHandle))
|
|
|
- {
|
|
|
- m_nextSearchHandle = (ushort)(searchHandle + 1);
|
|
|
- return searchHandle;
|
|
|
- }
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- public void ReleaseSearchHandle(ushort searchHandle)
|
|
|
- {
|
|
|
- if (OpenSearches.ContainsKey(searchHandle))
|
|
|
- {
|
|
|
- OpenSearches.Remove(searchHandle);
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|