Home | History | Annotate | Line # | Download | only in etc
security revision 1.43
      1   1.1       cgd #!/bin/sh -
      2   1.1       cgd #
      3  1.43    itojun #	$NetBSD: security,v 1.43 2000/05/05 18:28:53 itojun 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.43    itojun # Uudecode should not be in the /etc/mail/aliases file.
    295  1.32     lukem #
    296  1.31     lukem if checkyesno check_aliases; then
    297  1.43    itojun 	for f in /etc/mail/aliases /etc/aliases; do
    298  1.43    itojun 		if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then
    299  1.43    itojun 			printf "\nEntry for uudecode in $f file.\n"
    300  1.43    itojun 		fi
    301  1.43    itojun 	done
    302   1.9       cgd fi
    303   1.9       cgd 
    304   1.9       cgd # Files that should not have + signs.
    305  1.32     lukem #
    306  1.31     lukem if checkyesno check_rhosts; then
    307  1.15       mrg 	list="/etc/hosts.equiv /etc/hosts.lpd"
    308  1.15       mrg 	for f in $list ; do
    309  1.15       mrg 		if [ -f $f ] && egrep '\+' $f > /dev/null ; then
    310  1.15       mrg 			printf "\nPlus sign in $f file.\n"
    311  1.15       mrg 		fi
    312  1.15       mrg 	done
    313  1.15       mrg 
    314  1.15       mrg 	# Check for special users with .rhosts files.  Only root and toor should
    315  1.16     mikel 	# have .rhosts files.  Also, .rhosts files should not have plus signs.
    316  1.15       mrg 	awk -F: '$1 != "root" && $1 != "toor" && \
    317  1.15       mrg 		($3 < 100 || $1 == "ftp" || $1 == "uucp") \
    318  1.20   mycroft 			{ print $1 " " $9 }' $MP |
    319  1.19   mycroft 	sort -k2 |
    320  1.15       mrg 	while read uid homedir; do
    321  1.15       mrg 		if [ -f ${homedir}/.rhosts ] ; then
    322  1.15       mrg 			rhost=`ls -ldgT ${homedir}/.rhosts`
    323  1.15       mrg 			printf "$uid: $rhost\n"
    324  1.15       mrg 		fi
    325  1.15       mrg 	done > $OUTPUT
    326  1.15       mrg 	if [ -s $OUTPUT ] ; then
    327  1.15       mrg 		printf "\nChecking for special users with .rhosts files.\n"
    328  1.15       mrg 		cat $OUTPUT
    329  1.15       mrg 	fi
    330  1.15       mrg 
    331  1.15       mrg 	while read uid homedir; do
    332  1.35      fair 		if [ -f ${homedir}/.rhosts -a -r ${homedir}/.rhosts ] && \
    333  1.41  christos 		    cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null ; then
    334  1.15       mrg 			printf "$uid: + in .rhosts file.\n"
    335  1.15       mrg 		fi
    336  1.29     lukem 	done < $MPBYPATH > $OUTPUT
    337  1.15       mrg 	if [ -s $OUTPUT ] ; then
    338  1.15       mrg 		printf "\nChecking .rhosts files syntax.\n"
    339  1.15       mrg 		cat $OUTPUT
    340  1.15       mrg 	fi
    341   1.9       cgd fi
    342   1.9       cgd 
    343   1.9       cgd # Check home directories.  Directories should not be owned by someone else
    344   1.9       cgd # or writeable.
    345  1.32     lukem #
    346  1.31     lukem if checkyesno check_homes; then
    347  1.15       mrg 	while read uid homedir; do
    348  1.15       mrg 		if [ -d ${homedir}/ ] ; then
    349  1.15       mrg 			file=`ls -ldgT ${homedir}`
    350  1.15       mrg 			printf "$uid $file\n"
    351   1.9       cgd 		fi
    352  1.29     lukem 	done < $MPBYPATH |
    353  1.15       mrg 	awk '$1 != $4 && $4 != "root" \
    354  1.15       mrg 		{ print "user " $1 " home directory is owned by " $4 }
    355  1.15       mrg 	     $2 ~ /^-....w/ \
    356  1.15       mrg 		{ print "user " $1 " home directory is group writeable" }
    357  1.15       mrg 	     $2 ~ /^-.......w/ \
    358  1.27     lukem 		{ print "user " $1 " home directory is other writeable" }' \
    359  1.27     lukem 	    > $OUTPUT
    360  1.15       mrg 	if [ -s $OUTPUT ] ; then
    361  1.15       mrg 		printf "\nChecking home directories.\n"
    362  1.15       mrg 		cat $OUTPUT
    363  1.15       mrg 	fi
    364  1.15       mrg 
    365  1.15       mrg 	# Files that should not be owned by someone else or readable.
    366  1.27     lukem 	list=".Xauthority .netrc"
    367  1.15       mrg 	while read uid homedir; do
    368  1.15       mrg 		for f in $list ; do
    369  1.15       mrg 			file=${homedir}/${f}
    370  1.15       mrg 			if [ -f $file ] ; then
    371  1.15       mrg 				printf "$uid $f `ls -ldgT $file`\n"
    372  1.15       mrg 			fi
    373  1.15       mrg 		done
    374  1.29     lukem 	done < $MPBYPATH |
    375  1.15       mrg 	awk '$1 != $5 && $5 != "root" \
    376  1.15       mrg 		{ print "user " $1 " " $2 " file is owned by " $5 }
    377  1.15       mrg 	     $3 ~ /^-...r/ \
    378  1.15       mrg 		{ print "user " $1 " " $2 " file is group readable" }
    379  1.15       mrg 	     $3 ~ /^-......r/ \
    380  1.15       mrg 		{ print "user " $1 " " $2 " file is other readable" }
    381  1.15       mrg 	     $3 ~ /^-....w/ \
    382  1.15       mrg 		{ print "user " $1 " " $2 " file is group writeable" }
    383  1.15       mrg 	     $3 ~ /^-.......w/ \
    384  1.27     lukem 		{ print "user " $1 " " $2 " file is other writeable" }' \
    385  1.27     lukem 	    > $OUTPUT
    386  1.15       mrg 
    387  1.15       mrg 	# Files that should not be owned by someone else or writeable.
    388  1.19   mycroft 	list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
    389  1.19   mycroft 	      .cshrc .emacs .exrc .forward .history .klogin .login .logout \
    390  1.27     lukem 	      .profile .qmail .rc_history .rhosts .tcshrc .twmrc .xinitrc \
    391  1.27     lukem 	      .xsession"
    392  1.15       mrg 	while read uid homedir; do
    393  1.15       mrg 		for f in $list ; do
    394  1.15       mrg 			file=${homedir}/${f}
    395  1.15       mrg 			if [ -f $file ] ; then
    396  1.15       mrg 				printf "$uid $f `ls -ldgT $file`\n"
    397  1.15       mrg 			fi
    398  1.15       mrg 		done
    399  1.29     lukem 	done < $MPBYPATH |
    400  1.15       mrg 	awk '$1 != $5 && $5 != "root" \
    401  1.15       mrg 		{ print "user " $1 " " $2 " file is owned by " $5 }
    402  1.15       mrg 	     $3 ~ /^-....w/ \
    403  1.15       mrg 		{ print "user " $1 " " $2 " file is group writeable" }
    404  1.15       mrg 	     $3 ~ /^-.......w/ \
    405  1.27     lukem 		{ print "user " $1 " " $2 " file is other writeable" }' \
    406  1.27     lukem 	    >> $OUTPUT
    407  1.15       mrg 	if [ -s $OUTPUT ] ; then
    408  1.15       mrg 		printf "\nChecking dot files.\n"
    409  1.15       mrg 		cat $OUTPUT
    410  1.15       mrg 	fi
    411   1.9       cgd fi
    412   1.9       cgd 
    413   1.9       cgd # Mailboxes should be owned by user and unreadable.
    414  1.32     lukem #
    415  1.31     lukem if checkyesno check_varmail; then
    416  1.15       mrg 	ls -l /var/mail | sed 1d | \
    417  1.15       mrg 	awk '$3 != $9 \
    418  1.15       mrg 		{ print "user " $9 " mailbox is owned by " $3 }
    419  1.15       mrg 	     $1 != "-rw-------" \
    420  1.15       mrg 		{ print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
    421  1.15       mrg 	if [ -s $OUTPUT ] ; then
    422  1.15       mrg 		printf "\nChecking mailbox ownership.\n"
    423  1.15       mrg 		cat $OUTPUT
    424  1.15       mrg 	fi
    425  1.15       mrg fi
    426  1.15       mrg 
    427  1.32     lukem # NFS exports shouldn't be globally exported
    428  1.32     lukem #
    429  1.32     lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
    430  1.32     lukem 	awk '{
    431  1.22     lukem 		# ignore comments and blank lines
    432  1.39   hubertf 		if ($0 ~ /^\#/ || $0 ~ /^$/ )
    433  1.22     lukem 			next;
    434  1.22     lukem 
    435  1.15       mrg 		readonly = 0;
    436  1.15       mrg 		for (i = 2; i <= NF; ++i) {
    437  1.15       mrg 			if ($i ~ /-ro/)
    438  1.15       mrg 				readonly = 1;
    439  1.15       mrg 			else if ($i !~ /^-/)
    440  1.15       mrg 				next;
    441  1.15       mrg 		}
    442  1.15       mrg 		if (readonly)
    443  1.15       mrg 			print "File system " $1 " globally exported, read-only."
    444  1.15       mrg 		else
    445  1.15       mrg 			print "File system " $1 " globally exported, read-write."
    446  1.32     lukem 	}' < /etc/exports > $OUTPUT
    447  1.32     lukem 	if [ -s $OUTPUT ] ; then
    448  1.15       mrg 		printf "\nChecking for globally exported file systems.\n"
    449  1.15       mrg 		cat $OUTPUT
    450  1.15       mrg 	fi
    451   1.9       cgd fi
    452   1.9       cgd 
    453   1.9       cgd # Display any changes in setuid files and devices.
    454  1.32     lukem #
    455  1.31     lukem if checkyesno check_devices; then
    456  1.28     lukem 	> $ERR
    457  1.15       mrg 	(find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
    458  1.15       mrg 			-o -fstype procfs \) -a -prune -o \
    459  1.21   mycroft 	    \( \( -perm -u+s -a ! -type d \) -o \
    460  1.21   mycroft 	       \( -perm -g+s -a ! -type d \) -o \
    461  1.24     lukem 	       -type b -o -type c \) -print0 | \
    462  1.24     lukem 	xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
    463  1.15       mrg 
    464  1.15       mrg 	# Display any errors that occurred during system file walk.
    465  1.15       mrg 	if [ -s $OUTPUT ] ; then
    466  1.28     lukem 		printf "Setuid/device find errors:\n" >> $ERR
    467  1.28     lukem 		cat $OUTPUT >> $ERR
    468  1.28     lukem 		printf "\n" >> $ERR
    469  1.15       mrg 	fi
    470  1.15       mrg 
    471  1.15       mrg 	# Display any changes in the setuid file list.
    472  1.15       mrg 	egrep -v '^[bc]' $LIST > $TMP1
    473  1.15       mrg 	if [ -s $TMP1 ] ; then
    474  1.15       mrg 		# Check to make sure uudecode isn't setuid.
    475  1.15       mrg 		if grep -w uudecode $TMP1 > /dev/null ; then
    476  1.28     lukem 			printf "\nUudecode is setuid.\n" >> $ERR
    477  1.15       mrg 		fi
    478  1.15       mrg 
    479  1.15       mrg 		CUR=/var/backups/setuid.current
    480  1.15       mrg 		BACK=/var/backups/setuid.backup
    481   1.9       cgd 
    482  1.15       mrg 		if [ -s $CUR ] ; then
    483  1.15       mrg 			if cmp -s $CUR $TMP1 ; then
    484  1.15       mrg 				:
    485  1.15       mrg 			else
    486  1.15       mrg 				> $TMP2
    487  1.15       mrg 				join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
    488  1.15       mrg 				if [ -s $OUTPUT ] ; then
    489  1.28     lukem 					printf "Setuid additions:\n" >> $ERR
    490  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    491  1.28     lukem 					printf "\n" >> $ERR
    492  1.15       mrg 				fi
    493  1.15       mrg 
    494  1.15       mrg 				join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
    495  1.15       mrg 				if [ -s $OUTPUT ] ; then
    496  1.28     lukem 					printf "Setuid deletions:\n" >> $ERR
    497  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    498  1.28     lukem 					printf "\n" >> $ERR
    499  1.15       mrg 				fi
    500  1.15       mrg 
    501  1.20   mycroft 				sort -k10 $TMP2 $CUR $TMP1 | \
    502  1.27     lukem 				    sed -e 's/[	 ][	 ]*/ /g' | \
    503  1.27     lukem 				    uniq -u > $OUTPUT
    504  1.15       mrg 				if [ -s $OUTPUT ] ; then
    505  1.28     lukem 					printf "Setuid changes:\n" >> $ERR
    506  1.28     lukem 					column -t $OUTPUT >> $ERR
    507  1.28     lukem 					printf "\n" >> $ERR
    508  1.15       mrg 				fi
    509   1.9       cgd 
    510  1.15       mrg 				cp $CUR $BACK
    511  1.15       mrg 				cp $TMP1 $CUR
    512   1.9       cgd 			fi
    513  1.15       mrg 		else
    514  1.28     lukem 			printf "Setuid additions:\n" >> $ERR
    515  1.28     lukem 			column -t $TMP1 >> $ERR
    516  1.28     lukem 			printf "\n" >> $ERR
    517   1.9       cgd 			cp $TMP1 $CUR
    518   1.9       cgd 		fi
    519  1.15       mrg 	fi
    520  1.15       mrg 
    521  1.27     lukem 	# Check for block and character disk devices that are readable or
    522  1.27     lukem 	# writeable or not owned by root.operator.
    523  1.15       mrg 	>$TMP1
    524  1.27     lukem 	DISKLIST="acd ccd cd ch fd hk hp mcd md ra rb rd rl rx rz \
    525  1.27     lukem 	    sd se ss tz uk up vnd wd xd xy"
    526  1.27     lukem #	DISKLIST="$DISKLIST ct mt st wt"
    527  1.15       mrg 	for i in $DISKLIST; do
    528  1.15       mrg 		egrep "^b.*/${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
    529  1.15       mrg 		egrep "^c.*/r${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
    530  1.15       mrg 	done
    531  1.15       mrg 
    532  1.15       mrg 	awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
    533  1.25     lukem 		{ printf "Disk %s is user %s, group %s, permissions %s.\n", \
    534  1.25     lukem 		    $11, $3, $4, $1; }' < $TMP1 > $OUTPUT
    535  1.15       mrg 	if [ -s $OUTPUT ] ; then
    536  1.28     lukem 		printf "\nChecking disk ownership and permissions.\n" >> $ERR
    537  1.28     lukem 		cat $OUTPUT >> $ERR
    538  1.28     lukem 		printf "\n" >> $ERR
    539   1.9       cgd 	fi
    540   1.9       cgd 
    541  1.15       mrg 	# Display any changes in the device file list.
    542  1.20   mycroft 	egrep '^[bc]' $LIST | sort -k11 > $TMP1
    543  1.15       mrg 	if [ -s $TMP1 ] ; then
    544  1.15       mrg 		CUR=/var/backups/device.current
    545  1.15       mrg 		BACK=/var/backups/device.backup
    546  1.15       mrg 
    547  1.15       mrg 		if [ -s $CUR ] ; then
    548  1.15       mrg 			if cmp -s $CUR $TMP1 ; then
    549  1.15       mrg 				:
    550  1.15       mrg 			else
    551  1.15       mrg 				> $TMP2
    552  1.15       mrg 				join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
    553  1.15       mrg 				if [ -s $OUTPUT ] ; then
    554  1.28     lukem 					printf "Device additions:\n" >> $ERR
    555  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    556  1.28     lukem 					printf "\n" >> $ERR
    557  1.15       mrg 				fi
    558  1.15       mrg 
    559  1.15       mrg 				join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
    560  1.15       mrg 				if [ -s $OUTPUT ] ; then
    561  1.28     lukem 					printf "Device deletions:\n" >> $ERR
    562  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    563  1.28     lukem 					printf "\n" >> $ERR
    564  1.15       mrg 				fi
    565  1.15       mrg 
    566  1.27     lukem 				# Report any block device change. Ignore
    567  1.27     lukem 				# character devices, only the name is
    568  1.27     lukem 				# significant.
    569  1.15       mrg 				cat $TMP2 $CUR $TMP1 | \
    570  1.27     lukem 				    sed -e '/^c/d' | \
    571  1.27     lukem 				    sort -k11 | \
    572  1.27     lukem 				    sed -e 's/[	 ][	 ]*/ /g' | \
    573  1.27     lukem 				    uniq -u > $OUTPUT
    574  1.15       mrg 				if [ -s $OUTPUT ] ; then
    575  1.28     lukem 					printf "Block device changes:\n" >> $ERR
    576  1.28     lukem 					column -t $OUTPUT >> $ERR
    577  1.28     lukem 					printf "\n" >> $ERR
    578  1.15       mrg 				fi
    579   1.9       cgd 
    580  1.15       mrg 				cp $CUR $BACK
    581  1.15       mrg 				cp $TMP1 $CUR
    582   1.9       cgd 			fi
    583  1.15       mrg 		else
    584  1.28     lukem 			printf "Device additions:\n" >> $ERR
    585  1.28     lukem 			column -t $TMP1 >> $ERR
    586  1.28     lukem 			printf "\n" >> $ERR
    587  1.28     lukem 			cp $TMP1 $CUR >> $ERR
    588   1.9       cgd 		fi
    589  1.28     lukem 	fi
    590  1.28     lukem 	if [ -s $ERR ] ; then
    591  1.28     lukem 		printf "\nChecking setuid files and devices:\n"
    592  1.28     lukem 		cat $ERR
    593  1.28     lukem 		printf "\n"
    594   1.9       cgd 	fi
    595   1.9       cgd fi
    596   1.9       cgd 
    597   1.9       cgd # Check special files.
    598   1.9       cgd # Check system binaries.
    599   1.9       cgd #
    600   1.9       cgd # Create the mtree tree specifications using:
    601   1.9       cgd #
    602   1.9       cgd #	mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
    603  1.38    kleink #	chown root:wheel DIR.secure
    604  1.16     mikel #	chmod 600 DIR.secure
    605   1.9       cgd #
    606   1.9       cgd # Note, this is not complete protection against Trojan horsed binaries, as
    607   1.9       cgd # the hacker can modify the tree specification to match the replaced binary.
    608   1.9       cgd # For details on really protecting yourself against modified binaries, see
    609   1.9       cgd # the mtree(8) manual page.
    610  1.32     lukem #
    611  1.31     lukem if checkyesno check_mtree; then
    612   1.9       cgd 	mtree -e -p / -f /etc/mtree/special > $OUTPUT
    613  1.15       mrg 	if [ -s $OUTPUT ]; then
    614   1.9       cgd 		printf "\nChecking special files and directories.\n"
    615   1.9       cgd 		cat $OUTPUT
    616   1.9       cgd 	fi
    617   1.9       cgd 
    618   1.9       cgd 	> $OUTPUT
    619  1.16     mikel 	for file in /etc/mtree/*.secure; do
    620  1.16     mikel 		[ $file = '/etc/mtree/*.secure' ] && continue
    621   1.9       cgd 		tree=`sed -n -e '3s/.* //p' -e 3q $file`
    622   1.9       cgd 		mtree -f $file -p $tree > $TMP1
    623   1.9       cgd 		if [ -s $TMP1 ]; then
    624   1.9       cgd 			printf "\nChecking $tree:\n" >> $OUTPUT
    625   1.9       cgd 			cat $TMP1 >> $OUTPUT
    626   1.9       cgd 		fi
    627   1.9       cgd 	done
    628  1.15       mrg 	if [ -s $OUTPUT ]; then
    629   1.9       cgd 		printf "\nChecking system binaries:\n"
    630   1.9       cgd 		cat $OUTPUT
    631   1.9       cgd 	fi
    632   1.9       cgd fi
    633   1.9       cgd 
    634  1.32     lukem CHANGELIST=""
    635  1.32     lukem 
    636  1.32     lukem # Backup disklabels of available disks
    637  1.32     lukem #
    638  1.32     lukem if checkyesno check_disklabels; then
    639  1.32     lukem 		# generate list of old disklabels and remove them
    640  1.32     lukem 	ls -1d /var/backups/disklabel.* 2>/dev/null |
    641  1.32     lukem 	    egrep -v '\.(backup|current)$' > $LABELS
    642  1.32     lukem 	xargs rm < $LABELS
    643  1.32     lukem 
    644  1.40     perry 	disks=`iostat -x | sed 1d | awk '$1 !~ /^[cfm]d/ { print $1; }'`
    645  1.32     lukem 	for i in $disks; do
    646  1.32     lukem 		dlf="/var/backups/disklabel.$i"
    647  1.32     lukem 		disklabel $i > $dlf 2>/dev/null
    648  1.32     lukem 	done
    649  1.32     lukem 
    650  1.32     lukem 		# append list of new disklabels, sort list
    651  1.32     lukem 	ls -1d /var/backups/disklabel.* 2>/dev/null |
    652  1.32     lukem 	    egrep -v '\.(backup|current)$' >> $LABELS
    653  1.32     lukem 	sort -u -o $LABELS $LABELS
    654  1.32     lukem 	CHANGELIST=$LABELS
    655  1.32     lukem fi
    656  1.32     lukem 
    657   1.9       cgd # List of files that get backed up and checked for any modifications.  Each
    658   1.9       cgd # file is expected to have two backups, /var/backups/file.{current,backup}.
    659   1.9       cgd # Any changes cause the files to rotate.
    660  1.32     lukem #
    661  1.31     lukem if checkyesno check_changelist && [ -s /etc/changelist ] ; then
    662  1.32     lukem 	CHANGELIST="/etc/changelist $CHANGELIST"
    663  1.32     lukem fi
    664  1.32     lukem 
    665  1.32     lukem if [ -n "$CHANGELIST" ]; then
    666  1.32     lukem 	for file in `egrep -hv "^#|$MP" $CHANGELIST`; do
    667   1.9       cgd 		CUR=/var/backups/`basename $file`.current
    668   1.9       cgd 		BACK=/var/backups/`basename $file`.backup
    669  1.30   mycroft 		if [ -f $file ]; then
    670  1.30   mycroft 			if [ -f $CUR ] ; then
    671   1.9       cgd 				diff $CUR $file > $OUTPUT
    672   1.9       cgd 				if [ -s $OUTPUT ] ; then
    673   1.9       cgd 		printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
    674   1.9       cgd 					cat $OUTPUT
    675  1.30   mycroft 					mv -f $CUR $BACK
    676   1.9       cgd 					cp -p $file $CUR
    677  1.38    kleink 					chown root:wheel $CUR
    678   1.9       cgd 				fi
    679   1.9       cgd 			else
    680  1.30   mycroft 		printf "\n======\n%s added\n======\n" $file
    681  1.30   mycroft 				diff /dev/null $file
    682   1.9       cgd 				cp -p $file $CUR
    683  1.38    kleink 				chown root:wheel $CUR
    684  1.30   mycroft 			fi
    685  1.30   mycroft 		else
    686  1.30   mycroft 			if [ -f $CUR ]; then
    687  1.30   mycroft 		printf "\n======\n%s removed\n======\n" $file
    688  1.30   mycroft 				diff $CUR /dev/null
    689  1.30   mycroft 				mv -f $CUR $BACK
    690   1.9       cgd 			fi
    691   1.9       cgd 		fi
    692   1.9       cgd 	done
    693  1.42      fair fi
    694  1.42      fair 
    695  1.42      fair # run skeyaudit to inform users of ready to expire S/Keys
    696  1.42      fair #
    697  1.42      fair if checkyesno run_skeyaudit; then
    698  1.42      fair 	skeyaudit
    699   1.9       cgd fi
    700