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