2.5.3.4.2 ComputeACL
The ComputeACL subroutine determines the new ACL based on supplied Parent ACL, Creator ACL, and possibly the Token's DefaultDACL, depending on the supplied parameters and policy. This function is generally applicable to both the DACL and SACL portions of the security descriptor, although there are some specific behaviors that differ between the two types of DACL, so care has to be taken during implementation to honor the ComputeType parameter.
Parameters
ComputeType: Enumeration of COMPUTE_DACL and COMPUTE_SACL.
ParentACL: ACL from the parent security descriptor.
AutoInheritFlags: as specified in section 2.5.3.4.1. Note that it is possible to have the DACL_AUTO_INHERIT flag set when ComputeType is set to COMPUTE_SACL (or vice-versa).
ParentControl: Control flags from the parent security descriptor.
CreatorACL: ACL supplied in the security descriptor by the creator.
CreatorControl: Control flags supplied in the security descriptor by the creator.
IsContainerObject: TRUE if the object is a container; otherwise, FALSE.
ObjectTypes: Array of GUIDs for the object type being created.
GenericMapping: Mapping of generic permissions to resource manager-specific permissions supplied by the caller.
Owner: Owner to use in substituting the CreatorOwner SID.
Group: Group to use in substituting the CreatorGroup SID.
Token: Token for default values.
Returns
Computed ACL
ComputedControl
// The details of the algorithm to merge the parent ACL and the supplied ACL. // The Control flags computed are slightly different based on whether it is the // ACL in the DACL or the SACL field of the descriptor. // The caller specifies whether it is a DACL or a SACL using the parameter, // ComputeType. Set ComputedACL to NULL Set ComputedControl to NULL CALL ContainsInheritableACEs WITH ParentACL RETURNING ParentHasInheritableACEs IF ParentHasInheritableACEs = TRUE THEN // The Parent ACL has inheritable ACEs. The Parent ACL should be used if no Creator // ACL is supplied, or if the Creator ACL was supplied AND it is a default ACL based // on object type information IF(CreatorACL is not present) OR ((CreatorACL is present) AND (AutoInheritFlags contains DEFAULT_DESCRIPTOR_FOR_OBJECT)) THEN // Use only the inherited ACEs from the parent. First compute the ACL from the // parent ACL, then clean it up by resolving the generic mappings etc. CALL ComputeInheritedACLFromParent WITH ACL set to ParentACL, IsContainerObject set to IsContainerObject, ObjectTypes set to ObjectTypes RETURNING NextACL CALL PostProcessACL WITH ACL set to NextACL, CopyFilter set to CopyInheritedAces, Owner set to Owner, Group set to Group, GenericMapping set to GenericMapping RETURNING FinalACL Set ComputedACL to FinalACL RETURN ENDIF IF ((CreatorACL is present) AND (AutoInheritFlags does not contain DEFAULT_DESCRIPTOR_FOR_OBJECT)) THEN // Since a creator ACL is present, and we're not defaulting the // descriptor, determine which ACEs are inherited and compute the new ACL CALL PreProcessACLFromCreator WITH ACL set to CreatorACL RETURNING PreACL CALL ComputeInheritedACLFromCreator WITH ACL set to PreACL, IsContainerObject set to IsContainerObject, ObjectTypes set to ObjectTypes RETURNING TmpACL // Special handling for DACL types of ACLs IF (ComputeType = DACL_COMPUTE) THEN // DACL-specific operations IF (CreatorControl does not have DACL_PROTECTED flag set) AND (AutoInheritFlags contains DACL_AUTO_INHERIT) THEN // We're not working from a protected DACL, and we're supposed to // allow automatic inheritance. Compute the inherited ACEs from // Parent ACL this time, and append that to the ACL that we're building CALL ComputeInheritedACLFromParent WITH ACL set to ParentACL, IsContainerObject set to IsContainerObject, ObjectTypes set to ObjectTypes RETURNING InheritedParentACL Append InheritedParentACL.ACEs to TmpACL.ACE Set DACL_AUTO_INHERITED flag in ComputedControl ENDIF ENDIF // DACL-Specific behavior IF (ComputeType = SACL_COMPUTE) THEN // Similar to the above, perform SACL-specific operations IF (CreatorControl does not have SACL_PROTECTED flag set) AND (AutoInheritFlags contains SACL_AUTO_INHERIT flag) THEN // We're not working from a protected SACL, and we're supposed to // allow automatic inheritance. Compute the inherited ACEs from // Parent ACL this time, and append that to the ACL that we're building CALL ComputeInheritedACLFromParent WITH ACL set to ParentACL, IsContainerObject set to IsContainerObject, ObjectTypes set to ObjectTypes RETURNING InheritedParentACL Append InheritedParentACL.ACEs to TmpACL.ACE Set SACL_AUTO_INHERITED flag in ComputedControl ENDIF ENDIF // SACL-Specific behavior CALL PostProcessACL WITH ACL set to TmpACL, CopyFilter set to CopyInheritedAces, Owner set to Owner, Group set to Group, GenericMapping set to GenericMapping RETURNING ProcessedACL Set ComputedACL to ProcessedACL RETURN ENDIF // CreatorACL is present ELSE // ParentACL does not contain inheritable ACEs IF CreatorACL = NULL THEN // No ACL supplied for the object IF (ComputeType = DACL_COMPUTE) THEN Set TmpACL to Token.DefaultDACL ELSE // No default for SACL; left as NULL ENDIF ELSE // Explicit ACL was supplied for the object - either default or not. // In either case, use it for the object, since there are no inherited ACEs. CALL PreProcessACLFromCreator WITH CreatorACL RETURNING TmpACL ENDIF CALL PostProcessACL WITH ACL set to TmpACL, CopyFilter set to CopyAllAces, Owner set to Owner, Group set to Group, GenericMapping set to GenericMapping RETURNING ProcessedACL Set ComputedACL to ProcessedACL ENDIF // END ComputeACL