password_warn.sh - Notify users that a password change is needed

As a point of basic security, passwords should be changed on a frequent basis. Modern user authentication systems (NIS+, LDAP and so on) can be configured to automatically force users to change passwords on a (say) six-monthly basis. Standard Solaris NIS doesn't have this facility, so I have written a script to recognise when a user's password hasn't been changed and mail them the instructions needed.

The script works by comparing an old archive of the password file with the current password database and checking whether the encrypted password fields of each are different. Before running the script, take an archive copy of the password file and mail all users that passwords are in need of changing. Then, some time later, run this script and see which users have still not changed their passwords. Keep running and hounding until all passwords are changed or accounts disabled.

To customise this script for another site, change the SYSTEM settings from NIS or NONIS to appropriate system types for your site. You will also need to change the ADDRESS variable to your site's email domain and the value of the DEADLINE variable.

#!/bin/sh
#
################################
#set -vx
#
# Shell function definitions
#

get_nis_users()
{
ypcat passwd | awk -F: '{printf "%s ", $1}'
}

get_files_users()
{
awk -F: '{printf "%s ", $1}' $PWFILE
}

get_nis_pw()
{
ypmatch $user passwd | awk -F: '{print $2}'
}

get_files_pw()
{
grep "^${user}:" $PWFILE | awk -F: '{print $2}'
}

get_nis_name()
{
ypmatch $user passwd | awk -F: '{print $5}' | tr " " .
}

get_files_name()
{
grep "^${user}:" $PWFILE | awk -F: '{print $5}' | tr " " .
}

get_old_password()
{
grep "^${user}:" $ARFILE | awk -F: '{print $2}'
}

mail_warning()
{
for user in $UNCHANGED
do
  case $SYSTEM in
   nis)      name=`get_nis_name` ;; 
   nonis)    name=`get_files_name` ;; 
   *) echo Ooops ;;
  esac

  echo "Mailing ${name}@${ADDRESS} with password change information"
  mailx -s "UNIX password change information on $SERVERS servers" ${name}@${ADDRESS} <] [-p ] [-a ] 
Where
   -h help. Display this message and exit
   -m mail. Mail users 
   -v verbose mode
   -s  
        system is one of 
           nis (Systems which have NIS password authentication)
           nonis (Systems which do not have NIS password authentication)
   -p  The file containing the current passwords
   -a   The file containing old passwords for comparison

EOF
exit
}

#
# End of shell function definitions
#

#
# Default parameters
# 
MAILTO=no
SYSTEM=uk
PWFILE=/etc/shadow
ARFILE=
ADDRESS=example.co.uk
DEADLINE="Friday 30th February 2005"
VERBOSE=no

#
# Status reporting
#
STATUS=""
CHANGED=""
UNCHANGED=""
LOCKED=""
NOPW=""

#
# Parse the options
# 
while getopts hvms:p:a: X
do
    case $X in
       h) usage_note;;
       m) MAILTO=yes;;
       v) VERBOSE=yes;;
       s) SYSTEM=$OPTARG;;
       p) PWFILE=$OPTARG;;
       a) ARFILE=$OPTARG;;
       *) usage_note ; exit;;
    esac
done

if [ "$VERBOSE" = "yes" ]; then
    echo "Are we mailing? $MAILTO"
    echo "What system? $SYSTEM"
    echo "Which password file? $PWFILE"
    echo "Which old password file? $ARFILE"
fi

case $SYSTEM in
   nis)        USERS=`get_nis_users` ;
               SERVERS="NIS authenticated UNIX servers";
               CHANGE="passwd -r nis";
               SERVERNAME="name_of_host";;
   nonis)      USERS=`get_files_users`;
               SERVERS="Non-NIS authenticated UNIX servers";
               CHANGE="passwd -r files";
               SERVERNAME="name_of_non-NIS_host";;
   *) echo Ooops ;;
esac

for user in $USERS
do
case $SYSTEM in
   nis)           pass=`get_nis_pw`; 
                  opass=`get_old_password` ; 
                  ;;
   nonis)         pass=`get_files_pw`; 
                  opass=`get_old_password` ; 
                  ;;
   *) echo Ooops ;;
esac
if [ $opass ]; then
   if [ $pass ]; then
        if [ $pass = "*LK*" ]; then
           STATUS="LOCKED"
           LOCKED=`echo $LOCKED $user`
        elif [ ! $pass -o $pass = "NP" ]; then
           STATUS="NO PASSWORD"
           NOPW=`echo $NOPW $user`
        elif [ $pass = $opass ]; then
           STATUS="UNCHANGED"
           UNCHANGED=`echo $UNCHANGED $user`
        else
           STATUS="CHANGED"
           CHANGED=`echo $CHANGED $user`
        fi
   else
      STATUS="NO PASSWORD"
      opass="*** NOT SET ***"
   fi
else
      STATUS="NEW USER"
      opass="*** NOT SET ***"
fi
echo "User $user    Current $pass    Old $opass $STATUS"
done

if [ "$VERBOSE" = "yes" ]; then
    echo "Changed List: $CHANGED"
    echo ""
    echo "Unchanged List: $UNCHANGED"
    echo ""
    echo "Locked List: $LOCKED"
    echo ""
    echo "No Password List: $NOPW"
    echo ""
fi

if [ "$MAILTO" = "yes" ]; then
mail_warning
fi