Problems accessing the ntSecurityDescriptor property by using the ADSI LDAP provider (323749)
The information in this article applies to:
- Microsoft Active Directory Services Interface, Microsoft Active Directory Client
- Microsoft Active Directory Services Interface, System Component
This article was previously published under Q323749 SYMPTOMS
A user who is not a member of the Administrators group is granted full control of an Active Directory object. Even though the user has full control, the user cannot add Access Control Entries (ACEs) to the Discretionary Access Control List (DACL) without taking ownership of the object.
CAUSE
By default, when accessing the ntSecurityDescriptor property, the ADSI LDAP provider writes the whole security descriptor back to the object. If a non-administrative user tries to write the ownership information of a security descriptor, and the user does not own the object, the NT security system generates an error.
A user who is not an administrator or a member of the administrators group is not permitted to give ownership of any object to any other user. The user can only take ownership of objects. If the user does not already own the object, the NT security system assumes that the user is trying to give ownership of the object to another user or group.
RESOLUTION
To resolve this issue, change the default behavior of the ADSI LDAP provider to instruct the directory service to write only the Discretionary Access Control List (DACL) information portion of the security descriptor back to the object. The IADsObjectOptions interface is designed to let the programmer change the behavior of the LDAP security control.
WORKAROUND
By using the IADsObjectOptions interface on an object, you can override the default behavior of the ADSI LDAP provider so that the ADSI property cache can write specific parts of the security descriptor. The following code samples demonstrate how to write only the DACL back to the object.
Visual Basic sample code
The following code uses the IADsObjectOptions interface to instruct the ADSI LDAP provider to write only the DACL back to the object.
const ADS_OPTION_SECURITY_MASK = 3
const ADS_SECURITY_INFO_DACL = 4
dim obj
set obj = GetObject("LDAP://OU=Trash Me,dc=br549,dc=nttest,dc=microsoft,dc=com")
set oSD = obj.Get("ntSecurityDescriptor")<BR/>
'
' Work with the Security Descriptor.
'
obj.put "ntsecuritydescriptor",oSD
obj.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_DACL<BR/>
obj.SetInfo
WScript.Echo "Done"
Visual C++ sample code
The following code uses the IADsObjectOptions interface to instruct the LDAP security control to write only the DACL back to the object.
//
// Obtain an IADsObjectOptions interface from the object whose
// DACL you want to modify.
//
CComQIPtr <IADsObjectOptions, &IID_IADsObjectOptions> pObjOptions( m_pIADs );
if( pObjOptions )
{
VARIANT OptionsVar;
VariantInit(&OptionsVar);
//
// Set the option mask that you want to change. In this case,
// you want to change the object's security information.
// Use the ADS_OPTION_SECURITY_MASK mask. Because you want to modify the
// DACL, set the variant to the ADS_SEDCURITY_INFO_DACL flag.
//
V_I4(&OptionsVar)=ADS_SECURITY_INFO_DACL ;
V_VT(&OptionsVar)=VT_I4;
hr = pObjOptions->SetOption(ADS_OPTION_SECURITY_MASK, OptionsVar);
}
//
// The smart pointer that is declared for pObjOptions can be released, or it
// will be destroyed and then released after the pointer goes out of scope.
//
Visual C# sample codeDirectoryEntry entry = new DirectoryEntry("LDAP://cn=My Group,cn=users,
dc=dsdom,dc=extest,dc=microsoft,dc=com");
IADsSecurityDescriptor sd = (IADsSecurityDescriptor)entry.Properties["ntSecurityDescriptor"].Value;
IADsAccessControlList dacl = (IADsAccessControlList)sd.DiscretionaryAcl;
//Just reset the same DACL.
sd.DiscretionaryAcl = dacl;
IADsObjectOptions options = (IADsObjectOptions)entry.NativeObject;
options.SetOption((int)ADS_OPTION_ENUM.ADS_OPTION_SECURITY_MASK,
ADS_SECURITY_INFO_ENUM.ADS_SECURITY_INFO_DACL);
entry.Properties["ntSecurityDescriptor"].Value = sd;
try
{
entry.CommitChanges();
Console.WriteLine("Success");
}
catch(Exception e)
{
Console.WriteLine(e);
}
//Wait for the user to read the print out.
Console.ReadLine();
STATUSThis behavior is by design.REFERENCES
For more information about Platform SDK Directory Services documentation, visit the following Microsoft Developer Network (MSDN) Web sites:
Modification Type: | Major | Last Reviewed: | 1/6/2005 |
---|
Keywords: | kbDSWADSI2003Swept kbprb KB323749 kbAudDeveloper |
---|
|