security revision 1.52 1 1.1 cgd #!/bin/sh -
2 1.1 cgd #
3 1.52 atatat # $NetBSD: security,v 1.52 2001/04/04 03:17:19 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.52 atatat backup_file update $MP $CUR $BACK
143 1.9 cgd fi
144 1.9 cgd else
145 1.52 atatat backup_file add $MP $CUR $BACK
146 1.9 cgd fi
147 1.9 cgd
148 1.9 cgd # Check the group file syntax.
149 1.32 lukem #
150 1.31 lukem if checkyesno check_group; then
151 1.15 mrg GRP=/etc/group
152 1.49 jdolecek awk -F: -v "len=$max_grouplen" '{
153 1.15 mrg if ($0 ~ /^[ ]*$/) {
154 1.25 lukem printf "Line %d is a blank line.\n", NR;
155 1.15 mrg next;
156 1.15 mrg }
157 1.34 abs if (NF != 4 && ($1 != "+" || NF != 1))
158 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
159 1.34 abs if ($1 == "+" ) {
160 1.34 abs next;
161 1.34 abs }
162 1.15 mrg if ($1 !~ /^[A-za-z0-9]*$/)
163 1.25 lukem printf "Group %s has non-alphanumeric characters.\n",
164 1.25 lukem $1;
165 1.49 jdolecek if (length($1) > len)
166 1.49 jdolecek printf "Group %s has more than "len" characters.\n", $1;
167 1.15 mrg if ($3 !~ /[0-9]*/)
168 1.25 lukem printf "Login %s has a negative group id.\n", $1;
169 1.15 mrg }' < $GRP > $OUTPUT
170 1.15 mrg if [ -s $OUTPUT ] ; then
171 1.15 mrg printf "\nChecking the $GRP file:\n"
172 1.15 mrg cat $OUTPUT
173 1.15 mrg fi
174 1.15 mrg
175 1.15 mrg awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
176 1.15 mrg if [ -s $OUTPUT ] ; then
177 1.15 mrg printf "\n$GRP has duplicate group names.\n"
178 1.15 mrg column $OUTPUT
179 1.15 mrg fi
180 1.9 cgd fi
181 1.9 cgd
182 1.9 cgd # Check for root paths, umask values in startup files.
183 1.9 cgd # The check for the root paths is problematical -- it's likely to fail
184 1.9 cgd # in other environments. Once the shells have been modified to warn
185 1.9 cgd # of '.' in the path, the path tests should go away.
186 1.32 lukem #
187 1.31 lukem if checkyesno check_rootdotfiles; then
188 1.28 lukem > $OUTPUT
189 1.15 mrg rhome=`csh -fc "echo ~root"`
190 1.15 mrg umaskset=no
191 1.15 mrg list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
192 1.15 mrg for i in $list ; do
193 1.15 mrg if [ -f $i ] ; then
194 1.45 sommerfe if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ; then
195 1.15 mrg umaskset=yes
196 1.15 mrg fi
197 1.45 sommerfe # double check the umask value itself; ensure that both the
198 1.45 sommerfe # 020 and 002 bits are set.
199 1.45 sommerfe # we handle this in decimal initially to extract the digits,
200 1.45 sommerfe # and then extract the `2' bit of each digit.
201 1.45 sommerfe # this is made especially painful because
202 1.45 sommerfe # bitwise operations were left out of awk.
203 1.45 sommerfe egrep '^[ \t]*umask[ \t]+[0-7]+' $i |
204 1.45 sommerfe awk '{ g= ($2 % 100) - ($2 % 10);
205 1.45 sommerfe g /= 10;
206 1.45 sommerfe g = g % 4;
207 1.45 sommerfe g -= g % 2;
208 1.45 sommerfe if (g != 2) { print "\tRoot umask is group writeable" }
209 1.45 sommerfe o = ($2 % 10);
210 1.45 sommerfe o = o % 4;
211 1.45 sommerfe o -= o % 2;
212 1.45 sommerfe if (o != 2) { print "\tRoot umask is other writeable" } }' |
213 1.45 sommerfe sort -u >> $OUTPUT
214 1.26 lukem SAVE_PATH=$PATH
215 1.26 lukem unset PATH
216 1.15 mrg /bin/csh -f -s << end-of-csh > /dev/null 2>&1
217 1.15 mrg source $i
218 1.15 mrg /bin/ls -ldgT \$path > $TMP1
219 1.9 cgd end-of-csh
220 1.26 lukem PATH=$SAVE_PATH
221 1.15 mrg awk '{
222 1.15 mrg if ($10 ~ /^\.$/) {
223 1.27 lukem print "\tThe root path includes .";
224 1.15 mrg next;
225 1.15 mrg }
226 1.15 mrg }
227 1.15 mrg $1 ~ /^d....w/ \
228 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
229 1.15 mrg $1 ~ /^d.......w/ \
230 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
231 1.15 mrg < $TMP1 >> $OUTPUT
232 1.15 mrg fi
233 1.15 mrg done
234 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
235 1.27 lukem printf "\nChecking root csh paths, umask values:\n$list\n\n"
236 1.15 mrg if [ -s $OUTPUT ]; then
237 1.15 mrg cat $OUTPUT
238 1.15 mrg fi
239 1.15 mrg if [ $umaskset = "no" ] ; then
240 1.27 lukem printf "\tRoot csh startup files do not set the umask.\n"
241 1.15 mrg fi
242 1.9 cgd fi
243 1.9 cgd
244 1.28 lukem > $OUTPUT
245 1.15 mrg rhome=/root
246 1.15 mrg umaskset=no
247 1.23 lukem list="/etc/profile ${rhome}/.profile"
248 1.15 mrg for i in $list; do
249 1.15 mrg if [ -f $i ] ; then
250 1.15 mrg if egrep umask $i > /dev/null ; then
251 1.15 mrg umaskset=yes
252 1.15 mrg fi
253 1.15 mrg egrep umask $i |
254 1.15 mrg awk '$2 % 100 < 20 \
255 1.27 lukem { print "\tRoot umask is group writeable" } \
256 1.15 mrg $2 % 10 < 2 \
257 1.27 lukem { print "\tRoot umask is other writeable" }' \
258 1.27 lukem >> $OUTPUT
259 1.26 lukem SAVE_PATH=$PATH
260 1.26 lukem unset PATH
261 1.15 mrg /bin/sh << end-of-sh > /dev/null 2>&1
262 1.15 mrg . $i
263 1.26 lukem list=\`echo \$PATH | /usr/bin/sed -e \
264 1.26 lukem 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g'\`
265 1.15 mrg /bin/ls -ldgT \$list > $TMP1
266 1.9 cgd end-of-sh
267 1.26 lukem PATH=$SAVE_PATH
268 1.15 mrg awk '{
269 1.15 mrg if ($10 ~ /^\.$/) {
270 1.27 lukem print "\tThe root path includes .";
271 1.15 mrg next;
272 1.15 mrg }
273 1.15 mrg }
274 1.15 mrg $1 ~ /^d....w/ \
275 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
276 1.15 mrg $1 ~ /^d.......w/ \
277 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
278 1.15 mrg < $TMP1 >> $OUTPUT
279 1.9 cgd
280 1.15 mrg fi
281 1.15 mrg done
282 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
283 1.15 mrg printf "\nChecking root sh paths, umask values:\n$list\n"
284 1.15 mrg if [ -s $OUTPUT ]; then
285 1.15 mrg cat $OUTPUT
286 1.15 mrg fi
287 1.15 mrg if [ $umaskset = "no" ] ; then
288 1.27 lukem printf "\tRoot sh startup files do not set the umask.\n"
289 1.15 mrg fi
290 1.9 cgd fi
291 1.9 cgd fi
292 1.9 cgd
293 1.9 cgd # Root and uucp should both be in /etc/ftpusers.
294 1.32 lukem #
295 1.31 lukem if checkyesno check_ftpusers; then
296 1.28 lukem > $OUTPUT
297 1.28 lukem list="uucp "`awk '$2 == 0 { print $1 }' $MPBYUID`
298 1.27 lukem for i in $list; do
299 1.29 lukem if /usr/libexec/ftpd -C $i ; then
300 1.29 lukem printf "\t$i is not denied\n" >> $OUTPUT
301 1.27 lukem fi
302 1.27 lukem done
303 1.28 lukem if [ -s $OUTPUT ]; then
304 1.28 lukem printf "\nChecking the /etc/ftpusers configuration:\n"
305 1.28 lukem cat $OUTPUT
306 1.28 lukem fi
307 1.9 cgd fi
308 1.9 cgd
309 1.43 itojun # Uudecode should not be in the /etc/mail/aliases file.
310 1.32 lukem #
311 1.31 lukem if checkyesno check_aliases; then
312 1.43 itojun for f in /etc/mail/aliases /etc/aliases; do
313 1.43 itojun if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then
314 1.43 itojun printf "\nEntry for uudecode in $f file.\n"
315 1.43 itojun fi
316 1.43 itojun done
317 1.9 cgd fi
318 1.9 cgd
319 1.9 cgd # Files that should not have + signs.
320 1.32 lukem #
321 1.31 lukem if checkyesno check_rhosts; then
322 1.15 mrg list="/etc/hosts.equiv /etc/hosts.lpd"
323 1.15 mrg for f in $list ; do
324 1.15 mrg if [ -f $f ] && egrep '\+' $f > /dev/null ; then
325 1.15 mrg printf "\nPlus sign in $f file.\n"
326 1.15 mrg fi
327 1.15 mrg done
328 1.15 mrg
329 1.15 mrg # Check for special users with .rhosts files. Only root and toor should
330 1.16 mikel # have .rhosts files. Also, .rhosts files should not have plus signs.
331 1.15 mrg awk -F: '$1 != "root" && $1 != "toor" && \
332 1.15 mrg ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
333 1.20 mycroft { print $1 " " $9 }' $MP |
334 1.19 mycroft sort -k2 |
335 1.15 mrg while read uid homedir; do
336 1.15 mrg if [ -f ${homedir}/.rhosts ] ; then
337 1.15 mrg rhost=`ls -ldgT ${homedir}/.rhosts`
338 1.46 christos printf -- "$uid: $rhost\n"
339 1.15 mrg fi
340 1.15 mrg done > $OUTPUT
341 1.15 mrg if [ -s $OUTPUT ] ; then
342 1.15 mrg printf "\nChecking for special users with .rhosts files.\n"
343 1.15 mrg cat $OUTPUT
344 1.15 mrg fi
345 1.15 mrg
346 1.15 mrg while read uid homedir; do
347 1.35 fair if [ -f ${homedir}/.rhosts -a -r ${homedir}/.rhosts ] && \
348 1.41 christos cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null ; then
349 1.46 christos printf -- "$uid: + in .rhosts file.\n"
350 1.15 mrg fi
351 1.29 lukem done < $MPBYPATH > $OUTPUT
352 1.15 mrg if [ -s $OUTPUT ] ; then
353 1.15 mrg printf "\nChecking .rhosts files syntax.\n"
354 1.15 mrg cat $OUTPUT
355 1.15 mrg fi
356 1.9 cgd fi
357 1.9 cgd
358 1.9 cgd # Check home directories. Directories should not be owned by someone else
359 1.9 cgd # or writeable.
360 1.32 lukem #
361 1.31 lukem if checkyesno check_homes; then
362 1.15 mrg while read uid homedir; do
363 1.15 mrg if [ -d ${homedir}/ ] ; then
364 1.15 mrg file=`ls -ldgT ${homedir}`
365 1.46 christos printf -- "$uid $file\n"
366 1.9 cgd fi
367 1.29 lukem done < $MPBYPATH |
368 1.15 mrg awk '$1 != $4 && $4 != "root" \
369 1.15 mrg { print "user " $1 " home directory is owned by " $4 }
370 1.15 mrg $2 ~ /^-....w/ \
371 1.15 mrg { print "user " $1 " home directory is group writeable" }
372 1.15 mrg $2 ~ /^-.......w/ \
373 1.27 lukem { print "user " $1 " home directory is other writeable" }' \
374 1.27 lukem > $OUTPUT
375 1.15 mrg if [ -s $OUTPUT ] ; then
376 1.15 mrg printf "\nChecking home directories.\n"
377 1.15 mrg cat $OUTPUT
378 1.15 mrg fi
379 1.15 mrg
380 1.15 mrg # Files that should not be owned by someone else or readable.
381 1.27 lukem list=".Xauthority .netrc"
382 1.15 mrg while read uid homedir; do
383 1.15 mrg for f in $list ; do
384 1.15 mrg file=${homedir}/${f}
385 1.15 mrg if [ -f $file ] ; then
386 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
387 1.15 mrg fi
388 1.15 mrg done
389 1.29 lukem done < $MPBYPATH |
390 1.15 mrg awk '$1 != $5 && $5 != "root" \
391 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
392 1.15 mrg $3 ~ /^-...r/ \
393 1.15 mrg { print "user " $1 " " $2 " file is group readable" }
394 1.15 mrg $3 ~ /^-......r/ \
395 1.15 mrg { print "user " $1 " " $2 " file is other readable" }
396 1.15 mrg $3 ~ /^-....w/ \
397 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
398 1.15 mrg $3 ~ /^-.......w/ \
399 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
400 1.27 lukem > $OUTPUT
401 1.15 mrg
402 1.15 mrg # Files that should not be owned by someone else or writeable.
403 1.19 mycroft list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
404 1.19 mycroft .cshrc .emacs .exrc .forward .history .klogin .login .logout \
405 1.27 lukem .profile .qmail .rc_history .rhosts .tcshrc .twmrc .xinitrc \
406 1.27 lukem .xsession"
407 1.15 mrg while read uid homedir; do
408 1.15 mrg for f in $list ; do
409 1.15 mrg file=${homedir}/${f}
410 1.15 mrg if [ -f $file ] ; then
411 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
412 1.15 mrg fi
413 1.15 mrg done
414 1.29 lukem done < $MPBYPATH |
415 1.15 mrg awk '$1 != $5 && $5 != "root" \
416 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
417 1.15 mrg $3 ~ /^-....w/ \
418 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
419 1.15 mrg $3 ~ /^-.......w/ \
420 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
421 1.27 lukem >> $OUTPUT
422 1.15 mrg if [ -s $OUTPUT ] ; then
423 1.15 mrg printf "\nChecking dot files.\n"
424 1.15 mrg cat $OUTPUT
425 1.15 mrg fi
426 1.9 cgd fi
427 1.9 cgd
428 1.9 cgd # Mailboxes should be owned by user and unreadable.
429 1.32 lukem #
430 1.31 lukem if checkyesno check_varmail; then
431 1.15 mrg ls -l /var/mail | sed 1d | \
432 1.15 mrg awk '$3 != $9 \
433 1.15 mrg { print "user " $9 " mailbox is owned by " $3 }
434 1.15 mrg $1 != "-rw-------" \
435 1.15 mrg { print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
436 1.15 mrg if [ -s $OUTPUT ] ; then
437 1.15 mrg printf "\nChecking mailbox ownership.\n"
438 1.15 mrg cat $OUTPUT
439 1.15 mrg fi
440 1.15 mrg fi
441 1.15 mrg
442 1.32 lukem # NFS exports shouldn't be globally exported
443 1.32 lukem #
444 1.32 lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
445 1.32 lukem awk '{
446 1.22 lukem # ignore comments and blank lines
447 1.39 hubertf if ($0 ~ /^\#/ || $0 ~ /^$/ )
448 1.22 lukem next;
449 1.22 lukem
450 1.15 mrg readonly = 0;
451 1.15 mrg for (i = 2; i <= NF; ++i) {
452 1.15 mrg if ($i ~ /-ro/)
453 1.15 mrg readonly = 1;
454 1.15 mrg else if ($i !~ /^-/)
455 1.15 mrg next;
456 1.15 mrg }
457 1.15 mrg if (readonly)
458 1.15 mrg print "File system " $1 " globally exported, read-only."
459 1.15 mrg else
460 1.15 mrg print "File system " $1 " globally exported, read-write."
461 1.32 lukem }' < /etc/exports > $OUTPUT
462 1.32 lukem if [ -s $OUTPUT ] ; then
463 1.15 mrg printf "\nChecking for globally exported file systems.\n"
464 1.15 mrg cat $OUTPUT
465 1.15 mrg fi
466 1.9 cgd fi
467 1.9 cgd
468 1.9 cgd # Display any changes in setuid files and devices.
469 1.32 lukem #
470 1.31 lukem if checkyesno check_devices; then
471 1.28 lukem > $ERR
472 1.15 mrg (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
473 1.15 mrg -o -fstype procfs \) -a -prune -o \
474 1.21 mycroft \( \( -perm -u+s -a ! -type d \) -o \
475 1.21 mycroft \( -perm -g+s -a ! -type d \) -o \
476 1.24 lukem -type b -o -type c \) -print0 | \
477 1.24 lukem xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
478 1.15 mrg
479 1.15 mrg # Display any errors that occurred during system file walk.
480 1.15 mrg if [ -s $OUTPUT ] ; then
481 1.28 lukem printf "Setuid/device find errors:\n" >> $ERR
482 1.28 lukem cat $OUTPUT >> $ERR
483 1.28 lukem printf "\n" >> $ERR
484 1.15 mrg fi
485 1.15 mrg
486 1.15 mrg # Display any changes in the setuid file list.
487 1.15 mrg egrep -v '^[bc]' $LIST > $TMP1
488 1.15 mrg if [ -s $TMP1 ] ; then
489 1.15 mrg # Check to make sure uudecode isn't setuid.
490 1.15 mrg if grep -w uudecode $TMP1 > /dev/null ; then
491 1.28 lukem printf "\nUudecode is setuid.\n" >> $ERR
492 1.15 mrg fi
493 1.15 mrg
494 1.48 abs CUR=$backup_dir/setuid.current
495 1.48 abs BACK=$backup_dir/setuid.backup
496 1.9 cgd
497 1.15 mrg if [ -s $CUR ] ; then
498 1.15 mrg if cmp -s $CUR $TMP1 ; then
499 1.15 mrg :
500 1.15 mrg else
501 1.15 mrg > $TMP2
502 1.15 mrg join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
503 1.15 mrg if [ -s $OUTPUT ] ; then
504 1.28 lukem printf "Setuid additions:\n" >> $ERR
505 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
506 1.28 lukem printf "\n" >> $ERR
507 1.15 mrg fi
508 1.15 mrg
509 1.15 mrg join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
510 1.15 mrg if [ -s $OUTPUT ] ; then
511 1.28 lukem printf "Setuid deletions:\n" >> $ERR
512 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
513 1.28 lukem printf "\n" >> $ERR
514 1.15 mrg fi
515 1.15 mrg
516 1.20 mycroft sort -k10 $TMP2 $CUR $TMP1 | \
517 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
518 1.27 lukem uniq -u > $OUTPUT
519 1.15 mrg if [ -s $OUTPUT ] ; then
520 1.28 lukem printf "Setuid changes:\n" >> $ERR
521 1.28 lukem column -t $OUTPUT >> $ERR
522 1.28 lukem printf "\n" >> $ERR
523 1.15 mrg fi
524 1.9 cgd
525 1.52 atatat backup_file update $TMP1 $CUR $BACK
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.52 atatat backup_file add $TMP1 $CUR $BACK
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.52 atatat backup_file update $TMP1 $CUR $BACK
595 1.9 cgd fi
596 1.15 mrg else
597 1.28 lukem printf "Device additions:\n" >> $ERR
598 1.28 lukem column -t $TMP1 >> $ERR
599 1.28 lukem printf "\n" >> $ERR
600 1.52 atatat backup_file add $TMP1 $CUR $BACK >> $ERR
601 1.9 cgd fi
602 1.28 lukem fi
603 1.28 lukem if [ -s $ERR ] ; then
604 1.28 lukem printf "\nChecking setuid files and devices:\n"
605 1.28 lukem cat $ERR
606 1.28 lukem printf "\n"
607 1.9 cgd fi
608 1.9 cgd fi
609 1.9 cgd
610 1.9 cgd # Check special files.
611 1.9 cgd # Check system binaries.
612 1.9 cgd #
613 1.9 cgd # Create the mtree tree specifications using:
614 1.9 cgd #
615 1.9 cgd # mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid > DIR.secure
616 1.38 kleink # chown root:wheel DIR.secure
617 1.16 mikel # chmod 600 DIR.secure
618 1.9 cgd #
619 1.9 cgd # Note, this is not complete protection against Trojan horsed binaries, as
620 1.9 cgd # the hacker can modify the tree specification to match the replaced binary.
621 1.9 cgd # For details on really protecting yourself against modified binaries, see
622 1.9 cgd # the mtree(8) manual page.
623 1.32 lukem #
624 1.31 lukem if checkyesno check_mtree; then
625 1.9 cgd mtree -e -p / -f /etc/mtree/special > $OUTPUT
626 1.15 mrg if [ -s $OUTPUT ]; then
627 1.9 cgd printf "\nChecking special files and directories.\n"
628 1.9 cgd cat $OUTPUT
629 1.9 cgd fi
630 1.9 cgd
631 1.9 cgd > $OUTPUT
632 1.16 mikel for file in /etc/mtree/*.secure; do
633 1.16 mikel [ $file = '/etc/mtree/*.secure' ] && continue
634 1.9 cgd tree=`sed -n -e '3s/.* //p' -e 3q $file`
635 1.9 cgd mtree -f $file -p $tree > $TMP1
636 1.9 cgd if [ -s $TMP1 ]; then
637 1.9 cgd printf "\nChecking $tree:\n" >> $OUTPUT
638 1.9 cgd cat $TMP1 >> $OUTPUT
639 1.9 cgd fi
640 1.9 cgd done
641 1.15 mrg if [ -s $OUTPUT ]; then
642 1.9 cgd printf "\nChecking system binaries:\n"
643 1.9 cgd cat $OUTPUT
644 1.9 cgd fi
645 1.9 cgd fi
646 1.9 cgd
647 1.32 lukem CHANGELIST=""
648 1.32 lukem
649 1.32 lukem # Backup disklabels of available disks
650 1.32 lukem #
651 1.32 lukem if checkyesno check_disklabels; then
652 1.32 lukem # generate list of old disklabels and remove them
653 1.48 abs ls -1d $backup_dir/disklabel.* 2>/dev/null |
654 1.52 atatat egrep -v '\.(backup|current)(,v)?$' > $LABELS
655 1.32 lukem xargs rm < $LABELS
656 1.32 lukem
657 1.40 perry disks=`iostat -x | sed 1d | awk '$1 !~ /^[cfm]d/ { print $1; }'`
658 1.32 lukem for i in $disks; do
659 1.48 abs dlf="$backup_dir/disklabel.$i"
660 1.32 lukem disklabel $i > $dlf 2>/dev/null
661 1.32 lukem done
662 1.32 lukem
663 1.32 lukem # append list of new disklabels, sort list
664 1.48 abs ls -1d $backup_dir/disklabel.* 2>/dev/null |
665 1.52 atatat egrep -v '\.(backup|current)(,v)?$' >> $LABELS
666 1.32 lukem sort -u -o $LABELS $LABELS
667 1.32 lukem CHANGELIST=$LABELS
668 1.32 lukem fi
669 1.32 lukem
670 1.9 cgd # List of files that get backed up and checked for any modifications. Each
671 1.48 abs # file is expected to have two backups, $backup_dir/file.{current,backup}.
672 1.9 cgd # Any changes cause the files to rotate.
673 1.32 lukem #
674 1.31 lukem if checkyesno check_changelist && [ -s /etc/changelist ] ; then
675 1.32 lukem CHANGELIST="/etc/changelist $CHANGELIST"
676 1.32 lukem fi
677 1.32 lukem
678 1.32 lukem if [ -n "$CHANGELIST" ]; then
679 1.32 lukem for file in `egrep -hv "^#|$MP" $CHANGELIST`; do
680 1.48 abs CUR=$backup_dir/${file##*/}.current
681 1.48 abs BACK=$backup_dir/${file##*/}.backup
682 1.30 mycroft if [ -f $file ]; then
683 1.30 mycroft if [ -f $CUR ] ; then
684 1.9 cgd diff $CUR $file > $OUTPUT
685 1.9 cgd if [ -s $OUTPUT ] ; then
686 1.9 cgd printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
687 1.9 cgd cat $OUTPUT
688 1.52 atatat backup_file update $file $CUR $BACK
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.52 atatat backup_file add $file $CUR $BACK
694 1.30 mycroft fi
695 1.30 mycroft else
696 1.30 mycroft if [ -f $CUR ]; then
697 1.30 mycroft printf "\n======\n%s removed\n======\n" $file
698 1.30 mycroft diff $CUR /dev/null
699 1.52 atatat backup_file remove $file $CUR $BACK
700 1.9 cgd fi
701 1.9 cgd fi
702 1.9 cgd done
703 1.44 ad fi
704 1.44 ad
705 1.44 ad if [ -f /etc/security.local ]; then
706 1.44 ad echo ""
707 1.44 ad echo "Running /etc/security.local:"
708 1.44 ad . /etc/security.local
709 1.9 cgd fi
710