aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs')
-rw-r--r--Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs900
1 files changed, 900 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs b/Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs
new file mode 100644
index 000000000..a6ad59fb1
--- /dev/null
+++ b/Emby.Server.Implementations/IO/SharpCifs/Smb/SID.cs
@@ -0,0 +1,900 @@
+// 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();
+ }
+ }
+ }
+ }
+ }
+}