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