How Can I Prevent a Local User From Changing His or Her Password?

ScriptingGuy1

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I configure a local user account so that the user can’t change his or her password?

— DC

SpacerHey, Scripting Guy! AnswerScript Center

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 = &H0040

Set 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 = &H0040

Set 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

Discussion is closed.

Feedback usabilla icon