Setting Access Rights on an Object
When using the ADSI COM objects IADsSecurityDescriptor (security descriptor), IADsAccessControlList (DACLs and SACLs), and IADsAccessControlEntry (ACE) to add an ACE to a ACL, you are making changes to the nTSecurityDescriptor property of the specified object in the property cache. This means put methods on the objects that contain the new ACE and the IADs.SetInfo method must be called in order to write the updated security descriptor to the directory from the property cache.
For more information and a code example that sets an ACE on an object in Active Directory Domain Services, see Example Code for Setting an ACE on a Directory Object.
Use the following general process to create an ACE for an access right and setting that ACE on the DACL of an object.
Get an IADs interface pointer to the object.
Use the IADs.Get method to get the security descriptor of the object. The name of the property containing the security descriptor is nTSecurityDescriptor. The property will be returned as a VARIANT containing an IDispatch pointer (the vt member is VT_DISPATCH). Call QueryInterface on that IDispatch pointer to get an IADsSecurityDescriptor interface to use the methods on that interface to access the security descriptor's ACL.
Use the IADsSecurityDescriptor.DiscretionaryAcl property to get the DACL. The method returns an IDispatch pointer. Call QueryInterface on that IDispatch pointer to get an IADsAccessControlList interface to use the methods on that interface to access the individual ACEs in the ACL.
Use CoCreateInstance to create the ADSI COM object for the new ACE and get an IADsAccessControlEntry interface pointer to that object. Be aware that the class ID is CLSID_AccessControlEntry.
Set the properties of the ACE using the IADsAccessControlEntry methods:
- Use IADsAccessControlEntry::put_Trustee to set the trustee to whom this ACE applies. The trustee is a user, group, or other security principal. Your application should use the value from the appropriate property from the user or group object of the trustee to which you want to apply the ACE. The trustee is specified as a BSTR and can take the following forms:
- Domain account (the logon name used in a previous version of Windows NT) of the form "<domain>\<user account>" where "<domain>" is the name of the Windows NT domain that contains the user and "<user account>" is the sAMAccountName property of the specified user. For example: "fabrikam\jeffsmith".
- Well-known security principal that represents special identities defined by the Windows NT security system, such as everyone, local system, principal self, authenticated user, creator owner, and so on. The objects representing the well-known security principals are stored in the Well Known Security Principals container beneath the Configuration container. For example, anonymous logon.
- Built-in group that represent the built-in user groups defined by the Windows NT security system. It has the form "BUILTIN\<group name>" where "<group name>" 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. For example, "BUILTIN\Administrators".
- SID (string format) of the specified user, which is the objectSID property of the specified user. You can convert to string form using the ConvertSidToStringSid function in the Win32 Security API. For example: "S-1-5-32-548".
- Use the IADsAccessControlEntry.AccessMask property to set the mask that specifies the access right. The ADS_RIGHTS_ENUM enumeration specifies the access rights you can set on a directory object.
- Use the IADsAccessControlEntry.AceType property to specify whether to allow or deny the access rights set by AccessMask. For standard rights, this can be ADS_ACETYPE_ACCESS_ALLOWED or ADS_ACETYPE_ACCESS_DENIED. For object-specific rights (rights that apply to a specific part of an object or to a specific type of object), use ADS_ACETYPE_ACCESS_ALLOWED_OBJECT or ADS_ACETYPE_ACCESS_DENIED_OBJECT. The ADS_ACETYPE_ENUM enumeration specifies the access types you can set on an ACE.
- Use the IADsAccessControlEntry.AceFlags property to specify whether other containers or objects beneath the specified object can inherit the ACE. The ADS_ACEFLAG_ENUM enumeration specifies the inheritance flags you can set on an ACE.
- Use the IADsAccessControlEntry.Flags property to specify whether the right applies to a specific part of the object, an inherited object type, or both.
- If Flags is set to ADS_FLAG_OBJECT_TYPE_PRESENT, set the IADsAccessControlEntry.ObjectType property o specify a string containing the GUID of the object class (for ADS_RIGHT_DS_CREATE_CHILD or ADS_RIGHT_DS_DELETE_CHILD), property, property set, validated write, or extended right that the ACE applies to. The GUID must be specified as a string of the form produced by the StringFromGUID2 function in the COM library.
- If Flags is set to ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT, set the IADsAccessControlEntry.InheritedObjectType property to specify a string that contains the GUID of the inherited object class that the ACE applies to. The GUID must be specified as a string of the form produced by the StringFromGUID2 function in the COM library.
- Use IADsAccessControlEntry::put_Trustee to set the trustee to whom this ACE applies. The trustee is a user, group, or other security principal. Your application should use the value from the appropriate property from the user or group object of the trustee to which you want to apply the ACE. The trustee is specified as a BSTR and can take the following forms:
Use the QueryInterface method on the IADsAccessControlEntry object to get an IDispatch pointer. The IADsAccessControlList.AddAce method requires an IDispatch interface pointer to the ACE.
Use IADsAccessControlList.AddAce to add the new ACE to the DACL. Be aware that the order of the ACEs within the ACL can affect the evaluation of access to the object. The correct access to the object may require you to create an new ACL, add the ACEs from the existing ACL in the correct order to the new ACL, and then replace the existing ACL in the security descriptor with the new ACL. For more information, see Order of ACEs in a DACL.
Use the IADsSecurityDescriptor.DiscretionaryAcl property to write the DACL containing the new ACE to the security descriptor. For more information about DACLs, see Null DACLs and Empty DACLs.
Use the IADs.Put method to write the security descriptor to the object's nTSecurityDescriptor property to the property cache.
Use the IADs.SetInfo method to update the property on the object in the directory.