#if NET20 || NET35
// Sourced from
// https://github.com/dotnet/corefx/blob/a6f76f4f620cbe74821c6445af3f13e048361658/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurityT.cs.
// Only additions are preprocessor directives for conditional compilation and XML comments pulled from Microsoft documentation.
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the
// LICENSE file in the project root for more information.
/*============================================================
**
** Class: ObjectSecurity
**
** Purpose: Generic Managed ACL wrapper
**
** Date: February 7, 2007
**
===========================================================*/
using System.Runtime.InteropServices;
using System.Security.Principal;
using ResourceType = System.Security.AccessControl.ResourceType;
namespace System.Security.AccessControl
{
///
/// Represents a combination of a user's identity, an access mask, and an access control type (allow or deny). An AccessRule`1 object
/// also contains information about the how the rule is inherited by child objects and how that inheritance is propagated.
///
/// The access rights type for the access rule.
///
public class AccessRule : AccessRule where T : struct
{
// Constructors for creating access rules for file objects
/// Initializes a new instance of the class by using the specified values.
/// The identity to which the access rule applies.
/// The rights of the access rule.
/// The valid access control type.
public AccessRule(IdentityReference identity, T rights, AccessControlType type) :
this(identity, (int)(object)rights, false, InheritanceFlags.None, PropagationFlags.None, type)
{ }
/// Initializes a new instance of the class by using the specified values.
/// The identity to which the access rule applies.
/// The rights of the access rule.
/// The valid access control type.
public AccessRule(string identity, T rights, AccessControlType type) :
this(new NTAccount(identity), (int)(object)rights, false, InheritanceFlags.None, PropagationFlags.None, type)
{ }
// Constructor for creating access rules for folder objects
/// Initializes a new instance of the class by using the specified values.
/// The identity to which the access rule applies.
/// The rights of the access rule.
/// The inheritance properties of the access rule.
///
/// Whether inherited access rules are automatically propagated. The propagation flags are ignored if inheritanceFlags is set to None.
///
/// The valid access control type.
public AccessRule(IdentityReference identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
this(identity, (int)(object)rights, false, inheritanceFlags, propagationFlags, type)
{ }
/// Initializes a new instance of the class by using the specified values.
/// The identity to which the access rule applies.
/// The rights of the access rule.
/// The inheritance properties of the access rule.
///
/// Whether inherited access rules are automatically propagated. The propagation flags are ignored if inheritanceFlags is set to None.
///
/// The valid access control type.
public AccessRule(string identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
this(new NTAccount(identity), (int)(object)rights, false, inheritanceFlags, propagationFlags, type)
{ }
internal AccessRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, type)
{ }
/// Gets the rights of the current instance.
/// The rights, cast as type , of the current instance.
public T Rights => (T)(object)AccessMask;
}
/// Represents a combination of a user's identity and an access mask.
/// The type of the audit rule.
///
public class AuditRule : AuditRule where T : struct
{
/// Initializes a new instance of the class by using the specified values.
/// The identity to which this audit rule applies.
/// The rights of the audit rule.
/// The conditions for which the rule is audited.
public AuditRule(IdentityReference identity, T rights, AuditFlags flags) :
this(identity, rights, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
/// Initializes a new instance of the class by using the specified values.
/// The identity to which this audit rule applies.
/// The rights of the audit rule.
/// The inheritance properties of the audit rule.
/// Whether inherited audit rules are automatically propagated.
/// The conditions for which the rule is audited.
public AuditRule(IdentityReference identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
this(identity, (int)(object)rights, false, inheritanceFlags, propagationFlags, flags)
{
}
/// Initializes a new instance of the class by using the specified values.
/// The identity to which this audit rule applies.
/// The rights of the audit rule.
/// The conditions for which the rule is audited.
public AuditRule(string identity, T rights, AuditFlags flags) :
this(new NTAccount(identity), rights, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
/// Initializes a new instance of the class by using the specified values.
/// The identity to which this audit rule applies.
/// The rights of the audit rule.
/// The inheritance properties of the audit rule.
/// Whether inherited audit rules are automatically propagated.
/// The conditions for which the rule is audited.
public AuditRule(string identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
this(new NTAccount(identity), (int)(object)rights, false, inheritanceFlags, propagationFlags, flags)
{
}
internal AuditRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags)
{
}
/// Gets the rights of the audit rule.
/// The rights, cast as type , of the audit rule.
public T Rights => (T)(object)AccessMask;
}
///
/// Provides the ability to control access to objects without direct manipulation of Access Control Lists (ACLs); also grants the ability
/// to type-cast access rights.
///
/// The access rights for the object.
///
public abstract class ObjectSecurity : NativeObjectSecurity where T : struct
{
/// Initializes a new instance of the class.
///
/// if the new object is a container object.
///
///
/// The type of securable object with which the new object is associated.
///
protected ObjectSecurity(bool isContainer, ResourceType resourceType)
: base(isContainer, resourceType, null, null)
{ }
/// Initializes a new instance of the class.
///
/// if the new object is a container object.
///
///
/// The type of securable object with which the new object is associated.
///
///
/// The name of the securable object with which the new object is associated.
///
///
/// One of the enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// object.
///
protected ObjectSecurity(bool isContainer, ResourceType resourceType, string name, AccessControlSections includeSections)
: base(isContainer, resourceType, name, includeSections, null, null)
{ }
/// Initializes a new instance of the class.
///
/// if the new object is a container object.
///
///
/// The type of securable object with which the new object is associated.
///
///
/// The name of the securable object with which the new object is associated.
///
///
/// One of the enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// object.
///
/// A delegate implemented by integrators that provides custom exceptions.
/// An object that contains contextual information about the source or destination of the exception.
protected ObjectSecurity(bool isContainer, ResourceType resourceType, string name, AccessControlSections includeSections, ExceptionFromErrorCode exceptionFromErrorCode, object exceptionContext)
: base(isContainer, resourceType, name, includeSections, exceptionFromErrorCode, exceptionContext)
{ }
/// Initializes a new instance of the class.
///
/// if the new object is a container object.
///
///
/// The type of securable object with which the new object is associated.
///
/// A handle.
///
/// One of the enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// object.
///
protected ObjectSecurity(bool isContainer, ResourceType resourceType, SafeHandle safeHandle, AccessControlSections includeSections)
: base(isContainer, resourceType, safeHandle, includeSections, null, null)
{ }
/// Initializes a new instance of the class.
///
/// if the new object is a container object.
///
///
/// The type of securable object with which the new object is associated.
///
/// A handle.
///
/// One of the enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// object.
///
/// A delegate implemented by integrators that provides custom exceptions.
/// An object that contains contextual information about the source or destination of the exception.
protected ObjectSecurity(bool isContainer, ResourceType resourceType, SafeHandle safeHandle, AccessControlSections includeSections,
ExceptionFromErrorCode exceptionFromErrorCode, object exceptionContext)
: base(isContainer, resourceType, safeHandle, includeSections, exceptionFromErrorCode, exceptionContext)
{ }
///
/// Gets the of the securable object associated with this
/// object.
///
public override Type AccessRightType => typeof(T);
///
/// Gets the of the object associated with the access rules of this
/// object. The object must be an object
/// that can be cast as a object.
///
public override Type AccessRuleType => typeof(AccessRule);
///
/// Gets the object associated with the audit rules of this
/// object. The object must be an object
/// that can be cast as a object.
///
public override Type AuditRuleType => typeof(AuditRule);
///
/// Initializes a new instance of the class with the specified values.
///
/// The identity to which the access rule applies. It must be an object that can be cast as a .
///
/// The access mask of this rule. The access mask is a 32-bit collection of anonymous bits, the meaning of which is defined by the
/// individual integrators.
///
/// true if this rule is inherited from a parent container.
/// Specifies the inheritance properties of the access rule.
///
/// Specifies whether inherited access rules are automatically propagated. The propagation flags are ignored if
/// is set to .
///
/// Specifies the valid access control type.
/// The object that this method creates.
public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AccessControlType type) =>
new AccessRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, type);
// Override these if you need to do some custom bit remapping to hide any complexity from the user.
///
/// Adds the specified access rule to the Discretionary Access Control List (DACL) associated with this
/// object.
///
/// The rule to add.
public virtual void AddAccessRule(AccessRule rule) => base.AddAccessRule(rule);
///
/// Adds the specified audit rule to the System Access Control List (SACL) associated with this object.
///
/// The audit rule to add.
public virtual void AddAuditRule(AuditRule rule) => base.AddAuditRule(rule);
///
/// Initializes a new instance of the class with the specified values.
///
/// The identity to which the audit rule applies. It must be an object that can be cast as a .
///
/// The access mask of this rule. The access mask is a 32-bit collection of anonymous bits, the meaning of which is defined by the
/// individual integrators.
///
/// true if this rule is inherited from a parent container.
/// Specifies the inheritance properties of the audit rule.
///
/// Specifies whether inherited audit rules are automatically propagated. The propagation flags are ignored if
/// is set to .
///
/// Specifies the conditions for which the rule is audited.
/// The object that this method creates.
public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AuditFlags flags) =>
new AuditRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags);
///
/// Removes access rules that contain the same security identifier and access mask as the specified access rule from the
/// Discretionary Access Control List (DACL) associated with this object.
///
/// The rule to remove.
/// if the access rule was successfully removed; otherwise, .
public virtual bool RemoveAccessRule(AccessRule rule) => base.RemoveAccessRule(rule);
///
/// Removes all access rules that have the same security identifier as the specified access rule from the Discretionary Access
/// Control List (DACL) associated with this object.
///
/// The access rule to remove.
public virtual void RemoveAccessRuleAll(AccessRule rule) => base.RemoveAccessRuleAll(rule);
///
/// Removes all access rules that exactly match the specified access rule from the Discretionary Access Control List (DACL)
/// associated with this object
///
/// The access rule to remove.
public virtual void RemoveAccessRuleSpecific(AccessRule rule) => base.RemoveAccessRuleSpecific(rule);
///
/// Removes audit rules that contain the same security identifier and access mask as the specified audit rule from the System Access
/// Control List (SACL) associated with this object.
///
/// The audit rule to remove.
/// if the object was removed; otherwise, .
public virtual bool RemoveAuditRule(AuditRule rule) => base.RemoveAuditRule(rule);
///
/// Removes all audit rules that have the same security identifier as the specified audit rule from the System Access Control List
/// (SACL) associated with this object.
///
/// The audit rule to remove.
public virtual void RemoveAuditRuleAll(AuditRule rule) => base.RemoveAuditRuleAll(rule);
///
/// Removes all audit rules that exactly match the specified audit rule from the System Access Control List (SACL) associated with
/// this object.
///
/// The audit rule to remove.
public virtual void RemoveAuditRuleSpecific(AuditRule rule) => base.RemoveAuditRuleSpecific(rule);
///
/// Removes all access rules in the Discretionary Access Control List (DACL) associated with this
/// object and then adds the specified access rule.
///
/// The access rule to reset.
public virtual void ResetAccessRule(AccessRule rule) => base.ResetAccessRule(rule);
///
/// Removes all access rules that contain the same security identifier and qualifier as the specified access rule in the
/// Discretionary Access Control List (DACL) associated with this object and then adds the specified
/// access rule.
///
/// The access rule to set.
public virtual void SetAccessRule(AccessRule rule) => base.SetAccessRule(rule);
///
/// Removes all audit rules that contain the same security identifier and qualifier as the specified audit rule in the System Access
/// Control List (SACL) associated with this object and then adds the specified audit rule.
///
/// The audit rule to set.
public virtual void SetAuditRule(AuditRule rule) => base.SetAuditRule(rule);
// Use this in your own Persist after you have demanded any appropriate CAS permissions. Note that you will want your version to be
// internal and use a specialized Safe Handle.
///
/// Saves the security descriptor associated with this object to permanent storage, using the
/// specified handle.
///
/// The handle of the securable object with which this object is associated.
protected internal void Persist(SafeHandle handle)
{
WriteLock();
try
{
var persistRules = GetAccessControlSectionsFromChanges();
Persist(handle, persistRules);
OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
}
finally
{
WriteUnlock();
}
}
// Use this in your own Persist after you have demanded any appropriate CAS permissions. Note that you will want your version to be internal.
///
/// Saves the security descriptor associated with this object to permanent storage, using the
/// specified name.
///
/// The name of the securable object with which this object is associated.
protected internal void Persist(string name)
{
WriteLock();
try
{
var persistRules = GetAccessControlSectionsFromChanges();
Persist(name, persistRules);
OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
}
finally
{
WriteUnlock();
}
}
private AccessControlSections GetAccessControlSectionsFromChanges()
{
var persistRules = AccessControlSections.None;
if (AccessRulesModified)
{
persistRules = AccessControlSections.Access;
}
if (AuditRulesModified)
{
persistRules |= AccessControlSections.Audit;
}
if (OwnerModified)
{
persistRules |= AccessControlSections.Owner;
}
if (GroupModified)
{
persistRules |= AccessControlSections.Group;
}
return persistRules;
}
}
}
#endif