161f28255Scgd#!/bin/sh - 261f28255Scgd# 3*b2f03d66She# $NetBSD: security,v 1.132 2024/07/21 14:56:16 he Exp $ 491778fe0Scgd# from: @(#)security 8.1 (Berkeley) 6/9/93 561f28255Scgd# 661f28255Scgd 791778fe0ScgdPATH=/sbin:/usr/sbin:/bin:/usr/bin 861f28255Scgd 93c8a1444Sjmmvrcvar_manpage='security.conf(5)' 103c8a1444Sjmmv 118f59ce8eSlukemif [ -f /etc/rc.subr ]; then 128f59ce8eSlukem . /etc/rc.subr 138f59ce8eSlukemelse 148f59ce8eSlukem echo "Can't read /etc/rc.subr; aborting." 158f59ce8eSlukem exit 1; 168f59ce8eSlukemfi 178f59ce8eSlukem 1891778fe0Scgdumask 077 19350cdd6aScjsTZ=UTC; export TZ 2061f28255Scgd 21a9efb638Smrgif [ -s /etc/security.conf ]; then 22a9efb638Smrg . /etc/security.conf 23a9efb638Smrgfi 241410cf30Sagcif [ -s /etc/pkgpath.conf ]; then 251410cf30Sagc . /etc/pkgpath.conf 261410cf30Sagcfi 271c2ae9dcScgd 2896a1608eSlukem# Set reasonable defaults (if they're not set in security.conf) 2996a1608eSlukem# 3096a1608eSlukembackup_dir=${backup_dir:-/var/backups} 3196a1608eSlukemmax_loginlen=${max_loginlen:-8} 3296a1608eSlukemmax_grouplen=${max_grouplen:-8} 33dc76b0b0Sprlw1pkg_admin=${pkg_admin:-/usr/sbin/pkg_admin} 3467b08a07Sadrianppkg_info=${pkg_info:-/usr/sbin/pkg_info} 3596a1608eSlukem 3696a1608eSlukem# Other configurable variables 3796a1608eSlukem# 3896a1608eSlukemspecial_files="/etc/mtree/special /etc/mtree/special.local" 3996a1608eSlukemMP=/etc/master.passwd 4096a1608eSlukemCHANGELIST="" 4196a1608eSlukemwork_dir=$backup_dir/work 4296a1608eSlukem 4396a1608eSlukemif [ ! -d "$work_dir" ]; then 4496a1608eSlukem mkdir -p "$work_dir" 4596a1608eSlukemfi 4696a1608eSlukem 47d405da7fSmarttiSECUREDIR=$(mktemp -d -t _securedir) || exit 1 48a9efb638Smrg 4996a1608eSlukemtrap "/bin/rm -rf $SECUREDIR ; exit 0" EXIT INT QUIT PIPE 50684e89f3Slukem 51684e89f3Slukemif ! cd "$SECUREDIR"; then 52684e89f3Slukem echo "Can not cd to $SECUREDIR". 53a9efb638Smrg exit 1 54a9efb638Smrgfi 55a9efb638Smrg 56610ee5bdSlukemERR=err.$$ 57610ee5bdSlukemTMP1=tmp1.$$ 58610ee5bdSlukemTMP2=tmp2.$$ 59610ee5bdSlukemMPBYUID=mpbyuid.$$ 60610ee5bdSlukemMPBYPATH=mpbypath.$$ 61610ee5bdSlukemLIST=list.$$ 62610ee5bdSlukemOUTPUT=output.$$ 63610ee5bdSlukemLABELS=labels.$$ 64a4e58525ShaadLVM_LABELS=lvm.$$ 65610ee5bdSlukemPKGS=pkgs.$$ 66610ee5bdSlukemCHANGEFILES=changefiles.$$ 67610ee5bdSlukemSPECIALSPEC=specialspec.$$ 68a9efb638Smrg 6953cb2117Sjmmvif [ -n "${pkgdb_dir}" ]; then 7053cb2117Sjmmv echo "WARNING: Setting pkgdb_dir in security.conf(5) is deprecated" 7153cb2117Sjmmv echo "WARNING: Please define PKG_DBDIR in pkg_install.conf(5) instead" 7253cb2117Sjmmv _compat_K_flag="-K ${pkgdb_dir}" 7353cb2117Sjmmvfi 7453cb2117Sjmmv 7553cb2117Sjmmvhave_pkgs() { 7653cb2117Sjmmv $pkg_info ${_compat_K_flag} -q -E '*' 7753cb2117Sjmmv} 7853cb2117Sjmmv 7996a1608eSlukem# migrate_file old new 8096a1608eSlukem# Determine if the "${old}" path name needs to be migrated to the 8196a1608eSlukem# "${new}" path. Also checks if "${old}.current" needs migrating, 8296a1608eSlukem# and if so, migrate it and possibly "${old}.current,v" and 8396a1608eSlukem# "${old}.backup". 8496a1608eSlukem# 8596a1608eSlukemmigrate_file() 8696a1608eSlukem{ 8796a1608eSlukem _old=$1 8896a1608eSlukem _new=$2 899ae2b31fSkre if [ -z "$_old" ] || [ -z "$_new" ]; then 9096a1608eSlukem err 3 "USAGE: migrate_file old new" 9196a1608eSlukem fi 9296a1608eSlukem if [ ! -d "${_new%/*}" ]; then 9396a1608eSlukem mkdir -p "${_new%/*}" 9496a1608eSlukem fi 959ae2b31fSkre if [ -f "${_old}" ] && ! [ -f "${_new}" ]; then 9696a1608eSlukem echo "==> migrating ${_old}" 9796a1608eSlukem echo " to ${_new}" 9896a1608eSlukem mv "${_old}" "${_new}" 9996a1608eSlukem fi 1009ae2b31fSkre if [ -f "${_old}.current" ] && ! [ -f "${_new}.current" ]; then 10196a1608eSlukem echo "==> migrating ${_old}.current" 10296a1608eSlukem echo " to ${_new}.current" 10396a1608eSlukem mv "${_old}.current" "${_new}.current" 1049ae2b31fSkre if [ -f "${_old}.current,v" ] && 1059ae2b31fSkre ! [ -f "${_new}.current,v" ]; then 10696a1608eSlukem echo "==> migrating ${_old}.current,v" 10796a1608eSlukem echo " to ${_new}.current,v" 10896a1608eSlukem mv "${_old}.current,v" "${_new}.current,v" 10996a1608eSlukem fi 1109ae2b31fSkre if [ -f "${_old}.backup" ] && ! [ -f "${_new}.backup" ]; then 11196a1608eSlukem echo "==> migrating ${_old}.backup" 11296a1608eSlukem echo " to ${_new}.backup" 11396a1608eSlukem mv "${_old}.backup" "${_new}.backup" 11496a1608eSlukem fi 11596a1608eSlukem fi 11696a1608eSlukem} 117a9efb638Smrg 11896a1608eSlukem 11996a1608eSlukem# backup_and_diff file printdiff 12096a1608eSlukem# Determine if file needs backing up, and if so, do it. 12196a1608eSlukem# If printdiff is yes, display the diffs, otherwise 12296a1608eSlukem# just print a message saying "[changes omitted]". 12396a1608eSlukem# 12496a1608eSlukembackup_and_diff() 12596a1608eSlukem{ 12696a1608eSlukem _file=$1 12796a1608eSlukem _printdiff=$2 1289ae2b31fSkre if [ -z "$_file" ] || [ -z "$_printdiff" ]; then 12996a1608eSlukem err 3 "USAGE: backup_and_diff file printdiff" 13096a1608eSlukem fi 13196a1608eSlukem ! checkyesno _printdiff 13296a1608eSlukem _printdiff=$? 13396a1608eSlukem 13496a1608eSlukem _old=$backup_dir/${_file##*/} 13596a1608eSlukem case "$_file" in 13696a1608eSlukem $work_dir/*) 13796a1608eSlukem _new=$_file 13896a1608eSlukem migrate_file "$backup_dir/$_old" "$_new" 13996a1608eSlukem migrate_file "$_old" "$_new" 14096a1608eSlukem ;; 14196a1608eSlukem *) 14296a1608eSlukem _new=$backup_dir/$_file 14396a1608eSlukem migrate_file "$_old" "$_new" 14496a1608eSlukem ;; 14596a1608eSlukem esac 14696a1608eSlukem CUR=${_new}.current 14796a1608eSlukem BACK=${_new}.backup 14896a1608eSlukem if [ -f $_file ]; then 14996a1608eSlukem if [ -f $CUR ] ; then 15096a1608eSlukem if [ "$_printdiff" -ne 0 ]; then 1511d79603cSjhawk diff ${diff_options} $CUR $_file > $OUTPUT 15296a1608eSlukem else 15396a1608eSlukem if ! cmp -s $CUR $_file; then 15496a1608eSlukem echo "[changes omitted]" 15596a1608eSlukem fi > $OUTPUT 15696a1608eSlukem fi 15796a1608eSlukem if [ -s $OUTPUT ] ; then 15896a1608eSlukem printf \ 15996a1608eSlukem "\n======\n%s diffs (OLD < > NEW)\n======\n" $_file 16096a1608eSlukem cat $OUTPUT 16196a1608eSlukem backup_file update $_file $CUR $BACK 16296a1608eSlukem fi 16396a1608eSlukem else 16496a1608eSlukem printf "\n======\n%s added\n======\n" $_file 16596a1608eSlukem if [ "$_printdiff" -ne 0 ]; then 1661d79603cSjhawk diff ${diff_options} /dev/null $_file 16796a1608eSlukem else 16896a1608eSlukem echo "[changes omitted]" 16996a1608eSlukem fi 17096a1608eSlukem backup_file add $_file $CUR $BACK 17196a1608eSlukem fi 17296a1608eSlukem else 17396a1608eSlukem if [ -f $CUR ]; then 17496a1608eSlukem printf "\n======\n%s removed\n======\n" $_file 17596a1608eSlukem if [ "$_printdiff" -ne 0 ]; then 1761d79603cSjhawk diff ${diff_options} $CUR /dev/null 17796a1608eSlukem else 17896a1608eSlukem echo "[changes omitted]" 17996a1608eSlukem fi 18096a1608eSlukem backup_file remove $_file $CUR $BACK 18196a1608eSlukem fi 18296a1608eSlukem fi 18396a1608eSlukem} 18496a1608eSlukem 18596a1608eSlukem 18696a1608eSlukem# These are used several times. 18796a1608eSlukem# 188610ee5bdSlukemawk -F: '!/^\+/ { print $1 " " $3 }' $MP | sort -k2n > $MPBYUID 18990ec96dfSlukemawk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH 190610ee5bdSlukemfor file in $special_files; do 191610ee5bdSlukem [ -s $file ] && cat $file 192610ee5bdSlukemdone | mtree -CM -k all > $SPECIALSPEC || exit 1 1931c2ae9dcScgd 19496a1608eSlukem 195cba96d16Sriastradh# Check for enough entropy. 196cba96d16Sriastradh# 197cba96d16Sriastradhif checkyesno check_entropy; then 1981095510aSmartin if [ "$(sysctl -n kern.entropy.needed)" != 0 ]; then 199cba96d16Sriastradh printf '\n' 200cba96d16Sriastradh printf 'Entropy:\n' 201cba96d16Sriastradh printf 'System may need more entropy for cryptography.\n' 202cba96d16Sriastradh printf 'See the entropy(7) man page for details.\n' 203cba96d16Sriastradh fi 204cba96d16Sriastradhfi 205cba96d16Sriastradh 206cba96d16Sriastradh 20791778fe0Scgd# Check the master password file syntax. 2083a3b03bdSlukem# 2098f59ce8eSlukemif checkyesno check_passwd; then 210ea872628Sjhawk # XXX: the sense of permit_star is reversed; the code works as 211ea872628Sjhawk # implemented, but usage needs to be negated. 2121a4c8c02Sjhawk checkyesno check_passwd_permit_star && permit_star=0 || permit_star=1 2138e401e6cSjdolecek checkyesno check_passwd_permit_nonalpha \ 2148e401e6cSjdolecek && permit_nonalpha=1 || permit_nonalpha=0 2158e401e6cSjdolecek 2161a4c8c02Sjhawk awk -v "len=$max_loginlen" \ 2171a4c8c02Sjhawk -v "nowarn_shells_list=$check_passwd_nowarn_shells" \ 2181a4c8c02Sjhawk -v "nowarn_users_list=$check_passwd_nowarn_users" \ 2198e401e6cSjdolecek -v "permit_star=$permit_star" \ 2208e401e6cSjdolecek -v "permit_nonalpha=$permit_nonalpha" \ 2218e401e6cSjdolecek ' 222fb34424eSlukem BEGIN { 223fb34424eSlukem while ( getline < "/etc/shells" > 0 ) { 2248b10c79fShubertf if ($0 ~ /^\#/ || $0 ~ /^$/ ) 225fb34424eSlukem continue; 226fb34424eSlukem shells[$1]++; 227fb34424eSlukem } 2281a4c8c02Sjhawk split(nowarn_shells_list, a); 2291a4c8c02Sjhawk for (i in a) nowarn_shells[a[i]]++; 2301a4c8c02Sjhawk split(nowarn_users_list, a); 2311a4c8c02Sjhawk for (i in a) nowarn_users[a[i]]++; 2321a4c8c02Sjhawk uid0_users_list="root toor" 2331a4c8c02Sjhawk split(uid0_users_list, a); 2341a4c8c02Sjhawk for (i in a) uid0_users[a[i]]++; 235fb34424eSlukem FS=":"; 236fb34424eSlukem } 237fb34424eSlukem 238fb34424eSlukem { 23991778fe0Scgd if ($0 ~ /^[ ]*$/) { 240fb34424eSlukem printf "Line %d is a blank line.\n", NR; 24191778fe0Scgd next; 24291778fe0Scgd } 243d08cb6cfSdholland 244d08cb6cfSdholland # NIS compat entry? 245d08cb6cfSdholland compatline = $1 ~ "^[\\+-]"; 246d08cb6cfSdholland if (compatline) { 247d08cb6cfSdholland if ($1 == "+" && NF == 1) { 248d08cb6cfSdholland next; 249d08cb6cfSdholland } 250d08cb6cfSdholland sub("^.", "", $1); 251d08cb6cfSdholland } 252d08cb6cfSdholland if (NF != 10) 253fb34424eSlukem printf "Line %d has the wrong number of fields.\n", NR; 254d08cb6cfSdholland if (compatline) { 255d08cb6cfSdholland if ($3 == 0) 2561a4c8c02Sjhawk printf "Line %d includes entries with uid 0.\n", 2571a4c8c02Sjhawk NR; 258d08cb6cfSdholland if ($1 == "") 259dade5b29Sabs next; 260dade5b29Sabs } 2618e401e6cSjdolecek if (!permit_nonalpha && 262271ad04cSpeter $1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) 263fb34424eSlukem printf "Login %s has non-alphanumeric characters.\n", 264fb34424eSlukem $1; 265dade5b29Sabs if (length($1) > len) 2661a4c8c02Sjhawk printf "Login %s has more than "len" characters.\n", 2671a4c8c02Sjhawk $1; 268d08cb6cfSdholland if ($2 == "" && !compatline && !nowarn_users[$1]) 269fb34424eSlukem printf "Login %s has no password.\n", $1; 2701a4c8c02Sjhawk if (!nowarn_shells[$10] && !nowarn_users[$1]) { 271247041e3Sperry if (length($2) != 13 && 272247041e3Sperry length($2) != 20 && 27374377e4aSitojun $2 !~ /^\$1/ && 27474377e4aSitojun $2 !~ /^\$2/ && 27564b4f9dcSjmcneill $2 !~ /^\$sha1/ && 2768e79eccaSnia $2 !~ /^\$argon2(i|d|id)/ && 277247041e3Sperry $2 != "" && 2781a4c8c02Sjhawk (permit_star || $2 != "*") && 279247041e3Sperry $2 !~ /^\*[A-z-]+$/ && 280247041e3Sperry $1 != "toor") { 281fb34424eSlukem if ($10 == "" || shells[$10]) 2821a4c8c02Sjhawk printf "Login %s is off but still has "\ 2831a4c8c02Sjhawk "a valid shell (%s)\n", $1, $10; 284d08cb6cfSdholland } else if (compatline && $10 == "") { 285d08cb6cfSdholland # nothing 286fb34424eSlukem } else if (! shells[$10]) 2871a4c8c02Sjhawk printf "Login %s does not have a valid "\ 2881a4c8c02Sjhawk "shell (%s)\n", $1, $10; 2891a4c8c02Sjhawk } 2901a4c8c02Sjhawk if ($3 == 0 && !uid0_users[$1] && !nowarn_users[$1]) 291fb34424eSlukem printf "Login %s has a user id of 0.\n", $1; 292d08cb6cfSdholland if ($3 != "" && $3 < 0) 293fb34424eSlukem printf "Login %s has a negative user id.\n", $1; 294d08cb6cfSdholland if ($4 != "" && $4 < 0) 295fb34424eSlukem printf "Login %s has a negative group id.\n", $1; 29691778fe0Scgd }' < $MP > $OUTPUT 29791778fe0Scgd if [ -s $OUTPUT ] ; then 29891778fe0Scgd printf "\nChecking the $MP file:\n" 29991778fe0Scgd cat $OUTPUT 30061f28255Scgd fi 30161f28255Scgd 30291778fe0Scgd awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT 30391778fe0Scgd if [ -s $OUTPUT ] ; then 30491778fe0Scgd printf "\n$MP has duplicate user names.\n" 30591778fe0Scgd column $OUTPUT 30691778fe0Scgd fi 30791778fe0Scgd 308c6302b74Sspz awk -v "permit_dups_list=$check_passwd_permit_dups" \ 309c6302b74Sspz ' 310c6302b74Sspz BEGIN { 311c6302b74Sspz split(permit_dups_list, a); 312c6302b74Sspz for (i in a) permit_dups[a[i]]++; 313c6302b74Sspz } 314c6302b74Sspz { 315c6302b74Sspz if (!permit_dups[$1]) 316c6302b74Sspz print $2; 317c6302b74Sspz }' < $MPBYUID | uniq -d > $TMP2 31891778fe0Scgd if [ -s $TMP2 ] ; then 319c6302b74Sspz printf "\n$MP has duplicate user ids.\n" 32091778fe0Scgd while read uid; do 321f09b5e36Slukem grep -w $uid $MPBYUID 32291778fe0Scgd done < $TMP2 | column 32391778fe0Scgd fi 324a9efb638Smrgfi 32591778fe0Scgd 32691778fe0Scgd# Check the group file syntax. 3273a3b03bdSlukem# 3288f59ce8eSlukemif checkyesno check_group; then 32991778fe0Scgd GRP=/etc/group 3304ceebb11Sjdolecek awk -F: -v "len=$max_grouplen" '{ 33191778fe0Scgd if ($0 ~ /^[ ]*$/) { 332fb34424eSlukem printf "Line %d is a blank line.\n", NR; 33391778fe0Scgd next; 33491778fe0Scgd } 335dade5b29Sabs if (NF != 4 && ($1 != "+" || NF != 1)) 336fb34424eSlukem printf "Line %d has the wrong number of fields.\n", NR; 337dade5b29Sabs if ($1 == "+" ) { 338dade5b29Sabs next; 339dade5b29Sabs } 340271ad04cSpeter if ($1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) 341fb34424eSlukem printf "Group %s has non-alphanumeric characters.\n", 342fb34424eSlukem $1; 3434ceebb11Sjdolecek if (length($1) > len) 3444ceebb11Sjdolecek printf "Group %s has more than "len" characters.\n", $1; 34591778fe0Scgd if ($3 !~ /[0-9]*/) 346fb34424eSlukem printf "Login %s has a negative group id.\n", $1; 34791778fe0Scgd }' < $GRP > $OUTPUT 34891778fe0Scgd if [ -s $OUTPUT ] ; then 34991778fe0Scgd printf "\nChecking the $GRP file:\n" 35091778fe0Scgd cat $OUTPUT 35191778fe0Scgd fi 35291778fe0Scgd 35391778fe0Scgd awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT 3540d7af235Sspz dupgroups="" 3550d7af235Sspz for group in $(cat $OUTPUT) ; do 3568ce568ceSapb gcount=$(awk -F: "/$group/ { print \$1,\$3 }" $GRP | 3578ce568ceSapb sort -u | wc -l) 3580d7af235Sspz if [ $gcount -gt 1 ]; then 3590d7af235Sspz dupgroups="$dupgroups $group" 3600d7af235Sspz fi 3610d7af235Sspz done 362*b2f03d66She if [ ! -z "$dupgroups" ] ; then 36391778fe0Scgd printf "\n$GRP has duplicate group names.\n" 3640d7af235Sspz printf "$dupgroups\n" 36591778fe0Scgd fi 366a9efb638Smrgfi 36791778fe0Scgd 36891778fe0Scgd# Check for root paths, umask values in startup files. 36991778fe0Scgd# The check for the root paths is problematical -- it's likely to fail 37091778fe0Scgd# in other environments. Once the shells have been modified to warn 37191778fe0Scgd# of '.' in the path, the path tests should go away. 3723a3b03bdSlukem# 3738f59ce8eSlukemif checkyesno check_rootdotfiles; then 37496a1608eSlukem rhome=~root 37591778fe0Scgd umaskset=no 37691778fe0Scgd list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login" 37791778fe0Scgd for i in $list ; do 37891778fe0Scgd if [ -f $i ] ; then 37996a1608eSlukem if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ; 38096a1608eSlukem then 38191778fe0Scgd umaskset=yes 38291778fe0Scgd fi 383f263bbb1Slukem # Double check the umask value itself; ensure that 38496a1608eSlukem # both the group and other write bits are set. 38596a1608eSlukem # 3869928e1feSsommerfeld egrep '^[ \t]*umask[ \t]+[0-7]+' $i | 387f263bbb1Slukem awk '{ 38896a1608eSlukem if ($2 ~ /^.$/ || $2 ~! /[^2367].$/) { 3891035faffSwiz print "\tRoot umask is group writable" 390f263bbb1Slukem } 39196a1608eSlukem if ($2 ~ /[^2367]$/) { 3921035faffSwiz print "\tRoot umask is other writable" 393f263bbb1Slukem } 39496a1608eSlukem }' | sort -u 3950f26a045Slukem SAVE_PATH=$PATH 3960f26a045Slukem unset PATH 39791778fe0Scgd /bin/csh -f -s << end-of-csh > /dev/null 2>&1 39891778fe0Scgd source $i 39991778fe0Scgd /bin/ls -ldgT \$path > $TMP1 40091778fe0Scgdend-of-csh 401bc451d09Satatat export PATH=$SAVE_PATH 40291778fe0Scgd awk '{ 40391778fe0Scgd if ($10 ~ /^\.$/) { 40489fa41e9Slukem print "\tThe root path includes ."; 40591778fe0Scgd next; 40691778fe0Scgd } 40791778fe0Scgd } 40891778fe0Scgd $1 ~ /^d....w/ \ 4091035faffSwiz { print "\tRoot path directory " $10 " is group writable." } \ 41091778fe0Scgd $1 ~ /^d.......w/ \ 4111035faffSwiz { print "\tRoot path directory " $10 " is other writable." }' \ 41296a1608eSlukem < $TMP1 41391778fe0Scgd fi 41496a1608eSlukem done > $OUTPUT 415d65b3b7aSkre if [ $umaskset = no ] || [ -s $OUTPUT ] ; then 41689fa41e9Slukem printf "\nChecking root csh paths, umask values:\n$list\n\n" 41791778fe0Scgd if [ -s $OUTPUT ]; then 41891778fe0Scgd cat $OUTPUT 41991778fe0Scgd fi 4209ae2b31fSkre if [ $umaskset = no ] ; then 42189fa41e9Slukem printf "\tRoot csh startup files do not set the umask.\n" 42291778fe0Scgd fi 42391778fe0Scgd fi 42491778fe0Scgd 42591778fe0Scgd umaskset=no 426d0b6172bSlukem list="/etc/profile ${rhome}/.profile" 42791778fe0Scgd for i in $list; do 42891778fe0Scgd if [ -f $i ] ; then 42991778fe0Scgd if egrep umask $i > /dev/null ; then 43091778fe0Scgd umaskset=yes 43191778fe0Scgd fi 43291778fe0Scgd egrep umask $i | 43396a1608eSlukem awk '$2 ~ /^.$/ || $2 ~ /[^2367].$/ \ 4341035faffSwiz { print "\tRoot umask is group writable" } \ 43596a1608eSlukem $2 ~ /[^2367]$/ \ 4361035faffSwiz { print "\tRoot umask is other writable" }' 4370f26a045Slukem SAVE_PATH=$PATH 4380f26a045Slukem unset PATH 43991778fe0Scgd /bin/sh << end-of-sh > /dev/null 2>&1 44091778fe0Scgd . $i 4416f0af47aSchristos list=\$(echo \$PATH | /usr/bin/sed -e \ 4426f0af47aSchristos 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g') 44391778fe0Scgd /bin/ls -ldgT \$list > $TMP1 44491778fe0Scgdend-of-sh 445bc451d09Satatat export PATH=$SAVE_PATH 44691778fe0Scgd awk '{ 44791778fe0Scgd if ($10 ~ /^\.$/) { 44889fa41e9Slukem print "\tThe root path includes ."; 44991778fe0Scgd next; 45091778fe0Scgd } 45191778fe0Scgd } 45291778fe0Scgd $1 ~ /^d....w/ \ 4531035faffSwiz { print "\tRoot path directory " $10 " is group writable." } \ 45491778fe0Scgd $1 ~ /^d.......w/ \ 4551035faffSwiz { print "\tRoot path directory " $10 " is other writable." }' \ 45696a1608eSlukem < $TMP1 45791778fe0Scgd 45891778fe0Scgd fi 45996a1608eSlukem done > $OUTPUT 4609ae2b31fSkre if [ $umaskset = no ] || [ -s $OUTPUT ] ; then 46191778fe0Scgd printf "\nChecking root sh paths, umask values:\n$list\n" 46291778fe0Scgd if [ -s $OUTPUT ]; then 46391778fe0Scgd cat $OUTPUT 46491778fe0Scgd fi 4659ae2b31fSkre if [ $umaskset = no ] ; then 46689fa41e9Slukem printf "\tRoot sh startup files do not set the umask.\n" 46791778fe0Scgd fi 46891778fe0Scgd fi 469a9efb638Smrgfi 47091778fe0Scgd 47191778fe0Scgd# Root and uucp should both be in /etc/ftpusers. 4723a3b03bdSlukem# 4738f59ce8eSlukemif checkyesno check_ftpusers; then 4744f848eeeSchristos list="uucp "$(awk '$2 == 0 { print $1 }' $MPBYUID) 47589fa41e9Slukem for i in $list; do 47690ec96dfSlukem if /usr/libexec/ftpd -C $i ; then 47796a1608eSlukem printf "\t$i is not denied\n" 47891778fe0Scgd fi 47996a1608eSlukem done > $OUTPUT 480f09b5e36Slukem if [ -s $OUTPUT ]; then 481f09b5e36Slukem printf "\nChecking the /etc/ftpusers configuration:\n" 482f09b5e36Slukem cat $OUTPUT 483f09b5e36Slukem fi 484a9efb638Smrgfi 48591778fe0Scgd 48613c8f7a2Sitojun# Uudecode should not be in the /etc/mail/aliases file. 4873a3b03bdSlukem# 4888f59ce8eSlukemif checkyesno check_aliases; then 48913c8f7a2Sitojun for f in /etc/mail/aliases /etc/aliases; do 49013c8f7a2Sitojun if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then 49113c8f7a2Sitojun printf "\nEntry for uudecode in $f file.\n" 49291778fe0Scgd fi 49313c8f7a2Sitojun done 494a9efb638Smrgfi 49591778fe0Scgd 49691778fe0Scgd# Files that should not have + signs. 4973a3b03bdSlukem# 4988f59ce8eSlukemif checkyesno check_rhosts; then 49991778fe0Scgd list="/etc/hosts.equiv /etc/hosts.lpd" 50091778fe0Scgd for f in $list ; do 5011377ee09Spk if [ -f $f ] && egrep '\+' $f > /dev/null ; then 50291778fe0Scgd printf "\nPlus sign in $f file.\n" 50391778fe0Scgd fi 50491778fe0Scgd done 50591778fe0Scgd 50691778fe0Scgd # Check for special users with .rhosts files. Only root and toor should 5075b5eddafSmikel # have .rhosts files. Also, .rhosts files should not have plus signs. 50891778fe0Scgd awk -F: '$1 != "root" && $1 != "toor" && \ 50991778fe0Scgd ($3 < 100 || $1 == "ftp" || $1 == "uucp") \ 510df1a64b9Smycroft { print $1 " " $9 }' $MP | 5114a0848acSmycroft sort -k2 | 51291778fe0Scgd while read uid homedir; do 51391778fe0Scgd if [ -f ${homedir}/.rhosts ] ; then 5144f848eeeSchristos rhost=$(ls -ldgT ${homedir}/.rhosts) 515b4266bbcSchristos printf -- "$uid: $rhost\n" 51691778fe0Scgd fi 51791778fe0Scgd done > $OUTPUT 51891778fe0Scgd if [ -s $OUTPUT ] ; then 51991778fe0Scgd printf "\nChecking for special users with .rhosts files.\n" 52091778fe0Scgd cat $OUTPUT 52191778fe0Scgd fi 52291778fe0Scgd 52391778fe0Scgd while read uid homedir; do 5249ae2b31fSkre if [ -f ${homedir}/.rhosts ] && 5259ae2b31fSkre [ -r ${homedir}/.rhosts ] && 5269ae2b31fSkre cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null 5279ae2b31fSkre then 528b4266bbcSchristos printf -- "$uid: + in .rhosts file.\n" 52991778fe0Scgd fi 53090ec96dfSlukem done < $MPBYPATH > $OUTPUT 53191778fe0Scgd if [ -s $OUTPUT ] ; then 53291778fe0Scgd printf "\nChecking .rhosts files syntax.\n" 53391778fe0Scgd cat $OUTPUT 53491778fe0Scgd fi 535a9efb638Smrgfi 53691778fe0Scgd 53791778fe0Scgd# Check home directories. Directories should not be owned by someone else 5381035faffSwiz# or writable. 5393a3b03bdSlukem# 5408f59ce8eSlukemif checkyesno check_homes; then 541ea872628Sjhawk checkyesno check_homes_permit_usergroups && \ 542ea872628Sjhawk permit_usergroups=1 || permit_usergroups=0 54391778fe0Scgd while read uid homedir; do 54491778fe0Scgd if [ -d ${homedir}/ ] ; then 5454f848eeeSchristos file=$(ls -ldgT ${homedir}) 546b4266bbcSchristos printf -- "$uid $file\n" 54791778fe0Scgd fi 54890ec96dfSlukem done < $MPBYPATH | 549acaf72ecSspz awk -v "usergroups=$permit_usergroups" \ 550acaf72ecSspz -v "permit_owners_list=$check_homes_permit_other_owner" ' 551acaf72ecSspz BEGIN { 552acaf72ecSspz split(permit_owners_list, a); 553acaf72ecSspz for (i in a) permit_owners[a[i]]++; 554acaf72ecSspz } 555acaf72ecSspz $1 != $4 && $4 != "root" && !permit_owners[$1] \ 55691778fe0Scgd { print "user " $1 " home directory is owned by " $4 } 557f2e95068Sjnemeth $2 ~ /^d....w/ && (!usergroups || $5 != $1) \ 5581035faffSwiz { print "user " $1 " home directory is group writable" } 559f2e95068Sjnemeth $2 ~ /^d.......w/ \ 5601035faffSwiz { print "user " $1 " home directory is other writable" }' \ 56189fa41e9Slukem > $OUTPUT 56291778fe0Scgd if [ -s $OUTPUT ] ; then 56391778fe0Scgd printf "\nChecking home directories.\n" 56491778fe0Scgd cat $OUTPUT 56591778fe0Scgd fi 56691778fe0Scgd 56791778fe0Scgd # Files that should not be owned by someone else or readable. 56896a1608eSlukem list=".Xauthority .netrc .ssh/id_dsa .ssh/id_rsa .ssh/identity" 56991778fe0Scgd while read uid homedir; do 57091778fe0Scgd for f in $list ; do 57191778fe0Scgd file=${homedir}/${f} 57291778fe0Scgd if [ -f $file ] ; then 5734f848eeeSchristos printf -- "$uid $f $(ls -ldgT $file)\n" 57491778fe0Scgd fi 57591778fe0Scgd done 57690ec96dfSlukem done < $MPBYPATH | 577acaf72ecSspz awk -v "usergroups=$permit_usergroups" \ 578acaf72ecSspz -v "permit_owners_list=$check_homes_permit_other_owner" ' 579acaf72ecSspz BEGIN { 580acaf72ecSspz split(permit_owners_list, a); 581acaf72ecSspz for (i in a) permit_owners[a[i]]++; 582acaf72ecSspz } 583acaf72ecSspz $1 != $5 && $5 != "root" && !permit_owners[$1] \ 58491778fe0Scgd { print "user " $1 " " $2 " file is owned by " $5 } 585ea872628Sjhawk $3 ~ /^-...r/ && (!usergroups || $6 != $1) \ 58691778fe0Scgd { print "user " $1 " " $2 " file is group readable" } 58791778fe0Scgd $3 ~ /^-......r/ \ 58891778fe0Scgd { print "user " $1 " " $2 " file is other readable" } 589ea872628Sjhawk $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ 5901035faffSwiz { print "user " $1 " " $2 " file is group writable" } 59191778fe0Scgd $3 ~ /^-.......w/ \ 5921035faffSwiz { print "user " $1 " " $2 " file is other writable" }' \ 59389fa41e9Slukem > $OUTPUT 59491778fe0Scgd 5951035faffSwiz # Files that should not be owned by someone else or writable. 5964a0848acSmycroft list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \ 5978efcaddaSelric .cshrc .emacs .exrc .forward .history .k5login .klogin .login \ 5988efcaddaSelric .logout .profile .qmail .rc_history .rhosts .shosts ssh .tcshrc \ 5998efcaddaSelric .twmrc .xinitrc .xsession .ssh/authorized_keys \ 6008efcaddaSelric .ssh/authorized_keys2 .ssh/config .ssh/id_dsa.pub \ 6018efcaddaSelric .ssh/id_rsa.pub .ssh/identity.pub .ssh/known_hosts \ 6028efcaddaSelric .ssh/known_hosts2" 60391778fe0Scgd while read uid homedir; do 60491778fe0Scgd for f in $list ; do 60591778fe0Scgd file=${homedir}/${f} 60691778fe0Scgd if [ -f $file ] ; then 6074f848eeeSchristos printf -- "$uid $f $(ls -ldgT $file)\n" 60891778fe0Scgd fi 60991778fe0Scgd done 61090ec96dfSlukem done < $MPBYPATH | 611acaf72ecSspz awk -v "usergroups=$permit_usergroups" \ 612acaf72ecSspz -v "permit_owners_list=$check_homes_permit_other_owner" ' 613acaf72ecSspz BEGIN { 614acaf72ecSspz split(permit_owners_list, a); 615acaf72ecSspz for (i in a) permit_owners[a[i]]++; 616acaf72ecSspz } 617acaf72ecSspz $1 != $5 && $5 != "root" && !permit_owners[$1] \ 61891778fe0Scgd { print "user " $1 " " $2 " file is owned by " $5 } 619ea872628Sjhawk $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ 6201035faffSwiz { print "user " $1 " " $2 " file is group writable" } 62191778fe0Scgd $3 ~ /^-.......w/ \ 6221035faffSwiz { print "user " $1 " " $2 " file is other writable" }' \ 62389fa41e9Slukem >> $OUTPUT 62491778fe0Scgd if [ -s $OUTPUT ] ; then 62591778fe0Scgd printf "\nChecking dot files.\n" 62691778fe0Scgd cat $OUTPUT 62791778fe0Scgd fi 628a9efb638Smrgfi 62991778fe0Scgd 63091778fe0Scgd# Mailboxes should be owned by user and unreadable. 6313a3b03bdSlukem# 6328f59ce8eSlukemif checkyesno check_varmail; then 63334604558Sjhawk ls -lA /var/mail | \ 634f263bbb1Slukem awk ' NR == 1 { next; } 63534604558Sjhawk $9 ~ /^\./ {next; } 636f263bbb1Slukem $3 != $9 { 637f263bbb1Slukem print "user " $9 " mailbox is owned by " $3 638f263bbb1Slukem } 639f263bbb1Slukem $1 != "-rw-------" { 640f263bbb1Slukem print "user " $9 " mailbox is " $1 ", group " $4 641f263bbb1Slukem }' > $OUTPUT 64291778fe0Scgd if [ -s $OUTPUT ] ; then 64391778fe0Scgd printf "\nChecking mailbox ownership.\n" 64491778fe0Scgd cat $OUTPUT 64591778fe0Scgd fi 646a9efb638Smrgfi 64791778fe0Scgd 6483a3b03bdSlukem# NFS exports shouldn't be globally exported 6493a3b03bdSlukem# 6503a3b03bdSlukemif checkyesno check_nfs && [ -f /etc/exports ]; then 65191778fe0Scgd awk '{ 652b07aea8eSlukem # ignore comments and blank lines 6538b10c79fShubertf if ($0 ~ /^\#/ || $0 ~ /^$/ ) 654b07aea8eSlukem next; 655820a3576Stron # manage line continuation 656820a3576Stron while ($NF ~ /^\\$/) { 657820a3576Stron $NF = ""; 658820a3576Stron line = $0 ""; 659820a3576Stron getline; 660820a3576Stron $0 = line $0 ""; 661820a3576Stron } 662b07aea8eSlukem 663820a3576Stron delete dir; 664820a3576Stron readonly = ndir = 0; 665820a3576Stron for (i = 1; i <= NF; ++i) { 666820a3576Stron if ($i ~ /^\//) dir[ndir++] = $i; 667820a3576Stron else if ($i ~ /^-/) { 668820a3576Stron if ($i ~ /^-(ro|o)$/) readonly = 1; 669820a3576Stron if ($i ~ /^-network/) next; 670820a3576Stron } 671820a3576Stron else next; 67291778fe0Scgd } 67391778fe0Scgd if (readonly) 674820a3576Stron for (item in dir) 675820a3576Stron rodir[nrodir++] = dir[item]; 67691778fe0Scgd else 677820a3576Stron for (item in dir) 678820a3576Stron rwdir[nrwdir++] = dir[item]; 679820a3576Stron 680820a3576Stron } 681820a3576Stron 682820a3576Stron END { 683820a3576Stron if (nrodir) { 684820a3576Stron printf("Globally exported file system%s, read-only:\n", 685820a3576Stron nrodir > 1 ? "s" : ""); 686820a3576Stron for (item in rodir) 687820a3576Stron printf("\t%s\n", rodir[item]); 688820a3576Stron } 689820a3576Stron if (nrwdir) { 690820a3576Stron printf("Globally exported file system%s, read-write:\n", 691820a3576Stron nrwdir > 1 ? "s" : ""); 692820a3576Stron for (item in rwdir) 693820a3576Stron printf("\t%s\n", rwdir[item]); 694820a3576Stron } 69591778fe0Scgd }' < /etc/exports > $OUTPUT 69691778fe0Scgd if [ -s $OUTPUT ] ; then 69791778fe0Scgd printf "\nChecking for globally exported file systems.\n" 69891778fe0Scgd cat $OUTPUT 69991778fe0Scgd fi 7001377ee09Spkfi 70191778fe0Scgd 70291778fe0Scgd# Display any changes in setuid files and devices. 7033a3b03bdSlukem# 7048f59ce8eSlukemif checkyesno check_devices; then 705f09b5e36Slukem > $ERR 7067da8bb10Serh ( 7076d23caf2Slukem 7086d23caf2Slukem # Convert check_devices_ignore_fstypes="foo !bar bax" 7096d23caf2Slukem # into "-fstype foo -o ! -fstype bar -o -fstype bax" 7106d23caf2Slukem # and check_devices_ignore_paths="/foo !/bar /bax" 7116d23caf2Slukem # into " -path /foo -o ! -path /bar -o -path /bax" 7126d23caf2Slukem # 7136d23caf2Slukem ignexpr=$(\ 7146d23caf2Slukem echo $check_devices_ignore_fstypes | \ 7156d23caf2Slukem sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -fstype \2/g' ; \ 7166d23caf2Slukem echo $check_devices_ignore_paths | \ 7176d23caf2Slukem sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -path \2/g' \ 7186d23caf2Slukem ) 7196d23caf2Slukem 7206d23caf2Slukem # Massage the expression into ( $ignexpr ) -a -prune -o 7216d23caf2Slukem if [ -n "${ignexpr}" ]; then 7226d23caf2Slukem ignexpr=$(\ 7236d23caf2Slukem echo $ignexpr | \ 7246d23caf2Slukem sed -e 's/^-o /( /' \ 7256d23caf2Slukem -e 's/$/ ) -a -prune -o/' \ 7266d23caf2Slukem ) 7276d23caf2Slukem fi 7286d23caf2Slukem 7296d23caf2Slukem find / $ignexpr \ 730d8dcc658Smycroft \( \( -perm -u+s -a ! -type d \) -o \ 731d8dcc658Smycroft \( -perm -g+s -a ! -type d \) -o \ 732ff2ea5d1Slukem -type b -o -type c \) -print0 | \ 7336d23caf2Slukem xargs -0 ls -ldgTq | sort +9 > $LIST 7346d23caf2Slukem 7356d23caf2Slukem ) 2> $OUTPUT 73691778fe0Scgd 73791778fe0Scgd # Display any errors that occurred during system file walk. 73891778fe0Scgd if [ -s $OUTPUT ] ; then 739f09b5e36Slukem printf "Setuid/device find errors:\n" >> $ERR 740f09b5e36Slukem cat $OUTPUT >> $ERR 741f09b5e36Slukem printf "\n" >> $ERR 74291778fe0Scgd fi 74391778fe0Scgd 74491778fe0Scgd # Display any changes in the setuid file list. 74591778fe0Scgd egrep -v '^[bc]' $LIST > $TMP1 74691778fe0Scgd if [ -s $TMP1 ] ; then 74791778fe0Scgd # Check to make sure uudecode isn't setuid. 74891778fe0Scgd if grep -w uudecode $TMP1 > /dev/null ; then 749f09b5e36Slukem printf "\nUudecode is setuid.\n" >> $ERR 75091778fe0Scgd fi 75191778fe0Scgd 75296a1608eSlukem file=$work_dir/setuid 75396a1608eSlukem migrate_file "$backup_dir/setuid" "$file" 75496a1608eSlukem CUR=${file}.current 75596a1608eSlukem BACK=${file}.backup 75691778fe0Scgd if [ -s $CUR ] ; then 75791778fe0Scgd if cmp -s $CUR $TMP1 ; then 75891778fe0Scgd : 75991778fe0Scgd else 76091778fe0Scgd > $TMP2 76191778fe0Scgd join -110 -210 -v2 $CUR $TMP1 > $OUTPUT 76291778fe0Scgd if [ -s $OUTPUT ] ; then 763f09b5e36Slukem printf "Setuid additions:\n" >> $ERR 764f09b5e36Slukem tee -a $TMP2 < $OUTPUT >> $ERR 765f09b5e36Slukem printf "\n" >> $ERR 76691778fe0Scgd fi 76791778fe0Scgd 76891778fe0Scgd join -110 -210 -v1 $CUR $TMP1 > $OUTPUT 76991778fe0Scgd if [ -s $OUTPUT ] ; then 770f09b5e36Slukem printf "Setuid deletions:\n" >> $ERR 771f09b5e36Slukem tee -a $TMP2 < $OUTPUT >> $ERR 772f09b5e36Slukem printf "\n" >> $ERR 77391778fe0Scgd fi 77491778fe0Scgd 775df1a64b9Smycroft sort -k10 $TMP2 $CUR $TMP1 | \ 77689fa41e9Slukem sed -e 's/[ ][ ]*/ /g' | \ 77789fa41e9Slukem uniq -u > $OUTPUT 77891778fe0Scgd if [ -s $OUTPUT ] ; then 779f09b5e36Slukem printf "Setuid changes:\n" >> $ERR 780f09b5e36Slukem column -t $OUTPUT >> $ERR 781f09b5e36Slukem printf "\n" >> $ERR 78291778fe0Scgd fi 78391778fe0Scgd 7842811b170Satatat backup_file update $TMP1 $CUR $BACK 78591778fe0Scgd fi 78691778fe0Scgd else 787f09b5e36Slukem printf "Setuid additions:\n" >> $ERR 788f09b5e36Slukem column -t $TMP1 >> $ERR 789f09b5e36Slukem printf "\n" >> $ERR 7902811b170Satatat backup_file add $TMP1 $CUR $BACK 79191778fe0Scgd fi 79291778fe0Scgd fi 79391778fe0Scgd 79489fa41e9Slukem # Check for block and character disk devices that are readable or 7951035faffSwiz # writable or not owned by root.operator. 79691778fe0Scgd >$TMP1 7975a212acfSlukem DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \ 798e60403a3Ssimonb sd se ss uk up vnd wd xd xy" 79989fa41e9Slukem# DISKLIST="$DISKLIST ct mt st wt" 80091778fe0Scgd for i in $DISKLIST; do 801a9efb638Smrg egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 802a9efb638Smrg egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 80391778fe0Scgd done 80491778fe0Scgd 80591778fe0Scgd awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \ 806fb34424eSlukem { printf "Disk %s is user %s, group %s, permissions %s.\n", \ 807fb34424eSlukem $11, $3, $4, $1; }' < $TMP1 > $OUTPUT 80891778fe0Scgd if [ -s $OUTPUT ] ; then 809f09b5e36Slukem printf "\nChecking disk ownership and permissions.\n" >> $ERR 810f09b5e36Slukem cat $OUTPUT >> $ERR 811f09b5e36Slukem printf "\n" >> $ERR 81291778fe0Scgd fi 81391778fe0Scgd 81491778fe0Scgd # Display any changes in the device file list. 815df1a64b9Smycroft egrep '^[bc]' $LIST | sort -k11 > $TMP1 81691778fe0Scgd if [ -s $TMP1 ] ; then 81796a1608eSlukem file=$work_dir/device 81896a1608eSlukem migrate_file "$backup_dir/device" "$file" 81996a1608eSlukem CUR=${file}.current 82096a1608eSlukem BACK=${file}.backup 82191778fe0Scgd 82291778fe0Scgd if [ -s $CUR ] ; then 82391778fe0Scgd if cmp -s $CUR $TMP1 ; then 82491778fe0Scgd : 82591778fe0Scgd else 82691778fe0Scgd > $TMP2 82791778fe0Scgd join -111 -211 -v2 $CUR $TMP1 > $OUTPUT 82891778fe0Scgd if [ -s $OUTPUT ] ; then 829f09b5e36Slukem printf "Device additions:\n" >> $ERR 830f09b5e36Slukem tee -a $TMP2 < $OUTPUT >> $ERR 831f09b5e36Slukem printf "\n" >> $ERR 83291778fe0Scgd fi 83391778fe0Scgd 83491778fe0Scgd join -111 -211 -v1 $CUR $TMP1 > $OUTPUT 83591778fe0Scgd if [ -s $OUTPUT ] ; then 836f09b5e36Slukem printf "Device deletions:\n" >> $ERR 837f09b5e36Slukem tee -a $TMP2 < $OUTPUT >> $ERR 838f09b5e36Slukem printf "\n" >> $ERR 83991778fe0Scgd fi 84091778fe0Scgd 84189fa41e9Slukem # Report any block device change. Ignore 84289fa41e9Slukem # character devices, only the name is 84389fa41e9Slukem # significant. 84491778fe0Scgd cat $TMP2 $CUR $TMP1 | \ 84591778fe0Scgd sed -e '/^c/d' | \ 846df1a64b9Smycroft sort -k11 | \ 84791778fe0Scgd sed -e 's/[ ][ ]*/ /g' | \ 84891778fe0Scgd uniq -u > $OUTPUT 84991778fe0Scgd if [ -s $OUTPUT ] ; then 850f09b5e36Slukem printf "Block device changes:\n" >> $ERR 851f09b5e36Slukem column -t $OUTPUT >> $ERR 852f09b5e36Slukem printf "\n" >> $ERR 85391778fe0Scgd fi 85491778fe0Scgd 8552811b170Satatat backup_file update $TMP1 $CUR $BACK 85691778fe0Scgd fi 85791778fe0Scgd else 858f09b5e36Slukem printf "Device additions:\n" >> $ERR 859f09b5e36Slukem column -t $TMP1 >> $ERR 860f09b5e36Slukem printf "\n" >> $ERR 8612811b170Satatat backup_file add $TMP1 $CUR $BACK >> $ERR 86291778fe0Scgd fi 86391778fe0Scgd fi 864f09b5e36Slukem if [ -s $ERR ] ; then 865f09b5e36Slukem printf "\nChecking setuid files and devices:\n" 866f09b5e36Slukem cat $ERR 867f09b5e36Slukem printf "\n" 868f09b5e36Slukem fi 869a9efb638Smrgfi 87091778fe0Scgd 87191778fe0Scgd# Check special files. 87291778fe0Scgd# Check system binaries. 87391778fe0Scgd# 87491778fe0Scgd# Create the mtree tree specifications using: 87596a1608eSlukem# mtree -cx -pDIR -kmd5,uid,gid,mode,nlink,size,link,time > DIR.secure 876357a0baaSkleink# chown root:wheel DIR.secure 87796a1608eSlukem# chmod u+r,go= DIR.secure 87891778fe0Scgd# 87991778fe0Scgd# Note, this is not complete protection against Trojan horsed binaries, as 88091778fe0Scgd# the hacker can modify the tree specification to match the replaced binary. 88191778fe0Scgd# For details on really protecting yourself against modified binaries, see 88291778fe0Scgd# the mtree(8) manual page. 8833a3b03bdSlukem# 8848f59ce8eSlukemif checkyesno check_mtree; then 885687107d3Sjhawk if checkyesno check_mtree_follow_symlinks; then 886687107d3Sjhawk check_mtree_flags="-L" 887687107d3Sjhawk else 888687107d3Sjhawk check_mtree_flags="" 889687107d3Sjhawk fi 890610ee5bdSlukem mtree -e -l -p / $check_mtree_flags -f $SPECIALSPEC 3>&1 >$OUTPUT 2>&3 | 8916a6c54a1Sjhawk grep -v '^mtree: dev/tty: Device not configured$' >&2 89291778fe0Scgd if [ -s $OUTPUT ]; then 89391778fe0Scgd printf "\nChecking special files and directories.\n" 89491778fe0Scgd cat $OUTPUT 89591778fe0Scgd fi 89691778fe0Scgd 8975b5eddafSmikel for file in /etc/mtree/*.secure; do 8985b5eddafSmikel [ $file = '/etc/mtree/*.secure' ] && continue 8994f848eeeSchristos tree=$(sed -n -e '3s/.* //p' -e 3q $file) 900687107d3Sjhawk mtree $check_mtree_flags -f $file -p $tree > $TMP1 90191778fe0Scgd if [ -s $TMP1 ]; then 90296a1608eSlukem printf "\nChecking $tree:\n" 90396a1608eSlukem cat $TMP1 90491778fe0Scgd fi 90596a1608eSlukem done > $OUTPUT 90691778fe0Scgd if [ -s $OUTPUT ]; then 90791778fe0Scgd printf "\nChecking system binaries:\n" 90891778fe0Scgd cat $OUTPUT 90991778fe0Scgd fi 91091778fe0Scgdfi 91191778fe0Scgd 9123a3b03bdSlukem# Backup disklabels of available disks 9133a3b03bdSlukem# 9143a3b03bdSlukemif checkyesno check_disklabels; then 91596a1608eSlukem # migrate old disklabels 9164f848eeeSchristos for file in $(ls -1d $backup_dir/$backup_dir/disklabel.* \ 9174f848eeeSchristos $backup_dir/disklabel.* 2>/dev/null); do 91896a1608eSlukem migrate_file "$file" "$work_dir/${file##*/}" 91996a1608eSlukem done 92096a1608eSlukem 9218ce568ceSapb # generate list of old disklabels, fdisks & wedges, 9228ce568ceSapb # and remove them 9238ce568ceSapb ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ 9248ce568ceSapb 2>/dev/null | 9252811b170Satatat egrep -v '\.(backup|current)(,v)?$' > $LABELS 9263a3b03bdSlukem xargs rm < $LABELS 9273a3b03bdSlukem 9282f6dbbcfSmlelstv disks="$(/sbin/sysctl -n hw.iostatnames)" 9293c3f7bb8Schristos 9303c3f7bb8Schristos # generate disklabels of all disks excluding: cd fd md dk st 9313c3f7bb8Schristos # nfs and "device" (the header of iostat) 9323a3b03bdSlukem for i in $disks; do 9333c3f7bb8Schristos case $i in 9342f6dbbcfSmlelstv [cfm]d[0-9]*|dk[0-9]*|st[0-9]*|nfs[0-9]*) 9353c3f7bb8Schristos ;; 9363c3f7bb8Schristos *) 9376b45f4edSpgoyette if disklabel $i > /dev/null 2>&1; then 9383c3f7bb8Schristos disklabel $i > "$work_dir/disklabel.$i" 9393c3f7bb8Schristos fi 9403c3f7bb8Schristos ;; 9413c3f7bb8Schristos esac 9423a3b03bdSlukem done 9433a3b03bdSlukem 94496a1608eSlukem # if fdisk is available, generate fdisks for: ed ld sd wd 94596a1608eSlukem if [ -x /sbin/fdisk ]; then 94696a1608eSlukem for i in $disks; do 9473c3f7bb8Schristos case $i in 9483c3f7bb8Schristos [elsw]d[0-9]*) 9493c3f7bb8Schristos /sbin/fdisk $i > "$work_dir/fdisk.$i" \ 9503c3f7bb8Schristos 2>/dev/null 9513c3f7bb8Schristos ;; 9523c3f7bb8Schristos esac 95396a1608eSlukem done 95496a1608eSlukem fi 95596a1608eSlukem 9568ce568ceSapb # if dkctl is available, generate dkctl listwedges 9578ce568ceSapb # for: ed ld sd wd cgd ofdisk ra rl raid 958b21dec17Stron if [ -x /sbin/dkctl ]; then 959b21dec17Stron for i in $disks; do 9603c3f7bb8Schristos case $i in 9613c3f7bb8Schristos [elsw]d[0-9]*|cgd[0-9]*|ofdisk[0-9]*|r[al][0-9]*|raid[0-9]*) 9622f6dbbcfSmlelstv if /sbin/dkctl $i listwedges | 9632f6dbbcfSmlelstv grep -qe '[0-9] wedges:'; then 9648ce568ceSapb /sbin/dkctl $i listwedges \ 9658ce568ceSapb > "$work_dir/wedges.$i" 2>/dev/null 9663c3f7bb8Schristos fi 9673c3f7bb8Schristos ;; 9683c3f7bb8Schristos esac 969b21dec17Stron done 970b21dec17Stron fi 971b21dec17Stron 97225e09ac3Sriastradh # if raidctl is available, generate raidctls for: raid 97325e09ac3Sriastradh if [ -x /sbin/raidctl ]; then 97425e09ac3Sriastradh disks=$(iostat -x | awk 'NR > 1 && $1 ~ /^raid/ { print $1; }') 97525e09ac3Sriastradh for i in $disks; do 97625e09ac3Sriastradh /sbin/raidctl -G $i > "$work_dir/raidconf.$i" \ 97725e09ac3Sriastradh 2>/dev/null 97825e09ac3Sriastradh done 97925e09ac3Sriastradh fi 98025e09ac3Sriastradh 981b21dec17Stron # append list of new disklabels, fdisks and wedges 9828ce568ceSapb ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ 98325e09ac3Sriastradh $work_dir/raidconf.* 2>/dev/null | 9842811b170Satatat egrep -v '\.(backup|current)(,v)?$' >> $LABELS 98592025001Satatat CHANGELIST="$LABELS $CHANGELIST" 98692025001Satatatfi 98792025001Satatat 988a4e58525Shaadif checkyesno check_lvm; then 989b249d4b6Suebayasi # generate list of existing LVM elements Physical Volumes, 990b249d4b6Suebayasi # Volume Groups and Logical Volumes. 991a4e58525Shaad if [ -x /sbin/lvm ]; then 992a4e58525Shaad lvm pvdisplay -m >"$work_dir/lvm.pv" 2>/dev/null 993a4e58525Shaad lvm vgdisplay -m >"$work_dir/lvm.vg" 2>/dev/null 994a4e58525Shaad lvm lvdisplay -m >"$work_dir/lvm.lv" 2>/dev/null 995a4e58525Shaad fi 996a4e58525Shaad ls -1d $work_dir/lvm.* 2>/dev/null | 997a4e58525Shaad egrep -v '\.(backup|current)(,v)?$'>> $LVM_LABELS 998a4e58525Shaad CHANGELIST="$CHANGELIST $LVM_LABELS" 999a4e58525Shaadfi 1000a4e58525Shaad 100192025001Satatat# Check for changes in the list of installed pkgs 100292025001Satatat# 100353cb2117Sjmmvif checkyesno check_pkgs && have_pkgs; then 100496a1608eSlukem pkgs=$work_dir/pkgs 100596a1608eSlukem migrate_file "$backup_dir/pkgs" "$pkgs" 10061410cf30Sagc pkg_dbdir=$(${pkg_admin} config-var PKG_DBDIR) 1007d5fdd803Swiz : ${pkg_dbdir:=/usr/pkg/pkgdb} 100853cb2117Sjmmv ( cd $pkg_dbdir 100967b08a07Sadrianp $pkg_info | sort 101092025001Satatat echo "" 101192025001Satatat find . \( -name +REQUIRED_BY -o -name +CONTENTS \) -print0 | 101211336572Slukem xargs -0 ls -ldgTq | sort -t. +1 | sed -e 's, \./, ,' 101392025001Satatat ) > $pkgs 101496a1608eSlukem echo "$pkgs" > $PKGS 101592025001Satatat CHANGELIST="$PKGS $CHANGELIST" 10163a3b03bdSlukemfi 10173a3b03bdSlukem 101896a1608eSlukem# List of files that get backed up and checked for any modifications. 101991778fe0Scgd# Any changes cause the files to rotate. 10203a3b03bdSlukem# 102196a1608eSlukemif checkyesno check_changelist ; then 1022610ee5bdSlukem mtree -D -k type -f $SPECIALSPEC -E exclude | 1023610ee5bdSlukem sed '/^type=file/!d ; s/type=file \.//' | unvis > $CHANGEFILES 102496a1608eSlukem 10251dfde696Slukem ( 10266c2d977eSlukem # Add other files which might dynamically exist: 102796a1608eSlukem # /etc/ifconfig.* 102896a1608eSlukem # /etc/raid*.conf 10296c2d977eSlukem # /etc/rc.d/* 103096a1608eSlukem # /etc/rc.conf.d/* 10316c2d977eSlukem # 10321dfde696Slukem echo "/etc/ifconfig.*" 10331dfde696Slukem echo "/etc/raid*.conf" 10341dfde696Slukem echo "/etc/rc.d/*" 10351dfde696Slukem echo "/etc/rc.conf.d/*" 1036a4e58525Shaad echo "/etc/lvm/backup/*" 1037a4e58525Shaad echo "/etc/lvm/archive/*" 103896a1608eSlukem 10396c2d977eSlukem # Add /etc/changelist 10406c2d977eSlukem # 10416c2d977eSlukem if [ -s /etc/changelist ]; then 10421dfde696Slukem grep -v '^#' /etc/changelist 10436c2d977eSlukem fi 10441dfde696Slukem ) | while read file; do 10451dfde696Slukem case "$file" in 10461dfde696Slukem *[\*\?\[]*) # If changelist line is a glob ... 10471dfde696Slukem # ... expand possible backup files 10481dfde696Slukem # 1049c3e808d5Suwe ls -1d $backup_dir/${file}.current 2>/dev/null \ 10501dfde696Slukem | sed "s,^$backup_dir/,, ; s,\.current$,," 10516c2d977eSlukem 10521dfde696Slukem # ... expand possible files 10531dfde696Slukem # 1054c3e808d5Suwe ls -1d $file 2>/dev/null 10551dfde696Slukem ;; 10561dfde696Slukem *) 10571dfde696Slukem # Otherwise, just print the filename 10581dfde696Slukem echo $file 10591dfde696Slukem ;; 10601dfde696Slukem esac 10611dfde696Slukem done >> $CHANGEFILES 106296a1608eSlukem CHANGELIST="$CHANGEFILES $CHANGELIST" 10633a3b03bdSlukemfi 10643a3b03bdSlukem 1065c91905c4Sriastradh# Save entropy to ${random_file} if defined, like 1066c91905c4Sriastradh# /etc/rc.d/random_seed. 1067c91905c4Sriastradh# 1068c91905c4Sriastradhif [ -n "${random_file:-}" ]; then 1069c91905c4Sriastradh rndctl -S "$random_file" 1070c91905c4Sriastradhfi 1071c91905c4Sriastradh 107296a1608eSlukem# Special case backups, including the master password file and 107396a1608eSlukem# ssh private host keys. The normal backup mechanisms for 107496a1608eSlukem# $check_changelist (see below) also print out the actual file 107596a1608eSlukem# differences and we don't want to do that for these files 107696a1608eSlukem# 107796a1608eSlukemecho $MP > $TMP1 # always add /etc/master.passwd 1078610ee5bdSlukemmtree -D -k type -f $SPECIALSPEC -I nodiff | 1079610ee5bdSlukem sed '/^type=file/!d ; s/type=file \.//' | unvis >> $TMP1 1080949fa9aeSlukemgrep -v '^$' $TMP1 | sort -u > $TMP2 10816c2d977eSlukem 108274cf1ec6Slukemwhile read file; do 108396a1608eSlukem backup_and_diff "$file" no 108474cf1ec6Slukemdone < $TMP2 108596a1608eSlukem 108696a1608eSlukem 10873a3b03bdSlukemif [ -n "$CHANGELIST" ]; then 1088949fa9aeSlukem grep -h -v '^$' $CHANGELIST | sort -u > $TMP1 10896c2d977eSlukem comm -23 $TMP1 $TMP2 | while read file; do 109096a1608eSlukem backup_and_diff "$file" yes 109191778fe0Scgd done 109291778fe0Scgdfi 1093065c791dSfair 109453cb2117Sjmmvif have_pkgs; then 1095497b5f80Sjmmv if checkyesno check_pkg_vulnerabilities; then 10961410cf30Sagc ${pkg_admin} ${_compat_K_flag} audit >${OUTPUT} 2>&1 1097497b5f80Sjmmv if [ -s ${OUTPUT} ]; then 1098497b5f80Sjmmv printf "\nInstalled vulnerable packages:\n" 1099497b5f80Sjmmv cat ${OUTPUT} 1100497b5f80Sjmmv fi 1101497b5f80Sjmmv fi 1102497b5f80Sjmmv 1103497b5f80Sjmmv if checkyesno check_pkg_signatures; then 11041410cf30Sagc ${pkg_admin} ${_compat_K_flag} check >${OUTPUT} 2>&1 1105497b5f80Sjmmv if [ $? -ne 0 ]; then 1106497b5f80Sjmmv printf "\nFiles with invalid signatures:\n" 1107497b5f80Sjmmv cat ${OUTPUT} 1108497b5f80Sjmmv fi 1109497b5f80Sjmmv fi 1110497b5f80Sjmmvfi 1111497b5f80Sjmmv 1112fb3a33ffSadif [ -f /etc/security.local ]; then 11134d554522Skim . /etc/security.local > $OUTPUT 2>&1 11146a61a211Sjhawk if [ -s $OUTPUT ] ; then 11156a61a211Sjhawk printf "\nRunning /etc/security.local:\n" 11166a61a211Sjhawk cat $OUTPUT 11176a61a211Sjhawk fi 1118fb3a33ffSadfi 1119