2022-05-26 19:53:15 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
# notifypwexp - send mail to users whose passwords are expiring soon
|
|
|
|
# designed to be run daily or weekly from cron
|
|
|
|
|
|
|
|
# original code by Dennis Williamson
|
|
|
|
# modified by Georg Pfuetzenreuter <georg@lysergic.dev>
|
|
|
|
|
|
|
|
# ### SETUP ###
|
|
|
|
|
|
|
|
#for weekly cron:
|
|
|
|
weekmode=7
|
|
|
|
|
|
|
|
#for daily cron:
|
|
|
|
#weekmode=0
|
|
|
|
|
2022-05-26 20:05:21 +02:00
|
|
|
debug=false
|
|
|
|
|
2022-05-26 19:53:15 +02:00
|
|
|
admins="system"
|
|
|
|
declare -r aged=21 # minimum days after expiration before admins are emailed, set to 0 for "always"
|
|
|
|
|
|
|
|
hostname=`hostname --fqdn`
|
|
|
|
|
|
|
|
# /etc/shadow is system dependent
|
|
|
|
shadowfile="/etc/shadow"
|
|
|
|
# fields in /etc/shadow
|
|
|
|
declare -r last=2
|
|
|
|
#declare -r may=3 # not used in this script
|
|
|
|
declare -r must=4
|
|
|
|
declare -r warn=5
|
|
|
|
#declare -r grace=6 # not used in this script
|
|
|
|
declare -r disable=7
|
|
|
|
|
|
|
|
declare -r doesntmust=99999
|
|
|
|
declare -r warndefault=7
|
|
|
|
|
|
|
|
passwdfile="/etc/passwd"
|
|
|
|
declare -r uidfield=3
|
|
|
|
declare -r unamefield=1
|
|
|
|
# UID range is system dependent
|
|
|
|
declare -r uidmin=1000
|
|
|
|
declare -r uidmax=65534 # exclusive
|
|
|
|
|
|
|
|
# remove the hardcoded path from these progs to use them via $PATH
|
|
|
|
# mailx is system dependent
|
|
|
|
notifyprog="/bin/mail"
|
|
|
|
grepprog="/bin/grep"
|
|
|
|
awkprog="/usr/bin/awk"
|
|
|
|
dateprog="/bin/date"
|
|
|
|
|
|
|
|
# comment out one of these
|
|
|
|
#useUTC=""
|
|
|
|
useUTC="-u"
|
|
|
|
|
|
|
|
# +%s is a GNUism - set it to blank and use dateformat if you have
|
|
|
|
# a system that uses something else like epochdays, for example
|
|
|
|
epochseconds="+%s"
|
|
|
|
dateformat="" # blank for GNU when epochseconds="+%s"
|
|
|
|
secondsperday=86400 # set this to 1 for no division
|
|
|
|
#secondsperday=1
|
|
|
|
|
|
|
|
today=$(($($dateprog $useUTC $epochseconds $dateformat)/$secondsperday))
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "today: $today"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
oIFS=$IFS
|
|
|
|
|
|
|
|
# ### END SETUP ###
|
|
|
|
|
|
|
|
# ### MAIL TEMPLATES ###
|
|
|
|
|
|
|
|
# use single quotes around templates, backslash escapes and substitutions
|
|
|
|
# will be evaluated upon output
|
|
|
|
usersubjecttemplate='Your password is expiring soon'
|
|
|
|
|
|
|
|
gentemplate_userbody () {
|
|
|
|
local days="$1"
|
|
|
|
userbodytemplate="Your password on $hostname expires in $days days."
|
|
|
|
}
|
|
|
|
|
|
|
|
adminsubjecttemplate='User Password Expired: $user@$hostname'
|
|
|
|
adminbodytemplate='The password for user $user on $hostname expired $age days ago.
|
|
|
|
|
|
|
|
Please contact this user about their inactive account and consider whether
|
|
|
|
the account should be disabled or deleted.'
|
|
|
|
|
|
|
|
# ### END MAIL TEMPLATES ###
|
|
|
|
|
|
|
|
# get real users
|
|
|
|
users=$($awkprog -F: -v uidfield=$uidfield \
|
|
|
|
-v unamefield=$unamefield \
|
|
|
|
-v uidmin=$uidmin \
|
|
|
|
-v uidmax=$uidmax \
|
|
|
|
-- '$uidfield>=uidmin && $uidfield<uidmax \
|
|
|
|
{print $unamefield}' $passwdfile)
|
|
|
|
|
|
|
|
for user in $users;
|
|
|
|
do
|
|
|
|
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "user: $user"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
IFS=":"
|
|
|
|
usershadow=$($grepprog ^$user $shadowfile)
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "usershadow 1: $usershadow"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
# make an array out of it
|
|
|
|
usershadow=($usershadow)
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "usershadow 2: $usershadow"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
IFS=$oIFS
|
|
|
|
|
|
|
|
mustchange=${usershadow[$must]}
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "mustchange: $mustchange"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
disabledate=${usershadow[$disable]:-$doesntmust}
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "disabledate: $disabledate"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
# skip users that aren't expiring or that are disabled
|
|
|
|
if [[ $mustchange -ge $doesntmust || $disabledate -le $today ]] ; then continue; fi;
|
|
|
|
|
|
|
|
lastchange=${usershadow[$last]}
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "lastchange: $lastchange"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
warndays=${usershadow[$warn]:-$warndefault}
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "warndays: $warndays"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
expdate=$(("$lastchange" + "$mustchange"))
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "expdate: $expdate"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
threshhold=$(($today + $warndays + $weekmode))
|
2022-05-26 20:05:21 +02:00
|
|
|
if [ "$debug" = true ]; then
|
|
|
|
echo "threshhold: $treshhold"
|
|
|
|
fi
|
2022-05-26 19:53:15 +02:00
|
|
|
|
|
|
|
if [[ $expdate -lt $threshhold ]];
|
|
|
|
then
|
2022-05-26 20:05:21 +02:00
|
|
|
gentemplate_userbody "$(($expdate - $today))"
|
2022-05-26 19:53:15 +02:00
|
|
|
if [[ $expdate -ge $today ]];
|
|
|
|
then
|
|
|
|
subject=$(eval "echo \"$usersubjecttemplate\"")
|
|
|
|
body=$(eval "echo \"$userbodytemplate\"")
|
|
|
|
echo -e "$body" | $notifyprog -s "$subject" $user
|
|
|
|
else
|
|
|
|
if [[ $age -ge $aged ]];
|
|
|
|
then
|
|
|
|
subject=$(eval "echo \"$adminsubjecttemplate\"")
|
|
|
|
body=$(eval "echo \"$adminbodytemplate\"")
|
|
|
|
echo -e "$body" | $notifyprog -s "$subject" $admins
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
2022-05-26 20:05:21 +02:00
|
|
|
unset debug
|