#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