more tightening up of permissions
[unix-history] / usr / src / etc / security
index 16299de..5ea2ea4 100644 (file)
@@ -1,23 +1,8 @@
 #!/bin/sh -
 #
 #!/bin/sh -
 #
-#      @(#)security    5.17 (Berkeley) %G%
+#      @(#)security    8.1 (Berkeley) %G%
 #
 
 #
 
-# Script to check basic system security.  Checks included are:
-#      Password and group file check.
-#      Root umask, dot in root's path.
-#      Root and uucp in /etc/ftpusers.
-#      Entry for uudecode in /etc/aliases, if uudecode is setuid.
-#      Hosts.equiv syntax.
-#      Special users that have .rhosts files, .rhosts file syntax.
-#      Home directory and dot-file ownership and permissions.
-#      Mailbox ownership and permissions.
-#      Globally exported NFS file systems.
-#      Changes in setuid and device files.
-#      Block and character disk device ownership and permissions.
-#      File list from /etc/mtree/special.
-#      System binaries as described by files in /etc/mtree.
-
 PATH=/sbin:/usr/sbin:/bin:/usr/bin
 
 umask 077
 PATH=/sbin:/usr/sbin:/bin:/usr/bin
 
 umask 077
@@ -31,7 +16,7 @@ OUTPUT=/tmp/_secure6.$$
 
 trap 'rm -f $ERR $TMP1 $TMP2 $TMP3 $LIST $OUTPUT' 0
 
 
 trap 'rm -f $ERR $TMP1 $TMP2 $TMP3 $LIST $OUTPUT' 0
 
-# Check the password file syntax.
+# Check the master password file syntax.
 MP=/etc/master.passwd
 awk -F: '{
        if ($0 ~ /^[     ]*$/) {
 MP=/etc/master.passwd
 awk -F: '{
        if ($0 ~ /^[     ]*$/) {
@@ -40,8 +25,8 @@ awk -F: '{
        }
        if (NF != 10)
                printf("Line %d has the wrong number of fields.\n", NR);
        }
        if (NF != 10)
                printf("Line %d has the wrong number of fields.\n", NR);
-       if ($1 !~ /[A-za-z0-9]*/)
-               printf("Login %s has non-numeric characters.\n", $1);
+       if ($1 !~ /^[A-Za-z0-9]*$/)
+               printf("Login %s has non-alphanumeric characters.\n", $1);
        if (length($1) > 8)
                printf("Login %s has more than 8 characters.\n", $1);
        if ($2 == "")
        if (length($1) > 8)
                printf("Login %s has more than 8 characters.\n", $1);
        if ($2 == "")
@@ -53,7 +38,7 @@ awk -F: '{
        if ($3 < 0)
                printf("Login %s has a negative user id.\n", $1);
        if ($4 < 0)
        if ($3 < 0)
                printf("Login %s has a negative user id.\n", $1);
        if ($4 < 0)
-               printf("Login %s has a negative user id.\n", $1);
+               printf("Login %s has a negative group id.\n", $1);
 }' < $MP > $OUTPUT
 if [ -s $OUTPUT ] ; then
        printf "\nChecking the $MP file:\n"
 }' < $MP > $OUTPUT
 if [ -s $OUTPUT ] ; then
        printf "\nChecking the $MP file:\n"
@@ -75,6 +60,24 @@ if [ -s $TMP2 ] ; then
         done < $TMP2 | column
 fi
 
         done < $TMP2 | column
 fi
 
+# Backup the master password file; a special case, the normal backup
+# mechanisms also print out file differences and we don't want to do
+# that because this file has encrypted passwords in it.
+CUR=/var/backups/`basename $MP`.current
+BACK=/var/backups/`basename $MP`.backup
+if [ -s $CUR ] ; then
+       if cmp -s $CUR $MP; then
+               :
+       else
+               cp -p $CUR $BACK
+               cp -p $MP $CUR
+               chown root.wheel $CUR
+       fi
+else
+       cp -p $MP $CUR
+       chown root.wheel $CUR
+fi
+
 # Check the group file syntax.
 GRP=/etc/group
 awk -F: '{
 # Check the group file syntax.
 GRP=/etc/group
 awk -F: '{
@@ -84,12 +87,12 @@ awk -F: '{
        }
        if (NF != 4)
                printf("Line %d has the wrong number of fields.\n", NR);
        }
        if (NF != 4)
                printf("Line %d has the wrong number of fields.\n", NR);
-       if ($1 !~ /[A-za-z0-9]*/)
-               printf("Group %s has non-numeric characters.\n", $1);
+       if ($1 !~ /^[A-za-z0-9]*$/)
+               printf("Group %s has non-alphanumeric characters.\n", $1);
        if (length($1) > 8)
                printf("Group %s has more than 8 characters.\n", $1);
        if ($3 !~ /[0-9]*/)
        if (length($1) > 8)
                printf("Group %s has more than 8 characters.\n", $1);
        if ($3 !~ /[0-9]*/)
-               printf("Login %s has a negative user id.\n", $1);
+               printf("Login %s has a negative group id.\n", $1);
 }' < $GRP > $OUTPUT
 if [ -s $OUTPUT ] ; then
        printf "\nChecking the $GRP file:\n"
 }' < $GRP > $OUTPUT
 if [ -s $OUTPUT ] ; then
        printf "\nChecking the $GRP file:\n"
@@ -103,6 +106,9 @@ if [ -s $OUTPUT ] ; then
 fi
 
 # Check for root paths, umask values in startup files.
 fi
 
 # Check for root paths, umask values in startup files.
+# The check for the root paths is problematical -- it's likely to fail
+# in other environments.  Once the shells have been modified to warn
+# of '.' in the path, the path tests should go away.
 > $OUTPUT
 rhome=/root
 umaskset=no
 > $OUTPUT
 rhome=/root
 umaskset=no
@@ -123,7 +129,7 @@ for i in $list ; do
                        /bin/ls -ldgT \$path > $TMP1
 end-of-csh
                awk '{
                        /bin/ls -ldgT \$path > $TMP1
 end-of-csh
                awk '{
-                       if ($10 ~ /\./) {
+                       if ($10 ~ /^\.$/) {
                                print "The root path includes .";
                                next;
                        }
                                print "The root path includes .";
                                next;
                        }
@@ -166,7 +172,7 @@ for i in $list; do
                        /bin/ls -ldgT \$list > $TMP1
 end-of-sh
                awk '{
                        /bin/ls -ldgT \$list > $TMP1
 end-of-sh
                awk '{
-                       if ($10 ~ /\./) {
+                       if ($10 ~ /^\.$/) {
                                print "The root path includes .";
                                next;
                        }
                                print "The root path includes .";
                                next;
                        }
@@ -201,19 +207,21 @@ else
        printf "\nUucp not listed in /etc/ftpusers file.\n"
 fi
 
        printf "\nUucp not listed in /etc/ftpusers file.\n"
 fi
 
-# Uudecode should not be in the aliases file.
-if grep -w uudecode /etc/aliases; then
+# Uudecode should not be in the /etc/aliases file.
+if egrep 'uudecode|decode' /etc/aliases; then
        printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
 fi
 
        printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
 fi
 
-# Check for plus signs in /etc/hosts.equiv.
-if egrep '\+|^$' /etc/hosts.equiv > /dev/null ; then
-       printf "\nEmpty line or + in /etc/hosts.equiv file.\n"
-fi
+# Files that should not have + signs.
+list="/etc/hosts.equiv /etc/hosts.lpd"
+for f in $list ; do
+       if egrep '\+' $f > /dev/null ; then
+               printf "\nPlus sign in $f file.\n"
+       fi
+done
 
 # Check for special users with .rhosts files.  Only root and toor should
 
 # Check for special users with .rhosts files.  Only root and toor should
-# have a .rhosts files.  Also, .rhosts files should not have blank lines
-# or plus signs.
+# have a .rhosts files.  Also, .rhosts files should not plus signs.
 awk -F: '$1 != "root" && $1 != "toor" && \
        ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
                { print $1 " " $6 }' /etc/passwd |
 awk -F: '$1 != "root" && $1 != "toor" && \
        ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
                { print $1 " " $6 }' /etc/passwd |
@@ -231,8 +239,8 @@ fi
 awk -F: '{ print $1 " " $6 }' /etc/passwd | \
 while read uid homedir; do
        if [ -f ${homedir}/.rhosts ] && \
 awk -F: '{ print $1 " " $6 }' /etc/passwd | \
 while read uid homedir; do
        if [ -f ${homedir}/.rhosts ] && \
-           egrep '\+|^$' ${homedir}/.rhosts > /dev/null ; then
-               printf "$uid: empty line or + in .rhosts file.\n"
+           egrep '\+' ${homedir}/.rhosts > /dev/null ; then
+               printf "$uid: + in .rhosts file.\n"
        fi
 done > $OUTPUT
 if [ -s $OUTPUT ] ; then
        fi
 done > $OUTPUT
 if [ -s $OUTPUT ] ; then
@@ -240,8 +248,8 @@ if [ -s $OUTPUT ] ; then
        cat $OUTPUT
 fi
 
        cat $OUTPUT
 fi
 
-# Check home directories, dot files.
-# Directories should not be owned by someone else or writeable.
+# Check home directories.  Directories should not be owned by someone else
+# or writeable.
 awk -F: '{ print $1 " " $6 }' /etc/passwd | \
 while read uid homedir; do
        if [ -d ${homedir}/ ] ; then
 awk -F: '{ print $1 " " $6 }' /etc/passwd | \
 while read uid homedir; do
        if [ -d ${homedir}/ ] ; then
@@ -305,7 +313,7 @@ if [ -s $OUTPUT ] ; then
        cat $OUTPUT
 fi
 
        cat $OUTPUT
 fi
 
-# Check mailbox ownership and permissions.
+# Mailboxes should be owned by user and unreadable.
 ls -l /var/mail | sed 1d | \
 awk '$3 != $9 \
        { print "user " $9 " mailbox is owned by " $3 }
 ls -l /var/mail | sed 1d | \
 awk '$3 != $9 \
        { print "user " $9 " mailbox is owned by " $3 }
@@ -316,7 +324,7 @@ if [ -s $OUTPUT ] ; then
        cat $OUTPUT
 fi
 
        cat $OUTPUT
 fi
 
-# Check for globally exported file systems.
+# File systems should not be globally exported.
 awk '{
        readonly = 0;
        for (i = 2; i <= NF; ++i) {
 awk '{
        readonly = 0;
        for (i = 2; i <= NF; ++i) {
@@ -335,7 +343,7 @@ if [ -s $OUTPUT ] ; then
        cat $OUTPUT
 fi
 
        cat $OUTPUT
 fi
 
-# Display setuid and device changes.
+# Display any changes in setuid files and devices.
 printf "\nChecking setuid files and devices:\n"
 (find / ! -fstype local -a -prune -o \
     \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l -a \
 printf "\nChecking setuid files and devices:\n"
 (find / ! -fstype local -a -prune -o \
     \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l -a \
@@ -351,7 +359,6 @@ fi
 
 # Display any changes in the setuid file list.
 egrep -v '^[bc]' $LIST > $TMP1
 
 # Display any changes in the setuid file list.
 egrep -v '^[bc]' $LIST > $TMP1
-
 if [ -s $TMP1 ] ; then
        # Check to make sure uudecode isn't setuid.
        if grep -w uudecode $TMP1 > /dev/null ; then
 if [ -s $TMP1 ] ; then
        # Check to make sure uudecode isn't setuid.
        if grep -w uudecode $TMP1 > /dev/null ; then
@@ -399,25 +406,14 @@ if [ -s $TMP1 ] ; then
        fi
 fi
 
        fi
 fi
 
-# Check for block and character disk devices, that are readable or writeable
+# Check for block and character disk devices that are readable or writeable
 # or not owned by root.operator.
 # or not owned by root.operator.
-egrep '^b' $LIST > $TMP1
-egrep '^c.*/rdk[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rfd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rhd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rhk[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rhp[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rjb[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rkra[0-9][0-9]*[a-h]$' $LIST >> $TMP1
-egrep '^c.*/rra[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rrb[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rrd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rrl[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rrx[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rrz[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rsd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rup[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
-egrep '^c.*/rwd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
+>$TMP1
+DISKLIST="dk fd hd hk hp jb kra ra rb rd rl rx rz sd up wd"
+for i in $DISKLIST; do
+       egrep "^b.*/${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
+       egrep "^c.*/r${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
+done
 
 awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
        { printf("Disk %s is user %s, group %s, permissions %s.\n", \
 
 awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
        { printf("Disk %s is user %s, group %s, permissions %s.\n", \
@@ -428,8 +424,8 @@ if [ -s $OUTPUT ] ; then
        printf "\n"
 fi
 
        printf "\n"
 fi
 
-egrep '^[bc]' $LIST | sort +10 > $TMP1
 # Display any changes in the device file list.
 # Display any changes in the device file list.
+egrep '^[bc]' $LIST | sort +10 > $TMP1
 if [ -s $TMP1 ] ; then
        CUR=/var/backups/device.current
        BACK=/var/backups/device.backup
 if [ -s $TMP1 ] ; then
        CUR=/var/backups/device.current
        BACK=/var/backups/device.backup
@@ -477,7 +473,9 @@ if [ -s $TMP1 ] ; then
        fi
 fi
 
        fi
 fi
 
-# Check the system binaries.
+# Check special files.
+# Check system binaries.
+#
 # Create the mtree tree specifications using:
 #
 #      mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
 # Create the mtree tree specifications using:
 #
 #      mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
@@ -488,8 +486,6 @@ fi
 # the hacker can modify the tree specification to match the replaced binary.
 # For details on really protecting yourself against modified binaries, see
 # the mtree(8) manual page.
 # the hacker can modify the tree specification to match the replaced binary.
 # For details on really protecting yourself against modified binaries, see
 # the mtree(8) manual page.
-# Check for special files.
-
 if cd /etc/mtree; then
        mtree -e -p / -f /etc/mtree/special > $OUTPUT
        if [ -s $OUTPUT ] ; then
 if cd /etc/mtree; then
        mtree -e -p / -f /etc/mtree/special > $OUTPUT
        if [ -s $OUTPUT ] ; then
@@ -511,3 +507,28 @@ if cd /etc/mtree; then
                cat $OUTPUT
        fi
 fi
                cat $OUTPUT
        fi
 fi
+
+# List of files that get backed up and checked for any modifications.  Each
+# file is expected to have two backups, /var/backups/file.{current,backup}.
+# Any changes cause the files to rotate.
+if [ -s /etc/changelist ] ; then
+       for file in `cat /etc/changelist`; do
+               CUR=/var/backups/`basename $file`.current
+               BACK=/var/backups/`basename $file`.backup
+               if [ -s $file ]; then
+                       if [ -s $CUR ] ; then
+                               diff $CUR $file > $OUTPUT
+                               if [ -s $OUTPUT ] ; then
+               printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
+                                       cat $OUTPUT
+                                       cp -p $CUR $BACK
+                                       cp -p $file $CUR
+                                       chown root.wheel $CUR $BACK
+                               fi
+                       else
+                               cp -p $file $CUR
+                               chown root.wheel $CUR
+                       fi
+               fi
+       done
+fi