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