| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977 | // 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  USAusing 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;            }        }        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);                if (LocalAddr != null)                {                    Socket.Bind2(new IPEndPoint(LocalAddr, LocalPort));                }                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);                    if (LocalAddr != null)                    {                        Socket.Bind2(new IPEndPoint(LocalAddr, LocalPort));                    }                    Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()), port), 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.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;        }    }}
 |