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