xref: /csrg-svn/etc/security (revision 62848)
142328Sbostic#!/bin/sh -
242328Sbostic#
3*62848Sbostic#	@(#)security	8.1 (Berkeley) 06/09/93
442328Sbostic#
553105Sbostic
652578SbosticPATH=/sbin:/usr/sbin:/bin:/usr/bin
742328Sbostic
853130Sbosticumask 077
952215Sbostic
1053098SbosticERR=/tmp/_secure1.$$
1153098SbosticTMP1=/tmp/_secure2.$$
1253098SbosticTMP2=/tmp/_secure3.$$
1353130SbosticTMP3=/tmp/_secure4.$$
1453130SbosticLIST=/tmp/_secure5.$$
1553130SbosticOUTPUT=/tmp/_secure6.$$
1652578Sbostic
1753130Sbostictrap 'rm -f $ERR $TMP1 $TMP2 $TMP3 $LIST $OUTPUT' 0
1852578Sbostic
1953184Sbostic# Check the master password file syntax.
2053130SbosticMP=/etc/master.passwd
2153130Sbosticawk -F: '{
2253130Sbostic	if ($0 ~ /^[	 ]*$/) {
2353130Sbostic		printf("Line %d is a blank line.\n", NR);
2453130Sbostic		next;
2553130Sbostic	}
2653130Sbostic	if (NF != 10)
2753130Sbostic		printf("Line %d has the wrong number of fields.\n", NR);
2853155Sbostic	if ($1 !~ /^[A-Za-z0-9]*$/)
2953308Sbostic		printf("Login %s has non-alphanumeric characters.\n", $1);
3053130Sbostic	if (length($1) > 8)
3153130Sbostic		printf("Login %s has more than 8 characters.\n", $1);
3253130Sbostic	if ($2 == "")
3353130Sbostic		printf("Login %s has no password.\n", $1);
3453130Sbostic	if (length($2) != 13 && ($10 ~ /.*sh$/ || $10 == ""))
3553130Sbostic		printf("Login %s is off but still has a valid shell.\n", $1);
3653130Sbostic	if ($3 == 0 && $1 != "root" && $1 != "toor")
3753130Sbostic		printf("Login %s has a user id of 0.\n", $1);
3853130Sbostic	if ($3 < 0)
3953130Sbostic		printf("Login %s has a negative user id.\n", $1);
4053130Sbostic	if ($4 < 0)
4153155Sbostic		printf("Login %s has a negative group id.\n", $1);
4253130Sbostic}' < $MP > $OUTPUT
4353130Sbosticif [ -s $OUTPUT ] ; then
4453130Sbostic	printf "\nChecking the $MP file:\n"
4553130Sbostic	cat $OUTPUT
4653130Sbosticfi
4742328Sbostic
4853130Sbosticawk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
4953130Sbosticif [ -s $OUTPUT ] ; then
5053130Sbostic	printf "\n$MP has duplicate user names.\n"
5153130Sbostic	column $OUTPUT
5253130Sbosticfi
5352573Sbostic
5453130Sbosticawk -F: '{ print $1 " " $3 }' $MP | sort -n +1 | tee $TMP1 |
5553130Sbosticuniq -d -f 1 | awk '{ print $2 }' > $TMP2
5653130Sbosticif [ -s $TMP2 ] ; then
5753130Sbostic	printf "\n$MP has duplicate user id's.\n"
5853130Sbostic        while read uid; do
5953130Sbostic                grep -w $uid $TMP1
6053130Sbostic        done < $TMP2 | column
6153130Sbosticfi
6253104Sbostic
6353264Sbostic# Backup the master password file; a special case, the normal backup
6453264Sbostic# mechanisms also print out file differences and we don't want to do
6553264Sbostic# that because this file has encrypted passwords in it.
6653264SbosticCUR=/var/backups/`basename $MP`.current
6753264SbosticBACK=/var/backups/`basename $MP`.backup
6853264Sbosticif [ -s $CUR ] ; then
6953264Sbostic	if cmp -s $CUR $MP; then
7053264Sbostic		:
7153264Sbostic	else
7253264Sbostic		cp -p $CUR $BACK
7353264Sbostic		cp -p $MP $CUR
7453264Sbostic		chown root.wheel $CUR
7553264Sbostic	fi
7653264Sbosticelse
7753264Sbostic	cp -p $MP $CUR
7853264Sbostic	chown root.wheel $CUR
7953264Sbosticfi
8053264Sbostic
8153130Sbostic# Check the group file syntax.
8253130SbosticGRP=/etc/group
8353130Sbosticawk -F: '{
8453130Sbostic	if ($0 ~ /^[	 ]*$/) {
8553130Sbostic		printf("Line %d is a blank line.\n", NR);
8653130Sbostic		next;
8753130Sbostic	}
8853130Sbostic	if (NF != 4)
8953130Sbostic		printf("Line %d has the wrong number of fields.\n", NR);
9053159Sbostic	if ($1 !~ /^[A-za-z0-9]*$/)
9153308Sbostic		printf("Group %s has non-alphanumeric characters.\n", $1);
9253130Sbostic	if (length($1) > 8)
9353130Sbostic		printf("Group %s has more than 8 characters.\n", $1);
9453130Sbostic	if ($3 !~ /[0-9]*/)
9553155Sbostic		printf("Login %s has a negative group id.\n", $1);
9653130Sbostic}' < $GRP > $OUTPUT
9753130Sbosticif [ -s $OUTPUT ] ; then
9853130Sbostic	printf "\nChecking the $GRP file:\n"
9953130Sbostic	cat $OUTPUT
10053130Sbosticfi
10153130Sbostic
10253130Sbosticawk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
10353130Sbosticif [ -s $OUTPUT ] ; then
10453130Sbostic	printf "\n$GRP has duplicate group names.\n"
10553130Sbostic	column $OUTPUT
10653130Sbosticfi
10753130Sbostic
10853130Sbostic# Check for root paths, umask values in startup files.
10953184Sbostic# The check for the root paths is problematical -- it's likely to fail
11053184Sbostic# in other environments.  Once the shells have been modified to warn
11153184Sbostic# of '.' in the path, the path tests should go away.
11253130Sbostic> $OUTPUT
11353130Sbosticrhome=/root
11453130Sbosticumaskset=no
11553130Sbosticlist="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
11653130Sbosticfor i in $list ; do
11753130Sbostic	if [ -f $i ] ; then
11853130Sbostic		if egrep umask $i > /dev/null ; then
11953130Sbostic			umaskset=yes
12053104Sbostic		fi
12153130Sbostic		egrep umask $i |
12253130Sbostic		awk '$2 % 100 < 20 \
12353130Sbostic			{ print "Root umask is group writeable" }
12453130Sbostic		     $2 % 10 < 2 \
12553130Sbostic			{ print "Root umask is other writeable" }' >> $OUTPUT
12653130Sbostic		/bin/csh -f -s << end-of-csh > /dev/null 2>&1
12753130Sbostic			unset path
12853130Sbostic			source $i
12953130Sbostic			/bin/ls -ldgT \$path > $TMP1
13053130Sbosticend-of-csh
13153130Sbostic		awk '{
13253159Sbostic			if ($10 ~ /^\.$/) {
13353130Sbostic				print "The root path includes .";
13453130Sbostic				next;
13553130Sbostic			}
13653130Sbostic		     }
13753130Sbostic		     $1 ~ /^d....w/ \
13853130Sbostic        { print "Root path directory " $10 " is group writeable." } \
13953130Sbostic		     $1 ~ /^d.......w/ \
14053130Sbostic        { print "Root path directory " $10 " is other writeable." }' \
14153130Sbostic		< $TMP1 >> $OUTPUT
14253130Sbostic	fi
14353130Sbosticdone
14453130Sbosticif [ $umaskset = "no" -o -s $OUTPUT ] ; then
14553130Sbostic	printf "\nChecking root csh paths, umask values:\n$list\n"
14653130Sbostic	if [ -s $OUTPUT ]; then
14753130Sbostic		cat $OUTPUT
14853130Sbostic	fi
14953130Sbostic	if [ $umaskset = "no" ] ; then
15053130Sbostic		printf "\nRoot csh startup files do not set the umask.\n"
15153130Sbostic	fi
15253130Sbosticfi
15353104Sbostic
15453130Sbostic> $OUTPUT
15553130Sbosticrhome=/root
15653130Sbosticumaskset=no
15753130Sbosticlist="${rhome}/.profile"
15853130Sbosticfor i in $list; do
15953130Sbostic	if [ -f $i ] ; then
16053130Sbostic		if egrep umask $i > /dev/null ; then
16153130Sbostic			umaskset=yes
16253130Sbostic		fi
16353130Sbostic		egrep umask $i |
16453130Sbostic		awk '$2 % 100 < 20 \
16553130Sbostic			{ print "Root umask is group writeable" } \
16653130Sbostic		     $2 % 10 < 2 \
16753130Sbostic			{ print "Root umask is other writeable" }' >> $OUTPUT
16853130Sbostic		/bin/sh << end-of-sh > /dev/null 2>&1
16953130Sbostic			PATH=
17053130Sbostic			. $i
17153130Sbostic			list=\`echo \$PATH | /usr/bin/sed -e 's/:/ /g'\`
17253130Sbostic			/bin/ls -ldgT \$list > $TMP1
17353130Sbosticend-of-sh
17453130Sbostic		awk '{
17553159Sbostic			if ($10 ~ /^\.$/) {
17653130Sbostic				print "The root path includes .";
17753130Sbostic				next;
17853130Sbostic			}
17953130Sbostic		     }
18053130Sbostic		     $1 ~ /^d....w/ \
18153130Sbostic        { print "Root path directory " $10 " is group writeable." } \
18253130Sbostic		     $1 ~ /^d.......w/ \
18353130Sbostic        { print "Root path directory " $10 " is other writeable." }' \
18453130Sbostic		< $TMP1 >> $OUTPUT
18553130Sbostic
18653130Sbostic	fi
18753130Sbosticdone
18853130Sbosticif [ $umaskset = "no" -o -s $OUTPUT ] ; then
18953130Sbostic	printf "\nChecking root sh paths, umask values:\n$list\n"
19053130Sbostic	if [ -s $OUTPUT ]; then
19153130Sbostic		cat $OUTPUT
19253130Sbostic	fi
19353130Sbostic	if [ $umaskset = "no" ] ; then
19453130Sbostic		printf "\nRoot sh startup files do not set the umask.\n"
19553130Sbostic	fi
19653130Sbosticfi
19753130Sbostic
19853130Sbostic# Root and uucp should both be in /etc/ftpusers.
19953130Sbosticif egrep root /etc/ftpusers > /dev/null ; then
20053130Sbostic	:
20153130Sbosticelse
20253130Sbostic	printf "\nRoot not listed in /etc/ftpusers file.\n"
20353130Sbosticfi
20453130Sbosticif egrep uucp /etc/ftpusers > /dev/null ; then
20553130Sbostic	:
20653130Sbosticelse
20753130Sbostic	printf "\nUucp not listed in /etc/ftpusers file.\n"
20853130Sbosticfi
20953130Sbostic
21053184Sbostic# Uudecode should not be in the /etc/aliases file.
21153398Sbosticif egrep 'uudecode|decode' /etc/aliases; then
21253130Sbostic	printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
21353130Sbosticfi
21453130Sbostic
21553365Sbostic# Files that should not have + signs.
21653363Sbosticlist="/etc/hosts.equiv /etc/hosts.lpd"
21753363Sbosticfor f in $list ; do
21853365Sbostic	if egrep '\+' $f > /dev/null ; then
21953365Sbostic		printf "\nPlus sign in $f file.\n"
22053363Sbostic	fi
22153363Sbosticdone
22253130Sbostic
22353130Sbostic# Check for special users with .rhosts files.  Only root and toor should
22453365Sbostic# have a .rhosts files.  Also, .rhosts files should not plus signs.
22553130Sbosticawk -F: '$1 != "root" && $1 != "toor" && \
22653130Sbostic	($3 < 100 || $1 == "ftp" || $1 == "uucp") \
22753130Sbostic		{ print $1 " " $6 }' /etc/passwd |
22853130Sbosticwhile read uid homedir; do
22953130Sbostic	if [ -f ${homedir}/.rhosts ] ; then
23053130Sbostic		rhost=`ls -ldgT ${homedir}/.rhosts`
23153130Sbostic		printf "$uid: $rhost\n"
23253130Sbostic	fi
23353130Sbosticdone > $OUTPUT
23453130Sbosticif [ -s $OUTPUT ] ; then
23553130Sbostic	printf "\nChecking for special users with .rhosts files.\n"
23653130Sbostic	cat $OUTPUT
23753130Sbosticfi
23853130Sbostic
23953130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
24053130Sbosticwhile read uid homedir; do
24153130Sbostic	if [ -f ${homedir}/.rhosts ] && \
24253365Sbostic	    egrep '\+' ${homedir}/.rhosts > /dev/null ; then
24353365Sbostic		printf "$uid: + in .rhosts file.\n"
24453130Sbostic	fi
24553130Sbosticdone > $OUTPUT
24653130Sbosticif [ -s $OUTPUT ] ; then
24753130Sbostic	printf "\nChecking .rhosts files syntax.\n"
24853130Sbostic	cat $OUTPUT
24953130Sbosticfi
25053130Sbostic
25153184Sbostic# Check home directories.  Directories should not be owned by someone else
25253184Sbostic# or writeable.
25353130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
25453105Sbosticwhile read uid homedir; do
25553105Sbostic	if [ -d ${homedir}/ ] ; then
25653105Sbostic		file=`ls -ldgT ${homedir}`
25753130Sbostic		printf "$uid $file\n"
25853105Sbostic	fi
25953130Sbosticdone |
26053130Sbosticawk '$1 != $4 && $4 != "root" \
26153130Sbostic	{ print "user " $1 " home directory is owned by " $4 }
26253130Sbostic     $2 ~ /^-....w/ \
26353130Sbostic	{ print "user " $1 " home directory is group writeable" }
26453130Sbostic     $2 ~ /^-.......w/ \
26553130Sbostic	{ print "user " $1 " home directory is other writeable" }' > $OUTPUT
26653130Sbosticif [ -s $OUTPUT ] ; then
26753130Sbostic	printf "\nChecking home directories.\n"
26853130Sbostic	cat $OUTPUT
26953130Sbosticfi
27053105Sbostic
27153104Sbostic# Files that should not be owned by someone else or readable.
27253130Sbosticlist=".netrc .rhosts"
27353130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
27453104Sbosticwhile read uid homedir; do
27553130Sbostic	for f in $list ; do
27653130Sbostic		file=${homedir}/${f}
27753130Sbostic		if [ -f $file ] ; then
27853130Sbostic			printf "$uid $f `ls -ldgT $file`\n"
27953130Sbostic		fi
28053130Sbostic	done
28153130Sbosticdone |
28253130Sbosticawk '$1 != $5 && $5 != "root" \
28353130Sbostic	{ print "user " $1 " " $2 " file is owned by " $5 }
28453130Sbostic     $3 ~ /^-...r/ \
28553130Sbostic	{ print "user " $1 " " $2 " file is group readable" }
28653130Sbostic     $3 ~ /^-......r/ \
28753130Sbostic	{ print "user " $1 " " $2 " file is other readable" }
28853130Sbostic     $3 ~ /^-....w/ \
28953130Sbostic	{ print "user " $1 " " $2 " file is group writeable" }
29053130Sbostic     $3 ~ /^-.......w/ \
29153130Sbostic	{ print "user " $1 " " $2 " file is other writeable" }' > $OUTPUT
29253104Sbostic
29353104Sbostic# Files that should not be owned by someone else or writeable.
29453130Sbosticlist=".bashrc .cshrc .emacsrc .exrc .forward .klogin .login .logout \
29553130Sbostic      .profile .tcshrc"
29653130Sbosticawk -F: '{ print $1 " " $6 }' /etc/passwd | \
29753104Sbosticwhile read uid homedir; do
29853130Sbostic	for f in $list ; do
29953130Sbostic		file=${homedir}/${f}
30053130Sbostic		if [ -f $file ] ; then
30153130Sbostic			printf "$uid $f `ls -ldgT $file`\n"
30253130Sbostic		fi
30353130Sbostic	done
30453130Sbosticdone |
30553130Sbosticawk '$1 != $5 && $5 != "root" \
30653130Sbostic	{ print "user " $1 " " $2 " file is owned by " $5 }
30753130Sbostic     $3 ~ /^-....w/ \
30853130Sbostic	{ print "user " $1 " " $2 " file is group writeable" }
30953130Sbostic     $3 ~ /^-.......w/ \
31053130Sbostic	{ print "user " $1 " " $2 " file is other writeable" }' >> $OUTPUT
31153130Sbosticif [ -s $OUTPUT ] ; then
31253130Sbostic	printf "\nChecking dot files.\n"
31353130Sbostic	cat $OUTPUT
31453130Sbosticfi
31553104Sbostic
31653184Sbostic# Mailboxes should be owned by user and unreadable.
31753130Sbosticls -l /var/mail | sed 1d | \
31853130Sbosticawk '$3 != $9 \
31953130Sbostic	{ print "user " $9 " mailbox is owned by " $3 }
32053130Sbostic     $1 != "-rw-------" \
32153130Sbostic	{ print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
32253130Sbosticif [ -s $OUTPUT ] ; then
32353130Sbostic	printf "\nChecking mailbox ownership.\n"
32453130Sbostic	cat $OUTPUT
32553130Sbosticfi
32653104Sbostic
32753184Sbostic# File systems should not be globally exported.
32853105Sbosticawk '{
32953105Sbostic	readonly = 0;
33053105Sbostic	for (i = 2; i <= NF; ++i) {
33153105Sbostic		if ($i ~ /-ro/)
33253105Sbostic			readonly = 1;
33353105Sbostic		else if ($i !~ /^-/)
33453105Sbostic			next;
33553105Sbostic	}
33653105Sbostic	if (readonly)
33753105Sbostic		print "File system " $1 " globally exported, read-only."
33853105Sbostic	else
33953105Sbostic		print "File system " $1 " globally exported, read-write."
34053130Sbostic}' < /etc/exports > $OUTPUT
34153130Sbosticif [ -s $OUTPUT ] ; then
34253130Sbostic	printf "\nChecking for globally exported file systems.\n"
34353130Sbostic	cat $OUTPUT
34453130Sbosticfi
34553105Sbostic
34653184Sbostic# Display any changes in setuid files and devices.
34753130Sbosticprintf "\nChecking setuid files and devices:\n"
34853130Sbostic(find / ! -fstype local -a -prune -o \
34953130Sbostic    \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l -a \
35053130Sbostic       ! -type s \) | \
35153130Sbosticsort | sed -e 's/^/ls -ldgT /' | sh > $LIST) 2> $OUTPUT
35242328Sbostic
35353098Sbostic# Display any errors that occurred during system file walk.
35453130Sbosticif [ -s $OUTPUT ] ; then
35553130Sbostic	printf "Setuid/device find errors:\n"
35653130Sbostic	cat $OUTPUT
35753130Sbostic	printf "\n"
35842328Sbosticfi
35942328Sbostic
36053098Sbostic# Display any changes in the setuid file list.
36153130Sbosticegrep -v '^[bc]' $LIST > $TMP1
36253130Sbosticif [ -s $TMP1 ] ; then
36353130Sbostic	# Check to make sure uudecode isn't setuid.
36453130Sbostic	if grep -w uudecode $TMP1 > /dev/null ; then
36553130Sbostic		printf "\nUudecode is setuid.\n"
36653130Sbostic	fi
36753130Sbostic
36853130Sbostic	CUR=/var/backups/setuid.current
36953130Sbostic	BACK=/var/backups/setuid.backup
37053130Sbostic
37153098Sbostic	if [ -s $CUR ] ; then
37253130Sbostic		if cmp -s $CUR $TMP1 ; then
37352573Sbostic			:
37452573Sbostic		else
37553130Sbostic			> $TMP2
37653130Sbostic			join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
37753130Sbostic			if [ -s $OUTPUT ] ; then
37853130Sbostic				printf "Setuid additions:\n"
37953130Sbostic				tee -a $TMP2 < $OUTPUT
38053130Sbostic				printf "\n"
38152573Sbostic			fi
38252573Sbostic
38353130Sbostic			join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
38453130Sbostic			if [ -s $OUTPUT ] ; then
38553130Sbostic				printf "Setuid deletions:\n"
38653130Sbostic				tee -a $TMP2 < $OUTPUT
38753130Sbostic				printf "\n"
38852573Sbostic			fi
38952573Sbostic
39053130Sbostic			sort +9 $TMP2 $CUR $TMP1 | \
39153130Sbostic			    sed -e 's/[	 ][	 ]*/ /g' | uniq -u > $OUTPUT
39253130Sbostic			if [ -s $OUTPUT ] ; then
39353130Sbostic				printf "Setuid changes:\n"
39453130Sbostic				column -t $OUTPUT
39553130Sbostic				printf "\n"
39652573Sbostic			fi
39752573Sbostic
39853130Sbostic			cp $CUR $BACK
39953130Sbostic			cp $TMP1 $CUR
40052573Sbostic		fi
40152573Sbostic	else
40253130Sbostic		printf "Setuid additions:\n"
40353140Sbostic		column -t $TMP1
40453130Sbostic		printf "\n"
40553130Sbostic		cp $TMP1 $CUR
40652573Sbostic	fi
40752215Sbosticfi
40852215Sbostic
40953184Sbostic# Check for block and character disk devices that are readable or writeable
41053140Sbostic# or not owned by root.operator.
41153307Sbostic>$TMP1
41253307SbosticDISKLIST="dk fd hd hk hp jb kra ra rb rd rl rx rz sd up wd"
41353307Sbosticfor i in $DISKLIST; do
41453307Sbostic	egrep "^b.*/${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
41553307Sbostic	egrep "^c.*/r${i}[0-9][0-9]*[a-h]$"  $LIST >> $TMP1
41653307Sbosticdone
41753105Sbostic
41853140Sbosticawk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
41953140Sbostic	{ printf("Disk %s is user %s, group %s, permissions %s.\n", \
42053140Sbostic	    $11, $3, $4, $1); }' < $TMP1 > $OUTPUT
42153130Sbosticif [ -s $OUTPUT ] ; then
42253130Sbostic	printf "\nChecking disk ownership and permissions.\n"
42353130Sbostic	cat $OUTPUT
42453130Sbostic	printf "\n"
42553130Sbosticfi
42653105Sbostic
42753184Sbostic# Display any changes in the device file list.
42853140Sbosticegrep '^[bc]' $LIST | sort +10 > $TMP1
42953130Sbosticif [ -s $TMP1 ] ; then
43053130Sbostic	CUR=/var/backups/device.current
43153130Sbostic	BACK=/var/backups/device.backup
43253098Sbostic
43353098Sbostic	if [ -s $CUR ] ; then
43453130Sbostic		if cmp -s $CUR $TMP1 ; then
43553098Sbostic			:
43653098Sbostic		else
43753130Sbostic			> $TMP2
43853130Sbostic			join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
43953130Sbostic			if [ -s $OUTPUT ] ; then
44053130Sbostic				printf "Device additions:\n"
44153130Sbostic				tee -a $TMP2 < $OUTPUT
44253130Sbostic				printf "\n"
44353098Sbostic			fi
44453098Sbostic
44553130Sbostic			join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
44653130Sbostic			if [ -s $OUTPUT ] ; then
44753130Sbostic				printf "Device deletions:\n"
44853130Sbostic				tee -a $TMP2 < $OUTPUT
44953130Sbostic				printf "\n"
45053098Sbostic			fi
45153098Sbostic
45253140Sbostic			# Report any block device change.  Ignore character
45353140Sbostic			# devices, only the name is significant.
45453140Sbostic			cat $TMP2 $CUR $TMP1 | \
45553140Sbostic			sed -e '/^c/d' | \
45653140Sbostic			sort +10 | \
45753130Sbostic			sed -e 's/[	 ][	 ]*/ /g' | \
45853140Sbostic			uniq -u > $OUTPUT
45953130Sbostic			if [ -s $OUTPUT ] ; then
46053140Sbostic				printf "Block device changes:\n"
46153130Sbostic				column -t $OUTPUT
46253130Sbostic				printf "\n"
46353098Sbostic			fi
46453098Sbostic
46553130Sbostic			cp $CUR $BACK
46653130Sbostic			cp $TMP1 $CUR
46753098Sbostic		fi
46853098Sbostic	else
46953130Sbostic		printf "Device additions:\n"
47053140Sbostic		column -t $TMP1
47153130Sbostic		printf "\n"
47253130Sbostic		cp $TMP1 $CUR
47353098Sbostic	fi
47453098Sbosticfi
47553098Sbostic
47653142Sbostic# Check special files.
47753142Sbostic# Check system binaries.
47853142Sbostic#
47952578Sbostic# Create the mtree tree specifications using:
48052578Sbostic#
48153130Sbostic#	mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
48253130Sbostic#	chown root.wheel DIR.SECURE
48353130Sbostic#	chmod 600 DIR.SECURE
48452578Sbostic#
48552578Sbostic# Note, this is not complete protection against Trojan horsed binaries, as
48652578Sbostic# the hacker can modify the tree specification to match the replaced binary.
48752578Sbostic# For details on really protecting yourself against modified binaries, see
48852578Sbostic# the mtree(8) manual page.
48952578Sbosticif cd /etc/mtree; then
49053130Sbostic	mtree -e -p / -f /etc/mtree/special > $OUTPUT
49153130Sbostic	if [ -s $OUTPUT ] ; then
49253130Sbostic		printf "\nChecking special files and directories.\n"
49353130Sbostic		cat $OUTPUT
49453130Sbostic	fi
49553130Sbostic
49653130Sbostic	> $OUTPUT
49752578Sbostic	for file in *.secure; do
49852578Sbostic		tree=`sed -n -e '3s/.* //p' -e 3q $file`
49953130Sbostic		mtree -f $file -p $tree > $TMP1
50053130Sbostic		if [ -s $TMP1 ]; then
50153130Sbostic			printf "\nChecking $tree:\n" >> $OUTPUT
50253130Sbostic			cat $TMP1 >> $OUTPUT
50353130Sbostic		fi
50452578Sbostic	done
50553130Sbostic	if [ -s $OUTPUT ] ; then
50653130Sbostic		printf "\nChecking system binaries:\n"
50753130Sbostic		cat $OUTPUT
50853130Sbostic	fi
50952578Sbosticfi
51053264Sbostic
51153264Sbostic# List of files that get backed up and checked for any modifications.  Each
51253264Sbostic# file is expected to have two backups, /var/backups/file.{current,backup}.
51353264Sbostic# Any changes cause the files to rotate.
51453264Sbosticif [ -s /etc/changelist ] ; then
51553264Sbostic	for file in `cat /etc/changelist`; do
51653264Sbostic		CUR=/var/backups/`basename $file`.current
51753264Sbostic		BACK=/var/backups/`basename $file`.backup
51853264Sbostic		if [ -s $file ]; then
51953264Sbostic			if [ -s $CUR ] ; then
52053264Sbostic				diff $CUR $file > $OUTPUT
52153264Sbostic				if [ -s $OUTPUT ] ; then
52253264Sbostic		printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
52353264Sbostic					cat $OUTPUT
52453264Sbostic					cp -p $CUR $BACK
52553264Sbostic					cp -p $file $CUR
52653264Sbostic					chown root.wheel $CUR $BACK
52753264Sbostic				fi
52853264Sbostic			else
52953264Sbostic				cp -p $file $CUR
53053264Sbostic				chown root.wheel $CUR
53153264Sbostic			fi
53253264Sbostic		fi
53353264Sbostic	done
53453264Sbosticfi
535