#! /bin/ksh
#
# Monthlystuff - local commands to be run once a month (from cron).
#
# Version: 1995/05/03.
#
# Usage: Monthlystuff
#
# Problems found by this script should be mailed to a system
# administrator.
#
host=`hostname`
admin=system
#
umask 22
#
# Do the monthly accounting.
#
acctscript=//aurum/usr/local/bin/Acct1
acctmsg=/tmp/acctmsg.$$
/bin/rm -f $acctmsg
if [ -f $acctscript ]; then
   $acctscript >$acctmsg 2>&1
   mail -s "$host monthly accounting" $admin <<EOF1
Monthly accounting on `date` for $host.
-----------------------------------------------------------------------------

`cat $acctmsg`
EOF1
   /bin/rm -f $acctmsg
else
   mail -s "Trouble with $host monthly accounting" $admin <<EOF2
$0 could not find $acctscript
on `date` on $host.
EOF2
fi
#
# Check that all NFS file systems are available, if possible.
#
if [ -x /usr/local/bin/Getnfsdownlist ]; then
   nfsdownlist="`/usr/local/bin/Getnfsdownlist`"
   if [ "$nfsdownlist" != "" ]; then
      mail -s "Monthlystuff on $host found NFS servers down" $admin <<EOF3
Monthlystuff on $host found the following NFS servers are down:

`echo $nfsdownlist`

The Monthlystuff command was not run to completion - the portions of
it that scan disk directories were skipped.
EOF3
   fi
else
   nfsdownlist=""
fi
#
# Check all user files/directories for write permissions on
# files/directories. Mail each user a list of "bad" files.
#
findlist=/tmp/findlist.$$
/bin/rm -f $findlist
for homedir in /u0 /u1 /u
do
   if [ ! -d "$homedir" -o "$nfsdownlist" != "" ]; then
      continue
   fi
   cd $homedir
   for userid in *
   do
      if [ ! -d "$homedir/$userid" ]; then
	 continue
      fi
      if [ "$userid" = "lost+found" ]; then
	 continue
      fi
      cd $homedir/$userid
      find . \( -type f -o -type d \) \
       \( -perm -020 -o -perm -002 \) \
       -xdev -exec ls -lgd {} \; | sort >$findlist
      if [ -s $findlist ]; then
         mail -s "File permission problems on //$host$homedir" $userid <<EOF4
The following files/directories in //$host$homedir/$userid
have write permission for either the group and/or the world:

`cat $findlist`

The most common way to acquire such write permissions on files/directories
is the use the 'ftp' command 'put' - this should never be done!
Always use 'get' from the node you want to copy the file(s) to.

Also beware that 'tar' creates file archives with write permissions for
everyone - use the 'chmod' command after every use of 'tar' on Domain/OS.

You can use the 'chmod' command to change the permissions to '644' for
files and '755' for directories:
	chmod 644 list-of-filenames
	chmod 755 list-of-directory-names
EOF4
      fi
   done
done
/bin/rm -f $findlist
#
# Search the system software directories too.
# Ignore the user file directories.
# Try not to search trees like /usr/spool/news that are loaded with
# 66x files (this is avoided by making /usr/spool/news a link that
# points to /news, which is skipped).
# Ignore files with write permissions for the group as long as they
# are owned by news.news, or are in ./lib/newsbin.
#
findlist1=/tmp/findlist1.$$
findlist2=/tmp/findlist2.$$
/bin/rm -f $findlist1 $findlist2
#
# Do real files in /.
#
cd /
echo "Scanning //$host/:" >>$findlist1
echo "---------------------------------------------------------" >>$findlist1
for dir in /.* /*
do
   if [ "$nfsdownlist" != "" ]; then
      break
   fi
   if [ "$dir" = "/." -o "$dir" = "/.." ]; then
      continue
   fi
   if [ -d $dir -o -h $dir ]; then
      continue
   fi
   find $dir \( -type f -o -type d \) \
    \( -perm -020 -o -perm -002 \) \
    -xdev -exec ls -lgd {} \; | sort >>$findlist1
done
echo "" >>$findlist1
#
# Do real directories starting with /.
#
for dir in /.* /*
do
   if [ "$nfsdownlist" != "" ]; then
      break
   fi
   if [ "$dir" = "/." -o "$dir" = "/.." ]; then
      continue
   fi
   if [ -h $dir ]; then
      echo "*** Skipping symbolic link /$host$dir: ***" >>$findlist1
      echo "*********************************************************" >>$findlist1
      echo "" >>$findlist1
      continue
   fi
   if [ ! -d $dir ]; then
      continue
   fi
   if [ "$dir" = "/u0" -o "$dir" = "/u1" -o "$dir" = "/u" ]; then
      echo "*** Skipping user files directory //$host$dir: ***" >>$findlist1
      echo "*********************************************************" >>$findlist1
      echo "" >>$findlist1
      continue
   fi
   if [ "$dir" = "/install" ]; then
      echo "*** WARNING: Skipping Authorized Area //$host$dir: ***" >>$findlist1
      echo "*********************************************************" >>$findlist1
      echo "" >>$findlist1
      continue
   fi
   if [ "$dir" = "/news" ]; then
      echo "*** WARNING: Skipping news directory //$host$dir: ***" >>$findlist1
      echo "*********************************************************" >>$findlist1
      echo "" >>$findlist1
      continue
   fi
   cd $dir
   echo "Scanning //$host$dir:" >>$findlist1
   echo "---------------------------------------------------------" >>$findlist1
   find . \( -type f -o -type d \) \
    \( -perm -020 -o -perm -002 \) \
    -xdev -exec ls -lgd {} \; | sort >>$findlist1
   echo "" >>$findlist1
done
#
# Filter out some files/directories.
#
grep -v '^.rw.rw.r-.* news     news ' $findlist1 | \
 grep -v '^.rwxrwxr-x.*/lib/newsbin' | \
 grep -v '^........-.*news$' | \
 grep -v '^........-.*news\.[0-9]$' | \
 grep -v '^........-.*/local/man/man8/news' | \
 grep -v '^.rw-rw----.*/spool/mail/' >$findlist2 
mail -s "File permission problems on $host" $admin <<EOF5
The following files/directories in the system software on $host
have write permission for either the group and/or the world:

`cat $findlist2`
EOF5
/bin/rm -f $findlist1 $findlist2
cd /
#
# Do a 'syncids' command on the node.
# Also do any mounted volumes.
#
/etc/syncids -l //$host | \
 mail -s "Syncids listing for $host" $admin
if [ "$host" = "plumbum" ]; then
   /etc/syncids -l //$host/u1 | \
    mail -s "Syncids listing for $host/u1" $admin
fi
#
# Update the /etc/hosts file (plumbum only, who will propagate it).
#
#if [ "$host" = "plumbum" ]; then
#   hostscript=/usr/local/bin/updhosts
#   hostmsg=/tmp/hostmsg
#   /bin/rm -f $hostmsg
#   if [ -f $hostscript ]; then
#      $hostscript >$hostmsg 2>&1
#      mail -s "$host /etc/hosts update" $admin <<EOF6
#/etc/hosts update on `date` for $host.
#-----------------------------------------------------------------------------
#
#`cat $hostmsg`
#EOF6
#      /bin/rm -f $hostmsg
#   else
#      mail -s "Trouble with $host /etc/hosts update" $admin <<EOF7
#$0 could not find $hostscript
#on `date` on $host.
#EOF7
#   fi
#fi
#
# Check the /etc/sm and /etc/sm.bak directories for invalid host names.
#
if [ -d /etc/sm -o -d /etc/sm.bak ]; then
   smmsg=/tmp/smmsg.$$
   /bin/rm -f $smmsg
   for d in /etc/sm /etc/sm.bak
   do
      if [ -d $d ]; then
         if [ "`ll $d`" != "total 0" ]; then
            echo "$d contents on `date` for $host." >>$smmsg
            echo "---------------------------------------------------------------------------" >>$smmsg
            echo "" >>$smmsg
            ll $d >>$smmsg 2>&1
	 fi
      fi
   done
   if [ -s $smmsg ]; then
      mail -s "/etc/sm{,.bak} directory contents on $host" $admin <<EOF10
`cat $smmsg`

If the above list contains any invalid host names, the directory
needs manual cleanup to prevent statd from abusing the nameserver.
EOF10
   fi
   /bin/rm -f $smmsg
fi
#
# Check for '.nfs' files, and mail a list of them to the system manager.
#
dotnfslist=/tmp/dotnfslist.$$
find '/.nfs' >$dotnfslist
if [ -s $dotnfslist ]; then
   mail -s ".nfs* files found on host $host" $admin <<EOF12
The following left-over files from NFS server crashes should be
deleted from $host:

`cat $dotnfslist`
EOF12
fi
/bin/rm -f $dotnfslist
#
# Check for UID 0, and mail a list of them to the system manager.
# This idea from Bruce Hunter, Open Systems Today.
#
uid0list=/tmp/uid0list.$$
grep ':0:' /etc/passwd | grep -v '^root:' >$uid0list
if [ -s $uid0list ]; then
   mail -s "UID 0 accounts found on host $host" $admin <<EOF13
The following accounts have root access on $host:

`cat $uid0list`
EOF13
fi
/bin/rm -f $uid0list
#
# Check for accounts with no password, or the default password,
# and mail a list of them to the system manager.
#
badpasswdlist=/tmp/badpasswdlist.$$
defpasswd="`/usr/local/bin/Cryptpasswd alchemy AA`"
egrep "::[0-9]|:$defpasswd:" /etc/passwd | grep -v "^\+" >$badpasswdlist
if [ -s $badpasswdlist ]; then
   mail -s "Accounts with no/default password found on host $host" $admin <<EOF14
The following accounts have no password or still have the default
password on $host:

`cat $badpasswdlist`
EOF14
fi
/bin/rm -f $badpasswdlist
#
# Check /etc/hosts.{equiv,lpd} and all .rhosts/.netrc files for
# improper permissions and for '+' entries.
# Mail each owner a list of "bad" files.
#
mailfile=/tmp/mailfile.$$
tmpfile=/tmp/tmpfile.$$
for f in /etc/hosts.equiv /etc/hosts.lpd `findfile '/\.rhosts$'` \
 `findfile '/\.netrc$'`
do
   if [ ! -f "$f" ]; then
      continue
   fi
   /bin/rm -f $mailfile $tmpfile
   basef=`basename $f`
   if [ "$basef" = ".rhosts" ]; then
      userid="`ls -lg $f | awk '{print $3}'`"
      permcheck="-rw-------"
      permoctal="600"
      userfile=1
      checkplus=1
   elif [ "$basef" = ".netrc" ]; then
      userid="`ls -lg $f | awk '{print $3}'`"
      permcheck="-rw-------"
      permoctal="600"
      userfile=1
      checkplus=0
   else
      userid=$admin
      permcheck="-rw-r--r--"
      permoctal="644"
      userfile=0
      checkplus=1
   fi
   if [ "$userfile" != "0" ]; then
      cat <<EOF30 >>$mailfile
File $f on $host should be examined.
If you don't need it, please delete it as this file can be a security risk;
at least, delete any entries in the file that you don't need.

You should also check your '$basef' file on all remote hosts that
can access our systems, to ensure the permissions are '$permcheck'
and delete any unneeded entries.
EOF30
   fi
   if [ "$basef" = ".netrc" ]; then
      grep -s -v ' login *anonymous *password ' $f >/dev/null 2>&1
      if [ "$?" != "0" ]; then
         cat <<EOF31 >>$mailfile

Your $f file seems to contain only anonymous ftp logins,
and should pose no security risk to our systems or remote systems.
EOF31
      else
         cat <<EOF32 >>$mailfile

Your $f file seems to contain real account and password data;
this is not a good idea. Note that the file may be OK if the
data has been split over multiple lines, which this simple check
can not handle.
EOF32
      fi
   fi
   permfound="`ls -lg $f | awk '{print $1}'`"
   if [ "$permfound" != "$permcheck" ]; then
      cat <<EOF33 >>$mailfile


The $f file has improper permissions:

`ls -lg $f`

The permissions have been changed to $permoctal ($permcheck).
EOF33
      chmod "$permoctal" $f
   fi
   if [ "$checkplus" != "0" ]; then
      grep '\+' $f | grep -v '^\+@' >$tmpfile
      if [ -s $tmpfile ]; then
         cat <<EOF34 >>$mailfile


File $f contains the following '+' entries:

`cat $tmpfile`

These are extremely dangerous as they allow any user to log in
to your system/account with no password check.
EOF34
      fi
      grep -v '\.chem\.utoronto\.ca' $f >$tmpfile
      if [ -s $tmpfile ]; then
         cat <<EOF35 >>$mailfile


File $f contains the following entries
for non-Chemistry systems:

`cat $tmpfile`

These are dangerous as they allow any user who breaks into your foreign
account to log in to your system/account with no password check.
EOF35
      fi
   fi
   if [ -s $mailfile ]; then
      mail -s "Possible problem with $f on $host" $userid <$mailfile
   fi
   /bin/rm -f $mailfile $tmpfile
done
#
# Scan for setuid/setgid files and check file sizes, then compare it
# with the master listing (if any).
# File checksum idea from Bill Rieken, "Sys Admin" magazine, Nov/Dec 1993.
#
if [ -x /usr/local/bin/Find_setuid -a "$nfsdownlist" = "" ]; then
   newlist=/usr/local/lib/setuid.list
   basenewlist="`basename $newlist`"
   newlistdir="`echo $newlist | sed -e s=/$basenewlist$==`"
   masterlist=$newlist.master
   maillist=/tmp/maillist.$$
   echo "Scanning for setuid/setgid files on $host on `date`:" >$newlist
   echo "" >>$newlist
   /usr/local/bin/Find_setuid | sort +8 >>$newlist
#
   for d in `echo $PATH | sed 's/:/ /g'` /usr/lib /usr/local/lib
   do
      if [ ! -d $d ]; then
	 continue
      fi
      if [ "$d" = "." ]; then
	 continue
      fi
      echo "" >>$newlist
      echo "Doing checksums for directory $d on $host:" >>$newlist
      echo "" >>$newlist
      (cd $d; sum *) >>$newlist
   done
#
   if [ -f $masterlist ]; then
      diff $masterlist $newlist >$maillist
      mail -s "Setuid/setgid/sum diffs for $host" $admin <<EOF40
File data:
`ls -lg $masterlist $newlist`

`cat $maillist`

You may want to
   cd /$host$newlistdir
   mv `basename $newlist` `basename $masterlist`
to update the master list.
EOF40
      chmod 440 $masterlist $newlist
   else
      mail -s "Setuid/setgid/sum file list for $host" $admin <<EOF41
Scan the following list for anomalous entries, as it will become
the basis for future scans.

`cat $newlist`
EOF41
      mv $newlist $masterlist
      chmod 440 $masterlist
   fi
   /bin/rm -f $maillist
else
   mail -s "Find_setuid not run on $host" $admin <<EOF42
Monthlystuff on $host can't find /usr/local/bin/Find_setuid,
or some NFS servers were down, so the setuid/setgid/sum scan was not run.
EOF42
fi
#
exit 0
#
# End of Monthlystuff.
#
