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