My team is deploying Active Directory (AD). We've been working on a project that enhances the Microsoft Management Console (MMC) Active Directory Users and Computers snap-in by adding internally developed tools and scripts to several AD display specifiers. We've successfully figured everything out, except for one particular setting. We want to manage the User Cannot Change Password option, which appears on the Account property page of the User Properties dialog box. However, we haven't been able to find the property that manages this setting. We've looked in adsiedit.msc and in the Microsoft Developer Network's (MSDN's) description of all the User object properties, but to no avail. Can you point us in the right direction?
The User Cannot Change Password option isn't an attribute of the AD User object. To control this option programmatically, you need to use the User-Change-Password controlAccessRight, which is in the domain's cn=Extended-Rights,cn=Configuration container.
To enable the User Cannot Change Password option, you must add access-denied object-type access control entries (ACEs) to the discretionary ACL (DACL) of the target user's Security Descriptor (SD). The Microsoft article "How to Set the 'User Cannot Change Password' Option by Using a Program" (http://support.microsoft.com/directory/article.asp?id=kb;en-us;q301287) demonstrates how to use VBScript code to enable this setting.
To disable the User Cannot Change Password option, you perform the reverse action—that is, you remove the access-denied object-type ACEs from the DACL of the target user's SD. For example, the code in Listing 1 shows how to remove the ACEs that the sample code in "How to Set the 'User Cannot Change Password' Option by Using a Program" set. The code in Listing 1 begins by defining the two constants that you'll use to find the correct ACEs to remove from the User object's DACL. As the first constant's name implies, ADS_ACETYPE_ACCESS_DENIED_OBJECT identifies object-specific, access-denied ACEs. The USER_CHANGE_PASSWORD_RIGHTSGUID constant contains the value of the rightsGuid attribute for the domain's cn=User-Change-Password,cn=Extended-Rights,cn=Configuration controlAccessRight. After defining the constants, the script creates a two-element array to hold the names of the two trustees referenced in the Microsoft article's code sample.
In the code at callout A in Listing 1, the script binds to the target User object (i.e., the object representing the user for whom you're disabling the User Cannot Change Password option). To use this script, you need to change the ADsPath passed to the GetObject method to the ADsPath for the target User object in your domain. After binding to the target User object, the script retrieves that object's SD and DACL.
After you have a reference to the DACL, you can begin to examine each ACE in the DACL to determine whether it's the ACE to remove. As the code at callout B shows, the outermost For Each...Next statement loops through the trustee array called arrTrustees. During each iteration, a second For Each...Next statement loops through each ACE in the DACL. An If...Then...Else statement compares the current ACE's Trustee property against the trustee in the arrTrustees array. If a match occurs, a second If...Then...Else statement examines the ACE further to determine whether the ACE's AceType and ObjectType properties match the two constants defined at the top of the script. If they both match, the body of the second If...Then...Else statement removes the ACE from the DACL. This examination process repeats both for each ACE in the DACL and for each trustee in the arrTrustees array.
After the script removes the ACEs from the DACL, the script writes the modified DACL to the user's SD, as the code at callout C shows. The script then writes the updated SD to the local property cache and uses the SetInfo method to commit the change to the directory, at which point the User Cannot Change Password option is disabled.