aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs')
-rw-r--r--Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs389
1 files changed, 389 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs b/Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs
new file mode 100644
index 0000000000..2f62e5b8d0
--- /dev/null
+++ b/Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs
@@ -0,0 +1,389 @@
+// 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.IO;
+using SharpCifs.Util;
+using SharpCifs.Util.Sharpen;
+
+namespace SharpCifs.Smb
+{
+ public class Dfs
+ {
+ internal class CacheEntry
+ {
+ internal long Expiration;
+
+ internal Hashtable Map;
+
+ internal CacheEntry(long ttl)
+ {
+ if (ttl == 0)
+ {
+ ttl = Ttl;
+ }
+ Expiration = Runtime.CurrentTimeMillis() + ttl * 1000L;
+ Map = new Hashtable();
+ }
+ }
+
+ internal static LogStream Log = LogStream.GetInstance();
+
+ internal static readonly bool StrictView = Config.GetBoolean("jcifs.smb.client.dfs.strictView"
+ , false);
+
+ internal static readonly long Ttl = Config.GetLong("jcifs.smb.client.dfs.ttl", 300
+ );
+
+ internal static readonly bool Disabled = Config.GetBoolean("jcifs.smb.client.dfs.disabled"
+ , false);
+
+ internal static CacheEntry FalseEntry = new CacheEntry(0L);
+
+ internal CacheEntry Domains;
+
+ internal CacheEntry Referrals;
+
+ /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
+ public virtual Hashtable GetTrustedDomains(NtlmPasswordAuthentication auth)
+ {
+ if (Disabled || auth.Domain == "?")
+ {
+ return null;
+ }
+ if (Domains != null && Runtime.CurrentTimeMillis() > Domains.Expiration)
+ {
+ Domains = null;
+ }
+ if (Domains != null)
+ {
+ return Domains.Map;
+ }
+ try
+ {
+ UniAddress addr = UniAddress.GetByName(auth.Domain, true);
+ SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0);
+ CacheEntry entry = new CacheEntry(Ttl * 10L);
+ DfsReferral dr = trans.GetDfsReferrals(auth, string.Empty, 0);
+ if (dr != null)
+ {
+ DfsReferral start = dr;
+ do
+ {
+ string domain = dr.Server.ToLower();
+ entry.Map.Put(domain, new Hashtable());
+ dr = dr.Next;
+ }
+ while (dr != start);
+ Domains = entry;
+ return Domains.Map;
+ }
+ }
+ catch (IOException ioe)
+ {
+ if (Log.Level >= 3)
+ {
+ Runtime.PrintStackTrace(ioe, Log);
+ }
+ if (StrictView && ioe is SmbAuthException)
+ {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
+ public virtual bool IsTrustedDomain(string domain, NtlmPasswordAuthentication auth
+ )
+ {
+ Hashtable domains = GetTrustedDomains(auth);
+ if (domains == null)
+ {
+ return false;
+ }
+ domain = domain.ToLower();
+ return domains.Get(domain) != null;
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
+ public virtual SmbTransport GetDc(string domain, NtlmPasswordAuthentication auth)
+ {
+ if (Disabled)
+ {
+ return null;
+ }
+ try
+ {
+ UniAddress addr = UniAddress.GetByName(domain, true);
+ SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0);
+ DfsReferral dr = trans.GetDfsReferrals(auth, "\\" + domain, 1);
+ if (dr != null)
+ {
+ DfsReferral start = dr;
+ IOException e = null;
+ do
+ {
+ try
+ {
+ addr = UniAddress.GetByName(dr.Server);
+ return SmbTransport.GetSmbTransport(addr, 0);
+ }
+ catch (IOException ioe)
+ {
+ e = ioe;
+ }
+ dr = dr.Next;
+ }
+ while (dr != start);
+ throw e;
+ }
+ }
+ catch (IOException ioe)
+ {
+ if (Log.Level >= 3)
+ {
+ Runtime.PrintStackTrace(ioe, Log);
+ }
+ if (StrictView && ioe is SmbAuthException)
+ {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
+ public virtual DfsReferral GetReferral(SmbTransport trans, string domain, string
+ root, string path, NtlmPasswordAuthentication auth)
+ {
+ if (Disabled)
+ {
+ return null;
+ }
+ try
+ {
+ string p = "\\" + domain + "\\" + root;
+ if (path != null)
+ {
+ p += path;
+ }
+ DfsReferral dr = trans.GetDfsReferrals(auth, p, 0);
+ if (dr != null)
+ {
+ return dr;
+ }
+ }
+ catch (IOException ioe)
+ {
+ if (Log.Level >= 4)
+ {
+ Runtime.PrintStackTrace(ioe, Log);
+ }
+ if (StrictView && ioe is SmbAuthException)
+ {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
+ public virtual DfsReferral Resolve(string domain, string root, string path, NtlmPasswordAuthentication
+ auth)
+ {
+ lock (this)
+ {
+ DfsReferral dr = null;
+ long now = Runtime.CurrentTimeMillis();
+ if (Disabled || root.Equals("IPC$"))
+ {
+ return null;
+ }
+ Hashtable domains = GetTrustedDomains(auth);
+ if (domains != null)
+ {
+ domain = domain.ToLower();
+ Hashtable roots = (Hashtable)domains.Get(domain);
+ if (roots != null)
+ {
+ SmbTransport trans = null;
+ root = root.ToLower();
+ CacheEntry links = (CacheEntry)roots.Get(root);
+ if (links != null && now > links.Expiration)
+ {
+ //Sharpen.Collections.Remove(roots, root);
+ roots.Remove(root);
+ links = null;
+ }
+ if (links == null)
+ {
+ if ((trans = GetDc(domain, auth)) == null)
+ {
+ return null;
+ }
+ dr = GetReferral(trans, domain, root, path, auth);
+ if (dr != null)
+ {
+ int len = 1 + domain.Length + 1 + root.Length;
+ links = new CacheEntry(0L);
+ DfsReferral tmp = dr;
+ do
+ {
+ if (path == null)
+ {
+ // TODO: fix this
+ //tmp.map = links.map;
+ tmp.Key = "\\";
+ }
+ tmp.PathConsumed -= len;
+ tmp = tmp.Next;
+ }
+ while (tmp != dr);
+ if (dr.Key != null)
+ {
+ links.Map.Put(dr.Key, dr);
+ }
+ roots.Put(root, links);
+ }
+ else
+ {
+ if (path == null)
+ {
+ roots.Put(root, FalseEntry);
+ }
+ }
+ }
+ else
+ {
+ if (links == FalseEntry)
+ {
+ links = null;
+ }
+ }
+ if (links != null)
+ {
+ string link = "\\";
+ dr = (DfsReferral)links.Map.Get(link);
+ if (dr != null && now > dr.Expiration)
+ {
+ //Sharpen.Collections.Remove(links.map, link);
+ links.Map.Remove(link);
+ dr = null;
+ }
+ if (dr == null)
+ {
+ if (trans == null)
+ {
+ if ((trans = GetDc(domain, auth)) == null)
+ {
+ return null;
+ }
+ }
+ dr = GetReferral(trans, domain, root, path, auth);
+ if (dr != null)
+ {
+ dr.PathConsumed -= 1 + domain.Length + 1 + root.Length;
+ dr.Link = link;
+ links.Map.Put(link, dr);
+ }
+ }
+ }
+ }
+ }
+ if (dr == null && path != null)
+ {
+ if (Referrals != null && now > Referrals.Expiration)
+ {
+ Referrals = null;
+ }
+ if (Referrals == null)
+ {
+ Referrals = new CacheEntry(0);
+ }
+ string key = "\\" + domain + "\\" + root;
+ if (path.Equals("\\") == false)
+ {
+ key += path;
+ }
+ key = key.ToLower();
+ //ListIterator<object> iter = new ListIterator<object>(referrals.map.Keys.GetEnumerator(), 0);
+ foreach (var current in Referrals.Map.Keys)
+ {
+ string _key = (string)current;
+ int klen = _key.Length;
+ bool match = false;
+ if (klen == key.Length)
+ {
+ match = _key.Equals(key);
+ }
+ else
+ {
+ if (klen < key.Length)
+ {
+ match = _key.RegionMatches(false, 0, key, 0, klen) && key[klen] == '\\';
+ }
+ }
+ if (match)
+ {
+ dr = (DfsReferral)Referrals.Map.Get(_key);
+ }
+ }
+ }
+ return dr;
+ }
+ }
+
+ internal virtual void Insert(string path, DfsReferral dr)
+ {
+ lock (this)
+ {
+ int s1;
+ int s2;
+ string server;
+ string share;
+ string key;
+ if (Disabled)
+ {
+ return;
+ }
+ s1 = path.IndexOf('\\', 1);
+ s2 = path.IndexOf('\\', s1 + 1);
+ server = Runtime.Substring(path, 1, s1);
+ share = Runtime.Substring(path, s1 + 1, s2);
+ key = Runtime.Substring(path, 0, dr.PathConsumed).ToLower();
+ int ki = key.Length;
+ while (ki > 1 && key[ki - 1] == '\\')
+ {
+ ki--;
+ }
+ if (ki < key.Length)
+ {
+ key = Runtime.Substring(key, 0, ki);
+ }
+ dr.PathConsumed -= 1 + server.Length + 1 + share.Length;
+ if (Referrals != null && (Runtime.CurrentTimeMillis() + 10000) > Referrals.Expiration)
+ {
+ Referrals = null;
+ }
+ if (Referrals == null)
+ {
+ Referrals = new CacheEntry(0);
+ }
+ Referrals.Map.Put(key, dr);
+ }
+ }
+ }
+}