| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900 | // 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  USAusing System;using System.Collections;using System.Collections.Generic;using System.IO;using SharpCifs.Dcerpc;using SharpCifs.Dcerpc.Msrpc;using SharpCifs.Util;using SharpCifs.Util.Sharpen;using Hashtable = SharpCifs.Util.Sharpen.Hashtable; //not System.Collections.Hashtablenamespace SharpCifs.Smb{	/// <summary>	/// A Windows SID is a numeric identifier used to represent Windows	/// accounts.	/// </summary>	/// <remarks>	/// A Windows SID is a numeric identifier used to represent Windows	/// accounts. SIDs are commonly represented using a textual format such as	/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt> but they may	/// also be resolved to yield the name of the associated Windows account	/// such as <tt>Administrators</tt> or <tt>MYDOM\alice</tt>.	/// <p>	/// Consider the following output of <tt>examples/SidLookup.java</tt>:	/// <pre>	/// toString: S-1-5-21-4133388617-793952518-2001621813-512	/// toDisplayString: WNET\Domain Admins	/// getType: 2	/// getTypeText: Domain group	/// getDomainName: WNET	/// getAccountName: Domain Admins	/// </pre>	/// </remarks>	public class Sid : Rpc.SidT	{		public const int SidTypeUseNone = Lsarpc.SidNameUseNone;		public const int SidTypeUser = Lsarpc.SidNameUser;		public const int SidTypeDomGrp = Lsarpc.SidNameDomGrp;		public const int SidTypeDomain = Lsarpc.SidNameDomain;		public const int SidTypeAlias = Lsarpc.SidNameAlias;		public const int SidTypeWknGrp = Lsarpc.SidNameWknGrp;		public const int SidTypeDeleted = Lsarpc.SidNameDeleted;		public const int SidTypeInvalid = Lsarpc.SidNameInvalid;		public const int SidTypeUnknown = Lsarpc.SidNameUnknown;		internal static readonly string[] SidTypeNames = { "0", "User", "Domain group"			, "Domain", "Local group", "Builtin group", "Deleted", "Invalid", "Unknown" };		public const int SidFlagResolveSids = unchecked(0x0001);		public static Sid Everyone;		public static Sid CreatorOwner;		public static Sid SYSTEM;		static Sid()		{			try			{				Everyone = new Sid("S-1-1-0");				CreatorOwner = new Sid("S-1-3-0");				SYSTEM = new Sid("S-1-5-18");			}			catch (SmbException)			{			}		}		internal static Hashtable SidCache = new Hashtable();		/// <exception cref="System.IO.IOException"></exception>		internal static void ResolveSids(DcerpcHandle handle, LsaPolicyHandle policyHandle			, Sid[] sids)		{			MsrpcLookupSids rpc = new MsrpcLookupSids(policyHandle, sids);			handle.Sendrecv(rpc);			switch (rpc.Retval)			{				case 0:				case NtStatus.NtStatusNoneMapped:				case unchecked(0x00000107):				{					// NT_STATUS_SOME_NOT_MAPPED					break;				}				default:				{					throw new SmbException(rpc.Retval, false);				}			}			for (int si = 0; si < sids.Length; si++)			{				sids[si].Type = rpc.Names.Names[si].SidType;				sids[si].DomainName = null;				switch (sids[si].Type)				{					case SidTypeUser:					case SidTypeDomGrp:					case SidTypeDomain:					case SidTypeAlias:					case SidTypeWknGrp:					{						int sidIndex = rpc.Names.Names[si].SidIndex;						Rpc.Unicode_string ustr = rpc.Domains.Domains[sidIndex].Name;						sids[si].DomainName = (new UnicodeString(ustr, false)).ToString();						break;					}				}				sids[si].AcctName = (new UnicodeString(rpc.Names.Names[si].Name, false)).ToString					();				sids[si].OriginServer = null;				sids[si].OriginAuth = null;			}		}		/// <exception cref="System.IO.IOException"></exception>		internal static void ResolveSids0(string authorityServerName, NtlmPasswordAuthentication			 auth, Sid[] sids)		{			DcerpcHandle handle = null;			LsaPolicyHandle policyHandle = null;			lock (SidCache)			{				try				{					handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\lsarpc]"						, auth);					string server = authorityServerName;					int dot = server.IndexOf('.');					if (dot > 0 && char.IsDigit(server[0]) == false)					{						server = Runtime.Substring(server, 0, dot);					}					policyHandle = new LsaPolicyHandle(handle, "\\\\" + server, unchecked(0x00000800));					ResolveSids(handle, policyHandle, sids);				}				finally				{					if (handle != null)					{						if (policyHandle != null)						{							policyHandle.Close();						}						handle.Close();					}				}			}		}		/// <exception cref="System.IO.IOException"></exception>		public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication			 auth, Sid[] sids, int offset, int length)		{            List<object> list = new List<object>();//new List<object>(sids.Length);			int si;			lock (SidCache)			{				for (si = 0; si < length; si++)				{					Sid sid = (Sid)SidCache.Get(sids[offset + si]);					if (sid != null)					{						sids[offset + si].Type = sid.Type;						sids[offset + si].DomainName = sid.DomainName;						sids[offset + si].AcctName = sid.AcctName;					}					else					{						list.Add(sids[offset + si]);					}				}				if (list.Count > 0)				{					//sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);                    sids = (Sid[])list.ToArray();					ResolveSids0(authorityServerName, auth, sids);					for (si = 0; si < sids.Length; si++)					{						SidCache.Put(sids[si], sids[si]);					}				}			}		}		/// <summary>Resolve an array of SIDs using a cache and at most one MSRPC request.</summary>		/// <remarks>		/// Resolve an array of SIDs using a cache and at most one MSRPC request.		/// <p>		/// This method will attempt		/// to resolve SIDs using a cache and cache the results of any SIDs that		/// required resolving with the authority. SID cache entries are currently not		/// expired because under normal circumstances SID information never changes.		/// </remarks>		/// <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.		/// 	</param>		/// <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.		/// 	</param>		/// <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.		/// 	</param>		/// <exception cref="System.IO.IOException"></exception>		public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication			 auth, Sid[] sids)		{            List<object> list = new List<object>();//new List<object>(sids.Length);			int si;			lock (SidCache)			{				for (si = 0; si < sids.Length; si++)				{					Sid sid = (Sid)SidCache.Get(sids[si]);					if (sid != null)					{						sids[si].Type = sid.Type;						sids[si].DomainName = sid.DomainName;						sids[si].AcctName = sid.AcctName;					}					else					{						list.Add(sids[si]);					}				}				if (list.Count > 0)				{					//sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]);				    sids = (Sid[]) list.ToArray();					ResolveSids0(authorityServerName, auth, sids);					for (si = 0; si < sids.Length; si++)					{						SidCache.Put(sids[si], sids[si]);					}				}			}		}		/// <exception cref="System.IO.IOException"></exception>		public static Sid GetServerSid(string server, NtlmPasswordAuthentication			 auth)		{			DcerpcHandle handle = null;			LsaPolicyHandle policyHandle = null;			Lsarpc.LsarDomainInfo info = new Lsarpc.LsarDomainInfo();			MsrpcQueryInformationPolicy rpc;			lock (SidCache)			{				try				{					handle = DcerpcHandle.GetHandle("ncacn_np:" + server + "[\\PIPE\\lsarpc]", auth);					// NetApp doesn't like the 'generic' access mask values					policyHandle = new LsaPolicyHandle(handle, null, unchecked(0x00000001));					rpc = new MsrpcQueryInformationPolicy(policyHandle, Lsarpc.PolicyInfoAccountDomain						, info);					handle.Sendrecv(rpc);					if (rpc.Retval != 0)					{						throw new SmbException(rpc.Retval, false);					}					return new Sid(info.Sid, SidTypeDomain, (new UnicodeString						(info.Name, false)).ToString(), null, false);				}				finally				{					if (handle != null)					{						if (policyHandle != null)						{							policyHandle.Close();						}						handle.Close();					}				}			}		}		public static byte[] ToByteArray(Rpc.SidT sid)		{			byte[] dst = new byte[1 + 1 + 6 + sid.SubAuthorityCount * 4];			int di = 0;			dst[di++] = sid.Revision;			dst[di++] = sid.SubAuthorityCount;			Array.Copy(sid.IdentifierAuthority, 0, dst, di, 6);			di += 6;			for (int ii = 0; ii < sid.SubAuthorityCount; ii++)			{				Encdec.Enc_uint32le(sid.SubAuthority[ii], dst, di);				di += 4;			}			return dst;		}		internal int Type;		internal string DomainName;		internal string AcctName;		internal string OriginServer;		internal NtlmPasswordAuthentication OriginAuth;		public Sid(byte[] src, int si)		{			Revision = src[si++];			SubAuthorityCount = src[si++];			IdentifierAuthority = new byte[6];			Array.Copy(src, si, IdentifierAuthority, 0, 6);			si += 6;			if (SubAuthorityCount > 100)			{				throw new RuntimeException("Invalid SID sub_authority_count");			}			SubAuthority = new int[SubAuthorityCount];			for (int i = 0; i < SubAuthorityCount; i++)			{				SubAuthority[i] = ServerMessageBlock.ReadInt4(src, si);				si += 4;			}		}		/// <summary>		/// Construct a SID from it's textual representation such as		/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.		/// </summary>		/// <remarks>		/// Construct a SID from it's textual representation such as		/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.		/// </remarks>		/// <exception cref="SharpCifs.Smb.SmbException"></exception>		public Sid(string textual)		{			StringTokenizer st = new StringTokenizer(textual, "-");			if (st.CountTokens() < 3 || !st.NextToken().Equals("S"))			{				// need S-N-M				throw new SmbException("Bad textual SID format: " + textual);			}			Revision = byte.Parse(st.NextToken());			string tmp = st.NextToken();			long id = 0;			if (tmp.StartsWith("0x"))			{				//id = long.Parse(Sharpen.Runtime.Substring(tmp, 2), 16);                id = long.Parse(Runtime.Substring(tmp, 2));			}			else			{				id = long.Parse(tmp);			}			IdentifierAuthority = new byte[6];			for (int i = 5; id > 0; i--)			{				IdentifierAuthority[i] = unchecked((byte)(id % 256));				id >>= 8;			}			SubAuthorityCount = unchecked((byte)st.CountTokens());			if (SubAuthorityCount > 0)			{				SubAuthority = new int[SubAuthorityCount];				for (int i1 = 0; i1 < SubAuthorityCount; i1++)				{					SubAuthority[i1] = (int)(long.Parse(st.NextToken()) & unchecked(0xFFFFFFFFL));				}			}		}		/// <summary>		/// Construct a SID from a domain SID and an RID		/// (relative identifier).		/// </summary>		/// <remarks>		/// Construct a SID from a domain SID and an RID		/// (relative identifier). For example, a domain SID		/// <tt>S-1-5-21-1496946806-2192648263-3843101252</tt> and RID <tt>1029</tt> would		/// yield the SID <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.		/// </remarks>		public Sid(Sid domsid, int rid)		{			Revision = domsid.Revision;			IdentifierAuthority = domsid.IdentifierAuthority;			SubAuthorityCount = unchecked((byte)(domsid.SubAuthorityCount + 1));			SubAuthority = new int[SubAuthorityCount];			int i;			for (i = 0; i < domsid.SubAuthorityCount; i++)			{				SubAuthority[i] = domsid.SubAuthority[i];			}			SubAuthority[i] = rid;		}		public Sid(Rpc.SidT sid, int type, string domainName, string acctName, bool decrementAuthority			)		{			Revision = sid.Revision;			SubAuthorityCount = sid.SubAuthorityCount;			IdentifierAuthority = sid.IdentifierAuthority;			SubAuthority = sid.SubAuthority;			this.Type = type;			this.DomainName = domainName;			this.AcctName = acctName;			if (decrementAuthority)			{				SubAuthorityCount--;				SubAuthority = new int[SubAuthorityCount];				for (int i = 0; i < SubAuthorityCount; i++)				{					SubAuthority[i] = sid.SubAuthority[i];				}			}		}		public virtual Sid GetDomainSid()		{			return new Sid(this, SidTypeDomain, DomainName, null, GetType() 				!= SidTypeDomain);		}		public virtual int GetRid()		{			if (GetType() == SidTypeDomain)			{				throw new ArgumentException("This SID is a domain sid");			}			return SubAuthority[SubAuthorityCount - 1];		}		/// <summary>Returns the type of this SID indicating the state or type of account.</summary>		/// <remarks>		/// Returns the type of this SID indicating the state or type of account.		/// <p>		/// SID types are described in the following table.		/// <tt>		/// <table>		/// <tr><th>Type</th><th>Name</th></tr>		/// <tr><td>SID_TYPE_USE_NONE</td><td>0</td></tr>		/// <tr><td>SID_TYPE_USER</td><td>User</td></tr>		/// <tr><td>SID_TYPE_DOM_GRP</td><td>Domain group</td></tr>		/// <tr><td>SID_TYPE_DOMAIN</td><td>Domain</td></tr>		/// <tr><td>SID_TYPE_ALIAS</td><td>Local group</td></tr>		/// <tr><td>SID_TYPE_WKN_GRP</td><td>Builtin group</td></tr>		/// <tr><td>SID_TYPE_DELETED</td><td>Deleted</td></tr>		/// <tr><td>SID_TYPE_INVALID</td><td>Invalid</td></tr>		/// <tr><td>SID_TYPE_UNKNOWN</td><td>Unknown</td></tr>		/// </table>		/// </tt>		/// </remarks>		public virtual int GetType()		{			if (OriginServer != null)			{				ResolveWeak();			}			return Type;		}		/// <summary>		/// Return text represeting the SID type suitable for display to		/// users.		/// </summary>		/// <remarks>		/// Return text represeting the SID type suitable for display to		/// users. Text includes 'User', 'Domain group', 'Local group', etc.		/// </remarks>		public virtual string GetTypeText()		{			if (OriginServer != null)			{				ResolveWeak();			}			return SidTypeNames[Type];		}		/// <summary>		/// Return the domain name of this SID unless it could not be		/// resolved in which case the numeric representation is returned.		/// </summary>		/// <remarks>		/// Return the domain name of this SID unless it could not be		/// resolved in which case the numeric representation is returned.		/// </remarks>		public virtual string GetDomainName()		{			if (OriginServer != null)			{				ResolveWeak();			}			if (Type == SidTypeUnknown)			{				string full = ToString();				return Runtime.Substring(full, 0, full.Length - GetAccountName().Length -					 1);			}			return DomainName;		}		/// <summary>		/// Return the sAMAccountName of this SID unless it could not		/// be resolved in which case the numeric RID is returned.		/// </summary>		/// <remarks>		/// Return the sAMAccountName of this SID unless it could not		/// be resolved in which case the numeric RID is returned. If this		/// SID is a domain SID, this method will return an empty String.		/// </remarks>		public virtual string GetAccountName()		{			if (OriginServer != null)			{				ResolveWeak();			}			if (Type == SidTypeUnknown)			{				return string.Empty + SubAuthority[SubAuthorityCount - 1];			}			if (Type == SidTypeDomain)			{				return string.Empty;			}			return AcctName;		}		public override int GetHashCode()		{			int hcode = IdentifierAuthority[5];			for (int i = 0; i < SubAuthorityCount; i++)			{				hcode += 65599 * SubAuthority[i];			}			return hcode;		}		public override bool Equals(object obj)		{			if (obj is Sid)			{				Sid sid = (Sid)obj;				if (sid == this)				{					return true;				}				if (sid.SubAuthorityCount == SubAuthorityCount)				{					int i = SubAuthorityCount;					while (i-- > 0)					{						if (sid.SubAuthority[i] != SubAuthority[i])						{							return false;						}					}					for (i = 0; i < 6; i++)					{						if (sid.IdentifierAuthority[i] != IdentifierAuthority[i])						{							return false;						}					}					return sid.Revision == Revision;				}			}			return false;		}		/// <summary>		/// Return the numeric representation of this sid such as		/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.		/// </summary>		/// <remarks>		/// Return the numeric representation of this sid such as		/// <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.		/// </remarks>		public override string ToString()		{			string ret = "S-" + (Revision & unchecked(0xFF)) + "-";			if (IdentifierAuthority[0] != unchecked(0) || IdentifierAuthority[1] != unchecked(				0))			{				ret += "0x";				ret += Hexdump.ToHexString(IdentifierAuthority, 0, 6);			}			else			{				int shift = 0;				long id = 0;				for (int i = 5; i > 1; i--)				{					id += (IdentifierAuthority[i] & unchecked(0xFFL)) << shift;					shift += 8;				}				ret += id;			}			for (int i1 = 0; i1 < SubAuthorityCount; i1++)			{				ret += "-" + (SubAuthority[i1] & unchecked(0xFFFFFFFFL));			}			return ret;		}		/// <summary>		/// Return a String representing this SID ideal for display to		/// users.		/// </summary>		/// <remarks>		/// Return a String representing this SID ideal for display to		/// users. This method should return the same text that the ACL		/// editor in Windows would display.		/// <p>		/// Specifically, if the SID has		/// been resolved and it is not a domain SID or builtin account,		/// the full DOMAIN\name form of the account will be		/// returned (e.g. MYDOM\alice or MYDOM\Domain Users).		/// If the SID has been resolved but it is is a domain SID,		/// only the domain name will be returned (e.g. MYDOM).		/// If the SID has been resolved but it is a builtin account,		/// only the name component will be returned (e.g. SYSTEM).		/// If the sid cannot be resolved the numeric representation from		/// toString() is returned.		/// </remarks>		public virtual string ToDisplayString()		{			if (OriginServer != null)			{				ResolveWeak();			}			if (DomainName != null)			{				string str;				if (Type == SidTypeDomain)				{					str = DomainName;				}				else				{					if (Type == SidTypeWknGrp || DomainName.Equals("BUILTIN"))					{						if (Type == SidTypeUnknown)						{							str = ToString();						}						else						{							str = AcctName;						}					}					else					{						str = DomainName + "\\" + AcctName;					}				}				return str;			}			return ToString();		}		/// <summary>Manually resolve this SID.</summary>		/// <remarks>		/// Manually resolve this SID. Normally SIDs are automatically		/// resolved. However, if a SID is constructed explicitly using a SID		/// constructor, JCIFS will have no knowledge of the server that created the		/// SID and therefore cannot possibly resolve it automatically. In this case,		/// this method will be necessary.		/// </remarks>		/// <param name="authorityServerName">The FQDN of the server that is an authority for the SID.		/// 	</param>		/// <param name="auth">Credentials suitable for accessing the SID's information.</param>		/// <exception cref="System.IO.IOException"></exception>		public virtual void Resolve(string authorityServerName, NtlmPasswordAuthentication			 auth)		{			Sid[] sids = new Sid[1];			sids[0] = this;			ResolveSids(authorityServerName, auth, sids);		}		internal virtual void ResolveWeak()		{			if (OriginServer != null)			{				try				{					Resolve(OriginServer, OriginAuth);				}				catch (IOException)				{				}				finally				{					OriginServer = null;					OriginAuth = null;				}			}		}		/// <exception cref="System.IO.IOException"></exception>		internal static Sid[] GetGroupMemberSids0(DcerpcHandle handle, SamrDomainHandle			 domainHandle, Sid domsid, int rid, int flags)		{			SamrAliasHandle aliasHandle = null;			Lsarpc.LsarSidArray sidarray = new Lsarpc.LsarSidArray();			MsrpcGetMembersInAlias rpc = null;			try			{				aliasHandle = new SamrAliasHandle(handle, domainHandle, unchecked(0x0002000c), rid);				rpc = new MsrpcGetMembersInAlias(aliasHandle, sidarray);				handle.Sendrecv(rpc);				if (rpc.Retval != 0)				{					throw new SmbException(rpc.Retval, false);				}				Sid[] sids = new Sid[rpc.Sids.NumSids];				string originServer = handle.GetServer();				NtlmPasswordAuthentication originAuth = (NtlmPasswordAuthentication)handle.GetPrincipal					();				for (int i = 0; i < sids.Length; i++)				{					sids[i] = new Sid(rpc.Sids.Sids[i].Sid, 0, null, null, false);					sids[i].OriginServer = originServer;					sids[i].OriginAuth = originAuth;				}				if (sids.Length > 0 && (flags & SidFlagResolveSids) != 0)				{					ResolveSids(originServer, originAuth, sids);				}				return sids;			}			finally			{				if (aliasHandle != null)				{					aliasHandle.Close();				}			}		}		/// <exception cref="System.IO.IOException"></exception>		public virtual Sid[] GetGroupMemberSids(string authorityServerName, NtlmPasswordAuthentication			 auth, int flags)		{			if (Type != SidTypeDomGrp && Type != SidTypeAlias)			{				return new Sid[0];			}			DcerpcHandle handle = null;			SamrPolicyHandle policyHandle = null;			SamrDomainHandle domainHandle = null;			Sid domsid = GetDomainSid();			lock (SidCache)			{				try				{					handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]"						, auth);					policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x00000030));					domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x00000200), domsid);					return GetGroupMemberSids0(handle, domainHandle, domsid, GetRid(), 						flags);				}				finally				{					if (handle != null)					{						if (policyHandle != null)						{							if (domainHandle != null)							{								domainHandle.Close();							}							policyHandle.Close();						}						handle.Close();					}				}			}		}		/// <summary>		/// This specialized method returns a Map of users and local groups for the		/// target server where keys are SIDs representing an account and each value		/// is an List<object> of SIDs represents the local groups that the account is		/// a member of.		/// </summary>		/// <remarks>		/// This specialized method returns a Map of users and local groups for the		/// target server where keys are SIDs representing an account and each value		/// is an List<object> of SIDs represents the local groups that the account is		/// a member of.		/// <p/>		/// This method is designed to assist with computing access control for a		/// given user when the target object's ACL has local groups. Local groups		/// are not listed in a user's group membership (e.g. as represented by the		/// tokenGroups constructed attribute retrived via LDAP).		/// <p/>		/// Domain groups nested inside a local group are currently not expanded. In		/// this case the key (SID) type will be SID_TYPE_DOM_GRP rather than		/// SID_TYPE_USER.		/// </remarks>		/// <param name="authorityServerName">The server from which the local groups will be queried.		/// 	</param>		/// <param name="auth">The credentials required to query groups and group members.</param>		/// <param name="flags">		/// Flags that control the behavior of the operation. When all		/// name associated with SIDs will be required, the SID_FLAG_RESOLVE_SIDS		/// flag should be used which causes all group member SIDs to be resolved		/// together in a single more efficient operation.		/// </param>		/// <exception cref="System.IO.IOException"></exception>		internal static Hashtable GetLocalGroupsMap(string authorityServerName, NtlmPasswordAuthentication			 auth, int flags)		{			Sid domsid = GetServerSid(authorityServerName, auth);			DcerpcHandle handle = null;			SamrPolicyHandle policyHandle = null;			SamrDomainHandle domainHandle = null;			Samr.SamrSamArray sam = new Samr.SamrSamArray();			MsrpcEnumerateAliasesInDomain rpc;			lock (SidCache)			{				try				{					handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]"						, auth);					policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x02000000));					domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x02000000), domsid);					rpc = new MsrpcEnumerateAliasesInDomain(domainHandle, unchecked(0xFFFF), sam						);					handle.Sendrecv(rpc);					if (rpc.Retval != 0)					{						throw new SmbException(rpc.Retval, false);					}                    Hashtable map = new Hashtable();					for (int ei = 0; ei < rpc.Sam.Count; ei++)					{						Samr.SamrSamEntry entry = rpc.Sam.Entries[ei];						Sid[] mems = GetGroupMemberSids0(handle, domainHandle, domsid							, entry.Idx, flags);						Sid groupSid = new Sid(domsid, entry.Idx);						groupSid.Type = SidTypeAlias;						groupSid.DomainName = domsid.GetDomainName();						groupSid.AcctName = (new UnicodeString(entry.Name, false)).ToString();						for (int mi = 0; mi < mems.Length; mi++)						{							List<object> groups = (List<object>)map.Get(mems[mi]);							if (groups == null)							{								groups = new List<object>();								map.Put(mems[mi], groups);							}							if (!groups.Contains(groupSid))							{								groups.Add(groupSid);							}						}					}					return map;				}				finally				{					if (handle != null)					{						if (policyHandle != null)						{							if (domainHandle != null)							{								domainHandle.Close();							}							policyHandle.Close();						}						handle.Close();					}				}			}		}	}}
 |