**Active Directory Permissions : Security Descriptors**
 
This article of the SelfADSI tutorial explains how to read or set permissions on Active Directory objects by script. The following sections are available:
   

|   |   |
|---|---|
|[The internal structureof a Security Descriptors (SD)](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#SecurityDescriptorStructure)|[Permission Inheritance](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#PermissionInheritance)|
|[Access Control Lists (ACLs)](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACL)|[Read AD Permissions in a Script](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ReadPermissions)|
|[Access Control Entries (ACEs)](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACE)|[Set AD Permissions in a Script](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#WritePermissions)|
|[Control Flags in the SD Header](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ControlFlags)|[Remove AD Permissions in a Script](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#RemovePermissions)|
|[Flags in ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEFlags)||
|[List of permissions - Access Mask Bits in the ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#AccessMaskPermissions)||
|[Object Type GUIDs in ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEObjectTypeGUID)||
|[Inherited Type GUIDs in ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEInheritedTypeGUID)||
|[Trustees in ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#Trustees)||
   

Permissions in Active Directory are defined by so-called security descriptors, which are stored as properties directly in the AD objects. Actually, two different  
Active Directory attributes are internally structured as a security descriptor:
   

|   |   |   |
|---|---|---|
|nTSecurityDescriptor|Alle Objekte|Hier werden die Berechtigungen f?r das Objekt selbst gespeichert. Jedes Objekt hat einen eigenen Security Desriptor.|
|msExchMailboxSecurityDescriptor|Postfach-Benutzer|Diese Eigenschaft existiert nur in Microsoft Exchange-Umgebungen bei Benutzern mit Postfach. Es wird festgelegt, wer auf  <br>das betreffende Postfach zugreifen darf - allerdings nur zum Zeitpunkt der Erstellung des Postfachs. Sp?ter werden Postfachrechte  <br>nur durch dieses Attribut repr?sentiert, k?nnen jedoch nicht dar?ber gesetzt werden.|
 
The basic LDAP attribute data type for these attributes is a is [Microsoft's proprietary LDAP attribute syntax called](http://msdn.microsoft.com/en-us/library/cc223183\(v=PROT.13\).aspx) **String (NT Sec Desc)**. Basically, this is a binary format,  
but the data contents of a security descriptor can be fortunately read by scripts through the ADSI interface. The relevant objects are described in detail in the ADSI reference:

- [ADSI Reference : Security Interfaces](http://msdn.microsoft.com/en-us/library/aa746481%28v=VS.85%29.aspx)

But before we deal with the reading and setting of permissions in the Active Directory in scripting, we should take a look at the internal structures of a security descriptor.  
The exact structure of a general security descriptor value is described in these documents Micrsoft:

- [Microsoft Data Type Reference [MSDTY]](http://msdn.microsoft.com/en-us/library/cc230366%28v=PROT.10%29.aspx)
- [Technet : How Security Descriptors and Access Control Lists Work](http://technet.microsoft.com/en-us/library/cc781716%28WS.10%29.aspx#w2k3tr_acls_how_jyza)

**Note**: Security Descriptor structures are found not only at the permissions on directory objects, but also at  
permissions in the NTFS file system, registry permission or in general with all permissions on system objects  
(services, printers, etc.). This article focuses more on the specifics of the permissions in Active Directory, this  
concerns mainly the construction of [ACEs](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACE) and [Access Masks](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#AccessMaskPermissions).
   

**The internal structureof a Security Descriptors (SD)**  
The internal structure of a security descriptor is quite complex because we must consider several elements that are nested within each other:  
The **Security Descriptor** as a whole consists of a header, the owner information, and two different access lists (ACLs). Regarding these, the  
actual ACL permissions are included in the **Discretionary ACL (DACL)**. This DACL in turn consists of several **Access Control Entries (ACEs)**,  
four of which are relevant to us.

![Ein Active Directory Security Descriptor](Exported%20image%2020250808202102-0.png)  

**When creating scripts this means the following: When a script wants to read the permissions of an Active Directory , it must first read the Security**  
**Descirptor and the included DACL to get the list of ACEs. In that ACEs are the actual permissions stored. If you want to set permissions, so you have rarely to**  
**built up a security descriptor from nothing by yourself - there simply are no AD object that is not already configured with permissions. Immediately after the**  
**object creation permissions automatically result from the inheritance of the default settings. Granting or revoking permissions in scripts is thus based always**  
**on the change of the existing list of ACEs.**
 
Let us first consider the security descriptor with its construction of a header, owner information and ACLs. As mentioned above, we find a detailed description of the technical  
structure of a security descriptor in the Microsoft Technet:

- [Microsoft Data Type Reference [MSDTY] : Security Descriptor](http://msdn.microsoft.com/en-us/library/cc230297%28v=PROT.10%29.aspx)

![Struktur des Security Descriptors](Exported%20image%2020250808202106-1.png)

**Header**: A structure that includes a general revision value as well as various control bits. These flags provide information about how and of what elements the security descriptor in  
question is composed of - or will put together, if you want to create the structure with just a new Secruity descriptor. In addition, the **control flags** determine whether the permissions  
and audit settings are inherited by parent structures, or whether the inheritance is blocked in this security descriptor. Additionally,  
the header technically still contain offset addresses to determine the internal storage addresses of other components of the security descriptor.
 
**Owner**: The Object owner - technically in the form of a [SID (security identifier)](http://www.selfadsi.org/deep-inside/microsoft-sid-attributes.htm)​​. The owner is the user account that created the object. Owners may always change the permissions  
on the object. A special feature: Did a member of the pre-defined group of administrators create the object, then this group is registered as owner. When this field is set in a script,  
you can directly use a Windows login name, eg 'SELFADSI\pfoeckel'.
 
**Owner Group**: The group of the object owners - technically in the form of a [SID (security identifier)](http://www.selfadsi.org/deep-inside/microsoft-sid-attributes.htm)​​. The group owner is rarely  
used in practice, usually only the owner plays a role - the owner group is simply the primary group of the owner.
 
**SACL - System Access Control List**: The SACL is the list in which the auditing settings for that object are stored (**Which requests by whom are monitored and how?**).  
Only those who have the policy privilege '**Manage Auditing and Security Log'** on the domain controllers can  
read or write the SACL. Also keep in mind that there are still global audit flags which must be active for the directory service auditing on a domain controller (done via GPO).
 
**DACL - Discretionary Access Control List**: The DACL contains the access permissions on an object (**Who can do what?**). This is list with the actual permissions.  
It can always be changed by the owner of the object and of all those who are authorized with **WRITE_DAC** (see [list of Access Masks Bits](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#AccessMaskPermissions)) on the object. To read the  
Discrentionary Access Control, you need the **READ_CONTROL** right.
   

**Access Control Lists (ACLs)**  
An Access List (regardless whether a System ACL for auditing or a Discretionary ACL for permissions) always consists of a header and a number of Acces Control Entries (ACEs).  
The exact technical structure of an ACL is described here:

- [Microsoft Data Type Reference [MSDTY] : ACL](http://msdn.microsoft.com/en-us/library/cc230297%28v=PROT.10%29.aspx)

![Struktur einer Access Control List](Exported%20image%2020250808202107-2.png)

It should be noted that the revision value for an Active Directory ACL must always 4. The ACEs are so to speak the individual permissions that we see in the  
normal administrative management tool:
 ![Access Control Lists in der GUI](Exported%20image%2020250808202108-3.png)   
**Access Control Entries (ACEs)**  
An ACE is the config strucutre for a single permision grant (or denial of rights) for a particular user or a particular group. There are many different types of ACEs, but in the permissions for  
Active Directory, there are only four different types of meaning, two each for granting and the denying of permissions. The detailed technical structure of ACEs is described here:

- [Microsoft Data Type Reference [MSDTY] : ACE](http://msdn.microsoft.com/en-us/library/cc230295\(v=PROT.10\).aspx)

There is a simple ACE form, which can be used to grant/revoke permissions for the entire Obekt (including standard inheritance). There are still the more complex forms of the so-called   
Object ACEs. Because in the following cases, the simple form of ACEs are not enough:

- Permissions do not apply to the entire object, but only for a particular attribute or set of attributes (eg, write permission to the address information of a user object).
- For permission to create/delete sub-objects, when this shall concerns only certain classes (eg the right to create child groups).
- Special permission must be granted (some of which are maybe specific for other applications), eg the right to reset user passwords, or the right to send mail on behalf of another
- user, or the right to perform an AD data replication.
- Rights must be assigned to produce a self-reference to the object, eg the right to set yourself in a group as a member.

The four **ACE-Types** which are relevant for us, in detail:
 
**Access Allowed ACE:**

![Access Allowed ACE](Exported%20image%2020250808202108-4.png)

In this ACE the type field is always set to 1. It is designed for easy assignment of rights to the entire object. The ACE flags determine whether this is an inherited  
or explicitly given permission. An authorization of the ACE type 0 is always passed down to child objects.
   

**Access Allowed Object ACE:**

![Access Allowed Object ACE](Exported%20image%2020250808202109-5.png)

In this ACE the type field is to always set to 5. This object ACE can set both ACE special rights or limited rights, eg granted only for certain attributes (=\> [ObjectType GUID](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEObjectTypeGUID))  
as well as a special inheritance can be configured so they can inherit only certain classes of objects that right, or that the permission applies only to the object itself and is  
not inherited (=\> [Interhited Type GUID](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEInheritedTypeGUID)). The flags field indicates whether there is an object type field or a inherited type field, or both.
   

**Access Denied ACE:**

![Access Denied ACE](Exported%20image%2020250808202110-6.png)

In this type of ACE is to always set to 1. It is designed for simple revoking of permissions for the entire object. The ACE flags determine whether this is an  
inherited or explicitly assigned object revoking. A denial of the ACE type 5 is always propgated down to child objects.
 
   
**Access Denied Object ACE:**

![Access Denied Object ACE](Exported%20image%2020250808202110-7.png)

In this ACE the type field is to always set to 6. This object ACE can revoke both ACE special rights or limited rights, eg revoked only for certain attributes (=\> [ObjectType GUID](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEObjectTypeGUID))  
as well as a special inheritance can be configured so they can inherit only certain classes of objects that right, or that the permission denial applies only to the object itself  
and is not inherited (=\> [Interhited Type GUID](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEInheritedTypeGUID)). The flags field indicates whether there is an object type field or a inherited type field, or both.
   

**Control Flags in the SD Header**  
The header of a security descriptor contains the so-called control flags. Many of the flags do not matter when dealing with normal Active Directory permissions.  
The exact structure of the control flag is described here:

- [Microsoft Data Type Reference [MSDTY] : Security Descriptor](http://msdn.microsoft.com/en-us/library/cc230366\(v=PROT.10\).aspx)

If you **read** a security descriptor, the following flags play an important role:
   

|   |   |   |
|---|---|---|
|**Control Flag**|**Bit Value**|**Meaning**|
|DACL_AUTO_INHERITED|1024|The security descriptor is created through normal inheritance.|
|DACL_PROTECTED|4096|The security descriptor does NOT inherit permissions from parent objects. So if this flag is set, the rights inheritance for that AD object is disabled.|

   
If you **write or newly create** a Security Descriptor, the following flags are important:
   

|   |   |   |
|---|---|---|
|**Control Flag**|**Bit Value**|**Meaning**|
|OWNER_DEFAULTED|1|The Owner information is generated automatically. You can create a new Security Descriptor with this flag and does not need extra specify  <br>the Owner. In this case, the SID of the creating user himself is the owner (Exception: If a member of the default administrators creates an  <br>object, then the group and not the user account is the owner).|
|GROUP_DEFAULTED|2|The Owner Group information is generated automatically. You can create a new security descriptor with this flag, then an extra group ID  <br>for the owner do not need to be specified. In this case, the primary group of the creating user is used as the owner group.|
|DACL_DEFAULTED|8|The DACL (the permissions) will be automatically inherited from the parent container/object. You can use this flag to create a new security  <br>descriptor and simply inherit its rights without expicitely specifiying any permissions.|
|SACL_DEFAULTED|32|The SACL (the aduit settings) will be automatically inherited from the parent container/object. You can use this flag to create a new security  <br>descriptor and simply inherit its audit settings without expicitely specifiying any settings.|
 
**Flags in ACEs**  
The flags which are described here are part of every single Access Control Entry. So it may exist many times within one security descriptor. **Caution, risk of confusion**:  
In ACEs there are two types of flags: The "**ACE Flags**" and the "**Flags**". They control the inheritance settings of the regarding ACEs and may activate any existing Object type fields.
 
In every ACE there are "**ACE Flags**" that are part of the technical ACE header. These flags determine the mode of inheritance of new ACEs - or indicate the inheritance situation  
when you read the relevant ACE.
   

|   |   |   |   |   |
|---|---|---|---|---|
|**Flag**|**Abbreviation**  <br>**in** **SDDL**|**Value**  <br>**(dez)**|**Value**  <br>**(hex)**|**Explanation**|
|ADS_ACEFLAG_INHERIT_ACE  <br>  also called  <br>CONTAINER_INHERIT_ACE|**CI**|2|2|Child objects inherit the permissions. The flag 'Object Inherit (OI)' which plays an important  <br>role in the permissions for files and directories, is not required for AD rights. In AD permissions  <br>only the "Container Inherit (CI)" flag is used. It refers to all objects, even those who do not have  <br>sub-objects to themselves.|
|ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE|**NP**|4|4|Only the immediate child objects inherit the permissions. Can be set as an addition to the CI flag.|
|ADS_ACEFLAG_INHERIT_ONLY_ACE|**IO**|8|8|The permission is valid only for the child objects, but not for the actual object itself. Can be set as  <br>an addition to the CI flag.|
|ADS_ACEFLAG_INHERITED_ACE|**ID**|16|10|This flag indicates that this is a permission inherited from the top down. This flag can not be set,  <br>but can be checked to find inherited rights.|
 
There are also other flag values ​​they either don't exist in Active Directory ACLs, or aren't important for permissions, but for the audit settings in SACLs. A complete documentation of the  
flags can be found here:

- [Microsoft Data Type Reference [MSDTY] : ACE Flags](http://msdn.microsoft.com/en-us/library/cc230296%28v=prot.10%29.aspx)
- [Microsoft ADSI Reference :](http://msdn.microsoft.com/en-us/library/aa772285\(v=VS.85\).aspx) [ADS_ACEFLAG_ENUM](http://msdn.microsoft.com/en-us/library/aa772242%28v=vs.85%29.aspx)

The propagation of the permission to child objects can be specified more detailed in the more complex object ACEs (ACE type 5 and 6). There it can be determined for example whether  
such a right should only apply to child objects users, or only to groups. These must be placed in the appropriate ACEs the "Inherited Type". Whether this is the case, you can see in the  
so-called '**Flags**' field:
   

|   |   |   |
|---|---|---|
|**Flag**|**Bit Value**|**Meaning**|
|OBJECT_TYPE_PRESENT|1|The [Object Type field](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEObjectTypeGUID) in the ACE exists and contains an Object GUID with the following meaning<br><br>- For permission to create and delete child objects, the regarding object must be specified here. In the Object Type field,<br>- there is the GUID of an object class from the AD schema.<br>- For permissions to read and write properties, the attribute or the property set are given here to which the right relates. In the<br>- Object Type field, there is an attribute GUID from the schema or the GUID of a property sets from the [AD configuration partition](http://www.selfadsi.org/adsdb.htm) <br>- (container "Extended Rights").<br>- Regarding extended rights, the specific permission can be determined. In the Object Type field, there is an extended rights GUID<br>- from the [AD configuration partition](http://www.selfadsi.org/adsdb.htm) (container "Extended Rights").|
|INHERITED_OBJECT_TYPE_PRESENT|2|The [Inherited Object Type field](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEInheritedTypeGUID) in the ACE exists and contains an Object GUID of an object class from the AD schema.|

A complete documentation of the flags can be found here:

- [Microsoft ADSI Reference :](http://msdn.microsoft.com/en-us/library/aa772285\(v=VS.85\).aspx) [ADS_FLAGTYPE_ENUM](http://msdn.microsoft.com/en-us/library/aa772259\(v=vs.85\).aspx)
 
**List of permissions - Access Mask Bits in the ACEs**  
This is a list of permissions on Active Directory directory objects, as contained in the above-described access control entries (ACEs). For some access masks, various bits can  
be set simultaneously, eg there can be defined in a single ACE that someone has the permission to create user objects as well as to delete them (CC + DC). However,  
there are obvious limitations, because in a single object-ACE is room for exactly one ObjectType GUID, so it's as not possible to set the permission to delete user objects  
and for writing the address properties in the same ACE.  
   
The technical description of the Access mask bits from Microsoft:

- [Microsoft Data Type Reference [MSDTY] : Access Mask](http://msdn.microsoft.com/en-us/library/cc230294\(v=PROT.10\).aspx)
- [Microsoft ADSI Reference : ADS_RIGHTS_ENUM](http://msdn.microsoft.com/en-us/library/aa772285\(v=VS.85\).aspx)
 
|   |   |   |   |   |
|---|---|---|---|---|
|**Permission**|**Abbreviation**  <br>**in** **SDDL**|**Value**|**Value**  <br>**(hex)**|**Explanation**|
|ADS_RIGHT_DS_CREATE_CHILD|**CC**|1|1|Create child Objects. This right can be restricted to certain classes of objects. In this case the ACE property  <br>ObjectType must be set to the GUID of the appropriate object class (SchemaIDGuid in the class definition of the  <br>schema).|
|ADS_RIGHT_DS_DELETE_CHILD|**DC**|2|2|Delete child Objects. This right can be restricted to certain classes of objects. In this case the ACE property  <br>ObjectType must be set to the GUID of the appropriate object class (SchemaIDGuid in the class definition of  <br>the schema).|
|ADS_RIGHT_ACTRL_DS_LIST|**LC**|4|4|List child objects.|
|ADS_RIGHT_DS_SELF|**WS**<br><br>  <br><br>(auch SW)|8|8|Perform so called 'Validated Writes'. This right can be restricted to certain Validated Writes, eg 'Add yourself as  <br>a member', 'Set the own DNS address' etc. In this case the ACE property ObjectType must be the GUID of the  <br>appropriate ExtendedRights included (RightsGuid value from the Configuration Partition \ Extended-Rights).|
|ADS_RIGHT_DS_READ_PROP|**RP**|16|10|Read properties / attribute values of the regarding object. In this case the ACE property ObjectType must be  <br>set to the GUID of the appropriate attribute (SchemaIDGuid in the attribute definition of the schema).|
|ADS_RIGHT_DS_WRITE_PROP|**WP**|32|20|Write properties / set attribute values of the regarding object. In this case the ACE property ObjectType must  <br>be set to the GUID of the appropriate attribute (SchemaIDGuid in the attribute definition of the schema).|
|ADS_RIGHT_DS_DELETE_TREE|**DT**|64|40|Delete all subordinate child objects, no matter which permission is configured in the regarding sub structure.|
|ADS_RIGHT_DS_LIST_OBJECT|**LO**|128|80|List the object in question, although the general permission "ADS_RIGHT_ACTRL_DS_LIST" was maybe denied  <br>in the regarding container. It's kind of an overwrite for individual objects that are visible, although the rest of the  <br>container is hidden. This permission is effective only when [the third dsHeuristics flag](http://msdn.microsoft.com/en-us/library/ms675656\(v=VS.85\).aspx) is set to 1.|
|ADS_RIGHT_DS_CONTROL_ACCESS|**CA**<br><br>  <br><br>(auch CR)|256|100|Perform extended rights. This can be further restricted to specific extended rights, such as "Reset Password",  <br>"Change Rid Master", "Replication Synchronization", "Migrate SID History", etc. In this case the ACE property  <br>ObjectType must set to the GUID of the appropriate ExtendedRights (RightsGuid value from the Configuration  <br>Partition \ Extended-Rights).|
|ADS_RIGHT_DELETE|**DE**|65536|10000|Delete the regarding object.|
|ADS_RIGHT_READ_CONTROL|**RC**|131072|20000|Read the permissions (DACL) and the owner properties of the regarding object.|
|ADS_RIGHT_WRITE_DAC|**WD**|262144|40000|Change The permissions (DACL) of the regarding object. Note that the owner can always change the DACL, even  <br>if he do not have explicitly this right.|
|ADS_RIGHT_WRITE_OWNER|**WO**|524288|80000|Change the owner property of the regarding object.|
|ADS_RIGHT_SYNCHRONIZE|**SY**|1048576|100000|You will not see this permission when you deal with AD object rights - nor set this permission flag by yourself for  <br>any AD object. It's a generic permission and not required for Active Directory objects.|
|ADS_RIGHT_ACCESS_SYSTEM_SECURITY|**AS**|16777216|1000000|You will not see this permission when you deal with AD object rights - nor set this permission flag by yourself for  <br>any AD object. This bit has a meaning Only in SACLs audit settings: You can specify that the access to the SACL  <br>itsel fis audited .|
|ADS_RIGHT_GENERIC_ALL|**GA**|268435456|10000000|You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object  <br>permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:  <br>ADS_RIGHT_DS_CREATE_CHILD +  <br>ADS_RIGHT_DS_DELETE_CHILD +  <br>ADS_RIGHT_ACTRL_DS_LIST +  <br>ADS_RIGHT_DS_SELF +  <br>ADS_RIGHT_DS_READ_PROP +  <br>ADS_RIGHT_DS_WRITE_PROP +  <br>ADS_RIGHT_DS_DELETE_TREE +  <br>ADS_RIGHT_DS_LIST_OBJECT + ADS_RIGHT_DS_CONTROL_ACCESS +  <br>ADS_RIGHT_DELETE +  <br>ADS_RIGHT_READ_CONTROL +  <br>ADS_RIGHT_WRITE_DAC +  <br>ADS_RIGHT_WRITE_OWNER|
|ADS_RIGHT_GENERIC_EXECUTE|**GX**|536870912|20000000|You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object  <br>permissions, the system is internally translating this bit into the ADS_RIGHT_ACTRL_DS_LIST permission (list chlid objects):|
|ADS_RIGHT_GENERIC_WRITE|**GW**|1073741824|40000000|You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object  <br>permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:  <br>ADS_RIGHT_DS_SELF +  <br>ADS_RIGHT_DS_WRITE_PROP +  <br>ADS_RIGHT_READ_CONTROL|
|ADS_RIGHT_GENERIC_READ|**GR**|2147483648|80000000|You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object  <br>permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:  <br>ADS_RIGHT_DS_READ_PROP +  <br>ADS_RIGHT_ACTRL_DS_LIST +  <br>ADS_RIGHT_READ_CONTROL|
 
**Object Type GUIDs in ACEs**
 
In complex ACEs of type 5 and 6, there are a field named '**ObjectType GUID**'. There may be three cases in which this field is used. In these situations, the flag **OBJECT_TYPE_PRESENT** (1)  
in the respective access control entry must be set. By the way, the GUID here can be read and set in script as a simple character string.

- For **CC** / **DC** permissions (Create Child / Delete Child), the child object class can be specified here. In this case there is the GUID of an object class from the AD schema the Object
- Type field (SchemaIDGuid value in the class definition of the schema). A few important GUID values:==￼==

|   |   |
|---|---|
|**Object Class**|**GUID**|
|Organizational Units|bf967aa5-0de6-11d0-a285-00aa003049e2|
|Computer|bf967a86-0de6-11d0-a285-00aa003049e2|
|User|bf967aba-0de6-11d0-a285-00aa003049e2|
|Groups|bf967a9c-0de6-11d0-a285-00aa003049e2|
|Contacts|5cb41ed0-0e4c-11d0-a286-00aa003049e2|

- For **RP** / **WP** permission (Read Property / Write Property) here, the attribute or the property set can be specified here. In this case the Object Type field must be filled with
- a GUID of an attribute from the AD schema or the property set GUID from the configuration partition (container "Extended Rights") in . A few important attribute GUID values:==￼==

|   |   |
|---|---|
|**Attribute**|**GUID**|
|department|bf96794f-0de6-11d0-a285-00aa003049e2|
|description|bf967950-0de6-11d0-a285-00aa003049e2|
|displayName|bf967953-0de6-11d0-a285-00aa003049e2|
|givenName|f0f8ff8e-1191-11d0-a060-00aa006c33ed|
|mail|bf967961-0de6-11d0-a285-00aa003049e2|
|member|bf9679c0-0de6-11d0-a285-00aa003049e2|
|physicalDeliveryOfficeName|bf9679f7-0de6-11d0-a285-00aa003049e2|
|proxyAddresses|bf967a06-0de6-11d0-a285-00aa003049e2|
|sn|bf967a41-0de6-11d0-a285-00aa003049e2|
|telephoneNumber|bf967a49-0de6-11d0-a285-00aa003049e2|
 
A few examples for property set GUID values:
   

|   |   |
|---|---|
|**Property Set**|**GUID**|
|General Information|59ba2f42-79a2-11d0-9020-00c04fc2d3cf|
|Personal Information|77b5b886-944a-11d1-aebd-0000f80367c1|
|Private Information|91e647de-d96f-4b70-9557-d63ff4f3ccd8|
|Public Information|e48d0154-bcf8-11d1-8702-00c04fb96050|

- For extended **CA** rights (Control Access), the specific permission be specified here. In this case, the Object Type field must be filled with a GUID of an extended right from the
- config partition (container "Extended Rights"). Some examples of ExtendedRight GUIDs:==￼==

|   |   |
|---|---|
|**Extended Right**|**GUID**|
|Administer Exchange information store|d74a8762-22b9-11d3-aa62-00c04f8eedd8|
|Create Inbound Forest Trust|e2a36dc9-ae17-47c3-b58b-be34c55ba633|
|Change Password|ab721a53-1e2f-11d0-9819-00aa0040529b|
|Migrate SID History|ba33815a-4f93-4c76-87f3-57574bff8109|
|Reanimate Tombstones|45ec5156-db7e-47bb-b53f-dbeb2d03c40f|
|Receive As|ab721a56-1e2f-11d0-9819-00aa0040529b|
|Replication Synchronization|1131f6ab-9c07-11d1-f79f-00c04fc2dcd2|
|Reset Password|00299570-246d-11d0-a768-00aa006e0529|
|Send As|ab721a54-1e2f-11d0-9819-00aa0040529b|
|Unexpire Password|ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501|
|View Exchange information store status|d74a875e-22b9-11d3-aa62-00c04f8eedd8|
      

**Inherited Type GUIDs in ACEs**  
In complex ACEs of type 5 and 6, there are field named '**Inherited Object Type GUID**'. It can be used to pass on the privilege only to specific classes of objects  
(eg "The display name can be changed, but only in groups"). In this case, the flag **INHERITED_OBJECT_TYPE_PRESENT** (2) in the respective access control entry  
must be set. In th the Inherited Object Type field, there is the GUID of an object class from the AD schema (SchemaIDGuid value in the class definition of the schema).  
By the way, the GUID here can be read and set in script as a simple character string. A few important object class GUID values:
    
|   |   |
|---|---|
|**Objektklasse**|**GUID**|
|Organizational Units|bf967aa5-0de6-11d0-a285-00aa003049e2|
|Computer|bf967a86-0de6-11d0-a285-00aa003049e2|
|User|bf967aba-0de6-11d0-a285-00aa003049e2|
|Groups|bf967a9c-0de6-11d0-a285-00aa003049e2|
|Contacts|5cb41ed0-0e4c-11d0-a286-00aa003049e2|
 
**Trustees in ACEs**  
An Access Control Entriy (ACEs) always contains always the trustee, that means the account or group for which permissions are granted or revoked. When setting and reading trustee  
values, there may be two forms used:

- If you run a script to read or set permissions in the same Active Directory domain, then trustees will simply be represented in the NetBIOS notation '**DOMAIN\username**'
- or '**DOMAIN\groupname**'.
- If you are not automatically logged in the domain with your script, you have to use explicit credentials. Trustees must be specified then as technical security identifiers (SIDs),
- eg '**S-1-5-21-1621763826-2590103247-2238570322-1113**'. You must of course know how to get the SID of a user or group.

There is a detailed SelfADSI tuorial article about the structure of Microsoft SIDs and how to deal with them: "[Microsoft Security Identifier (SID) Attribute](http://www.selfadsi.org/deep-inside/microsoft-sid-attributes.htm)".
 
**Permission Inheritance**  
In the inheritance of permissions for Active Directory objects, there are several interesting aspects:

1. You may want to examine directory object in a script and check, whether the inheritance of permissions was basically disabled / blocked. Here you only need to check the 
2. DACL_PROTECTED bit in the [control flags](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ControlFlags) of the entire security descriptor.
3. You may want to find out via script for a single existing permission, whether it was inherited from the top down, or set explicitly. You can check the relevant Access Control Entry,
4. whether **INHERITED_ACE** the flag is set there in the [ACEFlags](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEFlags).
5. If you want to set new permissions by script, you want to determine whether and how these rights will be inherited by child objects. A large role is played by
6. the [flags in the ACE generated by you](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm#ACEFlags). You can use this matrix:￼
![Vererbungsreglen fr Active Directory Access Contro...](Exported%20image%2020250808202114-8.png)
   

**Read Active Directory Permissions in a Script**  
Here is an example how to read the permissions of a single Active Directory object. For this purpose we have to read and evaluate the LDAP attribute **nTSecurityDesriptor**:  
**'you have to use an object of your own environment!****￼****Set obj = GetObject("LDAP://CN=test,OU=users,OU=example,DC=ldapexplorer,DC=com")** **￼**  
**Const ADS_FLAG_OBJECT_TYPE_PRESENT = 1** **￼****Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = 2** **￼**  
**Set objACL = obj.get("nTSecurityDescriptor")** **￼****Set objDACL = objACL.DiscretionaryAcl** **￼**  
**WScript.Echo obj.distinguishedname & vbCrLf** **￼**  
**Set ace = CreateObject("AccessControlEntry")** **￼****For Each ace In objDACL** **￼** **WScript.Echo "__________________________________________________________________________________________________"** **￼** **￼** **'pure ACE data output** **￼** **output = "ACEType: " & ace.AceType & ", ACEFlags: " & ace.AceFlags & ", Mask: " & ace.AccessMask** **￼** **If (ace.AceType = 5) Or (ace.AceType = 6) Then** **￼** **output = output & ", Flags: " & ace.Flags** **￼**  
**If ((ace.Flags And ADS_FLAG_OBJECT_TYPE_PRESENT) \<\> 0) Then** **￼**    **output = output & ", ObjectTypeGUID: " & ace.ObjectType** **￼** **End If** **￼**  
**If ((ace.Flags And ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT) \<\> 0) Then** **￼**     **output = output & ", InheritedObjectTypeGUID: " & ace.InheritedObjectType** **￼** **End If** **￼** **End If** **￼** **output = output & ", Trustee: " & ace.Trustee** **￼** **WScript.Echo output** **￼****Next**  
[Download Script](http://www.selfadsi.org/scripts/read-object-permissions-basic.vbs.txt)

[![Download Icon](Exported%20image%2020250808202115-9.png)](http://www.selfadsi.org/scripts/read-object-permissions-basic.vbs.txt)  

The story becomes more complicated if you want a detailed analysis of the permissions and propagated inheritance. This is because the script have to seek and decode  
all the regarding GUIDs in the schema or the config partition. The two functions **decode_permission** and **decode_propagation** are used for this.
 
This script has to be run as an administrator on a system that is member in the regarding domain.  
**'you have to use an object of your own environment!****￼****Set obj = GetObject("LDAP://CN=test,OU=users,OU=example,DC=ldapexplorer,DC=com")****￼**  
**Const ADS_ACETYPE_ACCESS_ALLOWED = 0****￼****Const ADS_ACETYPE_ACCESS_DENIED = 1****￼****Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 5****￼****Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = 6****￼**  
**Const ADS_ACEFLAG_INHERITED_ACE = &H10****￼****Const ADS_ACEFLAG_INHERIT_ACE = &H2****￼****Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &H4****￼****Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8****￼**  
**Const ADS_RIGHT_DS_CREATE_CHILD = &H1****￼****Const ADS_RIGHT_DS_DELETE_CHILD = &H2****￼****Const ADS_RIGHT_ACTRL_DS_LIST = &H4****￼****Const ADS_RIGHT_DS_SELF = &H8****￼****Const ADS_RIGHT_DS_READ_PROP = &H10****￼****Const ADS_RIGHT_DS_WRITE_PROP = &H20****￼****Const ADS_RIGHT_DS_DELETE_TREE = &H40****￼****Const ADS_RIGHT_DS_LIST_OBJECT = &H80****￼****Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100****￼****Const ADS_RIGHT_DELETE = &H10000****￼****Const ADS_RIGHT_READ_CONTROL = &H20000****￼****Const ADS_RIGHT_WRITE_DAC = &H40000****￼****Const ADS_RIGHT_WRITE_OWNER = &H80000****￼****Const ADS_RIGHT_GENERIC_ALL = &H10000000****￼****Const ADS_RIGHT_GENERIC_WRITE = &H40000000****￼****Const ADS_RIGHT_GENERIC_READ = &H80000000****￼**  
**Const ADS_FLAG_OBJECT_TYPE_PRESENT = 1****￼****Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = 2****￼**  
**Set objACL = obj.get("nTSecurityDescriptor")****￼****Set objDACL = objACL.DiscretionaryAcl****￼**  
**WScript.Echo obj.distinguishedname & vbCrLf****￼**  
**Set ace = CreateObject("AccessControlEntry")** **￼****For Each ace In objDACL****￼** **WScript.Echo "__________________________________________________________________________________________________"****￼** **￼** **'1) -\> first: pure ACE data output****￼** **output = "ACEType: " & ace.AceType & ", ACEFlags: " & ace.AceFlags & ", Mask: " & ace.AccessMask** **￼** **If (ace.AceType = 5) Or (ace.AceType = 6) Then****￼** **output = output & ", Flags: " & ace.Flags****￼**  
**If ((ace.Flags And ADS_FLAG_OBJECT_TYPE_PRESENT) \<\> 0) Then****￼**    **output = output & ", ObjectTypeGUID: " & ace.ObjectType****￼** **End If****￼**  
**If ((ace.Flags And ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT) \<\> 0) Then****￼**     **output = output & ", InheritedObjectTypeGUID: " & ace.InheritedObjectType****￼** **End If****￼** **End If****￼** **output = output & ", Trustee: " & ace.Trustee****￼** **WScript.Echo output****￼**  
**'2) -\> decode ACE type****￼** **If ((ace.AceFlags And ADS_ACEFLAG_INHERITED_ACE) \<\> 0) Then** **￼** **WScript.Echo " Inherited"****￼** **Else****￼** **WScript.Echo " Directly"****￼** **End If****￼**  
**If (ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED) Or (ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT) Then****￼** **output = "Grant "****￼** **Else** **￼** **output = "Deny "****￼** **End If****￼** **output = output & "to " & ace.Trustee** **￼** **WScript.Echo " " & output****￼**  
**'3) -\> decode permissions****￼** **WScript.Echo " " & decode_permission(ace.AccessMask, ace.ObjectType)****￼**  
**'4) -\> decode inheritance****￼** **WScript.Echo " " & decode_propagation(ace.AceFlags, ace.InheritedObjectType)****￼****Next****￼**  
**Function decode_permission(mask, guid)****￼** **'converts an access mask value to a readable string****￼**  
**classNeeded = (((mask And ADS_RIGHT_DS_CREATE_CHILD) \<\> 0) Or ((mask And ADS_RIGHT_DS_DELETE_CHILD) \<\> 0))****￼** **attributeNeeded = (((mask And ADS_RIGHT_DS_READ_PROP) \<\> 0) Or ((mask And ADS_RIGHT_DS_WRITE_PROP) \<\> 0))****￼** **extendedNeeded = ((mask And ADS_RIGHT_DS_CONTROL_ACCESS) \<\> 0)****￼** **validatedNeeded = ((mask And ADS_RIGHT_DS_SELF) \<\> 0)****￼** **guidExists = (Len(guid) \> 0)****￼**  
**'handle objectTypeGuide...** **￼** **If (guidExists) Then****￼** **If (classNeeded And attributeNeeded) Then****￼** **objectclass = guid_to_class(ace.ObjectType)****￼** **attribute = guid_to_attribute(ace.ObjectType)****￼**  
**foundNoClass = (Left(objectclass, 1) = "{")** **￼** **foundNoAttribute = (Left(attribute, 1) = "{")** **￼**  
**If (foundNoClass And foundNoAttribute) Then****￼** **objectclass = " (" & objectclass & ")"****￼** **attribute = " (" & attribute & ")"****￼** **ElseIf (foundNoClass) Then** **￼** **objectclass = " (All Classes)"****￼** **attribute = "(" & attribute & ")"** **￼** **Else****￼** **objectclass = " (" & objectclass & ")"****￼** **attribute = " (All Properties)"****￼** **End If****￼** **ElseIf (classNeeded) Then****￼** **objectclass = " (" & guid_to_class(ace.ObjectType) & ")"****￼** **ElseIf (attributeNeeded) Then****￼** **attribute = " (" & guid_to_attribute(ace.ObjectType) & ")"****￼** **ElseIf (extendedNeeded) Then****￼** **extended = " (" & guid_to_right(ace.ObjectType) & ")"****￼** **ElseIf (validatedNeeded) Then****￼** **validated = " (" & guid_to_right(ace.ObjectType) & ")"****￼** **End If****￼** **Else****￼** **objectclass = " (All Classes)"****￼** **attribute = " (All Properties)"****￼** **extended = " (All Extended Rights)"****￼** **validated = " (All validated Rights)"****￼** **End If****￼**  
**decode_permission = ""****￼**  
**If ((mask And ADS_RIGHT_DS_CREATE_CHILD) \<\> 0) Then****￼** **decode_permission = decode_permission & vbcrlf & " Create Child" & objectclass****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_DELETE_CHILD) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Delete Child" & objectclass****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_ACTRL_DS_LIST) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " List Childs"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_SELF) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Validated Write" & validated****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_READ_PROP) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Read Property" & attribute****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_WRITE_PROP) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Write Property" & attribute****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_DELETE_TREE) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Delete Tree"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_LIST_OBJECT) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " List Object"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DS_CONTROL_ACCESS) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Control Access" & extended****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_DELETE) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Delete"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_READ_CONTROL) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Read Control"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_WRITE_DAC) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & " Write DAC"****￼** **End If****￼**  
**If ((mask And ADS_RIGHT_WRITE_OWNER) \<\> 0) Then** **￼** **decode_permission = decode_permission & vbcrlf & "Write Owner"****￼** **End If****￼**  
**If (Len(decode_permission) \> 1) Then** **￼** **decode_permission = Mid(decode_permission, 7)****￼** **End If****￼****End Function****￼**  
**Function decode_propagation(flags, guid)****￼** **'converts the ACE inheritance configuration to child objects in the corresponding readable string****￼**  
**guidExists = (Len(guid) \> 0)****￼** **decode_propagation = ""****￼** **If ((flags And ADS_ACEFLAG_INHERIT_ACE) = 0) Then****￼** **decode_propagation = "This Object Only"****￼** **Else****￼** **If ((flags And ADS_ACEFLAG_INHERIT_ONLY_ACE) = 0) Then****￼** **decode_propagation = decode_propagation & "Only "****￼** **Else****￼** **decode_propagation = "This object and "****￼** **End If****￼**  
**If ((flags And ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE) = 0) Then** **￼** **decode_propagation = decode_propagation & "only direct child objects"****￼** **Else****￼** **decode_propagation = decode_propagation & "child objects"****￼** **End If****￼**  
**If (guidExists) Then****￼** **decode_propagation = decode_propagation & " (" & guid_to_class(guid) & ")"****￼** **End If****￼** **End If****￼****End Function****￼**  
**Function guid_to_class(guidString)****￼** **'converts an objectclass schema-GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" in the name of a class****￼**  
**'create search filter****￼** **guidFilter = "(&(objectClass=classSchema)(schemaIDGUID=" & guid_to_filter(guidString) & "))"****￼**  
**'evaluate the schema path****￼** **Set rootDSE = GetObject("LDAP://rootDSE")** **￼** **schemaDN = rootDSE.Get("schemaNamingContext")****￼**  
**'search class****￼** **Set ado = CreateObject("ADODB.Connection")****￼** **ado.Provider = "ADSDSOObject"****￼** **ado.Open "ADSearch"** **￼** **On Error Resume Next****￼** **Set classObj = ado.Execute("\<LDAP://" & schemaDN & "\>;" & guidFilter & ";lDAPDisplayName;onelevel")****￼** **If (Err.Number = 0) And (classObj.RecordCount = 1) Then****￼** **guid_to_class = CStr(classObj.Fields(0).Value)****￼** **Else****￼** **guid_to_class = Mid(guidString, 2, Len(guidString) - 2)****￼** **End If****￼****End Function****￼**  
**Function guid_to_attribute(guidString)****￼** **'converts an objectclass schema-GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" to ...****￼** **'...the name of the corresponding attribute (or property sets) name****￼**  
**'create search filter** **￼** **guidFilter = "(&(objectClass=attributeSchema)(schemaIDGUID=" & guid_to_filter(guidString) & "))"****￼**  
**'evaluate the schema path****￼** **Set rootDSE = GetObject("LDAP://rootDSE")** **￼** **schemaDN = rootDSE.Get("schemaNamingContext")****￼**  
**'search attribute****￼** **Set ado = CreateObject("ADODB.Connection")****￼** **ado.Provider = "ADSDSOObject"****￼** **ado.Open "ADSearch"** **￼** **On Error Resume Next****￼** **Set classObj = ado.Execute("\<LDAP://" & schemaDN & "\>;" & guidFilter & ";lDAPDisplayName;onelevel")****￼** **If (Err.Number = 0) And (classObj.RecordCount = 1) Then****￼** **guid_to_attribute = CStr(classObj.Fields(0).Value)****￼** **Else****￼** **'no result =\> we search for a property set in the config partition****￼** **configDN = rootDSE.Get("configurationNamingContext")****￼** **extendedDN = "CN=Extended-Rights," & configDN****￼** **guidString = Mid(guidString, 2, Len(guidString) - 2)****￼** **guidFilter = "(&(rightsGuid=" & guidString & ")(validAccesses=48))"****￼**  
**Err.Clear****￼** **Set classObj = ado.Execute("\<LDAP://" & extendedDN & "\>;" & guidFilter & ";displayName;onelevel")****￼** **If (Err.Number = 0) And (classObj.RecordCount = 1) Then****￼** **guid_to_attribute = CStr(classObj.Fields(0).Value)****￼** **Else****￼** **guid_to_attribute = guidString****￼** **End If****￼** **End If****￼****End Function****￼**  
**Function guid_to_right(guidString)****￼** **'converts an objectclass schema-GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" to the name****￼** **'...of the extended rights / validated write****￼**  
**'create search filter****￼** **guidString = Mid(guidString, 2, Len(guidString) - 2)** **￼** **guidFilter = "(rightsGuid=" & guidString & ")"****￼**  
**'evaluate the path to the extended rights container****￼** **Set rootDSE = GetObject("LDAP://rootDSE")** **￼** **configDN = rootDSE.Get("configurationNamingContext")****￼** **extendedDN = "CN=Extended-Rights," & configDN****￼**  
**'search extended right****￼** **Set ado = CreateObject("ADODB.Connection")****￼** **ado.Provider = "ADSDSOObject"****￼** **ado.Open "ADSearch"** **￼** **On Error Resume Next****￼** **Set classObj = ado.Execute("\<LDAP://" & extendedDN & "\>;" & guidFilter & ";displayName;onelevel")****￼** **If (Err.Number = 0) And (classObj.RecordCount = 1) Then****￼** **guid_to_right = CStr(classObj.Fields(0).Value)****￼** **Else****￼** **guid_to_right = guidString****￼** **End If****￼****End Function****￼**  
**Function guid_to_filter(guidString)****￼** **'converts an objectclass schema-GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" to the****￼** **'....corresponding LDAP search filter for the binary data****￼**  
**guidValue = Array()****￼** **ReDim guidValue(16)****￼** **guidValue(0) = Mid(guidString, 8, 2)****￼** **guidValue(1) = Mid(guidString, 6, 2)****￼** **guidValue(2) = Mid(guidString, 4, 2)****￼** **guidValue(3) = Mid(guidString, 2, 2)****￼** **guidValue(4) = Mid(guidString, 13, 2)****￼** **guidValue(5) = Mid(guidString, 11, 2)****￼** **guidValue(6) = Mid(guidString, 18, 2)****￼** **guidValue(7) = Mid(guidString, 16, 2)****￼** **guidValue(8) = Mid(guidString, 21, 2)****￼** **guidValue(9) = Mid(guidString, 23, 2)****￼** **guidValue(10) = Mid(guidString, 26, 2)****￼** **guidValue(11) = Mid(guidString, 28, 2)****￼** **guidValue(12) = Mid(guidString, 30, 2)****￼** **guidValue(13) = Mid(guidString, 32, 2)****￼** **guidValue(14) = Mid(guidString, 34, 2)****￼** **guidValue(15) = Mid(guidString, 36, 2)****￼** **guid_to_filter = ""****￼** **For i = 0 To 15****￼** **guid_to_filter = guid_to_filter & "\" & guidValue(i)****￼** **Next****￼****End Function**  
[Download Script](http://www.selfadsi.org/scripts/read-object-permissions-complex.vbs.txt)
   

**Set Active Directory Permissions in a Script**  
Here is an example of how to assign permission for a single object in the Active Directory. For this purpose, you have to read the **nTSecurityDesriptor** attribute first.  
Then you can change the DAC within by adding new ACE entries. Later, the entire attribute is written back.
 
A trustee (for example user or a group from the same AD forest) gets permissions on a OU:

- Delete this OU (this counts only for the OU itself, so it should be empty then)
- Write permissions on the attribute "description" for all objects in this OU
- Reset passwords for user accounts in this OU

Please note the appropriate ACE flags and object GUIDs which are used for this permissions. The script has to be run as an administrator on a system that is member in  
the regarding domain:  
**'you have to use an object of your own environment!****￼****Set obj = GetObject("LDAP://OU=users,OU=example,DC=ldapexplorer,DC=com")****￼**  
**trustee = "LEX\AccessUser"****￼**  
**Const ADS_REVISION_DS = 4****￼**  
**Const ADS_ACETYPE_ACCESS_ALLOWED = 0****￼****Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 5****￼**  
**Const ADS_ACEFLAG_INHERIT_ACE = &H2****￼****Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8****￼**  
**Const ADS_RIGHT_DS_READ_PROP = &H10****￼****Const ADS_RIGHT_DS_WRITE_PROP = &H20****￼****Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100****￼****Const ADS_RIGHT_DELETE = &H10000****￼**  
**Const ADS_FLAG_OBJECT_TYPE_PRESENT = 1****￼****Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = 2****￼**  
**Const GUID_ATTR_DESCRIPTION = "{bf967950-0de6-11d0-a285-00aa003049e2}"****￼****Const GUID_CLASS_USER = "{bf967aba-0de6-11d0-a285-00aa003049e2}"****￼****Const GUID_RIGHT_RESETPASSWORD = "{ab721a53-1e2f-11d0-9819-00aa0040529b}"****￼**  
**Set objACL = obj.get("nTSecurityDescriptor")****￼****Set objDACL = objACL.DiscretionaryAcl****￼**  
**WScript.Echo obj.distinguishedname & vbCrLf****￼**  
**'create a new ACE entry: delete th OU, but not the child objects therein****￼****Set newAce = CreateObject("AccessControlEntry")** **￼****newAce.Trustee = trustee****￼****newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED****￼****newAce.AceFlags = 0****￼****newAce.AccessMask = ADS_RIGHT_DELETE****￼****newACE.Flags = 0****￼****objDACL.AddAce newAce****￼**  
**'create a new ACE entry: read/write the 'description' field for all contained obejcts****￼****Set newAce = CreateObject("AccessControlEntry")** **￼****newAce.Trustee = trustee****￼****newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT****￼****newAce.AceFlags = ADS_ACEFLAG_INHERIT_ACE Or ADS_ACEFLAG_INHERIT_ONLY_ACE****￼****newAce.AccessMask = ADS_RIGHT_DS_READ_PROP Or ADS_RIGHT_DS_WRITE_PROP****￼****newACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT****￼****newACE.ObjectType = GUID_ATTR_DESCRIPTION****￼****objDACL.AddAce newAce****￼**  
**'create a new ACE entry: reset password for user accounts****￼****Set newAce = CreateObject("AccessControlEntry")** **￼****newAce.Trustee = trustee****￼****newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT****￼****newAce.AceFlags = ADS_ACEFLAG_INHERIT_ACE****￼****newAce.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS****￼****newACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT Or ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT****￼****newACE.ObjectType = GUID_RIGHT_RESETPASSWORD****￼****newACE.InheritedObjectType = GUID_CLASS_USER****￼****objDACL.AddAce newAce****￼**  
**'write new DACL****￼****objACL.DiscretionaryAcl = objDACL****￼****obj.Put "ntSecurityDescriptor", objACL****￼****obj.SetInfo**  
[Download Script](http://www.selfadsi.org/scripts/set-object-permissions.vbs.txt)

[![Download Icon](Exported%20image%2020250808202115-10.png)](http://www.selfadsi.org/scripts/set-object-permissions.vbs.txt)   
**Remove Active Directory Permissions in a Script**  
Here is an example of how to get the permission for a single object in the Active Directory removed. For this purpose the **nTSecurityDesriptor** attribute has to be read.  
We read from the contained Discretionary Access Control List (DACL) all ACEs that are not inherited from above, and which do not grant permissions to the trustee which  
you want to remove from the DACL. In rewriting the entire attribute, then the permissions inherited from abovecome back automatically.  
**'you have to use an object of your own environment!****￼****Set obj = GetObject("LDAP://OU=users,OU=example,DC=ldapexplorer,DC=com")****￼****trustee = "LEX\AccessUser"****￼**  
**Const ADS_REVISION_DS = 4****￼**  
**Set objACL = obj.get("nTSecurityDescriptor")****￼**  
**Set objDACL = objACL.DiscretionaryAcl****￼****WScript.Echo obj.distinguishedname & vbCrLf****￼**  
**Set newDACL = CreateObject("AccessControlList")****￼****newDACL.AclRevision = ADS_REVISION_DS****￼****newDACL.AceCount = 0****￼**  
**Set ace = CreateObject("AccessControlEntry")** **￼****For Each ace In objDACL****￼** **'keep all the old ACEs, if they are NOT inherited and if the NOT contain the trustee****￼** **If ((ace.AceFlags And ADS_ACEFLAG_INHERITED_ACE) \<\> 0) Or (ace.Trustee \<\> trustee) Then****￼** **newDACL.AddAce ace****￼** **End If****￼****Next****￼**  
**'write new DACL****￼****objACL.DiscretionaryAcl = newDACL****￼****obj.Put "ntSecurityDescriptor", objACL****￼****obj.SetInfo**
 \> From \<[http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm](http://www.selfadsi.org/deep-inside/ad-security-descriptors.htm)\>