Dfs.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System.IO;
  18. using SharpCifs.Util;
  19. using SharpCifs.Util.Sharpen;
  20. namespace SharpCifs.Smb
  21. {
  22. public class Dfs
  23. {
  24. internal class CacheEntry
  25. {
  26. internal long Expiration;
  27. internal Hashtable Map;
  28. internal CacheEntry(long ttl)
  29. {
  30. if (ttl == 0)
  31. {
  32. ttl = Ttl;
  33. }
  34. Expiration = Runtime.CurrentTimeMillis() + ttl * 1000L;
  35. Map = new Hashtable();
  36. }
  37. }
  38. internal static LogStream Log = LogStream.GetInstance();
  39. internal static readonly bool StrictView = Config.GetBoolean("jcifs.smb.client.dfs.strictView"
  40. , false);
  41. internal static readonly long Ttl = Config.GetLong("jcifs.smb.client.dfs.ttl", 300
  42. );
  43. internal static readonly bool Disabled = Config.GetBoolean("jcifs.smb.client.dfs.disabled"
  44. , false);
  45. internal static CacheEntry FalseEntry = new CacheEntry(0L);
  46. internal CacheEntry Domains;
  47. internal CacheEntry Referrals;
  48. /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
  49. public virtual Hashtable GetTrustedDomains(NtlmPasswordAuthentication auth)
  50. {
  51. if (Disabled || auth.Domain == "?")
  52. {
  53. return null;
  54. }
  55. if (Domains != null && Runtime.CurrentTimeMillis() > Domains.Expiration)
  56. {
  57. Domains = null;
  58. }
  59. if (Domains != null)
  60. {
  61. return Domains.Map;
  62. }
  63. try
  64. {
  65. UniAddress addr = UniAddress.GetByName(auth.Domain, true);
  66. SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0);
  67. CacheEntry entry = new CacheEntry(Ttl * 10L);
  68. DfsReferral dr = trans.GetDfsReferrals(auth, string.Empty, 0);
  69. if (dr != null)
  70. {
  71. DfsReferral start = dr;
  72. do
  73. {
  74. string domain = dr.Server.ToLower();
  75. entry.Map.Put(domain, new Hashtable());
  76. dr = dr.Next;
  77. }
  78. while (dr != start);
  79. Domains = entry;
  80. return Domains.Map;
  81. }
  82. }
  83. catch (IOException ioe)
  84. {
  85. if (Log.Level >= 3)
  86. {
  87. Runtime.PrintStackTrace(ioe, Log);
  88. }
  89. if (StrictView && ioe is SmbAuthException)
  90. {
  91. throw (SmbAuthException)ioe;
  92. }
  93. }
  94. return null;
  95. }
  96. /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
  97. public virtual bool IsTrustedDomain(string domain, NtlmPasswordAuthentication auth
  98. )
  99. {
  100. Hashtable domains = GetTrustedDomains(auth);
  101. if (domains == null)
  102. {
  103. return false;
  104. }
  105. domain = domain.ToLower();
  106. return domains.Get(domain) != null;
  107. }
  108. /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
  109. public virtual SmbTransport GetDc(string domain, NtlmPasswordAuthentication auth)
  110. {
  111. if (Disabled)
  112. {
  113. return null;
  114. }
  115. try
  116. {
  117. UniAddress addr = UniAddress.GetByName(domain, true);
  118. SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0);
  119. DfsReferral dr = trans.GetDfsReferrals(auth, "\\" + domain, 1);
  120. if (dr != null)
  121. {
  122. DfsReferral start = dr;
  123. IOException e = null;
  124. do
  125. {
  126. try
  127. {
  128. addr = UniAddress.GetByName(dr.Server);
  129. return SmbTransport.GetSmbTransport(addr, 0);
  130. }
  131. catch (IOException ioe)
  132. {
  133. e = ioe;
  134. }
  135. dr = dr.Next;
  136. }
  137. while (dr != start);
  138. throw e;
  139. }
  140. }
  141. catch (IOException ioe)
  142. {
  143. if (Log.Level >= 3)
  144. {
  145. Runtime.PrintStackTrace(ioe, Log);
  146. }
  147. if (StrictView && ioe is SmbAuthException)
  148. {
  149. throw (SmbAuthException)ioe;
  150. }
  151. }
  152. return null;
  153. }
  154. /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
  155. public virtual DfsReferral GetReferral(SmbTransport trans, string domain, string
  156. root, string path, NtlmPasswordAuthentication auth)
  157. {
  158. if (Disabled)
  159. {
  160. return null;
  161. }
  162. try
  163. {
  164. string p = "\\" + domain + "\\" + root;
  165. if (path != null)
  166. {
  167. p += path;
  168. }
  169. DfsReferral dr = trans.GetDfsReferrals(auth, p, 0);
  170. if (dr != null)
  171. {
  172. return dr;
  173. }
  174. }
  175. catch (IOException ioe)
  176. {
  177. if (Log.Level >= 4)
  178. {
  179. Runtime.PrintStackTrace(ioe, Log);
  180. }
  181. if (StrictView && ioe is SmbAuthException)
  182. {
  183. throw (SmbAuthException)ioe;
  184. }
  185. }
  186. return null;
  187. }
  188. /// <exception cref="SharpCifs.Smb.SmbAuthException"></exception>
  189. public virtual DfsReferral Resolve(string domain, string root, string path, NtlmPasswordAuthentication
  190. auth)
  191. {
  192. lock (this)
  193. {
  194. DfsReferral dr = null;
  195. long now = Runtime.CurrentTimeMillis();
  196. if (Disabled || root.Equals("IPC$"))
  197. {
  198. return null;
  199. }
  200. Hashtable domains = GetTrustedDomains(auth);
  201. if (domains != null)
  202. {
  203. domain = domain.ToLower();
  204. Hashtable roots = (Hashtable)domains.Get(domain);
  205. if (roots != null)
  206. {
  207. SmbTransport trans = null;
  208. root = root.ToLower();
  209. CacheEntry links = (CacheEntry)roots.Get(root);
  210. if (links != null && now > links.Expiration)
  211. {
  212. //Sharpen.Collections.Remove(roots, root);
  213. roots.Remove(root);
  214. links = null;
  215. }
  216. if (links == null)
  217. {
  218. if ((trans = GetDc(domain, auth)) == null)
  219. {
  220. return null;
  221. }
  222. dr = GetReferral(trans, domain, root, path, auth);
  223. if (dr != null)
  224. {
  225. int len = 1 + domain.Length + 1 + root.Length;
  226. links = new CacheEntry(0L);
  227. DfsReferral tmp = dr;
  228. do
  229. {
  230. if (path == null)
  231. {
  232. // TODO: fix this
  233. //tmp.map = links.map;
  234. tmp.Key = "\\";
  235. }
  236. tmp.PathConsumed -= len;
  237. tmp = tmp.Next;
  238. }
  239. while (tmp != dr);
  240. if (dr.Key != null)
  241. {
  242. links.Map.Put(dr.Key, dr);
  243. }
  244. roots.Put(root, links);
  245. }
  246. else
  247. {
  248. if (path == null)
  249. {
  250. roots.Put(root, FalseEntry);
  251. }
  252. }
  253. }
  254. else
  255. {
  256. if (links == FalseEntry)
  257. {
  258. links = null;
  259. }
  260. }
  261. if (links != null)
  262. {
  263. string link = "\\";
  264. dr = (DfsReferral)links.Map.Get(link);
  265. if (dr != null && now > dr.Expiration)
  266. {
  267. //Sharpen.Collections.Remove(links.map, link);
  268. links.Map.Remove(link);
  269. dr = null;
  270. }
  271. if (dr == null)
  272. {
  273. if (trans == null)
  274. {
  275. if ((trans = GetDc(domain, auth)) == null)
  276. {
  277. return null;
  278. }
  279. }
  280. dr = GetReferral(trans, domain, root, path, auth);
  281. if (dr != null)
  282. {
  283. dr.PathConsumed -= 1 + domain.Length + 1 + root.Length;
  284. dr.Link = link;
  285. links.Map.Put(link, dr);
  286. }
  287. }
  288. }
  289. }
  290. }
  291. if (dr == null && path != null)
  292. {
  293. if (Referrals != null && now > Referrals.Expiration)
  294. {
  295. Referrals = null;
  296. }
  297. if (Referrals == null)
  298. {
  299. Referrals = new CacheEntry(0);
  300. }
  301. string key = "\\" + domain + "\\" + root;
  302. if (path.Equals("\\") == false)
  303. {
  304. key += path;
  305. }
  306. key = key.ToLower();
  307. //ListIterator<object> iter = new ListIterator<object>(referrals.map.Keys.GetEnumerator(), 0);
  308. foreach (var current in Referrals.Map.Keys)
  309. {
  310. string _key = (string)current;
  311. int klen = _key.Length;
  312. bool match = false;
  313. if (klen == key.Length)
  314. {
  315. match = _key.Equals(key);
  316. }
  317. else
  318. {
  319. if (klen < key.Length)
  320. {
  321. match = _key.RegionMatches(false, 0, key, 0, klen) && key[klen] == '\\';
  322. }
  323. }
  324. if (match)
  325. {
  326. dr = (DfsReferral)Referrals.Map.Get(_key);
  327. }
  328. }
  329. }
  330. return dr;
  331. }
  332. }
  333. internal virtual void Insert(string path, DfsReferral dr)
  334. {
  335. lock (this)
  336. {
  337. int s1;
  338. int s2;
  339. string server;
  340. string share;
  341. string key;
  342. if (Disabled)
  343. {
  344. return;
  345. }
  346. s1 = path.IndexOf('\\', 1);
  347. s2 = path.IndexOf('\\', s1 + 1);
  348. server = Runtime.Substring(path, 1, s1);
  349. share = Runtime.Substring(path, s1 + 1, s2);
  350. key = Runtime.Substring(path, 0, dr.PathConsumed).ToLower();
  351. int ki = key.Length;
  352. while (ki > 1 && key[ki - 1] == '\\')
  353. {
  354. ki--;
  355. }
  356. if (ki < key.Length)
  357. {
  358. key = Runtime.Substring(key, 0, ki);
  359. }
  360. dr.PathConsumed -= 1 + server.Length + 1 + share.Length;
  361. if (Referrals != null && (Runtime.CurrentTimeMillis() + 10000) > Referrals.Expiration)
  362. {
  363. Referrals = null;
  364. }
  365. if (Referrals == null)
  366. {
  367. Referrals = new CacheEntry(0);
  368. }
  369. Referrals.Map.Put(key, dr);
  370. }
  371. }
  372. }
  373. }