/// <summary> /// Creates a Security Identity for a well known SID (such as LOCAL SYSTEM) /// </summary> /// <param name="sidType">The type of well known SID</param> /// <returns>A populated Security Identity</returns> public static SecurityIdentity SecurityIdentityFromWellKnownSid(WELL_KNOWN_SID_TYPE sidType) { if (sidType == WELL_KNOWN_SID_TYPE.None) { throw new ExternalException("Unable to Get Well Known SID"); } SecurityIdentity secId = new SecurityIdentity(); secId.wellKnownSidType = sidType; // Get the size required for the SID uint size = SecurityIdentity.GetSidLengthRequired(SecurityIdentity.SID_MAX_SUB_AUTHORITIES);; IntPtr sidStruct = Marshal.AllocHGlobal((IntPtr)size); try { // Get the SID struct from the well known SID type if (!SecurityIdentity.CreateWellKnownSid(sidType, IntPtr.Zero, sidStruct, ref size)) { throw new ExternalException("Unable to Get Well Known SID"); } IntPtr sidString = IntPtr.Zero; // Convert the SID structure to a SID string SecurityIdentity.ConvertSidToStringSid(sidStruct, out sidString); try { // Marshal and store the SID string secId.sid = Marshal.PtrToStringAnsi(sidString); } finally { if (sidString != IntPtr.Zero) { Util.LocalFree(sidString); } } uint nameLen = 0; uint domainLen = 0; SID_NAME_USE nameUse; // Get the lengths of 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"); } 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"); } // Marshal and store the object name secId.name = String.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName)); } finally { if (accountName != IntPtr.Zero) { Marshal.FreeHGlobal(accountName); } if (domainName != IntPtr.Zero) { Marshal.FreeHGlobal(domainName); } } } finally { if (sidStruct != IntPtr.Zero) { Marshal.FreeHGlobal(sidStruct); } } return(secId); }
/// <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); } } }