using System; using System.Security.AccessControl; using System.Security.Principal; using Vanara.Extensions; using Vanara.InteropServices; using Vanara.PInvoke; using static Vanara.PInvoke.AdvApi32; namespace Vanara.Security.AccessControl { /// Helper methods for working with Access Control structures. public static class AccessControlHelper { /// Gets the number of ACEs held by an ACL. /// The pointer to the ACL structure to query. /// The ace count. [Obsolete("This function will be retired in a future release. Use the AceCount extension method from Vanara.PInvoke.WinNTExtensions in the Vanara.PInvoke.Security package.")] public static uint GetAceCount(this PACL pAcl) => pAcl.AceCount(); /// Gets the size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. /// The pointer to the ACL structure to query. /// The size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. [Obsolete("This function will be retired in a future release. Use the Length extension method from Vanara.PInvoke.WinNTExtensions in the Vanara.PInvoke.Security package.")] public static uint GetAclSize(PACL pAcl) => pAcl.Length(); /// Gets the access rights for the identity on the provided security descriptor. /// The security descriptor to check for access rights. /// The SID of the identity for which to get the rights. /// The access rights bitmask. public static uint GetEffectiveRights(this PSECURITY_DESCRIPTOR pSD, PSID pSid) { BuildTrusteeWithSid(out var t, pSid); GetSecurityDescriptorDacl(pSD, out _, out var pDacl, out _); GetEffectiveRightsFromAcl(pDacl, t, out var access); return access; } /// Gets the access rights for the identity on the provided security descriptor. /// The security descriptor to check for access rights. /// The SID of the identity for which to get the rights. /// The access rights bitmask. public static uint GetEffectiveRights(this RawSecurityDescriptor sd, SecurityIdentifier sid) { BuildTrusteeWithSid(out var t, GetPSID(sid)); using var pDacl = new PinnedAcl(sd.DiscretionaryAcl); GetEffectiveRightsFromAcl(pDacl.PACL, t, out var access); return access; } /// Gets a pointer to a SID from a . /// The instance. /// The PSID value. public static PSID GetPSID(this SecurityIdentifier sid) { using var ps = new PinnedSid(sid); return ps.PSID; } /// Gets the equivalent of an ACL. /// The pointer to an ACL structure. /// The instance. public static RawAcl RawAclFromPtr(PACL pAcl) => new RawAcl(((IntPtr)pAcl).ToArray((int)pAcl.Length()), 0); /// Converts a security descriptor to its SDDL string format. /// The security descriptor. /// The elements of the security descriptor to return. /// The SDDL string representation of the security descriptor. public static string ToSddl(this PSECURITY_DESCRIPTOR pSD, SECURITY_INFORMATION si) => ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, si); /// Converts a security descriptor to its SDDL string format. /// The security descriptor. /// The elements of the security descriptor to return. /// The SDDL string representation of the security descriptor. public static string ToSddl(this SafePSECURITY_DESCRIPTOR pSD, SECURITY_INFORMATION si) => ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, si); } /// Enables access to managed as unmanaged . public class PinnedAcl : PinnedObject { private readonly byte[] bytes; /// Initializes a new instance of the class. /// The instance. public PinnedAcl(RawAcl acl) { bytes = new byte[acl.BinaryLength]; acl.GetBinaryForm(bytes, 0); SetObject(bytes); } /// Gets the PACL value. public PACL PACL => (IntPtr)this; } /// Enables access to managed as unmanaged . public class PinnedSecurityDescriptor : PinnedObject { private readonly byte[] bytes; /// Initializes a new instance of the class. /// The object security. public PinnedSecurityDescriptor(ObjectSecurity sd) { bytes = sd.GetSecurityDescriptorBinaryForm(); SetObject(bytes); } /// Gets the PSECURITY_DESCRIPTOR value. public PSECURITY_DESCRIPTOR PSECURITY_DESCRIPTOR => (IntPtr)this; } /// Enables access to managed as unmanaged . /// public class PinnedSid : PinnedObject { private readonly byte[] bytes; /// Initializes a new instance of the class. /// The sid. public PinnedSid(SecurityIdentifier sid) { bytes = new byte[sid.BinaryLength]; sid.GetBinaryForm(bytes, 0); SetObject(bytes); } /// Gets the PSID value. public PSID PSID => (IntPtr)this; } }