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