The fun part of shell scripting is writing apparently perfectly Wirth-friendly code of immaculate Algol-like structure, peppered with inline bits of line noise that do the actual work. This is management-friendly because then they think they understand the immaculate structure, and because they don't understand the line noise it must therefore be simple.
#!/usr/bin/ksh
# Script XXXX_passwd_over_57_days_old
#
# D. Gerard | 10-Jan-06 | Adapted from XXXXXXXXX version (oracle password)
# | | for XXXX (Unix password). Is there a Solaris
# | | command which just gives us this info? Should be.
# function days_since_epoch()
# Number of days since 1st January, 1970 (= day 0)
# adapted from from SysAdmin Magazine, July 2003:
# http://www.samag.com/documents/s=8284/sam0307b/0307b_l3.htm
# arguments: $1 = day, $2 = month, $3 = year in format YYYY
days_since_epoch()
{
typeset -i DSE
DSE=$((($1-32075+1461*($3+4800+($2-14)/12)/4+367*($2-2-($2-14)/12*12)/12-3*(($3+4900+($2-14)/12)/100)/4)-2440588))
echo $DSE
}
# Output file of names for deletion
LISTFILE=/tmp/oldlist
echo > $LISTFILE
# Today in days since 01 01 1970
TODAY= `days_since_epoch \`date +"%d %m 20%y"\``
# Get list of usernames from /etc/passwd. We only want those in the form aa99999
for i in `/usr/bin/awk -F: '{print $1}' /etc/passwd | /usr/bin/grep '^[a-z]\{2\}[0-9]\{5\}$' `
do
# Get date of last password change (mmddyy, which we shuffle to yymmdd)
# NOTE: If never changed, logins gives the date as "010170"
# PS means password set; NP means no password set.
# NP will typically never have been used and have change date "010170"
DATE=`/usr/bin/logins -x -l $i | /usr/bin/awk '/PS|NP/ {print substr($2,5,2) substr($2,1,4)}'`
# Solaris two year dates 69-99 are 1969-1999, dates 00-68 are 2000-2068
if [[ "690000" > $DATE ]]
then DATE=`printf "20%s" $DATE`
else DATE=`printf "19%s" $DATE`
fi
# Is $DATE more than 57 days before today? Add to list
if [[ $(( $TODAY - `days_since_epoch \`(echo $DATE|/usr/bin/awk '{print substr($1,7,2) " " substr ($1,5,2) " " substr ($1,1,4)}')\``)) -gt 57 ]]
then echo $i >> $LISTFILE
fi
done
# In future, we may take action on the list automatically.
exit 0
Note I've missed my chance to inline even more of the magic. The YY to YYYY conversion can be inlined with nawk and ?: and the script is less than polished in general. But that can be fixed next version. In fact, I'll see if I can get everything from logins on inside the final if.
(no subject)
Date: 2006-01-16 02:36 pm (UTC)(no subject)
Date: 2006-01-16 02:36 pm (UTC)(no subject)
Date: 2006-01-16 02:49 pm (UTC)(no subject)
Date: 2006-01-16 02:55 pm (UTC)(no subject)
Date: 2006-01-16 03:16 pm (UTC)The simple tricks are the deadliest. Use lots of whitespace: partly to provide a more readable layout; partly to cover the fact that someone's indented an interesting statement by eighty characters, pushing it offscreen and rendering it invisible to all but the most paranoid hackers.
(no subject)
Date: 2006-01-16 03:29 pm (UTC)(no subject)
Date: 2006-01-16 03:31 pm (UTC)(no subject)
Date: 2006-01-16 03:34 pm (UTC)And those who occassionally use the wordwrap function to check for such underhand ruses :)
(no subject)
Date: 2006-01-16 03:42 pm (UTC)(no subject)
Date: 2006-01-16 03:57 pm (UTC)(no subject)
Date: 2006-01-16 03:57 pm (UTC)(no subject)
Date: 2006-01-16 03:58 pm (UTC)(no subject)
Date: 2006-01-16 05:08 pm (UTC)(no subject)
Date: 2006-01-16 05:31 pm (UTC)Also, just do the whole
for i in
do
done >> $LISTFILE
and so avoid do the append inside the loop.
Of course, since you read /etc/passwd directly to get the list of usernames, you don't appear to care about other naming services other than "files", so just read the /etc/shadow file directly,
which has the DSE value (or blank)
#!/bin/ksh -p LISTFILE=/tmp/oldlist days_since_epoch() { typeset -i DSE DSE=$((($1-32075+1461*($3+4800+($2-14)/12)/4+367*($2-2-($2-14)/12*12)/12-3*(($3+4900+($2-14)/12)/100)/4)-2440588)) echo $DSE } d=$(days_since_epoch $(date +"%d %m %Y")) let d=d-57 awk -F: '$3 < '$d' { print $1}' /etc/shadow | grep '^[a-z]\{2\}[0-9]\{5\}$' > $LISTFILE(note the %Y - this gives YYYY and is in Solaris 8 onwards)
(no subject)
Date: 2006-01-16 05:33 pm (UTC)(no subject)
Date: 2006-01-16 05:54 pm (UTC)(no subject)
Date: 2006-01-16 05:57 pm (UTC)1. Programmer time
2. Programmer interest.
i.e. I will do what I can and what I'm interested in doing ;-)