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