Set "User Cant Change Password" flag with Visual Basic?

Set "User Cant Change Password" flag with Visual Basic?

Post by Pavel Balasho » Fri, 08 Mar 2002 00:53:35


How i can to set "User Cant Change Password" flag with
Visual Basic?



Set "User Cant Change Password" flag with Visual Basic?

Post by Max L. Vaug » Fri, 08 Mar 2002 23:34:16

There are two basic methods for checking and unchecking the "User Cannot Change Password" check box programmatically.  One method involves using
the WinNT provider, the second uses the LDAP provider.

Method 1: Using the WinNT provider to programmatically check or uncheck the "User Cannot change password" checkbox.  The flag that controls this
check box is exposed in the UserFlags property of the user.  When this flag is set ( the bit is set to 1), two ACEs are added to the user objects ACL that deny
"NT AUTHORITY\SELF" and "Everyone" the rights to change the password.  When the bit is set to 0, the two ACEs are automatically removed and the
check box is unchecked.

The following VBS code isllustrates how to CHECK or UNCHECK  the checkbox:

Const    ADS_UF_PASSWD_CANT_CHANGE               =  &h0040
dim usr
' Set the user cannot change password
' bit using the WinNT provider
set usr = GetObject("WinNT://Your_Domain/UserID,user")
' Display the current value of the user flags.
' Use the variable SetClr to drive the select statement.  
' a value of "SET" will or in the ADS_UF_PASSWD_CANT_CHANGE bit
' while a value of "CLEAR" with XOR the bit out
WScript.Echo "Userflags->" & hex(usr.Get("UserFlags"))
SetClr = "SET"
Select Case  SetClr
  Case "SET"
    usr.Put "UserFlags", (usr.Get("UserFlags") Or ADS_UF_PASSWD_CANT_CHANGE)

  Case "CLEAR"
    usr.Put "UserFlags", (usr.Get("UserFlags") Xor ADS_UF_PASSWD_CANT_CHANGE)

End Select
WScript.Echo "UserFlags+>" & hex(usr.Get("UserFlags")

Method 2: Using a user object obtained using the LDAP provider, in order to set the check box, two ACEs must be added tothe ACL of the user object.  To
uncheck the box, these same two ACEs must be removed.  

The following VBS code illustrates how to create a user using the LDAP provider and CHECK the "User Cannot Change Password" check box.

Sub UserCannotChange(oUserObject)
 Dim oSecDescriptor
 Dim oDACL
 Dim oACE
 Dim oACE2

 Const CHANGE_PASSWORD_GUID = "{ab721a53-1e2f-11d0-9819-00aa0040529b}"
 Set oACE = CreateObject("AccessControlEntry")
 Set oACE2 = CreateObject("AccessControlEntry")
 '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.AceFlags = 0
 oACE.AceType = 6
 oACE.Flags = 1
 oACE.AccessMask = 256

 ' --- Create the Access Control Entry for Everyone---
 oACE2.Trustee = "EVERYONE"
 oACE2.AceFlags = 0
 oACE2.AceType = 6
 oACE2.Flags = 1
 oACE2.AccessMask = 256

 '--- 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

 ' -- Clean up --
 Set oACE = Nothing
 Set oACE2 = Nothing
 Set oDACL = Nothing
 Set oSecDescriptor = Nothing
End Sub
' Main Script
dim nwusr
dim ou
dim args
dim prv
dim strDefaultNamingContext
Dim CommonName
Dim SamName

set args = WScript.Arguments
if( args.count < 3 ) then
  WScript.Echo "Must have a Common name, a SamAccountName and a User Container RN. "
  WScript.Echo "Example: ldapUsr " & chr(34) & "CN=John Doe" & chr(34) & " johnD " & chr(34)&"OU=User Container" & chr(34)
  CommonName = args(0)
  SamName = args(1)
  RNofUserContainer = args(2)
end if
' First, determine the RootDSE and request the Default Nameing context
set prv = GetObject("LDAP://RootDSE")
strDefaultNamingContext = prv.Get("defaultNamingContext")
' Build the Base DN of the user object from the provided user container RN
' and the DefaultNaming Context
DNofUserContainer = "LDAP://"&RNofUserContainer&","&strDefaultNamingContext
WScript.Echo "DN of the base user containter: "
WScript.Echo DNofUserContainer
' Grab the container and create the user object inside it
set ou = GetObject(DNofUserContainer)
WScript.Echo "ADsPath of the User container: "
WScript.Echo ou.adspath
' Create the user object
' Two properties are required before the set info can be called, the CommonName ( CN ) and
' the SamAccountName. Place the appropriate value in the each property then
' flush the local cash back to the server.  User object is not actually added to the
' container until the SetInfo is called successfully.
Set nwusr = ou.Create("user", cstr(CommonName))
nwusr.SamAccountName = SamName
' Enable the account
nwusr.AccountDisabled = False
' Set the initial password to the SamAccountName
nwusr.SetPassword samnm
' Display the DN for the user object
WScript.Echo "New Users' ADsPath: "
WScript.Echo nwusr.adspath
' Now, lets prevent the user from changing their password...
Call UserCannotChange(nwusr)
set nwusr = nothing  
WScript.Echo "DONE"

Hope this helps!

Max Vaughn [MS]
Microsoft Developer Support

Disclaimer: This posting is provided "AS IS" with no warranties, and confers no rights. You assume all risk for your use.


Set "User Cant Change Password" flag with Visual Basic?

Post by Pavel Balasho » Sat, 09 Mar 2002 21:41:54

And what about "SmartCard login required for Interactive
logon" attribute?
Experimentally a got to know that it is 0x40000 in
userAccountControl bitmask

using LDAP provider can set and unset this attribute with
following code:
Set myUser = GetObject
myUser.Put "userAccountControl", (myUser.Get
("userAccountControl") Xor ADS_UF_SMARTCARD_REQUIRED)

The first question: how it possible to do with WinNT
provider? When i use this code:
set usr = GetObject("WinNT://TALLINNT/padmin,user")
usr.Put "UserFlags", (usr.Get("UserFlags") Xor
It only sets, and nevere removes flag "SC login is
required for interactive logon"

The second is: i failed to find out the documentation for
this flag, and my guess that it is bit in
userAccountControl may be incorrect