Admin Alert: Changing User Passwords on the Fly
August 5, 2009 Joe Hertvik
It’s always helpful to have some CL code handy for various system functions that i5/OS administrators may need to perform. This week, I’m presenting one of my favorite administrative CL programs: code to change passwords and disable user profiles through a program call. Feel free to examine this code and use it in your shop whenever you need to deputize users without security administrator authority to change passwords.
How This Code Began
Every once in awhile, I need to allow selected users without security administrator authority the ability to change a user profile password or to disable a user profile. While I realize that I may need to give them this ability, I don’t want to give their user profile security administrator authority, and I also need to place some controls on their abilities.
To satisfy this need, I wrote the following code that accepts a user profile name, a new password, and a flag to enable or disable the user. This code can be compiled with the adopted authority of a security administrator-enabled user to do two things:
You can use this code in exit programs, as a command, or in any other venue where you want to allow users without security administrator authority the ability to enter, edit, and change passwords. The results of the intended change are passed back to the calling user in the user’s local data area (LDA).
I call the program PSSWRDCHG and the code that makes it work is listed below.
Before I show you the code, however, let me sound a note of caution. This program must be compiled with the User Profile (USRPRF) parameter of its compile statement equal to *OWNER, and the program must be compiled under a user profile that has security administrator authority to your user profiles. This will allow the program to run under adopted authority, in which any user who can execute the program will be able to use the program to change user profiles.
After compilation, you must also be sure that *PUBLIC access to this program is set to *EXCLUDE to prevent users who are not explicitly authorized to run the program from running the program. To change *PUBLIC access to *EXCLUDE after the program is compiled, run the following Grant Object Authority (GRTOBJAUT) command from a green-screen command line.
GRTOBJAUT OBJ(library_name/PSSWRDCHG) OBJTYPE(*PGM) USER(*PUBLIC) AUT(*EXCLUDE)
Then when someone needs to use the program, you can explicitly grant run access to any user by running the following GRTOBJAUT command.
GRTOBJAUT OBJ(library_name/PSSWRDCHG) OBJTYPE(*PGM) USER(user_name) AUT(*USE)
By performing these steps, you can prevent all users from running the program, except for those users who are explicitly authorized to run the program.
Now back to my PSSWRDCHG code.
0001.00 /* This program changes the password for and + 0002.00 enables/disables the name of the user profile + 0003.00 that is passed into the program */ 0004.00 0005.00 /* IMPORTANT* This program must be compiled with adopted + 0006.00 authority and individuals users must be authorized to + 0007.00 the program to use it. THIS PROGRAM CHANGES PASSWORDS + 0008.00 FOR USERS SO BE CAREFUL WHO YOU AUTHORIZE TO + 0009.00 USE IT */ 0010.00 0011.00 PGM PARM(&USER &PASSWORD &ENABLE &USERNAME) 0012.00 DCL VAR(&USER1) TYPE(*CHAR) LEN(1) 0013.00 DCL VAR(&PASSWORD) TYPE(*CHAR) LEN(10) 0014.00 DCL VAR(&USER) TYPE(*CHAR) LEN(10) 0015.00 DCL VAR(&USERNAME) TYPE(*CHAR) LEN(50) 0016.00 DCL VAR(&USER2) TYPE(*CHAR) LEN(2) /* First two + 0017.00 digits of user ID */ 0018.00 DCL VAR(&ENABLE) TYPE(*CHAR) LEN(1) /* Enable + 0019.00 for processing */ 0020.00 DCL VAR(&CURPASSWRD) TYPE(*CHAR) LEN(10) + 0021.00 VALUE('*NOPWD') 0022.00 DCL VAR(&ERRORCD) TYPE(*UINT) LEN(4) 0023.00 DCL VAR(&PGMMSG) TYPE(*CHAR) LEN(512) + 0024.00 VALUE(*BLANKS) 0025.00 0026.00 0027.00 CHGVAR VAR(&USER1) VALUE(%SUBSTRING(&USER 1 1) 0028.00 0029.00 /* This program can only be used for non-IBM users */ 0030.00 IF COND(&USER1 *EQ 'Q') THEN(DO) 0031.00 SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Invalid + 0032.00 User. Cannot changes pwds for system users') 0033.00 GOTO CMDLBL(ENDPGM) 0034.00 ENDDO 0035.00 /*insert additional user profile restrictions here */ 0036.00 0037.00 IF COND(&ENABLE *EQ 'N') THEN(GOTO CMDLBL(ENABLE)) 0038.00 0039.00 /* Edit check the password to see if it's valid for + 0040.00 the system */ 0041.00 IF COND(&PASSWORD *EQ ' ') THEN(DO) 0042.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Blank password + 0043.00 entered. Please enter a password') 0044.00 GOTO CMDLBL(ENDPGM) 0045.00 ENDDO 0046.00 0047.00 /* Edit check the password to see if it's valid for + 0048.00 the system */ 0049.00 IF COND((&PASSWORD *GE '0 ') *AND + 0050.00 (&PASSWORD *LE '9999999999')) THEN(DO) 0051.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Password cannot + 0052.00 start with a number. Please reenter') 0053.00 GOTO CMDLBL(ENDPGM) 0054.00 ENDDO 0055.00 0056.00 /* Enable the user profile on the system */ 0057.00 ENABLE: IF COND(&ENABLE *EQ 'Y') THEN(DO) 0058.00 CHGUSRPRF USRPRF(&USER) STATUS(*ENABLED) TEXT(&USERNAME) 0059.00 MONMSG MSGID(CPF9801 CPF2204) EXEC(DO) 0060.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid user + 0061.00 profile. User cannot be found on system') 0062.00 GOTO CMDLBL(ENDPGM) 0063.00 ENDDO 0064.00 CHGDTAARA DTAARA(*LDA (161 80)) VALUE(&USERNAME) 0065.00 ENDDO 0066.00 ELSE CMD(DO) /* Disable the user profile */ 0067.00 CHGUSRPRF USRPRF(&USER) STATUS(*DISABLED) TEXT(&USERNAME) 0068.00 MONMSG MSGID(CPF9801 CPF2204) EXEC(DO) 0069.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid user + 0070.00 profile. User cannot be found on system') 0071.00 GOTO CMDLBL(ENDPGM) 0072.00 ENDDO 0073.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('User has been + 0074.00 disabled on the system.') 0075.00 CHGDTAARA DTAARA(*LDA (161 80)) VALUE(&USERNAME) 0076.00 GOTO CMDLBL(ENDPGM) 0077.00 ENDDO 0078.00 0079.00 /* Change the user profile password */ 0080.00 CALL PGM(QSYCHGPW) PARM(&USER &CURPASSWRD + 0081.00 &PASSWORD &ERRORCD) 0082.00 MONMSG MSGID(CPF22F5) EXEC(DO) 0083.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid password + 0084.00 entered. Cannot change password') 0085.00 GOTO CMDLBL(ENDPGM) 0086.00 ENDDO 0087.00 0088.00 /* Send any error messages that occurred to the LDA + 0089.00 for reporting to the calling program */ 0090.00 MONMSG MSGID(CPF22C0) EXEC(DO) 0091.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid password. + 0092.00 Does not meet system password rules') 0093.00 GOTO CMDLBL(ENDPGM) 0094.00 ENDDO 0095.00 0096.00 MONMSG MSGID(CPF22C2) EXEC(DO) 0097.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid password. + 0098.00 Password is not long enough') 0099.00 GOTO CMDLBL(ENDPGM) 0100.00 ENDDO 0101.00 0102.00 MONMSG MSGID(CPF22C3) EXEC(DO) 0103.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid + 0104.00 password. Password is too long for system') 0105.00 GOTO CMDLBL(ENDPGM) 0106.00 ENDDO 0107.00 0108.00 MONMSG MSGID(CPF22D1 CPD2356) EXEC(DO) 0109.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid password. + 0110.00 Cannot be same as user ID or current pwd') 0111.00 GOTO CMDLBL(ENDPGM) 0112.00 ENDDO 0113.00 0114.00 MONMSG MSGID(CPF9801) EXEC(DO) 0115.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('Invalid user + 0116.00 name. User not found.') 0117.00 GOTO CMDLBL(ENDPGM) 0118.00 ENDDO 0119.00 0120.00 /* Successful password change. Report to calling pgm */ 0121.00 CHGDTAARA DTAARA(*LDA (1 80)) VALUE('RF ID' *BCAT + 0122.00 &USER *BCAT 'User password has been + 0123.00 changed to' *BCAT &PASSWORD) 0124.00 0125.00 CHGDTAARA DTAARA(*LDA (81 80)) VALUE('User has been + 0126.00 enabled on the system') 0127.00 0128.00 0129.00 ENDPGM: ENDPGM
Here are the functions that are performed by each set of lines.
Lines 1.00-10.00 display a standard warning message that this program is used to change passwords for any user profile, and that whomever deals with it should be careful to keep this awesome authority away from those people who don’t deserve it. Be very stingy in who you give access to this code.
Line 11.00 passes in four parameters that define the name of the user that you want to change the password for (&USER), the value that you want to change the user’s password to (&PASSWORD), whether the user profile should be enabled or disabled after the program is run (&ENABLE), and the new user text name for the profile (&USERNAME).
Lines 13.00-26.00 define the variables that the program uses to make the change.
Lines 27.00-35.00 check to see if the calling user is trying to change the password for an IBM system user profile (any profile that starts with the letter ‘Q’). If it finds that the target user profile name starts with ‘Q’, it writes that information to the LDA and halts execution. If you have other users that you want to stop the program from changing passwords for, you can insert additional code after line 35.00.
Line 37.00 allows you to use the program just to disable a user without changing their user profile. If you pass in an ‘N’ in the &ENABLE parameter, the code will go to line 57.00 and disable the user profile.
Lines 39.00-54.00 perform some routine password edits to ensure that the password is not equal to blanks and that the entered password does not start with a number. You can insert more edits here if you wish to edit the password further. If the password contains invalid characters or blanks, the program stores appropriate messages in the LDA and exits the program.
Lines 56.00-77.00 enables or disables the passed in user profile name using the Change User Profile (CHGUSRPRF) command, depending on whether you passed in a ‘Y’ or an ‘N’ in the &ENABLE parameter. If the program is unable to perform this change, it notes the problem in the LDA and exits the program. If the program disables the user profile, it does not attempt to change the password and the code will finish executing.
Line 79.00-86.00 attempts to change the user profile password by using the Change User Password (QSYCHGPW) API. This API accepts four parameters:
Normally you would need to pass in the current user password to change the password using QSYSCHPW. However, if you compile this program using the adopted authority for a user who has security administrator (*SECADM), object management (*OBJMGT), and *USE authority for the user profile password being changed, the API will allow you to change the password without entering the current password. To enable this feature, the &CURPASSWRD variable used for the current password parameter is set to *NOPWD.
Lines 88.00-126.00 monitors the QSYSCHGPW call for any error messages that occur when attempting to change the password. If a problem occurs, the code adds the appropriate text to the LDA before going to the end of the program. The error messages that are monitored for here are common messages that occur if the user uses a password that violates any of the system’s password composition rules.
Lines 120.00-128.00 execute only when the password has been successfully changed. It puts two messages into the LDA informing the user that the password has been changed (LDA positions 1-80) and that the user has been enabled on the system (LDA positions 81-160).
Line 129.00 ends the program with an End Program (ENDPGM) command.
So this is Joe’s secret formula for allowing authorized users to change passwords through a command, exit program, or called program. Use it wisely and it will help you deputize responsible users to enable/disable user profiles or to change user passwords without giving them security administrator authority.
About Our Testing Environment
This article was tested on a System i 550 partition running i5/OS V5R4. Information presented here may also work with earlier versions of the i5/OS and OS/400 operating systems. However, earlier versions of commands presented here may have slightly different features due to improvements that were made from release to release.