xref: /csrg-svn/etc/security (revision 53140)
142328Sbostic#!/bin/sh -
242328Sbostic#
3*53140Sbostic#	@(#)security	5.17 (Berkeley) 04/08/92
442328Sbostic#
553105Sbostic
653105Sbostic# Script to check basic system security.  Checks included are:
753130Sbostic#	Password and group file check.
853130Sbostic#	Root umask, dot in root's path.
953130Sbostic#	Root and uucp in /etc/ftpusers.
1053130Sbostic#	Entry for uudecode in /etc/aliases, if uudecode is setuid.
1153130Sbostic#	Hosts.equiv syntax.
1253130Sbostic#	Special users that have .rhosts files, .rhosts file syntax.
1353105Sbostic#	Home directory and dot-file ownership and permissions.
1453105Sbostic#	Mailbox ownership and permissions.
1553130Sbostic#	Globally exported NFS file systems.
1653105Sbostic#	Changes in setuid and device files.
1753105Sbostic#	Block and character disk device ownership and permissions.
1853130Sbostic#	File list from /etc/mtree/special.
1953105Sbostic#	System binaries as described by files in /etc/mtree.
2053105Sbostic
2152578SbosticPATH=/sbin:/usr/sbin:/bin:/usr/bin
2242328Sbostic
2353130Sbosticumask 077
2452215Sbostic
2553098SbosticERR=/tmp/_secure1.$$
2653098SbosticTMP1=/tmp/_secure2.$$
2753098SbosticTMP2=/tmp/_secure3.$$
2853130SbosticTMP3=/tmp/_secure4.$$
2953130SbosticLIST=/tmp/_secure5.$$
3053130SbosticOUTPUT=/tmp/_secure6.$$
3152578Sbostic
3253130Sbostictrap 'rm -f $ERR $TMP1 $TMP2 $TMP3 $LIST $OUTPUT' 0
3352578Sbostic
3453130Sbostic# Check the password file syntax.
3553130SbosticMP=/etc/master.passwd
3653130Sbosticawk -F: '{
3753130Sbostic	if ($0 ~ /^[	 ]*$/) {
3853130Sbostic		printf("Line %d is a blank line.\n", NR);
3953130Sbostic		next;
4053130Sbostic	}
4153130Sbostic	if (NF != 10)
4253130Sbostic		printf("Line %d has the wrong number of fields.\n", NR);
4353130Sbostic	if ($1 !~ /[A-za-z0-9]*/)
4453130Sbostic		printf("Login %s has non-numeric characters.\n", $1);
4553130Sbostic	if (length($1) > 8)
4653130Sbostic		printf("Login %s has more than 8 characters.\n", $1);
4753130Sbostic	if ($2 == "")
4853130Sbostic		printf("Login %s has no password.\n", $1);
4953130Sbostic	if (length($2) != 13 && ($10 ~ /.*sh$/ || $10 == ""))
5053130Sbostic		printf("Login %s is off but still has a valid shell.\n", $1);
5153130Sbostic	if ($3 == 0 && $1 != "root" && $1 != "toor")
5253130Sbostic		printf("Login %s has a user id of 0.\n", $1);
5353130Sbostic	if ($3 < 0)
5453130Sbostic		printf("Login %s has a negative user id.\n", $1);
5553130Sbostic	if ($4 < 0)
5653130Sbostic		printf("Login %s has a negative user id.\n", $1);
5753130Sbostic}' < $MP > $OUTPUT
5853130Sbosticif [ -s $OUTPUT ] ; then
5953130Sbostic	printf "\nChecking the $MP file:\n"
6053130Sbostic	cat $OUTPUT
6153130Sbosticfi
6242328Sbostic
6353130Sbosticawk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
6453130Sbosticif [ -s $OUTPUT ] ; then
6553130Sbostic	printf "\n$MP has duplicate user names.\n"
6653130Sbostic	column $OUTPUT
6753130Sbosticfi
6852573Sbostic
6953130Sbosticawk -F: '{ print $1 " " $3 }' $MP | sort -n +1 | tee $TMP1 |
7053130Sbosticuniq -d -f 1 | awk '{ print $2 }' > $TMP2
7153130Sbosticif [ -s $TMP2 ] ; then
7253130Sbostic	printf "\n$MP has duplicate user id's.\n"
7353130Sbostic        while read uid; do
7453130Sbostic                grep -w $uid $TMP1
7553130Sbostic        done < $TMP2 | column
7653130Sbosticfi
7753104Sbostic
7853130Sbostic# Check the group file syntax.
7953130SbosticGRP=/etc/group
8053130Sbosticawk -F: '{
8153130Sbostic	if ($0 ~ /^[	 ]*$/) {
8253130Sbostic		printf("Line %d is a blank line.\n", NR);
8353130Sbostic		next;
8453130Sbostic	}
8553130Sbostic	if (NF != 4)
8653130Sbostic		printf("Line %d has the wrong number of fields.\n", NR);
8753130Sbostic	if ($1 !~ /[A-za-z0-9]*/)
8853130Sbostic		printf("Group %s has non-numeric characters.\n", $1);
8953130Sbostic	if (length($1) > 8)
9053130Sbostic		printf("Group %s has more than 8 characters.\n", $1);
9153130Sbostic	if ($3 !~ /[0-9]*/)
9253130Sbostic		printf("Login %s has a negative user id.\n", $1);
9353130Sbostic}' < $GRP > $OUTPUT
9453130Sbosticif [ -s $OUTPUT ] ; then
9553130Sbostic	printf "\nChecking the $GRP file:\n"
9653130Sbostic	cat $OUTPUT
9753130Sbosticfi
9853130Sbostic
9953130Sbosticawk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
10053130Sbosticif [ -s $OUTPUT ] ; then
10153130Sbostic	printf "\n$GRP has duplicate group names.\n"
10253130Sbostic	column $OUTPUT
10353130Sbosticfi
10453130Sbostic
10553130Sbostic# Check for root paths, umask values in startup files.
10653130Sbostic> $OUTPUT
10753130Sbosticrhome=/root
10853130Sbosticumaskset=no
10953130Sbosticlist="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
11053130Sbosticfor i in $list ; do
11153130Sbostic	if [ -f $i ] ; then
11253130Sbostic		if egrep umask $i > /dev/null ; then
11353130Sbostic			umaskset=yes
11453104Sbostic		fi
11553130Sbostic		egrep umask $i |
11653130Sbostic		awk '$2 % 100 < 20 \
11753130Sbostic			{ print "Root umask is group writeable" }
11853130Sbostic		     $2 % 10 < 2 \
11953130Sbostic			{ print "Root umask is other writeable" }' >> $OUTPUT
12053130Sbostic		/bin/csh -f -s << end-of-csh > /dev/null 2>&1
12153130Sbostic			unset path
12253130Sbostic			source $i
12353130Sbostic			/bin/ls -ldgT \$path > $TMP1
12453130Sbosticend-of-csh
12553130Sbostic		awk '{
12653130Sbostic			if ($10 ~ /\./) {
12753130Sbostic				print "The root path includes .";
12853130Sbostic				next;
12953130Sbostic			}
13053130Sbostic		     }
13153130Sbostic		     $1 ~ /^d....w/ \
13253130Sbostic        { print "Root path directory " $10 " is group writeable." } \
13353130Sbostic		     $1 ~ /^d.......w/ \
13453130Sbostic        { print "Root path directory " $10 " is other writeable." }' \
13553130Sbostic		< $TMP1 >> $OUTPUT
13653130Sbostic	fi
13753130Sbosticdone
13853130Sbosticif [ $umaskset = "no" -o -s $OUTPUT ] ; then
13953130Sbostic	printf "\nChecking root csh paths, umask values:\n$list\n"
14053130Sbostic	if [ -s $OUTPUT ]; then
14153130Sbostic		cat $OUTPUT
14253130Sbostic	fi
14353130Sbostic	if [ $umaskset = "no" ] ; then
14453130Sbostic		printf "\nRoot csh startup files do not set the umask.\n"
14553130Sbostic	fi
14653130Sbosticfi
14753104Sbostic
14853130Sbostic> $OUTPUT
14953130Sbosticrhome=/root
15053130Sbosticumaskset=no
15153130Sbosticlist="${rhome}/.profile"
15253130Sbosticfor i in $list; do
15353130Sbostic	if [ -f $i ] ; then
15453130Sbostic		if egrep umask $i > /dev/null ; then
15553130Sbostic			umaskset=yes
15653130Sbostic		fi
15753130Sbostic		egrep umask $i |
15853130Sbostic		awk '$2 % 100 < 20 \
15953130Sbostic			{ print "Root umask is group writeable" } \
16053130Sbostic		     $2 % 10 < 2 \
16153130Sbostic			{ print "Root umask is other writeable" }' >> $OUTPUT
16253130Sbostic		/bin/sh << end-of-sh > /dev/null 2>&1
16353130Sbostic			PATH=
16453130Sbostic			. $i
16553130Sbostic			list=\`echo \$PATH | /usr/bin/sed -e 's/:/ /g'\`
16653130Sbostic			/bin/ls -ldgT \$list > $TMP1
16753130Sbosticend-of-sh
16853130Sbostic		awk '{
16953130Sbostic			if ($10 ~ /\./) {
17053130Sbostic				print "The root path includes .";
17153130Sbostic				next;
17253130Sbostic			}
17353130Sbostic		     }
17453130Sbostic		     $1 ~ /^d....w/ \
17553130Sbostic        { print "Root path directory " $10 " is group writeable." } \
17653130Sbostic		     $1 ~ /^d.......w/ \
17753130Sbostic        { print "Root path directory " $10 " is other writeable." }' \
17853130Sbostic		< $TMP1 >> $OUTPUT
17953130Sbostic
18053130Sbostic	fi
18153130Sbosticdone
18253130Sbosticif [ $umaskset = "no" -o -s $OUTPUT ] ; then
18353130Sbostic	printf "\nChecking root sh paths, umask values:\n$list\n"
18453130Sbostic	if [ -s $OUTPUT ]; then
18553130Sbostic		cat $OUTPUT
18653130Sbostic	fi
18753130Sbostic	if [ $umaskset = "no" ] ; then
18853130Sbostic		printf "\nRoot sh startup files do not set the umask.\n"
18953130Sbostic	fi
19053130Sbosticfi
19153130Sbostic
19253130Sbostic# Root and uucp should both be in /etc/ftpusers.
19353130Sbosticif egrep root /etc/ftpusers > /dev/null ; then
19453130Sbostic	:
19553130Sbosticelse
19653130Sbostic	printf "\nRoot not listed in /etc/ftpusers file.\n"
19753130Sbosticfi
19853130Sbosticif egrep uucp /etc/ftpusers > /dev/null ; then
19953130Sbostic	:
20053130Sbosticelse
20153130Sbostic	printf "\nUucp not listed in /etc/ftpusers file.\n"
20253130Sbosticfi
20353130Sbostic
20453130Sbostic# Uudecode should not be in the aliases file.
20553130Sbosticif grep -w uudecode /etc/aliases; then
20653130Sbostic	printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
20753130Sbosticfi
20853130Sbostic
20953130Sbostic# Check for plus signs in /etc/hosts.equiv.
21053130Sbosticif egrep '\+|^$' /etc/hosts.equiv > /dev/null ; then
21153130Sbostic	printf "\nEmpty line or + in /etc/hosts.equiv file.\n"
21253130Sbosticfi
21353130Sbostic
21453130Sbostic# Check for special users with .rhosts files.  Only root and toor should
21553130Sbostic# have a .rhosts files.  Also, .rhosts files should not have blank lines
21653130Sbostic# or plus signs.
21753130Sbosticawk -F: '$1 != "root" && $1 != "toor" && \
21853130Sbostic	($3 < 100 || $1 == "ftp" || $1 == "uucp") \
21953130Sbostic		{ print $1 " " $6 }' /etc/passwd |
22053130Sbosticwhile read uid homedir; do
22153130Sbostic	if [ -f ${homedir}/.rhosts ] ; then
22253130Sbostic		rhost=`ls -ldgT ${homedir}/.rhosts`
22353130Sbostic		printf "$uid: $rhost\n"
22453130Sbostic	fi
22553130Sbosticdone > $OUTPUT
22653130Sbosticif [ -s $OUTPUT ] ; then
22753130Sbostic	printf "\nChecking for special users with .rhosts files.\n"
22853130Sbostic	cat $OUTPUT
22953130Sbosticfi
23053130Sbostic
23153130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
23253130Sbosticwhile read uid homedir; do
23353130Sbostic	if [ -f ${homedir}/.rhosts ] && \
23453130Sbostic	    egrep '\+|^$' ${homedir}/.rhosts > /dev/null ; then
23553130Sbostic		printf "$uid: empty line or + in .rhosts file.\n"
23653130Sbostic	fi
23753130Sbosticdone > $OUTPUT
23853130Sbosticif [ -s $OUTPUT ] ; then
23953130Sbostic	printf "\nChecking .rhosts files syntax.\n"
24053130Sbostic	cat $OUTPUT
24153130Sbosticfi
24253130Sbostic
24353130Sbostic# Check home directories, dot files.
24453105Sbostic# Directories should not be owned by someone else or writeable.
24553130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
24653105Sbosticwhile read uid homedir; do
24753105Sbostic	if [ -d ${homedir}/ ] ; then
24853105Sbostic		file=`ls -ldgT ${homedir}`
24953130Sbostic		printf "$uid $file\n"
25053105Sbostic	fi
25153130Sbosticdone |
25253130Sbosticawk '$1 != $4 && $4 != "root" \
25353130Sbostic	{ print "user " $1 " home directory is owned by " $4 }
25453130Sbostic     $2 ~ /^-....w/ \
25553130Sbostic	{ print "user " $1 " home directory is group writeable" }
25653130Sbostic     $2 ~ /^-.......w/ \
25753130Sbostic	{ print "user " $1 " home directory is other writeable" }' > $OUTPUT
25853130Sbosticif [ -s $OUTPUT ] ; then
25953130Sbostic	printf "\nChecking home directories.\n"
26053130Sbostic	cat $OUTPUT
26153130Sbosticfi
26253105Sbostic
26353104Sbostic# Files that should not be owned by someone else or readable.
26453130Sbosticlist=".netrc .rhosts"
26553130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
26653104Sbosticwhile read uid homedir; do
26753130Sbostic	for f in $list ; do
26853130Sbostic		file=${homedir}/${f}
26953130Sbostic		if [ -f $file ] ; then
27053130Sbostic			printf "$uid $f `ls -ldgT $file`\n"
27153130Sbostic		fi
27253130Sbostic	done
27353130Sbosticdone |
27453130Sbosticawk '$1 != $5 && $5 != "root" \
27553130Sbostic	{ print "user " $1 " " $2 " file is owned by " $5 }
27653130Sbostic     $3 ~ /^-...r/ \
27753130Sbostic	{ print "user " $1 " " $2 " file is group readable" }
27853130Sbostic     $3 ~ /^-......r/ \
27953130Sbostic	{ print "user " $1 " " $2 " file is other readable" }
28053130Sbostic     $3 ~ /^-....w/ \
28153130Sbostic	{ print "user " $1 " " $2 " file is group writeable" }
28253130Sbostic     $3 ~ /^-.......w/ \
28353130Sbostic	{ print "user " $1 " " $2 " file is other writeable" }' > $OUTPUT
28453104Sbostic
28553104Sbostic# Files that should not be owned by someone else or writeable.
28653130Sbosticlist=".bashrc .cshrc .emacsrc .exrc .forward .klogin .login .logout \
28753130Sbostic      .profile .tcshrc"
28853130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
28953104Sbosticwhile read uid homedir; do
29053130Sbostic	for f in $list ; do
29153130Sbostic		file=${homedir}/${f}
29253130Sbostic		if [ -f $file ] ; then
29353130Sbostic			printf "$uid $f `ls -ldgT $file`\n"
29453130Sbostic		fi
29553130Sbostic	done
29653130Sbosticdone |
29753130Sbosticawk '$1 != $5 && $5 != "root" \
29853130Sbostic	{ print "user " $1 " " $2 " file is owned by " $5 }
29953130Sbostic     $3 ~ /^-....w/ \
30053130Sbostic	{ print "user " $1 " " $2 " file is group writeable" }
30153130Sbostic     $3 ~ /^-.......w/ \
30253130Sbostic	{ print "user " $1 " " $2 " file is other writeable" }' >> $OUTPUT
30353130Sbosticif [ -s $OUTPUT ] ; then
30453130Sbostic	printf "\nChecking dot files.\n"
30553130Sbostic	cat $OUTPUT
30653130Sbosticfi
30753104Sbostic
30853104Sbostic# Check mailbox ownership and permissions.
30953130Sbosticls -l /var/mail | sed 1d | \
31053130Sbosticawk '$3 != $9 \
31153130Sbostic	{ print "user " $9 " mailbox is owned by " $3 }
31253130Sbostic     $1 != "-rw-------" \
31353130Sbostic	{ print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
31453130Sbosticif [ -s $OUTPUT ] ; then
31553130Sbostic	printf "\nChecking mailbox ownership.\n"
31653130Sbostic	cat $OUTPUT
31753130Sbosticfi
31853104Sbostic
31953105Sbostic# Check for globally exported file systems.
32053105Sbosticawk '{
32153105Sbostic	readonly = 0;
32253105Sbostic	for (i = 2; i <= NF; ++i) {
32353105Sbostic		if ($i ~ /-ro/)
32453105Sbostic			readonly = 1;
32553105Sbostic		else if ($i !~ /^-/)
32653105Sbostic			next;
32753105Sbostic	}
32853105Sbostic	if (readonly)
32953105Sbostic		print "File system " $1 " globally exported, read-only."
33053105Sbostic	else
33153105Sbostic		print "File system " $1 " globally exported, read-write."
33253130Sbostic}' < /etc/exports > $OUTPUT
33353130Sbosticif [ -s $OUTPUT ] ; then
33453130Sbostic	printf "\nChecking for globally exported file systems.\n"
33553130Sbostic	cat $OUTPUT
33653130Sbosticfi
33753105Sbostic
33853098Sbostic# Display setuid and device changes.
33953130Sbosticprintf "\nChecking setuid files and devices:\n"
34053130Sbostic(find / ! -fstype local -a -prune -o \
34153130Sbostic    \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l -a \
34253130Sbostic       ! -type s \) | \
34353130Sbosticsort | sed -e 's/^/ls -ldgT /' | sh > $LIST) 2> $OUTPUT
34442328Sbostic
34553098Sbostic# Display any errors that occurred during system file walk.
34653130Sbosticif [ -s $OUTPUT ] ; then
34753130Sbostic	printf "Setuid/device find errors:\n"
34853130Sbostic	cat $OUTPUT
34953130Sbostic	printf "\n"
35042328Sbosticfi
35142328Sbostic
35253098Sbostic# Display any changes in the setuid file list.
35353130Sbosticegrep -v '^[bc]' $LIST > $TMP1
35452215Sbostic
35553130Sbosticif [ -s $TMP1 ] ; then
35653130Sbostic	# Check to make sure uudecode isn't setuid.
35753130Sbostic	if grep -w uudecode $TMP1 > /dev/null ; then
35853130Sbostic		printf "\nUudecode is setuid.\n"
35953130Sbostic	fi
36053130Sbostic
36153130Sbostic	CUR=/var/backups/setuid.current
36253130Sbostic	BACK=/var/backups/setuid.backup
36353130Sbostic
36453098Sbostic	if [ -s $CUR ] ; then
36553130Sbostic		if cmp -s $CUR $TMP1 ; then
36652573Sbostic			:
36752573Sbostic		else
36853130Sbostic			> $TMP2
36953130Sbostic			join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
37053130Sbostic			if [ -s $OUTPUT ] ; then
37153130Sbostic				printf "Setuid additions:\n"
37253130Sbostic				tee -a $TMP2 < $OUTPUT
37353130Sbostic				printf "\n"
37452573Sbostic			fi
37552573Sbostic
37653130Sbostic			join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
37753130Sbostic			if [ -s $OUTPUT ] ; then
37853130Sbostic				printf "Setuid deletions:\n"
37953130Sbostic				tee -a $TMP2 < $OUTPUT
38053130Sbostic				printf "\n"
38152573Sbostic			fi
38252573Sbostic
38353130Sbostic			sort +9 $TMP2 $CUR $TMP1 | \
38453130Sbostic			    sed -e 's/[	 ][	 ]*/ /g' | uniq -u > $OUTPUT
38553130Sbostic			if [ -s $OUTPUT ] ; then
38653130Sbostic				printf "Setuid changes:\n"
38753130Sbostic				column -t $OUTPUT
38853130Sbostic				printf "\n"
38952573Sbostic			fi
39052573Sbostic
39153130Sbostic			cp $CUR $BACK
39253130Sbostic			cp $TMP1 $CUR
39352573Sbostic		fi
39452573Sbostic	else
39553130Sbostic		printf "Setuid additions:\n"
396*53140Sbostic		column -t $TMP1
39753130Sbostic		printf "\n"
39853130Sbostic		cp $TMP1 $CUR
39952573Sbostic	fi
40052215Sbosticfi
40152215Sbostic
402*53140Sbostic# Check for block and character disk devices, that are readable or writeable
403*53140Sbostic# or not owned by root.operator.
40453130Sbosticegrep '^b' $LIST > $TMP1
40553130Sbosticegrep '^c.*/rdk[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
40653130Sbosticegrep '^c.*/rfd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
40753130Sbosticegrep '^c.*/rhd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
40853130Sbosticegrep '^c.*/rhk[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
40953130Sbosticegrep '^c.*/rhp[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41053130Sbosticegrep '^c.*/rjb[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41153130Sbosticegrep '^c.*/rkra[0-9][0-9]*[a-h]$' $LIST >> $TMP1
41253130Sbosticegrep '^c.*/rra[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41353130Sbosticegrep '^c.*/rrb[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41453130Sbosticegrep '^c.*/rrd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41553130Sbosticegrep '^c.*/rrl[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41653130Sbosticegrep '^c.*/rrx[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41753130Sbosticegrep '^c.*/rrz[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41853130Sbosticegrep '^c.*/rsd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
41953130Sbosticegrep '^c.*/rup[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
42053130Sbosticegrep '^c.*/rwd[0-9][0-9]*[a-h]$'  $LIST >> $TMP1
42153105Sbostic
422*53140Sbosticawk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
423*53140Sbostic	{ printf("Disk %s is user %s, group %s, permissions %s.\n", \
424*53140Sbostic	    $11, $3, $4, $1); }' < $TMP1 > $OUTPUT
42553130Sbosticif [ -s $OUTPUT ] ; then
42653130Sbostic	printf "\nChecking disk ownership and permissions.\n"
42753130Sbostic	cat $OUTPUT
42853130Sbostic	printf "\n"
42953130Sbosticfi
43053105Sbostic
431*53140Sbosticegrep '^[bc]' $LIST | sort +10 > $TMP1
43253098Sbostic# Display any changes in the device file list.
43353130Sbosticif [ -s $TMP1 ] ; then
43453130Sbostic	CUR=/var/backups/device.current
43553130Sbostic	BACK=/var/backups/device.backup
43653098Sbostic
43753098Sbostic	if [ -s $CUR ] ; then
43853130Sbostic		if cmp -s $CUR $TMP1 ; then
43953098Sbostic			:
44053098Sbostic		else
44153130Sbostic			> $TMP2
44253130Sbostic			join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
44353130Sbostic			if [ -s $OUTPUT ] ; then
44453130Sbostic				printf "Device additions:\n"
44553130Sbostic				tee -a $TMP2 < $OUTPUT
44653130Sbostic				printf "\n"
44753098Sbostic			fi
44853098Sbostic
44953130Sbostic			join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
45053130Sbostic			if [ -s $OUTPUT ] ; then
45153130Sbostic				printf "Device deletions:\n"
45253130Sbostic				tee -a $TMP2 < $OUTPUT
45353130Sbostic				printf "\n"
45453098Sbostic			fi
45553098Sbostic
456*53140Sbostic			# Report any block device change.  Ignore character
457*53140Sbostic			# devices, only the name is significant.
458*53140Sbostic			cat $TMP2 $CUR $TMP1 | \
459*53140Sbostic			sed -e '/^c/d' | \
460*53140Sbostic			sort +10 | \
46153130Sbostic			sed -e 's/[	 ][	 ]*/ /g' | \
462*53140Sbostic			uniq -u > $OUTPUT
46353130Sbostic			if [ -s $OUTPUT ] ; then
464*53140Sbostic				printf "Block device changes:\n"
46553130Sbostic				column -t $OUTPUT
46653130Sbostic				printf "\n"
46753098Sbostic			fi
46853098Sbostic
46953130Sbostic			cp $CUR $BACK
47053130Sbostic			cp $TMP1 $CUR
47153098Sbostic		fi
47253098Sbostic	else
47353130Sbostic		printf "Device additions:\n"
474*53140Sbostic		column -t $TMP1
47553130Sbostic		printf "\n"
47653130Sbostic		cp $TMP1 $CUR
47753098Sbostic	fi
47853098Sbosticfi
47953098Sbostic
48052578Sbostic# Check the system binaries.
48152578Sbostic# Create the mtree tree specifications using:
48252578Sbostic#
48353130Sbostic#	mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
48453130Sbostic#	chown root.wheel DIR.SECURE
48553130Sbostic#	chmod 600 DIR.SECURE
48652578Sbostic#
48752578Sbostic# Note, this is not complete protection against Trojan horsed binaries, as
48852578Sbostic# the hacker can modify the tree specification to match the replaced binary.
48952578Sbostic# For details on really protecting yourself against modified binaries, see
49052578Sbostic# the mtree(8) manual page.
49153130Sbostic# Check for special files.
49253130Sbostic
49352578Sbosticif cd /etc/mtree; then
49453130Sbostic	mtree -e -p / -f /etc/mtree/special > $OUTPUT
49553130Sbostic	if [ -s $OUTPUT ] ; then
49653130Sbostic		printf "\nChecking special files and directories.\n"
49753130Sbostic		cat $OUTPUT
49853130Sbostic	fi
49953130Sbostic
50053130Sbostic	> $OUTPUT
50152578Sbostic	for file in *.secure; do
50252578Sbostic		tree=`sed -n -e '3s/.* //p' -e 3q $file`
50353130Sbostic		mtree -f $file -p $tree > $TMP1
50453130Sbostic		if [ -s $TMP1 ]; then
50553130Sbostic			printf "\nChecking $tree:\n" >> $OUTPUT
50653130Sbostic			cat $TMP1 >> $OUTPUT
50753130Sbostic		fi
50852578Sbostic	done
50953130Sbostic	if [ -s $OUTPUT ] ; then
51053130Sbostic		printf "\nChecking system binaries:\n"
51153130Sbostic		cat $OUTPUT
51253130Sbostic	fi
51352578Sbosticfi
514