Home | History | Annotate | Line # | Download | only in etc
security revision 1.78
      1   1.1       cgd #!/bin/sh -
      2   1.1       cgd #
      3  1.78    itojun #	$NetBSD: security,v 1.78 2002/06/18 22:43:53 itojun 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.64       cjs TZ=UTC; export TZ
     18   1.1       cgd 
     19  1.15       mrg if [ -s /etc/security.conf ]; then
     20  1.15       mrg 	. /etc/security.conf
     21  1.15       mrg fi
     22  1.15       mrg 
     23  1.67     lukem # Set reasonable defaults (if they're not set in security.conf)
     24  1.67     lukem #
     25  1.67     lukem backup_dir=${backup_dir:-/var/backups}
     26  1.67     lukem pkgdb_dir=${pkgdb_dir:-/var/db/pkg}
     27  1.67     lukem max_loginlen=${max_loginlen:-8}
     28  1.67     lukem max_grouplen=${max_grouplen:-8}
     29  1.67     lukem 
     30  1.67     lukem # Other configurable variables
     31  1.67     lukem #
     32  1.67     lukem special_files="/etc/mtree/special /etc/mtree/special.local"
     33  1.67     lukem MP=/etc/master.passwd
     34  1.67     lukem CHANGELIST=""
     35  1.67     lukem work_dir=$backup_dir/work
     36  1.67     lukem 
     37  1.67     lukem if [ ! -d "$work_dir" ]; then
     38  1.67     lukem 	mkdir -p "$work_dir"
     39  1.67     lukem fi
     40  1.67     lukem 
     41  1.56     lukem SECUREDIR=`mktemp -d /tmp/_securedir.XXXXXX` || exit 1
     42  1.56     lukem 
     43  1.67     lukem trap "/bin/rm -rf $SECUREDIR ; exit 0" EXIT INT QUIT PIPE
     44  1.15       mrg 
     45  1.56     lukem if ! cd "$SECUREDIR"; then
     46  1.56     lukem 	echo "Can not cd to $SECUREDIR".
     47  1.15       mrg 	exit 1
     48  1.15       mrg fi
     49  1.15       mrg 
     50  1.15       mrg ERR=secure1.$$
     51  1.15       mrg TMP1=secure2.$$
     52  1.15       mrg TMP2=secure3.$$
     53  1.28     lukem MPBYUID=secure4.$$
     54  1.29     lukem MPBYPATH=secure5.$$
     55  1.27     lukem LIST=secure6.$$
     56  1.27     lukem OUTPUT=secure7.$$
     57  1.32     lukem LABELS=secure8.$$
     58  1.62    atatat PKGS=secure9.$$
     59  1.67     lukem CHANGEFILES=secure10.$$
     60  1.67     lukem 
     61  1.15       mrg 
     62  1.67     lukem # migrate_file old new
     63  1.67     lukem #	Determine if the "${old}" path name needs to be migrated to the
     64  1.67     lukem #	"${new}" path. Also checks if "${old}.current" needs migrating,
     65  1.67     lukem #	and if so, migrate it and possibly "${old}.current,v" and
     66  1.67     lukem #	"${old}.backup".
     67  1.67     lukem #
     68  1.67     lukem migrate_file()
     69  1.67     lukem {
     70  1.67     lukem 	_old=$1
     71  1.67     lukem 	_new=$2
     72  1.67     lukem 	if [ -z "$_old" -o -z "$_new" ]; then
     73  1.67     lukem 		err 3 "USAGE: migrate_file old new"
     74  1.67     lukem 	fi
     75  1.67     lukem 	if [ ! -d "${_new%/*}" ]; then
     76  1.67     lukem 		mkdir -p "${_new%/*}"
     77  1.67     lukem 	fi
     78  1.67     lukem 	if [ -f "${_old}" -a ! -f "${_new}" ]; then
     79  1.67     lukem 		echo "==> migrating ${_old}"
     80  1.67     lukem 		echo "           to ${_new}"
     81  1.67     lukem 		mv "${_old}" "${_new}"
     82  1.67     lukem 	fi
     83  1.67     lukem 	if [ -f "${_old}.current" -a ! -f "${_new}.current" ]; then
     84  1.67     lukem 		echo "==> migrating ${_old}.current"
     85  1.67     lukem 		echo "           to ${_new}.current"
     86  1.67     lukem 		mv "${_old}.current" "${_new}.current"
     87  1.67     lukem 		if [ -f "${_old}.current,v" -a ! -f "${_new}.current,v" ]; then
     88  1.67     lukem 			echo "==> migrating ${_old}.current,v"
     89  1.67     lukem 			echo "           to ${_new}.current,v"
     90  1.67     lukem 			mv "${_old}.current,v" "${_new}.current,v"
     91  1.67     lukem 		fi
     92  1.67     lukem 		if [ -f "${_old}.backup" -a ! -f "${_new}.backup" ]; then
     93  1.67     lukem 			echo "==> migrating ${_old}.backup"
     94  1.67     lukem 			echo "           to ${_new}.backup"
     95  1.67     lukem 			mv "${_old}.backup" "${_new}.backup"
     96  1.67     lukem 		fi
     97  1.67     lukem 	fi
     98  1.67     lukem }
     99  1.67     lukem 
    100  1.67     lukem 
    101  1.67     lukem # backup_and_diff file printdiff
    102  1.67     lukem #	Determine if file needs backing up, and if so, do it.
    103  1.67     lukem #	If printdiff is yes, display the diffs, otherwise 
    104  1.67     lukem #	just print a message saying "[changes omitted]".
    105  1.67     lukem #
    106  1.67     lukem backup_and_diff()
    107  1.67     lukem {
    108  1.67     lukem 	_file=$1
    109  1.67     lukem 	_printdiff=$2
    110  1.67     lukem 	if [ -z "$_file" -o -z "$_printdiff" ]; then
    111  1.67     lukem 		err 3 "USAGE: backup_and_diff file printdiff"
    112  1.67     lukem 	fi
    113  1.67     lukem 	! checkyesno _printdiff
    114  1.67     lukem 	_printdiff=$?
    115  1.67     lukem 
    116  1.67     lukem 	_old=$backup_dir/${_file##*/}
    117  1.67     lukem 	case "$_file" in
    118  1.67     lukem 	$work_dir/*)
    119  1.67     lukem 		_new=$_file
    120  1.67     lukem 		migrate_file "$backup_dir/$_old" "$_new"
    121  1.67     lukem 		migrate_file "$_old" "$_new"
    122  1.67     lukem 		;;
    123  1.67     lukem 	*)
    124  1.67     lukem 		_new=$backup_dir/$_file
    125  1.67     lukem 		migrate_file "$_old" "$_new"
    126  1.67     lukem 		;;
    127  1.67     lukem 	esac
    128  1.67     lukem 	CUR=${_new}.current
    129  1.67     lukem 	BACK=${_new}.backup
    130  1.67     lukem 	if [ -f $_file ]; then
    131  1.67     lukem 		if [ -f $CUR ] ; then
    132  1.67     lukem 			if [ "$_printdiff" -ne 0 ]; then
    133  1.67     lukem 				diff $CUR $_file > $OUTPUT
    134  1.67     lukem 			else
    135  1.67     lukem 				if ! cmp -s $CUR $_file; then
    136  1.67     lukem 					echo "[changes omitted]"
    137  1.67     lukem 				fi > $OUTPUT
    138  1.67     lukem 			fi
    139  1.67     lukem 			if [ -s $OUTPUT ] ; then
    140  1.67     lukem 				printf \
    141  1.67     lukem 			"\n======\n%s diffs (OLD < > NEW)\n======\n" $_file
    142  1.67     lukem 				cat $OUTPUT
    143  1.67     lukem 				backup_file update $_file $CUR $BACK
    144  1.67     lukem 			fi
    145  1.67     lukem 		else
    146  1.67     lukem 			printf "\n======\n%s added\n======\n" $_file
    147  1.67     lukem 			if [ "$_printdiff" -ne 0 ]; then
    148  1.67     lukem 				diff /dev/null $_file
    149  1.67     lukem 			else
    150  1.67     lukem 				echo "[changes omitted]"
    151  1.67     lukem 			fi
    152  1.67     lukem 			backup_file add $_file $CUR $BACK
    153  1.67     lukem 		fi
    154  1.67     lukem 	else
    155  1.67     lukem 		if [ -f $CUR ]; then
    156  1.67     lukem 			printf "\n======\n%s removed\n======\n" $_file
    157  1.67     lukem 			if [ "$_printdiff" -ne 0 ]; then
    158  1.67     lukem 				diff $CUR /dev/null
    159  1.67     lukem 			else
    160  1.67     lukem 				echo "[changes omitted]"
    161  1.67     lukem 			fi
    162  1.67     lukem 			backup_file remove $_file $CUR $BACK
    163  1.67     lukem 		fi
    164  1.67     lukem 	fi
    165  1.67     lukem }
    166  1.48       abs 
    167   1.9       cgd 
    168  1.67     lukem # These are used several times.
    169  1.67     lukem #
    170  1.34       abs awk -F: '!/^+/ { print $1 " " $3 }' $MP | sort -k2n > $MPBYUID
    171  1.29     lukem awk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH
    172   1.9       cgd 
    173  1.67     lukem 
    174   1.9       cgd # Check the master password file syntax.
    175  1.32     lukem #
    176  1.31     lukem if checkyesno check_passwd; then
    177  1.34       abs 	awk -v "len=$max_loginlen" '
    178  1.25     lukem 	BEGIN {
    179  1.25     lukem 		while ( getline < "/etc/shells" > 0 ) {
    180  1.39   hubertf 			if ($0 ~ /^\#/ || $0 ~ /^$/ )
    181  1.25     lukem 				continue;
    182  1.25     lukem 			shells[$1]++;
    183  1.25     lukem 		}
    184  1.25     lukem 		FS=":";
    185  1.25     lukem 	}
    186  1.25     lukem 
    187  1.25     lukem 	{
    188  1.15       mrg 		if ($0 ~ /^[	 ]*$/) {
    189  1.25     lukem 			printf "Line %d is a blank line.\n", NR;
    190  1.15       mrg 			next;
    191  1.15       mrg 		}
    192  1.34       abs 		if (NF != 10 && ($1 != "+" || NF != 1))
    193  1.25     lukem 			printf "Line %d has the wrong number of fields.\n", NR;
    194  1.34       abs 		if ($1 == "+" )  {
    195  1.34       abs 			if (NF != 1 && $3 == 0)
    196  1.34       abs 			    printf "Line %d includes entries with uid 0.\n", NR;
    197  1.34       abs 			next;
    198  1.34       abs 		}
    199  1.53    atatat 		if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
    200  1.25     lukem 			printf "Login %s has non-alphanumeric characters.\n",
    201  1.25     lukem 			    $1;
    202  1.34       abs 		if (length($1) > len)
    203  1.34       abs 			printf "Login %s has more than "len" characters.\n", $1;
    204  1.15       mrg 		if ($2 == "")
    205  1.25     lukem 			printf "Login %s has no password.\n", $1;
    206  1.66     lukem 		if (length($2) != 13 &&
    207  1.66     lukem 		    length($2) != 20 &&
    208  1.78    itojun 		    $2 !~ /^\$1/ &&
    209  1.78    itojun 		    $2 !~ /^\$2/ &&
    210  1.59     perry 		    $2 != "" &&
    211  1.59     perry 		    $2 !~ /^\*[A-z-]+$/ &&
    212  1.59     perry 		    $1 != "toor") {
    213  1.25     lukem 			if ($10 == "" || shells[$10])
    214  1.27     lukem 		    printf "Login %s is off but still has a valid shell (%s)\n",
    215  1.25     lukem 				    $1, $10;
    216  1.25     lukem 		} else if (! shells[$10])
    217  1.25     lukem 			printf "Login %s does not have a valid shell (%s)\n",
    218  1.25     lukem 			    $1, $10;
    219  1.15       mrg 		if ($3 == 0 && $1 != "root" && $1 != "toor")
    220  1.25     lukem 			printf "Login %s has a user id of 0.\n", $1;
    221  1.15       mrg 		if ($3 < 0)
    222  1.25     lukem 			printf "Login %s has a negative user id.\n", $1;
    223  1.15       mrg 		if ($4 < 0)
    224  1.25     lukem 			printf "Login %s has a negative group id.\n", $1;
    225  1.15       mrg 	}' < $MP > $OUTPUT
    226  1.15       mrg 	if [ -s $OUTPUT ] ; then
    227  1.15       mrg 		printf "\nChecking the $MP file:\n"
    228  1.15       mrg 		cat $OUTPUT
    229  1.15       mrg 	fi
    230  1.15       mrg 
    231  1.15       mrg 	awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
    232  1.15       mrg 	if [ -s $OUTPUT ] ; then
    233  1.15       mrg 		printf "\n$MP has duplicate user names.\n"
    234  1.15       mrg 		column $OUTPUT
    235  1.15       mrg 	fi
    236  1.15       mrg 
    237  1.37  wrstuden # To not exclude 'toor', a standard duplicate root account, from the duplicate
    238  1.37  wrstuden # account test, uncomment the line below (without egrep in it)and comment
    239  1.37  wrstuden # out the line (with egrep in it) below it.
    240  1.37  wrstuden #
    241  1.37  wrstuden #	< $MPBYUID uniq -d -f 1 | awk '{ print $2 }' > $TMP2
    242  1.36  wrstuden 	< $MPBYUID egrep -v '^toor ' | uniq -d -f 1 | awk '{ print $2 }' > $TMP2
    243  1.15       mrg 	if [ -s $TMP2 ] ; then
    244  1.15       mrg 		printf "\n$MP has duplicate user id's.\n"
    245  1.15       mrg 		while read uid; do
    246  1.28     lukem 			grep -w $uid $MPBYUID
    247  1.15       mrg 		done < $TMP2 | column
    248  1.15       mrg 	fi
    249   1.9       cgd fi
    250   1.9       cgd 
    251   1.9       cgd # Check the group file syntax.
    252  1.32     lukem #
    253  1.31     lukem if checkyesno check_group; then
    254  1.15       mrg 	GRP=/etc/group
    255  1.49  jdolecek 	awk -F: -v "len=$max_grouplen" '{
    256  1.15       mrg 		if ($0 ~ /^[	 ]*$/) {
    257  1.25     lukem 			printf "Line %d is a blank line.\n", NR;
    258  1.15       mrg 			next;
    259  1.15       mrg 		}
    260  1.34       abs 		if (NF != 4 && ($1 != "+" || NF != 1))
    261  1.25     lukem 			printf "Line %d has the wrong number of fields.\n", NR;
    262  1.34       abs 		if ($1 == "+" )  {
    263  1.34       abs 			next;
    264  1.34       abs 		}
    265  1.53    atatat 		if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
    266  1.25     lukem 			printf "Group %s has non-alphanumeric characters.\n",
    267  1.25     lukem 			    $1;
    268  1.49  jdolecek 		if (length($1) > len)
    269  1.49  jdolecek 			printf "Group %s has more than "len" characters.\n", $1;
    270  1.15       mrg 		if ($3 !~ /[0-9]*/)
    271  1.25     lukem 			printf "Login %s has a negative group id.\n", $1;
    272  1.15       mrg 	}' < $GRP > $OUTPUT
    273  1.15       mrg 	if [ -s $OUTPUT ] ; then
    274  1.15       mrg 		printf "\nChecking the $GRP file:\n"
    275  1.15       mrg 		cat $OUTPUT
    276  1.15       mrg 	fi
    277  1.15       mrg 
    278  1.15       mrg 	awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
    279  1.15       mrg 	if [ -s $OUTPUT ] ; then
    280  1.15       mrg 		printf "\n$GRP has duplicate group names.\n"
    281  1.15       mrg 		column $OUTPUT
    282  1.15       mrg 	fi
    283   1.9       cgd fi
    284   1.9       cgd 
    285   1.9       cgd # Check for root paths, umask values in startup files.
    286   1.9       cgd # The check for the root paths is problematical -- it's likely to fail
    287   1.9       cgd # in other environments.  Once the shells have been modified to warn
    288   1.9       cgd # of '.' in the path, the path tests should go away.
    289  1.32     lukem #
    290  1.31     lukem if checkyesno check_rootdotfiles; then
    291  1.67     lukem 	rhome=~root
    292  1.15       mrg 	umaskset=no
    293  1.15       mrg 	list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
    294  1.15       mrg 	for i in $list ; do
    295  1.15       mrg 		if [ -f $i ] ; then
    296  1.67     lukem 			if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ;
    297  1.67     lukem 			then
    298  1.15       mrg 				umaskset=yes
    299  1.15       mrg 			fi
    300  1.63     lukem 			# Double check the umask value itself; ensure that
    301  1.67     lukem 			# both the group and other write bits are set.
    302  1.67     lukem 			#
    303  1.45  sommerfe 			egrep '^[ \t]*umask[ \t]+[0-7]+' $i |
    304  1.63     lukem 			awk '{
    305  1.67     lukem 				if ($2 ~ /^.$/ || $2 ~! /[^2367].$/) {
    306  1.63     lukem 					print "\tRoot umask is group writeable"
    307  1.63     lukem 				}
    308  1.67     lukem 				if ($2 ~ /[^2367]$/) {
    309  1.63     lukem 					print "\tRoot umask is other writeable"
    310  1.63     lukem 			    	}
    311  1.67     lukem 			    }' | sort -u
    312  1.26     lukem 			SAVE_PATH=$PATH
    313  1.26     lukem 			unset PATH
    314  1.15       mrg 			/bin/csh -f -s << end-of-csh > /dev/null 2>&1
    315  1.15       mrg 				source $i
    316  1.15       mrg 				/bin/ls -ldgT \$path > $TMP1
    317   1.9       cgd end-of-csh
    318  1.76    atatat 			export PATH=$SAVE_PATH
    319  1.15       mrg 			awk '{
    320  1.15       mrg 				if ($10 ~ /^\.$/) {
    321  1.27     lukem 					print "\tThe root path includes .";
    322  1.15       mrg 					next;
    323  1.15       mrg 				}
    324  1.15       mrg 			     }
    325  1.15       mrg 			     $1 ~ /^d....w/ \
    326  1.27     lukem 		{ print "\tRoot path directory " $10 " is group writeable." } \
    327  1.15       mrg 			     $1 ~ /^d.......w/ \
    328  1.27     lukem 		{ print "\tRoot path directory " $10 " is other writeable." }' \
    329  1.67     lukem 			< $TMP1
    330  1.15       mrg 		fi
    331  1.67     lukem 	done > $OUTPUT
    332  1.15       mrg 	if [ $umaskset = "no" -o -s $OUTPUT ] ; then
    333  1.27     lukem 		printf "\nChecking root csh paths, umask values:\n$list\n\n"
    334  1.15       mrg 		if [ -s $OUTPUT ]; then
    335  1.15       mrg 			cat $OUTPUT
    336  1.15       mrg 		fi
    337  1.15       mrg 		if [ $umaskset = "no" ] ; then
    338  1.27     lukem 		    printf "\tRoot csh startup files do not set the umask.\n"
    339  1.15       mrg 		fi
    340   1.9       cgd 	fi
    341   1.9       cgd 
    342  1.15       mrg 	umaskset=no
    343  1.23     lukem 	list="/etc/profile ${rhome}/.profile"
    344  1.15       mrg 	for i in $list; do
    345  1.15       mrg 		if [ -f $i ] ; then
    346  1.15       mrg 			if egrep umask $i > /dev/null ; then
    347  1.15       mrg 				umaskset=yes
    348  1.15       mrg 			fi
    349  1.15       mrg 			egrep umask $i |
    350  1.67     lukem 			awk '$2 ~ /^.$/ || $2 ~ /[^2367].$/ \
    351  1.27     lukem 				{ print "\tRoot umask is group writeable" } \
    352  1.67     lukem 			     $2 ~ /[^2367]$/ \
    353  1.67     lukem 				{ print "\tRoot umask is other writeable" }'
    354  1.26     lukem 			SAVE_PATH=$PATH
    355  1.26     lukem 			unset PATH
    356  1.15       mrg 			/bin/sh << end-of-sh > /dev/null 2>&1
    357  1.15       mrg 				. $i
    358  1.26     lukem 				list=\`echo \$PATH | /usr/bin/sed -e \
    359  1.26     lukem 				    's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g'\`
    360  1.15       mrg 				/bin/ls -ldgT \$list > $TMP1
    361   1.9       cgd end-of-sh
    362  1.76    atatat 			export PATH=$SAVE_PATH
    363  1.15       mrg 			awk '{
    364  1.15       mrg 				if ($10 ~ /^\.$/) {
    365  1.27     lukem 					print "\tThe root path includes .";
    366  1.15       mrg 					next;
    367  1.15       mrg 				}
    368  1.15       mrg 			     }
    369  1.15       mrg 			     $1 ~ /^d....w/ \
    370  1.27     lukem 		{ print "\tRoot path directory " $10 " is group writeable." } \
    371  1.15       mrg 			     $1 ~ /^d.......w/ \
    372  1.27     lukem 		{ print "\tRoot path directory " $10 " is other writeable." }' \
    373  1.67     lukem 			< $TMP1
    374   1.9       cgd 
    375  1.15       mrg 		fi
    376  1.67     lukem 	done > $OUTPUT
    377  1.15       mrg 	if [ $umaskset = "no" -o -s $OUTPUT ] ; then
    378  1.15       mrg 		printf "\nChecking root sh paths, umask values:\n$list\n"
    379  1.15       mrg 		if [ -s $OUTPUT ]; then
    380  1.15       mrg 			cat $OUTPUT
    381  1.15       mrg 		fi
    382  1.15       mrg 		if [ $umaskset = "no" ] ; then
    383  1.27     lukem 			printf "\tRoot sh startup files do not set the umask.\n"
    384  1.15       mrg 		fi
    385   1.9       cgd 	fi
    386   1.9       cgd fi
    387   1.9       cgd 
    388   1.9       cgd # Root and uucp should both be in /etc/ftpusers.
    389  1.32     lukem #
    390  1.31     lukem if checkyesno check_ftpusers; then
    391  1.28     lukem 	list="uucp "`awk '$2 == 0 { print $1 }' $MPBYUID`
    392  1.27     lukem 	for i in $list; do
    393  1.29     lukem 		if /usr/libexec/ftpd -C $i ; then
    394  1.67     lukem 			printf "\t$i is not denied\n"
    395  1.27     lukem 		fi
    396  1.67     lukem 	done > $OUTPUT
    397  1.28     lukem 	if [ -s $OUTPUT ]; then
    398  1.28     lukem 		printf "\nChecking the /etc/ftpusers configuration:\n"
    399  1.28     lukem 		cat $OUTPUT
    400  1.28     lukem 	fi
    401   1.9       cgd fi
    402   1.9       cgd 
    403  1.43    itojun # Uudecode should not be in the /etc/mail/aliases file.
    404  1.32     lukem #
    405  1.31     lukem if checkyesno check_aliases; then
    406  1.43    itojun 	for f in /etc/mail/aliases /etc/aliases; do
    407  1.43    itojun 		if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then
    408  1.43    itojun 			printf "\nEntry for uudecode in $f file.\n"
    409  1.43    itojun 		fi
    410  1.43    itojun 	done
    411   1.9       cgd fi
    412   1.9       cgd 
    413   1.9       cgd # Files that should not have + signs.
    414  1.32     lukem #
    415  1.31     lukem if checkyesno check_rhosts; then
    416  1.15       mrg 	list="/etc/hosts.equiv /etc/hosts.lpd"
    417  1.15       mrg 	for f in $list ; do
    418  1.15       mrg 		if [ -f $f ] && egrep '\+' $f > /dev/null ; then
    419  1.15       mrg 			printf "\nPlus sign in $f file.\n"
    420  1.15       mrg 		fi
    421  1.15       mrg 	done
    422  1.15       mrg 
    423  1.15       mrg 	# Check for special users with .rhosts files.  Only root and toor should
    424  1.16     mikel 	# have .rhosts files.  Also, .rhosts files should not have plus signs.
    425  1.15       mrg 	awk -F: '$1 != "root" && $1 != "toor" && \
    426  1.15       mrg 		($3 < 100 || $1 == "ftp" || $1 == "uucp") \
    427  1.20   mycroft 			{ print $1 " " $9 }' $MP |
    428  1.19   mycroft 	sort -k2 |
    429  1.15       mrg 	while read uid homedir; do
    430  1.15       mrg 		if [ -f ${homedir}/.rhosts ] ; then
    431  1.15       mrg 			rhost=`ls -ldgT ${homedir}/.rhosts`
    432  1.46  christos 			printf -- "$uid: $rhost\n"
    433  1.15       mrg 		fi
    434  1.15       mrg 	done > $OUTPUT
    435  1.15       mrg 	if [ -s $OUTPUT ] ; then
    436  1.15       mrg 		printf "\nChecking for special users with .rhosts files.\n"
    437  1.15       mrg 		cat $OUTPUT
    438  1.15       mrg 	fi
    439  1.15       mrg 
    440  1.15       mrg 	while read uid homedir; do
    441  1.35      fair 		if [ -f ${homedir}/.rhosts -a -r ${homedir}/.rhosts ] && \
    442  1.41  christos 		    cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null ; then
    443  1.46  christos 			printf -- "$uid: + in .rhosts file.\n"
    444  1.15       mrg 		fi
    445  1.29     lukem 	done < $MPBYPATH > $OUTPUT
    446  1.15       mrg 	if [ -s $OUTPUT ] ; then
    447  1.15       mrg 		printf "\nChecking .rhosts files syntax.\n"
    448  1.15       mrg 		cat $OUTPUT
    449  1.15       mrg 	fi
    450   1.9       cgd fi
    451   1.9       cgd 
    452   1.9       cgd # Check home directories.  Directories should not be owned by someone else
    453   1.9       cgd # or writeable.
    454  1.32     lukem #
    455  1.31     lukem if checkyesno check_homes; then
    456  1.15       mrg 	while read uid homedir; do
    457  1.15       mrg 		if [ -d ${homedir}/ ] ; then
    458  1.15       mrg 			file=`ls -ldgT ${homedir}`
    459  1.46  christos 			printf -- "$uid $file\n"
    460   1.9       cgd 		fi
    461  1.29     lukem 	done < $MPBYPATH |
    462  1.15       mrg 	awk '$1 != $4 && $4 != "root" \
    463  1.15       mrg 		{ print "user " $1 " home directory is owned by " $4 }
    464  1.15       mrg 	     $2 ~ /^-....w/ \
    465  1.15       mrg 		{ print "user " $1 " home directory is group writeable" }
    466  1.15       mrg 	     $2 ~ /^-.......w/ \
    467  1.27     lukem 		{ print "user " $1 " home directory is other writeable" }' \
    468  1.27     lukem 	    > $OUTPUT
    469  1.15       mrg 	if [ -s $OUTPUT ] ; then
    470  1.15       mrg 		printf "\nChecking home directories.\n"
    471  1.15       mrg 		cat $OUTPUT
    472  1.15       mrg 	fi
    473  1.15       mrg 
    474  1.15       mrg 	# Files that should not be owned by someone else or readable.
    475  1.67     lukem 	list=".Xauthority .netrc .ssh/id_dsa .ssh/id_rsa .ssh/identity"
    476  1.15       mrg 	while read uid homedir; do
    477  1.15       mrg 		for f in $list ; do
    478  1.15       mrg 			file=${homedir}/${f}
    479  1.15       mrg 			if [ -f $file ] ; then
    480  1.46  christos 				printf -- "$uid $f `ls -ldgT $file`\n"
    481  1.15       mrg 			fi
    482  1.15       mrg 		done
    483  1.29     lukem 	done < $MPBYPATH |
    484  1.15       mrg 	awk '$1 != $5 && $5 != "root" \
    485  1.15       mrg 		{ print "user " $1 " " $2 " file is owned by " $5 }
    486  1.15       mrg 	     $3 ~ /^-...r/ \
    487  1.15       mrg 		{ print "user " $1 " " $2 " file is group readable" }
    488  1.15       mrg 	     $3 ~ /^-......r/ \
    489  1.15       mrg 		{ print "user " $1 " " $2 " file is other readable" }
    490  1.15       mrg 	     $3 ~ /^-....w/ \
    491  1.15       mrg 		{ print "user " $1 " " $2 " file is group writeable" }
    492  1.15       mrg 	     $3 ~ /^-.......w/ \
    493  1.27     lukem 		{ print "user " $1 " " $2 " file is other writeable" }' \
    494  1.27     lukem 	    > $OUTPUT
    495  1.15       mrg 
    496  1.15       mrg 	# Files that should not be owned by someone else or writeable.
    497  1.19   mycroft 	list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
    498  1.19   mycroft 	      .cshrc .emacs .exrc .forward .history .klogin .login .logout \
    499  1.67     lukem 	      .profile .qmail .rc_history .rhosts .shosts ssh .tcshrc .twmrc \
    500  1.67     lukem 	      .xinitrc .xsession .ssh/authorized_keys .ssh/authorized_keys2 \
    501  1.67     lukem 	      .ssh/config .ssh/id_dsa.pub .ssh/id_rsa.pub .ssh/identity.pub \
    502  1.67     lukem 	      .ssh/known_hosts .ssh/known_hosts2"
    503  1.15       mrg 	while read uid homedir; do
    504  1.15       mrg 		for f in $list ; do
    505  1.15       mrg 			file=${homedir}/${f}
    506  1.15       mrg 			if [ -f $file ] ; then
    507  1.46  christos 				printf -- "$uid $f `ls -ldgT $file`\n"
    508  1.15       mrg 			fi
    509  1.15       mrg 		done
    510  1.29     lukem 	done < $MPBYPATH |
    511  1.15       mrg 	awk '$1 != $5 && $5 != "root" \
    512  1.15       mrg 		{ print "user " $1 " " $2 " file is owned by " $5 }
    513  1.15       mrg 	     $3 ~ /^-....w/ \
    514  1.15       mrg 		{ print "user " $1 " " $2 " file is group writeable" }
    515  1.15       mrg 	     $3 ~ /^-.......w/ \
    516  1.27     lukem 		{ print "user " $1 " " $2 " file is other writeable" }' \
    517  1.27     lukem 	    >> $OUTPUT
    518  1.15       mrg 	if [ -s $OUTPUT ] ; then
    519  1.15       mrg 		printf "\nChecking dot files.\n"
    520  1.15       mrg 		cat $OUTPUT
    521  1.15       mrg 	fi
    522   1.9       cgd fi
    523   1.9       cgd 
    524   1.9       cgd # Mailboxes should be owned by user and unreadable.
    525  1.32     lukem #
    526  1.31     lukem if checkyesno check_varmail; then
    527  1.63     lukem 	ls -l /var/mail | \
    528  1.63     lukem 	awk '	NR == 1 { next; }
    529  1.63     lukem 	    	$3 != $9 {
    530  1.63     lukem 			print "user " $9 " mailbox is owned by " $3
    531  1.63     lukem 		}
    532  1.63     lukem 		$1 != "-rw-------" {
    533  1.63     lukem 			print "user " $9 " mailbox is " $1 ", group " $4
    534  1.63     lukem 		}' > $OUTPUT
    535  1.15       mrg 	if [ -s $OUTPUT ] ; then
    536  1.15       mrg 		printf "\nChecking mailbox ownership.\n"
    537  1.15       mrg 		cat $OUTPUT
    538  1.15       mrg 	fi
    539  1.15       mrg fi
    540  1.15       mrg 
    541  1.32     lukem # NFS exports shouldn't be globally exported
    542  1.32     lukem #
    543  1.32     lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
    544  1.32     lukem 	awk '{
    545  1.22     lukem 		# ignore comments and blank lines
    546  1.39   hubertf 		if ($0 ~ /^\#/ || $0 ~ /^$/ )
    547  1.22     lukem 			next;
    548  1.22     lukem 
    549  1.15       mrg 		readonly = 0;
    550  1.15       mrg 		for (i = 2; i <= NF; ++i) {
    551  1.15       mrg 			if ($i ~ /-ro/)
    552  1.15       mrg 				readonly = 1;
    553  1.15       mrg 			else if ($i !~ /^-/)
    554  1.15       mrg 				next;
    555  1.15       mrg 		}
    556  1.15       mrg 		if (readonly)
    557  1.15       mrg 			print "File system " $1 " globally exported, read-only."
    558  1.15       mrg 		else
    559  1.15       mrg 			print "File system " $1 " globally exported, read-write."
    560  1.32     lukem 	}' < /etc/exports > $OUTPUT
    561  1.32     lukem 	if [ -s $OUTPUT ] ; then
    562  1.15       mrg 		printf "\nChecking for globally exported file systems.\n"
    563  1.15       mrg 		cat $OUTPUT
    564  1.15       mrg 	fi
    565   1.9       cgd fi
    566   1.9       cgd 
    567   1.9       cgd # Display any changes in setuid files and devices.
    568  1.32     lukem #
    569  1.31     lukem if checkyesno check_devices; then
    570  1.28     lukem 	> $ERR
    571  1.15       mrg 	(find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
    572  1.74     lukem 			-o -fstype null \
    573  1.15       mrg 			-o -fstype procfs \) -a -prune -o \
    574  1.21   mycroft 	    \( \( -perm -u+s -a ! -type d \) -o \
    575  1.21   mycroft 	       \( -perm -g+s -a ! -type d \) -o \
    576  1.24     lukem 	       -type b -o -type c \) -print0 | \
    577  1.24     lukem 	xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
    578  1.15       mrg 
    579  1.15       mrg 	# Display any errors that occurred during system file walk.
    580  1.15       mrg 	if [ -s $OUTPUT ] ; then
    581  1.28     lukem 		printf "Setuid/device find errors:\n" >> $ERR
    582  1.28     lukem 		cat $OUTPUT >> $ERR
    583  1.28     lukem 		printf "\n" >> $ERR
    584  1.15       mrg 	fi
    585  1.15       mrg 
    586  1.15       mrg 	# Display any changes in the setuid file list.
    587  1.15       mrg 	egrep -v '^[bc]' $LIST > $TMP1
    588  1.15       mrg 	if [ -s $TMP1 ] ; then
    589  1.15       mrg 		# Check to make sure uudecode isn't setuid.
    590  1.15       mrg 		if grep -w uudecode $TMP1 > /dev/null ; then
    591  1.28     lukem 			printf "\nUudecode is setuid.\n" >> $ERR
    592  1.15       mrg 		fi
    593  1.15       mrg 
    594  1.67     lukem 		file=$work_dir/setuid
    595  1.67     lukem 		migrate_file "$backup_dir/setuid" "$file"
    596  1.67     lukem 		CUR=${file}.current
    597  1.67     lukem 		BACK=${file}.backup
    598  1.15       mrg 		if [ -s $CUR ] ; then
    599  1.15       mrg 			if cmp -s $CUR $TMP1 ; then
    600  1.15       mrg 				:
    601  1.15       mrg 			else
    602  1.15       mrg 				> $TMP2
    603  1.15       mrg 				join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
    604  1.15       mrg 				if [ -s $OUTPUT ] ; then
    605  1.28     lukem 					printf "Setuid additions:\n" >> $ERR
    606  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    607  1.28     lukem 					printf "\n" >> $ERR
    608  1.15       mrg 				fi
    609  1.15       mrg 
    610  1.15       mrg 				join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
    611  1.15       mrg 				if [ -s $OUTPUT ] ; then
    612  1.28     lukem 					printf "Setuid deletions:\n" >> $ERR
    613  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    614  1.28     lukem 					printf "\n" >> $ERR
    615  1.15       mrg 				fi
    616  1.15       mrg 
    617  1.20   mycroft 				sort -k10 $TMP2 $CUR $TMP1 | \
    618  1.27     lukem 				    sed -e 's/[	 ][	 ]*/ /g' | \
    619  1.27     lukem 				    uniq -u > $OUTPUT
    620  1.15       mrg 				if [ -s $OUTPUT ] ; then
    621  1.28     lukem 					printf "Setuid changes:\n" >> $ERR
    622  1.28     lukem 					column -t $OUTPUT >> $ERR
    623  1.28     lukem 					printf "\n" >> $ERR
    624  1.15       mrg 				fi
    625   1.9       cgd 
    626  1.52    atatat 				backup_file update $TMP1 $CUR $BACK
    627   1.9       cgd 			fi
    628  1.15       mrg 		else
    629  1.28     lukem 			printf "Setuid additions:\n" >> $ERR
    630  1.28     lukem 			column -t $TMP1 >> $ERR
    631  1.28     lukem 			printf "\n" >> $ERR
    632  1.52    atatat 			backup_file add $TMP1 $CUR $BACK
    633   1.9       cgd 		fi
    634  1.15       mrg 	fi
    635  1.15       mrg 
    636  1.27     lukem 	# Check for block and character disk devices that are readable or
    637  1.27     lukem 	# writeable or not owned by root.operator.
    638  1.15       mrg 	>$TMP1
    639  1.61     lukem 	DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \
    640  1.57    simonb 	    sd se ss uk up vnd wd xd xy"
    641  1.27     lukem #	DISKLIST="$DISKLIST ct mt st wt"
    642  1.15       mrg 	for i in $DISKLIST; do
    643  1.15       mrg 		egrep "^b.*/${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
    644  1.15       mrg 		egrep "^c.*/r${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
    645  1.15       mrg 	done
    646  1.15       mrg 
    647  1.15       mrg 	awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
    648  1.25     lukem 		{ printf "Disk %s is user %s, group %s, permissions %s.\n", \
    649  1.25     lukem 		    $11, $3, $4, $1; }' < $TMP1 > $OUTPUT
    650  1.15       mrg 	if [ -s $OUTPUT ] ; then
    651  1.28     lukem 		printf "\nChecking disk ownership and permissions.\n" >> $ERR
    652  1.28     lukem 		cat $OUTPUT >> $ERR
    653  1.28     lukem 		printf "\n" >> $ERR
    654   1.9       cgd 	fi
    655   1.9       cgd 
    656  1.15       mrg 	# Display any changes in the device file list.
    657  1.20   mycroft 	egrep '^[bc]' $LIST | sort -k11 > $TMP1
    658  1.15       mrg 	if [ -s $TMP1 ] ; then
    659  1.67     lukem 		file=$work_dir/device
    660  1.67     lukem 		migrate_file "$backup_dir/device" "$file"
    661  1.67     lukem 		CUR=${file}.current
    662  1.67     lukem 		BACK=${file}.backup
    663  1.15       mrg 
    664  1.15       mrg 		if [ -s $CUR ] ; then
    665  1.15       mrg 			if cmp -s $CUR $TMP1 ; then
    666  1.15       mrg 				:
    667  1.15       mrg 			else
    668  1.15       mrg 				> $TMP2
    669  1.15       mrg 				join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
    670  1.15       mrg 				if [ -s $OUTPUT ] ; then
    671  1.28     lukem 					printf "Device additions:\n" >> $ERR
    672  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    673  1.28     lukem 					printf "\n" >> $ERR
    674  1.15       mrg 				fi
    675  1.15       mrg 
    676  1.15       mrg 				join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
    677  1.15       mrg 				if [ -s $OUTPUT ] ; then
    678  1.28     lukem 					printf "Device deletions:\n" >> $ERR
    679  1.28     lukem 					tee -a $TMP2 < $OUTPUT >> $ERR
    680  1.28     lukem 					printf "\n" >> $ERR
    681  1.15       mrg 				fi
    682  1.15       mrg 
    683  1.27     lukem 				# Report any block device change. Ignore
    684  1.27     lukem 				# character devices, only the name is
    685  1.27     lukem 				# significant.
    686  1.15       mrg 				cat $TMP2 $CUR $TMP1 | \
    687  1.27     lukem 				    sed -e '/^c/d' | \
    688  1.27     lukem 				    sort -k11 | \
    689  1.27     lukem 				    sed -e 's/[	 ][	 ]*/ /g' | \
    690  1.27     lukem 				    uniq -u > $OUTPUT
    691  1.15       mrg 				if [ -s $OUTPUT ] ; then
    692  1.28     lukem 					printf "Block device changes:\n" >> $ERR
    693  1.28     lukem 					column -t $OUTPUT >> $ERR
    694  1.28     lukem 					printf "\n" >> $ERR
    695  1.15       mrg 				fi
    696   1.9       cgd 
    697  1.52    atatat 				backup_file update $TMP1 $CUR $BACK
    698   1.9       cgd 			fi
    699  1.15       mrg 		else
    700  1.28     lukem 			printf "Device additions:\n" >> $ERR
    701  1.28     lukem 			column -t $TMP1 >> $ERR
    702  1.28     lukem 			printf "\n" >> $ERR
    703  1.52    atatat 			backup_file add $TMP1 $CUR $BACK >> $ERR
    704   1.9       cgd 		fi
    705  1.28     lukem 	fi
    706  1.28     lukem 	if [ -s $ERR ] ; then
    707  1.28     lukem 		printf "\nChecking setuid files and devices:\n"
    708  1.28     lukem 		cat $ERR
    709  1.28     lukem 		printf "\n"
    710   1.9       cgd 	fi
    711   1.9       cgd fi
    712   1.9       cgd 
    713   1.9       cgd # Check special files.
    714   1.9       cgd # Check system binaries.
    715   1.9       cgd #
    716   1.9       cgd # Create the mtree tree specifications using:
    717  1.67     lukem #	mtree -cx -pDIR -kmd5,uid,gid,mode,nlink,size,link,time > DIR.secure
    718  1.38    kleink #	chown root:wheel DIR.secure
    719  1.67     lukem #	chmod u+r,go= DIR.secure
    720   1.9       cgd #
    721   1.9       cgd # Note, this is not complete protection against Trojan horsed binaries, as
    722   1.9       cgd # the hacker can modify the tree specification to match the replaced binary.
    723   1.9       cgd # For details on really protecting yourself against modified binaries, see
    724   1.9       cgd # the mtree(8) manual page.
    725  1.32     lukem #
    726  1.31     lukem if checkyesno check_mtree; then
    727  1.67     lukem 	for file in $special_files; do
    728  1.67     lukem 		[ ! -s $file ] && continue
    729  1.67     lukem 		mtree -e -l -p / -f $file
    730  1.67     lukem 	done > $OUTPUT
    731  1.15       mrg 	if [ -s $OUTPUT ]; then
    732   1.9       cgd 		printf "\nChecking special files and directories.\n"
    733   1.9       cgd 		cat $OUTPUT
    734   1.9       cgd 	fi
    735   1.9       cgd 
    736  1.16     mikel 	for file in /etc/mtree/*.secure; do
    737  1.16     mikel 		[ $file = '/etc/mtree/*.secure' ] && continue
    738   1.9       cgd 		tree=`sed -n -e '3s/.* //p' -e 3q $file`
    739   1.9       cgd 		mtree -f $file -p $tree > $TMP1
    740   1.9       cgd 		if [ -s $TMP1 ]; then
    741  1.67     lukem 			printf "\nChecking $tree:\n"
    742  1.67     lukem 			cat $TMP1
    743   1.9       cgd 		fi
    744  1.67     lukem 	done > $OUTPUT
    745  1.15       mrg 	if [ -s $OUTPUT ]; then
    746   1.9       cgd 		printf "\nChecking system binaries:\n"
    747   1.9       cgd 		cat $OUTPUT
    748   1.9       cgd 	fi
    749   1.9       cgd fi
    750   1.9       cgd 
    751  1.32     lukem # Backup disklabels of available disks
    752  1.32     lukem #
    753  1.32     lukem if checkyesno check_disklabels; then
    754  1.67     lukem 		# migrate old disklabels
    755  1.67     lukem 	for file in `ls -1d $backup_dir/$backup_dir/disklabel.* \
    756  1.67     lukem 	    $backup_dir/disklabel.* 2>/dev/null`; do
    757  1.67     lukem 		migrate_file "$file" "$work_dir/${file##*/}"
    758  1.67     lukem 	done
    759  1.67     lukem 
    760  1.67     lukem 		# generate list of old disklabels & fdisks and remove them
    761  1.67     lukem 	ls -1d $work_dir/disklabel.* $work_dir/fdisk.* 2>/dev/null |
    762  1.52    atatat 	    egrep -v '\.(backup|current)(,v)?$' > $LABELS
    763  1.32     lukem 	xargs rm < $LABELS
    764  1.32     lukem 
    765  1.67     lukem 		# generate disklabels of all disks excluding:	cd fd md
    766  1.63     lukem 	disks=`iostat -x | awk 'NR > 1 && $1 !~ /^[cfm]d/ { print $1; }'`
    767  1.32     lukem 	for i in $disks; do
    768  1.67     lukem 		disklabel $i > "$work_dir/disklabel.$i" 2>/dev/null
    769  1.32     lukem 	done
    770  1.32     lukem 
    771  1.67     lukem 		# if fdisk is available, generate fdisks for:	ed ld sd wd
    772  1.67     lukem 	if [ -x /sbin/fdisk ]; then
    773  1.67     lukem 		disks=`iostat -x| awk 'NR > 1 && $1 ~ /^[elsw]d/ { print $1; }'`
    774  1.67     lukem 		for i in $disks; do
    775  1.67     lukem 			/sbin/fdisk $i > "$work_dir/fdisk.$i" 2>/dev/null
    776  1.67     lukem 		done
    777  1.67     lukem 	fi
    778  1.67     lukem 
    779  1.67     lukem 		# append list of new disklabels and fdisks
    780  1.67     lukem 	ls -1d $work_dir/disklabel.* $work_dir/fdisk.* 2>/dev/null |
    781  1.52    atatat 	    egrep -v '\.(backup|current)(,v)?$' >> $LABELS
    782  1.62    atatat 	CHANGELIST="$LABELS $CHANGELIST"
    783  1.62    atatat fi
    784  1.62    atatat 
    785  1.62    atatat # Check for changes in the list of installed pkgs
    786  1.62    atatat #
    787  1.65     lukem if checkyesno check_pkgs && [ -d $pkgdb_dir ]; then
    788  1.67     lukem 	pkgs=$work_dir/pkgs
    789  1.67     lukem 	migrate_file "$backup_dir/pkgs" "$pkgs"
    790  1.65     lukem 	(	cd $pkgdb_dir
    791  1.62    atatat 		pkg_info | sort
    792  1.62    atatat 		echo ""
    793  1.62    atatat 		find . \( -name +REQUIRED_BY -o -name +CONTENTS \) -print0 |
    794  1.72     lukem 			xargs -0 ls -ldgTq | sort -t. +1 | sed -e 's, \./, ,'
    795  1.62    atatat 	 ) > $pkgs
    796  1.67     lukem 	echo "$pkgs" > $PKGS
    797  1.62    atatat 	CHANGELIST="$PKGS $CHANGELIST"
    798  1.32     lukem fi
    799  1.32     lukem 
    800  1.67     lukem # List of files that get backed up and checked for any modifications.
    801   1.9       cgd # Any changes cause the files to rotate.
    802  1.32     lukem #
    803  1.67     lukem if checkyesno check_changelist ; then
    804  1.67     lukem 	for file in $special_files; do
    805  1.67     lukem 		[ ! -s $file ] && continue
    806  1.67     lukem 		mtree -D -k type -f $file -E exclude |
    807  1.67     lukem 		    sed '/^type=file/!d ; s/type=file \.//'
    808  1.67     lukem 	done > $CHANGEFILES
    809  1.67     lukem 
    810  1.75     lukem 	(
    811  1.68     lukem 		# Add other files which might dynamically exist:
    812  1.67     lukem 		#	/etc/ifconfig.*
    813  1.67     lukem 		#	/etc/raid*.conf
    814  1.68     lukem 		#	/etc/rc.d/*
    815  1.67     lukem 		#	/etc/rc.conf.d/*
    816  1.68     lukem 		#
    817  1.75     lukem 		echo "/etc/ifconfig.*"
    818  1.75     lukem 		echo "/etc/raid*.conf"
    819  1.75     lukem 		echo "/etc/rc.d/*"
    820  1.75     lukem 		echo "/etc/rc.conf.d/*"
    821  1.67     lukem 
    822  1.68     lukem 		# Add /etc/changelist
    823  1.68     lukem 		#
    824  1.75     lukem 		if [ -s /etc/changelist ]; then
    825  1.75     lukem 			grep -v '^#' /etc/changelist
    826  1.75     lukem 		fi
    827  1.75     lukem 	) | while read file; do
    828  1.75     lukem 		case "$file" in
    829  1.75     lukem 		*[\*\?\[]*)	# If changelist line is a glob ...
    830  1.75     lukem 				# ... expand possible backup files
    831  1.75     lukem 				#
    832  1.75     lukem 			ls -1d $(echo $backup_dir/${file}.current) 2>/dev/null \
    833  1.75     lukem 			    | sed "s,^$backup_dir/,, ; s,\.current$,,"
    834  1.75     lukem 				
    835  1.75     lukem 				# ... expand possible files
    836  1.75     lukem 				#
    837  1.75     lukem 			ls -1d $(echo $file) 2>/dev/null
    838  1.75     lukem 			;;
    839  1.75     lukem 		*)
    840  1.75     lukem 				# Otherwise, just print the filename
    841  1.75     lukem 			echo $file
    842  1.75     lukem 			;;
    843  1.75     lukem 		esac
    844  1.75     lukem 	done >> $CHANGEFILES
    845  1.67     lukem 	CHANGELIST="$CHANGEFILES $CHANGELIST"
    846  1.67     lukem fi
    847  1.67     lukem 
    848  1.67     lukem # Special case backups, including the master password file and
    849  1.67     lukem # ssh private host keys. The normal backup mechanisms for
    850  1.67     lukem # $check_changelist (see below) also print out the actual file
    851  1.67     lukem # differences and we don't want to do that for these files
    852  1.67     lukem #
    853  1.67     lukem echo $MP > $TMP1			# always add /etc/master.passwd
    854  1.67     lukem for file in $special_files; do
    855  1.67     lukem 	[ ! -s $file ] && continue
    856  1.70     lukem 	mtree -D -k type -f $file -I nodiff |
    857  1.67     lukem 	    sed '/^type=file/!d ; s/type=file \.//'
    858  1.67     lukem done >> $TMP1
    859  1.73     lukem grep -v '^$' $TMP1 | sort -u > $TMP2
    860  1.68     lukem 
    861  1.69     lukem while read file; do
    862  1.67     lukem 	backup_and_diff "$file" no
    863  1.69     lukem done < $TMP2
    864  1.67     lukem 
    865  1.32     lukem 
    866  1.32     lukem if [ -n "$CHANGELIST" ]; then
    867  1.73     lukem 	grep -h -v '^$' $CHANGELIST | sort -u > $TMP1
    868  1.68     lukem 	comm -23 $TMP1 $TMP2 | while read file; do
    869  1.67     lukem 		backup_and_diff "$file" yes
    870   1.9       cgd 	done
    871  1.44        ad fi
    872  1.44        ad 
    873  1.44        ad if [ -f /etc/security.local ]; then
    874  1.44        ad 	echo ""
    875  1.44        ad 	echo "Running /etc/security.local:"
    876  1.44        ad 	. /etc/security.local
    877   1.9       cgd fi
    878