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