How can I automatically notify users of expiring passwords?

Solution 1:

See if this does what you're looking for. You can set the warning time using the chage command or passwd -w:

#!/bin/bash

# notifypwexp - send mail to users whose passwords are expiring soon
# designed to be run daily or weekly from cron

# call with -w for weekly mode (checks to see if warning period begins in the next 7 days
# use -w for a weekly cron job, avoiding excessive emails

# with no option, it only checks whether we're in the warning period now
# use this for a daily cron job

# by Dennis Williamson

# ### SETUP ###

if [[ $1 == "-w" ]] # check for expiration warnings beginning during the next seven days
then
    weekmode=7
else
    weekmode=0
fi

admins="root postmaster"
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/mailx"
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

today=$(($($dateprog $useUTC $epochseconds $dateformat)/$secondsperday))
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'
userbodytemplate='Your password on $hostname expires in $(($expdate - $today)) days.

Please contact the IT department by email at \"helpdesk\" or at 
extension 555 if you have any questions. Help is also available at 
http://helpdesk.example.com/password'

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

    IFS=":"
    usershadow=$($grepprog ^$user $shadowfile)

    # make an array out of it
    usershadow=($usershadow)
    IFS=$oIFS

    mustchange=${usershadow[$must]}
    disabledate=${usershadow[$disable]:-$doesntmust}

    # skip users that aren't expiring or that are disabled
    if [[ $mustchange -ge $doesntmust || $disabledate -le $today  ]] ; then continue; fi;

    lastchange=${usershadow[$last]}
    warndays=${usershadow[$warn]:-$warndefault}
    expdate=$(($lastchange + $mustchange))

    threshhold=$(($today + $warndays + $weekmode))

    if [[ $expdate -lt $threshhold ]];
    then
        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

Solution 2:

Bash Script + Cron Seems like the most obvious solution.

Solution 3:

Use the -w option when changing their passwords. -w This will set the number of days in advance the user will begin receiving warnings that her password will expire, if the user’s account supports password lifetimes. Available to root only.