[BACK]Return to security CVS log [TXT][DIR] Up to [local] / src / etc

Annotation of src/etc/security, Revision 1.12

1.1       deraadt     1: #!/bin/sh -
                      2: #
1.12    ! millert     3: #      $OpenBSD: security,v 1.11 1996/10/22 07:58:30 tholo Exp $
1.1       deraadt     4: #
                      5: PATH=/sbin:/usr/sbin:/bin:/usr/bin
                      6:
                      7: umask 077
                      8:
1.7       deraadt     9: DIR=/tmp/_secure$$
                     10: ERR=$DIR/_secure1
                     11: TMP1=$DIR/_secure2
                     12: TMP2=$DIR/_secure3
                     13: TMP3=$DIR/_secure4
                     14: LIST=$DIR/_secure5
                     15: OUTPUT=$DIR/_secure6
1.1       deraadt    16:
1.7       deraadt    17:
                     18: if ! mkdir $DIR ; then
                     19:        printf "tmp directory %s already exists, looks like:\n" $DIR
                     20:        ls -alF $DIR
                     21:        exit 1
                     22: fi
1.8       deraadt    23:
                     24: trap 'rm -rf $DIR' 0
1.1       deraadt    25:
                     26: # Check the master password file syntax.
                     27: MP=/etc/master.passwd
                     28: awk -F: '{
                     29:        if ($0 ~ /^[     ]*$/) {
                     30:                printf("Line %d is a blank line.\n", NR);
                     31:                next;
                     32:        }
                     33:        if (NF != 10)
                     34:                printf("Line %d has the wrong number of fields.\n", NR);
1.2       deraadt    35:        if ($1 ~ /^[+-].*$/)
                     36:                next;
                     37:        if ($1 == "")
                     38:                printf("Line %d has an empty login field.\n",NR);
                     39:        else if ($1 !~ /^[A-Za-z0-9][A-Za-z0-9_-]*$/)
1.1       deraadt    40:                printf("Login %s has non-alphanumeric characters.\n", $1);
                     41:        if (length($1) > 8)
                     42:                printf("Login %s has more than 8 characters.\n", $1);
                     43:        if ($2 == "")
                     44:                printf("Login %s has no password.\n", $1);
                     45:        if (length($2) != 13 && ($10 ~ /.*sh$/ || $10 == ""))
                     46:                printf("Login %s is off but still has a valid shell.\n", $1);
1.9       deraadt    47:        if ($3 == 0 && $1 != "root")
1.1       deraadt    48:                printf("Login %s has a user id of 0.\n", $1);
                     49:        if ($3 < 0)
                     50:                printf("Login %s has a negative user id.\n", $1);
                     51:        if ($4 < 0)
                     52:                printf("Login %s has a negative group id.\n", $1);
                     53: }' < $MP > $OUTPUT
                     54: if [ -s $OUTPUT ] ; then
                     55:        printf "\nChecking the $MP file:\n"
                     56:        cat $OUTPUT
                     57: fi
                     58:
                     59: awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
                     60: if [ -s $OUTPUT ] ; then
                     61:        printf "\n$MP has duplicate user names.\n"
                     62:        column $OUTPUT
                     63: fi
                     64:
1.9       deraadt    65: awk -F: '{ print $1 " " $3 }' $MP | sort -n +1 | tee $TMP1 |
1.1       deraadt    66: uniq -d -f 1 | awk '{ print $2 }' > $TMP2
                     67: if [ -s $TMP2 ] ; then
                     68:        printf "\n$MP has duplicate user id's.\n"
                     69:         while read uid; do
                     70:                 grep -w $uid $TMP1
                     71:         done < $TMP2 | column
                     72: fi
                     73:
                     74: # Backup the master password file; a special case, the normal backup
                     75: # mechanisms also print out file differences and we don't want to do
                     76: # that because this file has encrypted passwords in it.
1.2       deraadt    77: if [ ! -d /var/backups ] ; then
                     78:        mkdir /var/backups
                     79:        chmod 755 /var/backups
                     80: fi
1.1       deraadt    81: CUR=/var/backups/`basename $MP`.current
                     82: BACK=/var/backups/`basename $MP`.backup
                     83: if [ -s $CUR ] ; then
                     84:        if cmp -s $CUR $MP; then
                     85:                :
                     86:        else
                     87:                cp -p $CUR $BACK
                     88:                cp -p $MP $CUR
                     89:                chown root.wheel $CUR
                     90:        fi
                     91: else
                     92:        cp -p $MP $CUR
                     93:        chown root.wheel $CUR
                     94: fi
                     95:
                     96: # Check the group file syntax.
                     97: GRP=/etc/group
                     98: awk -F: '{
                     99:        if ($0 ~ /^[     ]*$/) {
                    100:                printf("Line %d is a blank line.\n", NR);
                    101:                next;
                    102:        }
1.2       deraadt   103:        if ($1 ~ /^[+-].*$/)
                    104:                next;
1.1       deraadt   105:        if (NF != 4)
                    106:                printf("Line %d has the wrong number of fields.\n", NR);
                    107:        if ($1 !~ /^[A-za-z0-9]*$/)
                    108:                printf("Group %s has non-alphanumeric characters.\n", $1);
                    109:        if (length($1) > 8)
                    110:                printf("Group %s has more than 8 characters.\n", $1);
                    111:        if ($3 !~ /[0-9]*/)
                    112:                printf("Login %s has a negative group id.\n", $1);
                    113: }' < $GRP > $OUTPUT
                    114: if [ -s $OUTPUT ] ; then
                    115:        printf "\nChecking the $GRP file:\n"
                    116:        cat $OUTPUT
                    117: fi
                    118:
                    119: awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
                    120: if [ -s $OUTPUT ] ; then
                    121:        printf "\n$GRP has duplicate group names.\n"
                    122:        column $OUTPUT
                    123: fi
                    124:
                    125: # Check for root paths, umask values in startup files.
                    126: # The check for the root paths is problematical -- it's likely to fail
                    127: # in other environments.  Once the shells have been modified to warn
                    128: # of '.' in the path, the path tests should go away.
                    129: > $OUTPUT
                    130: rhome=/root
                    131: umaskset=no
                    132: list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
                    133: for i in $list ; do
                    134:        if [ -f $i ] ; then
                    135:                if egrep umask $i > /dev/null ; then
                    136:                        umaskset=yes
                    137:                fi
                    138:                egrep umask $i |
                    139:                awk '$2 % 100 < 20 \
                    140:                        { print "Root umask is group writeable" }
                    141:                     $2 % 10 < 2 \
                    142:                        { print "Root umask is other writeable" }' >> $OUTPUT
                    143:                /bin/csh -f -s << end-of-csh > /dev/null 2>&1
                    144:                        unset path
                    145:                        source $i
                    146:                        /bin/ls -ldgT \$path > $TMP1
                    147: end-of-csh
                    148:                awk '{
                    149:                        if ($10 ~ /^\.$/) {
                    150:                                print "The root path includes .";
                    151:                                next;
                    152:                        }
                    153:                     }
                    154:                     $1 ~ /^d....w/ \
                    155:         { print "Root path directory " $10 " is group writeable." } \
                    156:                     $1 ~ /^d.......w/ \
                    157:         { print "Root path directory " $10 " is other writeable." }' \
                    158:                < $TMP1 >> $OUTPUT
                    159:        fi
                    160: done
                    161: if [ $umaskset = "no" -o -s $OUTPUT ] ; then
                    162:        printf "\nChecking root csh paths, umask values:\n$list\n"
                    163:        if [ -s $OUTPUT ]; then
                    164:                cat $OUTPUT
                    165:        fi
                    166:        if [ $umaskset = "no" ] ; then
                    167:                printf "\nRoot csh startup files do not set the umask.\n"
                    168:        fi
                    169: fi
                    170:
                    171: > $OUTPUT
                    172: rhome=/root
                    173: umaskset=no
                    174: list="${rhome}/.profile"
                    175: for i in $list; do
                    176:        if [ -f $i ] ; then
                    177:                if egrep umask $i > /dev/null ; then
                    178:                        umaskset=yes
                    179:                fi
                    180:                egrep umask $i |
                    181:                awk '$2 % 100 < 20 \
                    182:                        { print "Root umask is group writeable" } \
                    183:                     $2 % 10 < 2 \
                    184:                        { print "Root umask is other writeable" }' >> $OUTPUT
                    185:                /bin/sh << end-of-sh > /dev/null 2>&1
                    186:                        PATH=
                    187:                        . $i
                    188:                        list=\`echo \$PATH | /usr/bin/sed -e 's/:/ /g'\`
                    189:                        /bin/ls -ldgT \$list > $TMP1
                    190: end-of-sh
                    191:                awk '{
                    192:                        if ($10 ~ /^\.$/) {
                    193:                                print "The root path includes .";
                    194:                                next;
                    195:                        }
                    196:                     }
                    197:                     $1 ~ /^d....w/ \
                    198:         { print "Root path directory " $10 " is group writeable." } \
                    199:                     $1 ~ /^d.......w/ \
                    200:         { print "Root path directory " $10 " is other writeable." }' \
                    201:                < $TMP1 >> $OUTPUT
                    202:
                    203:        fi
                    204: done
                    205: if [ $umaskset = "no" -o -s $OUTPUT ] ; then
                    206:        printf "\nChecking root sh paths, umask values:\n$list\n"
                    207:        if [ -s $OUTPUT ]; then
                    208:                cat $OUTPUT
                    209:        fi
                    210:        if [ $umaskset = "no" ] ; then
                    211:                printf "\nRoot sh startup files do not set the umask.\n"
                    212:        fi
                    213: fi
                    214:
                    215: # Root and uucp should both be in /etc/ftpusers.
                    216: if egrep root /etc/ftpusers > /dev/null ; then
                    217:        :
                    218: else
                    219:        printf "\nRoot not listed in /etc/ftpusers file.\n"
                    220: fi
                    221: if egrep uucp /etc/ftpusers > /dev/null ; then
                    222:        :
                    223: else
                    224:        printf "\nUucp not listed in /etc/ftpusers file.\n"
                    225: fi
                    226:
                    227: # Uudecode should not be in the /etc/aliases file.
                    228: if egrep 'uudecode|decode' /etc/aliases; then
                    229:        printf "\nThere is an entry for uudecode in the /etc/aliases file.\n"
                    230: fi
                    231:
                    232: # Files that should not have + signs.
1.2       deraadt   233: list="/etc/hosts.equiv /etc/shosts.equiv /etc/hosts.lpd"
1.1       deraadt   234: for f in $list ; do
1.6       millert   235:        if [ -s $f ] ; then
1.2       deraadt   236:                awk '{
1.6       millert   237:                        if ($0 ~ /^\+@.*$/ )
1.2       deraadt   238:                                next;
1.6       millert   239:                        if ($0 ~ /^\+.*$/ )
1.2       deraadt   240:                                printf("\nPlus sign in %s file.\n", FILENAME);
                    241:                }' $f
1.1       deraadt   242:        fi
                    243: done
                    244:
1.9       deraadt   245: # Check for special users with .rhosts/.shosts files.  Only root should
                    246: # have .rhosts/.shosts files.  Also, .rhosts/.shosts files
1.2       deraadt   247: # should not have plus signs.
1.9       deraadt   248: awk -F: '$1 != "root" && $1 !~ /^[+-].*$/ && \
1.1       deraadt   249:        ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
                    250:                { print $1 " " $6 }' /etc/passwd |
                    251: while read uid homedir; do
1.2       deraadt   252:        for j in .rhosts .shosts; do
                    253:                if [ -f ${homedir}/$j ] ; then
                    254:                        rhost=`ls -ldgT ${homedir}/$j`
                    255:                        printf "$uid: $rhost\n"
                    256:                fi
                    257:        done
1.1       deraadt   258: done > $OUTPUT
                    259: if [ -s $OUTPUT ] ; then
1.2       deraadt   260:        printf "\nChecking for special users with .rhosts/.shosts files.\n"
1.1       deraadt   261:        cat $OUTPUT
                    262: fi
                    263:
                    264: awk -F: '{ print $1 " " $6 }' /etc/passwd | \
                    265: while read uid homedir; do
1.2       deraadt   266:        for j in .rhosts .shosts; do
                    267:                if [ -f ${homedir}/$j ] ; then
                    268:                        awk '{
                    269:                                if ($0 ~ /^+@.*$/ )
                    270:                                        next;
1.4       deraadt   271:                                if ($0 ~ /^\+[  ]*$/ )
1.2       deraadt   272:                                        printf("%s has + sign in it.\n",
                    273:                                            FILENAME);
                    274:                        }' ${homedir}/$j
                    275:                fi
                    276:        done
1.1       deraadt   277: done > $OUTPUT
                    278: if [ -s $OUTPUT ] ; then
1.2       deraadt   279:        printf "\nChecking .rhosts/.shosts files syntax.\n"
1.1       deraadt   280:        cat $OUTPUT
                    281: fi
                    282:
                    283: # Check home directories.  Directories should not be owned by someone else
                    284: # or writeable.
1.2       deraadt   285: awk -F: '{ if ( $1 !~ /^[+-].*$/ ) print $1 " " $6 }' /etc/passwd | \
1.1       deraadt   286: while read uid homedir; do
                    287:        if [ -d ${homedir}/ ] ; then
                    288:                file=`ls -ldgT ${homedir}`
                    289:                printf "$uid $file\n"
                    290:        fi
                    291: done |
                    292: awk '$1 != $4 && $4 != "root" \
                    293:        { print "user " $1 " home directory is owned by " $4 }
                    294:      $2 ~ /^-....w/ \
                    295:        { print "user " $1 " home directory is group writeable" }
                    296:      $2 ~ /^-.......w/ \
                    297:        { print "user " $1 " home directory is other writeable" }' > $OUTPUT
                    298: if [ -s $OUTPUT ] ; then
                    299:        printf "\nChecking home directories.\n"
                    300:        cat $OUTPUT
                    301: fi
                    302:
                    303: # Files that should not be owned by someone else or readable.
1.2       deraadt   304: list=".netrc .rhosts .shosts"
1.1       deraadt   305: awk -F: '{ print $1 " " $6 }' /etc/passwd | \
                    306: while read uid homedir; do
                    307:        for f in $list ; do
                    308:                file=${homedir}/${f}
                    309:                if [ -f $file ] ; then
                    310:                        printf "$uid $f `ls -ldgT $file`\n"
                    311:                fi
                    312:        done
                    313: done |
                    314: awk '$1 != $5 && $5 != "root" \
                    315:        { print "user " $1 " " $2 " file is owned by " $5 }
                    316:      $3 ~ /^-......r/ \
                    317:        { print "user " $1 " " $2 " file is other readable" }
                    318:      $3 ~ /^-....w/ \
                    319:        { print "user " $1 " " $2 " file is group writeable" }
                    320:      $3 ~ /^-.......w/ \
                    321:        { print "user " $1 " " $2 " file is other writeable" }' > $OUTPUT
                    322:
                    323: # Files that should not be owned by someone else or writeable.
                    324: list=".bashrc .cshrc .emacs .exrc .forward .klogin .login .logout \
                    325:       .profile .tcshrc"
                    326: awk -F: '{ print $1 " " $6 }' /etc/passwd | \
                    327: while read uid homedir; do
                    328:        for f in $list ; do
                    329:                file=${homedir}/${f}
                    330:                if [ -f $file ] ; then
                    331:                        printf "$uid $f `ls -ldgT $file`\n"
                    332:                fi
                    333:        done
                    334: done |
                    335: awk '$1 != $5 && $5 != "root" \
                    336:        { print "user " $1 " " $2 " file is owned by " $5 }
                    337:      $3 ~ /^-....w/ \
                    338:        { print "user " $1 " " $2 " file is group writeable" }
                    339:      $3 ~ /^-.......w/ \
                    340:        { print "user " $1 " " $2 " file is other writeable" }' >> $OUTPUT
                    341: if [ -s $OUTPUT ] ; then
                    342:        printf "\nChecking dot files.\n"
                    343:        cat $OUTPUT
                    344: fi
                    345:
                    346: # Mailboxes should be owned by user and unreadable.
                    347: ls -l /var/mail | sed 1d | \
                    348: awk '$3 != $9 \
                    349:        { print "user " $9 " mailbox is owned by " $3 }
                    350:      $1 != "-rw-------" \
                    351:        { print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
                    352: if [ -s $OUTPUT ] ; then
                    353:        printf "\nChecking mailbox ownership.\n"
                    354:        cat $OUTPUT
                    355: fi
                    356:
1.2       deraadt   357: if [ -f /etc/exports ]; then
                    358:     # File systems should not be globally exported.
                    359:     awk '{
1.11      tholo     360:        if ($1 ~ /^#/)
                    361:                next;
1.1       deraadt   362:        readonly = 0;
                    363:        for (i = 2; i <= NF; ++i) {
                    364:                if ($i ~ /-ro/)
                    365:                        readonly = 1;
                    366:                else if ($i !~ /^-/)
                    367:                        next;
                    368:        }
                    369:        if (readonly)
                    370:                print "File system " $1 " globally exported, read-only."
                    371:        else
                    372:                print "File system " $1 " globally exported, read-write."
1.2       deraadt   373:     }' < /etc/exports > $OUTPUT
                    374:     if [ -s $OUTPUT ] ; then
1.1       deraadt   375:        printf "\nChecking for globally exported file systems.\n"
                    376:        cat $OUTPUT
1.2       deraadt   377:     fi
1.1       deraadt   378: fi
                    379:
1.5       deraadt   380: # Display any changes in setuid/setgid files and devices.
                    381: pending="\nChecking setuid/setgid files and devices:\n"
1.1       deraadt   382: (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
                    383:                -o -fstype procfs \) -a -prune -o \
1.11      tholo     384:        -type f -a \( -perm -u+s -o -perm -g+s \) -ls -o \
1.10      bitblt    385:        ! -type d -a ! -type f -a ! -type l -a ! -type s -ls | \
                    386: sort > $LIST) 2> $OUTPUT
1.1       deraadt   387:
                    388: # Display any errors that occurred during system file walk.
                    389: if [ -s $OUTPUT ] ; then
1.2       deraadt   390:        printf "${pending}Setuid/device find errors:\n"
                    391:        pending=
1.1       deraadt   392:        cat $OUTPUT
                    393:        printf "\n"
                    394: fi
                    395:
1.12    ! millert   396: # Display any changes in the setuid/setgid file list.
        !           397: egrep -v '^ *[0-9]+ +[0-9]+ +[bc]' $LIST > $TMP1
1.1       deraadt   398: if [ -s $TMP1 ] ; then
                    399:        # Check to make sure uudecode isn't setuid.
                    400:        if grep -w uudecode $TMP1 > /dev/null ; then
1.2       deraadt   401:                printf "${pending}\nUudecode is setuid.\n"
                    402:                pending=
1.1       deraadt   403:        fi
                    404:
                    405:        CUR=/var/backups/setuid.current
                    406:        BACK=/var/backups/setuid.backup
                    407:
                    408:        if [ -s $CUR ] ; then
                    409:                if cmp -s $CUR $TMP1 ; then
                    410:                        :
                    411:                else
                    412:                        > $TMP2
1.11      tholo     413:                        join -112 -212 -v2 $CUR $TMP1 > $OUTPUT
1.1       deraadt   414:                        if [ -s $OUTPUT ] ; then
1.2       deraadt   415:                                printf "${pending}Setuid additions:\n"
                    416:                                pending=
1.1       deraadt   417:                                tee -a $TMP2 < $OUTPUT
                    418:                                printf "\n"
                    419:                        fi
                    420:
1.11      tholo     421:                        join -112 -212 -v1 $CUR $TMP1 > $OUTPUT
1.1       deraadt   422:                        if [ -s $OUTPUT ] ; then
1.2       deraadt   423:                                printf "${pending}Setuid deletions:\n"
                    424:                                pending=
1.1       deraadt   425:                                tee -a $TMP2 < $OUTPUT
                    426:                                printf "\n"
                    427:                        fi
                    428:
1.11      tholo     429:                        sort +11 $TMP2 $CUR $TMP1 | \
1.1       deraadt   430:                            sed -e 's/[  ][      ]*/ /g' | uniq -u > $OUTPUT
                    431:                        if [ -s $OUTPUT ] ; then
1.2       deraadt   432:                                printf "${pending}Setuid changes:\n"
                    433:                                pending=
1.1       deraadt   434:                                column -t $OUTPUT
                    435:                                printf "\n"
                    436:                        fi
                    437:
                    438:                        cp $CUR $BACK
                    439:                        cp $TMP1 $CUR
                    440:                fi
                    441:        else
1.2       deraadt   442:                printf "${pending}Setuid additions:\n"
                    443:                pending=
1.1       deraadt   444:                column -t $TMP1
                    445:                printf "\n"
                    446:                cp $TMP1 $CUR
                    447:        fi
                    448: fi
                    449:
                    450: # Check for block and character disk devices that are readable or writeable
                    451: # or not owned by root.operator.
                    452: >$TMP1
1.2       deraadt   453: DISKLIST="dk fd hd hk hp jb kra ra rb rd rl rx xd rz sd up wd vnd ccd"
1.1       deraadt   454: for i in $DISKLIST; do
1.11      tholo     455:        egrep "^b.*/${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
                    456:        egrep "^c.*/r${i}[0-9][0-9]*[a-p]$"  $LIST >> $TMP1
1.1       deraadt   457: done
                    458:
                    459: awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
                    460:        { printf("Disk %s is user %s, group %s, permissions %s.\n", \
                    461:            $11, $3, $4, $1); }' < $TMP1 > $OUTPUT
                    462: if [ -s $OUTPUT ] ; then
                    463:        printf "\nChecking disk ownership and permissions.\n"
                    464:        cat $OUTPUT
                    465:        printf "\n"
                    466: fi
                    467:
                    468: # Display any changes in the device file list.
                    469: egrep '^[bc]' $LIST | sort +10 > $TMP1
                    470: if [ -s $TMP1 ] ; then
                    471:        CUR=/var/backups/device.current
                    472:        BACK=/var/backups/device.backup
                    473:
                    474:        if [ -s $CUR ] ; then
                    475:                if cmp -s $CUR $TMP1 ; then
                    476:                        :
                    477:                else
                    478:                        > $TMP2
                    479:                        join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
                    480:                        if [ -s $OUTPUT ] ; then
                    481:                                printf "Device additions:\n"
                    482:                                tee -a $TMP2 < $OUTPUT
                    483:                                printf "\n"
                    484:                        fi
                    485:
                    486:                        join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
                    487:                        if [ -s $OUTPUT ] ; then
                    488:                                printf "Device deletions:\n"
                    489:                                tee -a $TMP2 < $OUTPUT
                    490:                                printf "\n"
                    491:                        fi
                    492:
                    493:                        # Report any block device change.  Ignore character
                    494:                        # devices, only the name is significant.
                    495:                        cat $TMP2 $CUR $TMP1 | \
                    496:                        sed -e '/^c/d' | \
                    497:                        sort +10 | \
                    498:                        sed -e 's/[      ][      ]*/ /g' | \
                    499:                        uniq -u > $OUTPUT
                    500:                        if [ -s $OUTPUT ] ; then
                    501:                                printf "Block device changes:\n"
                    502:                                column -t $OUTPUT
                    503:                                printf "\n"
                    504:                        fi
                    505:
                    506:                        cp $CUR $BACK
                    507:                        cp $TMP1 $CUR
                    508:                fi
                    509:        else
                    510:                printf "Device additions:\n"
                    511:                column -t $TMP1
                    512:                printf "\n"
                    513:                cp $TMP1 $CUR
                    514:        fi
                    515: fi
                    516:
                    517: # Check special files.
                    518: # Check system binaries.
                    519: #
                    520: # Create the mtree tree specifications using:
                    521: #
                    522: #      mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
1.2       deraadt   523: #      chown root.wheel DIR.secure
                    524: #      chmod 600 DIR.secure
1.1       deraadt   525: #
                    526: # Note, this is not complete protection against Trojan horsed binaries, as
                    527: # the hacker can modify the tree specification to match the replaced binary.
                    528: # For details on really protecting yourself against modified binaries, see
                    529: # the mtree(8) manual page.
1.2       deraadt   530: if [ -d /etc/mtree ]; then
                    531:        cd /etc/mtree
1.1       deraadt   532:        mtree -e -p / -f /etc/mtree/special > $OUTPUT
                    533:        if [ -s $OUTPUT ] ; then
                    534:                printf "\nChecking special files and directories.\n"
                    535:                cat $OUTPUT
                    536:        fi
                    537:
                    538:        > $OUTPUT
                    539:        for file in *.secure; do
1.2       deraadt   540:                [ $file = '*.secure' ] && continue
1.1       deraadt   541:                tree=`sed -n -e '3s/.* //p' -e 3q $file`
                    542:                mtree -f $file -p $tree > $TMP1
                    543:                if [ -s $TMP1 ]; then
                    544:                        printf "\nChecking $tree:\n" >> $OUTPUT
                    545:                        cat $TMP1 >> $OUTPUT
                    546:                fi
                    547:        done
                    548:        if [ -s $OUTPUT ] ; then
                    549:                printf "\nChecking system binaries:\n"
                    550:                cat $OUTPUT
                    551:        fi
1.2       deraadt   552: else
                    553:        echo /etc/mtree is missing
1.1       deraadt   554: fi
                    555:
                    556: # List of files that get backed up and checked for any modifications.  Each
                    557: # file is expected to have two backups, /var/backups/file.{current,backup}.
                    558: # Any changes cause the files to rotate.
                    559: if [ -s /etc/changelist ] ; then
                    560:        for file in `cat /etc/changelist`; do
                    561:                CUR=/var/backups/`basename $file`.current
                    562:                BACK=/var/backups/`basename $file`.backup
                    563:                if [ -s $file ]; then
                    564:                        if [ -s $CUR ] ; then
                    565:                                diff $CUR $file > $OUTPUT
                    566:                                if [ -s $OUTPUT ] ; then
                    567:                printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
                    568:                                        cat $OUTPUT
                    569:                                        cp -p $CUR $BACK
                    570:                                        cp -p $file $CUR
                    571:                                        chown root.wheel $CUR $BACK
                    572:                                fi
                    573:                        else
                    574:                                cp -p $file $CUR
                    575:                                chown root.wheel $CUR
                    576:                        fi
                    577:                fi
                    578:        done
                    579: fi