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