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