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