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