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
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
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
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.
|
InheritedObjectType
|
This is the GUID of the User class.
|
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
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. As you saw in
Chapter 21, bits in specified positions on an
integer represent each of the flags.
|
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
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
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
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
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
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
|
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
|
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.
|
|
|