[ Team LiB ] Previous Section Next Section

23.1 How to Create an ACE Using ADSI

Microsoft has a habit of calling a shovel a ground insertion earth management device, that is, they like to give names that are not always intuitive to the average person. The contents of the five properties of the ACE object are not all immediately obvious from the names. In addition, as Microsoft uses the ACE for system-audit and permissions entries, a number of values that can go into the properties make sense only in a particular context. To complicate matters further, one property (AceFlags) is a catchall area that currently is the location for two completely different sets of information.

Creating an ACE is a simple matter. To set up an ACE, you need the following basic pieces of information:

AccessMask

What permissions you want to set

AceType

Whether you are setting allow/deny permissions or auditing for an object or property

Trustee

Who to apply the permissions to

AceFlags

What inheritance options you want and, if it is an audit entry, whether you are monitoring successes or failures

Flags, ObjectType, InheritedObjectType

What the ACE applies to if not just the entire object

We will now go through several examples to show you what the five properties of an ACE will contain based on certain security settings. Let's start with the simple example: giving a user full control permissions to an Organizational Unit. That means the information in Table 23-1 gets stored as an ACE on the SD of the Organizational Unit itself.

Table 23-1. Contents of the ACE properties when giving a user full control permissions to an Organizational Unit

Name of the property

Value to be stored

Trustee

Names the user who is to have the permission.

AccessMask

Gives full control (i.e. give every permission).

AceType

This is an allow permission.

AceFlags

The permission applies to this object. Child objects inherit this ACE.

Flags

Neither ObjectType nor InheritedObjectType is set.

ObjectType

Null.

InheritedObjectType

Null.

The user (Trustee) is allowed (AceType) full control (AccessMask) to the current object and all objects down the tree (AceFlags). The last three are not used here, as the permission is a simple one to an entire object.

If we were auditing successful and failed modifications to the entire Organizational Unit by the user, the contents of the audit ACE on the Organizational Unit would look like Table 23-2.

Table 23-2. Contents of the ACE properties when auditing successful modifications to an Organizational Unit and all children by a user

Name of the property

Value to be stored

Trustee

Names the user who is to be audited.

AccessMask

Gives full control (i.e., audit every action).

AceType

This is an audit ACE.

AceFlags

The auditing applies to this object. Child objects inherit this ACE. This ACE audits successes and failures.

Flags

Neither ObjectType nor InheritedObjectType is set.

ObjectType

Null.

InheritedObjectType

Null.

In this case we are auditing (AceType) successful and failed (AceFlags) modifications of all types (AccessMask) by a user (Trustee) for this object and all children (AceFlags).

Note the changes to AceFlags as compared to the previous permissions entry. While a permissions entry uses AceType to indicate whether it is allow or deny, an auditing entry uses AceFlags to indicate whether it is auditing successes or failures.

Let's take a look at a more complex example: giving the same user the ability to set the password for user objects within the entire branch beneath an Organizational Unit, as shown in Table 23-3. Again, this ACE is set on the SD of the Organizational Unit, yet it doesn't actually apply to the Organizational Unit itself. This ACE applies to passwords of user objects, so the Organizational Unit acts only as a carrier. The ACE is inherited down the tree by all containers that could ever contain users. As soon as a user is created in one of those containers, the ACE is instantly added as an ACE on the SD of the user via inheritance rules.

Table 23-3. Contents of the ACE properties for a more complex example

Name of the property

Value to be stored

Trustee

Names the user who is to have the permission.

AccessMask

Gives write access to a specific property.

AceType

This is an allow permission.

AceFlags

The permission is inherited only and does not apply to this object. Child objects inherit this ACE.

Flags

Both ObjectType and InheritedObjectType are set.

ObjectType

This is the GUID of the userPassword attribute.[1]

InheritedObjectType

This is the GUID of the User class.

[1] Globally Unique Identifiers (GUIDs) are used in the schema to distinguish objects and object attributes uniquely across your forest. Specifying that a GUID is used somewhere means that you are using a unique identifier for that item.

The user (Trustee) is allowed (AceType) write access (AccessMask) to a specific attribute of a specific object class (AccessMask and Flags), namely, the password (ObjectType) of user objects (InheritedObjectType). The ACE does not apply to the current object (AceFlags), so the current object is acting only as a propagator of the ACE down the tree (AceFlags).

To audit successful and failed modifications to the passwords of user objects within the entire branch beneath an Organizational Unit, the contents of the audit ACE on the Organizational Unit would look like Table 23-4.

Table 23-4. Contents of the ACE properties when auditing successful modifications to an Organizational Unit and all children by a user

Name of the property

Value to be stored

Trustee

Names the user who is to be audited.

AccessMask

Gives write access to a specific property.

AceType

This is an audit ACE.

AceFlags

The auditing is inherited only and does not apply to this object. Child objects inherit this ACE. This ACE audits successes and failures.

Flags

Both ObjectType and InheritedObjectType are set.

ObjectType

This is the GUID of the userPassword attribute.

InheritedObjectType

This is the GUID of the User class.

We are auditing (AceType) successful and failed (AceFlags) write access (AccessMask) to a specific attribute of a specific object class (AccessMask and Flags) by a user (Trustee), namely, the password (ObjectType) of user objects (InheritedObjectType). The ACE does not apply to the current object (AceFlags), so the current object is acting only as a propagator of the ACE down the tree (AceFlags).

Each ACE property uses a set of values that correspond to the text populating the tables. In the last example, AceFlags is held by the system as the integer 202 that is interpreted as a bit flag.[2] As you saw in Chapter 21, bits in specified positions on an integer represent each of the flags.

[2] We're using flags here as a general term (lowercase) to distinguish it from the ACE property called Flags (uppercase).

Many companies and programmers that publish sets of values like these do not always keep the sequences as simple as this. Sometimes the values make no sense as binary values. For example, under the later section Section 23.1.3, we'll show you that Microsoft has values of 0,1,2,5,6, and 7 for AceType. This may seem daft, since you won't know if the integer 7 represents 7 on its own or 5+2. Not only that, but surely every value can include 0, so how do you check for it? The simple answer is that in this case, each integer represents one and only one value at any one time, so there is no need to check for multiple bits.

Let's consider each of the properties of an ACE in turn to examine the values that can be stored within.

23.1.1 Trustee

The Trustee is the group or user receiving the permissions defined in the AccessMask and AceType fields or the user or group that is being audited. The Trustee can take any of the following forms:

Domain accounts

These are the logon names used in previous versions of Windows NT, in the form domain\useraccount, where domain is the name of the Windows NT domain that contains the user and useraccount is the sAMAccountName property of the specified user. An example is AMER\jsmith. This is still valid for Windows 2000 and Windows Server 2003 domains.

Well-known security principals

These represent special identities defined by the Windows NT/Windows 2000/Windows Server 2003 security system, such as Everyone, Authenticated Users, System, Creator Owner, etc. The objects representing the security principals are stored in the WellKnown Security Principals container beneath the Configuration container.

Built-in groups

These represent the built-in user groups defined by the Windows NT security system. They have the form BUILTIN\groupname where groupname is the name of the built-in user group. The objects representing the built-in groups are stored in the Builtin container beneath the domain container. An example is BUILTIN\Administrators.

Security Identifiers (SIDs)

These are specified in string format and represent the objectSID property of the specified user or group in Active Directory. An example is S-1-5-99-427-9.

Distinguished Name (DN)

This is the distinguishedName property of the specified user or group in Active Directory. An example is cn=Tracy Poodles,ou=Finance,dc=mycorp,dc=com.

23.1.2 AccessMask

The AccessMask specifies the single or multiple permissions you are setting or auditing for the ACE. Note that this property does not determine whether you are allowing or denying the permission or whether you are auditing successful or failed access, only what the permission is.

If you are applying the permissions to a specific object or property, you also need to specify the relevant GUID of the object or property that you are giving rights to in the ObjectType or InheritedObjectType properties.

The largest set of values applies to the AccessMask, which is probably what you would expect. See Table 23-5.

Table 23-5. AccessMask constants

ADSI name

Decimal value

Hex value

Description

ADS_RIGHT_GENERIC_ READ

2,147,483,648

&H80000000

Right to read from the Security Descriptor, to examine the object and its children, and to read all properties

ADS_RIGHT_GENERIC_ WRITE

1,073,741,824

&H40000000

Right to write all properties, write to the DACL, and add/remove the object from the tree

ADS_RIGHT_GENERIC_ EXECUTE

536,870,912

&H20000000

Right to list children of the object

ADS_RIGHT_GENERIC_ ALL

268,435,456

&H10000000

Right to create/delete children, delete the tree, read/write properties, examine the object and its children, add/remove the object from the tree, and read/write with an extended right

ADS_RIGHT_ACCESS_ SYSTEM_SECURITY

16,777,216

&H1000000

Right to get or set the SACL in the SD of the object

ADS_RIGHT_ SYNCHRONIZE

1,048,576

&H100000

Right to use the object for synchronization (see ADSI documentation for more information)

ADS_RIGHT_WRITE_ OWNER

524,288

&H80000

Right to assume ownership of the object; no right to grant ownership to others (User must be a trustee of the object)

ADS_RIGHT_WRITE_ DAC

262,144

&H40000

Right to write to the DACL of the object

ADS_RIGHT_READ_ CONTROL

131,072

&H20000

Right to read from the security descriptor of the object

ADS_RIGHT_DELETE

65,536

&H10000

Right to delete the object

ADS_RIGHT_DS_ CONTROL_ACCESS

256

&H100

Right to perform an application-specific extension on the object (GUID=extended right)

ADS_RIGHT_DS_LIST_ OBJECT

128

&H80

Right to examine the object (if this is missing, the object is hidden from the user)

ADS_RIGHT_DS_ DELETE_TREE

64

&H40

Right to delete all children of this object, regardless of the permission on the children

ADS_RIGHT_DS_ WRITE_PROP

32

&H20

Right to write properties of the object (GUID=specific property; no GUID=all properties)

ADS_RIGHT_DS_READ_ PROP

16

&H10

Right to read properties of the object (GUID=specific property; no GUID=all properties)

ADS_RIGHT_DS_SELF

8

&H8

Right to modify the group membership of a group object

ADS_RIGHT_ACTRL_ DS_LIST

4

&H4

Right to examine children of the object

ADS_RIGHT_DS_ DELETE_CHILD

2

&H2

Right to delete children of the object (GUID=specific child object class; no GUID=all child object classes)

ADS_RIGHT_DS_ CREATE_CHILD

1

&H1

Right to create children of the object (GUID=specific child object class; no GUID=all child object classes)

No name defined

-1

&HFFFFFFFFFFFFFFFF

Full control

These values were taken from the ADSI documentation for the ADS_RIGHTS_ENUM enumerated type available from the MSDN Library under the section described at the beginning of the chapter.

The value in the first column is the constant name that Microsoft defined for ADSI. This works fine if you are programming in VB or VC++ or scripting in a language that can make use of the available ADSI libraries, but with VBScript these constants are not defined. In other words, you have to define them in each script you use. To save you time, just copy the Const definitions from any of the ACE scripts provided on the O'Reilly web site for this book. We've included the values in decimal and in hex for two reasons. First, we will be using hex in the scripts; the decimal values are there in case you want to use them for your own preference. Second, Microsoft defines all their constants in hexadecimal, so that is what you will see in the ADSI documentation. &H is the prefix for a hex number in VBScript, so if you want to specify that a group can list, create, and delete all children, you would use the value &H7, consisting of the rights ADS_ RIGHT_ACTRL_DS_LIST + ADS_RIGHT_DS_DELETE_CHILD + ADS_RIGHT_DS_ CREATE_CHILD.

The last value has no name and is what you use if you want to define full control permissions. Note that in this case most programmers tend to use the integer value -1 even if they have used hex elsewhere.

The GUIDs relating to properties and children are discussed further under the ACE Flags property.

23.1.3 AceType

This property dictates whether the ACE denies permissions, allows permissions, or audits use of permissions (whether success or failure is defined in AceFlags). The values set here depend on whether the ACE applies to a specific object/property or just applies generally. See Table 23-6.

Only one value can be set at any one time. This is why the values are not 1, 2, 4, and so on.

Table 23-6. Constants

ADSI name

Decimal value

Hex value

Description

ADS_ACETYPE_SYSTEM_ ALARM_OBJECT

8

&H8

Not used.

ADS_ACETYPE_SYSTEM_ AUDIT_OBJECT

7

&H7

This is a system-audit entry ACE using a GUID.

ADS_ACETYPE_ACCESS_ DENIED_OBJECT

6

&H6

This is an access-denied ACE using a GUID.

ADS_ACETYPE_ACCESS_ ALLOWED_OBJECT

5

&H5

This is an access-allowed ACE using a GUID.

ADS_ACETYPE_SYSTEM_ AUDIT

2

&H2

This is a system-audit entry ACE using a Windows NT Security Descriptor.

ADS_ACETYPE_ACCESS_ DENIED

1

&H1

This is an access-denied ACE using a Windows NT Security Descriptor.

ADS_ACETYPE_ACCESS_ ALLOWED

0

&H0

This is an access-allowed ACE using a Windows NT Security Descriptor.

These values were taken from the ADSI documentation for the ADS_ACETYPE_ENUM enumerated type available from the MSDN Library under the section described at the beginning of the chapter.

Those ACEs that have a GUID in ObjectType or InheritedObjectType use the top three _OBJECT values. Any ACEs that do not refer to a specific GUID use the bottom three.

23.1.4 AceFlags

This catchall location stores two sets of information: inheritance and auditing. First it stores whether its children can inherit this ACE, whether the ACE applies to this object or is only acting as a propagator to pass it on to other objects, and whether the ACE is itself inherited. Second, for system-audit ACEs, this property indicates whether audit events are generated for success, failure, or both of the AccessMask permissions. See Table 23-7.

Table 23-7. AceFlags constants

ADSI name

Decimal value

Hex value

Description

ADS_ACEFLAG_FAILED_ACCESS

128

&H80

Used in the SACL only; indicates to generate audit messages for failed access attempts.

ADS_ACEFLAG_SUCCESSFUL_ ACCESS

64

&H40

Used in the SACL only; indicates whether to generate audit messages for successful access attempts.

ADS_ACEFLAG_VALID_INHERIT_ FLAGS

31

&H1F

Indicates whether the inherit flags for this ACE are valid (set only by the system).

ADS_ACEFLAG_INHERITED_ACE

16

&H10

Indicates whether this ACE was inherited (set only by the system).

ADS_ACEFLAG_INHERIT_ONLY_ ACE

8

&H8

Indicates an inherit-only ACE that does not exercise access controls on the object to which it is attached.

ADS_ACEFLAG_NO_ PROPAGATE_INHERIT_ACE

4

&H4

Child objects will not inherit this ACE.

ADS_ACEFLAG_INHERIT_ACE

2

&H2

Child objects will inherit this ACE.

These values were taken from the ADSI documentation for the ADS_ACEFLAG_ENUM enumerated type available from the MSDN Library under the section described at the beginning of the chapter.

There are three unusual aspects to this property:

  • The two SACL flags should surely be in AceType, not AceFlags, since AceType already indicates the allow or deny aspects of a DACL ACE. Strangely, they are here instead.

  • The ADS_ACEFLAG_INHERIT_ONLY_ACE indicates that the object that this ACE is attached to is acting only as a carrier for the object, rather than being affected by the ACE itself. This normally applies to containers, where the container acts as a placeholder for the ACE and applies it to whatever specific objects it is targeted to when they are created. If appropriate, the ACE will be propagated to containers below so they can act as carriers themselves.

  • Flags of this nature in ADSI normally are intended to indicate the presence or absence of something. The flag is set or it is not, giving us two states for whatever the flag refers to. Take a look at the last two flags in the table. The ADS_ ACEFLAG_INHERIT_ACE flag indicates that the ACE will be propagated down to child objects throughout the section of the tree below this object. If the ADS_ACEFLAG_INHERIT_ACE flag is set, ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE will not be set. If ADS_ACEFLAG_NO_PROPAGATE_ INHERIT_ACE is set, ADS_ACEFLAG_INHERIT_ACE is not, and this prevents the ACE from being inherited by subsequent generations of objects. Don't try to set both at the same time.

23.1.5 Flags, ObjectType, and InheritedObjectType

For the ACE to know whether it contains an ObjectType or InheritedObjectType field, it contains a Flags property. This can have only four values. If the value is 0, neither object is present in the ACE. The other three values (1, 2, and 3) are made up from the two constants displayed in Table 23-8.

Table 23-8. Flag type constants

ADSI name

Decimal value

Hex value

Description

ADS_FLAG_ INHERITED_OBJECT_ TYPE_PRESENT

2

&H2

Indicates that an InheritedObjectType is present in the ACE and that an ObjectType is not present

ADS_FLAG_OBJECT_ TYPE_PRESENT

1

&H1

Indicates that an ObjectType is present in the ACE and that an InheritedObjectType is not present

These values were taken from the ADSI documentation for the ADS_FLAGTYPE_ENUM enumerated type available from the MSDN Library under the section described at the beginning of the chapter.

The ObjectType and InheritedObjectType fields store GUIDs or null values that indicate what the ACE actually applies to. Table 23-9 explains it much better.

Table 23-9. How to use ObjectType and InheritedObjectType

ACE requirement

AceFlags

Flags

ObjectType

InheritedObjectType

Permissions are to apply to entire current object.

Effective on current object; not inherited by child objects.

Neither

Null (ignored but still set)

Null (ignored but still set)

Permissions are to apply to a specific attribute of the current object.

Effective on current object; not inherited by child objects.

ObjectType only

schemaIDGUID of the attributeSchema object that defines the attribute in the schema

Null (ignored but still set)

Permissions are to apply to all child objects.

Not effective on current object; inherited by children.

ObjectType only

Null[3]

Null (ignored but still set)

Permissions are to apply to child objects that are of a specific class.

Not effective on current object; inherited by children.

ObjectType only

schemaIDGUID of the classSchema object that defines the class in the schema

Null (ignored but still set)

Permissions are to apply to a specific attribute of specific child objects.

Not effective on current object; inherited by children.

Both

schemaIDGUID of the attributeSchema object that defines the attribute in the schema

schemaIDGUID of the classSchema object that defines the class in the schema

[3] Setting null for the ObjectType field in the third entry signifies that this ACE applies to all child objects; this is the only time that you do not use a GUID in this property. The system understands that a null value for a required ObjectType field is the same as providing the GUIDs for every possible child object all at once.

You do not need to set null items that are ignored; they will be set to null by the system on creation of the ACE.

Note that Flags, ObjectType, and InheritedObjectType have defaults of 0, null, and null, respectively.

    [ Team LiB ] Previous Section Next Section