Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

656 lines
17 KiB

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