| Platform SDK: Active Directory, ADSI, and Directory Services |
To determine whether the user is allowed to change his or her own password, read the ADS_UF_PASSWD_CANT_CHANGE (0x0040) bit on the userFlags attribute of the user's object. This flag is defined in the ADS_USER_FLAG_ENUM enumeration. You cannot set this flag directly.
To prevent a user from changing their password, you must set two ACEs in the security descriptor DACL of the user's object. One ACE denies the right to the user and another ACE denies the right to the Everyone group. Both ACEs are object-specific deny ACEs that specify the GUID of the extended right for changing passwords.
The following subroutine adds these two ACEs to prevent the user from changing the password. To change this right so the user can once again set their password, you must modify or delete the ACEs that deny access.
Sub UserCannotChange(oUserObject As IADsUser)
Dim oSecDescriptor As SecurityDescriptor
Dim oDACL As AccessControlList
Dim oACE As New AccessControlEntry
Dim oACE2 As New AccessControlEntry
Const CHANGE_PASSWORD_GUID = "{ab721a53-1e2f-11d0-9819-00aa0040529b}"
'In order to preven the user from changing his/her own password we place a
'disallow access control entry on the object for that permission
'-- Create the Access Control Entry for Self---
oACE.Trustee = "NT AUTHORITY\SELF"
oACE.AceFlags = 0
oACE.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
oACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT
oACE.ObjectType = CHANGE_PASSWORD_GUID
oACE.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS
' --- Create the Access Control Entry for Everyone---
oACE2.Trustee = "EVERYONE"
oACE2.AceFlags = 0
oACE2.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
oACE2.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT
oACE2.ObjectType = CHANGE_PASSWORD_GUID
oACE2.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS
'--- Get this objects Security Descriptor
Set oSecDescriptor = oUserObject.Get("ntSecurityDescriptor")
'--- Get the Discretionary ACL ---
Set oDACL = oSecDescriptor.DiscretionaryAcl
'-- Add our new ACEs and replace DACL---
oDACL.AddAce oACE
oDACL.AddAce oACE2
' -- Put the Security Descriptor back on the object --
oUserObject.Put "ntSecurityDescriptor", oSecDescriptor
oUserObject.SetInfo
' -- Clean up --
Set oACE = Nothing
Set oACE2 = Nothing
Set oDACL = Nothing
Set oSecDescriptor = Nothing
End Sub