Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Password maintenance

Using chpasswd and pwgen

David Tansley, System Administrator, Ace Europe
author photo
David Tansley is a freelance writer. He has 15 years of experience as a UNIX administrator, using AIX the last eight years. He enjoys playing badminton, then relaxing watching Formula 1, but nothing beats riding and touring on his GSA motorbike with his wife.

Summary:  When migrating users, a new password will have to be initially provided. One tool to use is chpasswd. Thinking of a good password can also be prone to creating dictionary words as a password. Using the password generator pwgen, this task can be made easy.

Date:  11 May 2010
Level:  Introductory PDF:  A4 and Letter (44KB | 12 pages)Get Adobe® Reader®
Also available in:   Chinese  Korean  Russian

Activity:  18772 views
Comments:  

When migrating users, an initial password should be provided. The user is then typically e-mailed or told of their new password via a phone call. The user will then be prompted to change their password when logging in (that is, if the security password policy rules are enforced). Password changes can also occur through ad-hoc requests which will require resetting the user account passwords, be it locally or remotely. Going through these password changes takes time and is very repetitive. However, using the AIX utility chpasswd (which is also shipped with Linux variants), these tasks can be carried out and repeated with ease.

Choosing a good password is, however, another matter. It is easy when changing or resetting several passwords at once to use dictionary words or even the users name, but, this is not good password policy. A password should be fairly easy enough to remember but not hard enough that the user has to write it down to remember it. Some people suggest using random passwords for ordinary user accounts is good security policy. I suggest that it is only good policy if the user can remember their own password. If the user writes their password down on a sticky note, they will very likely leave it where they can easily retrieve it, like underneath their desktop or in their desk draw. Ultimately, this might be an easy place for a suspecting intruder to find the user's password.

A good tool to use for generating pronounceable and non-pronounceable passwords, be it from a system administrator's perspective or from a user who wants to generate their own password, is the utility application called pwgen. Pwgen can generate one or multiple passwords, and you can specify different password lengths, which can include using a capital or numeric digit.

In this article, I will demonstrate the use of chpasswd and pwgen, and how they can be used interactively, or in batch, when dealing with password changes. I first came into contact with chpassswd when migrating users into an LDAP environment a few years back. Now it is my tool of choice for changing passwords, non-interactively, local or remote accounts. To see where to download pwgen be it binary or source see the Resources section.

Using chpasswd

With chpasswd, you can change a single or many account passwords in one hit. This means no more re-typing the password as you would normally do on the command line. Though chpasswd can be used interactively, I suggest using it in non-interactive mode. Use chpasswd since it is a quick way to change passwords.

The format to use chpasswd is:

chpasswd  -f <pwdadm flags> -c

Where:
-f pwdadm flags can be parsed
-c clears the password flags

The user and password are read from the standard input in the format:

user_name:user_password

Imagine we have just created three users accounts with the following names: alpha, bravo and charlie

No password has been set on these accounts yet, you can tell this by interrogating the /etc/passwd file and the pwdadm command:

# tail /etc/passwd
alpha:*:209:1:alpha.apps:/home/alpha:/usr/bin/ksh
bravo:*:210:1:bravo.suppt:/home/bravo:/usr/bin/ksh
charlie:*:211:1:charlie.suppt:/home/charlie:/usr/bin/ksh

Notice that the passwd file that the second column has a '*', this informs us that no password has yet been set. This can also be confirmed by querying one of the users with the pwdadm command:

 # pwdadm -q alpha
alpha:

No output has been produced, as no password has been set. If there was, then the 'lastupdate' field would be populated with a UTC timestamp in seconds when it was set.

Using chpasswd, I will demonstrate two ways these users will have there initial passwords set. In the following example, I am echoing from the command line the username of alpha with the password of mypasswd then piping through to chpasswd:

echo "alpha:mypasswd" | chpasswd

The login and password details can also be contained in a string and piped through to chpasswd, like so:

# detail="charlie:charpw"
echo $detail | chpasswd

Now querying user alpha via pwdadm we can see that the flags value ADMCHG has been set, which is the chpasswd default setting when resetting passwords:

# pwdadm -q alpha
alpha:
        lastupdate = 1265765265
        flags = ADMCHG

The ADMCHG indicates that next time the user alpha attempts to login using their initial password (mypasswd) that has been set, user alpha will be forced to change their password. This also applies to attempts on other accounts that have their ADMCHG flags set.

Passwords can also be changed, where the details are held in a file. For example consider the following contents of the file pass:

# cat pass
bravo:bravpass
charlie:charpass

In the previous file called pass, user bravo will have their password changed to bravpass and user charlie will have there password changed to charpass. To execute the password changes, simply cat the file and pipe it through to chpasswd, like so:

# cat pass | chpasswd

A file can also be redirected into chpasswd for processing. In this example, I'll specify that the users bravo and charlie will not have to change their password by specifying the 'c-' option (clear password flags) like so:

# chpasswd -c < pass

Using pwdadm to query the user charlie , the following is produced:

# pwdadm -q charlie
charlie:
        lastupdate = 1265853052

Notice the use of the clear flags option in the chpasswd command; it has cleared all flags value in that field.

To determine when a password was last set or changed, as indicated in the last update value in pwdadm output. The UTC time stamp in seconds will need to be converted into a more meaningful current date time stamp.

Both of the following commands return the last update of a password change or initial set (if present). In this example, we are interrogating user alpha's last password update:

# lssec -f /etc/security/passwd -s alpha -a lastupdate
alpha lastupdate=1265940457

# pwdadm -q alpha
alpha:
       lastupdate = 1265940457
       flags = ADMCHG

You can use perl or gawk to convert the UTC into the current time stamp, both of the following examples achieve the same result:

# perl -e 'use POSIX;print ctime(1265940457)'
Thu Feb 11 20:07:37 2010


# gawk 'BEGIN {print strftime("%c",1265940457)}'
Thu Feb 11 20:07:37 GMT 2010


Installing pwgen

The current pwgen version is 2.0.6 if you download the source. The binary version is at 2.0.5. In this demonstration I'll be using the source.

Once downloaded, unzip it and compile it:

# gunzip pwgen-2.06.tar.gz
# tar -xvf pwgen-2.06.tar
# cd pwgen-2.06
#./configure
# make
# make install

The pwgen binary will be installed in /usr/local/bin.


Using pwgen

Pwgen generates passwords that can be random (hard to remember) or easy on the brain (not to hard to remember). The utility can be used both interactively or in batch mode for scripts.

By default, pwgen prints a screen full of passwords to the standard output. Generally you would not want this; however, this could be useful if you or a user wishes to choose a password for a one-time use that is entered manually. When generating passwords, pwgen will try and mix it up with a number and capital by default.

The format is:

pwgen <options> <password_length> <number_of_passwords>

Common options are:

-1print passwords one per line
-cmust include a capital letter
-nmust include a number
-srandom password

To print a single password of 8 character length:

# pwgen 8 1
eej3eeZu

To print three passwords of 7 character length forcing the use of a capital letter use:

# pwgen -c 7 3
ohw4Aj7 Pei0obe gaw4De4

To print 10 passwords of 8 character length forcing the use of a capital letter and number use:

# pwgen -c -n 8 10
zum5Shei Choo6Eih Ub5uagei Ooxu6ohs Eix9xeip iV4yoeph Io3aeGhe taiTh6ia
cuere1AW phai9Pai

Pwgen will determine if you are executing the utility via a tty or not. If not, it will only generate one password by default, if no options are passed. This makes it easier for scripting, when you need to store values in a variable, like so:

# pass=$(pwgen)
# echo $pass
ohtherah

If you prefer, you can use the back-ticks for command substitution. It achieves the same result:

                pass=`pwgen`
                # echo $pass
                oowahxei
                

Of course, we can include as many passwords as we like. In the following example, three passwords are generated:

# pass=$(pwgen -c -n 8 3)
# echo $pass
EluBie0z thohku0W Ail3fu3z

To print a truly random password of eight characters use:

# pwgen -s 8 1
9bTzZxt9

A note of caution should be considered when using the random option (as in the previous example). These can be extremely hard to remember and, if assigned to a user, they could write down the password. In my experience, random generated passwords should only be used for application owner accounts.


Putting it together

Now that we have seen the tools pwgen and chpasswd in action, we can start setting initial passwords for users. Clearly this will have to be carried out via a script, such as Listing 1. First, determine a list of users you want to set the passwords for; this list could be contained in a file (although in this demonstration the users are contained in the string $list which contains three users). For each of these users, a password of eight character length will be generated using the command when each user is processed through the loop:

pwgen 8 1

An initial check is carried out making sure the user account is present on the AIX host. If it is, then the user name and generated password is appended to the file passfile in the format for chpasswd to process. Once all the users have been processed, the file is piped through chpasswd. If a user is not present in /etc/passwd then no user/password entry will be present in passfile for that user.


Listing 1. setpass
#!/bin/sh
# setpass

passfile=/home/dxtans/passfile
>$passfile

list="alpha bravo charlie"

for user in $list
 do
   if  ! grep -w ^$user /etc/passwd > /dev/null
   then
    echo "user NOT present: $user"
  else
   echo "user present: $user"
  pass=$(pwgen 8 1)
  echo "$user:$pass">>$passfile
 fi
done
cat $passfile | chpasswd

After running the script setpass, the file passfile is generated with the following contents, prior to processing through chpasswd:

# cat passfile
alpha:jiebuzio
bravo:oegaeyay
charlie:ooweipoa

In the next example (see Listing 2), a user called foxtrot is created with a initial password and login attribute changes. The create_user script demonstrates one way this can be done using pwgen for setting the password. In this example, a password is set for 8 characters containing at least one capital and one number:

pwgen -c -n 8 1

First, the user foxtrot is created with the su set to false. The password is then set on the account clearing all password restrict flags for the user (that means user foxtrot will not be prompted to change their password upon login). The gecos field is then set, expanding the variable $user to become foxtrot, and "apps" is then appended to the expanded variable. The maxage is set to five weeks, user foxtrot will be forced to change the password five weeks after the last password change or password set. User foxtrot cannot change that password until after one week , as dictated by the minage=1. Finally, the group memberships are set with the primary group being staff (which is the AIX default).


Listing 2. create_user
#!/bin/sh
# create_user

user="foxtrot"
pass=$(pwgen -c -n 8 1)
echo "the passwd for $user is: $pass"

echo  "creating user $user..creating password"
mkuser su=false $user
 if [ $? = 0 ]
  then
   echo "$user:$pass" | chpasswd -c
  else
   echo "error: unable to create user $user"
   exit 1
 fi
echo "changing $user attributes..."
  chuser gecos="${user}.apps" $user
  chuser maxage=5 $user
  chuser minage=1 $user

In the previous example when executing the script create_user, the output is:

# create_user
the passwd for foxtrot is: oiN2hi9r
creating user foxtrot..creating password
changing foxtrot attributes...

We can tell that the password flags have been cleared, by using the pwdadm command, as described earlier:

# pwdadm -q foxtrot
foxtrot:
        lastupdate = 1266174412

Changing the root password at frequent intervals is an audit requirement. The best way to do this, in my opinion, is to ssh out to each host as root and then change the password once connected on that host. Please note however, this is one password you do not want to forget. So it maybe advantageous to either first generate the password with pwgen locally, hard code it in the script, and then delete the password from the script after it has been rolled out and after the password has been secured in a physical place, like a safe. Do not forget to inform the other system administrators of the new password.

A good practice is to have all the hosts you want to connect to remotely contained a file. Using this approach means the file can then be read by other scripts, thus stopping typos by manually putting them in your scripts. A typical file containing the hosts could be in the following format:

# cat all_hosts
host1
host2
host3
host..

Listing 3 shows one easy way this could be done. The password has already been generated with pwgen and the password is 'tu8ahLae'. For each host we connect to, as read in the all_hosts file, the here document method is used. This means all commands that are contained between the words 'mayday' are read as standard input on the remote host. The string root:tu8ahLae is piped through to chpasswd, like so:

echo "root:tu8ahLae" | chpasswd 


Listing 3. chpw_root
#!/bin/sh
cat all_hosts | while read host
do
echo "[$host]″

ssh -T -t -l root $host<<'mayday'
hostname

echo "root:tu8ahLae" | chpasswd 
 if [ $? != 0 ]
then
echo " password of root change failed $host"
 else
echo " password of root change OK"
fi
mayday
done
        

The chpw_root script assumes the ssh keys have been exchanged from the remote hosts to the host where the script resides.


Notifying users

The script contained in Listing 2 creates a user with the initial password set, though the method of informing the user of their new password is a manual one. As this often involves copying and pasting the authentication details into an e-mail and then mailing the user or telephoning the details. A more automotive method could be to e-mail the user directly from the script. To do this, a process must be in place where the user and e-mail address can be associated. One option that could be considered is to use a file containing users Ids with their respective e-mail addresses. Another option could be to have their e-mail address in their gecos field in the /etc/password file in the form: <first_name>.<last_name>@<domain>,

dxtans:!:203:1:david.tansley@btinternet.com:/home/dxtans:/usr/bin/ksh

This scenario, however, opens the doors for typos especially if you have many AIX boxes, so it should only be considered if you administer a few boxes.

The other alternative (which I believe is a quicker method to set-up and requires zero amendments to the /etc/passwd file) is to have a global lookup file. This file could contain a list of all login-able users and their respective e-mail addresses, like so:

#  cat email_lookup
alpha   alpha.apps@mycompany.com
bravo   bravo.suppt@mycompany.com
charlie charlie.suppt@mycompany.com

This global file email_lookup containing all the user names and e-mail accounts could then be pushed out to all the boxes. Having one global file to update means less of a headache, just remember to update it when you add or delete a user, then push it out to all boxes again via scp. It does not matter if a user is not present on a remote box where the email_lookup file is present, because the lookup for that user will not take place, if changing passwords, as the user does not exist.

The script contained in Listing 4 uses the previous email_lookup file to find the user name and their respective e-mail address and notify the user of their account changes. It reads the user and password from the file passfile, (generated earlier in this demonstration) it then checks this is a valid account by checking /etc/passwd. If all is OK, then the e-mail address is extracted for that given user from the email_lookup file. The script assumes that the chpasswd has already been run, and the login and password details are present in the file passfile as presented earlier. Ideally the script should also contain the chpasswd and pwgen routines to change passwords in a single hit as demonstrated in this article. For now, the script contained in Listing 4 should give you some ideas on how to automatically notify users via e-mail once their password has been reset or changed.


Listing 4. email_user
#!/bin/sh
passfile=/home/dxtans/passfile
email_lookup=/home/dxtans/email_lookup

IFS=":"
cat $passfile | while read user pass
do
   if grep -w  ^$user /etc/passwd >/dev/null
     then
       echo "$user - found"
        email_name=$(grep -w  ^$user $email_lookup | awk '{print $2}')
          if [ "$email_name" = ""  ]
           then
            echo "lookup failed for this user:$user"
          fi
        mail -s "`hostname` account change" $email_name<<mayday
your account: $user
new password: $pass
mayday

   else
       echo "$user - NOT found"
fi
 done


Conclusion

Using pwgen along with chpasswd allows the system administrator to automate the task of setting user passwords. The passwords generated from pwgen are not easily predictable words, thus ensuring good security practice for password changes. I have also suggested two ways a user could be notified of password changes.


Resources

Learn

Get products and technologies

  • Download the binary and source, version 2.05

Discuss

About the author

author photo

David Tansley is a freelance writer. He has 15 years of experience as a UNIX administrator, using AIX the last eight years. He enjoys playing badminton, then relaxing watching Formula 1, but nothing beats riding and touring on his GSA motorbike with his wife.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=AIX and UNIX
ArticleID=488139
ArticleTitle=Password maintenance
publish-date=05112010
author1-email=david.tansley@btinternet.com
author1-email-cc=mmccrary@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers