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