aboutsummaryrefslogtreecommitdiff
path: root/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs')
-rw-r--r--Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs199
1 files changed, 131 insertions, 68 deletions
diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs
index 800d6d9bc..912b209a7 100644
--- a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs
+++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs
@@ -31,25 +31,30 @@ namespace SharpCifs.Smb
{
internal static readonly byte[] Buf = new byte[0xFFFF];
- internal static readonly SmbComNegotiate NegotiateRequest = new SmbComNegotiate(
- );
+ 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
- )
+ internal static SmbTransport GetSmbTransport(UniAddress address, int port)
{
lock (typeof(SmbTransport))
{
- return GetSmbTransport(address, port, SmbConstants.Laddr, SmbConstants.Lport, null);
+ return GetSmbTransport(address,
+ port,
+ SmbConstants.Laddr,
+ SmbConstants.Lport,
+ null);
}
}
- internal static SmbTransport GetSmbTransport(UniAddress address, int port
- , IPAddress localAddr, int localPort, string hostName)
+ internal static SmbTransport GetSmbTransport(UniAddress address,
+ int port,
+ IPAddress localAddr,
+ int localPort,
+ string hostName)
{
lock (typeof(SmbTransport))
{
@@ -59,18 +64,19 @@ namespace SharpCifs.Smb
{
if (SmbConstants.SsnLimit != 1)
{
- conn =
- SmbConstants.Connections.FirstOrDefault(
- c =>
- c.Matches(address, port, localAddr, localPort, hostName) &&
- (SmbConstants.SsnLimit ==
- 0 || c.Sessions.Count < SmbConstants.SsnLimit));
+ 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);
@@ -80,6 +86,26 @@ namespace SharpCifs.Smb
}
}
+
+ /// <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;
@@ -174,8 +200,10 @@ namespace SharpCifs.Smb
internal string TconHostName;
- internal SmbTransport(UniAddress address, int port, IPAddress localAddr, int localPort
- )
+ internal SmbTransport(UniAddress address,
+ int port,
+ IPAddress localAddr,
+ int localPort)
{
Server = new ServerData(this);
this.Address = address;
@@ -206,7 +234,8 @@ namespace SharpCifs.Smb
return ssn;
}
- if (SmbConstants.SoTimeout > 0 && SessionExpiration < (now = Runtime.CurrentTimeMillis()))
+ if (SmbConstants.SoTimeout > 0
+ && SessionExpiration < (now = Runtime.CurrentTimeMillis()))
{
SessionExpiration = now + SmbConstants.SoTimeout;
@@ -222,16 +251,25 @@ namespace SharpCifs.Smb
}
}
- internal virtual bool Matches(UniAddress address, int port, IPAddress localAddr,
- int localPort, string hostName)
+ 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;
+ 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>
@@ -250,31 +288,36 @@ namespace SharpCifs.Smb
internal virtual bool IsSignatureSetupRequired(NtlmPasswordAuthentication auth)
{
- return (Flags2 & SmbConstants.Flags2SecuritySignatures) != 0 && Digest ==
- null && auth != NtlmPasswordAuthentication.Null && NtlmPasswordAuthentication.Null
- .Equals(auth) == false;
+ 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
- );
+ 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 = 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
- ());
+ SessionServicePacket ssp = new SessionRequestPacket(calledName,
+ NbtAddress.GetLocalName());
Out.Write(Sbuf, 0, ssp.WriteWireFormat(Sbuf, 0));
if (Readn(In, Sbuf, 0, 4) < 4)
{
@@ -317,7 +360,8 @@ namespace SharpCifs.Smb
default:
{
Disconnect(true);
- throw new NbtException(NbtException.ErrSsnSrvc, errorCode);
+ throw new NbtException(NbtException.ErrSsnSrvc,
+ errorCode);
}
}
break;
@@ -326,8 +370,8 @@ namespace SharpCifs.Smb
case -1:
{
Disconnect(true);
- throw new NbtException(NbtException.ErrSsnSrvc, NbtException.ConnectionRefused
- );
+ throw new NbtException(NbtException.ErrSsnSrvc,
+ NbtException.ConnectionRefused);
}
default:
@@ -357,13 +401,18 @@ namespace SharpCifs.Smb
port = SmbConstants.DefaultPort;
}
// 445
- Socket = new SocketEx(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- if (LocalAddr != null)
- {
- Socket.Bind2(new IPEndPoint(LocalAddr, LocalPort));
- }
+ 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.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()), port), SmbConstants.ConnTimeout);
Socket.SoTimeOut = SmbConstants.SoTimeout;
Out = Socket.GetOutputStream();
In = Socket.GetInputStream();
@@ -430,21 +479,28 @@ namespace SharpCifs.Smb
}
catch (ConnectException)
{
- Port = (Port == -1 || Port == SmbConstants.DefaultPort) ? 139 : SmbConstants.DefaultPort;
+ 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)
+ if (
+ (Server.Capabilities & SmbConstants.CapExtendedSecurity)
+ != SmbConstants.CapExtendedSecurity
+ && Server.EncryptionKeyLength != 8
+ && SmbConstants.LmCompatibility == 0
+ )
{
- throw new SmbException("Unexpected encryption key length: " + Server.EncryptionKeyLength
- );
+ throw new SmbException("Unexpected encryption key length: "
+ + Server.EncryptionKeyLength);
}
TconHostName = Address.GetHostName();
- if (Server.SignaturesRequired || (Server.SignaturesEnabled && SmbConstants.Signpref))
+ if (Server.SignaturesRequired
+ || (Server.SignaturesEnabled && SmbConstants.Signpref))
{
Flags2 |= SmbConstants.Flags2SecuritySignatures;
}
@@ -459,7 +515,8 @@ namespace SharpCifs.Smb
}
SndBufSize = Math.Min(SndBufSize, Server.MaxBufferSize);
Capabilities &= Server.Capabilities;
- if ((Server.Capabilities & SmbConstants.CapExtendedSecurity) == SmbConstants.CapExtendedSecurity)
+ if ((Server.Capabilities & SmbConstants.CapExtendedSecurity)
+ == SmbConstants.CapExtendedSecurity)
{
Capabilities |= SmbConstants.CapExtendedSecurity;
}
@@ -494,6 +551,7 @@ namespace SharpCifs.Smb
//Socket.`Close` method deleted
//Socket.Close();
+ Socket.Shutdown(SocketShutdown.Both);
Socket.Dispose();
}
finally
@@ -536,7 +594,7 @@ namespace SharpCifs.Smb
Log.WriteLine("New data read: " + this);
Hexdump.ToHexdump(Log, Sbuf, 4, 32);
}
- for (; ; )
+ for (;;)
{
if (Sbuf[0] == 0x00 && Sbuf[1] == 0x00 &&
Sbuf[4] == 0xFF &&
@@ -575,8 +633,8 @@ namespace SharpCifs.Smb
{
Log.WriteLine(smb);
}
- while (smb is AndXServerMessageBlock && (smb = ((AndXServerMessageBlock)smb).Andx
- ) != null);
+ while (smb is AndXServerMessageBlock
+ && (smb = ((AndXServerMessageBlock)smb).Andx) != null);
if (Log.Level >= 6)
{
Hexdump.ToHexdump(Log, Buf, 4, n);
@@ -616,7 +674,9 @@ namespace SharpCifs.Smb
{
ServerMessageBlock resp = (ServerMessageBlock)response;
resp.UseUnicode = UseUnicode;
- resp.ExtendedSecurity = (Capabilities & SmbConstants.CapExtendedSecurity) == SmbConstants.CapExtendedSecurity;
+ resp.ExtendedSecurity
+ = (Capabilities & SmbConstants.CapExtendedSecurity)
+ == SmbConstants.CapExtendedSecurity;
lock (Buf)
{
Array.Copy(Sbuf, 0, Buf, 0, 4 + SmbConstants.HeaderLength);
@@ -626,8 +686,10 @@ namespace SharpCifs.Smb
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))))
+ if (resp.Command == ServerMessageBlock.SmbComReadAndx
+ && (errorCode == 0
+ || errorCode == unchecked((int)(0x80000005)))
+ )
{
// overflow indicator normal for pipe
SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp;
@@ -684,8 +746,7 @@ namespace SharpCifs.Smb
}
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual void CheckStatus(ServerMessageBlock req, ServerMessageBlock resp
- )
+ internal virtual void CheckStatus(ServerMessageBlock req, ServerMessageBlock resp)
{
resp.ErrorCode = SmbException.GetStatusByCode(resp.ErrorCode);
switch (resp.ErrorCode)
@@ -746,8 +807,7 @@ namespace SharpCifs.Smb
}
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response
- )
+ internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response)
{
Connect();
request.Flags2 |= Flags2;
@@ -809,7 +869,8 @@ namespace SharpCifs.Smb
timeout = resp.Expiration - Runtime.CurrentTimeMillis();
if (timeout <= 0)
{
- throw new TransportException(this + " timedout waiting for response to " + req);
+ throw new TransportException(
+ this + " timedout waiting for response to " + req);
}
}
if (response.ErrorCode != 0)
@@ -825,7 +886,7 @@ namespace SharpCifs.Smb
}
else
{
- throw new TransportException(ie);
+ throw new TransportException(ie);
}
}
finally
@@ -891,8 +952,9 @@ namespace SharpCifs.Smb
}
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
- internal virtual DfsReferral GetDfsReferrals(NtlmPasswordAuthentication auth, string
- path, int rn)
+ internal virtual DfsReferral GetDfsReferrals(NtlmPasswordAuthentication auth,
+ string path,
+ int rn)
{
SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
@@ -909,7 +971,7 @@ namespace SharpCifs.Smb
string[] arr = new string[4];
long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000;
int di = 0;
- for (; ; )
+ for (;;)
{
dr.ResolveHashes = auth.HashesExternal;
dr.Ttl = resp.Referrals[di].Ttl;
@@ -939,7 +1001,8 @@ namespace SharpCifs.Smb
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
internal virtual DfsReferral[] __getDfsReferrals(NtlmPasswordAuthentication auth,
- string path, int rn)
+ string path,
+ int rn)
{
SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null);
Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();