Hey, Scripting Guy! How can I configure a local user account so that the user can’t change his or her password?
— DC
Hey, DC. The secret here lies in the mysterious userFlags attribute. We’ll show you how to set a user account so that the user can’t change his or her password, then we’ll fill you in on some of the other local user account properties that can be managed with the userFlags attribute. And by then it will hopefully be time for lunch!
First the script that prevents a user from changing his or her password:
Const ADS_UF_PASSWD_CANT_CHANGE = &H0040Set objUser = GetObject(“WinNT://atl-ws-01/kenmyer”)
If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE objUser.Put “userFlags”, objPasswordNoChangeFlag objUser.SetInfo End If
We start out by defining a constant (with the catchy name ADS_UF_PASSWD_CANT_CHANGE) that we’ll need to identify the proper “switch” inside the userFlags attribute. The userFlags attribute is an example of a bitmask attribute, a single attribute that contains multiple properties and property values. For now, just consider a bitmask as being a bank of switches, with each switch representing a different property. If the switch for User Can’t Change Password is on, then the user can’t change his or her password; if the switch is off, then the user can change their password. That part is fairly intuitive; the only hard part of dealing with a bitmask is that the “switches” don’t have names like User Can’t Change Password. Instead, they have hexadecimal values, like &H0040. To carry out our task, we need to flip the &H0040 switch. That’s why we define this constant.
Next we connect to the kenmyer account on the computer atl-ws-01. At that point, we check to see if the switch in question is already on. When working with bitmasks, you’ll often see code like this:
If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
In plain English, this can be read as “If the userFlags attribute is present and if the ADS_UF_PASSWD_CANT_CHANGE switch is on, then this statement is true and we should do something.” In our case, we’re not interested in switches that are on; if the can’t change password flag is already set, then our work is done. We’re only interested in switches that are off. Hence we use this line of code, which takes action only if the switch is not on:
If Not objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then
Now we’re really going to confuse you. Take a look at this line of code:
objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE
Actually – all appearances aside – this is really pretty simple code. All we’re doing here is toggling the value of the user can’t change password switch. That’s what the XOR command does. If the switch is on, XOR turns if off; if the switch is off, XOR turns it on. We’re taking the current value of the userFlags attribute and toggling the user can’t change password switch. Because we know this switch is off (remember the If Not statement we just used?), the XOR command will turn that switch on. Our variable objPasswordNoChangeFlag will then contain exactly the same values that are in the current userFlags attribute, with one exception: the user can’t change password switch will now be on instead of off.
Still with us? The rest of the script is easy. This line of code write the value of the variable objPasswordNoChangeFlag to the userFlags attribute:
objUser.Put “userFlags”, objPasswordNoChangeFlag
We then use the SetInfo command to write those changes to the user account. Just like that, local user Ken Myer will no longer have the right to change his password on the computer atl-ws-01.
And what if wanted to let Ken Myer change his password? Hey, that’s easy. All we have to do is check to see if the user can’t change password switch is on, and then use XOR to turn it off:
Const ADS_UF_PASSWD_CANT_CHANGE = &H0040Set objUser = GetObject(“WinNT://atl-ws-01/kenmyer”)
If objUser.UserFlags AND ADS_UF_PASSWD_CANT_CHANGE Then objPasswordNoChangeFlag = objUser.UserFlags XOR ADS_UF_PASSWD_CANT_CHANGE objUser.Put “userFlags”, objPasswordNoChangeFlag objUser.SetInfo End If
The only difference is that we removed the word Not from our If-Then statement. That’s because now we want to find instances where the switch is on, the better to turn it off.
We agree: these bitmask attributes are confusing. If you’d like a little more information (and a picture or two), you might check out this portion of the Microsoft Windows 2000 Scripting Guide. And, as promised, here are some other local user account properties that can be managed using the userFlags attribute:
Property |
Constant |
Value |
Logon script will be executed |
ADS_UF_SCRIPT |
&H0001 |
Account is disabled |
ADS_UF_ACCOUNTDISABLE |
&H0002 |
Account requires a home directory |
ADS_UF_HOMEDIR_REQUIRED |
&H0008 |
Account is locked out |
ADS_UF_LOCKOUT |
&H0010 |
Account does not require a password |
ADS_UF_PASSWD_NOTREQD |
&H0020 |
User cannot change password |
ADS_UF_PASSWD_CANT_CHANGE |
&H0040 |
Encrypted text password allowed |
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED |
&H0080 |
Account password never expires |
ADS_UF_DONT_EXPIRE_PASSWD |
&H10000 |
Smartcard required for logon |
ADS_UF_SMARTCARD_REQUIRED |
&H40000 |
Password has expired |
ADS_UF_PASSWORD_EXPIRED |
&H800000 |
If you get bored sometime, substitute these values into the user can’t change password script and see what happens. (Of course, as always, we recommend you use a test machine – or at least a test account – when experimenting with scripts like this.)
0 comments