SMBServer.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  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;
  11. using System.Net.Sockets;
  12. using System.Text;
  13. using SMBLibrary.NetBios;
  14. using SMBLibrary.SMB1;
  15. using SMBLibrary.Services;
  16. using Utilities;
  17. namespace SMBLibrary.Server
  18. {
  19. public class SMBServer
  20. {
  21. public const int NetBiosOverTCPPort = 139;
  22. public const int DirectTCPPort = 445;
  23. public const string NTLanManagerDialect = "NT LM 0.12";
  24. public const bool EnableExtendedSecurity = true;
  25. private ShareCollection m_shares; // e.g. Shared folders
  26. private INTLMAuthenticationProvider m_users;
  27. private NamedPipeShare m_services; // Named pipes
  28. private IPAddress m_serverAddress;
  29. private SMBTransportType m_transport;
  30. private Socket m_listenerSocket;
  31. private bool m_listening;
  32. private Guid m_serverGuid;
  33. public SMBServer(ShareCollection shares, INTLMAuthenticationProvider users, IPAddress serverAddress, SMBTransportType transport)
  34. {
  35. m_shares = shares;
  36. m_users = users;
  37. m_serverAddress = serverAddress;
  38. m_serverGuid = Guid.NewGuid();
  39. m_transport = transport;
  40. m_services = new NamedPipeShare(shares.ListShares());
  41. }
  42. public void Start()
  43. {
  44. if (!m_listening)
  45. {
  46. m_listening = true;
  47. m_listenerSocket = new Socket(m_serverAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  48. int port = (m_transport == SMBTransportType.DirectTCPTransport ? DirectTCPPort : NetBiosOverTCPPort);
  49. m_listenerSocket.Bind(new IPEndPoint(m_serverAddress, port));
  50. m_listenerSocket.Listen((int)SocketOptionName.MaxConnections);
  51. m_listenerSocket.BeginAccept(ConnectRequestCallback, m_listenerSocket);
  52. }
  53. }
  54. public void Stop()
  55. {
  56. m_listening = false;
  57. SocketUtils.ReleaseSocket(m_listenerSocket);
  58. }
  59. // This method Accepts new connections
  60. private void ConnectRequestCallback(IAsyncResult ar)
  61. {
  62. System.Diagnostics.Debug.Print("[{0}] New connection request", DateTime.Now.ToString("HH:mm:ss:ffff"));
  63. Socket listenerSocket = (Socket)ar.AsyncState;
  64. Socket clientSocket;
  65. try
  66. {
  67. clientSocket = listenerSocket.EndAccept(ar);
  68. }
  69. catch (ObjectDisposedException)
  70. {
  71. return;
  72. }
  73. catch (SocketException ex)
  74. {
  75. const int WSAECONNRESET = 10054;
  76. // Client may have closed the connection before we start to process the connection request.
  77. // When we get this error, we have to continue to accept other requests.
  78. // See http://stackoverflow.com/questions/7704417/socket-endaccept-error-10054
  79. if (ex.ErrorCode == WSAECONNRESET)
  80. {
  81. m_listenerSocket.BeginAccept(ConnectRequestCallback, m_listenerSocket);
  82. }
  83. System.Diagnostics.Debug.Print("[{0}] Connection request error {1}", DateTime.Now.ToString("HH:mm:ss:ffff"), ex.ErrorCode);
  84. return;
  85. }
  86. StateObject state = new StateObject();
  87. state.ReceiveBuffer = new byte[StateObject.ReceiveBufferSize];
  88. // Disable the Nagle Algorithm for this tcp socket:
  89. clientSocket.NoDelay = true;
  90. state.ClientSocket = clientSocket;
  91. try
  92. {
  93. clientSocket.BeginReceive(state.ReceiveBuffer, 0, StateObject.ReceiveBufferSize, 0, ReceiveCallback, state);
  94. }
  95. catch (ObjectDisposedException)
  96. {
  97. }
  98. catch (SocketException)
  99. {
  100. }
  101. m_listenerSocket.BeginAccept(ConnectRequestCallback, m_listenerSocket);
  102. }
  103. private void ReceiveCallback(IAsyncResult result)
  104. {
  105. StateObject state = (StateObject)result.AsyncState;
  106. Socket clientSocket = state.ClientSocket;
  107. if (!m_listening)
  108. {
  109. clientSocket.Close();
  110. return;
  111. }
  112. byte[] receiveBuffer = state.ReceiveBuffer;
  113. int bytesReceived;
  114. try
  115. {
  116. bytesReceived = clientSocket.EndReceive(result);
  117. }
  118. catch (ObjectDisposedException)
  119. {
  120. return;
  121. }
  122. catch (SocketException)
  123. {
  124. return;
  125. }
  126. if (bytesReceived == 0)
  127. {
  128. // The other side has closed the connection
  129. System.Diagnostics.Debug.Print("[{0}] The other side closed the connection", DateTime.Now.ToString("HH:mm:ss:ffff"));
  130. clientSocket.Close();
  131. return;
  132. }
  133. byte[] currentBuffer = new byte[bytesReceived];
  134. Array.Copy(receiveBuffer, currentBuffer, bytesReceived);
  135. ProcessCurrentBuffer(currentBuffer, state);
  136. if (clientSocket.Connected)
  137. {
  138. try
  139. {
  140. clientSocket.BeginReceive(state.ReceiveBuffer, 0, StateObject.ReceiveBufferSize, 0, ReceiveCallback, state);
  141. }
  142. catch (ObjectDisposedException)
  143. {
  144. }
  145. catch (SocketException)
  146. {
  147. }
  148. }
  149. }
  150. public void ProcessCurrentBuffer(byte[] currentBuffer, StateObject state)
  151. {
  152. Socket clientSocket = state.ClientSocket;
  153. if (state.ConnectionBuffer.Length == 0)
  154. {
  155. state.ConnectionBuffer = currentBuffer;
  156. }
  157. else
  158. {
  159. byte[] oldConnectionBuffer = state.ConnectionBuffer;
  160. state.ConnectionBuffer = new byte[oldConnectionBuffer.Length + currentBuffer.Length];
  161. Array.Copy(oldConnectionBuffer, state.ConnectionBuffer, oldConnectionBuffer.Length);
  162. Array.Copy(currentBuffer, 0, state.ConnectionBuffer, oldConnectionBuffer.Length, currentBuffer.Length);
  163. }
  164. // we now have all SMB message bytes received so far in state.ConnectionBuffer
  165. int bytesLeftInBuffer = state.ConnectionBuffer.Length;
  166. while (bytesLeftInBuffer >= 4)
  167. {
  168. // The packet is either Direct TCP transport packet (which is an NBT Session Message
  169. // Packet) or an NBT packet.
  170. int bufferOffset = state.ConnectionBuffer.Length - bytesLeftInBuffer;
  171. byte flags = ByteReader.ReadByte(state.ConnectionBuffer, bufferOffset + 1);
  172. int trailerLength = (flags & 0x01) << 16 | BigEndianConverter.ToUInt16(state.ConnectionBuffer, bufferOffset + 2);
  173. int packetLength = 4 + trailerLength;
  174. if (flags > 0x01)
  175. {
  176. System.Diagnostics.Debug.Print("[{0}] Invalid NBT flags", DateTime.Now.ToString("HH:mm:ss:ffff"));
  177. state.ClientSocket.Close();
  178. return;
  179. }
  180. if (packetLength > bytesLeftInBuffer)
  181. {
  182. break;
  183. }
  184. else
  185. {
  186. byte[] packetBytes = new byte[packetLength];
  187. Array.Copy(state.ConnectionBuffer, bufferOffset, packetBytes, 0, packetLength);
  188. ProcessPacket(packetBytes, state);
  189. bytesLeftInBuffer -= packetLength;
  190. if (!clientSocket.Connected)
  191. {
  192. // Do not continue to process the buffer if the other side closed the connection
  193. return;
  194. }
  195. }
  196. }
  197. if (bytesLeftInBuffer > 0)
  198. {
  199. byte[] newReceiveBuffer = new byte[bytesLeftInBuffer];
  200. Array.Copy(state.ConnectionBuffer, state.ConnectionBuffer.Length - bytesLeftInBuffer, newReceiveBuffer, 0, bytesLeftInBuffer);
  201. state.ConnectionBuffer = newReceiveBuffer;
  202. }
  203. else
  204. {
  205. state.ConnectionBuffer = new byte[0];
  206. }
  207. }
  208. public void ProcessPacket(byte[] packetBytes, StateObject state)
  209. {
  210. SessionPacket packet = null;
  211. #if DEBUG
  212. packet = SessionPacket.GetSessionPacket(packetBytes);
  213. #else
  214. try
  215. {
  216. packet = SessionPacket.GetSessionPacket(packetBytes);
  217. }
  218. catch (Exception)
  219. {
  220. state.ClientSocket.Close();
  221. return;
  222. }
  223. #endif
  224. if (packet is SessionRequestPacket && m_transport == SMBTransportType.NetBiosOverTCP)
  225. {
  226. PositiveSessionResponsePacket response = new PositiveSessionResponsePacket();
  227. TrySendPacket(state, response);
  228. }
  229. else if (packet is SessionKeepAlivePacket && m_transport == SMBTransportType.NetBiosOverTCP)
  230. {
  231. // [RFC 1001] NetBIOS session keep alives do not require a response from the NetBIOS peer
  232. }
  233. else if (packet is SessionMessagePacket)
  234. {
  235. SMBMessage message = null;
  236. #if DEBUG
  237. message = SMBMessage.GetSMBMessage(packet.Trailer);
  238. System.Diagnostics.Debug.Print("[{0}] Message Received: {1} Commands, First Command: {2}, Packet length: {3}", DateTime.Now.ToString("HH:mm:ss:ffff"), message.Commands.Count, message.Commands[0].CommandName.ToString(), packet.Length);
  239. #else
  240. try
  241. {
  242. message = SMBMessage.GetSMBMessage(packet.Trailer);
  243. }
  244. catch (Exception)
  245. {
  246. state.ClientSocket.Close();
  247. return;
  248. }
  249. #endif
  250. ProcessMessage(message, state);
  251. }
  252. else
  253. {
  254. System.Diagnostics.Debug.Print("[{0}] Invalid NetBIOS packet", DateTime.Now.ToString("HH:mm:ss:ffff"));
  255. state.ClientSocket.Close();
  256. return;
  257. }
  258. }
  259. public void ProcessMessage(SMBMessage message, StateObject state)
  260. {
  261. SMBMessage reply = new SMBMessage();
  262. PrepareResponseHeader(reply, message);
  263. List<SMBCommand> sendQueue = new List<SMBCommand>();
  264. foreach (SMBCommand command in message.Commands)
  265. {
  266. SMBCommand response = ProcessCommand(reply.Header, command, state, sendQueue);
  267. if (response != null)
  268. {
  269. reply.Commands.Add(response);
  270. }
  271. if (reply.Header.Status != NTStatus.STATUS_SUCCESS)
  272. {
  273. break;
  274. }
  275. }
  276. if (reply.Commands.Count > 0)
  277. {
  278. TrySendMessage(state, reply);
  279. foreach (SMBCommand command in sendQueue)
  280. {
  281. SMBMessage secondaryReply = new SMBMessage();
  282. secondaryReply.Header = reply.Header;
  283. secondaryReply.Commands.Add(command);
  284. TrySendMessage(state, secondaryReply);
  285. }
  286. }
  287. }
  288. /// <summary>
  289. /// May return null
  290. /// </summary>
  291. public SMBCommand ProcessCommand(SMBHeader header, SMBCommand command, StateObject state, List<SMBCommand> sendQueue)
  292. {
  293. if (command is NegotiateRequest)
  294. {
  295. NegotiateRequest request = (NegotiateRequest)command;
  296. if (request.Dialects.Contains(SMBServer.NTLanManagerDialect))
  297. {
  298. if (EnableExtendedSecurity && header.ExtendedSecurityFlag)
  299. {
  300. return NegotiateHelper.GetNegotiateResponseExtended(request, m_serverGuid);
  301. }
  302. else
  303. {
  304. byte[] serverChallenge = m_users.GenerateServerChallenge();
  305. return NegotiateHelper.GetNegotiateResponse(header, request, serverChallenge);
  306. }
  307. }
  308. else
  309. {
  310. return new NegotiateResponseNotSupported();
  311. }
  312. }
  313. else if (command is SessionSetupAndXRequest)
  314. {
  315. SessionSetupAndXRequest request = (SessionSetupAndXRequest)command;
  316. state.MaxBufferSize = request.MaxBufferSize;
  317. return NegotiateHelper.GetSessionSetupResponse(header, request, m_users, state);
  318. }
  319. else if (command is SessionSetupAndXRequestExtended)
  320. {
  321. SessionSetupAndXRequestExtended request = (SessionSetupAndXRequestExtended)command;
  322. state.MaxBufferSize = request.MaxBufferSize;
  323. return NegotiateHelper.GetSessionSetupResponseExtended(header, request, m_users, state);
  324. }
  325. else if (command is EchoRequest)
  326. {
  327. return ServerResponseHelper.GetEchoResponse((EchoRequest)command, sendQueue);
  328. }
  329. else if (state.IsAuthenticated(header.UID))
  330. {
  331. if (command is TreeConnectAndXRequest)
  332. {
  333. TreeConnectAndXRequest request = (TreeConnectAndXRequest)command;
  334. return TreeConnectHelper.GetTreeConnectResponse(header, request, state, m_shares);
  335. }
  336. else if (command is LogoffAndXRequest)
  337. {
  338. return new LogoffAndXResponse();
  339. }
  340. else if (state.IsTreeConnected(header.TID))
  341. {
  342. string rootPath = state.GetConnectedTreePath(header.TID);
  343. object share;
  344. if (state.IsIPC(header.TID))
  345. {
  346. share = m_services;
  347. }
  348. else
  349. {
  350. share = m_shares.GetShareFromRelativePath(rootPath);
  351. }
  352. if (command is CreateDirectoryRequest)
  353. {
  354. if (!(share is FileSystemShare))
  355. {
  356. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  357. return new ErrorResponse(command.CommandName);
  358. }
  359. CreateDirectoryRequest request = (CreateDirectoryRequest)command;
  360. return FileSystemResponseHelper.GetCreateDirectoryResponse(header, request, (FileSystemShare)share, state);
  361. }
  362. else if (command is DeleteDirectoryRequest)
  363. {
  364. if (!(share is FileSystemShare))
  365. {
  366. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  367. return new ErrorResponse(command.CommandName);
  368. }
  369. DeleteDirectoryRequest request = (DeleteDirectoryRequest)command;
  370. return FileSystemResponseHelper.GetDeleteDirectoryResponse(header, request, (FileSystemShare)share, state);
  371. }
  372. else if (command is CloseRequest)
  373. {
  374. CloseRequest request = (CloseRequest)command;
  375. return ServerResponseHelper.GetCloseResponse(header, request, state);
  376. }
  377. else if (command is FlushRequest)
  378. {
  379. return new FlushResponse();
  380. }
  381. else if (command is DeleteRequest)
  382. {
  383. if (!(share is FileSystemShare))
  384. {
  385. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  386. return new ErrorResponse(command.CommandName);
  387. }
  388. DeleteRequest request = (DeleteRequest)command;
  389. return FileSystemResponseHelper.GetDeleteResponse(header, request, (FileSystemShare)share, state);
  390. }
  391. else if (command is RenameRequest)
  392. {
  393. if (!(share is FileSystemShare))
  394. {
  395. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  396. return new ErrorResponse(command.CommandName);
  397. }
  398. RenameRequest request = (RenameRequest)command;
  399. return FileSystemResponseHelper.GetRenameResponse(header, request, (FileSystemShare)share, state);
  400. }
  401. else if (command is QueryInformationRequest)
  402. {
  403. if (!(share is FileSystemShare))
  404. {
  405. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  406. return new ErrorResponse(command.CommandName);
  407. }
  408. QueryInformationRequest request = (QueryInformationRequest)command;
  409. return FileSystemResponseHelper.GetQueryInformationResponse(header, request, (FileSystemShare)share);
  410. }
  411. else if (command is SetInformationRequest)
  412. {
  413. if (!(share is FileSystemShare))
  414. {
  415. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  416. return new ErrorResponse(command.CommandName);
  417. }
  418. SetInformationRequest request = (SetInformationRequest)command;
  419. return FileSystemResponseHelper.GetSetInformationResponse(header, request, (FileSystemShare)share, state);
  420. }
  421. else if (command is ReadRequest)
  422. {
  423. ReadRequest request = (ReadRequest)command;
  424. return ReadWriteResponseHelper.GetReadResponse(header, request, share, state);
  425. }
  426. else if (command is WriteRequest)
  427. {
  428. string userName = state.GetConnectedUserName(header.UID);
  429. if (share is FileSystemShare && !((FileSystemShare)share).HasWriteAccess(userName))
  430. {
  431. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  432. return new ErrorResponse(command.CommandName);
  433. }
  434. WriteRequest request = (WriteRequest)command;
  435. return ReadWriteResponseHelper.GetWriteResponse(header, request, share, state);
  436. }
  437. else if (command is CheckDirectoryRequest)
  438. {
  439. if (!(share is FileSystemShare))
  440. {
  441. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  442. return new ErrorResponse(command.CommandName);
  443. }
  444. CheckDirectoryRequest request = (CheckDirectoryRequest)command;
  445. return FileSystemResponseHelper.GetCheckDirectoryResponse(header, request, (FileSystemShare)share);
  446. }
  447. else if (command is WriteRawRequest)
  448. {
  449. // [MS-CIFS] 3.3.5.26 - Receiving an SMB_COM_WRITE_RAW Request:
  450. // the server MUST verify that the Server.Capabilities include CAP_RAW_MODE,
  451. // If an error is detected [..] the Write Raw operation MUST fail and
  452. // the server MUST return a Final Server Response [..] with the Count field set to zero.
  453. return new WriteRawFinalResponse();
  454. }
  455. else if (command is SetInformation2Request)
  456. {
  457. if (!(share is FileSystemShare))
  458. {
  459. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  460. return new ErrorResponse(command.CommandName);
  461. }
  462. SetInformation2Request request = (SetInformation2Request)command;
  463. return FileSystemResponseHelper.GetSetInformation2Response(header, request, (FileSystemShare)share, state);
  464. }
  465. else if (command is LockingAndXRequest)
  466. {
  467. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  468. return new ErrorResponse(CommandName.SMB_COM_LOCKING_ANDX);
  469. }
  470. else if (command is OpenAndXRequest)
  471. {
  472. OpenAndXRequest request = (OpenAndXRequest)command;
  473. return OpenAndXHelper.GetOpenAndXResponse(header, request, share, state);
  474. }
  475. else if (command is ReadAndXRequest)
  476. {
  477. ReadAndXRequest request = (ReadAndXRequest)command;
  478. return ReadWriteResponseHelper.GetReadResponse(header, request, share, state);
  479. }
  480. else if (command is WriteAndXRequest)
  481. {
  482. string userName = state.GetConnectedUserName(header.UID);
  483. if (share is FileSystemShare && !((FileSystemShare)share).HasWriteAccess(userName))
  484. {
  485. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  486. return new ErrorResponse(command.CommandName);
  487. }
  488. WriteAndXRequest request = (WriteAndXRequest)command;
  489. return ReadWriteResponseHelper.GetWriteResponse(header, request, share, state);
  490. }
  491. else if (command is FindClose2Request)
  492. {
  493. return ServerResponseHelper.GetFindClose2Request(header, (FindClose2Request)command, state);
  494. }
  495. else if (command is TreeDisconnectRequest)
  496. {
  497. TreeDisconnectRequest request = (TreeDisconnectRequest)command;
  498. return TreeConnectHelper.GetTreeDisconnectResponse(header, request, state);
  499. }
  500. else if (command is TransactionRequest) // Both TransactionRequest and Transaction2Request
  501. {
  502. TransactionRequest request = (TransactionRequest)command;
  503. try
  504. {
  505. return TransactionHelper.GetTransactionResponse(header, request, share, state, sendQueue);
  506. }
  507. catch (UnsupportedInformationLevelException)
  508. {
  509. header.Status = NTStatus.STATUS_INVALID_PARAMETER;
  510. return new ErrorResponse(command.CommandName);
  511. }
  512. }
  513. else if (command is TransactionSecondaryRequest) // Both TransactionSecondaryRequest and Transaction2SecondaryRequest
  514. {
  515. TransactionSecondaryRequest request = (TransactionSecondaryRequest)command;
  516. try
  517. {
  518. return TransactionHelper.GetTransactionResponse(header, request, share, state, sendQueue);
  519. }
  520. catch (UnsupportedInformationLevelException)
  521. {
  522. header.Status = NTStatus.STATUS_INVALID_PARAMETER;
  523. return new ErrorResponse(command.CommandName);
  524. }
  525. }
  526. else if (command is NTTransactRequest)
  527. {
  528. NTTransactRequest request = (NTTransactRequest)command;
  529. return NTTransactHelper.GetNTTransactResponse(header, request, share, state, sendQueue);
  530. }
  531. else if (command is NTTransactSecondaryRequest)
  532. {
  533. NTTransactSecondaryRequest request = (NTTransactSecondaryRequest)command;
  534. return NTTransactHelper.GetNTTransactResponse(header, request, share, state, sendQueue);
  535. }
  536. else if (command is NTCreateAndXRequest)
  537. {
  538. NTCreateAndXRequest request = (NTCreateAndXRequest)command;
  539. return NTCreateHelper.GetNTCreateResponse(header, request, share, state);
  540. }
  541. }
  542. else
  543. {
  544. header.Status = NTStatus.STATUS_SMB_BAD_TID;
  545. return new ErrorResponse(command.CommandName);
  546. }
  547. }
  548. header.Status = NTStatus.STATUS_SMB_BAD_COMMAND;
  549. return new ErrorResponse(command.CommandName);
  550. }
  551. public static void TrySendMessage(StateObject state, SMBMessage reply)
  552. {
  553. SessionMessagePacket packet = new SessionMessagePacket();
  554. packet.Trailer = reply.GetBytes();
  555. TrySendPacket(state, packet);
  556. System.Diagnostics.Debug.Print("[{0}] Reply sent: {1} Commands, First Command: {2}, Packet length: {3}", DateTime.Now.ToString("HH:mm:ss:ffff"), reply.Commands.Count, reply.Commands[0].CommandName.ToString(), packet.Length);
  557. }
  558. public static void TrySendPacket(StateObject state, SessionPacket response)
  559. {
  560. Socket clientSocket = state.ClientSocket;
  561. try
  562. {
  563. clientSocket.Send(response.GetBytes());
  564. }
  565. catch (SocketException)
  566. {
  567. }
  568. catch (ObjectDisposedException)
  569. {
  570. }
  571. }
  572. private static void PrepareResponseHeader(SMBMessage response, SMBMessage request)
  573. {
  574. response.Header.Status = NTStatus.STATUS_SUCCESS;
  575. response.Header.Flags = HeaderFlags.CaseInsensitive | HeaderFlags.CanonicalizedPaths | HeaderFlags.Reply;
  576. response.Header.Flags2 = HeaderFlags2.NTStatusCode;
  577. if ((request.Header.Flags2 & HeaderFlags2.LongNamesAllowed) > 0)
  578. {
  579. response.Header.Flags2 |= HeaderFlags2.LongNamesAllowed | HeaderFlags2.LongNameUsed;
  580. }
  581. if ((request.Header.Flags2 & HeaderFlags2.ExtendedAttributes) > 0)
  582. {
  583. response.Header.Flags2 |= HeaderFlags2.ExtendedAttributes;
  584. }
  585. if ((request.Header.Flags2 & HeaderFlags2.ExtendedSecurity) > 0)
  586. {
  587. response.Header.Flags2 |= HeaderFlags2.ExtendedSecurity;
  588. }
  589. if ((request.Header.Flags2 & HeaderFlags2.Unicode) > 0)
  590. {
  591. response.Header.Flags2 |= HeaderFlags2.Unicode;
  592. }
  593. response.Header.MID = request.Header.MID;
  594. response.Header.PID = request.Header.PID;
  595. response.Header.UID = request.Header.UID;
  596. response.Header.TID = request.Header.TID;
  597. }
  598. }
  599. }