Platform SDK: Active Directory, ADSI, and Directory Services

User Cannot Change Password

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