/// <summary> /// Gets an opened SafeLsaHandle on the system specified. Once finished /// with the handle, call the .Dispose() method to clean it up. /// </summary> /// <param name="systemName">The target system to get the open handle, set to null for localhost</param> /// <param name="accessMask">PSPrivilege.LsaPolicyAccessMask with the requests access rights</param> /// <returns>SafeLsaHandle of the opened policy</returns> public static SafeLsaHandle OpenPolicy(string systemName, LsaPolicyAccessMask accessMask) { SafeLsaHandle handle; Helpers.LSA_UNICODE_STRING[] systemNameStr = new Helpers.LSA_UNICODE_STRING[1]; systemNameStr[0] = systemName; Helpers.LSA_OBJECT_ATTRIBUTES objectAttr = new Helpers.LSA_OBJECT_ATTRIBUTES(); UInt32 res = Advapi32.LsaOpenPolicy(systemNameStr, objectAttr, accessMask, out handle); if (res != (UInt32)LsaStatusCodes.STATUS_SUCCESS) { throw new Win32Exception((int)Advapi32.LsaNtStatusToWinError(res), String.Format("LsaOpenPolicy({0}) failed", systemName)); } return(handle); }
/// <summary> /// Assigns one or more privileges/rights to an account. The opened /// SafeLsaHandle must have the LookupNames access right. It will also /// need the CreateAccount access right if the account referenced does /// not exist. /// </summary> /// <param name="policy">The SafeLsaHandle opened with OpenPolicy</param> /// <param name="account">The account to add the right(s) to</param> /// <param name="rights">Array list rights that match the privilege constants</param> public static void AddAccountRights(SafeHandle policy, IdentityReference account, string[] rights) { Helpers.LSA_UNICODE_STRING[] rightsStr = new Helpers.LSA_UNICODE_STRING[rights.Length]; for (int i = 0; i < rights.Length; i++) { rightsStr[i] = rights[i]; } SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier)); byte[] sidBytes = new byte[sid.BinaryLength]; sid.GetBinaryForm(sidBytes, 0); UInt32 res = Advapi32.LsaAddAccountRights(policy, sidBytes, rightsStr, (UInt32)rights.Length); if (res != (UInt32)LsaStatusCodes.STATUS_SUCCESS) { throw new Win32Exception((int)Advapi32.LsaNtStatusToWinError(res), "LsaAddAccountRights() failed"); } }
/// <summary> /// Gets the accounts that hold the specified privilege. The accounts /// returned hold the specified privilege directly and not as part of /// membership to a group. The opened SafeLsaHandle must have the /// LookupNames and ViewLocalInformation access rights. /// https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/privilege-constants /// https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/account-rights-constants /// </summary> /// <param name="policy">The SafeLsaHandle opened with OpenPolicy</param> /// <param name="right">The privilege to enumerate, this matches the privilege constant names</param> /// <returns>List<SecurityIdentifier> of accounts that hold the specified privilege</SecurityIdentifier></returns> public static List <SecurityIdentifier> EnumerateAccountsWithUserRight(SafeHandle policy, string right) { List <SecurityIdentifier> accounts = new List <SecurityIdentifier>(); Helpers.LSA_UNICODE_STRING[] rightsStr = new Helpers.LSA_UNICODE_STRING[1]; rightsStr[0] = right; UInt32 res = Advapi32.LsaEnumerateAccountsWithUserRight(policy, rightsStr, out var buffer, out var countReturned); switch (res) { case (UInt32)LsaStatusCodes.STATUS_SUCCESS: try { for (int i = 0; i < (int)countReturned; i++) { IntPtr infoBuffer = IntPtr.Add(buffer, i * Marshal.SizeOf(typeof(Helpers.LSA_ENUMERATION_INFORMATION))); Helpers.LSA_ENUMERATION_INFORMATION info = Marshal.PtrToStructure <Helpers.LSA_ENUMERATION_INFORMATION>(infoBuffer); accounts.Add(new SecurityIdentifier(info.Sid)); } } finally { Advapi32.LsaFreeMemory(buffer); } break; case (UInt32)LsaStatusCodes.STATUS_NO_MORE_ENTRIES: break; case (UInt32)LsaStatusCodes.STATUS_NO_SUCH_PRIVILEGE: throw new ArgumentException(String.Format("No such privilege/right {0}", right)); default: throw new Win32Exception((int)Advapi32.LsaNtStatusToWinError(res), String.Format("LsaEnumerateAccountsWithUserRight({0}) failed", right)); } return(accounts); }