security revision 1.33 1 1.1 cgd #!/bin/sh -
2 1.1 cgd #
3 1.33 tv # $NetBSD: security,v 1.33 1998/09/14 19:42:42 tv Exp $
4 1.9 cgd # from: @(#)security 8.1 (Berkeley) 6/9/93
5 1.1 cgd #
6 1.1 cgd
7 1.9 cgd PATH=/sbin:/usr/sbin:/bin:/usr/bin
8 1.1 cgd
9 1.31 lukem if [ -f /etc/rc.subr ]; then
10 1.31 lukem . /etc/rc.subr
11 1.31 lukem else
12 1.31 lukem echo "Can't read /etc/rc.subr; aborting."
13 1.31 lukem exit 1;
14 1.31 lukem fi
15 1.31 lukem
16 1.9 cgd umask 077
17 1.1 cgd
18 1.15 mrg if [ -s /etc/security.conf ]; then
19 1.15 mrg . /etc/security.conf
20 1.15 mrg fi
21 1.15 mrg
22 1.15 mrg SECUREDIR=/tmp/_securedir.$$
23 1.15 mrg if ! mkdir $SECUREDIR; then
24 1.15 mrg echo can not create $SECUREDIR.
25 1.15 mrg exit 1
26 1.15 mrg fi
27 1.15 mrg
28 1.15 mrg if ! cd $SECUREDIR; then
29 1.15 mrg echo can not chdir to $SECUREDIR.
30 1.15 mrg exit 1
31 1.15 mrg fi
32 1.15 mrg
33 1.15 mrg ERR=secure1.$$
34 1.15 mrg TMP1=secure2.$$
35 1.15 mrg TMP2=secure3.$$
36 1.28 lukem MPBYUID=secure4.$$
37 1.29 lukem MPBYPATH=secure5.$$
38 1.27 lukem LIST=secure6.$$
39 1.27 lukem OUTPUT=secure7.$$
40 1.32 lukem LABELS=secure8.$$
41 1.15 mrg
42 1.27 lukem trap '/bin/rm -rf $SECUREDIR ; exit 0' 0 2 3
43 1.15 mrg
44 1.15 mrg MP=/etc/master.passwd
45 1.9 cgd
46 1.27 lukem # these is used several times.
47 1.28 lukem awk -F: '{ print $1 " " $3 }' $MP | sort -k2n > $MPBYUID
48 1.29 lukem awk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH
49 1.9 cgd
50 1.9 cgd # Check the master password file syntax.
51 1.32 lukem #
52 1.31 lukem if checkyesno check_passwd; then
53 1.25 lukem awk '
54 1.25 lukem BEGIN {
55 1.25 lukem while ( getline < "/etc/shells" > 0 ) {
56 1.25 lukem if ($LINE ~ /^\#/ || $LINE ~ /^$/ )
57 1.25 lukem continue;
58 1.25 lukem shells[$1]++;
59 1.25 lukem }
60 1.25 lukem FS=":";
61 1.25 lukem }
62 1.25 lukem
63 1.25 lukem {
64 1.15 mrg if ($0 ~ /^[ ]*$/) {
65 1.25 lukem printf "Line %d is a blank line.\n", NR;
66 1.15 mrg next;
67 1.15 mrg }
68 1.15 mrg if (NF != 10)
69 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
70 1.15 mrg if ($1 !~ /^[A-Za-z0-9]*$/)
71 1.25 lukem printf "Login %s has non-alphanumeric characters.\n",
72 1.25 lukem $1;
73 1.15 mrg if (length($1) > 8)
74 1.25 lukem printf "Login %s has more than 8 characters.\n", $1;
75 1.15 mrg if ($2 == "")
76 1.25 lukem printf "Login %s has no password.\n", $1;
77 1.33 tv if (length($2) != 13 && length($2) != 20 && $2 != "") {
78 1.25 lukem if ($10 == "" || shells[$10])
79 1.27 lukem printf "Login %s is off but still has a valid shell (%s)\n",
80 1.25 lukem $1, $10;
81 1.25 lukem } else if (! shells[$10])
82 1.25 lukem printf "Login %s does not have a valid shell (%s)\n",
83 1.25 lukem $1, $10;
84 1.15 mrg if ($3 == 0 && $1 != "root" && $1 != "toor")
85 1.25 lukem printf "Login %s has a user id of 0.\n", $1;
86 1.15 mrg if ($3 < 0)
87 1.25 lukem printf "Login %s has a negative user id.\n", $1;
88 1.15 mrg if ($4 < 0)
89 1.25 lukem printf "Login %s has a negative group id.\n", $1;
90 1.15 mrg }' < $MP > $OUTPUT
91 1.15 mrg if [ -s $OUTPUT ] ; then
92 1.15 mrg printf "\nChecking the $MP file:\n"
93 1.15 mrg cat $OUTPUT
94 1.15 mrg fi
95 1.15 mrg
96 1.15 mrg awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
97 1.15 mrg if [ -s $OUTPUT ] ; then
98 1.15 mrg printf "\n$MP has duplicate user names.\n"
99 1.15 mrg column $OUTPUT
100 1.15 mrg fi
101 1.15 mrg
102 1.28 lukem < $MPBYUID uniq -d -f 1 | awk '{ print $2 }' > $TMP2
103 1.15 mrg if [ -s $TMP2 ] ; then
104 1.15 mrg printf "\n$MP has duplicate user id's.\n"
105 1.15 mrg while read uid; do
106 1.28 lukem grep -w $uid $MPBYUID
107 1.15 mrg done < $TMP2 | column
108 1.15 mrg fi
109 1.9 cgd fi
110 1.9 cgd
111 1.9 cgd # Backup the master password file; a special case, the normal backup
112 1.9 cgd # mechanisms also print out file differences and we don't want to do
113 1.9 cgd # that because this file has encrypted passwords in it.
114 1.32 lukem #
115 1.9 cgd CUR=/var/backups/`basename $MP`.current
116 1.9 cgd BACK=/var/backups/`basename $MP`.backup
117 1.9 cgd if [ -s $CUR ] ; then
118 1.9 cgd if cmp -s $CUR $MP; then
119 1.9 cgd :
120 1.9 cgd else
121 1.9 cgd cp -p $CUR $BACK
122 1.9 cgd cp -p $MP $CUR
123 1.9 cgd chown root.wheel $CUR
124 1.9 cgd fi
125 1.9 cgd else
126 1.9 cgd cp -p $MP $CUR
127 1.9 cgd chown root.wheel $CUR
128 1.9 cgd fi
129 1.9 cgd
130 1.9 cgd # Check the group file syntax.
131 1.32 lukem #
132 1.31 lukem if checkyesno check_group; then
133 1.15 mrg GRP=/etc/group
134 1.15 mrg awk -F: '{
135 1.15 mrg if ($0 ~ /^[ ]*$/) {
136 1.25 lukem printf "Line %d is a blank line.\n", NR;
137 1.15 mrg next;
138 1.15 mrg }
139 1.15 mrg if (NF != 4)
140 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
141 1.15 mrg if ($1 !~ /^[A-za-z0-9]*$/)
142 1.25 lukem printf "Group %s has non-alphanumeric characters.\n",
143 1.25 lukem $1;
144 1.15 mrg if (length($1) > 8)
145 1.25 lukem printf "Group %s has more than 8 characters.\n", $1;
146 1.15 mrg if ($3 !~ /[0-9]*/)
147 1.25 lukem printf "Login %s has a negative group id.\n", $1;
148 1.15 mrg }' < $GRP > $OUTPUT
149 1.15 mrg if [ -s $OUTPUT ] ; then
150 1.15 mrg printf "\nChecking the $GRP file:\n"
151 1.15 mrg cat $OUTPUT
152 1.15 mrg fi
153 1.15 mrg
154 1.15 mrg awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
155 1.15 mrg if [ -s $OUTPUT ] ; then
156 1.15 mrg printf "\n$GRP has duplicate group names.\n"
157 1.15 mrg column $OUTPUT
158 1.15 mrg fi
159 1.9 cgd fi
160 1.9 cgd
161 1.9 cgd # Check for root paths, umask values in startup files.
162 1.9 cgd # The check for the root paths is problematical -- it's likely to fail
163 1.9 cgd # in other environments. Once the shells have been modified to warn
164 1.9 cgd # of '.' in the path, the path tests should go away.
165 1.32 lukem #
166 1.31 lukem if checkyesno check_rootdotfiles; then
167 1.28 lukem > $OUTPUT
168 1.15 mrg rhome=`csh -fc "echo ~root"`
169 1.15 mrg umaskset=no
170 1.15 mrg list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
171 1.15 mrg for i in $list ; do
172 1.15 mrg if [ -f $i ] ; then
173 1.15 mrg if egrep umask $i > /dev/null ; then
174 1.15 mrg umaskset=yes
175 1.15 mrg fi
176 1.15 mrg egrep umask $i |
177 1.15 mrg awk '$2 % 100 < 20 \
178 1.27 lukem { print "\tRoot umask is group writeable" }
179 1.15 mrg $2 % 10 < 2 \
180 1.27 lukem { print "\tRoot umask is other writeable" }' \
181 1.27 lukem >> $OUTPUT
182 1.26 lukem SAVE_PATH=$PATH
183 1.26 lukem unset PATH
184 1.15 mrg /bin/csh -f -s << end-of-csh > /dev/null 2>&1
185 1.15 mrg source $i
186 1.15 mrg /bin/ls -ldgT \$path > $TMP1
187 1.9 cgd end-of-csh
188 1.26 lukem PATH=$SAVE_PATH
189 1.15 mrg awk '{
190 1.15 mrg if ($10 ~ /^\.$/) {
191 1.27 lukem print "\tThe root path includes .";
192 1.15 mrg next;
193 1.15 mrg }
194 1.15 mrg }
195 1.15 mrg $1 ~ /^d....w/ \
196 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
197 1.15 mrg $1 ~ /^d.......w/ \
198 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
199 1.15 mrg < $TMP1 >> $OUTPUT
200 1.15 mrg fi
201 1.15 mrg done
202 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
203 1.27 lukem printf "\nChecking root csh paths, umask values:\n$list\n\n"
204 1.15 mrg if [ -s $OUTPUT ]; then
205 1.15 mrg cat $OUTPUT
206 1.15 mrg fi
207 1.15 mrg if [ $umaskset = "no" ] ; then
208 1.27 lukem printf "\tRoot csh startup files do not set the umask.\n"
209 1.15 mrg fi
210 1.9 cgd fi
211 1.9 cgd
212 1.28 lukem > $OUTPUT
213 1.15 mrg rhome=/root
214 1.15 mrg umaskset=no
215 1.23 lukem list="/etc/profile ${rhome}/.profile"
216 1.15 mrg for i in $list; do
217 1.15 mrg if [ -f $i ] ; then
218 1.15 mrg if egrep umask $i > /dev/null ; then
219 1.15 mrg umaskset=yes
220 1.15 mrg fi
221 1.15 mrg egrep umask $i |
222 1.15 mrg awk '$2 % 100 < 20 \
223 1.27 lukem { print "\tRoot umask is group writeable" } \
224 1.15 mrg $2 % 10 < 2 \
225 1.27 lukem { print "\tRoot umask is other writeable" }' \
226 1.27 lukem >> $OUTPUT
227 1.26 lukem SAVE_PATH=$PATH
228 1.26 lukem unset PATH
229 1.15 mrg /bin/sh << end-of-sh > /dev/null 2>&1
230 1.15 mrg . $i
231 1.26 lukem list=\`echo \$PATH | /usr/bin/sed -e \
232 1.26 lukem 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g'\`
233 1.15 mrg /bin/ls -ldgT \$list > $TMP1
234 1.9 cgd end-of-sh
235 1.26 lukem PATH=$SAVE_PATH
236 1.15 mrg awk '{
237 1.15 mrg if ($10 ~ /^\.$/) {
238 1.27 lukem print "\tThe root path includes .";
239 1.15 mrg next;
240 1.15 mrg }
241 1.15 mrg }
242 1.15 mrg $1 ~ /^d....w/ \
243 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
244 1.15 mrg $1 ~ /^d.......w/ \
245 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
246 1.15 mrg < $TMP1 >> $OUTPUT
247 1.9 cgd
248 1.15 mrg fi
249 1.15 mrg done
250 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
251 1.15 mrg printf "\nChecking root sh paths, umask values:\n$list\n"
252 1.15 mrg if [ -s $OUTPUT ]; then
253 1.15 mrg cat $OUTPUT
254 1.15 mrg fi
255 1.15 mrg if [ $umaskset = "no" ] ; then
256 1.27 lukem printf "\tRoot sh startup files do not set the umask.\n"
257 1.15 mrg fi
258 1.9 cgd fi
259 1.9 cgd fi
260 1.9 cgd
261 1.9 cgd # Root and uucp should both be in /etc/ftpusers.
262 1.32 lukem #
263 1.31 lukem if checkyesno check_ftpusers; then
264 1.28 lukem > $OUTPUT
265 1.28 lukem list="uucp "`awk '$2 == 0 { print $1 }' $MPBYUID`
266 1.27 lukem for i in $list; do
267 1.29 lukem if /usr/libexec/ftpd -C $i ; then
268 1.29 lukem printf "\t$i is not denied\n" >> $OUTPUT
269 1.27 lukem fi
270 1.27 lukem done
271 1.28 lukem if [ -s $OUTPUT ]; then
272 1.28 lukem printf "\nChecking the /etc/ftpusers configuration:\n"
273 1.28 lukem cat $OUTPUT
274 1.28 lukem fi
275 1.9 cgd fi
276 1.9 cgd
277 1.9 cgd # Uudecode should not be in the /etc/aliases file.
278 1.32 lukem #
279 1.31 lukem if checkyesno check_aliases; then
280 1.18 mikel if egrep '^[^#]*(uudecode|decode).*\|' /etc/aliases; then
281 1.18 mikel printf "\nEntry for uudecode in /etc/aliases file.\n"
282 1.15 mrg fi
283 1.9 cgd fi
284 1.9 cgd
285 1.9 cgd # Files that should not have + signs.
286 1.32 lukem #
287 1.31 lukem if checkyesno check_rhosts; then
288 1.15 mrg list="/etc/hosts.equiv /etc/hosts.lpd"
289 1.15 mrg for f in $list ; do
290 1.15 mrg if [ -f $f ] && egrep '\+' $f > /dev/null ; then
291 1.15 mrg printf "\nPlus sign in $f file.\n"
292 1.15 mrg fi
293 1.15 mrg done
294 1.15 mrg
295 1.15 mrg # Check for special users with .rhosts files. Only root and toor should
296 1.16 mikel # have .rhosts files. Also, .rhosts files should not have plus signs.
297 1.15 mrg awk -F: '$1 != "root" && $1 != "toor" && \
298 1.15 mrg ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
299 1.20 mycroft { print $1 " " $9 }' $MP |
300 1.19 mycroft sort -k2 |
301 1.15 mrg while read uid homedir; do
302 1.15 mrg if [ -f ${homedir}/.rhosts ] ; then
303 1.15 mrg rhost=`ls -ldgT ${homedir}/.rhosts`
304 1.15 mrg printf "$uid: $rhost\n"
305 1.15 mrg fi
306 1.15 mrg done > $OUTPUT
307 1.15 mrg if [ -s $OUTPUT ] ; then
308 1.15 mrg printf "\nChecking for special users with .rhosts files.\n"
309 1.15 mrg cat $OUTPUT
310 1.15 mrg fi
311 1.15 mrg
312 1.15 mrg while read uid homedir; do
313 1.15 mrg if [ -f ${homedir}/.rhosts ] && \
314 1.15 mrg egrep '\+' ${homedir}/.rhosts > /dev/null ; then
315 1.15 mrg printf "$uid: + in .rhosts file.\n"
316 1.15 mrg fi
317 1.29 lukem done < $MPBYPATH > $OUTPUT
318 1.15 mrg if [ -s $OUTPUT ] ; then
319 1.15 mrg printf "\nChecking .rhosts files syntax.\n"
320 1.15 mrg cat $OUTPUT
321 1.15 mrg fi
322 1.9 cgd fi
323 1.9 cgd
324 1.9 cgd # Check home directories. Directories should not be owned by someone else
325 1.9 cgd # or writeable.
326 1.32 lukem #
327 1.31 lukem if checkyesno check_homes; then
328 1.15 mrg while read uid homedir; do
329 1.15 mrg if [ -d ${homedir}/ ] ; then
330 1.15 mrg file=`ls -ldgT ${homedir}`
331 1.15 mrg printf "$uid $file\n"
332 1.9 cgd fi
333 1.29 lukem done < $MPBYPATH |
334 1.15 mrg awk '$1 != $4 && $4 != "root" \
335 1.15 mrg { print "user " $1 " home directory is owned by " $4 }
336 1.15 mrg $2 ~ /^-....w/ \
337 1.15 mrg { print "user " $1 " home directory is group writeable" }
338 1.15 mrg $2 ~ /^-.......w/ \
339 1.27 lukem { print "user " $1 " home directory is other writeable" }' \
340 1.27 lukem > $OUTPUT
341 1.15 mrg if [ -s $OUTPUT ] ; then
342 1.15 mrg printf "\nChecking home directories.\n"
343 1.15 mrg cat $OUTPUT
344 1.15 mrg fi
345 1.15 mrg
346 1.15 mrg # Files that should not be owned by someone else or readable.
347 1.27 lukem list=".Xauthority .netrc"
348 1.15 mrg while read uid homedir; do
349 1.15 mrg for f in $list ; do
350 1.15 mrg file=${homedir}/${f}
351 1.15 mrg if [ -f $file ] ; then
352 1.15 mrg printf "$uid $f `ls -ldgT $file`\n"
353 1.15 mrg fi
354 1.15 mrg done
355 1.29 lukem done < $MPBYPATH |
356 1.15 mrg awk '$1 != $5 && $5 != "root" \
357 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
358 1.15 mrg $3 ~ /^-...r/ \
359 1.15 mrg { print "user " $1 " " $2 " file is group readable" }
360 1.15 mrg $3 ~ /^-......r/ \
361 1.15 mrg { print "user " $1 " " $2 " file is other readable" }
362 1.15 mrg $3 ~ /^-....w/ \
363 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
364 1.15 mrg $3 ~ /^-.......w/ \
365 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
366 1.27 lukem > $OUTPUT
367 1.15 mrg
368 1.15 mrg # Files that should not be owned by someone else or writeable.
369 1.19 mycroft list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
370 1.19 mycroft .cshrc .emacs .exrc .forward .history .klogin .login .logout \
371 1.27 lukem .profile .qmail .rc_history .rhosts .tcshrc .twmrc .xinitrc \
372 1.27 lukem .xsession"
373 1.15 mrg while read uid homedir; do
374 1.15 mrg for f in $list ; do
375 1.15 mrg file=${homedir}/${f}
376 1.15 mrg if [ -f $file ] ; then
377 1.15 mrg printf "$uid $f `ls -ldgT $file`\n"
378 1.15 mrg fi
379 1.15 mrg done
380 1.29 lukem done < $MPBYPATH |
381 1.15 mrg awk '$1 != $5 && $5 != "root" \
382 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
383 1.15 mrg $3 ~ /^-....w/ \
384 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
385 1.15 mrg $3 ~ /^-.......w/ \
386 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
387 1.27 lukem >> $OUTPUT
388 1.15 mrg if [ -s $OUTPUT ] ; then
389 1.15 mrg printf "\nChecking dot files.\n"
390 1.15 mrg cat $OUTPUT
391 1.15 mrg fi
392 1.9 cgd fi
393 1.9 cgd
394 1.9 cgd # Mailboxes should be owned by user and unreadable.
395 1.32 lukem #
396 1.31 lukem if checkyesno check_varmail; then
397 1.15 mrg ls -l /var/mail | sed 1d | \
398 1.15 mrg awk '$3 != $9 \
399 1.15 mrg { print "user " $9 " mailbox is owned by " $3 }
400 1.15 mrg $1 != "-rw-------" \
401 1.15 mrg { print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
402 1.15 mrg if [ -s $OUTPUT ] ; then
403 1.15 mrg printf "\nChecking mailbox ownership.\n"
404 1.15 mrg cat $OUTPUT
405 1.15 mrg fi
406 1.15 mrg fi
407 1.15 mrg
408 1.32 lukem # NFS exports shouldn't be globally exported
409 1.32 lukem #
410 1.32 lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
411 1.32 lukem awk '{
412 1.22 lukem # ignore comments and blank lines
413 1.22 lukem if ($LINE ~ /^\#/ || $LINE ~ /^$/ )
414 1.22 lukem next;
415 1.22 lukem
416 1.15 mrg readonly = 0;
417 1.15 mrg for (i = 2; i <= NF; ++i) {
418 1.15 mrg if ($i ~ /-ro/)
419 1.15 mrg readonly = 1;
420 1.15 mrg else if ($i !~ /^-/)
421 1.15 mrg next;
422 1.15 mrg }
423 1.15 mrg if (readonly)
424 1.15 mrg print "File system " $1 " globally exported, read-only."
425 1.15 mrg else
426 1.15 mrg print "File system " $1 " globally exported, read-write."
427 1.32 lukem }' < /etc/exports > $OUTPUT
428 1.32 lukem if [ -s $OUTPUT ] ; then
429 1.15 mrg printf "\nChecking for globally exported file systems.\n"
430 1.15 mrg cat $OUTPUT
431 1.15 mrg fi
432 1.9 cgd fi
433 1.9 cgd
434 1.9 cgd # Display any changes in setuid files and devices.
435 1.32 lukem #
436 1.31 lukem if checkyesno check_devices; then
437 1.28 lukem > $ERR
438 1.15 mrg (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
439 1.15 mrg -o -fstype procfs \) -a -prune -o \
440 1.21 mycroft \( \( -perm -u+s -a ! -type d \) -o \
441 1.21 mycroft \( -perm -g+s -a ! -type d \) -o \
442 1.24 lukem -type b -o -type c \) -print0 | \
443 1.24 lukem xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
444 1.15 mrg
445 1.15 mrg # Display any errors that occurred during system file walk.
446 1.15 mrg if [ -s $OUTPUT ] ; then
447 1.28 lukem printf "Setuid/device find errors:\n" >> $ERR
448 1.28 lukem cat $OUTPUT >> $ERR
449 1.28 lukem printf "\n" >> $ERR
450 1.15 mrg fi
451 1.15 mrg
452 1.15 mrg # Display any changes in the setuid file list.
453 1.15 mrg egrep -v '^[bc]' $LIST > $TMP1
454 1.15 mrg if [ -s $TMP1 ] ; then
455 1.15 mrg # Check to make sure uudecode isn't setuid.
456 1.15 mrg if grep -w uudecode $TMP1 > /dev/null ; then
457 1.28 lukem printf "\nUudecode is setuid.\n" >> $ERR
458 1.15 mrg fi
459 1.15 mrg
460 1.15 mrg CUR=/var/backups/setuid.current
461 1.15 mrg BACK=/var/backups/setuid.backup
462 1.9 cgd
463 1.15 mrg if [ -s $CUR ] ; then
464 1.15 mrg if cmp -s $CUR $TMP1 ; then
465 1.15 mrg :
466 1.15 mrg else
467 1.15 mrg > $TMP2
468 1.15 mrg join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
469 1.15 mrg if [ -s $OUTPUT ] ; then
470 1.28 lukem printf "Setuid additions:\n" >> $ERR
471 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
472 1.28 lukem printf "\n" >> $ERR
473 1.15 mrg fi
474 1.15 mrg
475 1.15 mrg join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
476 1.15 mrg if [ -s $OUTPUT ] ; then
477 1.28 lukem printf "Setuid deletions:\n" >> $ERR
478 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
479 1.28 lukem printf "\n" >> $ERR
480 1.15 mrg fi
481 1.15 mrg
482 1.20 mycroft sort -k10 $TMP2 $CUR $TMP1 | \
483 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
484 1.27 lukem uniq -u > $OUTPUT
485 1.15 mrg if [ -s $OUTPUT ] ; then
486 1.28 lukem printf "Setuid changes:\n" >> $ERR
487 1.28 lukem column -t $OUTPUT >> $ERR
488 1.28 lukem printf "\n" >> $ERR
489 1.15 mrg fi
490 1.9 cgd
491 1.15 mrg cp $CUR $BACK
492 1.15 mrg cp $TMP1 $CUR
493 1.9 cgd fi
494 1.15 mrg else
495 1.28 lukem printf "Setuid additions:\n" >> $ERR
496 1.28 lukem column -t $TMP1 >> $ERR
497 1.28 lukem printf "\n" >> $ERR
498 1.9 cgd cp $TMP1 $CUR
499 1.9 cgd fi
500 1.15 mrg fi
501 1.15 mrg
502 1.27 lukem # Check for block and character disk devices that are readable or
503 1.27 lukem # writeable or not owned by root.operator.
504 1.15 mrg >$TMP1
505 1.27 lukem DISKLIST="acd ccd cd ch fd hk hp mcd md ra rb rd rl rx rz \
506 1.27 lukem sd se ss tz uk up vnd wd xd xy"
507 1.27 lukem # DISKLIST="$DISKLIST ct mt st wt"
508 1.15 mrg for i in $DISKLIST; do
509 1.15 mrg egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
510 1.15 mrg egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
511 1.15 mrg done
512 1.15 mrg
513 1.15 mrg awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
514 1.25 lukem { printf "Disk %s is user %s, group %s, permissions %s.\n", \
515 1.25 lukem $11, $3, $4, $1; }' < $TMP1 > $OUTPUT
516 1.15 mrg if [ -s $OUTPUT ] ; then
517 1.28 lukem printf "\nChecking disk ownership and permissions.\n" >> $ERR
518 1.28 lukem cat $OUTPUT >> $ERR
519 1.28 lukem printf "\n" >> $ERR
520 1.9 cgd fi
521 1.9 cgd
522 1.15 mrg # Display any changes in the device file list.
523 1.20 mycroft egrep '^[bc]' $LIST | sort -k11 > $TMP1
524 1.15 mrg if [ -s $TMP1 ] ; then
525 1.15 mrg CUR=/var/backups/device.current
526 1.15 mrg BACK=/var/backups/device.backup
527 1.15 mrg
528 1.15 mrg if [ -s $CUR ] ; then
529 1.15 mrg if cmp -s $CUR $TMP1 ; then
530 1.15 mrg :
531 1.15 mrg else
532 1.15 mrg > $TMP2
533 1.15 mrg join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
534 1.15 mrg if [ -s $OUTPUT ] ; then
535 1.28 lukem printf "Device additions:\n" >> $ERR
536 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
537 1.28 lukem printf "\n" >> $ERR
538 1.15 mrg fi
539 1.15 mrg
540 1.15 mrg join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
541 1.15 mrg if [ -s $OUTPUT ] ; then
542 1.28 lukem printf "Device deletions:\n" >> $ERR
543 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
544 1.28 lukem printf "\n" >> $ERR
545 1.15 mrg fi
546 1.15 mrg
547 1.27 lukem # Report any block device change. Ignore
548 1.27 lukem # character devices, only the name is
549 1.27 lukem # significant.
550 1.15 mrg cat $TMP2 $CUR $TMP1 | \
551 1.27 lukem sed -e '/^c/d' | \
552 1.27 lukem sort -k11 | \
553 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
554 1.27 lukem uniq -u > $OUTPUT
555 1.15 mrg if [ -s $OUTPUT ] ; then
556 1.28 lukem printf "Block device changes:\n" >> $ERR
557 1.28 lukem column -t $OUTPUT >> $ERR
558 1.28 lukem printf "\n" >> $ERR
559 1.15 mrg fi
560 1.9 cgd
561 1.15 mrg cp $CUR $BACK
562 1.15 mrg cp $TMP1 $CUR
563 1.9 cgd fi
564 1.15 mrg else
565 1.28 lukem printf "Device additions:\n" >> $ERR
566 1.28 lukem column -t $TMP1 >> $ERR
567 1.28 lukem printf "\n" >> $ERR
568 1.28 lukem cp $TMP1 $CUR >> $ERR
569 1.9 cgd fi
570 1.28 lukem fi
571 1.28 lukem if [ -s $ERR ] ; then
572 1.28 lukem printf "\nChecking setuid files and devices:\n"
573 1.28 lukem cat $ERR
574 1.28 lukem printf "\n"
575 1.9 cgd fi
576 1.9 cgd fi
577 1.9 cgd
578 1.9 cgd # Check special files.
579 1.9 cgd # Check system binaries.
580 1.9 cgd #
581 1.9 cgd # Create the mtree tree specifications using:
582 1.9 cgd #
583 1.9 cgd # mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
584 1.16 mikel # chown root.wheel DIR.secure
585 1.16 mikel # chmod 600 DIR.secure
586 1.9 cgd #
587 1.9 cgd # Note, this is not complete protection against Trojan horsed binaries, as
588 1.9 cgd # the hacker can modify the tree specification to match the replaced binary.
589 1.9 cgd # For details on really protecting yourself against modified binaries, see
590 1.9 cgd # the mtree(8) manual page.
591 1.32 lukem #
592 1.31 lukem if checkyesno check_mtree; then
593 1.9 cgd mtree -e -p / -f /etc/mtree/special > $OUTPUT
594 1.15 mrg if [ -s $OUTPUT ]; then
595 1.9 cgd printf "\nChecking special files and directories.\n"
596 1.9 cgd cat $OUTPUT
597 1.9 cgd fi
598 1.9 cgd
599 1.9 cgd > $OUTPUT
600 1.16 mikel for file in /etc/mtree/*.secure; do
601 1.16 mikel [ $file = '/etc/mtree/*.secure' ] && continue
602 1.9 cgd tree=`sed -n -e '3s/.* //p' -e 3q $file`
603 1.9 cgd mtree -f $file -p $tree > $TMP1
604 1.9 cgd if [ -s $TMP1 ]; then
605 1.9 cgd printf "\nChecking $tree:\n" >> $OUTPUT
606 1.9 cgd cat $TMP1 >> $OUTPUT
607 1.9 cgd fi
608 1.9 cgd done
609 1.15 mrg if [ -s $OUTPUT ]; then
610 1.9 cgd printf "\nChecking system binaries:\n"
611 1.9 cgd cat $OUTPUT
612 1.9 cgd fi
613 1.9 cgd fi
614 1.9 cgd
615 1.32 lukem CHANGELIST=""
616 1.32 lukem
617 1.32 lukem # Backup disklabels of available disks
618 1.32 lukem #
619 1.32 lukem if checkyesno check_disklabels; then
620 1.32 lukem # generate list of old disklabels and remove them
621 1.32 lukem ls -1d /var/backups/disklabel.* 2>/dev/null |
622 1.32 lukem egrep -v '\.(backup|current)$' > $LABELS
623 1.32 lukem xargs rm < $LABELS
624 1.32 lukem
625 1.32 lukem disks=`iostat -x | sed 1d | awk '$1 !~ /^[mf]d/ { print $1; }'`
626 1.32 lukem for i in $disks; do
627 1.32 lukem dlf="/var/backups/disklabel.$i"
628 1.32 lukem disklabel $i > $dlf 2>/dev/null
629 1.32 lukem done
630 1.32 lukem
631 1.32 lukem # append list of new disklabels, sort list
632 1.32 lukem ls -1d /var/backups/disklabel.* 2>/dev/null |
633 1.32 lukem egrep -v '\.(backup|current)$' >> $LABELS
634 1.32 lukem sort -u -o $LABELS $LABELS
635 1.32 lukem CHANGELIST=$LABELS
636 1.32 lukem fi
637 1.32 lukem
638 1.9 cgd # List of files that get backed up and checked for any modifications. Each
639 1.9 cgd # file is expected to have two backups, /var/backups/file.{current,backup}.
640 1.9 cgd # Any changes cause the files to rotate.
641 1.32 lukem #
642 1.31 lukem if checkyesno check_changelist && [ -s /etc/changelist ] ; then
643 1.32 lukem CHANGELIST="/etc/changelist $CHANGELIST"
644 1.32 lukem fi
645 1.32 lukem
646 1.32 lukem if [ -n "$CHANGELIST" ]; then
647 1.32 lukem for file in `egrep -hv "^#|$MP" $CHANGELIST`; do
648 1.9 cgd CUR=/var/backups/`basename $file`.current
649 1.9 cgd BACK=/var/backups/`basename $file`.backup
650 1.30 mycroft if [ -f $file ]; then
651 1.30 mycroft if [ -f $CUR ] ; then
652 1.9 cgd diff $CUR $file > $OUTPUT
653 1.9 cgd if [ -s $OUTPUT ] ; then
654 1.9 cgd printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
655 1.9 cgd cat $OUTPUT
656 1.30 mycroft mv -f $CUR $BACK
657 1.9 cgd cp -p $file $CUR
658 1.30 mycroft chown root.wheel $CUR
659 1.9 cgd fi
660 1.9 cgd else
661 1.30 mycroft printf "\n======\n%s added\n======\n" $file
662 1.30 mycroft diff /dev/null $file
663 1.9 cgd cp -p $file $CUR
664 1.9 cgd chown root.wheel $CUR
665 1.30 mycroft fi
666 1.30 mycroft else
667 1.30 mycroft if [ -f $CUR ]; then
668 1.30 mycroft printf "\n======\n%s removed\n======\n" $file
669 1.30 mycroft diff $CUR /dev/null
670 1.30 mycroft mv -f $CUR $BACK
671 1.9 cgd fi
672 1.9 cgd fi
673 1.9 cgd done
674 1.9 cgd fi
675