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