mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-30 18:22:48 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			901 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			901 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // 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;
 | |
| 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.Hashtable
 | |
| 
 | |
| namespace 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();
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |