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

Annotation of src/etc/security, Revision 1.27

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