SmbTransport.cs 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using System.Linq;
  21. using System.Net;
  22. using System.Net.Sockets;
  23. using SharpCifs.Netbios;
  24. using SharpCifs.Util;
  25. using SharpCifs.Util.Sharpen;
  26. using SharpCifs.Util.Transport;
  27. namespace SharpCifs.Smb
  28. {
  29. public class SmbTransport : Transport
  30. {
  31. internal static readonly byte[] Buf = new byte[0xFFFF];
  32. internal static readonly SmbComNegotiate NegotiateRequest = new SmbComNegotiate();
  33. internal static LogStream LogStatic = LogStream.GetInstance();
  34. internal static Hashtable DfsRoots = null;
  35. internal static SmbTransport GetSmbTransport(UniAddress address, int port)
  36. {
  37. lock (typeof(SmbTransport))
  38. {
  39. return GetSmbTransport(address,
  40. port,
  41. SmbConstants.Laddr,
  42. SmbConstants.Lport,
  43. null);
  44. }
  45. }
  46. internal static SmbTransport GetSmbTransport(UniAddress address,
  47. int port,
  48. IPAddress localAddr,
  49. int localPort,
  50. string hostName)
  51. {
  52. lock (typeof(SmbTransport))
  53. {
  54. SmbTransport conn;
  55. lock (SmbConstants.Connections)
  56. {
  57. if (SmbConstants.SsnLimit != 1)
  58. {
  59. conn = SmbConstants.Connections
  60. .FirstOrDefault(c => c.Matches(address,
  61. port,
  62. localAddr,
  63. localPort,
  64. hostName)
  65. && (SmbConstants.SsnLimit == 0
  66. || c.Sessions.Count < SmbConstants.SsnLimit));
  67. if (conn != null)
  68. {
  69. return conn;
  70. }
  71. }
  72. conn = new SmbTransport(address, port, localAddr, localPort);
  73. SmbConstants.Connections.Insert(0, conn);
  74. }
  75. return conn;
  76. }
  77. }
  78. /// <summary>
  79. /// Clear All Cached Transport-Connections
  80. /// </summary>
  81. public static void ClearCachedConnections()
  82. {
  83. lock (typeof(SmbTransport))
  84. lock (SmbConstants.Connections)
  85. {
  86. foreach (var transport in SmbConstants.Connections)
  87. {
  88. try { transport.Disconnect(true); }
  89. catch (Exception) {}
  90. }
  91. SmbConstants.Connections.Clear();
  92. }
  93. }
  94. internal class ServerData
  95. {
  96. internal byte Flags;
  97. internal int Flags2;
  98. internal int MaxMpxCount;
  99. internal int MaxBufferSize;
  100. internal int SessionKey;
  101. internal int Capabilities;
  102. internal string OemDomainName;
  103. internal int SecurityMode;
  104. internal int Security;
  105. internal bool EncryptedPasswords;
  106. internal bool SignaturesEnabled;
  107. internal bool SignaturesRequired;
  108. internal int MaxNumberVcs;
  109. internal int MaxRawSize;
  110. internal long ServerTime;
  111. internal int ServerTimeZone;
  112. internal int EncryptionKeyLength;
  113. internal byte[] EncryptionKey;
  114. internal byte[] Guid;
  115. internal ServerData(SmbTransport enclosing)
  116. {
  117. this._enclosing = enclosing;
  118. }
  119. private readonly SmbTransport _enclosing;
  120. }
  121. internal IPAddress LocalAddr;
  122. internal int LocalPort;
  123. internal UniAddress Address;
  124. internal SocketEx Socket;
  125. internal int Port;
  126. internal int Mid;
  127. internal OutputStream Out;
  128. internal InputStream In;
  129. internal byte[] Sbuf = new byte[512];
  130. internal SmbComBlankResponse Key = new SmbComBlankResponse();
  131. internal long SessionExpiration = Runtime.CurrentTimeMillis() + SmbConstants.SoTimeout;
  132. internal List<object> Referrals = new List<object>();
  133. internal SigningDigest Digest;
  134. internal List<SmbSession> Sessions = new List<SmbSession>();
  135. internal ServerData Server;
  136. internal int Flags2 = SmbConstants.Flags2;
  137. internal int MaxMpxCount = SmbConstants.MaxMpxCount;
  138. internal int SndBufSize = SmbConstants.SndBufSize;
  139. internal int RcvBufSize = SmbConstants.RcvBufSize;
  140. internal int Capabilities = SmbConstants.Capabilities;
  141. internal int SessionKey = 0x00000000;
  142. internal bool UseUnicode = SmbConstants.UseUnicode;
  143. internal string TconHostName;
  144. internal SmbTransport(UniAddress address,
  145. int port,
  146. IPAddress localAddr,
  147. int localPort)
  148. {
  149. Server = new ServerData(this);
  150. this.Address = address;
  151. this.Port = port;
  152. this.LocalAddr = localAddr;
  153. this.LocalPort = localPort;
  154. }
  155. internal virtual SmbSession GetSmbSession()
  156. {
  157. lock (this)
  158. {
  159. return GetSmbSession(new NtlmPasswordAuthentication(null, null, null));
  160. }
  161. }
  162. internal virtual SmbSession GetSmbSession(NtlmPasswordAuthentication auth)
  163. {
  164. lock (this)
  165. {
  166. SmbSession ssn;
  167. long now;
  168. ssn = Sessions.FirstOrDefault(s => s.Matches(auth));
  169. if (ssn != null)
  170. {
  171. ssn.Auth = auth;
  172. return ssn;
  173. }
  174. if (SmbConstants.SoTimeout > 0
  175. && SessionExpiration < (now = Runtime.CurrentTimeMillis()))
  176. {
  177. SessionExpiration = now + SmbConstants.SoTimeout;
  178. foreach (var session in Sessions.Where(s => s.Expiration < now))
  179. {
  180. session.Logoff(false);
  181. }
  182. }
  183. ssn = new SmbSession(Address, Port, LocalAddr, LocalPort, auth);
  184. ssn.transport = this;
  185. Sessions.Add(ssn);
  186. return ssn;
  187. }
  188. }
  189. internal virtual bool Matches(UniAddress address,
  190. int port,
  191. IPAddress localAddr,
  192. int localPort,
  193. string hostName)
  194. {
  195. if (hostName == null)
  196. {
  197. hostName = address.GetHostName();
  198. }
  199. return (TconHostName == null
  200. || Runtime.EqualsIgnoreCase(hostName, TconHostName))
  201. && address.Equals(this.Address)
  202. && (port == -1
  203. || port == this.Port
  204. || (port == 445 && this.Port == 139))
  205. && (localAddr == this.LocalAddr
  206. || (localAddr != null && localAddr.Equals(this.LocalAddr)))
  207. && localPort == this.LocalPort;
  208. }
  209. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  210. internal virtual bool HasCapability(int cap)
  211. {
  212. try
  213. {
  214. Connect(SmbConstants.ResponseTimeout);
  215. }
  216. catch (IOException ioe)
  217. {
  218. throw new SmbException(ioe.Message, ioe);
  219. }
  220. return (Capabilities & cap) == cap;
  221. }
  222. internal virtual bool IsSignatureSetupRequired(NtlmPasswordAuthentication auth)
  223. {
  224. return (Flags2 & SmbConstants.Flags2SecuritySignatures) != 0
  225. && Digest == null
  226. && auth != NtlmPasswordAuthentication.Null
  227. && NtlmPasswordAuthentication.Null.Equals(auth) == false;
  228. }
  229. /// <exception cref="System.IO.IOException"></exception>
  230. internal virtual void Ssn139()
  231. {
  232. Name calledName = new Name(Address.FirstCalledName(), 0x20, null);
  233. do
  234. {
  235. Socket = new SocketEx(AddressFamily.InterNetwork,
  236. SocketType.Stream,
  237. ProtocolType.Tcp);
  238. //TCPローカルポートは、毎回空いているものを使う。
  239. //https://blogs.msdn.microsoft.com/dgorti/2005/09/18/only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted/
  240. Socket.Bind(new IPEndPoint(LocalAddr, 0));
  241. Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()),
  242. 139),
  243. SmbConstants.ConnTimeout);
  244. Socket.SoTimeOut = SmbConstants.SoTimeout;
  245. Out = Socket.GetOutputStream();
  246. In = Socket.GetInputStream();
  247. SessionServicePacket ssp = new SessionRequestPacket(calledName,
  248. NbtAddress.GetLocalName());
  249. Out.Write(Sbuf, 0, ssp.WriteWireFormat(Sbuf, 0));
  250. if (Readn(In, Sbuf, 0, 4) < 4)
  251. {
  252. try
  253. {
  254. //Socket.`Close` method deleted
  255. //Socket.Close();
  256. Socket.Dispose();
  257. }
  258. catch (IOException)
  259. {
  260. }
  261. throw new SmbException("EOF during NetBIOS session request");
  262. }
  263. switch (Sbuf[0] & 0xFF)
  264. {
  265. case SessionServicePacket.PositiveSessionResponse:
  266. {
  267. if (Log.Level >= 4)
  268. {
  269. Log.WriteLine("session established ok with " + Address);
  270. }
  271. return;
  272. }
  273. case SessionServicePacket.NegativeSessionResponse:
  274. {
  275. int errorCode = In.Read() & 0xFF;
  276. switch (errorCode)
  277. {
  278. case NbtException.CalledNotPresent:
  279. case NbtException.NotListeningCalled:
  280. {
  281. //Socket.`Close` method deleted
  282. //Socket.Close();
  283. Socket.Dispose();
  284. break;
  285. }
  286. default:
  287. {
  288. Disconnect(true);
  289. throw new NbtException(NbtException.ErrSsnSrvc,
  290. errorCode);
  291. }
  292. }
  293. break;
  294. }
  295. case -1:
  296. {
  297. Disconnect(true);
  298. throw new NbtException(NbtException.ErrSsnSrvc,
  299. NbtException.ConnectionRefused);
  300. }
  301. default:
  302. {
  303. Disconnect(true);
  304. throw new NbtException(NbtException.ErrSsnSrvc, 0);
  305. }
  306. }
  307. }
  308. while ((calledName.name = Address.NextCalledName()) != null);
  309. throw new IOException("Failed to establish session with " + Address);
  310. }
  311. /// <exception cref="System.IO.IOException"></exception>
  312. private void Negotiate(int port, ServerMessageBlock resp)
  313. {
  314. lock (Sbuf)
  315. {
  316. if (port == 139)
  317. {
  318. Ssn139();
  319. }
  320. else
  321. {
  322. if (port == -1)
  323. {
  324. port = SmbConstants.DefaultPort;
  325. }
  326. // 445
  327. Socket = new SocketEx(AddressFamily.InterNetwork,
  328. SocketType.Stream,
  329. ProtocolType.Tcp);
  330. //TCPローカルポートは、毎回空いているものを使う。
  331. //https://blogs.msdn.microsoft.com/dgorti/2005/09/18/only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted/
  332. Socket.Bind(new IPEndPoint(LocalAddr, 0));
  333. Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()),
  334. port), // <- 445
  335. SmbConstants.ConnTimeout);
  336. Socket.SoTimeOut = SmbConstants.SoTimeout;
  337. Out = Socket.GetOutputStream();
  338. In = Socket.GetInputStream();
  339. }
  340. if (++Mid == 32000)
  341. {
  342. Mid = 1;
  343. }
  344. NegotiateRequest.Mid = Mid;
  345. int n = NegotiateRequest.Encode(Sbuf, 4);
  346. Encdec.Enc_uint32be(n & 0xFFFF, Sbuf, 0);
  347. if (Log.Level >= 4)
  348. {
  349. Log.WriteLine(NegotiateRequest);
  350. if (Log.Level >= 6)
  351. {
  352. Hexdump.ToHexdump(Log, Sbuf, 4, n);
  353. }
  354. }
  355. Out.Write(Sbuf, 0, 4 + n);
  356. Out.Flush();
  357. if (PeekKey() == null)
  358. {
  359. throw new IOException("transport closed in negotiate");
  360. }
  361. int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF;
  362. if (size < 33 || (4 + size) > Sbuf.Length)
  363. {
  364. throw new IOException("Invalid payload size: " + size);
  365. }
  366. Readn(In, Sbuf, 4 + 32, size - 32);
  367. resp.Decode(Sbuf, 4);
  368. if (Log.Level >= 4)
  369. {
  370. Log.WriteLine(resp);
  371. if (Log.Level >= 6)
  372. {
  373. Hexdump.ToHexdump(Log, Sbuf, 4, n);
  374. }
  375. }
  376. }
  377. }
  378. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  379. public virtual void Connect()
  380. {
  381. try
  382. {
  383. base.Connect(SmbConstants.ResponseTimeout);
  384. }
  385. catch (TransportException te)
  386. {
  387. throw new SmbException("Failed to connect: " + Address, te);
  388. }
  389. }
  390. /// <exception cref="System.IO.IOException"></exception>
  391. protected internal override void DoConnect()
  392. {
  393. SmbComNegotiateResponse resp = new SmbComNegotiateResponse(Server);
  394. try
  395. {
  396. Negotiate(Port, resp);
  397. }
  398. catch (ConnectException)
  399. {
  400. Port = (Port == -1 || Port == SmbConstants.DefaultPort)
  401. ? 139
  402. : SmbConstants.DefaultPort;
  403. Negotiate(Port, resp);
  404. }
  405. if (resp.DialectIndex > 10)
  406. {
  407. throw new SmbException("This client does not support the negotiated dialect.");
  408. }
  409. if (
  410. (Server.Capabilities & SmbConstants.CapExtendedSecurity)
  411. != SmbConstants.CapExtendedSecurity
  412. && Server.EncryptionKeyLength != 8
  413. && SmbConstants.LmCompatibility == 0
  414. )
  415. {
  416. throw new SmbException("Unexpected encryption key length: "
  417. + Server.EncryptionKeyLength);
  418. }
  419. TconHostName = Address.GetHostName();
  420. if (Server.SignaturesRequired
  421. || (Server.SignaturesEnabled && SmbConstants.Signpref))
  422. {
  423. Flags2 |= SmbConstants.Flags2SecuritySignatures;
  424. }
  425. else
  426. {
  427. Flags2 &= 0xFFFF ^ SmbConstants.Flags2SecuritySignatures;
  428. }
  429. MaxMpxCount = Math.Min(MaxMpxCount, Server.MaxMpxCount);
  430. if (MaxMpxCount < 1)
  431. {
  432. MaxMpxCount = 1;
  433. }
  434. SndBufSize = Math.Min(SndBufSize, Server.MaxBufferSize);
  435. Capabilities &= Server.Capabilities;
  436. if ((Server.Capabilities & SmbConstants.CapExtendedSecurity)
  437. == SmbConstants.CapExtendedSecurity)
  438. {
  439. Capabilities |= SmbConstants.CapExtendedSecurity;
  440. }
  441. // & doesn't copy high bit
  442. if ((Capabilities & SmbConstants.CapUnicode) == 0)
  443. {
  444. // server doesn't want unicode
  445. if (SmbConstants.ForceUnicode)
  446. {
  447. Capabilities |= SmbConstants.CapUnicode;
  448. }
  449. else
  450. {
  451. UseUnicode = false;
  452. Flags2 &= 0xFFFF ^ SmbConstants.Flags2Unicode;
  453. }
  454. }
  455. }
  456. /// <exception cref="System.IO.IOException"></exception>
  457. protected internal override void DoDisconnect(bool hard)
  458. {
  459. try
  460. {
  461. foreach (var ssn in Sessions)
  462. {
  463. ssn.Logoff(hard);
  464. }
  465. Out.Close();
  466. In.Close();
  467. //Socket.`Close` method deleted
  468. //Socket.Close();
  469. Socket.Shutdown(SocketShutdown.Both);
  470. Socket.Dispose();
  471. }
  472. finally
  473. {
  474. Digest = null;
  475. Socket = null;
  476. TconHostName = null;
  477. }
  478. }
  479. /// <exception cref="System.IO.IOException"></exception>
  480. protected internal override void MakeKey(ServerMessageBlock request)
  481. {
  482. if (++Mid == 32000)
  483. {
  484. Mid = 1;
  485. }
  486. request.Mid = Mid;
  487. }
  488. /// <exception cref="System.IO.IOException"></exception>
  489. protected internal override ServerMessageBlock PeekKey()
  490. {
  491. int n;
  492. do
  493. {
  494. if ((n = Readn(In, Sbuf, 0, 4)) < 4)
  495. {
  496. return null;
  497. }
  498. }
  499. while (Sbuf[0] == 0x85);
  500. if ((n = Readn(In, Sbuf, 4, 32)) < 32)
  501. {
  502. return null;
  503. }
  504. if (Log.Level >= 4)
  505. {
  506. Log.WriteLine("New data read: " + this);
  507. Hexdump.ToHexdump(Log, Sbuf, 4, 32);
  508. }
  509. for (;;)
  510. {
  511. if (Sbuf[0] == 0x00 && Sbuf[1] == 0x00 &&
  512. Sbuf[4] == 0xFF &&
  513. Sbuf[5] == 'S' &&
  514. Sbuf[6] == 'M' &&
  515. Sbuf[7] == 'B')
  516. {
  517. break;
  518. }
  519. for (int i = 0; i < 35; i++)
  520. {
  521. Sbuf[i] = Sbuf[i + 1];
  522. }
  523. int b;
  524. if ((b = In.Read()) == -1)
  525. {
  526. return null;
  527. }
  528. Sbuf[35] = unchecked((byte)b);
  529. }
  530. Key.Mid = Encdec.Dec_uint16le(Sbuf, 34) & 0xFFFF;
  531. return Key;
  532. }
  533. /// <exception cref="System.IO.IOException"></exception>
  534. protected internal override void DoSend(ServerMessageBlock request)
  535. {
  536. lock (Buf)
  537. {
  538. ServerMessageBlock smb = request;
  539. int n = smb.Encode(Buf, 4);
  540. Encdec.Enc_uint32be(n & 0xFFFF, Buf, 0);
  541. if (Log.Level >= 4)
  542. {
  543. do
  544. {
  545. Log.WriteLine(smb);
  546. }
  547. while (smb is AndXServerMessageBlock
  548. && (smb = ((AndXServerMessageBlock)smb).Andx) != null);
  549. if (Log.Level >= 6)
  550. {
  551. Hexdump.ToHexdump(Log, Buf, 4, n);
  552. }
  553. }
  554. Out.Write(Buf, 0, 4 + n);
  555. }
  556. }
  557. /// <exception cref="System.IO.IOException"></exception>
  558. protected internal virtual void DoSend0(ServerMessageBlock request)
  559. {
  560. try
  561. {
  562. DoSend(request);
  563. }
  564. catch (IOException ioe)
  565. {
  566. if (Log.Level > 2)
  567. {
  568. Runtime.PrintStackTrace(ioe, Log);
  569. }
  570. try
  571. {
  572. Disconnect(true);
  573. }
  574. catch (IOException ioe2)
  575. {
  576. Runtime.PrintStackTrace(ioe2, Log);
  577. }
  578. throw;
  579. }
  580. }
  581. /// <exception cref="System.IO.IOException"></exception>
  582. protected internal override void DoRecv(Response response)
  583. {
  584. ServerMessageBlock resp = (ServerMessageBlock)response;
  585. resp.UseUnicode = UseUnicode;
  586. resp.ExtendedSecurity
  587. = (Capabilities & SmbConstants.CapExtendedSecurity)
  588. == SmbConstants.CapExtendedSecurity;
  589. lock (Buf)
  590. {
  591. Array.Copy(Sbuf, 0, Buf, 0, 4 + SmbConstants.HeaderLength);
  592. int size = Encdec.Dec_uint16be(Buf, 2) & 0xFFFF;
  593. if (size < (SmbConstants.HeaderLength + 1) || (4 + size) > RcvBufSize)
  594. {
  595. throw new IOException("Invalid payload size: " + size);
  596. }
  597. int errorCode = Encdec.Dec_uint32le(Buf, 9) & unchecked((int)(0xFFFFFFFF));
  598. if (resp.Command == ServerMessageBlock.SmbComReadAndx
  599. && (errorCode == 0
  600. || errorCode == unchecked((int)(0x80000005)))
  601. )
  602. {
  603. // overflow indicator normal for pipe
  604. SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp;
  605. int off = SmbConstants.HeaderLength;
  606. Readn(In, Buf, 4 + off, 27);
  607. off += 27;
  608. resp.Decode(Buf, 4);
  609. int pad = r.DataOffset - off;
  610. if (r.ByteCount > 0 && pad > 0 && pad < 4)
  611. {
  612. Readn(In, Buf, 4 + off, pad);
  613. }
  614. if (r.DataLength > 0)
  615. {
  616. Readn(In, r.B, r.Off, r.DataLength);
  617. }
  618. }
  619. else
  620. {
  621. Readn(In, Buf, 4 + 32, size - 32);
  622. resp.Decode(Buf, 4);
  623. if (resp is SmbComTransactionResponse)
  624. {
  625. ((SmbComTransactionResponse)resp).Current();
  626. }
  627. }
  628. if (Digest != null && resp.ErrorCode == 0)
  629. {
  630. Digest.Verify(Buf, 4, resp);
  631. }
  632. if (Log.Level >= 4)
  633. {
  634. Log.WriteLine(response);
  635. if (Log.Level >= 6)
  636. {
  637. Hexdump.ToHexdump(Log, Buf, 4, size);
  638. }
  639. }
  640. }
  641. }
  642. /// <exception cref="System.IO.IOException"></exception>
  643. protected internal override void DoSkip()
  644. {
  645. int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF;
  646. if (size < 33 || (4 + size) > RcvBufSize)
  647. {
  648. In.Skip(In.Available());
  649. }
  650. else
  651. {
  652. In.Skip(size - 32);
  653. }
  654. }
  655. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  656. internal virtual void CheckStatus(ServerMessageBlock req, ServerMessageBlock resp)
  657. {
  658. resp.ErrorCode = SmbException.GetStatusByCode(resp.ErrorCode);
  659. switch (resp.ErrorCode)
  660. {
  661. case NtStatus.NtStatusOk:
  662. {
  663. break;
  664. }
  665. case NtStatus.NtStatusAccessDenied:
  666. case NtStatus.NtStatusWrongPassword:
  667. case NtStatus.NtStatusLogonFailure:
  668. case NtStatus.NtStatusAccountRestriction:
  669. case NtStatus.NtStatusInvalidLogonHours:
  670. case NtStatus.NtStatusInvalidWorkstation:
  671. case NtStatus.NtStatusPasswordExpired:
  672. case NtStatus.NtStatusAccountDisabled:
  673. case NtStatus.NtStatusAccountLockedOut:
  674. case NtStatus.NtStatusTrustedDomainFailure:
  675. {
  676. throw new SmbAuthException(resp.ErrorCode);
  677. }
  678. case NtStatus.NtStatusPathNotCovered:
  679. {
  680. if (req.Auth == null)
  681. {
  682. throw new SmbException(resp.ErrorCode, null);
  683. }
  684. DfsReferral dr = GetDfsReferrals(req.Auth, req.Path, 1);
  685. if (dr == null)
  686. {
  687. throw new SmbException(resp.ErrorCode, null);
  688. }
  689. SmbFile.Dfs.Insert(req.Path, dr);
  690. throw dr;
  691. }
  692. case unchecked((int)(0x80000005)):
  693. {
  694. break;
  695. }
  696. case NtStatus.NtStatusMoreProcessingRequired:
  697. {
  698. break;
  699. }
  700. default:
  701. {
  702. throw new SmbException(resp.ErrorCode, null);
  703. }
  704. }
  705. if (resp.VerifyFailed)
  706. {
  707. throw new SmbException("Signature verification failed.");
  708. }
  709. }
  710. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  711. internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response)
  712. {
  713. Connect();
  714. request.Flags2 |= Flags2;
  715. request.UseUnicode = UseUnicode;
  716. request.Response = response;
  717. if (request.Digest == null)
  718. {
  719. request.Digest = Digest;
  720. }
  721. try
  722. {
  723. if (response == null)
  724. {
  725. DoSend0(request);
  726. return;
  727. }
  728. if (request is SmbComTransaction)
  729. {
  730. response.Command = request.Command;
  731. SmbComTransaction req = (SmbComTransaction)request;
  732. SmbComTransactionResponse resp = (SmbComTransactionResponse)response;
  733. req.MaxBufferSize = SndBufSize;
  734. resp.Reset();
  735. try
  736. {
  737. BufferCache.GetBuffers(req, resp);
  738. req.Current();
  739. if (req.MoveNext())
  740. {
  741. SmbComBlankResponse interim = new SmbComBlankResponse();
  742. Sendrecv(req, interim, SmbConstants.ResponseTimeout);
  743. if (interim.ErrorCode != 0)
  744. {
  745. CheckStatus(req, interim);
  746. }
  747. req.Current();
  748. }
  749. else
  750. {
  751. MakeKey(req);
  752. }
  753. lock (this)
  754. {
  755. response.Received = false;
  756. resp.IsReceived = false;
  757. try
  758. {
  759. ResponseMap.Put(req, resp);
  760. do
  761. {
  762. DoSend0(req);
  763. }
  764. while (req.MoveNext() && req.Current() != null);
  765. long timeout = SmbConstants.ResponseTimeout;
  766. resp.Expiration = Runtime.CurrentTimeMillis() + timeout;
  767. while (resp.MoveNext())
  768. {
  769. Runtime.Wait(this, timeout);
  770. timeout = resp.Expiration - Runtime.CurrentTimeMillis();
  771. if (timeout <= 0)
  772. {
  773. throw new TransportException(
  774. this + " timedout waiting for response to " + req);
  775. }
  776. }
  777. if (response.ErrorCode != 0)
  778. {
  779. CheckStatus(req, resp);
  780. }
  781. }
  782. catch (Exception ie)
  783. {
  784. if (ie is SmbException)
  785. {
  786. throw;
  787. }
  788. else
  789. {
  790. throw new TransportException(ie);
  791. }
  792. }
  793. finally
  794. {
  795. //Sharpen.Collections.Remove<Hashtable, SmbComTransaction>(response_map, req);
  796. ResponseMap.Remove(req);
  797. }
  798. }
  799. }
  800. finally
  801. {
  802. BufferCache.ReleaseBuffer(req.TxnBuf);
  803. BufferCache.ReleaseBuffer(resp.TxnBuf);
  804. }
  805. }
  806. else
  807. {
  808. response.Command = request.Command;
  809. Sendrecv(request, response, SmbConstants.ResponseTimeout);
  810. }
  811. }
  812. catch (SmbException se)
  813. {
  814. throw;
  815. }
  816. catch (IOException ioe)
  817. {
  818. throw new SmbException(ioe.Message, ioe);
  819. }
  820. CheckStatus(request, response);
  821. }
  822. public override string ToString()
  823. {
  824. return base.ToString() + "[" + Address + ":" + Port + "]";
  825. }
  826. internal virtual void DfsPathSplit(string path, string[] result)
  827. {
  828. int ri = 0;
  829. int rlast = result.Length - 1;
  830. int i = 0;
  831. int b = 0;
  832. int len = path.Length;
  833. do
  834. {
  835. if (ri == rlast)
  836. {
  837. result[rlast] = Runtime.Substring(path, b);
  838. return;
  839. }
  840. if (i == len || path[i] == '\\')
  841. {
  842. result[ri++] = Runtime.Substring(path, b, i);
  843. b = i + 1;
  844. }
  845. }
  846. while (i++ < len);
  847. while (ri < result.Length)
  848. {
  849. result[ri++] = string.Empty;
  850. }
  851. }
  852. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  853. internal virtual DfsReferral GetDfsReferrals(NtlmPasswordAuthentication auth,
  854. string path,
  855. int rn)
  856. {
  857. SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
  858. Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
  859. ipc.Send(new Trans2GetDfsReferral(path), resp);
  860. if (resp.NumReferrals == 0)
  861. {
  862. return null;
  863. }
  864. if (rn == 0 || resp.NumReferrals < rn)
  865. {
  866. rn = resp.NumReferrals;
  867. }
  868. DfsReferral dr = new DfsReferral();
  869. string[] arr = new string[4];
  870. long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000;
  871. int di = 0;
  872. for (;;)
  873. {
  874. dr.ResolveHashes = auth.HashesExternal;
  875. dr.Ttl = resp.Referrals[di].Ttl;
  876. dr.Expiration = expiration;
  877. if (path.Equals(string.Empty))
  878. {
  879. dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower();
  880. }
  881. else
  882. {
  883. DfsPathSplit(resp.Referrals[di].Node, arr);
  884. dr.Server = arr[1];
  885. dr.Share = arr[2];
  886. dr.Path = arr[3];
  887. }
  888. dr.PathConsumed = resp.PathConsumed;
  889. di++;
  890. if (di == rn)
  891. {
  892. break;
  893. }
  894. dr.Append(new DfsReferral());
  895. dr = dr.Next;
  896. }
  897. return dr.Next;
  898. }
  899. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  900. internal virtual DfsReferral[] __getDfsReferrals(NtlmPasswordAuthentication auth,
  901. string path,
  902. int rn)
  903. {
  904. SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
  905. Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
  906. ipc.Send(new Trans2GetDfsReferral(path), resp);
  907. if (rn == 0 || resp.NumReferrals < rn)
  908. {
  909. rn = resp.NumReferrals;
  910. }
  911. DfsReferral[] drs = new DfsReferral[rn];
  912. string[] arr = new string[4];
  913. long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000;
  914. for (int di = 0; di < drs.Length; di++)
  915. {
  916. DfsReferral dr = new DfsReferral();
  917. dr.ResolveHashes = auth.HashesExternal;
  918. dr.Ttl = resp.Referrals[di].Ttl;
  919. dr.Expiration = expiration;
  920. if (path.Equals(string.Empty))
  921. {
  922. dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower();
  923. }
  924. else
  925. {
  926. DfsPathSplit(resp.Referrals[di].Node, arr);
  927. dr.Server = arr[1];
  928. dr.Share = arr[2];
  929. dr.Path = arr[3];
  930. }
  931. dr.PathConsumed = resp.PathConsumed;
  932. drs[di] = dr;
  933. }
  934. return drs;
  935. }
  936. }
  937. }