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