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

Annotation of src/etc/security, Revision 1.13

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