Home | History | Annotate | Line # | Download | only in etc
security revision 1.9
      1  1.1  cgd #!/bin/sh -
      2  1.1  cgd #
      3  1.9  cgd #	from: @(#)security	8.1 (Berkeley) 6/9/93
      4  1.9  cgd #	$Id: security,v 1.9 1994/06/15 04:28:20 cgd Exp $
      5  1.1  cgd #
      6  1.1  cgd 
      7  1.9  cgd PATH=/sbin:/usr/sbin:/bin:/usr/bin
      8  1.1  cgd 
      9  1.9  cgd umask 077
     10  1.1  cgd 
     11  1.9  cgd ERR=/tmp/_secure1.$$
     12  1.9  cgd TMP1=/tmp/_secure2.$$
     13  1.9  cgd TMP2=/tmp/_secure3.$$
     14  1.9  cgd TMP3=/tmp/_secure4.$$
     15  1.9  cgd LIST=/tmp/_secure5.$$
     16  1.9  cgd OUTPUT=/tmp/_secure6.$$
     17  1.9  cgd 
     18  1.9  cgd trap 'rm -f $ERR $TMP1 $TMP2 $TMP3 $LIST $OUTPUT' 0
     19  1.9  cgd 
     20  1.9  cgd # Check the master password file syntax.
     21  1.9  cgd MP=/etc/master.passwd
     22  1.9  cgd awk -F: '{
     23  1.9  cgd 	if ($0 ~ /^[	 ]*$/) {
     24  1.9  cgd 		printf("Line %d is a blank line.\n", NR);
     25  1.9  cgd 		next;
     26  1.9  cgd 	}
     27  1.9  cgd 	if (NF != 10)
     28  1.9  cgd 		printf("Line %d has the wrong number of fields.\n", NR);
     29  1.9  cgd 	if ($1 !~ /^[A-Za-z0-9]*$/)
     30  1.9  cgd 		printf("Login %s has non-alphanumeric characters.\n", $1);
     31  1.9  cgd 	if (length($1) > 8)
     32  1.9  cgd 		printf("Login %s has more than 8 characters.\n", $1);
     33  1.9  cgd 	if ($2 == "")
     34  1.9  cgd 		printf("Login %s has no password.\n", $1);
     35  1.9  cgd 	if (length($2) != 13 && ($10 ~ /.*sh$/ || $10 == ""))
     36  1.9  cgd 		printf("Login %s is off but still has a valid shell.\n", $1);
     37  1.9  cgd 	if ($3 == 0 && $1 != "root" && $1 != "toor")
     38  1.9  cgd 		printf("Login %s has a user id of 0.\n", $1);
     39  1.9  cgd 	if ($3 < 0)
     40  1.9  cgd 		printf("Login %s has a negative user id.\n", $1);
     41  1.9  cgd 	if ($4 < 0)
     42  1.9  cgd 		printf("Login %s has a negative group id.\n", $1);
     43  1.9  cgd }' < $MP > $OUTPUT
     44  1.9  cgd if [ -s $OUTPUT ] ; then
     45  1.9  cgd 	printf "\nChecking the $MP file:\n"
     46  1.9  cgd 	cat $OUTPUT
     47  1.9  cgd fi
     48  1.9  cgd 
     49  1.9  cgd awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
     50  1.9  cgd if [ -s $OUTPUT ] ; then
     51  1.9  cgd 	printf "\n$MP has duplicate user names.\n"
     52  1.9  cgd 	column $OUTPUT
     53  1.9  cgd fi
     54  1.9  cgd 
     55  1.9  cgd awk -F: '{ print $1 " " $3 }' $MP | sort -n +1 | tee $TMP1 |
     56  1.9  cgd uniq -d -f 1 | awk '{ print $2 }' > $TMP2
     57  1.9  cgd if [ -s $TMP2 ] ; then
     58  1.9  cgd 	printf "\n$MP has duplicate user id's.\n"
     59  1.9  cgd         while read uid; do
     60  1.9  cgd                 grep -w $uid $TMP1
     61  1.9  cgd         done < $TMP2 | column
     62  1.9  cgd fi
     63  1.9  cgd 
     64  1.9  cgd # Backup the master password file; a special case, the normal backup
     65  1.9  cgd # mechanisms also print out file differences and we don't want to do
     66  1.9  cgd # that because this file has encrypted passwords in it.
     67  1.9  cgd CUR=/var/backups/`basename $MP`.current
     68  1.9  cgd BACK=/var/backups/`basename $MP`.backup
     69  1.9  cgd if [ -s $CUR ] ; then
     70  1.9  cgd 	if cmp -s $CUR $MP; then
     71  1.9  cgd 		:
     72  1.9  cgd 	else
     73  1.9  cgd 		cp -p $CUR $BACK
     74  1.9  cgd 		cp -p $MP $CUR
     75  1.9  cgd 		chown root.wheel $CUR
     76  1.9  cgd 	fi
     77  1.9  cgd else
     78  1.9  cgd 	cp -p $MP $CUR
     79  1.9  cgd 	chown root.wheel $CUR
     80  1.9  cgd fi
     81  1.9  cgd 
     82  1.9  cgd # Check the group file syntax.
     83  1.9  cgd GRP=/etc/group
     84  1.9  cgd awk -F: '{
     85  1.9  cgd 	if ($0 ~ /^[	 ]*$/) {
     86  1.9  cgd 		printf("Line %d is a blank line.\n", NR);
     87  1.9  cgd 		next;
     88  1.9  cgd 	}
     89  1.9  cgd 	if (NF != 4)
     90  1.9  cgd 		printf("Line %d has the wrong number of fields.\n", NR);
     91  1.9  cgd 	if ($1 !~ /^[A-za-z0-9]*$/)
     92  1.9  cgd 		printf("Group %s has non-alphanumeric characters.\n", $1);
     93  1.9  cgd 	if (length($1) > 8)
     94  1.9  cgd 		printf("Group %s has more than 8 characters.\n", $1);
     95  1.9  cgd 	if ($3 !~ /[0-9]*/)
     96  1.9  cgd 		printf("Login %s has a negative group id.\n", $1);
     97  1.9  cgd }' < $GRP > $OUTPUT
     98  1.9  cgd if [ -s $OUTPUT ] ; then
     99  1.9  cgd 	printf "\nChecking the $GRP file:\n"
    100  1.9  cgd 	cat $OUTPUT
    101  1.9  cgd fi
    102  1.9  cgd 
    103  1.9  cgd awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
    104  1.9  cgd if [ -s $OUTPUT ] ; then
    105  1.9  cgd 	printf "\n$GRP has duplicate group names.\n"
    106  1.9  cgd 	column $OUTPUT
    107  1.9  cgd fi
    108  1.9  cgd 
    109  1.9  cgd # Check for root paths, umask values in startup files.
    110  1.9  cgd # The check for the root paths is problematical -- it's likely to fail
    111  1.9  cgd # in other environments.  Once the shells have been modified to warn
    112  1.9  cgd # of '.' in the path, the path tests should go away.
    113  1.9  cgd > $OUTPUT
    114  1.9  cgd rhome=/root
    115  1.9  cgd umaskset=no
    116  1.9  cgd list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
    117  1.9  cgd for i in $list ; do
    118  1.9  cgd 	if [ -f $i ] ; then
    119  1.9  cgd 		if egrep umask $i > /dev/null ; then
    120  1.9  cgd 			umaskset=yes
    121  1.9  cgd 		fi
    122  1.9  cgd 		egrep umask $i |
    123  1.9  cgd 		awk '$2 % 100 < 20 \
    124  1.9  cgd 			{ print "Root umask is group writeable" }
    125  1.9  cgd 		     $2 % 10 < 2 \
    126  1.9  cgd 			{ print "Root umask is other writeable" }' >> $OUTPUT
    127  1.9  cgd 		/bin/csh -f -s << end-of-csh > /dev/null 2>&1
    128  1.9  cgd 			unset path
    129  1.9  cgd 			source $i
    130  1.9  cgd 			/bin/ls -ldgT \$path > $TMP1
    131  1.9  cgd end-of-csh
    132  1.9  cgd 		awk '{
    133  1.9  cgd 			if ($10 ~ /^\.$/) {
    134  1.9  cgd 				print "The root path includes .";
    135  1.9  cgd 				next;
    136  1.9  cgd 			}
    137  1.9  cgd 		     }
    138  1.9  cgd 		     $1 ~ /^d....w/ \
    139  1.9  cgd         { print "Root path directory " $10 " is group writeable." } \
    140  1.9  cgd 		     $1 ~ /^d.......w/ \
    141  1.9  cgd         { print "Root path directory " $10 " is other writeable." }' \
    142  1.9  cgd 		< $TMP1 >> $OUTPUT
    143  1.9  cgd 	fi
    144  1.9  cgd done
    145  1.9  cgd if [ $umaskset = "no" -o -s $OUTPUT ] ; then
    146  1.9  cgd 	printf "\nChecking root csh paths, umask values:\n$list\n"
    147  1.9  cgd 	if [ -s $OUTPUT ]; then
    148  1.9  cgd 		cat $OUTPUT
    149  1.9  cgd 	fi
    150  1.9  cgd 	if [ $umaskset = "no" ] ; then
    151  1.9  cgd 		printf "\nRoot csh startup files do not set the umask.\n"
    152  1.9  cgd 	fi
    153  1.9  cgd fi
    154  1.9  cgd 
    155  1.9  cgd > $OUTPUT
    156  1.9  cgd rhome=/root
    157  1.9  cgd umaskset=no
    158  1.9  cgd list="${rhome}/.profile"
    159  1.9  cgd for i in $list; do
    160  1.9  cgd 	if [ -f $i ] ; then
    161  1.9  cgd 		if egrep umask $i > /dev/null ; then
    162  1.9  cgd 			umaskset=yes
    163  1.9  cgd 		fi
    164  1.9  cgd 		egrep umask $i |
    165  1.9  cgd 		awk '$2 % 100 < 20 \
    166  1.9  cgd 			{ print "Root umask is group writeable" } \
    167  1.9  cgd 		     $2 % 10 < 2 \
    168  1.9  cgd 			{ print "Root umask is other writeable" }' >> $OUTPUT
    169  1.9  cgd 		/bin/sh << end-of-sh > /dev/null 2>&1
    170  1.9  cgd 			PATH=
    171  1.9  cgd 			. $i
    172  1.9  cgd 			list=\`echo \$PATH | /usr/bin/sed -e 's/:/ /g'\`
    173  1.9  cgd 			/bin/ls -ldgT \$list > $TMP1
    174  1.9  cgd end-of-sh
    175  1.9  cgd 		awk '{
    176  1.9  cgd 			if ($10 ~ /^\.$/) {
    177  1.9  cgd 				print "The root path includes .";
    178  1.9  cgd 				next;
    179  1.9  cgd 			}
    180  1.9  cgd 		     }
    181  1.9  cgd 		     $1 ~ /^d....w/ \
    182  1.9  cgd         { print "Root path directory " $10 " is group writeable." } \
    183  1.9  cgd 		     $1 ~ /^d.......w/ \
    184  1.9  cgd         { print "Root path directory " $10 " is other writeable." }' \
    185  1.9  cgd 		< $TMP1 >> $OUTPUT
    186  1.9  cgd 
    187  1.9  cgd 	fi
    188  1.9  cgd done
    189  1.9  cgd if [ $umaskset = "no" -o -s $OUTPUT ] ; then
    190  1.9  cgd 	printf "\nChecking root sh paths, umask values:\n$list\n"
    191  1.9  cgd 	if [ -s $OUTPUT ]; then
    192  1.9  cgd 		cat $OUTPUT
    193  1.9  cgd 	fi
    194  1.9  cgd 	if [ $umaskset = "no" ] ; then
    195  1.9  cgd 		printf "\nRoot sh startup files do not set the umask.\n"
    196  1.9  cgd 	fi
    197  1.9  cgd fi
    198  1.9  cgd 
    199  1.9  cgd # Root and uucp should both be in /etc/ftpusers.
    200  1.9  cgd if egrep root /etc/ftpusers > /dev/null ; then
    201  1.9  cgd 	:
    202  1.9  cgd else
    203  1.9  cgd 	printf "\nRoot not listed in /etc/ftpusers file.\n"
    204  1.9  cgd fi
    205  1.9  cgd if egrep uucp /etc/ftpusers > /dev/null ; then
    206  1.9  cgd 	:
    207  1.9  cgd else
    208  1.9  cgd 	printf "\nUucp not listed in /etc/ftpusers file.\n"
    209  1.9  cgd fi
    210  1.9  cgd 
    211  1.9  cgd # Uudecode should not be in the /etc/aliases file.
    212  1.9  cgd if egrep 'uudecode|decode' /etc/aliases; then
    213  1.9  cgd 	printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
    214  1.9  cgd fi
    215  1.9  cgd 
    216  1.9  cgd # Files that should not have + signs.
    217  1.9  cgd list="/etc/hosts.equiv /etc/hosts.lpd"
    218  1.9  cgd for f in $list ; do
    219  1.9  cgd 	if egrep '\+' $f > /dev/null ; then
    220  1.9  cgd 		printf "\nPlus sign in $f file.\n"
    221  1.9  cgd 	fi
    222  1.9  cgd done
    223  1.9  cgd 
    224  1.9  cgd # Check for special users with .rhosts files.  Only root and toor should
    225  1.9  cgd # have a .rhosts files.  Also, .rhosts files should not plus signs.
    226  1.9  cgd awk -F: '$1 != "root" && $1 != "toor" && \
    227  1.9  cgd 	($3 < 100 || $1 == "ftp" || $1 == "uucp") \
    228  1.9  cgd 		{ print $1 " " $6 }' /etc/passwd |
    229  1.9  cgd while read uid homedir; do
    230  1.9  cgd 	if [ -f ${homedir}/.rhosts ] ; then
    231  1.9  cgd 		rhost=`ls -ldgT ${homedir}/.rhosts`
    232  1.9  cgd 		printf "$uid: $rhost\n"
    233  1.9  cgd 	fi
    234  1.9  cgd done > $OUTPUT
    235  1.9  cgd if [ -s $OUTPUT ] ; then
    236  1.9  cgd 	printf "\nChecking for special users with .rhosts files.\n"
    237  1.9  cgd 	cat $OUTPUT
    238  1.9  cgd fi
    239  1.9  cgd 
    240  1.9  cgd awk -F: '{ print $1 " " $6 }' /etc/passwd | \
    241  1.9  cgd while read uid homedir; do
    242  1.9  cgd 	if [ -f ${homedir}/.rhosts ] && \
    243  1.9  cgd 	    egrep '\+' ${homedir}/.rhosts > /dev/null ; then
    244  1.9  cgd 		printf "$uid: + in .rhosts file.\n"
    245  1.9  cgd 	fi
    246  1.9  cgd done > $OUTPUT
    247  1.9  cgd if [ -s $OUTPUT ] ; then
    248  1.9  cgd 	printf "\nChecking .rhosts files syntax.\n"
    249  1.9  cgd 	cat $OUTPUT
    250  1.9  cgd fi
    251  1.9  cgd 
    252  1.9  cgd # Check home directories.  Directories should not be owned by someone else
    253  1.9  cgd # or writeable.
    254  1.9  cgd awk -F: '{ print $1 " " $6 }' /etc/passwd | \
    255  1.9  cgd while read uid homedir; do
    256  1.9  cgd 	if [ -d ${homedir}/ ] ; then
    257  1.9  cgd 		file=`ls -ldgT ${homedir}`
    258  1.9  cgd 		printf "$uid $file\n"
    259  1.9  cgd 	fi
    260  1.9  cgd done |
    261  1.9  cgd awk '$1 != $4 && $4 != "root" \
    262  1.9  cgd 	{ print "user " $1 " home directory is owned by " $4 }
    263  1.9  cgd      $2 ~ /^-....w/ \
    264  1.9  cgd 	{ print "user " $1 " home directory is group writeable" }
    265  1.9  cgd      $2 ~ /^-.......w/ \
    266  1.9  cgd 	{ print "user " $1 " home directory is other writeable" }' > $OUTPUT
    267  1.9  cgd if [ -s $OUTPUT ] ; then
    268  1.9  cgd 	printf "\nChecking home directories.\n"
    269  1.9  cgd 	cat $OUTPUT
    270  1.9  cgd fi
    271  1.9  cgd 
    272  1.9  cgd # Files that should not be owned by someone else or readable.
    273  1.9  cgd list=".netrc .rhosts"
    274  1.9  cgd awk -F: '{ print $1 " " $6 }' /etc/passwd | \
    275  1.9  cgd while read uid homedir; do
    276  1.9  cgd 	for f in $list ; do
    277  1.9  cgd 		file=${homedir}/${f}
    278  1.9  cgd 		if [ -f $file ] ; then
    279  1.9  cgd 			printf "$uid $f `ls -ldgT $file`\n"
    280  1.9  cgd 		fi
    281  1.9  cgd 	done
    282  1.9  cgd done |
    283  1.9  cgd awk '$1 != $5 && $5 != "root" \
    284  1.9  cgd 	{ print "user " $1 " " $2 " file is owned by " $5 }
    285  1.9  cgd      $3 ~ /^-...r/ \
    286  1.9  cgd 	{ print "user " $1 " " $2 " file is group readable" }
    287  1.9  cgd      $3 ~ /^-......r/ \
    288  1.9  cgd 	{ print "user " $1 " " $2 " file is other readable" }
    289  1.9  cgd      $3 ~ /^-....w/ \
    290  1.9  cgd 	{ print "user " $1 " " $2 " file is group writeable" }
    291  1.9  cgd      $3 ~ /^-.......w/ \
    292  1.9  cgd 	{ print "user " $1 " " $2 " file is other writeable" }' > $OUTPUT
    293  1.9  cgd 
    294  1.9  cgd # Files that should not be owned by someone else or writeable.
    295  1.9  cgd list=".bashrc .cshrc .emacsrc .exrc .forward .klogin .login .logout \
    296  1.9  cgd       .profile .tcshrc"
    297  1.9  cgd awk -F: '{ print $1 " " $6 }' /etc/passwd | \
    298  1.9  cgd while read uid homedir; do
    299  1.9  cgd 	for f in $list ; do
    300  1.9  cgd 		file=${homedir}/${f}
    301  1.9  cgd 		if [ -f $file ] ; then
    302  1.9  cgd 			printf "$uid $f `ls -ldgT $file`\n"
    303  1.9  cgd 		fi
    304  1.9  cgd 	done
    305  1.9  cgd done |
    306  1.9  cgd awk '$1 != $5 && $5 != "root" \
    307  1.9  cgd 	{ print "user " $1 " " $2 " file is owned by " $5 }
    308  1.9  cgd      $3 ~ /^-....w/ \
    309  1.9  cgd 	{ print "user " $1 " " $2 " file is group writeable" }
    310  1.9  cgd      $3 ~ /^-.......w/ \
    311  1.9  cgd 	{ print "user " $1 " " $2 " file is other writeable" }' >> $OUTPUT
    312  1.9  cgd if [ -s $OUTPUT ] ; then
    313  1.9  cgd 	printf "\nChecking dot files.\n"
    314  1.9  cgd 	cat $OUTPUT
    315  1.9  cgd fi
    316  1.9  cgd 
    317  1.9  cgd # Mailboxes should be owned by user and unreadable.
    318  1.9  cgd ls -l /var/mail | sed 1d | \
    319  1.9  cgd awk '$3 != $9 \
    320  1.9  cgd 	{ print "user " $9 " mailbox is owned by " $3 }
    321  1.9  cgd      $1 != "-rw-------" \
    322  1.9  cgd 	{ print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
    323  1.9  cgd if [ -s $OUTPUT ] ; then
    324  1.9  cgd 	printf "\nChecking mailbox ownership.\n"
    325  1.9  cgd 	cat $OUTPUT
    326  1.9  cgd fi
    327  1.9  cgd 
    328  1.9  cgd # File systems should not be globally exported.
    329  1.9  cgd awk '{
    330  1.9  cgd 	readonly = 0;
    331  1.9  cgd 	for (i = 2; i <= NF; ++i) {
    332  1.9  cgd 		if ($i ~ /-ro/)
    333  1.9  cgd 			readonly = 1;
    334  1.9  cgd 		else if ($i !~ /^-/)
    335  1.9  cgd 			next;
    336  1.9  cgd 	}
    337  1.9  cgd 	if (readonly)
    338  1.9  cgd 		print "File system " $1 " globally exported, read-only."
    339  1.9  cgd 	else
    340  1.9  cgd 		print "File system " $1 " globally exported, read-write."
    341  1.9  cgd }' < /etc/exports > $OUTPUT
    342  1.9  cgd if [ -s $OUTPUT ] ; then
    343  1.9  cgd 	printf "\nChecking for globally exported file systems.\n"
    344  1.9  cgd 	cat $OUTPUT
    345  1.9  cgd fi
    346  1.9  cgd 
    347  1.9  cgd # Display any changes in setuid files and devices.
    348  1.9  cgd printf "\nChecking setuid files and devices:\n"
    349  1.9  cgd (find / ! -fstype local -a -prune -o \
    350  1.9  cgd     \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l -a \
    351  1.9  cgd        ! -type s \) | \
    352  1.9  cgd sort | sed -e 's/^/ls -ldgT /' | sh > $LIST) 2> $OUTPUT
    353  1.9  cgd 
    354  1.9  cgd # Display any errors that occurred during system file walk.
    355  1.9  cgd if [ -s $OUTPUT ] ; then
    356  1.9  cgd 	printf "Setuid/device find errors:\n"
    357  1.9  cgd 	cat $OUTPUT
    358  1.9  cgd 	printf "\n"
    359  1.9  cgd fi
    360  1.9  cgd 
    361  1.9  cgd # Display any changes in the setuid file list.
    362  1.9  cgd egrep -v '^[bc]' $LIST > $TMP1
    363  1.9  cgd if [ -s $TMP1 ] ; then
    364  1.9  cgd 	# Check to make sure uudecode isn't setuid.
    365  1.9  cgd 	if grep -w uudecode $TMP1 > /dev/null ; then
    366  1.9  cgd 		printf "\nUudecode is setuid.\n"
    367  1.9  cgd 	fi
    368  1.9  cgd 
    369  1.9  cgd 	CUR=/var/backups/setuid.current
    370  1.9  cgd 	BACK=/var/backups/setuid.backup
    371  1.9  cgd 
    372  1.9  cgd 	if [ -s $CUR ] ; then
    373  1.9  cgd 		if cmp -s $CUR $TMP1 ; then
    374  1.9  cgd 			:
    375  1.9  cgd 		else
    376  1.9  cgd 			> $TMP2
    377  1.9  cgd 			join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
    378  1.9  cgd 			if [ -s $OUTPUT ] ; then
    379  1.9  cgd 				printf "Setuid additions:\n"
    380  1.9  cgd 				tee -a $TMP2 < $OUTPUT
    381  1.9  cgd 				printf "\n"
    382  1.9  cgd 			fi
    383  1.9  cgd 
    384  1.9  cgd 			join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
    385  1.9  cgd 			if [ -s $OUTPUT ] ; then
    386  1.9  cgd 				printf "Setuid deletions:\n"
    387  1.9  cgd 				tee -a $TMP2 < $OUTPUT
    388  1.9  cgd 				printf "\n"
    389  1.9  cgd 			fi
    390  1.9  cgd 
    391  1.9  cgd 			sort +9 $TMP2 $CUR $TMP1 | \
    392  1.9  cgd 			    sed -e 's/[	 ][	 ]*/ /g' | uniq -u > $OUTPUT
    393  1.9  cgd 			if [ -s $OUTPUT ] ; then
    394  1.9  cgd 				printf "Setuid changes:\n"
    395  1.9  cgd 				column -t $OUTPUT
    396  1.9  cgd 				printf "\n"
    397  1.9  cgd 			fi
    398  1.9  cgd 
    399  1.9  cgd 			cp $CUR $BACK
    400  1.9  cgd 			cp $TMP1 $CUR
    401  1.9  cgd 		fi
    402  1.9  cgd 	else
    403  1.9  cgd 		printf "Setuid additions:\n"
    404  1.9  cgd 		column -t $TMP1
    405  1.9  cgd 		printf "\n"
    406  1.9  cgd 		cp $TMP1 $CUR
    407  1.9  cgd 	fi
    408  1.9  cgd fi
    409  1.9  cgd 
    410  1.9  cgd # Check for block and character disk devices that are readable or writeable
    411  1.9  cgd # or not owned by root.operator.
    412  1.9  cgd >$TMP1
    413  1.9  cgd DISKLIST="dk fd hd hk hp jb kra ra rb rd rl rx rz sd up wd"
    414  1.9  cgd for i in $DISKLIST; do
    415  1.9  cgd 	egrep "^b.*/${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
    416  1.9  cgd 	egrep "^c.*/r${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
    417  1.9  cgd done
    418  1.9  cgd 
    419  1.9  cgd awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
    420  1.9  cgd 	{ printf("Disk %s is user %s, group %s, permissions %s.\n", \
    421  1.9  cgd 	    $11, $3, $4, $1); }' < $TMP1 > $OUTPUT
    422  1.9  cgd if [ -s $OUTPUT ] ; then
    423  1.9  cgd 	printf "\nChecking disk ownership and permissions.\n"
    424  1.9  cgd 	cat $OUTPUT
    425  1.9  cgd 	printf "\n"
    426  1.9  cgd fi
    427  1.9  cgd 
    428  1.9  cgd # Display any changes in the device file list.
    429  1.9  cgd egrep '^[bc]' $LIST | sort +10 > $TMP1
    430  1.9  cgd if [ -s $TMP1 ] ; then
    431  1.9  cgd 	CUR=/var/backups/device.current
    432  1.9  cgd 	BACK=/var/backups/device.backup
    433  1.9  cgd 
    434  1.9  cgd 	if [ -s $CUR ] ; then
    435  1.9  cgd 		if cmp -s $CUR $TMP1 ; then
    436  1.9  cgd 			:
    437  1.9  cgd 		else
    438  1.9  cgd 			> $TMP2
    439  1.9  cgd 			join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
    440  1.9  cgd 			if [ -s $OUTPUT ] ; then
    441  1.9  cgd 				printf "Device additions:\n"
    442  1.9  cgd 				tee -a $TMP2 < $OUTPUT
    443  1.9  cgd 				printf "\n"
    444  1.9  cgd 			fi
    445  1.9  cgd 
    446  1.9  cgd 			join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
    447  1.9  cgd 			if [ -s $OUTPUT ] ; then
    448  1.9  cgd 				printf "Device deletions:\n"
    449  1.9  cgd 				tee -a $TMP2 < $OUTPUT
    450  1.9  cgd 				printf "\n"
    451  1.9  cgd 			fi
    452  1.9  cgd 
    453  1.9  cgd 			# Report any block device change.  Ignore character
    454  1.9  cgd 			# devices, only the name is significant.
    455  1.9  cgd 			cat $TMP2 $CUR $TMP1 | \
    456  1.9  cgd 			sed -e '/^c/d' | \
    457  1.9  cgd 			sort +10 | \
    458  1.9  cgd 			sed -e 's/[	 ][	 ]*/ /g' | \
    459  1.9  cgd 			uniq -u > $OUTPUT
    460  1.9  cgd 			if [ -s $OUTPUT ] ; then
    461  1.9  cgd 				printf "Block device changes:\n"
    462  1.9  cgd 				column -t $OUTPUT
    463  1.9  cgd 				printf "\n"
    464  1.9  cgd 			fi
    465  1.9  cgd 
    466  1.9  cgd 			cp $CUR $BACK
    467  1.9  cgd 			cp $TMP1 $CUR
    468  1.9  cgd 		fi
    469  1.9  cgd 	else
    470  1.9  cgd 		printf "Device additions:\n"
    471  1.9  cgd 		column -t $TMP1
    472  1.9  cgd 		printf "\n"
    473  1.9  cgd 		cp $TMP1 $CUR
    474  1.9  cgd 	fi
    475  1.9  cgd fi
    476  1.9  cgd 
    477  1.9  cgd # Check special files.
    478  1.9  cgd # Check system binaries.
    479  1.9  cgd #
    480  1.9  cgd # Create the mtree tree specifications using:
    481  1.9  cgd #
    482  1.9  cgd #	mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
    483  1.9  cgd #	chown root.wheel DIR.SECURE
    484  1.9  cgd #	chmod 600 DIR.SECURE
    485  1.9  cgd #
    486  1.9  cgd # Note, this is not complete protection against Trojan horsed binaries, as
    487  1.9  cgd # the hacker can modify the tree specification to match the replaced binary.
    488  1.9  cgd # For details on really protecting yourself against modified binaries, see
    489  1.9  cgd # the mtree(8) manual page.
    490  1.9  cgd if cd /etc/mtree; then
    491  1.9  cgd 	mtree -e -p / -f /etc/mtree/special > $OUTPUT
    492  1.9  cgd 	if [ -s $OUTPUT ] ; then
    493  1.9  cgd 		printf "\nChecking special files and directories.\n"
    494  1.9  cgd 		cat $OUTPUT
    495  1.9  cgd 	fi
    496  1.9  cgd 
    497  1.9  cgd 	> $OUTPUT
    498  1.9  cgd 	for file in *.secure; do
    499  1.9  cgd 		tree=`sed -n -e '3s/.* //p' -e 3q $file`
    500  1.9  cgd 		mtree -f $file -p $tree > $TMP1
    501  1.9  cgd 		if [ -s $TMP1 ]; then
    502  1.9  cgd 			printf "\nChecking $tree:\n" >> $OUTPUT
    503  1.9  cgd 			cat $TMP1 >> $OUTPUT
    504  1.9  cgd 		fi
    505  1.9  cgd 	done
    506  1.9  cgd 	if [ -s $OUTPUT ] ; then
    507  1.9  cgd 		printf "\nChecking system binaries:\n"
    508  1.9  cgd 		cat $OUTPUT
    509  1.9  cgd 	fi
    510  1.9  cgd fi
    511  1.9  cgd 
    512  1.9  cgd # List of files that get backed up and checked for any modifications.  Each
    513  1.9  cgd # file is expected to have two backups, /var/backups/file.{current,backup}.
    514  1.9  cgd # Any changes cause the files to rotate.
    515  1.9  cgd if [ -s /etc/changelist ] ; then
    516  1.9  cgd 	for file in `cat /etc/changelist`; do
    517  1.9  cgd 		CUR=/var/backups/`basename $file`.current
    518  1.9  cgd 		BACK=/var/backups/`basename $file`.backup
    519  1.9  cgd 		if [ -s $file ]; then
    520  1.9  cgd 			if [ -s $CUR ] ; then
    521  1.9  cgd 				diff $CUR $file > $OUTPUT
    522  1.9  cgd 				if [ -s $OUTPUT ] ; then
    523  1.9  cgd 		printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
    524  1.9  cgd 					cat $OUTPUT
    525  1.9  cgd 					cp -p $CUR $BACK
    526  1.9  cgd 					cp -p $file $CUR
    527  1.9  cgd 					chown root.wheel $CUR $BACK
    528  1.9  cgd 				fi
    529  1.9  cgd 			else
    530  1.9  cgd 				cp -p $file $CUR
    531  1.9  cgd 				chown root.wheel $CUR
    532  1.9  cgd 			fi
    533  1.9  cgd 		fi
    534  1.9  cgd 	done
    535  1.9  cgd fi
    536