diff options
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs')
| -rw-r--r-- | Emby.Server.Implementations/IO/SharpCifs/Smb/Dfs.cs | 389 |
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); + } + } + } +} |
