How Security Descriptors and Access Control Lists Work

Applies To: Windows Server 2003, Windows Server 2003 R2, Windows Server 2003 with SP1, Windows Server 2003 with SP2

In this section

  • Security Descriptor Architecture

  • ACL Architecture

  • Inheritance

  • Related Information

All objects in Active Directory, and all securable objects on a local computer or on the network, have security descriptors to help control access to the objects. Security descriptors include information about who owns an object, who can access it and in what way, and what types of access are audited. Security descriptors, in turn, contain the access control list (ACL) of an object, which includes all of the security permissions that apply to that object. An object’s security descriptor can contain two types of ACLs:

  • A discretionary access control list (DACL) that identifies the users and groups who are allowed or denied access

  • A system access control list (SACL) that controls how access is audited

The access control model that is used by the Windows Server 2003 operating system is administered at the object level by setting different levels of access, or permissions, to objects. If permissions are configured for an object, its security descriptor contains a DACL with security identifiers (SIDs) for the users and groups that are allowed or denied access. If auditing is configured for the object, its security descriptor also contains a SACL that controls how the security subsystem audits attempts to access the object.

You can use this access control model to individually secure objects such as files and folders, Active Directory objects, registry keys, and printers, as well as devices, ports, services, processes, and threads. Because of this individual control, you can adjust the security of objects to meet the needs of your organization, delegate authority over objects or attributes, and create custom objects or attributes that require unique security protections to be defined.

The following sections define the basic elements of security descriptors and ACLs, look at where access control information comes from, discuss how access control permissions are inherited, and describe how ACLs work in an optimal environment. An optimal environment for ACLs is defined as follows:

  • Security on objects is designed using the theory of least privilege. Users are assigned the least level of access that they need to perform their job functions.

  • Groups, rather than individual user accounts, are used to grant or deny access to resources.

  • A consistent model is used for assigning permissions.

  • Permissions on Active Directory objects are not assigned to domain local groups.

Securable Objects

A securable object is an object that can have a security descriptor. All named Windows objects are securable. Some unnamed objects, such as process and thread objects, can also have security descriptors. Each type of securable object defines its own set of specific access rights and its own mapping of generic access rights.

The following are the common securable objects:

  • Files or folders on an NTFS file system

  • Active Directory objects

  • Registry keys

  • Network shares

  • Local or remote printers

  • Windows services

  • Named pipes

  • Anonymous pipes

  • Processes

  • Threads

  • File-mapping objects

  • Access tokens

  • Window-management objects (window stations and desktops)

  • Interprocess synchronization objects (events, mutexes, semaphores, and waitable timers)

  • Job objects

  • Distributed Component Object Model (DCOM) objects

Security Descriptor Architecture

Access control information that is associated with an object is contained in the object’s security descriptor. When a user tries to access the object, the operating system examines the object’s security descriptor to determine whether the access will be granted. Before allowing a subject to proceed with the action it intends to carry out on an object, the operating system’s security subsystem performs an access check to determine whether the subject is authorized to perform the action on that object.

The information that is included in a security descriptor depends on the type of object and how it was created. In general, security descriptors can include information about the following:

  • Which user owns the object

  • Which users and groups are allowed or denied access

  • Which users and groups’ access should be audited

  • How objects in a container inherit access control information from the container

Parts of a Security Descriptor

A security descriptor is a binary data structure of variable length. The data structure has the following parts:

The header contains a revision number and a set of control flags that describe characteristics of the security descriptor, such as the memory layout, which elements are present, and how particular elements were added or modified.

Owner

The Owner field contains the SID for the object’s owner. The owner of an object can modify permissions and give other users the right to take ownership.

Primary Group

The Primary Group field contains the SID for the owner’s primary group. This information is used only by the POSIX subsystem, and it is ignored by the rest of Windows Server 2003.

DACL

The DACL is a list of zero or more access control entries (ACEs). Each ACE in the list has a header that specifies whether the ACE allows or denies access, a SID that specifies a particular user or group, and an access mask that lists the operations that are allowed or denied. The content of the DACL is controlled by the object’s owner. The owner can share control with other users by granting them Change Permissions (WRITE_DAC) permission. Note that it is possible for a security descriptor to have no DACL (also known as a NULL DACL); this gives unconditional access to everyone. A security descriptor with an empty DACL gives no access to anyone. For more information, see “No DACL vs. Empty DACL” later in this section.

SACL

The SACL is similar to the DACL except that the SACL is used to audit rather than control access to an object. When an audited action occurs, the operating system records the event in the security log. Each ACE in a SACL has a header that indicates whether auditing is triggered by success or failure or both, a SID that specifies a particular user or security group to monitor, and an access mask that lists the operations to audit. The content of the SACL is controlled by security administrators for the local system. Security administrators are users who have been assigned the Manage Auditing and Security Log (SeSecurityPrivilege) privilege. By default, this privilege is assigned to the built-in Administrators group.

Layout in Memory

A security descriptor’s layout in memory can be either self-relative or absolute. Which of the two formats a particular security descriptor uses is indicated by a control flag in the security descriptor’s header.

A self-relative security descriptor is stored in a contiguous block of memory, and the address for each part of the descriptor is expressed as an offset from the beginning of the memory block. To locate any part of the security descriptor, a process must be given only the address of the area in memory where the security descriptor begins. The process determines where the part in question begins by adding the memory offset for the part to the memory address for the security descriptor. (Hence, the name “self-relative”; the address for a part is relative to the address for the whole.)

The following figure illustrates the layout of a security descriptor in self-relative format.

Security Descriptor in Self-Relative Format

Security Descriptor in Self-Relative Format

Self-relative layout is used for security descriptors on objects that must be stored on disk, transmitted by a communications protocol, or copied in memory.

A security descriptor in absolute format contains pointers to its information, not the information itself. This format enables each component of the security descriptor to be allocated separately and assembled on the fly. It is used for objects that do not require persistent storage, such as objects that exist only during the lifetime of a single process. The following figure illustrates the layout of a security descriptor in absolute format.

Security Descriptor in Absolute Format

Security Descriptor in Absolute Format

Security Descriptor Control Flags

A security descriptor’s header contains a set of control flags that qualify the meaning of the security descriptor or its components. In Windows 2000 and later operating systems, control flags play an important role in the automatic propagation of inheritable security information from parent (container) objects to child (contained) objects.

Security descriptor control flags are stored in a bit field, and they are turned on or off by setting individual bits. The following table lists the security descriptor control flags and their meaning.

Security Descriptor Control Flags

Flag Meaning

SE_DACL_AUTO_INHERITED

Windows 2000 and later: Inheritable ACEs in this object’s DACL have been propagated to existing child objects.

This flag is not set in security descriptors for Windows NT, which does not support automatic propagation of inheritable ACEs.

SE_DACL_DEFAULTED

The DACL was provided by a default mechanism.

This flag can affect how the operating system treats the DACL with respect to inheritance. The operating system ignores this flag if SE_DACL_PRESENT is not set.

SE_DACL_PRESENT

The security descriptor has a DACL.

Windows 2000 and later: If this flag is not set (that is, if the security descriptor has no DACL), SE_DACL_PROTECTED must be set. Otherwise, the operating system considers the security descriptor to be invalid.

SE_DACL_PROTECTED

Windows 2000 and later: The security descriptor’s DACL cannot be modified by inheritable ACEs.

If this flag is not set, the security descriptor inherits information from the security descriptor of the parent object.

SE_GROUP_DEFAULTED

The primary group SID was provided by a default mechanism.

SE_OWNER_DEFAULTED

The owner SID was provided by a default mechanism.

SE_SACL_AUTO_INHERITED

Windows 2000 and later: Inheritable ACEs in this object’s SACL have been propagated to existing child objects.

This flag is not set in security descriptors for Windows NT, which does not support automatic propagation of inheritable ACEs.

SE_SACL_DEFAULTED

The SACL was provided by a default mechanism.

This flag can affect how the operating system treats the SACL with respect to inheritance. The operating system ignores this flag if SE_SACL_PRESENT is not set.

SE_SACL_PRESENT

The security descriptor has a SACL.

SE_SACL_PROTECTED

Windows 2000 and later: The security descriptor’s SACL cannot be modified by inheritable ACEs.

SE_SELF_RELATIVE

The security descriptor is in self-relative format with all information in a contiguous block of memory. If this flag is not set, the security descriptor is in absolute format.

Where Access Control Information Comes From

Access control information is first written to an object’s security descriptor when the object is created. This information can later be modified. In both cases, the information that goes into a security descriptor can come from one of the following sources:

  • The subject

  • The Object Manager

  • The parent object

When a subject creates a new object, it can assign a security descriptor to the object. If the subject does not assign a security descriptor, the operating system uses access control information inherited from the parent object to create one. If no information is available to inherit, the operating system uses default access control information provided by the object manager for the particular type of object that the subject wants to create.

After an object is created, information in its security descriptor can be changed by the object’s owner or by another user who has the owner’s permission. Changes can also come from the parent object when that object’s owner modifies its security descriptor. Every time the security descriptor on a container object is changed, the object manager propagates any changes that are marked as inheritable to all objects in the container.

Subjects

A subject is a thread executing in the security context provided by an access token. A subject’s access token contains information that can be used in security descriptors for new objects that the subject creates and existing objects that the subject modifies. This information includes the following fields.

Default Owner

This field of an access token contains the SID that identifies the security principal that, by default, becomes the owner of objects that the subject either creates or takes ownership of. Typically, the default owner is the individual user that is represented by the access token. When the SID in the Default Owner field of the subject’s access token is copied to the Owner field of an object’s security descriptor, SE_OWNER_DEFAULTED is set in the security descriptor’s control flags.

Note

  • When users who are members of the local Administrators group access objects on Windows Server 2003, the Default Owner field in the user’s access token contains the SID for the Administrators group, not the SID for the user. A similar rule applies to users who access objects in Active Directory. If the user is a member of the Domain Admins group, the Default Owner field in the user’s access token contains the SID for the Domain Admins group. In both cases, objects that the user creates or takes ownership of are owned by the group, not by the individual user.

  • On Windows XP Professional, the Default Owner field always contains the user’s SID. This is a change from Windows 2000 and earlier operating systems, in which the rules were the same for both Windows 2000 Server and Windows XP Professional.

Primary Group

This field of an access token contains the SID for the user’s primary group. When the SID in the Primary Group field of the subject’s access token is copied to the Primary Group field of an object’s security descriptor, SE_GROUP_DEFAULTED is set in the security descriptor’s control flags.

Default DACL

This field of an access token might contain a DACL, or it might be empty. If the subject’s access token contains a DACL, it can be used as the DACL in a new object’s security descriptor. If the Default DACL field is used in the security descriptor for a new object, SE_DACL_DEFAULTED is set in the security descriptor’s control flags.

Object Managers

The object manager can provide default security information for new objects. In Windows Server 2003, the only object manager that supplies default permissions for new objects is Active Directory.

For more information, see “DACLs for Newly Created Active Directory Objects” later in this section.

Parent Objects

Some objects can contain other objects. For example, an NTFS folder object can contain file objects and other folder objects. A registry key object can contain subkey objects. An Active Directory organizational unit (OU) object can contain other OU objects as well as user objects, group objects, and computer objects. Terminal objects contain Window Station objects that contain Desktop objects that contain Window objects. Any object that is contained by another object is called a “child” object. A “child” object’s container is its “parent” object.

Child objects can inherit access control information from their parent object. For example, suppose that the administrator for a server creates a file share with one folder, Public$. The administrator creates this folder so that users can have a place to store information that they want to share. With this purpose in mind, the administrator sets the permissions, which are implemented as ACEs, as shown in the following figure.

Permission Entries on Public Folder (Owner: Administrators)

Permission Entries on Public Folder

None of the permissions that are listed in this figure were acquired through inheritance. This is because the administrator cleared the check box for Inherit from parent the permission entries that apply to child objects. Clearing the check box sets the security descriptor control flag SE_DACL_PROTECTED, which protects a child object’s DACL by blocking inheritance from the parent object’s DACL.

Permissions that are acquired through inheritance are called “inherited” permissions. Permissions that are not inherited, but are instead defined directly on an object, are called “explicit” permissions*.* One way to tell an explicit permission from an inherited permission is to select an entry in the Permission Entries list and read the text that is displayed after the list. In this figure, the second entry is selected, and the text after the list says This permission is defined directly on this object. In other words, the permission is explicit, not inherited.

The text in this figure also says This permission is inherited by child objects. Permissions on a parent object that apply to child objects are called “inheritable” permissions. To see which of the permissions that are set on a parent object are inheritable, examine the Apply to column of Permission Entries. If Apply to says This object only (or, for folder objects, This folder only), the permission is not inherited by child objects. Of the four permissions that are shown in this figure, three are inheritable and one is not.

To see how inheritable permissions become inherited permissions, suppose that Alice creates a subfolder in Public$. Alice is an engineer, so she names her folder Engineering Data. Because this new object is a child of Public$, its DACL inherits permissions from the DACL on Public$. The new object’s permissions are shown in the following figure.

Permission Entries on Engineering Data Folder (Owner: Alice)

Permission Entries on Engineering Data Folder

Note that Alice has not cleared the check box for Inherit from parent the permission entries that apply to child objects, so inheritable permissions in the parent object’s DACL are inherited by the child object’s DACL. Inherited permissions are indicated in Permission Entries by a disabled (unavailable) symbol at the beginning of each entry. The permission is still effective; all that is disabled is the ability to modify the entry. Because inherited permissions are defined on a parent object, they can be changed only by modifying the parent object’s DACL.

Even though inherited permissions cannot be changed, the owner of a child object can add explicit permissions to the object’s DACL. For example, suppose Alice decides that inherited permissions that are given to Creator Owner are too restrictive because they allow only the user who creates a file to make changes to the file. She wants all members of the Engineering group to be able to edit and add information to the Engineering Data folder, so she explicitly gives this group Modify permission for all objects in the folder. Alice also feels that people in her company’s marketing department will misuse information in Engineering Data, so she decides to explicitly deny the Marketing group full control of (and therefore all access to) the folder, subfolders, and files. The results of Alice’s changes to the access control settings are shown in the following figure.

Modified Permission Entries on Engineering Data Folder

Modified Permission Entries on Engineering Folder

The list of permission entries in this figure now includes two explicit permissions, both with enabled symbols indicating that the entries can be edited. Note that explicit permissions appear at the top of the list. Permissions are listed in the order in which they will be processed during an access check. Because explicit permissions are listed before inherited permissions, they are processed first. The assumption is that the owner of a child object adds explicit permissions in order to qualify inherited permissions. For example, in this figure, an inherited permission allows Everyone to read the folder, subfolders, and files. Alice has added an explicit permission that denies all access to a subset of the group Everyone — the Marketing group. The explicit deny entry is placed before any inherited entries; therefore, it is processed before any inherited entries. For more information about ACE order, see “Order of ACEs in a DACL” later in this section.

Alice applied both of her explicit permissions to This folder, subfolders, and files because she wants child objects in her folder to inherit the new permissions. If the Engineering Data folder were on a server running Windows NT, the new explicit permissions would affect only new objects created in her folder, because the access control model used in Windows NT supports inheritance only at the time that an object is created. To change permissions on existing objects in a Windows NT system, Alice would need to take the additional step of setting explicit permissions on each existing subfolder and file. What is new in Windows 2000 and later is inheritance after the time of creation. New or changed inheritable permissions in the DACL on a parent object are automatically propagated to existing child objects every time the DACL on the parent object changes. If Alice’s folder were on a system running Windows 2000 or later, the entry denying Marketing permission to access the Engineering Data folder would be propagated to subfolders as soon as Alice clicked Apply in the Advanced Security Settings dialog box.

Automatic propagation of inheritable permissions is a powerful capability because you can use it to change permissions on an entire tree of objects by changing permissions on the top-level object in the tree. For example, suppose a member of the Administrators group realizes that information in the Public$ folder and its subfolders is proprietary, not public. In that case, it is inappropriate to allow Everyone access because that group includes the Guest account. The administrator decides that it is more prudent to allow access only to Authenticated Users, a group that includes only users whose identities can be authenticated by the server or by a trusted security authority. To tighten security on the folder, the administrator simply needs to change Everyone to Authenticated Users for two entries in the permissions list. The change is shown in the following figure.

Modified Permission Entries on Public Folder

Modified Permission Entries on Public Folder

When the administrator applies the changes to the access control settings on the parent object, all inheritable permissions in the parent object’s DACL are propagated to DACLs on subfolders and files. The impact on the Engineering Data folder is shown in the following figure.

Permission Entries Propagated to Engineering Data Folder

Permission Entries Propagated to Engineering Data

Note that propagation of inheritable permissions from the Public$ folder to the Engineering Data folder does not change explicit permissions in the child’s DACL. Only inherited permissions are replaced when inheritable permissions are propagated to existing child objects. However, if explicit permissions are also inheritable, the propagation process reapplies them as it moves down the tree. For example, both explicit permissions that Alice added to the DACL on her folder are inheritable by child objects in the folder. As the propagation process moves downward from Alice’s folder, it picks up these additional inheritable permissions and applies them to the DACL of any child object that it finds.

The owner of a parent object can choose to overwrite explicit permissions that are defined on child objects. This is done by selecting the Replace permission entries on all child objects with entries shown here that apply to child objects check box in the Advanced Security Settings dialog box. When the owner of a parent object chooses this option, the propagation process removes explicit permissions from the DACLs on all child objects. It also sets the option Inherit from parent the permission entries that apply to child objects on all child objects, removing any protection from inheritance that might have been set by the objects’ owners.

ACL Architecture

An ACL is an ordered list of ACEs that define the protections that apply to an object and its properties. Each ACE identifies a security principal and specifies a set of access rights that are allowed, denied, or audited for that security principal.

An object’s security descriptor can contain two ACLs:

  • A DACL that identifies the users and groups that are allowed or denied access

  • A SACL that controls how access is audited

The following figure shows the data structure for an ACL.

Data Structure of an ACL

Data Structure of an ACL

Parts of an ACL

The individual parts of an ACL are as follows.

ACL size

The number of bytes of memory allocated for the ACL. The size of an ACL varies with the number and size of its ACEs. The maximum size of an ACL is 64K, or approximately 1,820 ACEs, depending on the size of the ACEs. However, for performance reasons, the maximum size is not practical.

ACL revision

The revision number for the ACL’s data structure. The structure of an ACL is the same for all revisions, but the structure of ACEs in the ACL can vary.

ACE count

The number of ACEs in the ACL. A value of zero means the ACL has no ACEs — it is empty; therefore, access-checking can stop. Note that an empty DACL differs from a NULL DACL. An empty DACL gives no access to anyone, but a NULL DACL gives unconditional access to everyone, and should therefore be avoided. For more information, see “No DACL vs. Empty DACL” later in this section.

ACEs

An ordered list containing zero or more ACEs. During an access check, ACEs are processed in the order in which they are listed.

How the System Uses ACLs

When a thread tries to access a securable object, the system either grants or denies access. If the object does not have a DACL, the system grants access; otherwise, the system looks for ACEs in the object’s DACL that apply to the thread. Each ACE in the object’s DACL specifies the access rights that are allowed or denied for a security principal or logon session.

The system compares the trustee in each ACE to the trustees that are identified in the thread’s access token. An access token contains SIDs that identify the user and the group accounts to which the user belongs. A token also contains a logon SID that identifies the current logon session.

The system examines each ACE in sequence until one of the following events occurs:

  • An access-denied ACE explicitly denies any of the requested access rights to one of the trustees listed in the thread’s access token.

  • One or more access-allowed ACEs for trustees listed in the thread’s access token explicitly grant all the requested access rights.

  • All ACEs have been checked and there is still at least one requested access right that has not been explicitly allowed, in which case, access is implicitly denied.

Because the system stops checking ACEs when the requested access is explicitly granted or denied, the order of ACEs in a DACL is important.

Access Control Entries

All ACEs include the following access control information:

  • A SID that identifies a user or group

  • An access mask that specifies access rights

  • A set of bit flags that determine whether child objects can inherit the ACE

  • A flag that indicates the type of ACE

ACE Types

Windows 2000 and Windows Server 2003 support six types of ACEs. Three are generic ACE types that can be present in ACLs that are attached to all securable objects. The three remaining ACE types are object specific and can occur only in ACLs for Active Directory objects. The following tables list the generic and object-specific ACE types.

Generic ACE Types

Type Description

Access-denied

Used in a DACL to deny access

Access-allowed

Used in a DACL to allow access

System-audit

Used in a SACL to log attempts to access

Object-Specific ACE Types

Type Description

Access-denied, object-specific

Used in a DACL to deny access to a property or property set or to limit inheritance to a specified type of child object

Access-allowed, object-specific

Used in a DACL to allow access to a property or property set or to limit inheritance to a specified type of child object

System-audit, object-specific

Used in a SACL to log attempts to access a property or property set or to limit inheritance to a specified type of child object

Generic and object-specific ACEs are fundamentally alike. What sets them apart is the degree of control they offer over inheritance and object access.

Generic ACEs offer limited control over the kinds of child objects that can inherit them. Essentially, they can distinguish only between containers and noncontainers. For example, the DACL on a Folder object in NTFS can include a generic ACE that allows a group of users to list the folder’s contents. This is an operation that can be performed only on container objects; therefore, the ACE that allows the operation can be flagged as a CONTAINER_INHERIT_ACE. Only container objects in the folder (that is, only other Folder objects) inherit the ACE. Noncontainer objects (that is, File objects) do not inherit the ACE of the parent object.

Object-specific ACEs offer a greater degree of control over the types of child objects that can inherit them. For example, an OU object’s ACL can have an object-specific ACE that is marked for inheritance only by User objects. Other types of objects, such as Computer objects, will not inherit the ACE. This capability is why object-specific ACEs are called object specific. Their inheritance can be limited to specific types of child objects.

There are similar differences in how the two categories of ACE types control access to objects. Generic ACEs apply to an entire object. If a generic ACE gives a particular user Read access, the user can read all the information that is associated with the object — both data and properties. This is not a serious limitation for most object types. File objects, for example, have few properties, which are all used for describing characteristics of the object rather than for storing information. Most of the information in a File object is stored as object data; therefore, there is little need for separate controls on a file’s properties.

Object-specific ACEs can apply to any individual property of an object or to a set of properties. These ACE types are used only in ACLs for Active Directory objects, which, unlike other object types, store most of their information in properties. It is often desirable to place independent controls on each property of an Active Directory object, and object-specific ACEs make that possible. For example, when you define permissions for a User object, you can use one object-specific ACE to allow Principal Self (that is, the user) Write access to the Phone-Home-Primary (homePhone) property, and you can use other object-specific ACEs to deny Principal Self access to the Logon-Hours (logonHours) property and other properties that set restrictions on the user account.

Structure of a Generic ACE

All three generic ACE types — access denied, access allowed, and system audit — have the same data structure, which is illustrated in the following figure.

Structure of a Generic ACE

Structure of a Generic ACE

The individual parts of an ACE are as follows.

ACE Size

The number of bytes of memory that are allocated for the ACE.

ACEType

Specifies whether the ACE allows, denies, or monitors access.

Inheritance and Audit Flags

A set of bit flags that control inheritance and auditing. For information about inheritance flags, see “Inheritance” later in this section. The following table describes audit flags.

Audit Flags

Flag Meaning

FAILED_ACCESS_ACE_FLAG

Meaningful only in system-audit and system-audit object ACEs. The access mask specifies operations that are logged when they fail.

SUCCESSFUL_ACCESS_ACE_FLAG

Meaningful only in system-audit and system-audit object ACEs. The access mask specifies operations that are logged when they succeed.

Access Mask

A 32-bit value whose bits correspond to access rights for the object. Bits can be set either on or off, but the setting’s meaning depends on the ACE type. For example, if the bit that corresponds to the right to read permissions is turned on, and the ACE type is Deny, the ACE denies the right to read the object’s permissions. If the same bit is set on but the ACE type is Allow, the ACE grants the right to read the object’s permissions.

SID

Identifies a user or group whose access is controlled or monitored by this ACE.

Structure of an Object-Specific ACE

The following figure shows the structure of an object-specific ACE.

Structure of an Object-Specific ACE

Structure of an Object-Specific ACE

The fields for ACE Size, ACEType, Inheritance and Audit Flags, Access Mask, and SID are identical to like elements in the data structure for a generic ACE. The key differences between a generic and an object-specific ACE are as described in the following sections.

Object flags

Object flags indicate whether Object Type or Inherited Object Type is present. The following table shows the three possible object flags.

Object Flags

Flag Meaning

0 (no flags)

Neither Object Type nor Inherited Object Type is present. In this case, the ACE applies to the entire object. It is, in effect, a generic ACE.

ACE_OBJECT_TYPE_PRESENT

ACE applies to a property, property set, or extended right, or it controls the ability to create a particular type of child object.

ACE_INHERITED_OBJECT_TYPE_PRESENT

ACE can be inherited only by a particular type of child object.

Object Type

Object Type contains a globally unique identifier (GUID) that identifies one of the following:

  • schemaIDGUID. When the schema ID GUID is specified in the ACE, the ACE controls who can create a child object from the identified class schema within a container. The SID portion of the ACE identifies a user or group who can create this type of child object. The ACE’s access mask contains the object-specific access right ADS_RIGHT_DS_CREATE_CHILD.

  • propertyGUID. When a property GUID is specified in the ACE, the ACE controls the ability to read or write a particular property or property set. The SID portion of the ACE identifies a user or group who can read or write the property or property set. The ACE’s access mask contains either ADS_RIGHT_DS_READ_PROP or ADS_RIGHT_DS_WRITE_PROP.

  • rightsGUID. When an extended rights GUID is specified in the ACE, the ACE controls the right to perform the operation that is associated with the extended right. The SID portion of the ACE identifies a user or group who has the extended right. The ACE’s access mask contains ADS_RIGHT_DS_CONTROL_ACCESS. For a list of Extended rights GUIDs, see the Extended Rights Reference.

Inherited Object Type

Inherited Object Type contains a GUID that identifies the type of child object that can inherit the ACE. Inheritance is also controlled by the ACE’s Inheritance Flags and by any protection against inheritance placed on the child object in its Security Descriptor Control Flags.

DACLs for Newly Created Objects

The operating system uses the following rules to set the DACL in the security descriptors for most types of new securable objects:

  1. The object’s DACL is the DACL from the security descriptor, which is specified by the creating process. The operating system merges any inheritable ACEs into the DACL unless SE_DACL_PROTECTED is set in the security descriptor control flags. The operating system then sets the SE_DACL_PRESENT security descriptor control flag.

  2. If the creating process does not specify a security descriptor, the operating system builds the object’s DACL from inheritable ACEs in the parent object’s DACL. The operating system then sets the SE_DACL_PRESENT security descriptor control flag.

  3. If the parent object has no inheritable ACEs, the operating system asks the object manager to provide a default DACL. The operating system then sets the SE_DACL_PRESENT and SE_DACL_DEFAULTED security descriptor control flags.

  4. If the object manager does not provide a default DACL, the operating system checks the subject’s access token for a default DACL. The operating system then sets the SE_DACL_PRESENT and SE_DACL_DEFAULTED security descriptor control flags.

  5. If the subject’s access token does not have a default DACL, the new object is assigned no DACL, which allows unconditional access by everyone. The SE_DACL_PRESENT security descriptor control flag is not set.

DACLs for Newly Created Active Directory Objects

The method that is used to build a DACL for a new Active Directory object is slightly different from the method that is used to build DACLs for other object types. There are two key differences:

  • The rules for creating a DACL distinguish between generic inheritable ACEs and object-specific inheritable ACEs in the parent object’s security descriptor. Generic inheritable ACEs can be inherited by all types of child objects. Object-specific inheritable ACEs can be inherited only by the type of child object to which they apply.

  • The Active Directory schema can provide a security descriptor. Each object class that is defined in the schema has a defaultSecurityDescriptor attribute. If neither the creating process nor inheritance from the parent object provides a DACL for a new Active Directory object, the operating system uses the DACL in the default security descriptor that is specified by the schema.

The operating system uses the following rules to set the DACL in the security descriptor for new Active Directory objects:

  1. The object’s initial DACL is the DACL from the security descriptor that is specified by the creating process.

  2. The operating system merges inheritable ACEs on the parent object into the new object’s DACL. It then sets the SE_DACL_PRESENT security descriptor control flag.

  3. If the parent object has no inheritable object-specific ACEs for the type of object being created, the operating system uses the default DACL from the Active Directory schema for that object type. It then sets the SE_DACL_PRESENT and SE_DACL_DEFAULTED security descriptor control flags.

  4. If the Active Directory schema does not specify a default DACL for the object type, the operating system checks the subject’s access token for a default DACL. It then sets the SE_DACL_PRESENT and SE_DACL_DEFAULTED security descriptor control flags.

  5. If the subject’s access token does not have a default DACL, the new object is assigned no DACL, which gives unconditional access to everyone. The SE_DACL_PRESENT security descriptor control flag is not set.

SACLs for Newly Created Objects

The operating system uses the following rules to set the SACL in the security descriptors for new securable objects:

  1. If the creating process provides an explicit SACL, the operating system places it in the object’s security descriptor. The operating system merges any inheritable ACEs into the SACL unless SE_SACL_PROTECTED is set in the security descriptor control flags. It then sets the SE_SACL_PRESENT security descriptor control flag.

  2. If the creating process does not provide an explicit SACL, the operating system builds the object’s SACL from inheritable ACEs in the parent object’s SACL. It then sets the SE_SACL_PRESENT security descriptor control flag.

  3. If the parent object has no inheritable ACEs, the operating system asks the object manager to provide a default SACL. It then sets the SE_SACL_PRESENT and SE_SACL_DEFAULTED security descriptor control flags.

  4. If the object manager does not provide a default SACL, the new object is assigned no SACL.

Inheritance

Inheritance is the process that propagates ACEs from the ACL of a parent object to the ACL of a child object. In Windows Server 2003, inheritable ACEs can be propagated from parent to child when one of the following events takes place:

  • A new child object is created.

  • The DACL on the parent object is modified.

  • The SACL on the parent object is modified.

In this model, any object can be the child of another object. Only container objects can be parents. The ACL for a container object can carry ACEs that are not effective on the container but are present only for the purpose of inheritance — only so that they can be passed down to subsequent levels of objects in the container hierarchy until they reach a child object that is not a container, where they become effective ACEs.

The mechanism for inheritance depends on two things: a set of inheritance flags in each ACE and a set of inheritance rules that are built into the operating system.

Inheritance Flags

The header for an ACE contains a set of inheritance flags that control how the ACE is inherited and how the ACE affects a child object that inherits it. The following table lists the inheritance flags.

Inheritance Flags

Flag Meaning

INHERITED_ACE

Windows 2000 and later: The ACE was inherited from a parent object’s DACL or SACL.

This flag is not set in an explicit ACE — an ACE defined directly on the object.

INHERIT_ONLY_ACE

Indicates that this is an inherit-only ACE. The ACE is ignored during an access check but can be propagated to child objects.

If this flag is not set, the ACE is an effective ACE — an ACE that is processed during an access check.

Both effective and inherit-only ACEs can be inherited. Whether an ACE is inherited depends on the state of the flags for OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE.

CONTAINER_INHERIT_ACE

Container objects inherit this ACE as an effective ACE. When the ACE is inherited by a container object, the operating system clears the flag for INHERIT_ONLY_ACE.

OBJECT_INHERIT_ACE

Noncontainer objects inherit this ACE as an effective ACE. When the ACE is inherited by a noncontainer object, the operating system clears the flag for INHERIT_ONLY_ACE.

Container objects also inherit this ACE but only for the purpose of inheritance. When the ACE is inherited by a container object, the operating system sets the flag for INHERIT_ONLY_ACE.

NO_PROPAGATE_INHERIT_ACE

If a child object inherits an ACE where this flag is set, the operating system clears the flags for OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE. This prevents the ACE from being inherited by subsequent generations of objects.

Rules of Inheritance

The operating system interprets the inheritance flags and other inheritance information according to the rules of ACE inheritance that are outlined in the following table. These rules function the same way for both DACLs and SACLs. When the operating system propagates inheritable ACEs to child objects, it observes the preferred (or canonical) order. After ACEs have been propagated, the system sets the INHERITED_ACE flag in all inherited ACEs.

The following table lists the rules of inheritance from parent ACEs to child ACLs.

Rules of Inheritance

Parent ACE Inheritance Flags Effect on Child ACL

No flags

None.

OBJECT_INHERIT_ACE only

Noncontainer child objects: Inherited as an effective ACE.

Container child objects: Containers inherit an inherit-only ACE unless the NO_PROPAGATE_INHERIT_ACE flag is also set.

CONTAINER_INHERIT_ACE only

Noncontainer child objects: No effect on the child object.

Container child objects: The child object inherits an effective ACE. The inherited ACE is inheritable unless the NO_PROPAGATE_INHERIT_ACE flag is also set.

CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE

Noncontainer child objects: Inherited as an effective ACE.

Container child objects: The child object inherits an effective ACE. The inherited ACE is inheritable unless the NO_PROPAGATE_INHERIT_ACE flag is also set.

If an inherited ACE is an effective ACE for the child object, the system maps any generic rights to the specific rights for the child object. Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the appropriate SID. If an inherited ACE is an inherit-only ACE, any generic rights or generic SIDs are left unchanged so that they can be mapped appropriately when the ACE is inherited by the next generation of child objects.

When a container object inherits an ACE that is both effective on the container and inheritable by its descendants, the container might inherit two ACEs. This occurs if the inheritable ACE contains generic information. The container inherits an inherit-only ACE containing the generic information, and an effective ACE in which the generic information is mapped.

An object-specific ACE has an Inherited Object Type field that can contain a GUID to identify the type of object that can inherit the ACE. If the field does not contain a GUID, the inheritance rules are the same as for a standard ACE. If the field contains a GUID, the ACE is inheritable by objects that match the GUID if OBJECT_INHERIT_ACE is set and by containers that match the GUID if CONTAINER_INHERIT_ACE is set.

Order of ACEs in a DACL

The preferred order of ACEs in a DACL is called the “canonical” order. For Windows 2000 and Windows Server 2003, the canonical order is the following:

  • All explicit ACEs are placed in a group before any inherited ACEs.

  • Within the group of explicit ACEs, access-denied ACEs are placed before access-allowed ACEs.

  • Inherited ACEs are placed in the order in which they are inherited. ACEs that are inherited from the child object’s parent come first, then ACEs inherited from the grandparent, and so on up the tree of objects.

The following figure shows the canonical order of ACEs.

Canonical Order of ACEs

Canonical Order of ACE

The canonical order ensures that an explicit access-denied ACE is enforced regardless of any explicit access-allowed ACE. This means that the object’s owner can define permissions that allow access to a group of users, such as Everyone, but deny access to a subset of the group, such as Marketing. If the object’s ACEs are in canonical order, the ACE that denies Marketing comes before the ACE that allows Everyone. During an access check, the operating system steps through the ACEs in the order in which they appear in the object’s DACL, so that the deny ACE is processed before the allow ACE. As a result, users who are members of the Marketing group are denied access. Everyone else is allowed access to the object.

The canonical order also ensures that all explicit ACEs are processed before any inherited ACE. This is consistent with the concept of discretionaryaccess control: access to a child object is at the discretion of the child’s owner, not the parent’s owner. The owner of a child object can define permissions directly on the child that modify the effects of inherited permissions. For example, suppose a parent object has an inheritable ACE that denies access to Marketing. And suppose the owner of a child object defines an explicit ACE that allows access to a subset of Marketing — let’s say a user named Bob. If the child object’s ACEs are in canonical order, the explicit ACE that allows Bob access comes before any inherited ACE, including the inherited ACE that denies access to Marketing. During an access check, the operating system reaches the ACE that allows Bob access before it gets to the ACE that denies access to Marketing. As a result, Bob is allowed access to the object even though he is a member of the Marketing group. Other members of the Marketing group are denied access.

What Happens During an Upgrade from Windows NT 4.0

When you upgrade a computer from Windows NT 4.0 to Windows Server 2003, the security descriptors on NTFS and registry objects must also be upgraded to reflect the new canonical order. This change does not take place during setup. Instead, the DACLs on existing objects are upgraded the first time that their security descriptors are modified after the operating system upgrade. Due to the automatic propagation of inheritable ACEs, the DACLs on all objects in the hierarchy below a modified object are also converted to the new canonical order.

The security descriptors for objects that have been converted contain the security descriptor control flags SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED.

The operating system uses the following rules for propagating inherited ACEs to child objects:

  • If a child object with no DACL inherits an ACE, the result is a child object with a DACL containing only the inherited ACE.

  • If a child object with an empty DACL inherits an ACE, the result is a child object with a DACL containing only the inherited ACE.

  • If you remove an inheritable ACE from a parent object, automatic inheritance removes any copies of the ACE that are inherited by child objects.

  • If automatic inheritance results in the removal of all ACEs from a child object’s DACL, the child object has an empty DACL rather than no DACL.

No DACL vs. Empty DACL

A security descriptor with no DACL (also known as a NULL DACL) gives unconditional access to everyone. A security descriptor with an empty DACL gives no access to anyone.

In Windows NT, if a developer wanted to allow everyone unconditional access to an object, his code could create the object with a NULL DACL — that is, without a DACL. In Windows 2000 and later, it is still possible to create objects with a NULL DACL, but code that does this must set the SE_DACL_PROTECTED security descriptor control flag to prevent the object from acquiring a DACL through inheritance. In the worst case, forgetting to protect a NULL DACL can result in an empty DACL if the parent object has no inheritable permissions. The result would be to allow no access to anyone, exactly the opposite of what the object’s creator intended.

Best practice is not to use NULL DACLs at all. If you are developing for Windows 2000 or later and want to give everyone unconditional access to an object, create a DACL with one ACE that grants Everyone full control. In Windows Server 2003, the Everyone group no longer includes Anonymous Logon; therefore you might also want to include a second ACE that grants Anonymous Logon full control.

The following resources contain additional information that is relevant to this section: