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