StateObject.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* Copyright (C) 2014-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Net.Sockets;
  11. using System.Text;
  12. using Utilities;
  13. namespace SMBLibrary.Server
  14. {
  15. public class StateObject
  16. {
  17. public Socket ClientSocket = null;
  18. public const int ReceiveBufferSize = 65536;
  19. public byte[] ReceiveBuffer = new byte[ReceiveBufferSize]; // immediate receive buffer
  20. public byte[] ConnectionBuffer = new byte[0]; // we append the receive buffer here until we have a complete Message
  21. public int MaxBufferSize;
  22. public bool LargeRead;
  23. public bool LargeWrite;
  24. // Key is UID
  25. private Dictionary<ushort, string> m_connectedUsers = new Dictionary<ushort, string>();
  26. private ushort m_nextUID = 1;
  27. // Key is TID
  28. private Dictionary<ushort, string> m_connectedTrees = new Dictionary<ushort, string>();
  29. private ushort m_nextTID = 1;
  30. // Key is FID
  31. private Dictionary<ushort, OpenedFileObject> m_openedFiles = new Dictionary<ushort, OpenedFileObject>();
  32. private ushort m_nextFID = 1;
  33. // Key is FID
  34. private Dictionary<ushort, byte[]> m_namedPipeResponse = new Dictionary<ushort, byte[]>();
  35. // Key is PID
  36. public Dictionary<uint, ProcessStateObject> ProcessStateList = new Dictionary<uint, ProcessStateObject>();
  37. public const int MaxSearches = 2048; // Windows servers initialize Server.MaxSearches to 2048.
  38. public Dictionary<ushort, List<FileSystemEntry>> OpenSearches = new Dictionary<ushort, List<FileSystemEntry>>();
  39. private ushort m_nextSearchHandle = 1;
  40. /// <summary>
  41. /// An open UID MUST be unique within an SMB connection.
  42. /// The value of 0xFFFE SHOULD NOT be used as a valid UID. All other possible values for a UID, excluding zero (0x0000), are valid.
  43. /// </summary>
  44. private ushort AllocateUserID()
  45. {
  46. while (m_connectedUsers.ContainsKey(m_nextUID) || m_nextUID == 0 || m_nextUID == 0xFFFE || m_nextUID == 0xFFFF)
  47. {
  48. m_nextUID++;
  49. }
  50. ushort userID = m_nextUID;
  51. m_nextUID++;
  52. return userID;
  53. }
  54. public ushort AddConnectedUser(string userName)
  55. {
  56. ushort userID = AllocateUserID();
  57. m_connectedUsers.Add(userID, userName);
  58. return userID;
  59. }
  60. public string GetConnectedUserName(ushort userID)
  61. {
  62. if (m_connectedUsers.ContainsKey(userID))
  63. {
  64. return m_connectedUsers[userID];
  65. }
  66. else
  67. {
  68. return null;
  69. }
  70. }
  71. public bool IsAuthenticated(ushort userID)
  72. {
  73. return m_connectedUsers.ContainsKey(userID);
  74. }
  75. public void RemoveConnectedUser(ushort userID)
  76. {
  77. m_connectedUsers.Remove(userID);
  78. }
  79. /// <summary>
  80. /// An open TID MUST be unique within an SMB connection.
  81. /// The value 0xFFFF MUST NOT be used as a valid TID. All other possible values for TID, including zero (0x0000), are valid.
  82. /// </summary>
  83. private ushort AllocateTreeID()
  84. {
  85. while (m_connectedTrees.ContainsKey(m_nextTID) || m_nextTID == 0 || m_nextTID == 0xFFFF)
  86. {
  87. m_nextTID++;
  88. }
  89. ushort treeID = m_nextTID;
  90. m_nextTID++;
  91. return treeID;
  92. }
  93. public ushort AddConnectedTree(string relativePath)
  94. {
  95. ushort treeID = AllocateTreeID();
  96. m_connectedTrees.Add(treeID, relativePath);
  97. return treeID;
  98. }
  99. public string GetConnectedTreePath(ushort treeID)
  100. {
  101. if (m_connectedTrees.ContainsKey(treeID))
  102. {
  103. return m_connectedTrees[treeID];
  104. }
  105. else
  106. {
  107. return null;
  108. }
  109. }
  110. public void RemoveConnectedTree(ushort treeID)
  111. {
  112. m_connectedTrees.Remove(treeID);
  113. }
  114. public bool IsTreeConnected(ushort treeID)
  115. {
  116. return m_connectedTrees.ContainsKey(treeID);
  117. }
  118. public bool IsIPC(ushort treeID)
  119. {
  120. string relativePath = GetConnectedTreePath(treeID);
  121. return String.Equals(relativePath, "\\IPC$", StringComparison.InvariantCultureIgnoreCase);
  122. }
  123. public ProcessStateObject GetProcessState(uint processID)
  124. {
  125. if (ProcessStateList.ContainsKey(processID))
  126. {
  127. return ProcessStateList[processID];
  128. }
  129. else
  130. {
  131. return null;
  132. }
  133. }
  134. /// <summary>
  135. /// Get or Create process state
  136. /// </summary>
  137. public ProcessStateObject ObtainProcessState(uint processID)
  138. {
  139. if (ProcessStateList.ContainsKey(processID))
  140. {
  141. return ProcessStateList[processID];
  142. }
  143. else
  144. {
  145. ProcessStateObject processState = new ProcessStateObject();
  146. ProcessStateList[processID] = processState;
  147. return processState;
  148. }
  149. }
  150. /// <summary>
  151. /// The value 0xFFFF MUST NOT be used as a valid FID. All other possible values for FID, including zero (0x0000) are valid.
  152. /// </summary>
  153. /// <returns></returns>
  154. private ushort AllocateFileID()
  155. {
  156. while (m_openedFiles.ContainsKey(m_nextFID) || m_nextFID == 0 || m_nextFID == 0xFFFF)
  157. {
  158. m_nextFID++;
  159. }
  160. ushort fileID = m_nextFID;
  161. m_nextFID++;
  162. return fileID;
  163. }
  164. /// <param name="relativePath">Should include the path relative to the file system</param>
  165. /// <returns>FileID</returns>
  166. public ushort AddOpenedFile(string relativePath)
  167. {
  168. return AddOpenedFile(relativePath, null);
  169. }
  170. public ushort AddOpenedFile(string relativePath, Stream stream)
  171. {
  172. ushort fileID = AllocateFileID();
  173. m_openedFiles.Add(fileID, new OpenedFileObject(relativePath, stream));
  174. return fileID;
  175. }
  176. public string GetOpenedFilePath(ushort fileID)
  177. {
  178. if (m_openedFiles.ContainsKey(fileID))
  179. {
  180. return m_openedFiles[fileID].Path;
  181. }
  182. else
  183. {
  184. return null;
  185. }
  186. }
  187. public OpenedFileObject GetOpenedFileObject(ushort fileID)
  188. {
  189. if (m_openedFiles.ContainsKey(fileID))
  190. {
  191. return m_openedFiles[fileID];
  192. }
  193. else
  194. {
  195. return null;
  196. }
  197. }
  198. public bool IsFileOpen(ushort fileID)
  199. {
  200. return m_openedFiles.ContainsKey(fileID);
  201. }
  202. public void RemoveOpenedFile(ushort fileID)
  203. {
  204. Stream stream = m_openedFiles[fileID].Stream;
  205. if (stream != null)
  206. {
  207. System.Diagnostics.Debug.Print("[{0}] Closing file '{1}'", DateTime.Now.ToString("HH:mm:ss:ffff"), m_openedFiles[fileID].Path);
  208. stream.Close();
  209. }
  210. m_openedFiles.Remove(fileID);
  211. }
  212. public void StoreNamedPipeReply(ushort fileID, byte[] response)
  213. {
  214. m_namedPipeResponse.Add(fileID, response);
  215. }
  216. public byte[] RetrieveNamedPipeReply(ushort fileID)
  217. {
  218. if (m_namedPipeResponse.ContainsKey(fileID))
  219. {
  220. byte[] result = m_namedPipeResponse[fileID];
  221. m_namedPipeResponse.Remove(fileID);
  222. return result;
  223. }
  224. else
  225. {
  226. return new byte[0];
  227. }
  228. }
  229. public uint? GetMaxDataCount(uint processID)
  230. {
  231. ProcessStateObject processState = GetProcessState(processID);
  232. if (processState != null)
  233. {
  234. return processState.MaxDataCount;
  235. }
  236. else
  237. {
  238. return null;
  239. }
  240. }
  241. public ushort AllocateSearchHandle()
  242. {
  243. while (OpenSearches.ContainsKey(m_nextSearchHandle) || m_nextSearchHandle == 0 || m_nextSearchHandle == 0xFFFF)
  244. {
  245. m_nextSearchHandle++;
  246. }
  247. ushort searchHandle = m_nextSearchHandle;
  248. m_nextSearchHandle++;
  249. return searchHandle;
  250. }
  251. public void ReleaseSearchHandle(ushort searchHandle)
  252. {
  253. if (OpenSearches.ContainsKey(searchHandle))
  254. {
  255. OpenSearches.Remove(searchHandle);
  256. }
  257. }
  258. }
  259. }