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;
}
}