SID.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  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;
  18. using System.Collections;
  19. using System.Collections.Generic;
  20. using System.IO;
  21. using SharpCifs.Dcerpc;
  22. using SharpCifs.Dcerpc.Msrpc;
  23. using SharpCifs.Util;
  24. using SharpCifs.Util.Sharpen;
  25. using Hashtable = SharpCifs.Util.Sharpen.Hashtable; //not System.Collections.Hashtable
  26. namespace SharpCifs.Smb
  27. {
  28. /// <summary>
  29. /// A Windows SID is a numeric identifier used to represent Windows
  30. /// accounts.
  31. /// </summary>
  32. /// <remarks>
  33. /// A Windows SID is a numeric identifier used to represent Windows
  34. /// accounts. SIDs are commonly represented using a textual format such as
  35. /// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt> but they may
  36. /// also be resolved to yield the name of the associated Windows account
  37. /// such as <tt>Administrators</tt> or <tt>MYDOM\alice</tt>.
  38. /// <p>
  39. /// Consider the following output of <tt>examples/SidLookup.java</tt>:
  40. /// <pre>
  41. /// toString: S-1-5-21-4133388617-793952518-2001621813-512
  42. /// toDisplayString: WNET\Domain Admins
  43. /// getType: 2
  44. /// getTypeText: Domain group
  45. /// getDomainName: WNET
  46. /// getAccountName: Domain Admins
  47. /// </pre>
  48. /// </remarks>
  49. public class Sid : Rpc.SidT
  50. {
  51. public const int SidTypeUseNone = Lsarpc.SidNameUseNone;
  52. public const int SidTypeUser = Lsarpc.SidNameUser;
  53. public const int SidTypeDomGrp = Lsarpc.SidNameDomGrp;
  54. public const int SidTypeDomain = Lsarpc.SidNameDomain;
  55. public const int SidTypeAlias = Lsarpc.SidNameAlias;
  56. public const int SidTypeWknGrp = Lsarpc.SidNameWknGrp;
  57. public const int SidTypeDeleted = Lsarpc.SidNameDeleted;
  58. public const int SidTypeInvalid = Lsarpc.SidNameInvalid;
  59. public const int SidTypeUnknown = Lsarpc.SidNameUnknown;
  60. internal static readonly string[] SidTypeNames = { "0", "User", "Domain group"
  61. , "Domain", "Local group", "Builtin group", "Deleted", "Invalid", "Unknown" };
  62. public const int SidFlagResolveSids = unchecked(0x0001);
  63. public static Sid Everyone;
  64. public static Sid CreatorOwner;
  65. public static Sid SYSTEM;
  66. static Sid()
  67. {
  68. try
  69. {
  70. Everyone = new Sid("S-1-1-0");
  71. CreatorOwner = new Sid("S-1-3-0");
  72. SYSTEM = new Sid("S-1-5-18");
  73. }
  74. catch (SmbException)
  75. {
  76. }
  77. }
  78. internal static Hashtable SidCache = new Hashtable();
  79. /// <exception cref="System.IO.IOException"></exception>
  80. internal static void ResolveSids(DcerpcHandle handle, LsaPolicyHandle policyHandle
  81. , Sid[] sids)
  82. {
  83. MsrpcLookupSids rpc = new MsrpcLookupSids(policyHandle, sids);
  84. handle.Sendrecv(rpc);
  85. switch (rpc.Retval)
  86. {
  87. case 0:
  88. case NtStatus.NtStatusNoneMapped:
  89. case unchecked(0x00000107):
  90. {
  91. // NT_STATUS_SOME_NOT_MAPPED
  92. break;
  93. }
  94. default:
  95. {
  96. throw new SmbException(rpc.Retval, false);
  97. }
  98. }
  99. for (int si = 0; si < sids.Length; si++)
  100. {
  101. sids[si].Type = rpc.Names.Names[si].SidType;
  102. sids[si].DomainName = null;
  103. switch (sids[si].Type)
  104. {
  105. case SidTypeUser:
  106. case SidTypeDomGrp:
  107. case SidTypeDomain:
  108. case SidTypeAlias:
  109. case SidTypeWknGrp:
  110. {
  111. int sidIndex = rpc.Names.Names[si].SidIndex;
  112. Rpc.Unicode_string ustr = rpc.Domains.Domains[sidIndex].Name;
  113. sids[si].DomainName = (new UnicodeString(ustr, false)).ToString();
  114. break;
  115. }
  116. }
  117. sids[si].AcctName = (new UnicodeString(rpc.Names.Names[si].Name, false)).ToString
  118. ();
  119. sids[si].OriginServer = null;
  120. sids[si].OriginAuth = null;
  121. }
  122. }
  123. /// <exception cref="System.IO.IOException"></exception>
  124. internal static void ResolveSids0(string authorityServerName, NtlmPasswordAuthentication
  125. auth, Sid[] sids)
  126. {
  127. DcerpcHandle handle = null;
  128. LsaPolicyHandle policyHandle = null;
  129. lock (SidCache)
  130. {
  131. try
  132. {
  133. handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\lsarpc]"
  134. , auth);
  135. string server = authorityServerName;
  136. int dot = server.IndexOf('.');
  137. if (dot > 0 && char.IsDigit(server[0]) == false)
  138. {
  139. server = Runtime.Substring(server, 0, dot);
  140. }
  141. policyHandle = new LsaPolicyHandle(handle, "\\\\" + server, unchecked(0x00000800));
  142. ResolveSids(handle, policyHandle, sids);
  143. }
  144. finally
  145. {
  146. if (handle != null)
  147. {
  148. if (policyHandle != null)
  149. {
  150. policyHandle.Close();
  151. }
  152. handle.Close();
  153. }
  154. }
  155. }
  156. }
  157. /// <exception cref="System.IO.IOException"></exception>
  158. public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication
  159. auth, Sid[] sids, int offset, int length)
  160. {
  161. List<object> list = new List<object>();//new List<object>(sids.Length);
  162. int si;
  163. lock (SidCache)
  164. {
  165. for (si = 0; si < length; si++)
  166. {
  167. Sid sid = (Sid)SidCache.Get(sids[offset + si]);
  168. if (sid != null)
  169. {
  170. sids[offset + si].Type = sid.Type;
  171. sids[offset + si].DomainName = sid.DomainName;
  172. sids[offset + si].AcctName = sid.AcctName;
  173. }
  174. else
  175. {
  176. list.Add(sids[offset + si]);
  177. }
  178. }
  179. if (list.Count > 0)
  180. {
  181. //sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);
  182. sids = (Sid[])list.ToArray();
  183. ResolveSids0(authorityServerName, auth, sids);
  184. for (si = 0; si < sids.Length; si++)
  185. {
  186. SidCache.Put(sids[si], sids[si]);
  187. }
  188. }
  189. }
  190. }
  191. /// <summary>Resolve an array of SIDs using a cache and at most one MSRPC request.</summary>
  192. /// <remarks>
  193. /// Resolve an array of SIDs using a cache and at most one MSRPC request.
  194. /// <p>
  195. /// This method will attempt
  196. /// to resolve SIDs using a cache and cache the results of any SIDs that
  197. /// required resolving with the authority. SID cache entries are currently not
  198. /// expired because under normal circumstances SID information never changes.
  199. /// </remarks>
  200. /// <param name="authorityServerName">The hostname of the server that should be queried. For maximum efficiency this should be the hostname of a domain controller however a member server will work as well and a domain controller may not return names for SIDs corresponding to local accounts for which the domain controller is not an authority.
  201. /// </param>
  202. /// <param name="auth">The credentials that should be used to communicate with the named server. As usual, <tt>null</tt> indicates that default credentials should be used.
  203. /// </param>
  204. /// <param name="sids">The SIDs that should be resolved. After this function is called, the names associated with the SIDs may be queried with the <tt>toDisplayString</tt>, <tt>getDomainName</tt>, and <tt>getAccountName</tt> methods.
  205. /// </param>
  206. /// <exception cref="System.IO.IOException"></exception>
  207. public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication
  208. auth, Sid[] sids)
  209. {
  210. List<object> list = new List<object>();//new List<object>(sids.Length);
  211. int si;
  212. lock (SidCache)
  213. {
  214. for (si = 0; si < sids.Length; si++)
  215. {
  216. Sid sid = (Sid)SidCache.Get(sids[si]);
  217. if (sid != null)
  218. {
  219. sids[si].Type = sid.Type;
  220. sids[si].DomainName = sid.DomainName;
  221. sids[si].AcctName = sid.AcctName;
  222. }
  223. else
  224. {
  225. list.Add(sids[si]);
  226. }
  227. }
  228. if (list.Count > 0)
  229. {
  230. //sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);
  231. sids = (Sid[]) list.ToArray();
  232. ResolveSids0(authorityServerName, auth, sids);
  233. for (si = 0; si < sids.Length; si++)
  234. {
  235. SidCache.Put(sids[si], sids[si]);
  236. }
  237. }
  238. }
  239. }
  240. /// <exception cref="System.IO.IOException"></exception>
  241. public static Sid GetServerSid(string server, NtlmPasswordAuthentication
  242. auth)
  243. {
  244. DcerpcHandle handle = null;
  245. LsaPolicyHandle policyHandle = null;
  246. Lsarpc.LsarDomainInfo info = new Lsarpc.LsarDomainInfo();
  247. MsrpcQueryInformationPolicy rpc;
  248. lock (SidCache)
  249. {
  250. try
  251. {
  252. handle = DcerpcHandle.GetHandle("ncacn_np:" + server + "[\\PIPE\\lsarpc]", auth);
  253. // NetApp doesn't like the 'generic' access mask values
  254. policyHandle = new LsaPolicyHandle(handle, null, unchecked(0x00000001));
  255. rpc = new MsrpcQueryInformationPolicy(policyHandle, Lsarpc.PolicyInfoAccountDomain
  256. , info);
  257. handle.Sendrecv(rpc);
  258. if (rpc.Retval != 0)
  259. {
  260. throw new SmbException(rpc.Retval, false);
  261. }
  262. return new Sid(info.Sid, SidTypeDomain, (new UnicodeString
  263. (info.Name, false)).ToString(), null, false);
  264. }
  265. finally
  266. {
  267. if (handle != null)
  268. {
  269. if (policyHandle != null)
  270. {
  271. policyHandle.Close();
  272. }
  273. handle.Close();
  274. }
  275. }
  276. }
  277. }
  278. public static byte[] ToByteArray(Rpc.SidT sid)
  279. {
  280. byte[] dst = new byte[1 + 1 + 6 + sid.SubAuthorityCount * 4];
  281. int di = 0;
  282. dst[di++] = sid.Revision;
  283. dst[di++] = sid.SubAuthorityCount;
  284. Array.Copy(sid.IdentifierAuthority, 0, dst, di, 6);
  285. di += 6;
  286. for (int ii = 0; ii < sid.SubAuthorityCount; ii++)
  287. {
  288. Encdec.Enc_uint32le(sid.SubAuthority[ii], dst, di);
  289. di += 4;
  290. }
  291. return dst;
  292. }
  293. internal int Type;
  294. internal string DomainName;
  295. internal string AcctName;
  296. internal string OriginServer;
  297. internal NtlmPasswordAuthentication OriginAuth;
  298. public Sid(byte[] src, int si)
  299. {
  300. Revision = src[si++];
  301. SubAuthorityCount = src[si++];
  302. IdentifierAuthority = new byte[6];
  303. Array.Copy(src, si, IdentifierAuthority, 0, 6);
  304. si += 6;
  305. if (SubAuthorityCount > 100)
  306. {
  307. throw new RuntimeException("Invalid SID sub_authority_count");
  308. }
  309. SubAuthority = new int[SubAuthorityCount];
  310. for (int i = 0; i < SubAuthorityCount; i++)
  311. {
  312. SubAuthority[i] = ServerMessageBlock.ReadInt4(src, si);
  313. si += 4;
  314. }
  315. }
  316. /// <summary>
  317. /// Construct a SID from it's textual representation such as
  318. /// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
  319. /// </summary>
  320. /// <remarks>
  321. /// Construct a SID from it's textual representation such as
  322. /// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
  323. /// </remarks>
  324. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  325. public Sid(string textual)
  326. {
  327. StringTokenizer st = new StringTokenizer(textual, "-");
  328. if (st.CountTokens() < 3 || !st.NextToken().Equals("S"))
  329. {
  330. // need S-N-M
  331. throw new SmbException("Bad textual SID format: " + textual);
  332. }
  333. Revision = byte.Parse(st.NextToken());
  334. string tmp = st.NextToken();
  335. long id = 0;
  336. if (tmp.StartsWith("0x"))
  337. {
  338. //id = long.Parse(Sharpen.Runtime.Substring(tmp, 2), 16);
  339. id = long.Parse(Runtime.Substring(tmp, 2));
  340. }
  341. else
  342. {
  343. id = long.Parse(tmp);
  344. }
  345. IdentifierAuthority = new byte[6];
  346. for (int i = 5; id > 0; i--)
  347. {
  348. IdentifierAuthority[i] = unchecked((byte)(id % 256));
  349. id >>= 8;
  350. }
  351. SubAuthorityCount = unchecked((byte)st.CountTokens());
  352. if (SubAuthorityCount > 0)
  353. {
  354. SubAuthority = new int[SubAuthorityCount];
  355. for (int i1 = 0; i1 < SubAuthorityCount; i1++)
  356. {
  357. SubAuthority[i1] = (int)(long.Parse(st.NextToken()) & unchecked(0xFFFFFFFFL));
  358. }
  359. }
  360. }
  361. /// <summary>
  362. /// Construct a SID from a domain SID and an RID
  363. /// (relative identifier).
  364. /// </summary>
  365. /// <remarks>
  366. /// Construct a SID from a domain SID and an RID
  367. /// (relative identifier). For example, a domain SID
  368. /// <tt>S-1-5-21-1496946806-2192648263-3843101252</tt> and RID <tt>1029</tt> would
  369. /// yield the SID <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
  370. /// </remarks>
  371. public Sid(Sid domsid, int rid)
  372. {
  373. Revision = domsid.Revision;
  374. IdentifierAuthority = domsid.IdentifierAuthority;
  375. SubAuthorityCount = unchecked((byte)(domsid.SubAuthorityCount + 1));
  376. SubAuthority = new int[SubAuthorityCount];
  377. int i;
  378. for (i = 0; i < domsid.SubAuthorityCount; i++)
  379. {
  380. SubAuthority[i] = domsid.SubAuthority[i];
  381. }
  382. SubAuthority[i] = rid;
  383. }
  384. public Sid(Rpc.SidT sid, int type, string domainName, string acctName, bool decrementAuthority
  385. )
  386. {
  387. Revision = sid.Revision;
  388. SubAuthorityCount = sid.SubAuthorityCount;
  389. IdentifierAuthority = sid.IdentifierAuthority;
  390. SubAuthority = sid.SubAuthority;
  391. this.Type = type;
  392. this.DomainName = domainName;
  393. this.AcctName = acctName;
  394. if (decrementAuthority)
  395. {
  396. SubAuthorityCount--;
  397. SubAuthority = new int[SubAuthorityCount];
  398. for (int i = 0; i < SubAuthorityCount; i++)
  399. {
  400. SubAuthority[i] = sid.SubAuthority[i];
  401. }
  402. }
  403. }
  404. public virtual Sid GetDomainSid()
  405. {
  406. return new Sid(this, SidTypeDomain, DomainName, null, GetType()
  407. != SidTypeDomain);
  408. }
  409. public virtual int GetRid()
  410. {
  411. if (GetType() == SidTypeDomain)
  412. {
  413. throw new ArgumentException("This SID is a domain sid");
  414. }
  415. return SubAuthority[SubAuthorityCount - 1];
  416. }
  417. /// <summary>Returns the type of this SID indicating the state or type of account.</summary>
  418. /// <remarks>
  419. /// Returns the type of this SID indicating the state or type of account.
  420. /// <p>
  421. /// SID types are described in the following table.
  422. /// <tt>
  423. /// <table>
  424. /// <tr><th>Type</th><th>Name</th></tr>
  425. /// <tr><td>SID_TYPE_USE_NONE</td><td>0</td></tr>
  426. /// <tr><td>SID_TYPE_USER</td><td>User</td></tr>
  427. /// <tr><td>SID_TYPE_DOM_GRP</td><td>Domain group</td></tr>
  428. /// <tr><td>SID_TYPE_DOMAIN</td><td>Domain</td></tr>
  429. /// <tr><td>SID_TYPE_ALIAS</td><td>Local group</td></tr>
  430. /// <tr><td>SID_TYPE_WKN_GRP</td><td>Builtin group</td></tr>
  431. /// <tr><td>SID_TYPE_DELETED</td><td>Deleted</td></tr>
  432. /// <tr><td>SID_TYPE_INVALID</td><td>Invalid</td></tr>
  433. /// <tr><td>SID_TYPE_UNKNOWN</td><td>Unknown</td></tr>
  434. /// </table>
  435. /// </tt>
  436. /// </remarks>
  437. public virtual int GetType()
  438. {
  439. if (OriginServer != null)
  440. {
  441. ResolveWeak();
  442. }
  443. return Type;
  444. }
  445. /// <summary>
  446. /// Return text represeting the SID type suitable for display to
  447. /// users.
  448. /// </summary>
  449. /// <remarks>
  450. /// Return text represeting the SID type suitable for display to
  451. /// users. Text includes 'User', 'Domain group', 'Local group', etc.
  452. /// </remarks>
  453. public virtual string GetTypeText()
  454. {
  455. if (OriginServer != null)
  456. {
  457. ResolveWeak();
  458. }
  459. return SidTypeNames[Type];
  460. }
  461. /// <summary>
  462. /// Return the domain name of this SID unless it could not be
  463. /// resolved in which case the numeric representation is returned.
  464. /// </summary>
  465. /// <remarks>
  466. /// Return the domain name of this SID unless it could not be
  467. /// resolved in which case the numeric representation is returned.
  468. /// </remarks>
  469. public virtual string GetDomainName()
  470. {
  471. if (OriginServer != null)
  472. {
  473. ResolveWeak();
  474. }
  475. if (Type == SidTypeUnknown)
  476. {
  477. string full = ToString();
  478. return Runtime.Substring(full, 0, full.Length - GetAccountName().Length -
  479. 1);
  480. }
  481. return DomainName;
  482. }
  483. /// <summary>
  484. /// Return the sAMAccountName of this SID unless it could not
  485. /// be resolved in which case the numeric RID is returned.
  486. /// </summary>
  487. /// <remarks>
  488. /// Return the sAMAccountName of this SID unless it could not
  489. /// be resolved in which case the numeric RID is returned. If this
  490. /// SID is a domain SID, this method will return an empty String.
  491. /// </remarks>
  492. public virtual string GetAccountName()
  493. {
  494. if (OriginServer != null)
  495. {
  496. ResolveWeak();
  497. }
  498. if (Type == SidTypeUnknown)
  499. {
  500. return string.Empty + SubAuthority[SubAuthorityCount - 1];
  501. }
  502. if (Type == SidTypeDomain)
  503. {
  504. return string.Empty;
  505. }
  506. return AcctName;
  507. }
  508. public override int GetHashCode()
  509. {
  510. int hcode = IdentifierAuthority[5];
  511. for (int i = 0; i < SubAuthorityCount; i++)
  512. {
  513. hcode += 65599 * SubAuthority[i];
  514. }
  515. return hcode;
  516. }
  517. public override bool Equals(object obj)
  518. {
  519. if (obj is Sid)
  520. {
  521. Sid sid = (Sid)obj;
  522. if (sid == this)
  523. {
  524. return true;
  525. }
  526. if (sid.SubAuthorityCount == SubAuthorityCount)
  527. {
  528. int i = SubAuthorityCount;
  529. while (i-- > 0)
  530. {
  531. if (sid.SubAuthority[i] != SubAuthority[i])
  532. {
  533. return false;
  534. }
  535. }
  536. for (i = 0; i < 6; i++)
  537. {
  538. if (sid.IdentifierAuthority[i] != IdentifierAuthority[i])
  539. {
  540. return false;
  541. }
  542. }
  543. return sid.Revision == Revision;
  544. }
  545. }
  546. return false;
  547. }
  548. /// <summary>
  549. /// Return the numeric representation of this sid such as
  550. /// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
  551. /// </summary>
  552. /// <remarks>
  553. /// Return the numeric representation of this sid such as
  554. /// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
  555. /// </remarks>
  556. public override string ToString()
  557. {
  558. string ret = "S-" + (Revision & unchecked(0xFF)) + "-";
  559. if (IdentifierAuthority[0] != unchecked(0) || IdentifierAuthority[1] != unchecked(
  560. 0))
  561. {
  562. ret += "0x";
  563. ret += Hexdump.ToHexString(IdentifierAuthority, 0, 6);
  564. }
  565. else
  566. {
  567. int shift = 0;
  568. long id = 0;
  569. for (int i = 5; i > 1; i--)
  570. {
  571. id += (IdentifierAuthority[i] & unchecked(0xFFL)) << shift;
  572. shift += 8;
  573. }
  574. ret += id;
  575. }
  576. for (int i1 = 0; i1 < SubAuthorityCount; i1++)
  577. {
  578. ret += "-" + (SubAuthority[i1] & unchecked(0xFFFFFFFFL));
  579. }
  580. return ret;
  581. }
  582. /// <summary>
  583. /// Return a String representing this SID ideal for display to
  584. /// users.
  585. /// </summary>
  586. /// <remarks>
  587. /// Return a String representing this SID ideal for display to
  588. /// users. This method should return the same text that the ACL
  589. /// editor in Windows would display.
  590. /// <p>
  591. /// Specifically, if the SID has
  592. /// been resolved and it is not a domain SID or builtin account,
  593. /// the full DOMAIN\name form of the account will be
  594. /// returned (e.g. MYDOM\alice or MYDOM\Domain Users).
  595. /// If the SID has been resolved but it is is a domain SID,
  596. /// only the domain name will be returned (e.g. MYDOM).
  597. /// If the SID has been resolved but it is a builtin account,
  598. /// only the name component will be returned (e.g. SYSTEM).
  599. /// If the sid cannot be resolved the numeric representation from
  600. /// toString() is returned.
  601. /// </remarks>
  602. public virtual string ToDisplayString()
  603. {
  604. if (OriginServer != null)
  605. {
  606. ResolveWeak();
  607. }
  608. if (DomainName != null)
  609. {
  610. string str;
  611. if (Type == SidTypeDomain)
  612. {
  613. str = DomainName;
  614. }
  615. else
  616. {
  617. if (Type == SidTypeWknGrp || DomainName.Equals("BUILTIN"))
  618. {
  619. if (Type == SidTypeUnknown)
  620. {
  621. str = ToString();
  622. }
  623. else
  624. {
  625. str = AcctName;
  626. }
  627. }
  628. else
  629. {
  630. str = DomainName + "\\" + AcctName;
  631. }
  632. }
  633. return str;
  634. }
  635. return ToString();
  636. }
  637. /// <summary>Manually resolve this SID.</summary>
  638. /// <remarks>
  639. /// Manually resolve this SID. Normally SIDs are automatically
  640. /// resolved. However, if a SID is constructed explicitly using a SID
  641. /// constructor, JCIFS will have no knowledge of the server that created the
  642. /// SID and therefore cannot possibly resolve it automatically. In this case,
  643. /// this method will be necessary.
  644. /// </remarks>
  645. /// <param name="authorityServerName">The FQDN of the server that is an authority for the SID.
  646. /// </param>
  647. /// <param name="auth">Credentials suitable for accessing the SID's information.</param>
  648. /// <exception cref="System.IO.IOException"></exception>
  649. public virtual void Resolve(string authorityServerName, NtlmPasswordAuthentication
  650. auth)
  651. {
  652. Sid[] sids = new Sid[1];
  653. sids[0] = this;
  654. ResolveSids(authorityServerName, auth, sids);
  655. }
  656. internal virtual void ResolveWeak()
  657. {
  658. if (OriginServer != null)
  659. {
  660. try
  661. {
  662. Resolve(OriginServer, OriginAuth);
  663. }
  664. catch (IOException)
  665. {
  666. }
  667. finally
  668. {
  669. OriginServer = null;
  670. OriginAuth = null;
  671. }
  672. }
  673. }
  674. /// <exception cref="System.IO.IOException"></exception>
  675. internal static Sid[] GetGroupMemberSids0(DcerpcHandle handle, SamrDomainHandle
  676. domainHandle, Sid domsid, int rid, int flags)
  677. {
  678. SamrAliasHandle aliasHandle = null;
  679. Lsarpc.LsarSidArray sidarray = new Lsarpc.LsarSidArray();
  680. MsrpcGetMembersInAlias rpc = null;
  681. try
  682. {
  683. aliasHandle = new SamrAliasHandle(handle, domainHandle, unchecked(0x0002000c), rid);
  684. rpc = new MsrpcGetMembersInAlias(aliasHandle, sidarray);
  685. handle.Sendrecv(rpc);
  686. if (rpc.Retval != 0)
  687. {
  688. throw new SmbException(rpc.Retval, false);
  689. }
  690. Sid[] sids = new Sid[rpc.Sids.NumSids];
  691. string originServer = handle.GetServer();
  692. NtlmPasswordAuthentication originAuth = (NtlmPasswordAuthentication)handle.GetPrincipal
  693. ();
  694. for (int i = 0; i < sids.Length; i++)
  695. {
  696. sids[i] = new Sid(rpc.Sids.Sids[i].Sid, 0, null, null, false);
  697. sids[i].OriginServer = originServer;
  698. sids[i].OriginAuth = originAuth;
  699. }
  700. if (sids.Length > 0 && (flags & SidFlagResolveSids) != 0)
  701. {
  702. ResolveSids(originServer, originAuth, sids);
  703. }
  704. return sids;
  705. }
  706. finally
  707. {
  708. if (aliasHandle != null)
  709. {
  710. aliasHandle.Close();
  711. }
  712. }
  713. }
  714. /// <exception cref="System.IO.IOException"></exception>
  715. public virtual Sid[] GetGroupMemberSids(string authorityServerName, NtlmPasswordAuthentication
  716. auth, int flags)
  717. {
  718. if (Type != SidTypeDomGrp && Type != SidTypeAlias)
  719. {
  720. return new Sid[0];
  721. }
  722. DcerpcHandle handle = null;
  723. SamrPolicyHandle policyHandle = null;
  724. SamrDomainHandle domainHandle = null;
  725. Sid domsid = GetDomainSid();
  726. lock (SidCache)
  727. {
  728. try
  729. {
  730. handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]"
  731. , auth);
  732. policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x00000030));
  733. domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x00000200), domsid);
  734. return GetGroupMemberSids0(handle, domainHandle, domsid, GetRid(),
  735. flags);
  736. }
  737. finally
  738. {
  739. if (handle != null)
  740. {
  741. if (policyHandle != null)
  742. {
  743. if (domainHandle != null)
  744. {
  745. domainHandle.Close();
  746. }
  747. policyHandle.Close();
  748. }
  749. handle.Close();
  750. }
  751. }
  752. }
  753. }
  754. /// <summary>
  755. /// This specialized method returns a Map of users and local groups for the
  756. /// target server where keys are SIDs representing an account and each value
  757. /// is an List<object> of SIDs represents the local groups that the account is
  758. /// a member of.
  759. /// </summary>
  760. /// <remarks>
  761. /// This specialized method returns a Map of users and local groups for the
  762. /// target server where keys are SIDs representing an account and each value
  763. /// is an List<object> of SIDs represents the local groups that the account is
  764. /// a member of.
  765. /// <p/>
  766. /// This method is designed to assist with computing access control for a
  767. /// given user when the target object's ACL has local groups. Local groups
  768. /// are not listed in a user's group membership (e.g. as represented by the
  769. /// tokenGroups constructed attribute retrived via LDAP).
  770. /// <p/>
  771. /// Domain groups nested inside a local group are currently not expanded. In
  772. /// this case the key (SID) type will be SID_TYPE_DOM_GRP rather than
  773. /// SID_TYPE_USER.
  774. /// </remarks>
  775. /// <param name="authorityServerName">The server from which the local groups will be queried.
  776. /// </param>
  777. /// <param name="auth">The credentials required to query groups and group members.</param>
  778. /// <param name="flags">
  779. /// Flags that control the behavior of the operation. When all
  780. /// name associated with SIDs will be required, the SID_FLAG_RESOLVE_SIDS
  781. /// flag should be used which causes all group member SIDs to be resolved
  782. /// together in a single more efficient operation.
  783. /// </param>
  784. /// <exception cref="System.IO.IOException"></exception>
  785. internal static Hashtable GetLocalGroupsMap(string authorityServerName, NtlmPasswordAuthentication
  786. auth, int flags)
  787. {
  788. Sid domsid = GetServerSid(authorityServerName, auth);
  789. DcerpcHandle handle = null;
  790. SamrPolicyHandle policyHandle = null;
  791. SamrDomainHandle domainHandle = null;
  792. Samr.SamrSamArray sam = new Samr.SamrSamArray();
  793. MsrpcEnumerateAliasesInDomain rpc;
  794. lock (SidCache)
  795. {
  796. try
  797. {
  798. handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]"
  799. , auth);
  800. policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x02000000));
  801. domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x02000000), domsid);
  802. rpc = new MsrpcEnumerateAliasesInDomain(domainHandle, unchecked(0xFFFF), sam
  803. );
  804. handle.Sendrecv(rpc);
  805. if (rpc.Retval != 0)
  806. {
  807. throw new SmbException(rpc.Retval, false);
  808. }
  809. Hashtable map = new Hashtable();
  810. for (int ei = 0; ei < rpc.Sam.Count; ei++)
  811. {
  812. Samr.SamrSamEntry entry = rpc.Sam.Entries[ei];
  813. Sid[] mems = GetGroupMemberSids0(handle, domainHandle, domsid
  814. , entry.Idx, flags);
  815. Sid groupSid = new Sid(domsid, entry.Idx);
  816. groupSid.Type = SidTypeAlias;
  817. groupSid.DomainName = domsid.GetDomainName();
  818. groupSid.AcctName = (new UnicodeString(entry.Name, false)).ToString();
  819. for (int mi = 0; mi < mems.Length; mi++)
  820. {
  821. List<object> groups = (List<object>)map.Get(mems[mi]);
  822. if (groups == null)
  823. {
  824. groups = new List<object>();
  825. map.Put(mems[mi], groups);
  826. }
  827. if (!groups.Contains(groupSid))
  828. {
  829. groups.Add(groupSid);
  830. }
  831. }
  832. }
  833. return map;
  834. }
  835. finally
  836. {
  837. if (handle != null)
  838. {
  839. if (policyHandle != null)
  840. {
  841. if (domainHandle != null)
  842. {
  843. domainHandle.Close();
  844. }
  845. policyHandle.Close();
  846. }
  847. handle.Close();
  848. }
  849. }
  850. }
  851. }
  852. }
  853. }