How to Create an ACE Using ADSI






How to Create an ACE Using ADSI

Microsoft has a habit of calling a shovel a ground insertion earth management device (GIEMD for short); 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 serves as the location for two completely different sets of information.

Creating an ACE is a simple matter, getting it right is a little more difficult. 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 seven 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 Figure gets stored as an ACE on the SD of the Organizational Unit itself.

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 properties in the table are not used here, as the permission is a simple one that is being applied 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 Figure.

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 set to allow or deny, an auditing entry uses AceFlags to indicate whether it is auditing successes or failures.


Be careful with adding audit entries to Active Directory. Auditing imparts significant overhead to a domain controller's workload, and it is easily possible to enable too much auditing. Too much auditing can cause the domain to not function properly or perform its functions very slowly as well as fill the security log with a lot of entries that probably are not very useful.


Let's take a look at a more complex example: giving the same user the ability to set the description for user objects within the entire branch beneath an Organizational Unit, as shown in Figure. 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 the description attribute of user objects, so the Organizational Unit acts only as a carrier. The ACE is inherited down the tree by all objects, but only ever directly affects users. As soon as an object is created in one of those containers, the ACE is instantly added as an ACE on the SD of the object via inheritance rules. When access is being checked, if the object is a user, the ACE is "in effect" and allows the trustee to make the specified change.

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 schemaIDGUID of the description attribute.[a]

InheritedObjectType

This is the schemaIDGUID of the User class.


[a] 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 description (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 description of user objects within the entire branch beneath an Organizational Unit, the contents of the audit ACE on the Organizational Unit would look like Figure.

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 schemaIDGUID of the description attribute.

InheritedObjectType

This is the schemaIDGUID 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 description (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 following tables. Let's consider each of the properties of an ACE in turn to examine the values that can be stored within.

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 Well-Known 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.


User Principal Name (UPN)

This is the userPrincipalName property of the specified user or group in Active Directory. An example is [email protected]p.com.

When using a trustee in an ACE, you should always try to use a group, not a user. Groups are far more flexible in that you can easily change who has permissions or easily grant more trustees the same permission by adding more users to the group. You also need to be very careful of the scope of the group. For example, a domain local group is not a good group scope to use for granting write access to an object in the configuration container in a multi-domain forest because the domain local groups are effective only on domain controllers from the domain the groups exist in. If you find you can write to a configuration container object on a domain controller from one domain but not on a domain controller in another domain, there is a good chance your access was granted through a domain local group.


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 Figure.

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 invoke a validated write update.

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

No name defined

983551

&HF01FF

Full control, alternate value


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 both 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 two values have no name and are what you use if you want to define full control permissions. Note that in this case, most programmers tend to use the decimal value -1 even if they have used hexadecimal values elsewhere.

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

You probably noticed two different numeric values for full control in Figure. While -1 is the "official" value for full control, you will often find 983551 set in some ACEs that were configured as full control. 983551 is the combination of ADS_RIGHT_WRITE_OWNER, ADS_RIGHT_WRITE_DAC, ADS_RIGHT_READ_CONTROL, ADS_RIGHT_DELETE, ADS_RIGHT_DS_CONTROL_ACCESS, ADS_RIGHT_DS_LIST_OBJECT, ADS_RIGHT_DS_DELETE_TREE, ADS_RIGHT_DS_WRITE_PROP, ADS_RIGHT_DS_READ_PROP, ADS_RIGHT_DS_SELF, ADS_RIGHT_ACTRL_DS_LIST, ADS_RIGHT_DS_DELETE_CHILD, and ADS_RIGHT_DS_CREATE_CHILD.


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 Figure.

AceType 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.


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


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 four _OBJECT values. Any ACEs that do not refer to a specific GUID use the bottom three.

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 itself is inherited. Second, for system-audit ACEs, this property indicates whether audit events are generated for success, failure, or both of the AccessMask permissions. See Figure.

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.

  • Flags of this nature in ADSI are 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.

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 Figure.

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

ADS_FLAG_OBJECT_ TYPE_PRESENT

1

&H1

Indicates that an ObjectType is present in the ACE


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. Figure explains it much better.

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 or rightsGuid of the controlAccessRight object that defines the extended right, property set, or validated right in the extended-rights container

Null (ignored but still set)

Permissions are to apply to all child objects.

Not effective on current object; inherited by children

ObjectType only

Null[a]

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 or rightsGuid of the controlAccessRight object that defines the extended right, property set, or validated right in the extended-rights container

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 or rightsGuid of the controlAccessRight object that defines the extended right, property set, or validated right in the extended-rights container

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


[a] 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.




 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows