security revision 1.61 1 1.1 cgd #!/bin/sh -
2 1.1 cgd #
3 1.61 lukem # $NetBSD: security,v 1.61 2001/09/24 03:19:43 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.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.53 atatat if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[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.59 perry if (length($2) != 13 &&
90 1.59 perry length($2) != 20 &&
91 1.59 perry length($2) != 34 &&
92 1.59 perry $2 != "" &&
93 1.59 perry $2 !~ /^\*[A-z-]+$/ &&
94 1.59 perry $1 != "toor") {
95 1.25 lukem if ($10 == "" || shells[$10])
96 1.27 lukem printf "Login %s is off but still has a valid shell (%s)\n",
97 1.25 lukem $1, $10;
98 1.25 lukem } else if (! shells[$10])
99 1.25 lukem printf "Login %s does not have a valid shell (%s)\n",
100 1.25 lukem $1, $10;
101 1.15 mrg if ($3 == 0 && $1 != "root" && $1 != "toor")
102 1.25 lukem printf "Login %s has a user id of 0.\n", $1;
103 1.15 mrg if ($3 < 0)
104 1.25 lukem printf "Login %s has a negative user id.\n", $1;
105 1.15 mrg if ($4 < 0)
106 1.25 lukem printf "Login %s has a negative group id.\n", $1;
107 1.15 mrg }' < $MP > $OUTPUT
108 1.15 mrg if [ -s $OUTPUT ] ; then
109 1.15 mrg printf "\nChecking the $MP file:\n"
110 1.15 mrg cat $OUTPUT
111 1.15 mrg fi
112 1.15 mrg
113 1.15 mrg awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
114 1.15 mrg if [ -s $OUTPUT ] ; then
115 1.15 mrg printf "\n$MP has duplicate user names.\n"
116 1.15 mrg column $OUTPUT
117 1.15 mrg fi
118 1.15 mrg
119 1.37 wrstuden # To not exclude 'toor', a standard duplicate root account, from the duplicate
120 1.37 wrstuden # account test, uncomment the line below (without egrep in it)and comment
121 1.37 wrstuden # out the line (with egrep in it) below it.
122 1.37 wrstuden #
123 1.37 wrstuden # < $MPBYUID uniq -d -f 1 | awk '{ print $2 }' > $TMP2
124 1.36 wrstuden < $MPBYUID egrep -v '^toor ' | uniq -d -f 1 | awk '{ print $2 }' > $TMP2
125 1.15 mrg if [ -s $TMP2 ] ; then
126 1.15 mrg printf "\n$MP has duplicate user id's.\n"
127 1.15 mrg while read uid; do
128 1.28 lukem grep -w $uid $MPBYUID
129 1.15 mrg done < $TMP2 | column
130 1.15 mrg fi
131 1.9 cgd fi
132 1.9 cgd
133 1.9 cgd # Backup the master password file; a special case, the normal backup
134 1.9 cgd # mechanisms also print out file differences and we don't want to do
135 1.9 cgd # that because this file has encrypted passwords in it.
136 1.32 lukem #
137 1.48 abs CUR=$backup_dir/${MP##*/}.current
138 1.48 abs BACK=$backup_dir/${MP##*/}.backup
139 1.9 cgd if [ -s $CUR ] ; then
140 1.9 cgd if cmp -s $CUR $MP; then
141 1.9 cgd :
142 1.9 cgd else
143 1.52 atatat backup_file update $MP $CUR $BACK
144 1.9 cgd fi
145 1.9 cgd else
146 1.52 atatat backup_file add $MP $CUR $BACK
147 1.9 cgd fi
148 1.9 cgd
149 1.9 cgd # Check the group file syntax.
150 1.32 lukem #
151 1.31 lukem if checkyesno check_group; then
152 1.15 mrg GRP=/etc/group
153 1.49 jdolecek awk -F: -v "len=$max_grouplen" '{
154 1.15 mrg if ($0 ~ /^[ ]*$/) {
155 1.25 lukem printf "Line %d is a blank line.\n", NR;
156 1.15 mrg next;
157 1.15 mrg }
158 1.34 abs if (NF != 4 && ($1 != "+" || NF != 1))
159 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
160 1.34 abs if ($1 == "+" ) {
161 1.34 abs next;
162 1.34 abs }
163 1.53 atatat if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
164 1.25 lukem printf "Group %s has non-alphanumeric characters.\n",
165 1.25 lukem $1;
166 1.49 jdolecek if (length($1) > len)
167 1.49 jdolecek printf "Group %s has more than "len" characters.\n", $1;
168 1.15 mrg if ($3 !~ /[0-9]*/)
169 1.25 lukem printf "Login %s has a negative group id.\n", $1;
170 1.15 mrg }' < $GRP > $OUTPUT
171 1.15 mrg if [ -s $OUTPUT ] ; then
172 1.15 mrg printf "\nChecking the $GRP file:\n"
173 1.15 mrg cat $OUTPUT
174 1.15 mrg fi
175 1.15 mrg
176 1.15 mrg awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
177 1.15 mrg if [ -s $OUTPUT ] ; then
178 1.15 mrg printf "\n$GRP has duplicate group names.\n"
179 1.15 mrg column $OUTPUT
180 1.15 mrg fi
181 1.9 cgd fi
182 1.9 cgd
183 1.9 cgd # Check for root paths, umask values in startup files.
184 1.9 cgd # The check for the root paths is problematical -- it's likely to fail
185 1.9 cgd # in other environments. Once the shells have been modified to warn
186 1.9 cgd # of '.' in the path, the path tests should go away.
187 1.32 lukem #
188 1.31 lukem if checkyesno check_rootdotfiles; then
189 1.28 lukem > $OUTPUT
190 1.15 mrg rhome=`csh -fc "echo ~root"`
191 1.15 mrg umaskset=no
192 1.15 mrg list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
193 1.15 mrg for i in $list ; do
194 1.15 mrg if [ -f $i ] ; then
195 1.45 sommerfe if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ; then
196 1.15 mrg umaskset=yes
197 1.15 mrg fi
198 1.45 sommerfe # double check the umask value itself; ensure that both the
199 1.45 sommerfe # 020 and 002 bits are set.
200 1.45 sommerfe # we handle this in decimal initially to extract the digits,
201 1.45 sommerfe # and then extract the `2' bit of each digit.
202 1.45 sommerfe # this is made especially painful because
203 1.45 sommerfe # bitwise operations were left out of awk.
204 1.45 sommerfe egrep '^[ \t]*umask[ \t]+[0-7]+' $i |
205 1.45 sommerfe awk '{ g= ($2 % 100) - ($2 % 10);
206 1.45 sommerfe g /= 10;
207 1.45 sommerfe g = g % 4;
208 1.45 sommerfe g -= g % 2;
209 1.45 sommerfe if (g != 2) { print "\tRoot umask is group writeable" }
210 1.45 sommerfe o = ($2 % 10);
211 1.45 sommerfe o = o % 4;
212 1.45 sommerfe o -= o % 2;
213 1.45 sommerfe if (o != 2) { print "\tRoot umask is other writeable" } }' |
214 1.45 sommerfe sort -u >> $OUTPUT
215 1.26 lukem SAVE_PATH=$PATH
216 1.26 lukem unset PATH
217 1.15 mrg /bin/csh -f -s << end-of-csh > /dev/null 2>&1
218 1.15 mrg source $i
219 1.15 mrg /bin/ls -ldgT \$path > $TMP1
220 1.9 cgd end-of-csh
221 1.26 lukem PATH=$SAVE_PATH
222 1.15 mrg awk '{
223 1.15 mrg if ($10 ~ /^\.$/) {
224 1.27 lukem print "\tThe root path includes .";
225 1.15 mrg next;
226 1.15 mrg }
227 1.15 mrg }
228 1.15 mrg $1 ~ /^d....w/ \
229 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
230 1.15 mrg $1 ~ /^d.......w/ \
231 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
232 1.15 mrg < $TMP1 >> $OUTPUT
233 1.15 mrg fi
234 1.15 mrg done
235 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
236 1.27 lukem printf "\nChecking root csh paths, umask values:\n$list\n\n"
237 1.15 mrg if [ -s $OUTPUT ]; then
238 1.15 mrg cat $OUTPUT
239 1.15 mrg fi
240 1.15 mrg if [ $umaskset = "no" ] ; then
241 1.27 lukem printf "\tRoot csh startup files do not set the umask.\n"
242 1.15 mrg fi
243 1.9 cgd fi
244 1.9 cgd
245 1.28 lukem > $OUTPUT
246 1.15 mrg rhome=/root
247 1.15 mrg umaskset=no
248 1.23 lukem list="/etc/profile ${rhome}/.profile"
249 1.15 mrg for i in $list; do
250 1.15 mrg if [ -f $i ] ; then
251 1.15 mrg if egrep umask $i > /dev/null ; then
252 1.15 mrg umaskset=yes
253 1.15 mrg fi
254 1.15 mrg egrep umask $i |
255 1.15 mrg awk '$2 % 100 < 20 \
256 1.27 lukem { print "\tRoot umask is group writeable" } \
257 1.15 mrg $2 % 10 < 2 \
258 1.27 lukem { print "\tRoot umask is other writeable" }' \
259 1.27 lukem >> $OUTPUT
260 1.26 lukem SAVE_PATH=$PATH
261 1.26 lukem unset PATH
262 1.15 mrg /bin/sh << end-of-sh > /dev/null 2>&1
263 1.15 mrg . $i
264 1.26 lukem list=\`echo \$PATH | /usr/bin/sed -e \
265 1.26 lukem 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g'\`
266 1.15 mrg /bin/ls -ldgT \$list > $TMP1
267 1.9 cgd end-of-sh
268 1.26 lukem PATH=$SAVE_PATH
269 1.15 mrg awk '{
270 1.15 mrg if ($10 ~ /^\.$/) {
271 1.27 lukem print "\tThe root path includes .";
272 1.15 mrg next;
273 1.15 mrg }
274 1.15 mrg }
275 1.15 mrg $1 ~ /^d....w/ \
276 1.27 lukem { print "\tRoot path directory " $10 " is group writeable." } \
277 1.15 mrg $1 ~ /^d.......w/ \
278 1.27 lukem { print "\tRoot path directory " $10 " is other writeable." }' \
279 1.15 mrg < $TMP1 >> $OUTPUT
280 1.9 cgd
281 1.15 mrg fi
282 1.15 mrg done
283 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
284 1.15 mrg printf "\nChecking root sh paths, umask values:\n$list\n"
285 1.15 mrg if [ -s $OUTPUT ]; then
286 1.15 mrg cat $OUTPUT
287 1.15 mrg fi
288 1.15 mrg if [ $umaskset = "no" ] ; then
289 1.27 lukem printf "\tRoot sh startup files do not set the umask.\n"
290 1.15 mrg fi
291 1.9 cgd fi
292 1.9 cgd fi
293 1.9 cgd
294 1.9 cgd # Root and uucp should both be in /etc/ftpusers.
295 1.32 lukem #
296 1.31 lukem if checkyesno check_ftpusers; then
297 1.28 lukem > $OUTPUT
298 1.28 lukem list="uucp "`awk '$2 == 0 { print $1 }' $MPBYUID`
299 1.27 lukem for i in $list; do
300 1.29 lukem if /usr/libexec/ftpd -C $i ; then
301 1.29 lukem printf "\t$i is not denied\n" >> $OUTPUT
302 1.27 lukem fi
303 1.27 lukem done
304 1.28 lukem if [ -s $OUTPUT ]; then
305 1.28 lukem printf "\nChecking the /etc/ftpusers configuration:\n"
306 1.28 lukem cat $OUTPUT
307 1.28 lukem fi
308 1.9 cgd fi
309 1.9 cgd
310 1.43 itojun # Uudecode should not be in the /etc/mail/aliases file.
311 1.32 lukem #
312 1.31 lukem if checkyesno check_aliases; then
313 1.43 itojun for f in /etc/mail/aliases /etc/aliases; do
314 1.43 itojun if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then
315 1.43 itojun printf "\nEntry for uudecode in $f file.\n"
316 1.43 itojun fi
317 1.43 itojun done
318 1.9 cgd fi
319 1.9 cgd
320 1.9 cgd # Files that should not have + signs.
321 1.32 lukem #
322 1.31 lukem if checkyesno check_rhosts; then
323 1.15 mrg list="/etc/hosts.equiv /etc/hosts.lpd"
324 1.15 mrg for f in $list ; do
325 1.15 mrg if [ -f $f ] && egrep '\+' $f > /dev/null ; then
326 1.15 mrg printf "\nPlus sign in $f file.\n"
327 1.15 mrg fi
328 1.15 mrg done
329 1.15 mrg
330 1.15 mrg # Check for special users with .rhosts files. Only root and toor should
331 1.16 mikel # have .rhosts files. Also, .rhosts files should not have plus signs.
332 1.15 mrg awk -F: '$1 != "root" && $1 != "toor" && \
333 1.15 mrg ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
334 1.20 mycroft { print $1 " " $9 }' $MP |
335 1.19 mycroft sort -k2 |
336 1.15 mrg while read uid homedir; do
337 1.15 mrg if [ -f ${homedir}/.rhosts ] ; then
338 1.15 mrg rhost=`ls -ldgT ${homedir}/.rhosts`
339 1.46 christos printf -- "$uid: $rhost\n"
340 1.15 mrg fi
341 1.15 mrg done > $OUTPUT
342 1.15 mrg if [ -s $OUTPUT ] ; then
343 1.15 mrg printf "\nChecking for special users with .rhosts files.\n"
344 1.15 mrg cat $OUTPUT
345 1.15 mrg fi
346 1.15 mrg
347 1.15 mrg while read uid homedir; do
348 1.35 fair if [ -f ${homedir}/.rhosts -a -r ${homedir}/.rhosts ] && \
349 1.41 christos cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null ; then
350 1.46 christos printf -- "$uid: + in .rhosts file.\n"
351 1.15 mrg fi
352 1.29 lukem done < $MPBYPATH > $OUTPUT
353 1.15 mrg if [ -s $OUTPUT ] ; then
354 1.15 mrg printf "\nChecking .rhosts files syntax.\n"
355 1.15 mrg cat $OUTPUT
356 1.15 mrg fi
357 1.9 cgd fi
358 1.9 cgd
359 1.9 cgd # Check home directories. Directories should not be owned by someone else
360 1.9 cgd # or writeable.
361 1.32 lukem #
362 1.31 lukem if checkyesno check_homes; then
363 1.15 mrg while read uid homedir; do
364 1.15 mrg if [ -d ${homedir}/ ] ; then
365 1.15 mrg file=`ls -ldgT ${homedir}`
366 1.46 christos printf -- "$uid $file\n"
367 1.9 cgd fi
368 1.29 lukem done < $MPBYPATH |
369 1.15 mrg awk '$1 != $4 && $4 != "root" \
370 1.15 mrg { print "user " $1 " home directory is owned by " $4 }
371 1.15 mrg $2 ~ /^-....w/ \
372 1.15 mrg { print "user " $1 " home directory is group writeable" }
373 1.15 mrg $2 ~ /^-.......w/ \
374 1.27 lukem { print "user " $1 " home directory is other writeable" }' \
375 1.27 lukem > $OUTPUT
376 1.15 mrg if [ -s $OUTPUT ] ; then
377 1.15 mrg printf "\nChecking home directories.\n"
378 1.15 mrg cat $OUTPUT
379 1.15 mrg fi
380 1.15 mrg
381 1.15 mrg # Files that should not be owned by someone else or readable.
382 1.27 lukem list=".Xauthority .netrc"
383 1.15 mrg while read uid homedir; do
384 1.15 mrg for f in $list ; do
385 1.15 mrg file=${homedir}/${f}
386 1.15 mrg if [ -f $file ] ; then
387 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
388 1.15 mrg fi
389 1.15 mrg done
390 1.29 lukem done < $MPBYPATH |
391 1.15 mrg awk '$1 != $5 && $5 != "root" \
392 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
393 1.15 mrg $3 ~ /^-...r/ \
394 1.15 mrg { print "user " $1 " " $2 " file is group readable" }
395 1.15 mrg $3 ~ /^-......r/ \
396 1.15 mrg { print "user " $1 " " $2 " file is other readable" }
397 1.15 mrg $3 ~ /^-....w/ \
398 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
399 1.15 mrg $3 ~ /^-.......w/ \
400 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
401 1.27 lukem > $OUTPUT
402 1.15 mrg
403 1.15 mrg # Files that should not be owned by someone else or writeable.
404 1.19 mycroft list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
405 1.19 mycroft .cshrc .emacs .exrc .forward .history .klogin .login .logout \
406 1.27 lukem .profile .qmail .rc_history .rhosts .tcshrc .twmrc .xinitrc \
407 1.27 lukem .xsession"
408 1.15 mrg while read uid homedir; do
409 1.15 mrg for f in $list ; do
410 1.15 mrg file=${homedir}/${f}
411 1.15 mrg if [ -f $file ] ; then
412 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
413 1.15 mrg fi
414 1.15 mrg done
415 1.29 lukem done < $MPBYPATH |
416 1.15 mrg awk '$1 != $5 && $5 != "root" \
417 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
418 1.15 mrg $3 ~ /^-....w/ \
419 1.15 mrg { print "user " $1 " " $2 " file is group writeable" }
420 1.15 mrg $3 ~ /^-.......w/ \
421 1.27 lukem { print "user " $1 " " $2 " file is other writeable" }' \
422 1.27 lukem >> $OUTPUT
423 1.15 mrg if [ -s $OUTPUT ] ; then
424 1.15 mrg printf "\nChecking dot files.\n"
425 1.15 mrg cat $OUTPUT
426 1.15 mrg fi
427 1.9 cgd fi
428 1.9 cgd
429 1.9 cgd # Mailboxes should be owned by user and unreadable.
430 1.32 lukem #
431 1.31 lukem if checkyesno check_varmail; then
432 1.15 mrg ls -l /var/mail | sed 1d | \
433 1.15 mrg awk '$3 != $9 \
434 1.15 mrg { print "user " $9 " mailbox is owned by " $3 }
435 1.15 mrg $1 != "-rw-------" \
436 1.15 mrg { print "user " $9 " mailbox is " $1 ", group " $4 }' > $OUTPUT
437 1.15 mrg if [ -s $OUTPUT ] ; then
438 1.15 mrg printf "\nChecking mailbox ownership.\n"
439 1.15 mrg cat $OUTPUT
440 1.15 mrg fi
441 1.15 mrg fi
442 1.15 mrg
443 1.32 lukem # NFS exports shouldn't be globally exported
444 1.32 lukem #
445 1.32 lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
446 1.32 lukem awk '{
447 1.22 lukem # ignore comments and blank lines
448 1.39 hubertf if ($0 ~ /^\#/ || $0 ~ /^$/ )
449 1.22 lukem next;
450 1.22 lukem
451 1.15 mrg readonly = 0;
452 1.15 mrg for (i = 2; i <= NF; ++i) {
453 1.15 mrg if ($i ~ /-ro/)
454 1.15 mrg readonly = 1;
455 1.15 mrg else if ($i !~ /^-/)
456 1.15 mrg next;
457 1.15 mrg }
458 1.15 mrg if (readonly)
459 1.15 mrg print "File system " $1 " globally exported, read-only."
460 1.15 mrg else
461 1.15 mrg print "File system " $1 " globally exported, read-write."
462 1.32 lukem }' < /etc/exports > $OUTPUT
463 1.32 lukem if [ -s $OUTPUT ] ; then
464 1.15 mrg printf "\nChecking for globally exported file systems.\n"
465 1.15 mrg cat $OUTPUT
466 1.15 mrg fi
467 1.9 cgd fi
468 1.9 cgd
469 1.9 cgd # Display any changes in setuid files and devices.
470 1.32 lukem #
471 1.31 lukem if checkyesno check_devices; then
472 1.28 lukem > $ERR
473 1.15 mrg (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
474 1.15 mrg -o -fstype procfs \) -a -prune -o \
475 1.21 mycroft \( \( -perm -u+s -a ! -type d \) -o \
476 1.21 mycroft \( -perm -g+s -a ! -type d \) -o \
477 1.24 lukem -type b -o -type c \) -print0 | \
478 1.24 lukem xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
479 1.15 mrg
480 1.15 mrg # Display any errors that occurred during system file walk.
481 1.15 mrg if [ -s $OUTPUT ] ; then
482 1.28 lukem printf "Setuid/device find errors:\n" >> $ERR
483 1.28 lukem cat $OUTPUT >> $ERR
484 1.28 lukem printf "\n" >> $ERR
485 1.15 mrg fi
486 1.15 mrg
487 1.15 mrg # Display any changes in the setuid file list.
488 1.15 mrg egrep -v '^[bc]' $LIST > $TMP1
489 1.15 mrg if [ -s $TMP1 ] ; then
490 1.15 mrg # Check to make sure uudecode isn't setuid.
491 1.15 mrg if grep -w uudecode $TMP1 > /dev/null ; then
492 1.28 lukem printf "\nUudecode is setuid.\n" >> $ERR
493 1.15 mrg fi
494 1.15 mrg
495 1.48 abs CUR=$backup_dir/setuid.current
496 1.48 abs BACK=$backup_dir/setuid.backup
497 1.9 cgd
498 1.15 mrg if [ -s $CUR ] ; then
499 1.15 mrg if cmp -s $CUR $TMP1 ; then
500 1.15 mrg :
501 1.15 mrg else
502 1.15 mrg > $TMP2
503 1.15 mrg join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
504 1.15 mrg if [ -s $OUTPUT ] ; then
505 1.28 lukem printf "Setuid additions:\n" >> $ERR
506 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
507 1.28 lukem printf "\n" >> $ERR
508 1.15 mrg fi
509 1.15 mrg
510 1.15 mrg join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
511 1.15 mrg if [ -s $OUTPUT ] ; then
512 1.28 lukem printf "Setuid deletions:\n" >> $ERR
513 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
514 1.28 lukem printf "\n" >> $ERR
515 1.15 mrg fi
516 1.15 mrg
517 1.20 mycroft sort -k10 $TMP2 $CUR $TMP1 | \
518 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
519 1.27 lukem uniq -u > $OUTPUT
520 1.15 mrg if [ -s $OUTPUT ] ; then
521 1.28 lukem printf "Setuid changes:\n" >> $ERR
522 1.28 lukem column -t $OUTPUT >> $ERR
523 1.28 lukem printf "\n" >> $ERR
524 1.15 mrg fi
525 1.9 cgd
526 1.52 atatat backup_file update $TMP1 $CUR $BACK
527 1.9 cgd fi
528 1.15 mrg else
529 1.28 lukem printf "Setuid additions:\n" >> $ERR
530 1.28 lukem column -t $TMP1 >> $ERR
531 1.28 lukem printf "\n" >> $ERR
532 1.52 atatat backup_file add $TMP1 $CUR $BACK
533 1.9 cgd fi
534 1.15 mrg fi
535 1.15 mrg
536 1.27 lukem # Check for block and character disk devices that are readable or
537 1.27 lukem # writeable or not owned by root.operator.
538 1.15 mrg >$TMP1
539 1.61 lukem DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \
540 1.57 simonb sd se ss uk up vnd wd xd xy"
541 1.27 lukem # DISKLIST="$DISKLIST ct mt st wt"
542 1.15 mrg for i in $DISKLIST; do
543 1.15 mrg egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
544 1.15 mrg egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
545 1.15 mrg done
546 1.15 mrg
547 1.15 mrg awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
548 1.25 lukem { printf "Disk %s is user %s, group %s, permissions %s.\n", \
549 1.25 lukem $11, $3, $4, $1; }' < $TMP1 > $OUTPUT
550 1.15 mrg if [ -s $OUTPUT ] ; then
551 1.28 lukem printf "\nChecking disk ownership and permissions.\n" >> $ERR
552 1.28 lukem cat $OUTPUT >> $ERR
553 1.28 lukem printf "\n" >> $ERR
554 1.9 cgd fi
555 1.9 cgd
556 1.15 mrg # Display any changes in the device file list.
557 1.20 mycroft egrep '^[bc]' $LIST | sort -k11 > $TMP1
558 1.15 mrg if [ -s $TMP1 ] ; then
559 1.48 abs CUR=$backup_dir/device.current
560 1.48 abs BACK=$backup_dir/device.backup
561 1.15 mrg
562 1.15 mrg if [ -s $CUR ] ; then
563 1.15 mrg if cmp -s $CUR $TMP1 ; then
564 1.15 mrg :
565 1.15 mrg else
566 1.15 mrg > $TMP2
567 1.15 mrg join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
568 1.15 mrg if [ -s $OUTPUT ] ; then
569 1.28 lukem printf "Device additions:\n" >> $ERR
570 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
571 1.28 lukem printf "\n" >> $ERR
572 1.15 mrg fi
573 1.15 mrg
574 1.15 mrg join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
575 1.15 mrg if [ -s $OUTPUT ] ; then
576 1.28 lukem printf "Device deletions:\n" >> $ERR
577 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
578 1.28 lukem printf "\n" >> $ERR
579 1.15 mrg fi
580 1.15 mrg
581 1.27 lukem # Report any block device change. Ignore
582 1.27 lukem # character devices, only the name is
583 1.27 lukem # significant.
584 1.15 mrg cat $TMP2 $CUR $TMP1 | \
585 1.27 lukem sed -e '/^c/d' | \
586 1.27 lukem sort -k11 | \
587 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
588 1.27 lukem uniq -u > $OUTPUT
589 1.15 mrg if [ -s $OUTPUT ] ; then
590 1.28 lukem printf "Block device changes:\n" >> $ERR
591 1.28 lukem column -t $OUTPUT >> $ERR
592 1.28 lukem printf "\n" >> $ERR
593 1.15 mrg fi
594 1.9 cgd
595 1.52 atatat backup_file update $TMP1 $CUR $BACK
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.52 atatat backup_file add $TMP1 $CUR $BACK >> $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.58 perry mtree -e -l -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.52 atatat egrep -v '\.(backup|current)(,v)?$' > $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.52 atatat egrep -v '\.(backup|current)(,v)?$' >> $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.54 atatat # old changelist backup names
682 1.54 atatat OCUR=$backup_dir/${file##*/}.current
683 1.54 atatat OBACK=$backup_dir/${file##*/}.backup
684 1.54 atatat # new changelist backup names
685 1.54 atatat CUR=$backup_dir$file.current
686 1.54 atatat BACK=$backup_dir$file.backup
687 1.54 atatat # roll over old backups
688 1.54 atatat if [ ! -d ${CUR%/*} ]; then
689 1.54 atatat mkdir -p ${CUR%/*}
690 1.54 atatat fi
691 1.54 atatat if [ -f $OCUR -a ! -f $CUR ]; then
692 1.54 atatat mv $OCUR $CUR
693 1.54 atatat fi
694 1.54 atatat if [ -f $OCUR,v -a ! -f $CUR,v ]; then
695 1.54 atatat mv $OCUR,v $CUR,v
696 1.54 atatat fi
697 1.54 atatat if [ -f $OBACK -a ! -f $BACK ]; then
698 1.54 atatat mv $OBACK $BACK
699 1.54 atatat fi
700 1.54 atatat # and down to work
701 1.30 mycroft if [ -f $file ]; then
702 1.30 mycroft if [ -f $CUR ] ; then
703 1.9 cgd diff $CUR $file > $OUTPUT
704 1.9 cgd if [ -s $OUTPUT ] ; then
705 1.9 cgd printf "\n======\n%s diffs (OLD < > NEW)\n======\n" $file
706 1.9 cgd cat $OUTPUT
707 1.52 atatat backup_file update $file $CUR $BACK
708 1.9 cgd fi
709 1.9 cgd else
710 1.30 mycroft printf "\n======\n%s added\n======\n" $file
711 1.30 mycroft diff /dev/null $file
712 1.52 atatat backup_file add $file $CUR $BACK
713 1.30 mycroft fi
714 1.30 mycroft else
715 1.30 mycroft if [ -f $CUR ]; then
716 1.30 mycroft printf "\n======\n%s removed\n======\n" $file
717 1.30 mycroft diff $CUR /dev/null
718 1.52 atatat backup_file remove $file $CUR $BACK
719 1.9 cgd fi
720 1.9 cgd fi
721 1.9 cgd done
722 1.44 ad fi
723 1.44 ad
724 1.44 ad if [ -f /etc/security.local ]; then
725 1.44 ad echo ""
726 1.44 ad echo "Running /etc/security.local:"
727 1.44 ad . /etc/security.local
728 1.9 cgd fi
729