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