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