BASH: Check in /etc/shadow if user password is locked
Don't parse the shadow
file manually
Parsing such files is fragile if you fail to account for all eventualities (for example, disabled passwords are often encoded as a single *
; do other solutions deal with that?).
Additionally, authentication may not happen through shadow
(but instead through NIS or ldap or who knows what).There are standard tools that will deal with all this for you. In this case, passwd
:
-S, --status Display account status information. The status information consists of 7 fields. The first field is the user's login name. The second field indicates if the user account has a locked password (L), has no password (NP), or has a usable password (P). The third field gives the date of the last password change. The next four fields are the minimum age, maximum age, warning period, and inactivity period for the password. These ages are expressed in days.
So passwd -S | cut -d ' ' -f 2
will yield what you need. A simple if/then will translate it to your desired variable:
if [ "$(passwd -S "$USER" | cut -d ' ' -f 2)" = "P" ]
then
disabled="False"
else
disabled="True"
fi
The same applies to locking a user's password; this is preferably done through usermod
(--lock
option), not editing shadow
manually.
Why not just do it all with awk?
awk -F: '/<username>/ {if(substr($2,1,1) == "!"){print "True"} else {print "False"}}' /etc/shadow
U=$user LC_ALL=C awk -F: < /etc/shadow '
$1 "" == ENVIRON["U"] {
user_found = 1
if ($2 ~ /^!/) {
print "True"
exit 0
} else {
print "False"
exit 1
}
}
END {
if (!user_found) {
print "False"
print "User "ENVIRON["U"]" not found" > "/dev/stderr"
exit 2
}
}'
$1 "" == ENVIRON["U"]
compares the first field with ENVIRON["U"]
lexically. Without the ""
, the fields could end-up being compared numerically if they look like numbers (causing inf
to match against INF
or Infinity
for instance).
Without LC_ALL=C
, since some awk
implementations use strcoll()
for the ==
lexical comparison, it could end-up checking wrong entries for user names that sort the same.