security revision 1.87 1 1.1 cgd #!/bin/sh -
2 1.1 cgd #
3 1.87 jhawk # $NetBSD: security,v 1.87 2003/11/19 20:28:19 jhawk 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.64 cjs TZ=UTC; export TZ
18 1.1 cgd
19 1.15 mrg if [ -s /etc/security.conf ]; then
20 1.15 mrg . /etc/security.conf
21 1.15 mrg fi
22 1.15 mrg
23 1.67 lukem # Set reasonable defaults (if they're not set in security.conf)
24 1.67 lukem #
25 1.67 lukem backup_dir=${backup_dir:-/var/backups}
26 1.67 lukem pkgdb_dir=${pkgdb_dir:-/var/db/pkg}
27 1.67 lukem max_loginlen=${max_loginlen:-8}
28 1.67 lukem max_grouplen=${max_grouplen:-8}
29 1.67 lukem
30 1.67 lukem # Other configurable variables
31 1.67 lukem #
32 1.67 lukem special_files="/etc/mtree/special /etc/mtree/special.local"
33 1.67 lukem MP=/etc/master.passwd
34 1.67 lukem CHANGELIST=""
35 1.67 lukem work_dir=$backup_dir/work
36 1.67 lukem
37 1.67 lukem if [ ! -d "$work_dir" ]; then
38 1.67 lukem mkdir -p "$work_dir"
39 1.67 lukem fi
40 1.67 lukem
41 1.56 lukem SECUREDIR=`mktemp -d /tmp/_securedir.XXXXXX` || exit 1
42 1.56 lukem
43 1.67 lukem trap "/bin/rm -rf $SECUREDIR ; exit 0" EXIT INT QUIT PIPE
44 1.15 mrg
45 1.56 lukem if ! cd "$SECUREDIR"; then
46 1.56 lukem echo "Can not cd to $SECUREDIR".
47 1.15 mrg exit 1
48 1.15 mrg fi
49 1.15 mrg
50 1.15 mrg ERR=secure1.$$
51 1.15 mrg TMP1=secure2.$$
52 1.15 mrg TMP2=secure3.$$
53 1.28 lukem MPBYUID=secure4.$$
54 1.29 lukem MPBYPATH=secure5.$$
55 1.27 lukem LIST=secure6.$$
56 1.27 lukem OUTPUT=secure7.$$
57 1.32 lukem LABELS=secure8.$$
58 1.62 atatat PKGS=secure9.$$
59 1.67 lukem CHANGEFILES=secure10.$$
60 1.67 lukem
61 1.15 mrg
62 1.67 lukem # migrate_file old new
63 1.67 lukem # Determine if the "${old}" path name needs to be migrated to the
64 1.67 lukem # "${new}" path. Also checks if "${old}.current" needs migrating,
65 1.67 lukem # and if so, migrate it and possibly "${old}.current,v" and
66 1.67 lukem # "${old}.backup".
67 1.67 lukem #
68 1.67 lukem migrate_file()
69 1.67 lukem {
70 1.67 lukem _old=$1
71 1.67 lukem _new=$2
72 1.67 lukem if [ -z "$_old" -o -z "$_new" ]; then
73 1.67 lukem err 3 "USAGE: migrate_file old new"
74 1.67 lukem fi
75 1.67 lukem if [ ! -d "${_new%/*}" ]; then
76 1.67 lukem mkdir -p "${_new%/*}"
77 1.67 lukem fi
78 1.67 lukem if [ -f "${_old}" -a ! -f "${_new}" ]; then
79 1.67 lukem echo "==> migrating ${_old}"
80 1.67 lukem echo " to ${_new}"
81 1.67 lukem mv "${_old}" "${_new}"
82 1.67 lukem fi
83 1.67 lukem if [ -f "${_old}.current" -a ! -f "${_new}.current" ]; then
84 1.67 lukem echo "==> migrating ${_old}.current"
85 1.67 lukem echo " to ${_new}.current"
86 1.67 lukem mv "${_old}.current" "${_new}.current"
87 1.67 lukem if [ -f "${_old}.current,v" -a ! -f "${_new}.current,v" ]; then
88 1.67 lukem echo "==> migrating ${_old}.current,v"
89 1.67 lukem echo " to ${_new}.current,v"
90 1.67 lukem mv "${_old}.current,v" "${_new}.current,v"
91 1.67 lukem fi
92 1.67 lukem if [ -f "${_old}.backup" -a ! -f "${_new}.backup" ]; then
93 1.67 lukem echo "==> migrating ${_old}.backup"
94 1.67 lukem echo " to ${_new}.backup"
95 1.67 lukem mv "${_old}.backup" "${_new}.backup"
96 1.67 lukem fi
97 1.67 lukem fi
98 1.67 lukem }
99 1.67 lukem
100 1.67 lukem
101 1.67 lukem # backup_and_diff file printdiff
102 1.67 lukem # Determine if file needs backing up, and if so, do it.
103 1.67 lukem # If printdiff is yes, display the diffs, otherwise
104 1.67 lukem # just print a message saying "[changes omitted]".
105 1.67 lukem #
106 1.67 lukem backup_and_diff()
107 1.67 lukem {
108 1.67 lukem _file=$1
109 1.67 lukem _printdiff=$2
110 1.67 lukem if [ -z "$_file" -o -z "$_printdiff" ]; then
111 1.67 lukem err 3 "USAGE: backup_and_diff file printdiff"
112 1.67 lukem fi
113 1.67 lukem ! checkyesno _printdiff
114 1.67 lukem _printdiff=$?
115 1.67 lukem
116 1.67 lukem _old=$backup_dir/${_file##*/}
117 1.67 lukem case "$_file" in
118 1.67 lukem $work_dir/*)
119 1.67 lukem _new=$_file
120 1.67 lukem migrate_file "$backup_dir/$_old" "$_new"
121 1.67 lukem migrate_file "$_old" "$_new"
122 1.67 lukem ;;
123 1.67 lukem *)
124 1.67 lukem _new=$backup_dir/$_file
125 1.67 lukem migrate_file "$_old" "$_new"
126 1.67 lukem ;;
127 1.67 lukem esac
128 1.67 lukem CUR=${_new}.current
129 1.67 lukem BACK=${_new}.backup
130 1.67 lukem if [ -f $_file ]; then
131 1.67 lukem if [ -f $CUR ] ; then
132 1.67 lukem if [ "$_printdiff" -ne 0 ]; then
133 1.83 jhawk diff ${diff_options} $CUR $_file > $OUTPUT
134 1.67 lukem else
135 1.67 lukem if ! cmp -s $CUR $_file; then
136 1.67 lukem echo "[changes omitted]"
137 1.67 lukem fi > $OUTPUT
138 1.67 lukem fi
139 1.67 lukem if [ -s $OUTPUT ] ; then
140 1.67 lukem printf \
141 1.67 lukem "\n======\n%s diffs (OLD < > NEW)\n======\n" $_file
142 1.67 lukem cat $OUTPUT
143 1.67 lukem backup_file update $_file $CUR $BACK
144 1.67 lukem fi
145 1.67 lukem else
146 1.67 lukem printf "\n======\n%s added\n======\n" $_file
147 1.67 lukem if [ "$_printdiff" -ne 0 ]; then
148 1.83 jhawk diff ${diff_options} /dev/null $_file
149 1.67 lukem else
150 1.67 lukem echo "[changes omitted]"
151 1.67 lukem fi
152 1.67 lukem backup_file add $_file $CUR $BACK
153 1.67 lukem fi
154 1.67 lukem else
155 1.67 lukem if [ -f $CUR ]; then
156 1.67 lukem printf "\n======\n%s removed\n======\n" $_file
157 1.67 lukem if [ "$_printdiff" -ne 0 ]; then
158 1.83 jhawk diff ${diff_options} $CUR /dev/null
159 1.67 lukem else
160 1.67 lukem echo "[changes omitted]"
161 1.67 lukem fi
162 1.67 lukem backup_file remove $_file $CUR $BACK
163 1.67 lukem fi
164 1.67 lukem fi
165 1.67 lukem }
166 1.48 abs
167 1.9 cgd
168 1.67 lukem # These are used several times.
169 1.67 lukem #
170 1.34 abs awk -F: '!/^+/ { print $1 " " $3 }' $MP | sort -k2n > $MPBYUID
171 1.29 lukem awk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH
172 1.9 cgd
173 1.67 lukem
174 1.9 cgd # Check the master password file syntax.
175 1.32 lukem #
176 1.31 lukem if checkyesno check_passwd; then
177 1.85 jhawk # XXX: the sense of permit_star is reversed; the code works as
178 1.85 jhawk # implemented, but usage needs to be negated.
179 1.81 jhawk checkyesno check_passwd_permit_star && permit_star=0 || permit_star=1
180 1.81 jhawk awk -v "len=$max_loginlen" \
181 1.81 jhawk -v "nowarn_shells_list=$check_passwd_nowarn_shells" \
182 1.81 jhawk -v "nowarn_users_list=$check_passwd_nowarn_users" \
183 1.81 jhawk -v "permit_star=$permit_star" '
184 1.25 lukem BEGIN {
185 1.25 lukem while ( getline < "/etc/shells" > 0 ) {
186 1.39 hubertf if ($0 ~ /^\#/ || $0 ~ /^$/ )
187 1.25 lukem continue;
188 1.25 lukem shells[$1]++;
189 1.25 lukem }
190 1.81 jhawk split(nowarn_shells_list, a);
191 1.81 jhawk for (i in a) nowarn_shells[a[i]]++;
192 1.81 jhawk split(nowarn_users_list, a);
193 1.81 jhawk for (i in a) nowarn_users[a[i]]++;
194 1.81 jhawk uid0_users_list="root toor"
195 1.81 jhawk split(uid0_users_list, a);
196 1.81 jhawk for (i in a) uid0_users[a[i]]++;
197 1.25 lukem FS=":";
198 1.25 lukem }
199 1.25 lukem
200 1.25 lukem {
201 1.15 mrg if ($0 ~ /^[ ]*$/) {
202 1.25 lukem printf "Line %d is a blank line.\n", NR;
203 1.15 mrg next;
204 1.15 mrg }
205 1.34 abs if (NF != 10 && ($1 != "+" || NF != 1))
206 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
207 1.34 abs if ($1 == "+" ) {
208 1.34 abs if (NF != 1 && $3 == 0)
209 1.81 jhawk printf "Line %d includes entries with uid 0.\n",
210 1.81 jhawk NR;
211 1.34 abs next;
212 1.34 abs }
213 1.53 atatat if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
214 1.25 lukem printf "Login %s has non-alphanumeric characters.\n",
215 1.25 lukem $1;
216 1.34 abs if (length($1) > len)
217 1.81 jhawk printf "Login %s has more than "len" characters.\n",
218 1.81 jhawk $1;
219 1.81 jhawk if ($2 == "" && !nowarn_users[$1])
220 1.81 jhawk printf "Login %s has no password.\n", $1;
221 1.81 jhawk if (!nowarn_shells[$10] && !nowarn_users[$1]) {
222 1.81 jhawk if (length($2) != 13 &&
223 1.81 jhawk length($2) != 20 &&
224 1.81 jhawk $2 !~ /^\$1/ &&
225 1.81 jhawk $2 !~ /^\$2/ &&
226 1.81 jhawk $2 != "" &&
227 1.81 jhawk (permit_star || $2 != "*") &&
228 1.81 jhawk $2 !~ /^\*[A-z-]+$/ &&
229 1.81 jhawk $1 != "toor") {
230 1.81 jhawk if ($10 == "" || shells[$10])
231 1.81 jhawk printf "Login %s is off but still has "\
232 1.81 jhawk "a valid shell (%s)\n", $1, $10;
233 1.81 jhawk } else if (! shells[$10])
234 1.81 jhawk printf "Login %s does not have a valid "\
235 1.81 jhawk "shell (%s)\n", $1, $10;
236 1.81 jhawk }
237 1.81 jhawk if ($3 == 0 && !uid0_users[$1] && !nowarn_users[$1])
238 1.25 lukem printf "Login %s has a user id of 0.\n", $1;
239 1.15 mrg if ($3 < 0)
240 1.25 lukem printf "Login %s has a negative user id.\n", $1;
241 1.15 mrg if ($4 < 0)
242 1.25 lukem printf "Login %s has a negative group id.\n", $1;
243 1.15 mrg }' < $MP > $OUTPUT
244 1.15 mrg if [ -s $OUTPUT ] ; then
245 1.15 mrg printf "\nChecking the $MP file:\n"
246 1.15 mrg cat $OUTPUT
247 1.15 mrg fi
248 1.15 mrg
249 1.15 mrg awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT
250 1.15 mrg if [ -s $OUTPUT ] ; then
251 1.15 mrg printf "\n$MP has duplicate user names.\n"
252 1.15 mrg column $OUTPUT
253 1.15 mrg fi
254 1.15 mrg
255 1.37 wrstuden # To not exclude 'toor', a standard duplicate root account, from the duplicate
256 1.37 wrstuden # account test, uncomment the line below (without egrep in it)and comment
257 1.37 wrstuden # out the line (with egrep in it) below it.
258 1.37 wrstuden #
259 1.37 wrstuden # < $MPBYUID uniq -d -f 1 | awk '{ print $2 }' > $TMP2
260 1.36 wrstuden < $MPBYUID egrep -v '^toor ' | uniq -d -f 1 | awk '{ print $2 }' > $TMP2
261 1.15 mrg if [ -s $TMP2 ] ; then
262 1.15 mrg printf "\n$MP has duplicate user id's.\n"
263 1.15 mrg while read uid; do
264 1.28 lukem grep -w $uid $MPBYUID
265 1.15 mrg done < $TMP2 | column
266 1.15 mrg fi
267 1.9 cgd fi
268 1.9 cgd
269 1.9 cgd # Check the group file syntax.
270 1.32 lukem #
271 1.31 lukem if checkyesno check_group; then
272 1.15 mrg GRP=/etc/group
273 1.49 jdolecek awk -F: -v "len=$max_grouplen" '{
274 1.15 mrg if ($0 ~ /^[ ]*$/) {
275 1.25 lukem printf "Line %d is a blank line.\n", NR;
276 1.15 mrg next;
277 1.15 mrg }
278 1.34 abs if (NF != 4 && ($1 != "+" || NF != 1))
279 1.25 lukem printf "Line %d has the wrong number of fields.\n", NR;
280 1.34 abs if ($1 == "+" ) {
281 1.34 abs next;
282 1.34 abs }
283 1.53 atatat if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
284 1.25 lukem printf "Group %s has non-alphanumeric characters.\n",
285 1.25 lukem $1;
286 1.49 jdolecek if (length($1) > len)
287 1.49 jdolecek printf "Group %s has more than "len" characters.\n", $1;
288 1.15 mrg if ($3 !~ /[0-9]*/)
289 1.25 lukem printf "Login %s has a negative group id.\n", $1;
290 1.15 mrg }' < $GRP > $OUTPUT
291 1.15 mrg if [ -s $OUTPUT ] ; then
292 1.15 mrg printf "\nChecking the $GRP file:\n"
293 1.15 mrg cat $OUTPUT
294 1.15 mrg fi
295 1.15 mrg
296 1.15 mrg awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT
297 1.15 mrg if [ -s $OUTPUT ] ; then
298 1.15 mrg printf "\n$GRP has duplicate group names.\n"
299 1.15 mrg column $OUTPUT
300 1.15 mrg fi
301 1.9 cgd fi
302 1.9 cgd
303 1.9 cgd # Check for root paths, umask values in startup files.
304 1.9 cgd # The check for the root paths is problematical -- it's likely to fail
305 1.9 cgd # in other environments. Once the shells have been modified to warn
306 1.9 cgd # of '.' in the path, the path tests should go away.
307 1.32 lukem #
308 1.31 lukem if checkyesno check_rootdotfiles; then
309 1.67 lukem rhome=~root
310 1.15 mrg umaskset=no
311 1.15 mrg list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login"
312 1.15 mrg for i in $list ; do
313 1.15 mrg if [ -f $i ] ; then
314 1.67 lukem if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ;
315 1.67 lukem then
316 1.15 mrg umaskset=yes
317 1.15 mrg fi
318 1.63 lukem # Double check the umask value itself; ensure that
319 1.67 lukem # both the group and other write bits are set.
320 1.67 lukem #
321 1.45 sommerfe egrep '^[ \t]*umask[ \t]+[0-7]+' $i |
322 1.63 lukem awk '{
323 1.67 lukem if ($2 ~ /^.$/ || $2 ~! /[^2367].$/) {
324 1.80 wiz print "\tRoot umask is group writable"
325 1.63 lukem }
326 1.67 lukem if ($2 ~ /[^2367]$/) {
327 1.80 wiz print "\tRoot umask is other writable"
328 1.63 lukem }
329 1.67 lukem }' | sort -u
330 1.26 lukem SAVE_PATH=$PATH
331 1.26 lukem unset PATH
332 1.15 mrg /bin/csh -f -s << end-of-csh > /dev/null 2>&1
333 1.15 mrg source $i
334 1.15 mrg /bin/ls -ldgT \$path > $TMP1
335 1.9 cgd end-of-csh
336 1.76 atatat export PATH=$SAVE_PATH
337 1.15 mrg awk '{
338 1.15 mrg if ($10 ~ /^\.$/) {
339 1.27 lukem print "\tThe root path includes .";
340 1.15 mrg next;
341 1.15 mrg }
342 1.15 mrg }
343 1.15 mrg $1 ~ /^d....w/ \
344 1.80 wiz { print "\tRoot path directory " $10 " is group writable." } \
345 1.15 mrg $1 ~ /^d.......w/ \
346 1.80 wiz { print "\tRoot path directory " $10 " is other writable." }' \
347 1.67 lukem < $TMP1
348 1.15 mrg fi
349 1.67 lukem done > $OUTPUT
350 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
351 1.27 lukem printf "\nChecking root csh paths, umask values:\n$list\n\n"
352 1.15 mrg if [ -s $OUTPUT ]; then
353 1.15 mrg cat $OUTPUT
354 1.15 mrg fi
355 1.15 mrg if [ $umaskset = "no" ] ; then
356 1.27 lukem printf "\tRoot csh startup files do not set the umask.\n"
357 1.15 mrg fi
358 1.9 cgd fi
359 1.9 cgd
360 1.15 mrg umaskset=no
361 1.23 lukem list="/etc/profile ${rhome}/.profile"
362 1.15 mrg for i in $list; do
363 1.15 mrg if [ -f $i ] ; then
364 1.15 mrg if egrep umask $i > /dev/null ; then
365 1.15 mrg umaskset=yes
366 1.15 mrg fi
367 1.15 mrg egrep umask $i |
368 1.67 lukem awk '$2 ~ /^.$/ || $2 ~ /[^2367].$/ \
369 1.80 wiz { print "\tRoot umask is group writable" } \
370 1.67 lukem $2 ~ /[^2367]$/ \
371 1.80 wiz { print "\tRoot umask is other writable" }'
372 1.26 lukem SAVE_PATH=$PATH
373 1.26 lukem unset PATH
374 1.15 mrg /bin/sh << end-of-sh > /dev/null 2>&1
375 1.15 mrg . $i
376 1.26 lukem list=\`echo \$PATH | /usr/bin/sed -e \
377 1.26 lukem 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g'\`
378 1.15 mrg /bin/ls -ldgT \$list > $TMP1
379 1.9 cgd end-of-sh
380 1.76 atatat export PATH=$SAVE_PATH
381 1.15 mrg awk '{
382 1.15 mrg if ($10 ~ /^\.$/) {
383 1.27 lukem print "\tThe root path includes .";
384 1.15 mrg next;
385 1.15 mrg }
386 1.15 mrg }
387 1.15 mrg $1 ~ /^d....w/ \
388 1.80 wiz { print "\tRoot path directory " $10 " is group writable." } \
389 1.15 mrg $1 ~ /^d.......w/ \
390 1.80 wiz { print "\tRoot path directory " $10 " is other writable." }' \
391 1.67 lukem < $TMP1
392 1.9 cgd
393 1.15 mrg fi
394 1.67 lukem done > $OUTPUT
395 1.15 mrg if [ $umaskset = "no" -o -s $OUTPUT ] ; then
396 1.15 mrg printf "\nChecking root sh paths, umask values:\n$list\n"
397 1.15 mrg if [ -s $OUTPUT ]; then
398 1.15 mrg cat $OUTPUT
399 1.15 mrg fi
400 1.15 mrg if [ $umaskset = "no" ] ; then
401 1.27 lukem printf "\tRoot sh startup files do not set the umask.\n"
402 1.15 mrg fi
403 1.9 cgd fi
404 1.9 cgd fi
405 1.9 cgd
406 1.9 cgd # Root and uucp should both be in /etc/ftpusers.
407 1.32 lukem #
408 1.31 lukem if checkyesno check_ftpusers; then
409 1.28 lukem list="uucp "`awk '$2 == 0 { print $1 }' $MPBYUID`
410 1.27 lukem for i in $list; do
411 1.29 lukem if /usr/libexec/ftpd -C $i ; then
412 1.67 lukem printf "\t$i is not denied\n"
413 1.27 lukem fi
414 1.67 lukem done > $OUTPUT
415 1.28 lukem if [ -s $OUTPUT ]; then
416 1.28 lukem printf "\nChecking the /etc/ftpusers configuration:\n"
417 1.28 lukem cat $OUTPUT
418 1.28 lukem fi
419 1.9 cgd fi
420 1.9 cgd
421 1.43 itojun # Uudecode should not be in the /etc/mail/aliases file.
422 1.32 lukem #
423 1.31 lukem if checkyesno check_aliases; then
424 1.43 itojun for f in /etc/mail/aliases /etc/aliases; do
425 1.43 itojun if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then
426 1.43 itojun printf "\nEntry for uudecode in $f file.\n"
427 1.43 itojun fi
428 1.43 itojun done
429 1.9 cgd fi
430 1.9 cgd
431 1.9 cgd # Files that should not have + signs.
432 1.32 lukem #
433 1.31 lukem if checkyesno check_rhosts; then
434 1.15 mrg list="/etc/hosts.equiv /etc/hosts.lpd"
435 1.15 mrg for f in $list ; do
436 1.15 mrg if [ -f $f ] && egrep '\+' $f > /dev/null ; then
437 1.15 mrg printf "\nPlus sign in $f file.\n"
438 1.15 mrg fi
439 1.15 mrg done
440 1.15 mrg
441 1.15 mrg # Check for special users with .rhosts files. Only root and toor should
442 1.16 mikel # have .rhosts files. Also, .rhosts files should not have plus signs.
443 1.15 mrg awk -F: '$1 != "root" && $1 != "toor" && \
444 1.15 mrg ($3 < 100 || $1 == "ftp" || $1 == "uucp") \
445 1.20 mycroft { print $1 " " $9 }' $MP |
446 1.19 mycroft sort -k2 |
447 1.15 mrg while read uid homedir; do
448 1.15 mrg if [ -f ${homedir}/.rhosts ] ; then
449 1.15 mrg rhost=`ls -ldgT ${homedir}/.rhosts`
450 1.46 christos printf -- "$uid: $rhost\n"
451 1.15 mrg fi
452 1.15 mrg done > $OUTPUT
453 1.15 mrg if [ -s $OUTPUT ] ; then
454 1.15 mrg printf "\nChecking for special users with .rhosts files.\n"
455 1.15 mrg cat $OUTPUT
456 1.15 mrg fi
457 1.15 mrg
458 1.15 mrg while read uid homedir; do
459 1.35 fair if [ -f ${homedir}/.rhosts -a -r ${homedir}/.rhosts ] && \
460 1.41 christos cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null ; then
461 1.46 christos printf -- "$uid: + in .rhosts file.\n"
462 1.15 mrg fi
463 1.29 lukem done < $MPBYPATH > $OUTPUT
464 1.15 mrg if [ -s $OUTPUT ] ; then
465 1.15 mrg printf "\nChecking .rhosts files syntax.\n"
466 1.15 mrg cat $OUTPUT
467 1.15 mrg fi
468 1.9 cgd fi
469 1.9 cgd
470 1.9 cgd # Check home directories. Directories should not be owned by someone else
471 1.80 wiz # or writable.
472 1.32 lukem #
473 1.31 lukem if checkyesno check_homes; then
474 1.85 jhawk checkyesno check_homes_permit_usergroups && \
475 1.85 jhawk permit_usergroups=1 || permit_usergroups=0
476 1.15 mrg while read uid homedir; do
477 1.15 mrg if [ -d ${homedir}/ ] ; then
478 1.15 mrg file=`ls -ldgT ${homedir}`
479 1.46 christos printf -- "$uid $file\n"
480 1.9 cgd fi
481 1.29 lukem done < $MPBYPATH |
482 1.85 jhawk awk -v "usergroups=$permit_usergroups" '
483 1.85 jhawk $1 != $4 && $4 != "root" \
484 1.15 mrg { print "user " $1 " home directory is owned by " $4 }
485 1.85 jhawk $2 ~ /^-....w/ (!usergroups || $5 != $1) \
486 1.80 wiz { print "user " $1 " home directory is group writable" }
487 1.15 mrg $2 ~ /^-.......w/ \
488 1.80 wiz { print "user " $1 " home directory is other writable" }' \
489 1.27 lukem > $OUTPUT
490 1.15 mrg if [ -s $OUTPUT ] ; then
491 1.15 mrg printf "\nChecking home directories.\n"
492 1.15 mrg cat $OUTPUT
493 1.15 mrg fi
494 1.15 mrg
495 1.15 mrg # Files that should not be owned by someone else or readable.
496 1.67 lukem list=".Xauthority .netrc .ssh/id_dsa .ssh/id_rsa .ssh/identity"
497 1.15 mrg while read uid homedir; do
498 1.15 mrg for f in $list ; do
499 1.15 mrg file=${homedir}/${f}
500 1.15 mrg if [ -f $file ] ; then
501 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
502 1.15 mrg fi
503 1.15 mrg done
504 1.29 lukem done < $MPBYPATH |
505 1.85 jhawk awk -v "usergroups=$permit_usergroups" '
506 1.85 jhawk $1 != $5 && $5 != "root" \
507 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
508 1.85 jhawk $3 ~ /^-...r/ && (!usergroups || $6 != $1) \
509 1.15 mrg { print "user " $1 " " $2 " file is group readable" }
510 1.15 mrg $3 ~ /^-......r/ \
511 1.15 mrg { print "user " $1 " " $2 " file is other readable" }
512 1.85 jhawk $3 ~ /^-....w/ && (!usergroups || $6 != $1) \
513 1.80 wiz { print "user " $1 " " $2 " file is group writable" }
514 1.15 mrg $3 ~ /^-.......w/ \
515 1.80 wiz { print "user " $1 " " $2 " file is other writable" }' \
516 1.27 lukem > $OUTPUT
517 1.15 mrg
518 1.80 wiz # Files that should not be owned by someone else or writable.
519 1.19 mycroft list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \
520 1.79 elric .cshrc .emacs .exrc .forward .history .k5login .klogin .login \
521 1.79 elric .logout .profile .qmail .rc_history .rhosts .shosts ssh .tcshrc \
522 1.79 elric .twmrc .xinitrc .xsession .ssh/authorized_keys \
523 1.79 elric .ssh/authorized_keys2 .ssh/config .ssh/id_dsa.pub \
524 1.79 elric .ssh/id_rsa.pub .ssh/identity.pub .ssh/known_hosts \
525 1.79 elric .ssh/known_hosts2"
526 1.15 mrg while read uid homedir; do
527 1.15 mrg for f in $list ; do
528 1.15 mrg file=${homedir}/${f}
529 1.15 mrg if [ -f $file ] ; then
530 1.46 christos printf -- "$uid $f `ls -ldgT $file`\n"
531 1.15 mrg fi
532 1.15 mrg done
533 1.29 lukem done < $MPBYPATH |
534 1.85 jhawk awk -v "usergroups=$permit_usergroups" '
535 1.85 jhawk $1 != $5 && $5 != "root" \
536 1.15 mrg { print "user " $1 " " $2 " file is owned by " $5 }
537 1.85 jhawk $3 ~ /^-....w/ && (!usergroups || $6 != $1) \
538 1.80 wiz { print "user " $1 " " $2 " file is group writable" }
539 1.15 mrg $3 ~ /^-.......w/ \
540 1.80 wiz { print "user " $1 " " $2 " file is other writable" }' \
541 1.27 lukem >> $OUTPUT
542 1.15 mrg if [ -s $OUTPUT ] ; then
543 1.15 mrg printf "\nChecking dot files.\n"
544 1.15 mrg cat $OUTPUT
545 1.15 mrg fi
546 1.9 cgd fi
547 1.9 cgd
548 1.9 cgd # Mailboxes should be owned by user and unreadable.
549 1.32 lukem #
550 1.31 lukem if checkyesno check_varmail; then
551 1.86 jhawk ls -lA /var/mail | \
552 1.63 lukem awk ' NR == 1 { next; }
553 1.86 jhawk $9 ~ /^\./ {next; }
554 1.63 lukem $3 != $9 {
555 1.63 lukem print "user " $9 " mailbox is owned by " $3
556 1.63 lukem }
557 1.63 lukem $1 != "-rw-------" {
558 1.63 lukem print "user " $9 " mailbox is " $1 ", group " $4
559 1.63 lukem }' > $OUTPUT
560 1.15 mrg if [ -s $OUTPUT ] ; then
561 1.15 mrg printf "\nChecking mailbox ownership.\n"
562 1.15 mrg cat $OUTPUT
563 1.15 mrg fi
564 1.15 mrg fi
565 1.15 mrg
566 1.32 lukem # NFS exports shouldn't be globally exported
567 1.32 lukem #
568 1.32 lukem if checkyesno check_nfs && [ -f /etc/exports ]; then
569 1.32 lukem awk '{
570 1.22 lukem # ignore comments and blank lines
571 1.39 hubertf if ($0 ~ /^\#/ || $0 ~ /^$/ )
572 1.22 lukem next;
573 1.22 lukem
574 1.15 mrg readonly = 0;
575 1.15 mrg for (i = 2; i <= NF; ++i) {
576 1.15 mrg if ($i ~ /-ro/)
577 1.15 mrg readonly = 1;
578 1.15 mrg else if ($i !~ /^-/)
579 1.15 mrg next;
580 1.15 mrg }
581 1.15 mrg if (readonly)
582 1.15 mrg print "File system " $1 " globally exported, read-only."
583 1.15 mrg else
584 1.15 mrg print "File system " $1 " globally exported, read-write."
585 1.32 lukem }' < /etc/exports > $OUTPUT
586 1.32 lukem if [ -s $OUTPUT ] ; then
587 1.15 mrg printf "\nChecking for globally exported file systems.\n"
588 1.15 mrg cat $OUTPUT
589 1.15 mrg fi
590 1.9 cgd fi
591 1.9 cgd
592 1.9 cgd # Display any changes in setuid files and devices.
593 1.32 lukem #
594 1.31 lukem if checkyesno check_devices; then
595 1.28 lukem > $ERR
596 1.15 mrg (find / \( ! -fstype local -o -fstype fdesc -o -fstype kernfs \
597 1.74 lukem -o -fstype null \
598 1.15 mrg -o -fstype procfs \) -a -prune -o \
599 1.21 mycroft \( \( -perm -u+s -a ! -type d \) -o \
600 1.21 mycroft \( -perm -g+s -a ! -type d \) -o \
601 1.24 lukem -type b -o -type c \) -print0 | \
602 1.24 lukem xargs -0 ls -ldgTq | sort +9 > $LIST) 2> $OUTPUT
603 1.15 mrg
604 1.15 mrg # Display any errors that occurred during system file walk.
605 1.15 mrg if [ -s $OUTPUT ] ; then
606 1.28 lukem printf "Setuid/device find errors:\n" >> $ERR
607 1.28 lukem cat $OUTPUT >> $ERR
608 1.28 lukem printf "\n" >> $ERR
609 1.15 mrg fi
610 1.15 mrg
611 1.15 mrg # Display any changes in the setuid file list.
612 1.15 mrg egrep -v '^[bc]' $LIST > $TMP1
613 1.15 mrg if [ -s $TMP1 ] ; then
614 1.15 mrg # Check to make sure uudecode isn't setuid.
615 1.15 mrg if grep -w uudecode $TMP1 > /dev/null ; then
616 1.28 lukem printf "\nUudecode is setuid.\n" >> $ERR
617 1.15 mrg fi
618 1.15 mrg
619 1.67 lukem file=$work_dir/setuid
620 1.67 lukem migrate_file "$backup_dir/setuid" "$file"
621 1.67 lukem CUR=${file}.current
622 1.67 lukem BACK=${file}.backup
623 1.15 mrg if [ -s $CUR ] ; then
624 1.15 mrg if cmp -s $CUR $TMP1 ; then
625 1.15 mrg :
626 1.15 mrg else
627 1.15 mrg > $TMP2
628 1.15 mrg join -110 -210 -v2 $CUR $TMP1 > $OUTPUT
629 1.15 mrg if [ -s $OUTPUT ] ; then
630 1.28 lukem printf "Setuid additions:\n" >> $ERR
631 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
632 1.28 lukem printf "\n" >> $ERR
633 1.15 mrg fi
634 1.15 mrg
635 1.15 mrg join -110 -210 -v1 $CUR $TMP1 > $OUTPUT
636 1.15 mrg if [ -s $OUTPUT ] ; then
637 1.28 lukem printf "Setuid deletions:\n" >> $ERR
638 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
639 1.28 lukem printf "\n" >> $ERR
640 1.15 mrg fi
641 1.15 mrg
642 1.20 mycroft sort -k10 $TMP2 $CUR $TMP1 | \
643 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
644 1.27 lukem uniq -u > $OUTPUT
645 1.15 mrg if [ -s $OUTPUT ] ; then
646 1.28 lukem printf "Setuid changes:\n" >> $ERR
647 1.28 lukem column -t $OUTPUT >> $ERR
648 1.28 lukem printf "\n" >> $ERR
649 1.15 mrg fi
650 1.9 cgd
651 1.52 atatat backup_file update $TMP1 $CUR $BACK
652 1.9 cgd fi
653 1.15 mrg else
654 1.28 lukem printf "Setuid additions:\n" >> $ERR
655 1.28 lukem column -t $TMP1 >> $ERR
656 1.28 lukem printf "\n" >> $ERR
657 1.52 atatat backup_file add $TMP1 $CUR $BACK
658 1.9 cgd fi
659 1.15 mrg fi
660 1.15 mrg
661 1.27 lukem # Check for block and character disk devices that are readable or
662 1.80 wiz # writable or not owned by root.operator.
663 1.15 mrg >$TMP1
664 1.61 lukem DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \
665 1.57 simonb sd se ss uk up vnd wd xd xy"
666 1.27 lukem # DISKLIST="$DISKLIST ct mt st wt"
667 1.15 mrg for i in $DISKLIST; do
668 1.15 mrg egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
669 1.15 mrg egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1
670 1.15 mrg done
671 1.15 mrg
672 1.15 mrg awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \
673 1.25 lukem { printf "Disk %s is user %s, group %s, permissions %s.\n", \
674 1.25 lukem $11, $3, $4, $1; }' < $TMP1 > $OUTPUT
675 1.15 mrg if [ -s $OUTPUT ] ; then
676 1.28 lukem printf "\nChecking disk ownership and permissions.\n" >> $ERR
677 1.28 lukem cat $OUTPUT >> $ERR
678 1.28 lukem printf "\n" >> $ERR
679 1.9 cgd fi
680 1.9 cgd
681 1.15 mrg # Display any changes in the device file list.
682 1.20 mycroft egrep '^[bc]' $LIST | sort -k11 > $TMP1
683 1.15 mrg if [ -s $TMP1 ] ; then
684 1.67 lukem file=$work_dir/device
685 1.67 lukem migrate_file "$backup_dir/device" "$file"
686 1.67 lukem CUR=${file}.current
687 1.67 lukem BACK=${file}.backup
688 1.15 mrg
689 1.15 mrg if [ -s $CUR ] ; then
690 1.15 mrg if cmp -s $CUR $TMP1 ; then
691 1.15 mrg :
692 1.15 mrg else
693 1.15 mrg > $TMP2
694 1.15 mrg join -111 -211 -v2 $CUR $TMP1 > $OUTPUT
695 1.15 mrg if [ -s $OUTPUT ] ; then
696 1.28 lukem printf "Device additions:\n" >> $ERR
697 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
698 1.28 lukem printf "\n" >> $ERR
699 1.15 mrg fi
700 1.15 mrg
701 1.15 mrg join -111 -211 -v1 $CUR $TMP1 > $OUTPUT
702 1.15 mrg if [ -s $OUTPUT ] ; then
703 1.28 lukem printf "Device deletions:\n" >> $ERR
704 1.28 lukem tee -a $TMP2 < $OUTPUT >> $ERR
705 1.28 lukem printf "\n" >> $ERR
706 1.15 mrg fi
707 1.15 mrg
708 1.27 lukem # Report any block device change. Ignore
709 1.27 lukem # character devices, only the name is
710 1.27 lukem # significant.
711 1.15 mrg cat $TMP2 $CUR $TMP1 | \
712 1.27 lukem sed -e '/^c/d' | \
713 1.27 lukem sort -k11 | \
714 1.27 lukem sed -e 's/[ ][ ]*/ /g' | \
715 1.27 lukem uniq -u > $OUTPUT
716 1.15 mrg if [ -s $OUTPUT ] ; then
717 1.28 lukem printf "Block device changes:\n" >> $ERR
718 1.28 lukem column -t $OUTPUT >> $ERR
719 1.28 lukem printf "\n" >> $ERR
720 1.15 mrg fi
721 1.9 cgd
722 1.52 atatat backup_file update $TMP1 $CUR $BACK
723 1.9 cgd fi
724 1.15 mrg else
725 1.28 lukem printf "Device additions:\n" >> $ERR
726 1.28 lukem column -t $TMP1 >> $ERR
727 1.28 lukem printf "\n" >> $ERR
728 1.52 atatat backup_file add $TMP1 $CUR $BACK >> $ERR
729 1.9 cgd fi
730 1.28 lukem fi
731 1.28 lukem if [ -s $ERR ] ; then
732 1.28 lukem printf "\nChecking setuid files and devices:\n"
733 1.28 lukem cat $ERR
734 1.28 lukem printf "\n"
735 1.9 cgd fi
736 1.9 cgd fi
737 1.9 cgd
738 1.9 cgd # Check special files.
739 1.9 cgd # Check system binaries.
740 1.9 cgd #
741 1.9 cgd # Create the mtree tree specifications using:
742 1.67 lukem # mtree -cx -pDIR -kmd5,uid,gid,mode,nlink,size,link,time > DIR.secure
743 1.38 kleink # chown root:wheel DIR.secure
744 1.67 lukem # chmod u+r,go= DIR.secure
745 1.9 cgd #
746 1.9 cgd # Note, this is not complete protection against Trojan horsed binaries, as
747 1.9 cgd # the hacker can modify the tree specification to match the replaced binary.
748 1.9 cgd # For details on really protecting yourself against modified binaries, see
749 1.9 cgd # the mtree(8) manual page.
750 1.32 lukem #
751 1.31 lukem if checkyesno check_mtree; then
752 1.82 jhawk if checkyesno check_mtree_follow_symlinks; then
753 1.82 jhawk check_mtree_flags="-L"
754 1.82 jhawk else
755 1.82 jhawk check_mtree_flags=""
756 1.82 jhawk fi
757 1.67 lukem for file in $special_files; do
758 1.67 lukem [ ! -s $file ] && continue
759 1.82 jhawk mtree -e -l -p / $check_mtree_flags -f $file
760 1.87 jhawk done 3>&1 >$OUTPUT 2>&3 |
761 1.87 jhawk grep -v '^mtree: dev/tty: Device not configured$' >&2
762 1.15 mrg if [ -s $OUTPUT ]; then
763 1.9 cgd printf "\nChecking special files and directories.\n"
764 1.9 cgd cat $OUTPUT
765 1.9 cgd fi
766 1.9 cgd
767 1.16 mikel for file in /etc/mtree/*.secure; do
768 1.16 mikel [ $file = '/etc/mtree/*.secure' ] && continue
769 1.9 cgd tree=`sed -n -e '3s/.* //p' -e 3q $file`
770 1.82 jhawk mtree $check_mtree_flags -f $file -p $tree > $TMP1
771 1.9 cgd if [ -s $TMP1 ]; then
772 1.67 lukem printf "\nChecking $tree:\n"
773 1.67 lukem cat $TMP1
774 1.9 cgd fi
775 1.67 lukem done > $OUTPUT
776 1.15 mrg if [ -s $OUTPUT ]; then
777 1.9 cgd printf "\nChecking system binaries:\n"
778 1.9 cgd cat $OUTPUT
779 1.9 cgd fi
780 1.9 cgd fi
781 1.9 cgd
782 1.32 lukem # Backup disklabels of available disks
783 1.32 lukem #
784 1.32 lukem if checkyesno check_disklabels; then
785 1.67 lukem # migrate old disklabels
786 1.67 lukem for file in `ls -1d $backup_dir/$backup_dir/disklabel.* \
787 1.67 lukem $backup_dir/disklabel.* 2>/dev/null`; do
788 1.67 lukem migrate_file "$file" "$work_dir/${file##*/}"
789 1.67 lukem done
790 1.67 lukem
791 1.67 lukem # generate list of old disklabels & fdisks and remove them
792 1.67 lukem ls -1d $work_dir/disklabel.* $work_dir/fdisk.* 2>/dev/null |
793 1.52 atatat egrep -v '\.(backup|current)(,v)?$' > $LABELS
794 1.32 lukem xargs rm < $LABELS
795 1.32 lukem
796 1.67 lukem # generate disklabels of all disks excluding: cd fd md
797 1.63 lukem disks=`iostat -x | awk 'NR > 1 && $1 !~ /^[cfm]d/ { print $1; }'`
798 1.32 lukem for i in $disks; do
799 1.67 lukem disklabel $i > "$work_dir/disklabel.$i" 2>/dev/null
800 1.32 lukem done
801 1.32 lukem
802 1.67 lukem # if fdisk is available, generate fdisks for: ed ld sd wd
803 1.67 lukem if [ -x /sbin/fdisk ]; then
804 1.67 lukem disks=`iostat -x| awk 'NR > 1 && $1 ~ /^[elsw]d/ { print $1; }'`
805 1.67 lukem for i in $disks; do
806 1.67 lukem /sbin/fdisk $i > "$work_dir/fdisk.$i" 2>/dev/null
807 1.67 lukem done
808 1.67 lukem fi
809 1.67 lukem
810 1.67 lukem # append list of new disklabels and fdisks
811 1.67 lukem ls -1d $work_dir/disklabel.* $work_dir/fdisk.* 2>/dev/null |
812 1.52 atatat egrep -v '\.(backup|current)(,v)?$' >> $LABELS
813 1.62 atatat CHANGELIST="$LABELS $CHANGELIST"
814 1.62 atatat fi
815 1.62 atatat
816 1.62 atatat # Check for changes in the list of installed pkgs
817 1.62 atatat #
818 1.65 lukem if checkyesno check_pkgs && [ -d $pkgdb_dir ]; then
819 1.67 lukem pkgs=$work_dir/pkgs
820 1.67 lukem migrate_file "$backup_dir/pkgs" "$pkgs"
821 1.65 lukem ( cd $pkgdb_dir
822 1.62 atatat pkg_info | sort
823 1.62 atatat echo ""
824 1.62 atatat find . \( -name +REQUIRED_BY -o -name +CONTENTS \) -print0 |
825 1.72 lukem xargs -0 ls -ldgTq | sort -t. +1 | sed -e 's, \./, ,'
826 1.62 atatat ) > $pkgs
827 1.67 lukem echo "$pkgs" > $PKGS
828 1.62 atatat CHANGELIST="$PKGS $CHANGELIST"
829 1.32 lukem fi
830 1.32 lukem
831 1.67 lukem # List of files that get backed up and checked for any modifications.
832 1.9 cgd # Any changes cause the files to rotate.
833 1.32 lukem #
834 1.67 lukem if checkyesno check_changelist ; then
835 1.67 lukem for file in $special_files; do
836 1.67 lukem [ ! -s $file ] && continue
837 1.67 lukem mtree -D -k type -f $file -E exclude |
838 1.67 lukem sed '/^type=file/!d ; s/type=file \.//'
839 1.67 lukem done > $CHANGEFILES
840 1.67 lukem
841 1.75 lukem (
842 1.68 lukem # Add other files which might dynamically exist:
843 1.67 lukem # /etc/ifconfig.*
844 1.67 lukem # /etc/raid*.conf
845 1.68 lukem # /etc/rc.d/*
846 1.67 lukem # /etc/rc.conf.d/*
847 1.68 lukem #
848 1.75 lukem echo "/etc/ifconfig.*"
849 1.75 lukem echo "/etc/raid*.conf"
850 1.75 lukem echo "/etc/rc.d/*"
851 1.75 lukem echo "/etc/rc.conf.d/*"
852 1.67 lukem
853 1.68 lukem # Add /etc/changelist
854 1.68 lukem #
855 1.75 lukem if [ -s /etc/changelist ]; then
856 1.75 lukem grep -v '^#' /etc/changelist
857 1.75 lukem fi
858 1.75 lukem ) | while read file; do
859 1.75 lukem case "$file" in
860 1.75 lukem *[\*\?\[]*) # If changelist line is a glob ...
861 1.75 lukem # ... expand possible backup files
862 1.75 lukem #
863 1.75 lukem ls -1d $(echo $backup_dir/${file}.current) 2>/dev/null \
864 1.75 lukem | sed "s,^$backup_dir/,, ; s,\.current$,,"
865 1.75 lukem
866 1.75 lukem # ... expand possible files
867 1.75 lukem #
868 1.75 lukem ls -1d $(echo $file) 2>/dev/null
869 1.75 lukem ;;
870 1.75 lukem *)
871 1.75 lukem # Otherwise, just print the filename
872 1.75 lukem echo $file
873 1.75 lukem ;;
874 1.75 lukem esac
875 1.75 lukem done >> $CHANGEFILES
876 1.67 lukem CHANGELIST="$CHANGEFILES $CHANGELIST"
877 1.67 lukem fi
878 1.67 lukem
879 1.67 lukem # Special case backups, including the master password file and
880 1.67 lukem # ssh private host keys. The normal backup mechanisms for
881 1.67 lukem # $check_changelist (see below) also print out the actual file
882 1.67 lukem # differences and we don't want to do that for these files
883 1.67 lukem #
884 1.67 lukem echo $MP > $TMP1 # always add /etc/master.passwd
885 1.67 lukem for file in $special_files; do
886 1.67 lukem [ ! -s $file ] && continue
887 1.70 lukem mtree -D -k type -f $file -I nodiff |
888 1.67 lukem sed '/^type=file/!d ; s/type=file \.//'
889 1.67 lukem done >> $TMP1
890 1.73 lukem grep -v '^$' $TMP1 | sort -u > $TMP2
891 1.68 lukem
892 1.69 lukem while read file; do
893 1.67 lukem backup_and_diff "$file" no
894 1.69 lukem done < $TMP2
895 1.67 lukem
896 1.32 lukem
897 1.32 lukem if [ -n "$CHANGELIST" ]; then
898 1.73 lukem grep -h -v '^$' $CHANGELIST | sort -u > $TMP1
899 1.68 lukem comm -23 $TMP1 $TMP2 | while read file; do
900 1.67 lukem backup_and_diff "$file" yes
901 1.9 cgd done
902 1.44 ad fi
903 1.44 ad
904 1.44 ad if [ -f /etc/security.local ]; then
905 1.84 jhawk . /etc/security.local > $OUTPUT
906 1.84 jhawk if [ -s $OUTPUT ] ; then
907 1.84 jhawk printf "\nRunning /etc/security.local:\n"
908 1.84 jhawk cat $OUTPUT
909 1.84 jhawk fi
910 1.9 cgd fi
911