12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- // This code is derived from jcifs smb client library <jcifs at samba dot org>
- // Ported by J. Arturo <webmaster at komodosoft dot net>
- //
- // This library is free software; you can redistribute it and/or
- // modify it under the terms of the GNU Lesser General Public
- // License as published by the Free Software Foundation; either
- // version 2.1 of the License, or (at your option) any later version.
- //
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- // Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public
- // License along with this library; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using SharpCifs.Netbios;
- using SharpCifs.Util;
- using SharpCifs.Util.Sharpen;
- using SharpCifs.Util.Transport;
- namespace SharpCifs.Smb
- {
- public class SmbTransport : Transport
- {
- internal static readonly byte[] Buf = new byte[0xFFFF];
- internal static readonly SmbComNegotiate NegotiateRequest = new SmbComNegotiate();
- internal static LogStream LogStatic = LogStream.GetInstance();
- internal static Hashtable DfsRoots = null;
- internal static SmbTransport GetSmbTransport(UniAddress address, int port)
- {
- lock (typeof(SmbTransport))
- {
- return GetSmbTransport(address,
- port,
- SmbConstants.Laddr,
- SmbConstants.Lport,
- null);
- }
- }
- internal static SmbTransport GetSmbTransport(UniAddress address,
- int port,
- IPAddress localAddr,
- int localPort,
- string hostName)
- {
- lock (typeof(SmbTransport))
- {
- SmbTransport conn;
- lock (SmbConstants.Connections)
- {
- if (SmbConstants.SsnLimit != 1)
- {
- conn = SmbConstants.Connections
- .FirstOrDefault(c => c.Matches(address,
- port,
- localAddr,
- localPort,
- hostName)
- && (SmbConstants.SsnLimit == 0
- || c.Sessions.Count < SmbConstants.SsnLimit));
- if (conn != null)
- {
- return conn;
- }
- }
- conn = new SmbTransport(address, port, localAddr, localPort);
- SmbConstants.Connections.Insert(0, conn);
- }
- return conn;
- }
- }
- /// <summary>
- /// Clear All Cached Transport-Connections
- /// </summary>
- public static void ClearCachedConnections()
- {
- lock (typeof(SmbTransport))
- lock (SmbConstants.Connections)
- {
- foreach (var transport in SmbConstants.Connections)
- {
- try { transport.Disconnect(true); }
- catch (Exception) {}
- }
- SmbConstants.Connections.Clear();
- }
- }
- internal class ServerData
- {
- internal byte Flags;
- internal int Flags2;
- internal int MaxMpxCount;
- internal int MaxBufferSize;
- internal int SessionKey;
- internal int Capabilities;
- internal string OemDomainName;
- internal int SecurityMode;
- internal int Security;
- internal bool EncryptedPasswords;
- internal bool SignaturesEnabled;
- internal bool SignaturesRequired;
- internal int MaxNumberVcs;
- internal int MaxRawSize;
- internal long ServerTime;
- internal int ServerTimeZone;
- internal int EncryptionKeyLength;
- internal byte[] EncryptionKey;
- internal byte[] Guid;
- internal ServerData(SmbTransport enclosing)
- {
- this._enclosing = enclosing;
- }
- private readonly SmbTransport _enclosing;
- }
- internal IPAddress LocalAddr;
- internal int LocalPort;
- internal UniAddress Address;
- internal SocketEx Socket;
- internal int Port;
- internal int Mid;
- internal OutputStream Out;
- internal InputStream In;
- internal byte[] Sbuf = new byte[512];
- internal SmbComBlankResponse Key = new SmbComBlankResponse();
- internal long SessionExpiration = Runtime.CurrentTimeMillis() + SmbConstants.SoTimeout;
- internal List<object> Referrals = new List<object>();
- internal SigningDigest Digest;
- internal List<SmbSession> Sessions = new List<SmbSession>();
- internal ServerData Server;
- internal int Flags2 = SmbConstants.Flags2;
- internal int MaxMpxCount = SmbConstants.MaxMpxCount;
- internal int SndBufSize = SmbConstants.SndBufSize;
- internal int RcvBufSize = SmbConstants.RcvBufSize;
- internal int Capabilities = SmbConstants.Capabilities;
- internal int SessionKey = 0x00000000;
- internal bool UseUnicode = SmbConstants.UseUnicode;
- internal string TconHostName;
- internal SmbTransport(UniAddress address,
- int port,
- IPAddress localAddr,
- int localPort)
- {
- Server = new ServerData(this);
- this.Address = address;
- this.Port = port;
- this.LocalAddr = localAddr;
- this.LocalPort = localPort;
- }
- internal virtual SmbSession GetSmbSession()
- {
- lock (this)
- {
- return GetSmbSession(new NtlmPasswordAuthentication(null, null, null));
- }
- }
- internal virtual SmbSession GetSmbSession(NtlmPasswordAuthentication auth)
- {
- lock (this)
- {
- SmbSession ssn;
- long now;
- ssn = Sessions.FirstOrDefault(s => s.Matches(auth));
- if (ssn != null)
- {
- ssn.Auth = auth;
- return ssn;
- }
- if (SmbConstants.SoTimeout > 0
- && SessionExpiration < (now = Runtime.CurrentTimeMillis()))
- {
- SessionExpiration = now + SmbConstants.SoTimeout;
- foreach (var session in Sessions.Where(s => s.Expiration < now))
- {
- session.Logoff(false);
- }
- }
- ssn = new SmbSession(Address, Port, LocalAddr, LocalPort, auth);
- ssn.transport = this;
- Sessions.Add(ssn);
- return ssn;
- }
- }
- internal virtual bool Matches(UniAddress address,
- int port,
- IPAddress localAddr,
- int localPort,
- string hostName)
- {
- if (hostName == null)
- {
- hostName = address.GetHostName();
- }
- return (TconHostName == null
- || Runtime.EqualsIgnoreCase(hostName, TconHostName))
- && address.Equals(this.Address)
- && (port == -1
- || port == this.Port
- || (port == 445 && this.Port == 139))
- && (localAddr == this.LocalAddr
- || (localAddr != null && localAddr.Equals(this.LocalAddr)))
- && localPort == this.LocalPort;
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual bool HasCapability(int cap)
- {
- try
- {
- Connect(SmbConstants.ResponseTimeout);
- }
- catch (IOException ioe)
- {
- throw new SmbException(ioe.Message, ioe);
- }
- return (Capabilities & cap) == cap;
- }
- internal virtual bool IsSignatureSetupRequired(NtlmPasswordAuthentication auth)
- {
- return (Flags2 & SmbConstants.Flags2SecuritySignatures) != 0
- && Digest == null
- && auth != NtlmPasswordAuthentication.Null
- && NtlmPasswordAuthentication.Null.Equals(auth) == false;
- }
- /// <exception cref="System.IO.IOException"></exception>
- internal virtual void Ssn139()
- {
- Name calledName = new Name(Address.FirstCalledName(), 0x20, null);
- do
- {
- Socket = new SocketEx(AddressFamily.InterNetwork,
- SocketType.Stream,
- ProtocolType.Tcp);
- //TCPローカルポートは、毎回空いているものを使う。
- //https://blogs.msdn.microsoft.com/dgorti/2005/09/18/only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted/
- Socket.Bind(new IPEndPoint(LocalAddr, 0));
- Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()),
- 139),
- SmbConstants.ConnTimeout);
-
- Socket.SoTimeOut = SmbConstants.SoTimeout;
- Out = Socket.GetOutputStream();
- In = Socket.GetInputStream();
- SessionServicePacket ssp = new SessionRequestPacket(calledName,
- NbtAddress.GetLocalName());
- Out.Write(Sbuf, 0, ssp.WriteWireFormat(Sbuf, 0));
- if (Readn(In, Sbuf, 0, 4) < 4)
- {
- try
- {
- //Socket.`Close` method deleted
- //Socket.Close();
- Socket.Dispose();
- }
- catch (IOException)
- {
- }
- throw new SmbException("EOF during NetBIOS session request");
- }
- switch (Sbuf[0] & 0xFF)
- {
- case SessionServicePacket.PositiveSessionResponse:
- {
- if (Log.Level >= 4)
- {
- Log.WriteLine("session established ok with " + Address);
- }
- return;
- }
- case SessionServicePacket.NegativeSessionResponse:
- {
- int errorCode = In.Read() & 0xFF;
- switch (errorCode)
- {
- case NbtException.CalledNotPresent:
- case NbtException.NotListeningCalled:
- {
- //Socket.`Close` method deleted
- //Socket.Close();
- Socket.Dispose();
- break;
- }
- default:
- {
- Disconnect(true);
- throw new NbtException(NbtException.ErrSsnSrvc,
- errorCode);
- }
- }
- break;
- }
- case -1:
- {
- Disconnect(true);
- throw new NbtException(NbtException.ErrSsnSrvc,
- NbtException.ConnectionRefused);
- }
- default:
- {
- Disconnect(true);
- throw new NbtException(NbtException.ErrSsnSrvc, 0);
- }
- }
- }
- while ((calledName.name = Address.NextCalledName()) != null);
- throw new IOException("Failed to establish session with " + Address);
- }
- /// <exception cref="System.IO.IOException"></exception>
- private void Negotiate(int port, ServerMessageBlock resp)
- {
- lock (Sbuf)
- {
- if (port == 139)
- {
- Ssn139();
- }
- else
- {
- if (port == -1)
- {
- port = SmbConstants.DefaultPort;
- }
- // 445
- Socket = new SocketEx(AddressFamily.InterNetwork,
- SocketType.Stream,
- ProtocolType.Tcp);
- //TCPローカルポートは、毎回空いているものを使う。
- //https://blogs.msdn.microsoft.com/dgorti/2005/09/18/only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted/
- Socket.Bind(new IPEndPoint(LocalAddr, 0));
- Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()),
- port), // <- 445
- SmbConstants.ConnTimeout);
- Socket.SoTimeOut = SmbConstants.SoTimeout;
- Out = Socket.GetOutputStream();
- In = Socket.GetInputStream();
- }
- if (++Mid == 32000)
- {
- Mid = 1;
- }
- NegotiateRequest.Mid = Mid;
- int n = NegotiateRequest.Encode(Sbuf, 4);
- Encdec.Enc_uint32be(n & 0xFFFF, Sbuf, 0);
- if (Log.Level >= 4)
- {
- Log.WriteLine(NegotiateRequest);
- if (Log.Level >= 6)
- {
- Hexdump.ToHexdump(Log, Sbuf, 4, n);
- }
- }
- Out.Write(Sbuf, 0, 4 + n);
- Out.Flush();
- if (PeekKey() == null)
- {
- throw new IOException("transport closed in negotiate");
- }
- int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF;
- if (size < 33 || (4 + size) > Sbuf.Length)
- {
- throw new IOException("Invalid payload size: " + size);
- }
- Readn(In, Sbuf, 4 + 32, size - 32);
- resp.Decode(Sbuf, 4);
- if (Log.Level >= 4)
- {
- Log.WriteLine(resp);
- if (Log.Level >= 6)
- {
- Hexdump.ToHexdump(Log, Sbuf, 4, n);
- }
- }
- }
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- public virtual void Connect()
- {
- try
- {
- base.Connect(SmbConstants.ResponseTimeout);
- }
- catch (TransportException te)
- {
- throw new SmbException("Failed to connect: " + Address, te);
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void DoConnect()
- {
- SmbComNegotiateResponse resp = new SmbComNegotiateResponse(Server);
- try
- {
- Negotiate(Port, resp);
- }
- catch (ConnectException)
- {
- Port = (Port == -1 || Port == SmbConstants.DefaultPort)
- ? 139
- : SmbConstants.DefaultPort;
- Negotiate(Port, resp);
- }
- if (resp.DialectIndex > 10)
- {
- throw new SmbException("This client does not support the negotiated dialect.");
- }
- if (
- (Server.Capabilities & SmbConstants.CapExtendedSecurity)
- != SmbConstants.CapExtendedSecurity
- && Server.EncryptionKeyLength != 8
- && SmbConstants.LmCompatibility == 0
- )
- {
- throw new SmbException("Unexpected encryption key length: "
- + Server.EncryptionKeyLength);
- }
- TconHostName = Address.GetHostName();
- if (Server.SignaturesRequired
- || (Server.SignaturesEnabled && SmbConstants.Signpref))
- {
- Flags2 |= SmbConstants.Flags2SecuritySignatures;
- }
- else
- {
- Flags2 &= 0xFFFF ^ SmbConstants.Flags2SecuritySignatures;
- }
- MaxMpxCount = Math.Min(MaxMpxCount, Server.MaxMpxCount);
- if (MaxMpxCount < 1)
- {
- MaxMpxCount = 1;
- }
- SndBufSize = Math.Min(SndBufSize, Server.MaxBufferSize);
- Capabilities &= Server.Capabilities;
- if ((Server.Capabilities & SmbConstants.CapExtendedSecurity)
- == SmbConstants.CapExtendedSecurity)
- {
- Capabilities |= SmbConstants.CapExtendedSecurity;
- }
- // & doesn't copy high bit
- if ((Capabilities & SmbConstants.CapUnicode) == 0)
- {
- // server doesn't want unicode
- if (SmbConstants.ForceUnicode)
- {
- Capabilities |= SmbConstants.CapUnicode;
- }
- else
- {
- UseUnicode = false;
- Flags2 &= 0xFFFF ^ SmbConstants.Flags2Unicode;
- }
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void DoDisconnect(bool hard)
- {
- try
- {
- foreach (var ssn in Sessions)
- {
- ssn.Logoff(hard);
- }
- Out.Close();
- In.Close();
- //Socket.`Close` method deleted
- //Socket.Close();
- Socket.Shutdown(SocketShutdown.Both);
- Socket.Dispose();
- }
- finally
- {
- Digest = null;
- Socket = null;
- TconHostName = null;
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void MakeKey(ServerMessageBlock request)
- {
- if (++Mid == 32000)
- {
- Mid = 1;
- }
- request.Mid = Mid;
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override ServerMessageBlock PeekKey()
- {
- int n;
- do
- {
- if ((n = Readn(In, Sbuf, 0, 4)) < 4)
- {
- return null;
- }
- }
- while (Sbuf[0] == 0x85);
- if ((n = Readn(In, Sbuf, 4, 32)) < 32)
- {
- return null;
- }
- if (Log.Level >= 4)
- {
- Log.WriteLine("New data read: " + this);
- Hexdump.ToHexdump(Log, Sbuf, 4, 32);
- }
- for (;;)
- {
- if (Sbuf[0] == 0x00 && Sbuf[1] == 0x00 &&
- Sbuf[4] == 0xFF &&
- Sbuf[5] == 'S' &&
- Sbuf[6] == 'M' &&
- Sbuf[7] == 'B')
- {
- break;
- }
- for (int i = 0; i < 35; i++)
- {
- Sbuf[i] = Sbuf[i + 1];
- }
- int b;
- if ((b = In.Read()) == -1)
- {
- return null;
- }
- Sbuf[35] = unchecked((byte)b);
- }
- Key.Mid = Encdec.Dec_uint16le(Sbuf, 34) & 0xFFFF;
- return Key;
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void DoSend(ServerMessageBlock request)
- {
- lock (Buf)
- {
- ServerMessageBlock smb = request;
- int n = smb.Encode(Buf, 4);
- Encdec.Enc_uint32be(n & 0xFFFF, Buf, 0);
- if (Log.Level >= 4)
- {
- do
- {
- Log.WriteLine(smb);
- }
- while (smb is AndXServerMessageBlock
- && (smb = ((AndXServerMessageBlock)smb).Andx) != null);
- if (Log.Level >= 6)
- {
- Hexdump.ToHexdump(Log, Buf, 4, n);
- }
- }
- Out.Write(Buf, 0, 4 + n);
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal virtual void DoSend0(ServerMessageBlock request)
- {
- try
- {
- DoSend(request);
- }
- catch (IOException ioe)
- {
- if (Log.Level > 2)
- {
- Runtime.PrintStackTrace(ioe, Log);
- }
- try
- {
- Disconnect(true);
- }
- catch (IOException ioe2)
- {
- Runtime.PrintStackTrace(ioe2, Log);
- }
- throw;
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void DoRecv(Response response)
- {
- ServerMessageBlock resp = (ServerMessageBlock)response;
- resp.UseUnicode = UseUnicode;
- resp.ExtendedSecurity
- = (Capabilities & SmbConstants.CapExtendedSecurity)
- == SmbConstants.CapExtendedSecurity;
- lock (Buf)
- {
- Array.Copy(Sbuf, 0, Buf, 0, 4 + SmbConstants.HeaderLength);
- int size = Encdec.Dec_uint16be(Buf, 2) & 0xFFFF;
- if (size < (SmbConstants.HeaderLength + 1) || (4 + size) > RcvBufSize)
- {
- throw new IOException("Invalid payload size: " + size);
- }
- int errorCode = Encdec.Dec_uint32le(Buf, 9) & unchecked((int)(0xFFFFFFFF));
- if (resp.Command == ServerMessageBlock.SmbComReadAndx
- && (errorCode == 0
- || errorCode == unchecked((int)(0x80000005)))
- )
- {
- // overflow indicator normal for pipe
- SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp;
- int off = SmbConstants.HeaderLength;
- Readn(In, Buf, 4 + off, 27);
- off += 27;
- resp.Decode(Buf, 4);
- int pad = r.DataOffset - off;
- if (r.ByteCount > 0 && pad > 0 && pad < 4)
- {
- Readn(In, Buf, 4 + off, pad);
- }
- if (r.DataLength > 0)
- {
- Readn(In, r.B, r.Off, r.DataLength);
- }
- }
- else
- {
- Readn(In, Buf, 4 + 32, size - 32);
- resp.Decode(Buf, 4);
- if (resp is SmbComTransactionResponse)
- {
- ((SmbComTransactionResponse)resp).Current();
- }
- }
- if (Digest != null && resp.ErrorCode == 0)
- {
- Digest.Verify(Buf, 4, resp);
- }
- if (Log.Level >= 4)
- {
- Log.WriteLine(response);
- if (Log.Level >= 6)
- {
- Hexdump.ToHexdump(Log, Buf, 4, size);
- }
- }
- }
- }
- /// <exception cref="System.IO.IOException"></exception>
- protected internal override void DoSkip()
- {
- int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF;
- if (size < 33 || (4 + size) > RcvBufSize)
- {
- In.Skip(In.Available());
- }
- else
- {
- In.Skip(size - 32);
- }
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual void CheckStatus(ServerMessageBlock req, ServerMessageBlock resp)
- {
- resp.ErrorCode = SmbException.GetStatusByCode(resp.ErrorCode);
- switch (resp.ErrorCode)
- {
- case NtStatus.NtStatusOk:
- {
- break;
- }
- case NtStatus.NtStatusAccessDenied:
- case NtStatus.NtStatusWrongPassword:
- case NtStatus.NtStatusLogonFailure:
- case NtStatus.NtStatusAccountRestriction:
- case NtStatus.NtStatusInvalidLogonHours:
- case NtStatus.NtStatusInvalidWorkstation:
- case NtStatus.NtStatusPasswordExpired:
- case NtStatus.NtStatusAccountDisabled:
- case NtStatus.NtStatusAccountLockedOut:
- case NtStatus.NtStatusTrustedDomainFailure:
- {
- throw new SmbAuthException(resp.ErrorCode);
- }
- case NtStatus.NtStatusPathNotCovered:
- {
- if (req.Auth == null)
- {
- throw new SmbException(resp.ErrorCode, null);
- }
- DfsReferral dr = GetDfsReferrals(req.Auth, req.Path, 1);
- if (dr == null)
- {
- throw new SmbException(resp.ErrorCode, null);
- }
- SmbFile.Dfs.Insert(req.Path, dr);
- throw dr;
- }
- case unchecked((int)(0x80000005)):
- {
- break;
- }
- case NtStatus.NtStatusMoreProcessingRequired:
- {
- break;
- }
- default:
- {
- throw new SmbException(resp.ErrorCode, null);
- }
- }
- if (resp.VerifyFailed)
- {
- throw new SmbException("Signature verification failed.");
- }
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response)
- {
- Connect();
- request.Flags2 |= Flags2;
- request.UseUnicode = UseUnicode;
- request.Response = response;
- if (request.Digest == null)
- {
- request.Digest = Digest;
- }
- try
- {
- if (response == null)
- {
- DoSend0(request);
- return;
- }
- if (request is SmbComTransaction)
- {
- response.Command = request.Command;
- SmbComTransaction req = (SmbComTransaction)request;
- SmbComTransactionResponse resp = (SmbComTransactionResponse)response;
- req.MaxBufferSize = SndBufSize;
- resp.Reset();
- try
- {
- BufferCache.GetBuffers(req, resp);
- req.Current();
- if (req.MoveNext())
- {
- SmbComBlankResponse interim = new SmbComBlankResponse();
- Sendrecv(req, interim, SmbConstants.ResponseTimeout);
- if (interim.ErrorCode != 0)
- {
- CheckStatus(req, interim);
- }
- req.Current();
- }
- else
- {
- MakeKey(req);
- }
- lock (this)
- {
- response.Received = false;
- resp.IsReceived = false;
- try
- {
- ResponseMap.Put(req, resp);
- do
- {
- DoSend0(req);
- }
- while (req.MoveNext() && req.Current() != null);
- long timeout = SmbConstants.ResponseTimeout;
- resp.Expiration = Runtime.CurrentTimeMillis() + timeout;
- while (resp.MoveNext())
- {
- Runtime.Wait(this, timeout);
- timeout = resp.Expiration - Runtime.CurrentTimeMillis();
- if (timeout <= 0)
- {
- throw new TransportException(
- this + " timedout waiting for response to " + req);
- }
- }
- if (response.ErrorCode != 0)
- {
- CheckStatus(req, resp);
- }
- }
- catch (Exception ie)
- {
- if (ie is SmbException)
- {
- throw;
- }
- else
- {
- throw new TransportException(ie);
- }
- }
- finally
- {
- //Sharpen.Collections.Remove<Hashtable, SmbComTransaction>(response_map, req);
- ResponseMap.Remove(req);
- }
- }
- }
- finally
- {
- BufferCache.ReleaseBuffer(req.TxnBuf);
- BufferCache.ReleaseBuffer(resp.TxnBuf);
- }
- }
- else
- {
- response.Command = request.Command;
- Sendrecv(request, response, SmbConstants.ResponseTimeout);
- }
- }
- catch (SmbException se)
- {
- throw;
- }
- catch (IOException ioe)
- {
- throw new SmbException(ioe.Message, ioe);
- }
- CheckStatus(request, response);
- }
- public override string ToString()
- {
- return base.ToString() + "[" + Address + ":" + Port + "]";
- }
- internal virtual void DfsPathSplit(string path, string[] result)
- {
- int ri = 0;
- int rlast = result.Length - 1;
- int i = 0;
- int b = 0;
- int len = path.Length;
- do
- {
- if (ri == rlast)
- {
- result[rlast] = Runtime.Substring(path, b);
- return;
- }
- if (i == len || path[i] == '\\')
- {
- result[ri++] = Runtime.Substring(path, b, i);
- b = i + 1;
- }
- }
- while (i++ < len);
- while (ri < result.Length)
- {
- result[ri++] = string.Empty;
- }
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual DfsReferral GetDfsReferrals(NtlmPasswordAuthentication auth,
- string path,
- int rn)
- {
- SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
- Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
- ipc.Send(new Trans2GetDfsReferral(path), resp);
- if (resp.NumReferrals == 0)
- {
- return null;
- }
- if (rn == 0 || resp.NumReferrals < rn)
- {
- rn = resp.NumReferrals;
- }
- DfsReferral dr = new DfsReferral();
- string[] arr = new string[4];
- long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000;
- int di = 0;
- for (;;)
- {
- dr.ResolveHashes = auth.HashesExternal;
- dr.Ttl = resp.Referrals[di].Ttl;
- dr.Expiration = expiration;
- if (path.Equals(string.Empty))
- {
- dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower();
- }
- else
- {
- DfsPathSplit(resp.Referrals[di].Node, arr);
- dr.Server = arr[1];
- dr.Share = arr[2];
- dr.Path = arr[3];
- }
- dr.PathConsumed = resp.PathConsumed;
- di++;
- if (di == rn)
- {
- break;
- }
- dr.Append(new DfsReferral());
- dr = dr.Next;
- }
- return dr.Next;
- }
- /// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual DfsReferral[] __getDfsReferrals(NtlmPasswordAuthentication auth,
- string path,
- int rn)
- {
- SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
- Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
- ipc.Send(new Trans2GetDfsReferral(path), resp);
- if (rn == 0 || resp.NumReferrals < rn)
- {
- rn = resp.NumReferrals;
- }
- DfsReferral[] drs = new DfsReferral[rn];
- string[] arr = new string[4];
- long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000;
- for (int di = 0; di < drs.Length; di++)
- {
- DfsReferral dr = new DfsReferral();
- dr.ResolveHashes = auth.HashesExternal;
- dr.Ttl = resp.Referrals[di].Ttl;
- dr.Expiration = expiration;
- if (path.Equals(string.Empty))
- {
- dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower();
- }
- else
- {
- DfsPathSplit(resp.Referrals[di].Node, arr);
- dr.Server = arr[1];
- dr.Share = arr[2];
- dr.Path = arr[3];
- }
- dr.PathConsumed = resp.PathConsumed;
- drs[di] = dr;
- }
- return drs;
- }
- }
- }
|