private static extern int LsaLookupNames2(IntPtr PolicyHandle, uint Flags, uint Count, LSA_UNICODE_STRING[] Names, out IntPtr ReferencedDomains, out IntPtr Sids);
/// <summary> /// Creates a Security Identity from an object name (e.g. DOMAIN\AccountName) /// </summary> /// <param name="name">A security object name (i.e. a Computer, Account, or Group)</param> /// <returns>A populated Security Identity</returns> public static SecurityIdentity SecurityIdentityFromName(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name == "") { throw new ArgumentException("Argument 'name' cannot be the empty string.", "name"); } var attribs = new LSA_OBJECT_ATTRIBUTES { Attributes = 0, ObjectName = IntPtr.Zero, RootDirectory = IntPtr.Zero, SecurityDescriptor = IntPtr.Zero, SecurityQualityOfService = IntPtr.Zero }; attribs.Length = (uint)Marshal.SizeOf(attribs); var status = LsaOpenPolicy(IntPtr.Zero, ref attribs, ACCESS_MASK.POLICY_LOOKUP_NAMES, out var handle); if (status != 0) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(LsaNtStatusToWinError(status))); } try { var nameString = new LSA_UNICODE_STRING { Buffer = name, Length = (ushort)(name.Length * UnicodeEncoding.CharSize), MaxLength = (ushort)(name.Length * UnicodeEncoding.CharSize + UnicodeEncoding.CharSize) }; status = LsaLookupNames2(handle, 0, 1, new LSA_UNICODE_STRING[] { nameString }, out var domains, out var sids); if (status != 0) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(LsaNtStatusToWinError(status))); } try { var secId = new SecurityIdentity(); var lsaSid = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(sids, typeof(LSA_TRANSLATED_SID2)); var sidStruct = lsaSid.Sid; var sidString = IntPtr.Zero; // Get the SID string if (!ConvertSidToStringSid(sidStruct, out sidString)) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(Util.GetLastError())); } try { // Marshal and store the SID string secId.sid = Marshal.PtrToStringAnsi(sidString); } finally { if (sidString != IntPtr.Zero) { Util.LocalFree(sidString); } } // Check if the SID is a well known SID secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf <string>(wellKnownSids, secId.sid); uint nameLen = 0; uint domainLen = 0; // Get the lengths for the object and domain names LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out var nameUse); if (nameLen == 0) { throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError())); } var accountName = Marshal.AllocHGlobal((IntPtr)nameLen); var domainName = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero; try { // Get the object and domain names if (!LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse)) { throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError())); } // Marshal and store the object name secId.name = string.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName)); return(secId); } finally { if (accountName != IntPtr.Zero) { Marshal.FreeHGlobal(accountName); } if (domainName != IntPtr.Zero) { Marshal.FreeHGlobal(domainName); } } } finally { if (domains != IntPtr.Zero) { LsaFreeMemory(domains); } if (sids != IntPtr.Zero) { LsaFreeMemory(sids); } } } finally { if (handle != IntPtr.Zero) { LsaClose(handle); } } }
/// <summary> /// Creates a Security Identity from an object name (e.g. DOMAIN\AccountName) /// </summary> /// <param name="name">A security object name (i.e. a Computer, Account, or Group)</param> /// <returns>A populated Security Identity</returns> public static SecurityIdentity SecurityIdentityFromName(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name == "") { throw new ArgumentException("Argument 'name' cannot be the empty string.", "name"); } LSA_OBJECT_ATTRIBUTES attribs = new LSA_OBJECT_ATTRIBUTES(); attribs.Attributes = 0; attribs.ObjectName = IntPtr.Zero; attribs.RootDirectory = IntPtr.Zero; attribs.SecurityDescriptor = IntPtr.Zero; attribs.SecurityQualityOfService = IntPtr.Zero; attribs.Length = (uint)Marshal.SizeOf(attribs); IntPtr handle; int status = SecurityIdentity.LsaOpenPolicy(IntPtr.Zero, ref attribs, ACCESS_MASK.POLICY_LOOKUP_NAMES, out handle); if(status != 0) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(SecurityIdentity.LsaNtStatusToWinError(status))); } try { LSA_UNICODE_STRING nameString = new LSA_UNICODE_STRING(); nameString.Buffer = name; nameString.Length = (ushort)(name.Length * UnicodeEncoding.CharSize); nameString.MaxLength = (ushort)(name.Length * UnicodeEncoding.CharSize + UnicodeEncoding.CharSize); IntPtr domains; IntPtr sids; status = SecurityIdentity.LsaLookupNames2(handle, 0, 1, new LSA_UNICODE_STRING[] { nameString }, out domains, out sids); if(status != 0) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(SecurityIdentity.LsaNtStatusToWinError(status))); } try { SecurityIdentity secId = new SecurityIdentity(); LSA_TRANSLATED_SID2 lsaSid = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(sids, typeof(LSA_TRANSLATED_SID2)); IntPtr sidStruct = lsaSid.Sid; IntPtr sidString = IntPtr.Zero; // Get the SID string if (!SecurityIdentity.ConvertSidToStringSid(sidStruct, out sidString)) { throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(Util.GetLastError())); } try { // Marshal and store the SID string secId.sid = Marshal.PtrToStringAnsi(sidString); } finally { if (sidString != IntPtr.Zero) Util.LocalFree(sidString); } // Check if the SID is a well known SID secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf<string>(SecurityIdentity.wellKnownSids, secId.sid); SID_NAME_USE nameUse; uint nameLen = 0; uint domainLen = 0; // Get the lengths for the object and domain names SecurityIdentity.LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out nameUse); if (nameLen == 0) { throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError())); } IntPtr accountName = Marshal.AllocHGlobal((IntPtr)nameLen); IntPtr domainName = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero; try { // Get the object and domain names if (!SecurityIdentity.LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse)) { throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError())); } // Marshal and store the object name secId.name = String.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName)); return secId; } finally { if (accountName != IntPtr.Zero) Marshal.FreeHGlobal(accountName); if (domainName != IntPtr.Zero) Marshal.FreeHGlobal(domainName); } } finally { if (domains != IntPtr.Zero) SecurityIdentity.LsaFreeMemory(domains); if (sids != IntPtr.Zero) SecurityIdentity.LsaFreeMemory(sids); } } finally { if (handle != IntPtr.Zero) SecurityIdentity.LsaClose(handle); } }