How to get a list of users with their password status (expired, account locked...)?
Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
How to get a list of users with their password status (expired, account locked...)?
At my company we are migrating from SCO UNIX to RHEL and one of the tasks we often had to do on SCO is get a list of all users whose password has expired and of those, who didn't react, whose account is now locked.
I can imagine this could be done by analyzing the contents of /etc/passwd and /etc/shadow but before going this way, I'd like to know if
1) there is another simpler way to do it
2) if not, then if somebody already has a similar script to share?
You're right, the information is in /etc/passwd and /etc/shadow.
Here is a script to get the information, haven't seen a script yet that totally breaks it down by field but I'm sure it can be done.
This is from Redhat.com explaining the fields of /etc/shadow
Code:
The /etc/shadow file is readable only by the root user, and contains password and optional password aging information. As in the /etc/passwd file, each user's information is on a separate line. Each of these lines is a nine field, colon delimited list including the following information:
Username — The name the user types when logging into the system. This allows the login application to retrieve the user's password (and related information).
Encrypted password — The 13 to 24 character password. The password is encrypted using either the crypt library function, or the md5 hash algorithm. In this field, values other than a validly-formatted encrypted or hashed password are used to control user logins and to show the password status. For example, if the value is ! or * the account is locked, and the user is not allowed to log in. If the value is !! a password has never been set before (and the user, not having set a password, will not be able to log in).
Date password last changed — The number of days since January 1, 1970 (also called the epoch) that the password was last changed. This information is used for the following password aging fields.
Number of days before password can be changed — The minimum number of days that must pass before the password can be changed.
Number of days before password change is required — The number of days that must pass before the password must be changed.
Number of days warning before password change — The number of days before password expiration during which the user is warned of the impending expiration.
Number of days before the account is disabled — The number of days after a password expires before the account will be disabled.
Date since the account has been disabled — The date (stored as the number of days since the epoch) since the user account has been disabled.
A reserved field — A field that is ignored in Red Hat Linux.
Here is an example line from /etc/shadow:
juan:$1$.QKDPc5E$SWlkjRWexrXYgc98F.:11956:0:90:5:30:12197:
This line shows the following information for user juan:
The password was last changed September 25, 2002
There is no minimum amount of time required before the password can be changed
The password must be changed every 90 days
The user will get a warning five days before the password must be changed.
The account will be disabled 30 days after the password expires if no login attempt is made
The account will expire on May 24, 2003
For more information on the /etc/shadow file, type man 5 shadow.
Originally posted by homey Something like this may get you started...
Thanks, that was really helpful. Here's my current version. It might be useful for others:
Code:
#!/bin/bash
formatDate() {
date +%d"."%m"."%Y -d " $1 day"
}
padr() {
string="$1................................................"
echo "$string" | cut -c1-$2
}
length() {
length=`echo "$@" | wc -c | cut -c1-8`
length=$(( $length -1 ))
echo $length
}
padl() {
string="................................................$1"
length=`length "$string"`
echo "$string" | cut -c`expr $length - $2`-$length
}
if [ "$#" = "0" ]; then
echo
echo "List of user accounts with password information"
echo "==============================================="
echo `date`
echo
echo "Legend: M=Minimum password age W=Warning in days before exp"
echo " Dis=Account Disabled"
echo "------------------------------------------------------------------------------------------"
echo "Username |Full name |UID |LastChange|M|Max |W|Passwd Exp|Dis |Acct Exp "
echo "----------|-------------------------|-----|----------|-|-----|-|----------|----|----------"
fi
sort /etc/passwd |grep ":/home/" | awk -F":" '{print}' |\
while read line ; do
name=`echo -e $line | awk -F: '{print$1}'`
uname=`cat /etc/shadow | grep -r "^$name:" | awk -F":" '{print}'`
thisuser=`echo -e $uname | awk -F: '{print$1}'`
if [ "$#" = "1" ] && [ "$1" = "$thisuser" ] || [ "$#" = "0" ]; then
a=`echo -e $uname | awk -F: '{print$3}'`
b=`echo -e $uname | awk -F: '{print$4}'`
c=`echo -e $uname | awk -F: '{print$5}'`
d=`echo -e $uname | awk -F: '{print$6}'`
e=`echo -e $uname | awk -F: '{print$7}'`
f=`echo -e $uname | awk -F: '{print$8}'`
uid=`echo -e $line | awk -F: '{print$3}'`
fullname=`echo -e $line | awk -F: '{print$5}'`
now=$(( ($(date +%s) / 86400) ))
pass=$(( $now - $a ))
last=`formatDate -$pass`
if test "$f" != "" ; then
next=$(( $f - $now ))
exp=`formatDate $next`
else
exp=`echo NEVER`
fi
pexpt=$(( $a + $c ))
pexpt=$(( $pexpt - $now ))
pexp=`formatDate $pexpt`
if [ "$#" = "1" ]; then
echo
echo "===Information for user $name==="
echo "Full name: $fullname"
echo "User ID: $uid"
echo "Password last changed: $last"
echo "Minumum password age: $b"
echo "Maximum password age: $c"
echo "Password warning age: $d"
echo "Password expires on: $pexp"
if test "$e" != "" ; then
echo "The account will be disabled *$e* days after expiration"
fi
echo "The account expires on: $exp"
echo
else
name=`padr $name 10`
c=`padl $c 4`
if test "$e" = "" ; then
e="."
fi
e=`padl $e 3`
exp=`padl $exp 9`
fullname=`padr "$fullname" 25`
uid=`padl $uid 4`
echo "$name|$fullname|$uid|$last|$b|$c|$d|$pexp|$e|$exp"
fi
fi
done
This allows you to get a tabular display of all users (if launched without argument) and a verbose line-by-line list for a specific user if the username is given as a first argument. Feedback and improvements welcome.
Cool! Here is the output which looks good except for this part... date: invalid date ` 99996 day'
Code:
List of user accounts with password information
===============================================
Mon Feb 28 09:23:58 EST 2005
Legend: M=Minimum password age W=Warning in days before exp
Dis=Account Disabled
------------------------------------------------------------------------------------------
Username |Full name |UID |LastChange|M|Max |W|Passwd Exp|Dis |Acct Exp
----------|-------------------------|-----|----------|-|-----|-|----------|----|----------
date: invalid date ` 99996 day'
joe....|.........................|..501|01.03.2005|0|99999|7||....|.....NEVER
date: invalid date ` 99960 day'
jane....|.........................|..500|01.03.2005|0|99999|7||....|.....NEVER
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.