Managing Security for Objects in the Active Directory

   

Managing Security for Objects in the Active Directory

In response to critical analysis regarding the granularity of the administrative model implemented in Windows NT, Microsoft's efforts with the Active Directory are sure to please administrators eager to break free of the chains binding them to the most mundane administrative tasks . This newfound freedom comes at the cost of additional complexity to the design and programmatic manipulation of the entries in the directory. However, most will agree that such complexity is a worthwhile compromise to gain the additional features and benefits derived from having such fine granularity to the administrative model.

Warning

Programmatic administration of the security descriptors for Active Directory objects is not a topic that should be tackled by those new to the Active Directory or Visual Basic. To successfully achieve a working security model, you often must pass a properly formatted schemaIDGuid for either an object class or attribute definition.

To perform this task, you can use a custom DLL included with the sample code associated with this text, found at http://www.newriders.com/adsi .


Security administration of objects in the directory uses the following basic flow to assign establish permissions on an object:

  1. Bind to an object in the directory.

  2. Open the object's security descriptor.

  3. Obtain the discretionary access control list (DACL) from the security descriptor.

  4. Create a new access control entry (ACE.)

  5. Assign the appropriate constants to the fields in the ACE.

  6. Assign a trustee to the ACE.

  7. Write the ACE to the DACL.

  8. Write the DACL to the Security Descriptor.

  9. Write the update back to the Active Directory.

Based on the constants assigned within the properties of the access control entry, you can determine whether child objects should inherit the permissions assigned to the parent object. You can also specify whether the permissions will be inherited by all objects or will affect just a single object class or attribute definition.

After you understand how the security descriptors are manipulated programmatically, you can manipulate the most powerful security feature of the Active Directory: the delegation of administrative authority.

By managing security down to the attribute level, you can create an administrative model in which specific groups of users can manage a very small subset of properties for all users in a particular container. Imagine how much you would reduce administrative burden if you could create a Web page wherein users could manage their own user information, such as department, telephone extension, address, and so on. The number of solutions you can implement by taking advantage of attribute-level security descriptors is limited only by the design of your directory and by your own creativity.

Constants Used in ACEs

To configure the ACE for an object in the Active Directory, you must reference the proper constant representing the right you wish to grant, the type of access control entry, and the inheritance scope for the ACE.

Directory Object Access Rights

To specify the rights for an object in the Active Directory, you can assign any of the constants found in Table 12.2 to the AccessMask ACE field.

Table 12.2. Access Mask Property Flags
Constant Value Description
Full Control Access -1 To specify full control, set the value of the s AccessMask ACE field to “1.
ADS_RIGHT_DS_CREATE_CHILD 0x1 Grants the ability to create child objects. All objects can be created unless the ObjectType field in the ACE contains a valid schemaIDGuid for an object class.
ADS_RIGHT_DS_DELETE_CHILD 0x2 Grants the ability to delete child objects of all classes, unless the ObjectType contains a valid schemaIDGuid for an object class.
ADS_RIGHT_ACTRL_DS_LIST 0x4 Grants the ability to list all child objects.
ADS_RIGHT_DS_SELF 0x8 Grants the ability to list the object itself.
ADS_RIGHT_DS_READ_PROP 0x10 Grants the ability to read object properties. Setting the ObjectType to a valid property or property set GUID restricts the grant to a specific property or property set.
ADS_RIGHT_DS_WRITE_PROP 0x20 Grants the ability to write object properties. Can be restricted using the ObjectType ACE member. Setting the ObjectType to a valid property or property set GUID restricts the grant to a specific property or property set.
ADS_RIGHT_DS_DELETE_TREE 0x40 Grants the ability to delete the object and all associated child objects.
ADS_RIGHT_DS_LIST_OBJECT 0x80 Can be used to show or hide an object from user view.
ADS_RIGHT_DS_CONTROL_ACCESS 0x100 Grants the ability to perform an operation restricted by an extended access right. Must specify a rights GUID identifying a controlAccessRight object in the Extended-Rights container in the configuration partition (naming context).
ADS_RIGHT_DELETE 0x10000 Grants the right to delete the object.
ADS_RIGHT_READ_CONTROL 0x20000 Grants the right to read the object's security descriptor.
ADS_RIGHT_WRITE_DAC 0x40000 Grants the right to modify the discretionary access control list.
ADS_RIGHT_OWNER 0x80000 Grants the right to take ownership of an object.
ADS_RIGHT_SYNCHRONIZE 0x100000 Enables the object to be used for synchronization.
ADS_RIGHT_ACCESS_SYSTEM_SECURITY 0x1000000 Grants the right to manipulate the object's SACL.
ADS_RIGHT_GENERIC_ALL 0x10000000 Grants the right to create or delete child objects and subtrees, read and write all properties, and add or remove the object from the directory.
ADS_RIGHT_GENERIC_EXECUTE 0x20000000 Grants the ability to list the object's children.
ADS_RIGHT_GENERIC_WRITE 0x40000000 Grants the right to write to the DACL and all properties, as well as to remove the object from the directory.
ADS_RIGHT_GENERIC_READ 0x80000000 Grants the right to read the security descriptor, all properties, and any children of the object.
Access Control Entry Types

To specify the type of ACE used in an Active Directory object access control list (ACL), assign one of the constants in Table 12.3 to the AceType ACE field.

Table 12.3. AceType Flag Values
Constant Value Description
ADS_ACETYPE_ACCESS_ALLOWED Access allowed, no object class discrimination
ADS_ACETYPE_ACCESS_DENIED 0x1 Access denied , no object class discrimination
ADS_ACETYPE_SYSTEM_AUDIT 0x2 System type ACE, no object class discrimination
ADS_ACETYPE_ACCESS_ALLOWED_OBJECT 0x5 Access allowed for objects defined by ObjectType or InheritedObjectType
ADS_ACETYPE_ACCESS_DENIED_OBJECT 0x6 Access denied for objects defined by ObjectType or InheritedObjectType
ADS_ACETYPE_SYSTEM_AUDIT_OBJECT 0x7 System type ACE, applied only to objects defined by ObjectType or InheritedObjectType
Security Propagation and Inheritance

To define the scope of inheritance and the use of system audit messages, assign one of the constants in Table 12.4 to an ACE's AceFlags field.

Table 12.4. AceFlags Flag Values
Constant Value Description
ADS_ACEFLAG_INHERIT_ACE 0x2 Child objects inherit the ACE unless the ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE flag has been set.
ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE 0x4 The ACEs for all child objects will not contain this ACE.
ADS_ACEFLAG_INHERIT_ONLY_ACE 0x8 Specifies the ACE to be inherited for child objects, but is not subject to the ACE itself.
ADS_ACEFLAG_INHERITED_ACE 0x10 System controlled bit to determine whether the ACE was derived from the parent object.
ADS_ACEFLAG_VALID_INHERIT_FLAGS 0x1f System controlled bit to determine whether inherit flags are valid.
ADS_ACEFLAG_SUCCESSFUL_ACCESS 0x40 Used with SACL ACEs to generate a successful audit message.
ADS_ACEFLAG_FAILED_ACCESS 0x80 Used with SACL ACEs to generate a failed audit message.
ObjectType Constants

To restrict an ACE to a particular class of objects (or even an individual object class attribute) assign the schemaIDGuid associated with the object class to the ACE's ObjectType field and then assign one of the constants in Table 12.5 to the Flags field in the ACE.

Table 12.5. ACE Flags Flag Values
Constant Value Description
ADS_FLAG_OBJECT_TYPE_PRESENT 0x1 Indicates that the ObjectType field has been populated with a schemaIDGuid and that the ObjectType GUID should be used.
ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT 0x2 Indicates that the InheritedObjectType field has been populated with a schemaIDGuid and that the InheritedObjectType GUID should be used.

Basic Active Directory Security Administration

Every object in the Active Directory maintains a security descriptor that can be manipulated programmatically using Visual Basic. In this section, we'll explore basic manipulation of an object's security descriptor, including enumeration of the defined access control entries in an access control list, addition of an access control entry that only applies to the bound object's ACL, and removal of ACEs.

Enumerating the ACEs Within an Active Directory ACL Using Visual Basic

To enumerate the ACEs within the ACL of an object's security descriptor, use the following Visual Basic code:

 Dim Obj As IADs Dim ACE As AccessControlEntry Dim DiscretionaryACL As AccessControlList Dim SecurityDescriptor As IADsSecurityDescripter Dim ObjectDistinguishedName As String ObjectDistinguishedName = "ou=Admins,dc=eCommerce2000,dc=com" Set Obj = GetObject("LDAP:// " & ObjectDistinguishedName) Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DiscretionaryACL = SecurityDescriptor.DiscretionaryACL For Each ACE In DiscretionaryACL     Debug.Print ACE.Trustee     If (ACE.AccessMask And ADS_RIGHT_DELETE) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DELETE"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DELETE for SchemaIDGuid: " & ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DELETE for SchemaIDGuid: " & graphics/ccc.gif ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_READ_CONTROL) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_READ_CONTROL"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_READ_CONTROL for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_READ_CONTROL for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_WRITE_DAC) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_WRITE_DAC"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_WRITE_DAC for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_WRITE_DAC for SchemaIDGuid: " & graphics/ccc.gif ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_WRITE_OWNER) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_WRITE_OWNER"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_WRITE_OWNER for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_WRITE_OWNER for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_SYNCHRONIZE) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_SYNCHRONIZE"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_SYNCHRONIZE for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_SYNCHRONIZE for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_ACCESS_SYSTEM_SECURITY) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_ACCESS_SYSTEM_SECURITY"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_ACCESS_SYSTEM_SECURITY for SchemaIDGuid: " graphics/ccc.gif & ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_ACCESS_SYSTEM_SECURITY for graphics/ccc.gif SchemaIDGuid: " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_GENERIC_READ) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_GENERIC_READ"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & ///"ADS_RIGHT_GENERIC_READ for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_GENERIC_READ for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_GENERIC_WRITE) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_GENERIC_WRITE"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_GENERIC_WRITE for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_GENERIC_WRITE for SchemaIDGuid: graphics/ccc.gif " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_GENERIC_EXECUTE) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_GENERIC_EXECUTE"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_GENERIC_EXECUTE for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_GENERIC_EXECUTE for graphics/ccc.gif SchemaIDGuid: " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_GENERIC_ALL) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_GENERIC_ALL"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_GENERIC_ALL for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_GENERIC_ALL for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_CREATE_CHILD) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_CREATE_CHILD"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_CREATE_CHILD for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_CREATE_CHILD for graphics/ccc.gif SchemaIDGuid: " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_DELETE_CHILD) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_DELETE_CHILD"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_DELETE_CHILD for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_DELETE_CHILD for graphics/ccc.gif SchemaIDGuid: " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_ACTRL_DS_LIST) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_ACTRL_DS_LIST"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_ACTRL_DS_LIST for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_ACTRL_DS_LIST for SchemaIDGuid: graphics/ccc.gif " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_SELF) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_SELF"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_SELF for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_SELF for SchemaIDGuid: " & graphics/ccc.gif ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_READ_PROP) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_READ_PROP"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_READ_PROP for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_READ_PROP for SchemaIDGuid: " graphics/ccc.gif & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_WRITE_PROP) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_WRITE_PROP"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_WRITE_PROP for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_WRITE_PROP for SchemaIDGuid: graphics/ccc.gif " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_DELETE_TREE) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_DELETE_TREE"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_DELETE_TREE for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_DELETE_TREE for SchemaIDGuid: graphics/ccc.gif " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_LIST_OBJECT) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_LIST_OBJECT"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_LIST_OBJECT for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_LIST_OBJECT for SchemaIDGuid: graphics/ccc.gif " & ACE.InheritedObjectType             End If         End If     End If     If (ACE.AccessMask And ADS_RIGHT_DS_CONTROL_ACCESS) <> 0 Then         If (ACE.ObjectType = "" And ACE.InheritedObjectType = "") Then             Debug.Print vbTab & "ADS_RIGHT_DS_CONTROL_ACCESS"         Else             If ACE.InheritedObjectType = "" Then                 Debug.Print vbTab & "ADS_RIGHT_DS_CONTROL_ACCESS for SchemaIDGuid: " & graphics/ccc.gif ACE.ObjectType             Else                 Debug.Print vbTab & "Inherited ADS_RIGHT_DS_CONTROL_ACCESS for graphics/ccc.gif SchemaIDGuid: " & ACE.InheritedObjectType             End If         End If     End If Next 
Adding an ACE to an Active Directory Object ACL Using Visual Basic

To add a new ACE to the ACL of an object's security descriptor, use the following Visual Basic code and the tables used for ACE field flag values (refer to the section "Constants Used in ACEs") as a guide:

 Dim Obj As IADs Dim SecurityDescriptor As IADsSecurityDescriptor Dim ACE As AccessControlEntry Dim DACL As AccessControlList Set Obj = GetObject("LDAP://ou=Admins,dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL Set ACE = CreateObject("AccessControlEntry") ACE.AccessMask = ADS_RIGHT_DELETE Or ADS_RIGHT_GENERIC_READ Or ADS_RIGHT_GENERIC_WRITE ACE.AceFlags = ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE ACE.AceType = ADS_ACETYPE_ACCESS_ALLOWED ACE.Trustee = "eCommerce2000\DMZAdmin" DACL.AddAce ACE SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 
Removing an ACE from an Active Directory Object ACL Using Visual Basic

Use the following Visual Basic code to remove all ACEs for a particular trustee:

 Dim Obj As IADs Dim ACE As AccessControlEntry Dim DACL As AccessControlList Dim SecurityDescriptor As IADsSecurityDescriptor Set Obj = GetObject("LDAP://cn=Guest,ou=users, dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL For Each ACE In DACL     If UCase(ACE.Trustee) = "ECOMMERCE2000\GUEST" Then         DACL.RemoveAce ACE     End If Next SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 

Tip

Although the previous code example indiscriminately removes an ACE based on the trustee's name , you can design a conditional to remove an ACE based on ObjectType or AccessMask constants .


Advanced Topics in Active Directory Security Manipulation

The true power of the Active Directory is found in the Directory's ability to create ACLs for security descriptors at the attribute level, and its ability to delegate administrative privileges for objects in the directory.

A key element to creating a delegation model for the Active Directory is based on the concept of inheritance . Just as you can propagate an ACL throughout the entire file structure in the file system, the Active Directory allows you to specify permissions for a parent object and allow child objects to inherit the ACL.

By assigning the ADS_ACEFLAG_INHERIT_ACE constant to the AceFlags field in the ACE, you can allow or disallow the ability for child objects to inherit the permissions assigned to the parent object.

To establish a delegation model, you can assign trustees the ability to create and remove child objects, or even create and remove specific types of objects. To make this work effectively, you typically assign permissions to a container object (such as an OU) to establish the ability to manage child entities in the directory.

To take this a step further, because Windows 2000's Active Directory allows attribute-level permissions to be assigned, you can even specify specific object attributes that trustees can manipulate.

Adding an ACE to an Active Directory OU ACL with Inheritance to All Child Objects Using Visual Basic

As shown in the following Visual Basic code, by simply changing the AceFlags field value assignment, you can allow child objects to inherit the permissions assigned to parent objects in the directory:

 Dim Obj As IADs Dim SecurityDescriptor As IADsSecurityDescriptor Dim ACE As AccessControlEntry Dim DACL As AccessControlList Set Obj = GetObject("LDAP://ou=Admins,dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL Set ACE = CreateObject("AccessControlEntry") ACE.AccessMask = ADS_RIGHT_GENERIC_READ ACE.AceFlags = ADS_ACEFLAG_INHERIT_ACE ACE.AceType = ADS_ACETYPE_ACCESS_ALLOWED ACE.Trustee = "eCommerce2000\DMZAdmin" DACL.AddAce ACE SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 
Adding an ACE to an Active Directory OU ACL with Inheritance to a Single Class of Child Objects Using Visual Basic

To allow a user to manipulate a subset of object classes, you can specify the allowed (or denied) object class in an ACE within the ACL assigned to the security descriptor for the OU.

For example, creating an access control entry based on an object class definition can be useful if you want a user to be able to create and delete objects belonging only to the Group object class. In this scenario, this user can create and remove groups within the particular OU, but cannot create any other type of object in the container.

Assigning the schemaIDGuid of the desired object class to the ObjectType field in the ACE and assigning the ACE's Flags field to ADS_FLAG_OBJECT_TYPE_PRESENT perform specification of a particular object class.

The schemaIDGuid is defined in the schema container of the directory; however, to use the GUID in the ObjectType field, a string must be created and assigned in the form {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} .

After obtaining and formatting the proper GUID for the object class (usually done in combination with the StringFromGUID2 API call), you can use the following Visual Basic code to guide your efforts to create an application that will restrict object manipulation to a single object class:

 Dim Obj As IADs Dim SecurityDescriptor As IADsSecurityDescriptor Dim ACE As AccessControlEntry Dim DACL As AccessControlList Set Obj = GetObject("LDAP://ou=Admins,dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL Set ACE = CreateObject("AccessControlEntry") ACE.AccessMask = ADS_RIGHT_DS_DELETE_TREE ACE.AceFlags = ADS_ACEFLAG_INHERIT_ACE ACE.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT ACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT ACE.ObjectType = "{BF967A9C-0DE6-11D0-A285-00AA003049E2}" ACE.Trustee = "eCommerce2000\DMZAdmin" DACL.AddAce ACE SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 

Note

The GUID used in the previous example was for group objects.

If you prefer not to hard-code GUIDs into your application, you can download the COM-based GetSchemaIDGuid.DLL from http://www.newriders.com/adsi to programmatically derive the GUID for a particular object class.


Removing an ACE from an Active Directory OU ACL with Inheritance to a Single Class of Child Objects Using Visual Basic

To remove an ACE that has been assigned to restrict object manipulation to a specific class, simply use a conditional to match the ObjectType and Trustee fields during the enumeration process, as shown in the following Visual Basic code segment:

 Dim Obj As IADs Dim ACE As AccessControlEntry Dim DACL As AccessControlList Dim SecurityDescriptor As Variant Set Obj = GetObject("LDAP://ou=Admins,dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL For Each ACE In DACL     If ((UCase(ACE.Trustee) = "ECOMMERCE2000\DMZADMIN") and (ACE.ObjectType = graphics/ccc.gif "{BF967A9C-0DE6-11D0-A285-00AA003049E2}")) Then         DACL.RemoveAce ACE     End If Next SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 
Adding an ACE to an Active Directory OU ACL with Inheritance to a Single Property for an Object Class Using Visual Basic

Just as you can restrict manipulation of objects based on object class, you can also specify which attributes a user has the right to read and modify. Once again, you simply need to assign the schemaIDGuid for the desired property to the ObjectType field and set the AccessMask field to ADS_RIGHT_DS_READ_PROP or ADS_RIGHT_DS_WRITE_PROP .

The following Visual Code segment allows users to write their own telephoneNumber attribute for objects in the Users container:

 Dim Obj As IADs Dim SecurityDescriptor As IADsSecurityDescriptor Dim ACE As AccessControlEntry Dim DACL As AccessControlList Set Obj = GetObject("LDAP://ou=Admins,dc=eCommerce2000,dc=com") Set SecurityDescriptor = Obj.Get("ntSecurityDescriptor") Set DACL = SecurityDescriptor.DiscretionaryACL Set ACE = CreateObject("AccessControlEntry") ACE.AccessMask = ADS_RIGHT_DS_READ_PROP Or ADS_RIGHT_DS_WRITE_PROP ACE.AceFlags = ADS_ACEFLAG_INHERIT_ACE ACE.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT ACE.ObjectType = "{BF967A49-0DE6-11D0-A285-00AA003049E2}" ACE.Trustee = "NT AUTHORITY\SELF" DACL.AddAce ACE SecurityDescriptor.DiscretionaryACL = DACL Obj.Put "ntSecurityDescriptor", Array(SecurityDescriptor) Obj.SetInfo 

   
Top


Windows NT. 2000 ADSI Scripting for System Administration
Windows NT/2000 ADSI Scripting for System Administration
ISBN: 1578702194
EAN: 2147483647
Year: 2000
Pages: 194
Authors: Thomas Eck

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net