SMB1ConnectionState.cs 9.4 KB

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