| @@ -1,1098 +1,1105 @@ | | | @@ -1,1098 +1,1105 @@ |
1 | #!/bin/sh - | | 1 | #!/bin/sh - |
2 | # | | 2 | # |
3 | # $NetBSD: security,v 1.125 2019/09/18 22:27:55 uwe Exp $ | | 3 | # $NetBSD: security,v 1.126 2019/12/06 14:43:30 riastradh Exp $ |
4 | # from: @(#)security 8.1 (Berkeley) 6/9/93 | | 4 | # from: @(#)security 8.1 (Berkeley) 6/9/93 |
5 | # | | 5 | # |
6 | | | 6 | |
7 | PATH=/sbin:/usr/sbin:/bin:/usr/bin | | 7 | PATH=/sbin:/usr/sbin:/bin:/usr/bin |
8 | | | 8 | |
9 | rcvar_manpage='security.conf(5)' | | 9 | rcvar_manpage='security.conf(5)' |
10 | | | 10 | |
11 | if [ -f /etc/rc.subr ]; then | | 11 | if [ -f /etc/rc.subr ]; then |
12 | . /etc/rc.subr | | 12 | . /etc/rc.subr |
13 | else | | 13 | else |
14 | echo "Can't read /etc/rc.subr; aborting." | | 14 | echo "Can't read /etc/rc.subr; aborting." |
15 | exit 1; | | 15 | exit 1; |
16 | fi | | 16 | fi |
17 | | | 17 | |
18 | umask 077 | | 18 | umask 077 |
19 | TZ=UTC; export TZ | | 19 | TZ=UTC; export TZ |
20 | | | 20 | |
21 | if [ -s /etc/security.conf ]; then | | 21 | if [ -s /etc/security.conf ]; then |
22 | . /etc/security.conf | | 22 | . /etc/security.conf |
23 | fi | | 23 | fi |
24 | if [ -s /etc/pkgpath.conf ]; then | | 24 | if [ -s /etc/pkgpath.conf ]; then |
25 | . /etc/pkgpath.conf | | 25 | . /etc/pkgpath.conf |
26 | fi | | 26 | fi |
27 | | | 27 | |
28 | # Set reasonable defaults (if they're not set in security.conf) | | 28 | # Set reasonable defaults (if they're not set in security.conf) |
29 | # | | 29 | # |
30 | backup_dir=${backup_dir:-/var/backups} | | 30 | backup_dir=${backup_dir:-/var/backups} |
31 | max_loginlen=${max_loginlen:-8} | | 31 | max_loginlen=${max_loginlen:-8} |
32 | max_grouplen=${max_grouplen:-8} | | 32 | max_grouplen=${max_grouplen:-8} |
33 | pkg_admin=${pkg_admin:-/usr/sbin/pkg_admin} | | 33 | pkg_admin=${pkg_admin:-/usr/sbin/pkg_admin} |
34 | pkg_info=${pkg_info:-/usr/sbin/pkg_info} | | 34 | pkg_info=${pkg_info:-/usr/sbin/pkg_info} |
35 | | | 35 | |
36 | # Other configurable variables | | 36 | # Other configurable variables |
37 | # | | 37 | # |
38 | special_files="/etc/mtree/special /etc/mtree/special.local" | | 38 | special_files="/etc/mtree/special /etc/mtree/special.local" |
39 | MP=/etc/master.passwd | | 39 | MP=/etc/master.passwd |
40 | CHANGELIST="" | | 40 | CHANGELIST="" |
41 | work_dir=$backup_dir/work | | 41 | work_dir=$backup_dir/work |
42 | | | 42 | |
43 | if [ ! -d "$work_dir" ]; then | | 43 | if [ ! -d "$work_dir" ]; then |
44 | mkdir -p "$work_dir" | | 44 | mkdir -p "$work_dir" |
45 | fi | | 45 | fi |
46 | | | 46 | |
47 | SECUREDIR=$(mktemp -d -t _securedir) || exit 1 | | 47 | SECUREDIR=$(mktemp -d -t _securedir) || exit 1 |
48 | | | 48 | |
49 | trap "/bin/rm -rf $SECUREDIR ; exit 0" EXIT INT QUIT PIPE | | 49 | trap "/bin/rm -rf $SECUREDIR ; exit 0" EXIT INT QUIT PIPE |
50 | | | 50 | |
51 | if ! cd "$SECUREDIR"; then | | 51 | if ! cd "$SECUREDIR"; then |
52 | echo "Can not cd to $SECUREDIR". | | 52 | echo "Can not cd to $SECUREDIR". |
53 | exit 1 | | 53 | exit 1 |
54 | fi | | 54 | fi |
55 | | | 55 | |
56 | ERR=err.$$ | | 56 | ERR=err.$$ |
57 | TMP1=tmp1.$$ | | 57 | TMP1=tmp1.$$ |
58 | TMP2=tmp2.$$ | | 58 | TMP2=tmp2.$$ |
59 | MPBYUID=mpbyuid.$$ | | 59 | MPBYUID=mpbyuid.$$ |
60 | MPBYPATH=mpbypath.$$ | | 60 | MPBYPATH=mpbypath.$$ |
61 | LIST=list.$$ | | 61 | LIST=list.$$ |
62 | OUTPUT=output.$$ | | 62 | OUTPUT=output.$$ |
63 | LABELS=labels.$$ | | 63 | LABELS=labels.$$ |
64 | LVM_LABELS=lvm.$$ | | 64 | LVM_LABELS=lvm.$$ |
65 | PKGS=pkgs.$$ | | 65 | PKGS=pkgs.$$ |
66 | CHANGEFILES=changefiles.$$ | | 66 | CHANGEFILES=changefiles.$$ |
67 | SPECIALSPEC=specialspec.$$ | | 67 | SPECIALSPEC=specialspec.$$ |
68 | | | 68 | |
69 | if [ -n "${pkgdb_dir}" ]; then | | 69 | if [ -n "${pkgdb_dir}" ]; then |
70 | echo "WARNING: Setting pkgdb_dir in security.conf(5) is deprecated" | | 70 | echo "WARNING: Setting pkgdb_dir in security.conf(5) is deprecated" |
71 | echo "WARNING: Please define PKG_DBDIR in pkg_install.conf(5) instead" | | 71 | echo "WARNING: Please define PKG_DBDIR in pkg_install.conf(5) instead" |
72 | _compat_K_flag="-K ${pkgdb_dir}" | | 72 | _compat_K_flag="-K ${pkgdb_dir}" |
73 | fi | | 73 | fi |
74 | | | 74 | |
75 | have_pkgs() { | | 75 | have_pkgs() { |
76 | $pkg_info ${_compat_K_flag} -q -E '*' | | 76 | $pkg_info ${_compat_K_flag} -q -E '*' |
77 | } | | 77 | } |
78 | | | 78 | |
79 | # migrate_file old new | | 79 | # migrate_file old new |
80 | # Determine if the "${old}" path name needs to be migrated to the | | 80 | # Determine if the "${old}" path name needs to be migrated to the |
81 | # "${new}" path. Also checks if "${old}.current" needs migrating, | | 81 | # "${new}" path. Also checks if "${old}.current" needs migrating, |
82 | # and if so, migrate it and possibly "${old}.current,v" and | | 82 | # and if so, migrate it and possibly "${old}.current,v" and |
83 | # "${old}.backup". | | 83 | # "${old}.backup". |
84 | # | | 84 | # |
85 | migrate_file() | | 85 | migrate_file() |
86 | { | | 86 | { |
87 | _old=$1 | | 87 | _old=$1 |
88 | _new=$2 | | 88 | _new=$2 |
89 | if [ -z "$_old" ] || [ -z "$_new" ]; then | | 89 | if [ -z "$_old" ] || [ -z "$_new" ]; then |
90 | err 3 "USAGE: migrate_file old new" | | 90 | err 3 "USAGE: migrate_file old new" |
91 | fi | | 91 | fi |
92 | if [ ! -d "${_new%/*}" ]; then | | 92 | if [ ! -d "${_new%/*}" ]; then |
93 | mkdir -p "${_new%/*}" | | 93 | mkdir -p "${_new%/*}" |
94 | fi | | 94 | fi |
95 | if [ -f "${_old}" ] && ! [ -f "${_new}" ]; then | | 95 | if [ -f "${_old}" ] && ! [ -f "${_new}" ]; then |
96 | echo "==> migrating ${_old}" | | 96 | echo "==> migrating ${_old}" |
97 | echo " to ${_new}" | | 97 | echo " to ${_new}" |
98 | mv "${_old}" "${_new}" | | 98 | mv "${_old}" "${_new}" |
99 | fi | | 99 | fi |
100 | if [ -f "${_old}.current" ] && ! [ -f "${_new}.current" ]; then | | 100 | if [ -f "${_old}.current" ] && ! [ -f "${_new}.current" ]; then |
101 | echo "==> migrating ${_old}.current" | | 101 | echo "==> migrating ${_old}.current" |
102 | echo " to ${_new}.current" | | 102 | echo " to ${_new}.current" |
103 | mv "${_old}.current" "${_new}.current" | | 103 | mv "${_old}.current" "${_new}.current" |
104 | if [ -f "${_old}.current,v" ] && | | 104 | if [ -f "${_old}.current,v" ] && |
105 | ! [ -f "${_new}.current,v" ]; then | | 105 | ! [ -f "${_new}.current,v" ]; then |
106 | echo "==> migrating ${_old}.current,v" | | 106 | echo "==> migrating ${_old}.current,v" |
107 | echo " to ${_new}.current,v" | | 107 | echo " to ${_new}.current,v" |
108 | mv "${_old}.current,v" "${_new}.current,v" | | 108 | mv "${_old}.current,v" "${_new}.current,v" |
109 | fi | | 109 | fi |
110 | if [ -f "${_old}.backup" ] && ! [ -f "${_new}.backup" ]; then | | 110 | if [ -f "${_old}.backup" ] && ! [ -f "${_new}.backup" ]; then |
111 | echo "==> migrating ${_old}.backup" | | 111 | echo "==> migrating ${_old}.backup" |
112 | echo " to ${_new}.backup" | | 112 | echo " to ${_new}.backup" |
113 | mv "${_old}.backup" "${_new}.backup" | | 113 | mv "${_old}.backup" "${_new}.backup" |
114 | fi | | 114 | fi |
115 | fi | | 115 | fi |
116 | } | | 116 | } |
117 | | | 117 | |
118 | | | 118 | |
119 | # backup_and_diff file printdiff | | 119 | # backup_and_diff file printdiff |
120 | # Determine if file needs backing up, and if so, do it. | | 120 | # Determine if file needs backing up, and if so, do it. |
121 | # If printdiff is yes, display the diffs, otherwise | | 121 | # If printdiff is yes, display the diffs, otherwise |
122 | # just print a message saying "[changes omitted]". | | 122 | # just print a message saying "[changes omitted]". |
123 | # | | 123 | # |
124 | backup_and_diff() | | 124 | backup_and_diff() |
125 | { | | 125 | { |
126 | _file=$1 | | 126 | _file=$1 |
127 | _printdiff=$2 | | 127 | _printdiff=$2 |
128 | if [ -z "$_file" ] || [ -z "$_printdiff" ]; then | | 128 | if [ -z "$_file" ] || [ -z "$_printdiff" ]; then |
129 | err 3 "USAGE: backup_and_diff file printdiff" | | 129 | err 3 "USAGE: backup_and_diff file printdiff" |
130 | fi | | 130 | fi |
131 | ! checkyesno _printdiff | | 131 | ! checkyesno _printdiff |
132 | _printdiff=$? | | 132 | _printdiff=$? |
133 | | | 133 | |
134 | _old=$backup_dir/${_file##*/} | | 134 | _old=$backup_dir/${_file##*/} |
135 | case "$_file" in | | 135 | case "$_file" in |
136 | $work_dir/*) | | 136 | $work_dir/*) |
137 | _new=$_file | | 137 | _new=$_file |
138 | migrate_file "$backup_dir/$_old" "$_new" | | 138 | migrate_file "$backup_dir/$_old" "$_new" |
139 | migrate_file "$_old" "$_new" | | 139 | migrate_file "$_old" "$_new" |
140 | ;; | | 140 | ;; |
141 | *) | | 141 | *) |
142 | _new=$backup_dir/$_file | | 142 | _new=$backup_dir/$_file |
143 | migrate_file "$_old" "$_new" | | 143 | migrate_file "$_old" "$_new" |
144 | ;; | | 144 | ;; |
145 | esac | | 145 | esac |
146 | CUR=${_new}.current | | 146 | CUR=${_new}.current |
147 | BACK=${_new}.backup | | 147 | BACK=${_new}.backup |
148 | if [ -f $_file ]; then | | 148 | if [ -f $_file ]; then |
149 | if [ -f $CUR ] ; then | | 149 | if [ -f $CUR ] ; then |
150 | if [ "$_printdiff" -ne 0 ]; then | | 150 | if [ "$_printdiff" -ne 0 ]; then |
151 | diff ${diff_options} $CUR $_file > $OUTPUT | | 151 | diff ${diff_options} $CUR $_file > $OUTPUT |
152 | else | | 152 | else |
153 | if ! cmp -s $CUR $_file; then | | 153 | if ! cmp -s $CUR $_file; then |
154 | echo "[changes omitted]" | | 154 | echo "[changes omitted]" |
155 | fi > $OUTPUT | | 155 | fi > $OUTPUT |
156 | fi | | 156 | fi |
157 | if [ -s $OUTPUT ] ; then | | 157 | if [ -s $OUTPUT ] ; then |
158 | printf \ | | 158 | printf \ |
159 | "\n======\n%s diffs (OLD < > NEW)\n======\n" $_file | | 159 | "\n======\n%s diffs (OLD < > NEW)\n======\n" $_file |
160 | cat $OUTPUT | | 160 | cat $OUTPUT |
161 | backup_file update $_file $CUR $BACK | | 161 | backup_file update $_file $CUR $BACK |
162 | fi | | 162 | fi |
163 | else | | 163 | else |
164 | printf "\n======\n%s added\n======\n" $_file | | 164 | printf "\n======\n%s added\n======\n" $_file |
165 | if [ "$_printdiff" -ne 0 ]; then | | 165 | if [ "$_printdiff" -ne 0 ]; then |
166 | diff ${diff_options} /dev/null $_file | | 166 | diff ${diff_options} /dev/null $_file |
167 | else | | 167 | else |
168 | echo "[changes omitted]" | | 168 | echo "[changes omitted]" |
169 | fi | | 169 | fi |
170 | backup_file add $_file $CUR $BACK | | 170 | backup_file add $_file $CUR $BACK |
171 | fi | | 171 | fi |
172 | else | | 172 | else |
173 | if [ -f $CUR ]; then | | 173 | if [ -f $CUR ]; then |
174 | printf "\n======\n%s removed\n======\n" $_file | | 174 | printf "\n======\n%s removed\n======\n" $_file |
175 | if [ "$_printdiff" -ne 0 ]; then | | 175 | if [ "$_printdiff" -ne 0 ]; then |
176 | diff ${diff_options} $CUR /dev/null | | 176 | diff ${diff_options} $CUR /dev/null |
177 | else | | 177 | else |
178 | echo "[changes omitted]" | | 178 | echo "[changes omitted]" |
179 | fi | | 179 | fi |
180 | backup_file remove $_file $CUR $BACK | | 180 | backup_file remove $_file $CUR $BACK |
181 | fi | | 181 | fi |
182 | fi | | 182 | fi |
183 | } | | 183 | } |
184 | | | 184 | |
185 | | | 185 | |
186 | # These are used several times. | | 186 | # These are used several times. |
187 | # | | 187 | # |
188 | awk -F: '!/^\+/ { print $1 " " $3 }' $MP | sort -k2n > $MPBYUID | | 188 | awk -F: '!/^\+/ { print $1 " " $3 }' $MP | sort -k2n > $MPBYUID |
189 | awk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH | | 189 | awk -F: '{ print $1 " " $9 }' $MP | sort -k2 > $MPBYPATH |
190 | for file in $special_files; do | | 190 | for file in $special_files; do |
191 | [ -s $file ] && cat $file | | 191 | [ -s $file ] && cat $file |
192 | done | mtree -CM -k all > $SPECIALSPEC || exit 1 | | 192 | done | mtree -CM -k all > $SPECIALSPEC || exit 1 |
193 | | | 193 | |
194 | | | 194 | |
195 | # Check the master password file syntax. | | 195 | # Check the master password file syntax. |
196 | # | | 196 | # |
197 | if checkyesno check_passwd; then | | 197 | if checkyesno check_passwd; then |
198 | # XXX: the sense of permit_star is reversed; the code works as | | 198 | # XXX: the sense of permit_star is reversed; the code works as |
199 | # implemented, but usage needs to be negated. | | 199 | # implemented, but usage needs to be negated. |
200 | checkyesno check_passwd_permit_star && permit_star=0 || permit_star=1 | | 200 | checkyesno check_passwd_permit_star && permit_star=0 || permit_star=1 |
201 | checkyesno check_passwd_permit_nonalpha \ | | 201 | checkyesno check_passwd_permit_nonalpha \ |
202 | && permit_nonalpha=1 || permit_nonalpha=0 | | 202 | && permit_nonalpha=1 || permit_nonalpha=0 |
203 | | | 203 | |
204 | awk -v "len=$max_loginlen" \ | | 204 | awk -v "len=$max_loginlen" \ |
205 | -v "nowarn_shells_list=$check_passwd_nowarn_shells" \ | | 205 | -v "nowarn_shells_list=$check_passwd_nowarn_shells" \ |
206 | -v "nowarn_users_list=$check_passwd_nowarn_users" \ | | 206 | -v "nowarn_users_list=$check_passwd_nowarn_users" \ |
207 | -v "permit_star=$permit_star" \ | | 207 | -v "permit_star=$permit_star" \ |
208 | -v "permit_nonalpha=$permit_nonalpha" \ | | 208 | -v "permit_nonalpha=$permit_nonalpha" \ |
209 | ' | | 209 | ' |
210 | BEGIN { | | 210 | BEGIN { |
211 | while ( getline < "/etc/shells" > 0 ) { | | 211 | while ( getline < "/etc/shells" > 0 ) { |
212 | if ($0 ~ /^\#/ || $0 ~ /^$/ ) | | 212 | if ($0 ~ /^\#/ || $0 ~ /^$/ ) |
213 | continue; | | 213 | continue; |
214 | shells[$1]++; | | 214 | shells[$1]++; |
215 | } | | 215 | } |
216 | split(nowarn_shells_list, a); | | 216 | split(nowarn_shells_list, a); |
217 | for (i in a) nowarn_shells[a[i]]++; | | 217 | for (i in a) nowarn_shells[a[i]]++; |
218 | split(nowarn_users_list, a); | | 218 | split(nowarn_users_list, a); |
219 | for (i in a) nowarn_users[a[i]]++; | | 219 | for (i in a) nowarn_users[a[i]]++; |
220 | uid0_users_list="root toor" | | 220 | uid0_users_list="root toor" |
221 | split(uid0_users_list, a); | | 221 | split(uid0_users_list, a); |
222 | for (i in a) uid0_users[a[i]]++; | | 222 | for (i in a) uid0_users[a[i]]++; |
223 | FS=":"; | | 223 | FS=":"; |
224 | } | | 224 | } |
225 | | | 225 | |
226 | { | | 226 | { |
227 | if ($0 ~ /^[ ]*$/) { | | 227 | if ($0 ~ /^[ ]*$/) { |
228 | printf "Line %d is a blank line.\n", NR; | | 228 | printf "Line %d is a blank line.\n", NR; |
229 | next; | | 229 | next; |
230 | } | | 230 | } |
231 | | | 231 | |
232 | # NIS compat entry? | | 232 | # NIS compat entry? |
233 | compatline = $1 ~ "^[\\+-]"; | | 233 | compatline = $1 ~ "^[\\+-]"; |
234 | if (compatline) { | | 234 | if (compatline) { |
235 | if ($1 == "+" && NF == 1) { | | 235 | if ($1 == "+" && NF == 1) { |
236 | next; | | 236 | next; |
237 | } | | 237 | } |
238 | sub("^.", "", $1); | | 238 | sub("^.", "", $1); |
239 | } | | 239 | } |
240 | if (NF != 10) | | 240 | if (NF != 10) |
241 | printf "Line %d has the wrong number of fields.\n", NR; | | 241 | printf "Line %d has the wrong number of fields.\n", NR; |
242 | if (compatline) { | | 242 | if (compatline) { |
243 | if ($3 == 0) | | 243 | if ($3 == 0) |
244 | printf "Line %d includes entries with uid 0.\n", | | 244 | printf "Line %d includes entries with uid 0.\n", |
245 | NR; | | 245 | NR; |
246 | if ($1 == "") | | 246 | if ($1 == "") |
247 | next; | | 247 | next; |
248 | } | | 248 | } |
249 | if (!permit_nonalpha && | | 249 | if (!permit_nonalpha && |
250 | $1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) | | 250 | $1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) |
251 | printf "Login %s has non-alphanumeric characters.\n", | | 251 | printf "Login %s has non-alphanumeric characters.\n", |
252 | $1; | | 252 | $1; |
253 | if (length($1) > len) | | 253 | if (length($1) > len) |
254 | printf "Login %s has more than "len" characters.\n", | | 254 | printf "Login %s has more than "len" characters.\n", |
255 | $1; | | 255 | $1; |
256 | if ($2 == "" && !compatline && !nowarn_users[$1]) | | 256 | if ($2 == "" && !compatline && !nowarn_users[$1]) |
257 | printf "Login %s has no password.\n", $1; | | 257 | printf "Login %s has no password.\n", $1; |
258 | if (!nowarn_shells[$10] && !nowarn_users[$1]) { | | 258 | if (!nowarn_shells[$10] && !nowarn_users[$1]) { |
259 | if (length($2) != 13 && | | 259 | if (length($2) != 13 && |
260 | length($2) != 20 && | | 260 | length($2) != 20 && |
261 | $2 !~ /^\$1/ && | | 261 | $2 !~ /^\$1/ && |
262 | $2 !~ /^\$2/ && | | 262 | $2 !~ /^\$2/ && |
263 | $2 !~ /^\$sha1/ && | | 263 | $2 !~ /^\$sha1/ && |
264 | $2 != "" && | | 264 | $2 != "" && |
265 | (permit_star || $2 != "*") && | | 265 | (permit_star || $2 != "*") && |
266 | $2 !~ /^\*[A-z-]+$/ && | | 266 | $2 !~ /^\*[A-z-]+$/ && |
267 | $1 != "toor") { | | 267 | $1 != "toor") { |
268 | if ($10 == "" || shells[$10]) | | 268 | if ($10 == "" || shells[$10]) |
269 | printf "Login %s is off but still has "\ | | 269 | printf "Login %s is off but still has "\ |
270 | "a valid shell (%s)\n", $1, $10; | | 270 | "a valid shell (%s)\n", $1, $10; |
271 | } else if (compatline && $10 == "") { | | 271 | } else if (compatline && $10 == "") { |
272 | # nothing | | 272 | # nothing |
273 | } else if (! shells[$10]) | | 273 | } else if (! shells[$10]) |
274 | printf "Login %s does not have a valid "\ | | 274 | printf "Login %s does not have a valid "\ |
275 | "shell (%s)\n", $1, $10; | | 275 | "shell (%s)\n", $1, $10; |
276 | } | | 276 | } |
277 | if ($3 == 0 && !uid0_users[$1] && !nowarn_users[$1]) | | 277 | if ($3 == 0 && !uid0_users[$1] && !nowarn_users[$1]) |
278 | printf "Login %s has a user id of 0.\n", $1; | | 278 | printf "Login %s has a user id of 0.\n", $1; |
279 | if ($3 != "" && $3 < 0) | | 279 | if ($3 != "" && $3 < 0) |
280 | printf "Login %s has a negative user id.\n", $1; | | 280 | printf "Login %s has a negative user id.\n", $1; |
281 | if ($4 != "" && $4 < 0) | | 281 | if ($4 != "" && $4 < 0) |
282 | printf "Login %s has a negative group id.\n", $1; | | 282 | printf "Login %s has a negative group id.\n", $1; |
283 | }' < $MP > $OUTPUT | | 283 | }' < $MP > $OUTPUT |
284 | if [ -s $OUTPUT ] ; then | | 284 | if [ -s $OUTPUT ] ; then |
285 | printf "\nChecking the $MP file:\n" | | 285 | printf "\nChecking the $MP file:\n" |
286 | cat $OUTPUT | | 286 | cat $OUTPUT |
287 | fi | | 287 | fi |
288 | | | 288 | |
289 | awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT | | 289 | awk -F: '{ print $1 }' $MP | sort | uniq -d > $OUTPUT |
290 | if [ -s $OUTPUT ] ; then | | 290 | if [ -s $OUTPUT ] ; then |
291 | printf "\n$MP has duplicate user names.\n" | | 291 | printf "\n$MP has duplicate user names.\n" |
292 | column $OUTPUT | | 292 | column $OUTPUT |
293 | fi | | 293 | fi |
294 | | | 294 | |
295 | awk -v "permit_dups_list=$check_passwd_permit_dups" \ | | 295 | awk -v "permit_dups_list=$check_passwd_permit_dups" \ |
296 | ' | | 296 | ' |
297 | BEGIN { | | 297 | BEGIN { |
298 | split(permit_dups_list, a); | | 298 | split(permit_dups_list, a); |
299 | for (i in a) permit_dups[a[i]]++; | | 299 | for (i in a) permit_dups[a[i]]++; |
300 | } | | 300 | } |
301 | { | | 301 | { |
302 | if (!permit_dups[$1]) | | 302 | if (!permit_dups[$1]) |
303 | print $2; | | 303 | print $2; |
304 | }' < $MPBYUID | uniq -d > $TMP2 | | 304 | }' < $MPBYUID | uniq -d > $TMP2 |
305 | if [ -s $TMP2 ] ; then | | 305 | if [ -s $TMP2 ] ; then |
306 | printf "\n$MP has duplicate user ids.\n" | | 306 | printf "\n$MP has duplicate user ids.\n" |
307 | while read uid; do | | 307 | while read uid; do |
308 | grep -w $uid $MPBYUID | | 308 | grep -w $uid $MPBYUID |
309 | done < $TMP2 | column | | 309 | done < $TMP2 | column |
310 | fi | | 310 | fi |
311 | fi | | 311 | fi |
312 | | | 312 | |
313 | # Check the group file syntax. | | 313 | # Check the group file syntax. |
314 | # | | 314 | # |
315 | if checkyesno check_group; then | | 315 | if checkyesno check_group; then |
316 | GRP=/etc/group | | 316 | GRP=/etc/group |
317 | awk -F: -v "len=$max_grouplen" '{ | | 317 | awk -F: -v "len=$max_grouplen" '{ |
318 | if ($0 ~ /^[ ]*$/) { | | 318 | if ($0 ~ /^[ ]*$/) { |
319 | printf "Line %d is a blank line.\n", NR; | | 319 | printf "Line %d is a blank line.\n", NR; |
320 | next; | | 320 | next; |
321 | } | | 321 | } |
322 | if (NF != 4 && ($1 != "+" || NF != 1)) | | 322 | if (NF != 4 && ($1 != "+" || NF != 1)) |
323 | printf "Line %d has the wrong number of fields.\n", NR; | | 323 | printf "Line %d has the wrong number of fields.\n", NR; |
324 | if ($1 == "+" ) { | | 324 | if ($1 == "+" ) { |
325 | next; | | 325 | next; |
326 | } | | 326 | } |
327 | if ($1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) | | 327 | if ($1 !~ /^[_A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])*$/) |
328 | printf "Group %s has non-alphanumeric characters.\n", | | 328 | printf "Group %s has non-alphanumeric characters.\n", |
329 | $1; | | 329 | $1; |
330 | if (length($1) > len) | | 330 | if (length($1) > len) |
331 | printf "Group %s has more than "len" characters.\n", $1; | | 331 | printf "Group %s has more than "len" characters.\n", $1; |
332 | if ($3 !~ /[0-9]*/) | | 332 | if ($3 !~ /[0-9]*/) |
333 | printf "Login %s has a negative group id.\n", $1; | | 333 | printf "Login %s has a negative group id.\n", $1; |
334 | }' < $GRP > $OUTPUT | | 334 | }' < $GRP > $OUTPUT |
335 | if [ -s $OUTPUT ] ; then | | 335 | if [ -s $OUTPUT ] ; then |
336 | printf "\nChecking the $GRP file:\n" | | 336 | printf "\nChecking the $GRP file:\n" |
337 | cat $OUTPUT | | 337 | cat $OUTPUT |
338 | fi | | 338 | fi |
339 | | | 339 | |
340 | awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT | | 340 | awk -F: '{ print $1 }' $GRP | sort | uniq -d > $OUTPUT |
341 | dupgroups="" | | 341 | dupgroups="" |
342 | for group in $(cat $OUTPUT) ; do | | 342 | for group in $(cat $OUTPUT) ; do |
343 | gcount=$(awk -F: "/$group/ { print \$1,\$3 }" $GRP | | | 343 | gcount=$(awk -F: "/$group/ { print \$1,\$3 }" $GRP | |
344 | sort -u | wc -l) | | 344 | sort -u | wc -l) |
345 | if [ $gcount -gt 1 ]; then | | 345 | if [ $gcount -gt 1 ]; then |
346 | dupgroups="$dupgroups $group" | | 346 | dupgroups="$dupgroups $group" |
347 | fi | | 347 | fi |
348 | done | | 348 | done |
349 | if [ ! -z $dupgroups ] ; then | | 349 | if [ ! -z $dupgroups ] ; then |
350 | printf "\n$GRP has duplicate group names.\n" | | 350 | printf "\n$GRP has duplicate group names.\n" |
351 | printf "$dupgroups\n" | | 351 | printf "$dupgroups\n" |
352 | fi | | 352 | fi |
353 | fi | | 353 | fi |
354 | | | 354 | |
355 | # Check for root paths, umask values in startup files. | | 355 | # Check for root paths, umask values in startup files. |
356 | # The check for the root paths is problematical -- it's likely to fail | | 356 | # The check for the root paths is problematical -- it's likely to fail |
357 | # in other environments. Once the shells have been modified to warn | | 357 | # in other environments. Once the shells have been modified to warn |
358 | # of '.' in the path, the path tests should go away. | | 358 | # of '.' in the path, the path tests should go away. |
359 | # | | 359 | # |
360 | if checkyesno check_rootdotfiles; then | | 360 | if checkyesno check_rootdotfiles; then |
361 | rhome=~root | | 361 | rhome=~root |
362 | umaskset=no | | 362 | umaskset=no |
363 | list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login" | | 363 | list="/etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login" |
364 | for i in $list ; do | | 364 | for i in $list ; do |
365 | if [ -f $i ] ; then | | 365 | if [ -f $i ] ; then |
366 | if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ; | | 366 | if egrep '^[ \t]*umask[ \t]+[0-7]+' $i > /dev/null ; |
367 | then | | 367 | then |
368 | umaskset=yes | | 368 | umaskset=yes |
369 | fi | | 369 | fi |
370 | # Double check the umask value itself; ensure that | | 370 | # Double check the umask value itself; ensure that |
371 | # both the group and other write bits are set. | | 371 | # both the group and other write bits are set. |
372 | # | | 372 | # |
373 | egrep '^[ \t]*umask[ \t]+[0-7]+' $i | | | 373 | egrep '^[ \t]*umask[ \t]+[0-7]+' $i | |
374 | awk '{ | | 374 | awk '{ |
375 | if ($2 ~ /^.$/ || $2 ~! /[^2367].$/) { | | 375 | if ($2 ~ /^.$/ || $2 ~! /[^2367].$/) { |
376 | print "\tRoot umask is group writable" | | 376 | print "\tRoot umask is group writable" |
377 | } | | 377 | } |
378 | if ($2 ~ /[^2367]$/) { | | 378 | if ($2 ~ /[^2367]$/) { |
379 | print "\tRoot umask is other writable" | | 379 | print "\tRoot umask is other writable" |
380 | } | | 380 | } |
381 | }' | sort -u | | 381 | }' | sort -u |
382 | SAVE_PATH=$PATH | | 382 | SAVE_PATH=$PATH |
383 | unset PATH | | 383 | unset PATH |
384 | /bin/csh -f -s << end-of-csh > /dev/null 2>&1 | | 384 | /bin/csh -f -s << end-of-csh > /dev/null 2>&1 |
385 | source $i | | 385 | source $i |
386 | /bin/ls -ldgT \$path > $TMP1 | | 386 | /bin/ls -ldgT \$path > $TMP1 |
387 | end-of-csh | | 387 | end-of-csh |
388 | export PATH=$SAVE_PATH | | 388 | export PATH=$SAVE_PATH |
389 | awk '{ | | 389 | awk '{ |
390 | if ($10 ~ /^\.$/) { | | 390 | if ($10 ~ /^\.$/) { |
391 | print "\tThe root path includes ."; | | 391 | print "\tThe root path includes ."; |
392 | next; | | 392 | next; |
393 | } | | 393 | } |
394 | } | | 394 | } |
395 | $1 ~ /^d....w/ \ | | 395 | $1 ~ /^d....w/ \ |
396 | { print "\tRoot path directory " $10 " is group writable." } \ | | 396 | { print "\tRoot path directory " $10 " is group writable." } \ |
397 | $1 ~ /^d.......w/ \ | | 397 | $1 ~ /^d.......w/ \ |
398 | { print "\tRoot path directory " $10 " is other writable." }' \ | | 398 | { print "\tRoot path directory " $10 " is other writable." }' \ |
399 | < $TMP1 | | 399 | < $TMP1 |
400 | fi | | 400 | fi |
401 | done > $OUTPUT | | 401 | done > $OUTPUT |
402 | if [ $umaskset = no ] || [ -s $OUTPUT ] ; then | | 402 | if [ $umaskset = no ] || [ -s $OUTPUT ] ; then |
403 | printf "\nChecking root csh paths, umask values:\n$list\n\n" | | 403 | printf "\nChecking root csh paths, umask values:\n$list\n\n" |
404 | if [ -s $OUTPUT ]; then | | 404 | if [ -s $OUTPUT ]; then |
405 | cat $OUTPUT | | 405 | cat $OUTPUT |
406 | fi | | 406 | fi |
407 | if [ $umaskset = no ] ; then | | 407 | if [ $umaskset = no ] ; then |
408 | printf "\tRoot csh startup files do not set the umask.\n" | | 408 | printf "\tRoot csh startup files do not set the umask.\n" |
409 | fi | | 409 | fi |
410 | fi | | 410 | fi |
411 | | | 411 | |
412 | umaskset=no | | 412 | umaskset=no |
413 | list="/etc/profile ${rhome}/.profile" | | 413 | list="/etc/profile ${rhome}/.profile" |
414 | for i in $list; do | | 414 | for i in $list; do |
415 | if [ -f $i ] ; then | | 415 | if [ -f $i ] ; then |
416 | if egrep umask $i > /dev/null ; then | | 416 | if egrep umask $i > /dev/null ; then |
417 | umaskset=yes | | 417 | umaskset=yes |
418 | fi | | 418 | fi |
419 | egrep umask $i | | | 419 | egrep umask $i | |
420 | awk '$2 ~ /^.$/ || $2 ~ /[^2367].$/ \ | | 420 | awk '$2 ~ /^.$/ || $2 ~ /[^2367].$/ \ |
421 | { print "\tRoot umask is group writable" } \ | | 421 | { print "\tRoot umask is group writable" } \ |
422 | $2 ~ /[^2367]$/ \ | | 422 | $2 ~ /[^2367]$/ \ |
423 | { print "\tRoot umask is other writable" }' | | 423 | { print "\tRoot umask is other writable" }' |
424 | SAVE_PATH=$PATH | | 424 | SAVE_PATH=$PATH |
425 | unset PATH | | 425 | unset PATH |
426 | /bin/sh << end-of-sh > /dev/null 2>&1 | | 426 | /bin/sh << end-of-sh > /dev/null 2>&1 |
427 | . $i | | 427 | . $i |
428 | list=\$(echo \$PATH | /usr/bin/sed -e \ | | 428 | list=\$(echo \$PATH | /usr/bin/sed -e \ |
429 | 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g') | | 429 | 's/^:/.:/;s/:$/:./;s/::/:.:/g;s/:/ /g') |
430 | /bin/ls -ldgT \$list > $TMP1 | | 430 | /bin/ls -ldgT \$list > $TMP1 |
431 | end-of-sh | | 431 | end-of-sh |
432 | export PATH=$SAVE_PATH | | 432 | export PATH=$SAVE_PATH |
433 | awk '{ | | 433 | awk '{ |
434 | if ($10 ~ /^\.$/) { | | 434 | if ($10 ~ /^\.$/) { |
435 | print "\tThe root path includes ."; | | 435 | print "\tThe root path includes ."; |
436 | next; | | 436 | next; |
437 | } | | 437 | } |
438 | } | | 438 | } |
439 | $1 ~ /^d....w/ \ | | 439 | $1 ~ /^d....w/ \ |
440 | { print "\tRoot path directory " $10 " is group writable." } \ | | 440 | { print "\tRoot path directory " $10 " is group writable." } \ |
441 | $1 ~ /^d.......w/ \ | | 441 | $1 ~ /^d.......w/ \ |
442 | { print "\tRoot path directory " $10 " is other writable." }' \ | | 442 | { print "\tRoot path directory " $10 " is other writable." }' \ |
443 | < $TMP1 | | 443 | < $TMP1 |
444 | | | 444 | |
445 | fi | | 445 | fi |
446 | done > $OUTPUT | | 446 | done > $OUTPUT |
447 | if [ $umaskset = no ] || [ -s $OUTPUT ] ; then | | 447 | if [ $umaskset = no ] || [ -s $OUTPUT ] ; then |
448 | printf "\nChecking root sh paths, umask values:\n$list\n" | | 448 | printf "\nChecking root sh paths, umask values:\n$list\n" |
449 | if [ -s $OUTPUT ]; then | | 449 | if [ -s $OUTPUT ]; then |
450 | cat $OUTPUT | | 450 | cat $OUTPUT |
451 | fi | | 451 | fi |
452 | if [ $umaskset = no ] ; then | | 452 | if [ $umaskset = no ] ; then |
453 | printf "\tRoot sh startup files do not set the umask.\n" | | 453 | printf "\tRoot sh startup files do not set the umask.\n" |
454 | fi | | 454 | fi |
455 | fi | | 455 | fi |
456 | fi | | 456 | fi |
457 | | | 457 | |
458 | # Root and uucp should both be in /etc/ftpusers. | | 458 | # Root and uucp should both be in /etc/ftpusers. |
459 | # | | 459 | # |
460 | if checkyesno check_ftpusers; then | | 460 | if checkyesno check_ftpusers; then |
461 | list="uucp "$(awk '$2 == 0 { print $1 }' $MPBYUID) | | 461 | list="uucp "$(awk '$2 == 0 { print $1 }' $MPBYUID) |
462 | for i in $list; do | | 462 | for i in $list; do |
463 | if /usr/libexec/ftpd -C $i ; then | | 463 | if /usr/libexec/ftpd -C $i ; then |
464 | printf "\t$i is not denied\n" | | 464 | printf "\t$i is not denied\n" |
465 | fi | | 465 | fi |
466 | done > $OUTPUT | | 466 | done > $OUTPUT |
467 | if [ -s $OUTPUT ]; then | | 467 | if [ -s $OUTPUT ]; then |
468 | printf "\nChecking the /etc/ftpusers configuration:\n" | | 468 | printf "\nChecking the /etc/ftpusers configuration:\n" |
469 | cat $OUTPUT | | 469 | cat $OUTPUT |
470 | fi | | 470 | fi |
471 | fi | | 471 | fi |
472 | | | 472 | |
473 | # Uudecode should not be in the /etc/mail/aliases file. | | 473 | # Uudecode should not be in the /etc/mail/aliases file. |
474 | # | | 474 | # |
475 | if checkyesno check_aliases; then | | 475 | if checkyesno check_aliases; then |
476 | for f in /etc/mail/aliases /etc/aliases; do | | 476 | for f in /etc/mail/aliases /etc/aliases; do |
477 | if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then | | 477 | if [ -f $f ] && egrep '^[^#]*(uudecode|decode).*\|' $f; then |
478 | printf "\nEntry for uudecode in $f file.\n" | | 478 | printf "\nEntry for uudecode in $f file.\n" |
479 | fi | | 479 | fi |
480 | done | | 480 | done |
481 | fi | | 481 | fi |
482 | | | 482 | |
483 | # Files that should not have + signs. | | 483 | # Files that should not have + signs. |
484 | # | | 484 | # |
485 | if checkyesno check_rhosts; then | | 485 | if checkyesno check_rhosts; then |
486 | list="/etc/hosts.equiv /etc/hosts.lpd" | | 486 | list="/etc/hosts.equiv /etc/hosts.lpd" |
487 | for f in $list ; do | | 487 | for f in $list ; do |
488 | if [ -f $f ] && egrep '\+' $f > /dev/null ; then | | 488 | if [ -f $f ] && egrep '\+' $f > /dev/null ; then |
489 | printf "\nPlus sign in $f file.\n" | | 489 | printf "\nPlus sign in $f file.\n" |
490 | fi | | 490 | fi |
491 | done | | 491 | done |
492 | | | 492 | |
493 | # Check for special users with .rhosts files. Only root and toor should | | 493 | # Check for special users with .rhosts files. Only root and toor should |
494 | # have .rhosts files. Also, .rhosts files should not have plus signs. | | 494 | # have .rhosts files. Also, .rhosts files should not have plus signs. |
495 | awk -F: '$1 != "root" && $1 != "toor" && \ | | 495 | awk -F: '$1 != "root" && $1 != "toor" && \ |
496 | ($3 < 100 || $1 == "ftp" || $1 == "uucp") \ | | 496 | ($3 < 100 || $1 == "ftp" || $1 == "uucp") \ |
497 | { print $1 " " $9 }' $MP | | | 497 | { print $1 " " $9 }' $MP | |
498 | sort -k2 | | | 498 | sort -k2 | |
499 | while read uid homedir; do | | 499 | while read uid homedir; do |
500 | if [ -f ${homedir}/.rhosts ] ; then | | 500 | if [ -f ${homedir}/.rhosts ] ; then |
501 | rhost=$(ls -ldgT ${homedir}/.rhosts) | | 501 | rhost=$(ls -ldgT ${homedir}/.rhosts) |
502 | printf -- "$uid: $rhost\n" | | 502 | printf -- "$uid: $rhost\n" |
503 | fi | | 503 | fi |
504 | done > $OUTPUT | | 504 | done > $OUTPUT |
505 | if [ -s $OUTPUT ] ; then | | 505 | if [ -s $OUTPUT ] ; then |
506 | printf "\nChecking for special users with .rhosts files.\n" | | 506 | printf "\nChecking for special users with .rhosts files.\n" |
507 | cat $OUTPUT | | 507 | cat $OUTPUT |
508 | fi | | 508 | fi |
509 | | | 509 | |
510 | while read uid homedir; do | | 510 | while read uid homedir; do |
511 | if [ -f ${homedir}/.rhosts ] && | | 511 | if [ -f ${homedir}/.rhosts ] && |
512 | [ -r ${homedir}/.rhosts ] && | | 512 | [ -r ${homedir}/.rhosts ] && |
513 | cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null | | 513 | cat -f ${homedir}/.rhosts | egrep '\+' > /dev/null |
514 | then | | 514 | then |
515 | printf -- "$uid: + in .rhosts file.\n" | | 515 | printf -- "$uid: + in .rhosts file.\n" |
516 | fi | | 516 | fi |
517 | done < $MPBYPATH > $OUTPUT | | 517 | done < $MPBYPATH > $OUTPUT |
518 | if [ -s $OUTPUT ] ; then | | 518 | if [ -s $OUTPUT ] ; then |
519 | printf "\nChecking .rhosts files syntax.\n" | | 519 | printf "\nChecking .rhosts files syntax.\n" |
520 | cat $OUTPUT | | 520 | cat $OUTPUT |
521 | fi | | 521 | fi |
522 | fi | | 522 | fi |
523 | | | 523 | |
524 | # Check home directories. Directories should not be owned by someone else | | 524 | # Check home directories. Directories should not be owned by someone else |
525 | # or writable. | | 525 | # or writable. |
526 | # | | 526 | # |
527 | if checkyesno check_homes; then | | 527 | if checkyesno check_homes; then |
528 | checkyesno check_homes_permit_usergroups && \ | | 528 | checkyesno check_homes_permit_usergroups && \ |
529 | permit_usergroups=1 || permit_usergroups=0 | | 529 | permit_usergroups=1 || permit_usergroups=0 |
530 | while read uid homedir; do | | 530 | while read uid homedir; do |
531 | if [ -d ${homedir}/ ] ; then | | 531 | if [ -d ${homedir}/ ] ; then |
532 | file=$(ls -ldgT ${homedir}) | | 532 | file=$(ls -ldgT ${homedir}) |
533 | printf -- "$uid $file\n" | | 533 | printf -- "$uid $file\n" |
534 | fi | | 534 | fi |
535 | done < $MPBYPATH | | | 535 | done < $MPBYPATH | |
536 | awk -v "usergroups=$permit_usergroups" \ | | 536 | awk -v "usergroups=$permit_usergroups" \ |
537 | -v "permit_owners_list=$check_homes_permit_other_owner" ' | | 537 | -v "permit_owners_list=$check_homes_permit_other_owner" ' |
538 | BEGIN { | | 538 | BEGIN { |
539 | split(permit_owners_list, a); | | 539 | split(permit_owners_list, a); |
540 | for (i in a) permit_owners[a[i]]++; | | 540 | for (i in a) permit_owners[a[i]]++; |
541 | } | | 541 | } |
542 | $1 != $4 && $4 != "root" && !permit_owners[$1] \ | | 542 | $1 != $4 && $4 != "root" && !permit_owners[$1] \ |
543 | { print "user " $1 " home directory is owned by " $4 } | | 543 | { print "user " $1 " home directory is owned by " $4 } |
544 | $2 ~ /^d....w/ && (!usergroups || $5 != $1) \ | | 544 | $2 ~ /^d....w/ && (!usergroups || $5 != $1) \ |
545 | { print "user " $1 " home directory is group writable" } | | 545 | { print "user " $1 " home directory is group writable" } |
546 | $2 ~ /^d.......w/ \ | | 546 | $2 ~ /^d.......w/ \ |
547 | { print "user " $1 " home directory is other writable" }' \ | | 547 | { print "user " $1 " home directory is other writable" }' \ |
548 | > $OUTPUT | | 548 | > $OUTPUT |
549 | if [ -s $OUTPUT ] ; then | | 549 | if [ -s $OUTPUT ] ; then |
550 | printf "\nChecking home directories.\n" | | 550 | printf "\nChecking home directories.\n" |
551 | cat $OUTPUT | | 551 | cat $OUTPUT |
552 | fi | | 552 | fi |
553 | | | 553 | |
554 | # Files that should not be owned by someone else or readable. | | 554 | # Files that should not be owned by someone else or readable. |
555 | list=".Xauthority .netrc .ssh/id_dsa .ssh/id_rsa .ssh/identity" | | 555 | list=".Xauthority .netrc .ssh/id_dsa .ssh/id_rsa .ssh/identity" |
556 | while read uid homedir; do | | 556 | while read uid homedir; do |
557 | for f in $list ; do | | 557 | for f in $list ; do |
558 | file=${homedir}/${f} | | 558 | file=${homedir}/${f} |
559 | if [ -f $file ] ; then | | 559 | if [ -f $file ] ; then |
560 | printf -- "$uid $f $(ls -ldgT $file)\n" | | 560 | printf -- "$uid $f $(ls -ldgT $file)\n" |
561 | fi | | 561 | fi |
562 | done | | 562 | done |
563 | done < $MPBYPATH | | | 563 | done < $MPBYPATH | |
564 | awk -v "usergroups=$permit_usergroups" \ | | 564 | awk -v "usergroups=$permit_usergroups" \ |
565 | -v "permit_owners_list=$check_homes_permit_other_owner" ' | | 565 | -v "permit_owners_list=$check_homes_permit_other_owner" ' |
566 | BEGIN { | | 566 | BEGIN { |
567 | split(permit_owners_list, a); | | 567 | split(permit_owners_list, a); |
568 | for (i in a) permit_owners[a[i]]++; | | 568 | for (i in a) permit_owners[a[i]]++; |
569 | } | | 569 | } |
570 | $1 != $5 && $5 != "root" && !permit_owners[$1] \ | | 570 | $1 != $5 && $5 != "root" && !permit_owners[$1] \ |
571 | { print "user " $1 " " $2 " file is owned by " $5 } | | 571 | { print "user " $1 " " $2 " file is owned by " $5 } |
572 | $3 ~ /^-...r/ && (!usergroups || $6 != $1) \ | | 572 | $3 ~ /^-...r/ && (!usergroups || $6 != $1) \ |
573 | { print "user " $1 " " $2 " file is group readable" } | | 573 | { print "user " $1 " " $2 " file is group readable" } |
574 | $3 ~ /^-......r/ \ | | 574 | $3 ~ /^-......r/ \ |
575 | { print "user " $1 " " $2 " file is other readable" } | | 575 | { print "user " $1 " " $2 " file is other readable" } |
576 | $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ | | 576 | $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ |
577 | { print "user " $1 " " $2 " file is group writable" } | | 577 | { print "user " $1 " " $2 " file is group writable" } |
578 | $3 ~ /^-.......w/ \ | | 578 | $3 ~ /^-.......w/ \ |
579 | { print "user " $1 " " $2 " file is other writable" }' \ | | 579 | { print "user " $1 " " $2 " file is other writable" }' \ |
580 | > $OUTPUT | | 580 | > $OUTPUT |
581 | | | 581 | |
582 | # Files that should not be owned by someone else or writable. | | 582 | # Files that should not be owned by someone else or writable. |
583 | list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \ | | 583 | list=".bash_history .bash_login .bash_logout .bash_profile .bashrc \ |
584 | .cshrc .emacs .exrc .forward .history .k5login .klogin .login \ | | 584 | .cshrc .emacs .exrc .forward .history .k5login .klogin .login \ |
585 | .logout .profile .qmail .rc_history .rhosts .shosts ssh .tcshrc \ | | 585 | .logout .profile .qmail .rc_history .rhosts .shosts ssh .tcshrc \ |
586 | .twmrc .xinitrc .xsession .ssh/authorized_keys \ | | 586 | .twmrc .xinitrc .xsession .ssh/authorized_keys \ |
587 | .ssh/authorized_keys2 .ssh/config .ssh/id_dsa.pub \ | | 587 | .ssh/authorized_keys2 .ssh/config .ssh/id_dsa.pub \ |
588 | .ssh/id_rsa.pub .ssh/identity.pub .ssh/known_hosts \ | | 588 | .ssh/id_rsa.pub .ssh/identity.pub .ssh/known_hosts \ |
589 | .ssh/known_hosts2" | | 589 | .ssh/known_hosts2" |
590 | while read uid homedir; do | | 590 | while read uid homedir; do |
591 | for f in $list ; do | | 591 | for f in $list ; do |
592 | file=${homedir}/${f} | | 592 | file=${homedir}/${f} |
593 | if [ -f $file ] ; then | | 593 | if [ -f $file ] ; then |
594 | printf -- "$uid $f $(ls -ldgT $file)\n" | | 594 | printf -- "$uid $f $(ls -ldgT $file)\n" |
595 | fi | | 595 | fi |
596 | done | | 596 | done |
597 | done < $MPBYPATH | | | 597 | done < $MPBYPATH | |
598 | awk -v "usergroups=$permit_usergroups" \ | | 598 | awk -v "usergroups=$permit_usergroups" \ |
599 | -v "permit_owners_list=$check_homes_permit_other_owner" ' | | 599 | -v "permit_owners_list=$check_homes_permit_other_owner" ' |
600 | BEGIN { | | 600 | BEGIN { |
601 | split(permit_owners_list, a); | | 601 | split(permit_owners_list, a); |
602 | for (i in a) permit_owners[a[i]]++; | | 602 | for (i in a) permit_owners[a[i]]++; |
603 | } | | 603 | } |
604 | $1 != $5 && $5 != "root" && !permit_owners[$1] \ | | 604 | $1 != $5 && $5 != "root" && !permit_owners[$1] \ |
605 | { print "user " $1 " " $2 " file is owned by " $5 } | | 605 | { print "user " $1 " " $2 " file is owned by " $5 } |
606 | $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ | | 606 | $3 ~ /^-....w/ && (!usergroups || $6 != $1) \ |
607 | { print "user " $1 " " $2 " file is group writable" } | | 607 | { print "user " $1 " " $2 " file is group writable" } |
608 | $3 ~ /^-.......w/ \ | | 608 | $3 ~ /^-.......w/ \ |
609 | { print "user " $1 " " $2 " file is other writable" }' \ | | 609 | { print "user " $1 " " $2 " file is other writable" }' \ |
610 | >> $OUTPUT | | 610 | >> $OUTPUT |
611 | if [ -s $OUTPUT ] ; then | | 611 | if [ -s $OUTPUT ] ; then |
612 | printf "\nChecking dot files.\n" | | 612 | printf "\nChecking dot files.\n" |
613 | cat $OUTPUT | | 613 | cat $OUTPUT |
614 | fi | | 614 | fi |
615 | fi | | 615 | fi |
616 | | | 616 | |
617 | # Mailboxes should be owned by user and unreadable. | | 617 | # Mailboxes should be owned by user and unreadable. |
618 | # | | 618 | # |
619 | if checkyesno check_varmail; then | | 619 | if checkyesno check_varmail; then |
620 | ls -lA /var/mail | \ | | 620 | ls -lA /var/mail | \ |
621 | awk ' NR == 1 { next; } | | 621 | awk ' NR == 1 { next; } |
622 | $9 ~ /^\./ {next; } | | 622 | $9 ~ /^\./ {next; } |
623 | $3 != $9 { | | 623 | $3 != $9 { |
624 | print "user " $9 " mailbox is owned by " $3 | | 624 | print "user " $9 " mailbox is owned by " $3 |
625 | } | | 625 | } |
626 | $1 != "-rw-------" { | | 626 | $1 != "-rw-------" { |
627 | print "user " $9 " mailbox is " $1 ", group " $4 | | 627 | print "user " $9 " mailbox is " $1 ", group " $4 |
628 | }' > $OUTPUT | | 628 | }' > $OUTPUT |
629 | if [ -s $OUTPUT ] ; then | | 629 | if [ -s $OUTPUT ] ; then |
630 | printf "\nChecking mailbox ownership.\n" | | 630 | printf "\nChecking mailbox ownership.\n" |
631 | cat $OUTPUT | | 631 | cat $OUTPUT |
632 | fi | | 632 | fi |
633 | fi | | 633 | fi |
634 | | | 634 | |
635 | # NFS exports shouldn't be globally exported | | 635 | # NFS exports shouldn't be globally exported |
636 | # | | 636 | # |
637 | if checkyesno check_nfs && [ -f /etc/exports ]; then | | 637 | if checkyesno check_nfs && [ -f /etc/exports ]; then |
638 | awk '{ | | 638 | awk '{ |
639 | # ignore comments and blank lines | | 639 | # ignore comments and blank lines |
640 | if ($0 ~ /^\#/ || $0 ~ /^$/ ) | | 640 | if ($0 ~ /^\#/ || $0 ~ /^$/ ) |
641 | next; | | 641 | next; |
642 | # manage line continuation | | 642 | # manage line continuation |
643 | while ($NF ~ /^\\$/) { | | 643 | while ($NF ~ /^\\$/) { |
644 | $NF = ""; | | 644 | $NF = ""; |
645 | line = $0 ""; | | 645 | line = $0 ""; |
646 | getline; | | 646 | getline; |
647 | $0 = line $0 ""; | | 647 | $0 = line $0 ""; |
648 | } | | 648 | } |
649 | | | 649 | |
650 | delete dir; | | 650 | delete dir; |
651 | readonly = ndir = 0; | | 651 | readonly = ndir = 0; |
652 | for (i = 1; i <= NF; ++i) { | | 652 | for (i = 1; i <= NF; ++i) { |
653 | if ($i ~ /^\//) dir[ndir++] = $i; | | 653 | if ($i ~ /^\//) dir[ndir++] = $i; |
654 | else if ($i ~ /^-/) { | | 654 | else if ($i ~ /^-/) { |
655 | if ($i ~ /^-(ro|o)$/) readonly = 1; | | 655 | if ($i ~ /^-(ro|o)$/) readonly = 1; |
656 | if ($i ~ /^-network/) next; | | 656 | if ($i ~ /^-network/) next; |
657 | } | | 657 | } |
658 | else next; | | 658 | else next; |
659 | } | | 659 | } |
660 | if (readonly) | | 660 | if (readonly) |
661 | for (item in dir) | | 661 | for (item in dir) |
662 | rodir[nrodir++] = dir[item]; | | 662 | rodir[nrodir++] = dir[item]; |
663 | else | | 663 | else |
664 | for (item in dir) | | 664 | for (item in dir) |
665 | rwdir[nrwdir++] = dir[item]; | | 665 | rwdir[nrwdir++] = dir[item]; |
666 | | | 666 | |
667 | } | | 667 | } |
668 | | | 668 | |
669 | END { | | 669 | END { |
670 | if (nrodir) { | | 670 | if (nrodir) { |
671 | printf("Globally exported file system%s, read-only:\n", | | 671 | printf("Globally exported file system%s, read-only:\n", |
672 | nrodir > 1 ? "s" : ""); | | 672 | nrodir > 1 ? "s" : ""); |
673 | for (item in rodir) | | 673 | for (item in rodir) |
674 | printf("\t%s\n", rodir[item]); | | 674 | printf("\t%s\n", rodir[item]); |
675 | } | | 675 | } |
676 | if (nrwdir) { | | 676 | if (nrwdir) { |
677 | printf("Globally exported file system%s, read-write:\n", | | 677 | printf("Globally exported file system%s, read-write:\n", |
678 | nrwdir > 1 ? "s" : ""); | | 678 | nrwdir > 1 ? "s" : ""); |
679 | for (item in rwdir) | | 679 | for (item in rwdir) |
680 | printf("\t%s\n", rwdir[item]); | | 680 | printf("\t%s\n", rwdir[item]); |
681 | } | | 681 | } |
682 | }' < /etc/exports > $OUTPUT | | 682 | }' < /etc/exports > $OUTPUT |
683 | if [ -s $OUTPUT ] ; then | | 683 | if [ -s $OUTPUT ] ; then |
684 | printf "\nChecking for globally exported file systems.\n" | | 684 | printf "\nChecking for globally exported file systems.\n" |
685 | cat $OUTPUT | | 685 | cat $OUTPUT |
686 | fi | | 686 | fi |
687 | fi | | 687 | fi |
688 | | | 688 | |
689 | # Display any changes in setuid files and devices. | | 689 | # Display any changes in setuid files and devices. |
690 | # | | 690 | # |
691 | if checkyesno check_devices; then | | 691 | if checkyesno check_devices; then |
692 | > $ERR | | 692 | > $ERR |
693 | ( | | 693 | ( |
694 | | | 694 | |
695 | # Convert check_devices_ignore_fstypes="foo !bar bax" | | 695 | # Convert check_devices_ignore_fstypes="foo !bar bax" |
696 | # into "-fstype foo -o ! -fstype bar -o -fstype bax" | | 696 | # into "-fstype foo -o ! -fstype bar -o -fstype bax" |
697 | # and check_devices_ignore_paths="/foo !/bar /bax" | | 697 | # and check_devices_ignore_paths="/foo !/bar /bax" |
698 | # into " -path /foo -o ! -path /bar -o -path /bax" | | 698 | # into " -path /foo -o ! -path /bar -o -path /bax" |
699 | # | | 699 | # |
700 | ignexpr=$(\ | | 700 | ignexpr=$(\ |
701 | echo $check_devices_ignore_fstypes | \ | | 701 | echo $check_devices_ignore_fstypes | \ |
702 | sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -fstype \2/g' ; \ | | 702 | sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -fstype \2/g' ; \ |
703 | echo $check_devices_ignore_paths | \ | | 703 | echo $check_devices_ignore_paths | \ |
704 | sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -path \2/g' \ | | 704 | sed -e's/\(!*\)\([^[:space:]]\{1,\}\)/-o \1 -path \2/g' \ |
705 | ) | | 705 | ) |
706 | | | 706 | |
707 | # Massage the expression into ( $ignexpr ) -a -prune -o | | 707 | # Massage the expression into ( $ignexpr ) -a -prune -o |
708 | if [ -n "${ignexpr}" ]; then | | 708 | if [ -n "${ignexpr}" ]; then |
709 | ignexpr=$(\ | | 709 | ignexpr=$(\ |
710 | echo $ignexpr | \ | | 710 | echo $ignexpr | \ |
711 | sed -e 's/^-o /( /' \ | | 711 | sed -e 's/^-o /( /' \ |
712 | -e 's/$/ ) -a -prune -o/' \ | | 712 | -e 's/$/ ) -a -prune -o/' \ |
713 | ) | | 713 | ) |
714 | fi | | 714 | fi |
715 | | | 715 | |
716 | find / $ignexpr \ | | 716 | find / $ignexpr \ |
717 | \( \( -perm -u+s -a ! -type d \) -o \ | | 717 | \( \( -perm -u+s -a ! -type d \) -o \ |
718 | \( -perm -g+s -a ! -type d \) -o \ | | 718 | \( -perm -g+s -a ! -type d \) -o \ |
719 | -type b -o -type c \) -print0 | \ | | 719 | -type b -o -type c \) -print0 | \ |
720 | xargs -0 ls -ldgTq | sort +9 > $LIST | | 720 | xargs -0 ls -ldgTq | sort +9 > $LIST |
721 | | | 721 | |
722 | ) 2> $OUTPUT | | 722 | ) 2> $OUTPUT |
723 | | | 723 | |
724 | # Display any errors that occurred during system file walk. | | 724 | # Display any errors that occurred during system file walk. |
725 | if [ -s $OUTPUT ] ; then | | 725 | if [ -s $OUTPUT ] ; then |
726 | printf "Setuid/device find errors:\n" >> $ERR | | 726 | printf "Setuid/device find errors:\n" >> $ERR |
727 | cat $OUTPUT >> $ERR | | 727 | cat $OUTPUT >> $ERR |
728 | printf "\n" >> $ERR | | 728 | printf "\n" >> $ERR |
729 | fi | | 729 | fi |
730 | | | 730 | |
731 | # Display any changes in the setuid file list. | | 731 | # Display any changes in the setuid file list. |
732 | egrep -v '^[bc]' $LIST > $TMP1 | | 732 | egrep -v '^[bc]' $LIST > $TMP1 |
733 | if [ -s $TMP1 ] ; then | | 733 | if [ -s $TMP1 ] ; then |
734 | # Check to make sure uudecode isn't setuid. | | 734 | # Check to make sure uudecode isn't setuid. |
735 | if grep -w uudecode $TMP1 > /dev/null ; then | | 735 | if grep -w uudecode $TMP1 > /dev/null ; then |
736 | printf "\nUudecode is setuid.\n" >> $ERR | | 736 | printf "\nUudecode is setuid.\n" >> $ERR |
737 | fi | | 737 | fi |
738 | | | 738 | |
739 | file=$work_dir/setuid | | 739 | file=$work_dir/setuid |
740 | migrate_file "$backup_dir/setuid" "$file" | | 740 | migrate_file "$backup_dir/setuid" "$file" |
741 | CUR=${file}.current | | 741 | CUR=${file}.current |
742 | BACK=${file}.backup | | 742 | BACK=${file}.backup |
743 | if [ -s $CUR ] ; then | | 743 | if [ -s $CUR ] ; then |
744 | if cmp -s $CUR $TMP1 ; then | | 744 | if cmp -s $CUR $TMP1 ; then |
745 | : | | 745 | : |
746 | else | | 746 | else |
747 | > $TMP2 | | 747 | > $TMP2 |
748 | join -110 -210 -v2 $CUR $TMP1 > $OUTPUT | | 748 | join -110 -210 -v2 $CUR $TMP1 > $OUTPUT |
749 | if [ -s $OUTPUT ] ; then | | 749 | if [ -s $OUTPUT ] ; then |
750 | printf "Setuid additions:\n" >> $ERR | | 750 | printf "Setuid additions:\n" >> $ERR |
751 | tee -a $TMP2 < $OUTPUT >> $ERR | | 751 | tee -a $TMP2 < $OUTPUT >> $ERR |
752 | printf "\n" >> $ERR | | 752 | printf "\n" >> $ERR |
753 | fi | | 753 | fi |
754 | | | 754 | |
755 | join -110 -210 -v1 $CUR $TMP1 > $OUTPUT | | 755 | join -110 -210 -v1 $CUR $TMP1 > $OUTPUT |
756 | if [ -s $OUTPUT ] ; then | | 756 | if [ -s $OUTPUT ] ; then |
757 | printf "Setuid deletions:\n" >> $ERR | | 757 | printf "Setuid deletions:\n" >> $ERR |
758 | tee -a $TMP2 < $OUTPUT >> $ERR | | 758 | tee -a $TMP2 < $OUTPUT >> $ERR |
759 | printf "\n" >> $ERR | | 759 | printf "\n" >> $ERR |
760 | fi | | 760 | fi |
761 | | | 761 | |
762 | sort -k10 $TMP2 $CUR $TMP1 | \ | | 762 | sort -k10 $TMP2 $CUR $TMP1 | \ |
763 | sed -e 's/[ ][ ]*/ /g' | \ | | 763 | sed -e 's/[ ][ ]*/ /g' | \ |
764 | uniq -u > $OUTPUT | | 764 | uniq -u > $OUTPUT |
765 | if [ -s $OUTPUT ] ; then | | 765 | if [ -s $OUTPUT ] ; then |
766 | printf "Setuid changes:\n" >> $ERR | | 766 | printf "Setuid changes:\n" >> $ERR |
767 | column -t $OUTPUT >> $ERR | | 767 | column -t $OUTPUT >> $ERR |
768 | printf "\n" >> $ERR | | 768 | printf "\n" >> $ERR |
769 | fi | | 769 | fi |
770 | | | 770 | |
771 | backup_file update $TMP1 $CUR $BACK | | 771 | backup_file update $TMP1 $CUR $BACK |
772 | fi | | 772 | fi |
773 | else | | 773 | else |
774 | printf "Setuid additions:\n" >> $ERR | | 774 | printf "Setuid additions:\n" >> $ERR |
775 | column -t $TMP1 >> $ERR | | 775 | column -t $TMP1 >> $ERR |
776 | printf "\n" >> $ERR | | 776 | printf "\n" >> $ERR |
777 | backup_file add $TMP1 $CUR $BACK | | 777 | backup_file add $TMP1 $CUR $BACK |
778 | fi | | 778 | fi |
779 | fi | | 779 | fi |
780 | | | 780 | |
781 | # Check for block and character disk devices that are readable or | | 781 | # Check for block and character disk devices that are readable or |
782 | # writable or not owned by root.operator. | | 782 | # writable or not owned by root.operator. |
783 | >$TMP1 | | 783 | >$TMP1 |
784 | DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \ | | 784 | DISKLIST="ccd ch hk hp ld md ra raid rb rd rl rx \ |
785 | sd se ss uk up vnd wd xd xy" | | 785 | sd se ss uk up vnd wd xd xy" |
786 | # DISKLIST="$DISKLIST ct mt st wt" | | 786 | # DISKLIST="$DISKLIST ct mt st wt" |
787 | for i in $DISKLIST; do | | 787 | for i in $DISKLIST; do |
788 | egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 | | 788 | egrep "^b.*/${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 |
789 | egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 | | 789 | egrep "^c.*/r${i}[0-9][0-9]*[a-p]$" $LIST >> $TMP1 |
790 | done | | 790 | done |
791 | | | 791 | |
792 | awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \ | | 792 | awk '$3 != "root" || $4 != "operator" || $1 !~ /.rw-r-----/ \ |
793 | { printf "Disk %s is user %s, group %s, permissions %s.\n", \ | | 793 | { printf "Disk %s is user %s, group %s, permissions %s.\n", \ |
794 | $11, $3, $4, $1; }' < $TMP1 > $OUTPUT | | 794 | $11, $3, $4, $1; }' < $TMP1 > $OUTPUT |
795 | if [ -s $OUTPUT ] ; then | | 795 | if [ -s $OUTPUT ] ; then |
796 | printf "\nChecking disk ownership and permissions.\n" >> $ERR | | 796 | printf "\nChecking disk ownership and permissions.\n" >> $ERR |
797 | cat $OUTPUT >> $ERR | | 797 | cat $OUTPUT >> $ERR |
798 | printf "\n" >> $ERR | | 798 | printf "\n" >> $ERR |
799 | fi | | 799 | fi |
800 | | | 800 | |
801 | # Display any changes in the device file list. | | 801 | # Display any changes in the device file list. |
802 | egrep '^[bc]' $LIST | sort -k11 > $TMP1 | | 802 | egrep '^[bc]' $LIST | sort -k11 > $TMP1 |
803 | if [ -s $TMP1 ] ; then | | 803 | if [ -s $TMP1 ] ; then |
804 | file=$work_dir/device | | 804 | file=$work_dir/device |
805 | migrate_file "$backup_dir/device" "$file" | | 805 | migrate_file "$backup_dir/device" "$file" |
806 | CUR=${file}.current | | 806 | CUR=${file}.current |
807 | BACK=${file}.backup | | 807 | BACK=${file}.backup |
808 | | | 808 | |
809 | if [ -s $CUR ] ; then | | 809 | if [ -s $CUR ] ; then |
810 | if cmp -s $CUR $TMP1 ; then | | 810 | if cmp -s $CUR $TMP1 ; then |
811 | : | | 811 | : |
812 | else | | 812 | else |
813 | > $TMP2 | | 813 | > $TMP2 |
814 | join -111 -211 -v2 $CUR $TMP1 > $OUTPUT | | 814 | join -111 -211 -v2 $CUR $TMP1 > $OUTPUT |
815 | if [ -s $OUTPUT ] ; then | | 815 | if [ -s $OUTPUT ] ; then |
816 | printf "Device additions:\n" >> $ERR | | 816 | printf "Device additions:\n" >> $ERR |
817 | tee -a $TMP2 < $OUTPUT >> $ERR | | 817 | tee -a $TMP2 < $OUTPUT >> $ERR |
818 | printf "\n" >> $ERR | | 818 | printf "\n" >> $ERR |
819 | fi | | 819 | fi |
820 | | | 820 | |
821 | join -111 -211 -v1 $CUR $TMP1 > $OUTPUT | | 821 | join -111 -211 -v1 $CUR $TMP1 > $OUTPUT |
822 | if [ -s $OUTPUT ] ; then | | 822 | if [ -s $OUTPUT ] ; then |
823 | printf "Device deletions:\n" >> $ERR | | 823 | printf "Device deletions:\n" >> $ERR |
824 | tee -a $TMP2 < $OUTPUT >> $ERR | | 824 | tee -a $TMP2 < $OUTPUT >> $ERR |
825 | printf "\n" >> $ERR | | 825 | printf "\n" >> $ERR |
826 | fi | | 826 | fi |
827 | | | 827 | |
828 | # Report any block device change. Ignore | | 828 | # Report any block device change. Ignore |
829 | # character devices, only the name is | | 829 | # character devices, only the name is |
830 | # significant. | | 830 | # significant. |
831 | cat $TMP2 $CUR $TMP1 | \ | | 831 | cat $TMP2 $CUR $TMP1 | \ |
832 | sed -e '/^c/d' | \ | | 832 | sed -e '/^c/d' | \ |
833 | sort -k11 | \ | | 833 | sort -k11 | \ |
834 | sed -e 's/[ ][ ]*/ /g' | \ | | 834 | sed -e 's/[ ][ ]*/ /g' | \ |
835 | uniq -u > $OUTPUT | | 835 | uniq -u > $OUTPUT |
836 | if [ -s $OUTPUT ] ; then | | 836 | if [ -s $OUTPUT ] ; then |
837 | printf "Block device changes:\n" >> $ERR | | 837 | printf "Block device changes:\n" >> $ERR |
838 | column -t $OUTPUT >> $ERR | | 838 | column -t $OUTPUT >> $ERR |
839 | printf "\n" >> $ERR | | 839 | printf "\n" >> $ERR |
840 | fi | | 840 | fi |
841 | | | 841 | |
842 | backup_file update $TMP1 $CUR $BACK | | 842 | backup_file update $TMP1 $CUR $BACK |
843 | fi | | 843 | fi |
844 | else | | 844 | else |
845 | printf "Device additions:\n" >> $ERR | | 845 | printf "Device additions:\n" >> $ERR |
846 | column -t $TMP1 >> $ERR | | 846 | column -t $TMP1 >> $ERR |
847 | printf "\n" >> $ERR | | 847 | printf "\n" >> $ERR |
848 | backup_file add $TMP1 $CUR $BACK >> $ERR | | 848 | backup_file add $TMP1 $CUR $BACK >> $ERR |
849 | fi | | 849 | fi |
850 | fi | | 850 | fi |
851 | if [ -s $ERR ] ; then | | 851 | if [ -s $ERR ] ; then |
852 | printf "\nChecking setuid files and devices:\n" | | 852 | printf "\nChecking setuid files and devices:\n" |
853 | cat $ERR | | 853 | cat $ERR |
854 | printf "\n" | | 854 | printf "\n" |
855 | fi | | 855 | fi |
856 | fi | | 856 | fi |
857 | | | 857 | |
858 | # Check special files. | | 858 | # Check special files. |
859 | # Check system binaries. | | 859 | # Check system binaries. |
860 | # | | 860 | # |
861 | # Create the mtree tree specifications using: | | 861 | # Create the mtree tree specifications using: |
862 | # mtree -cx -pDIR -kmd5,uid,gid,mode,nlink,size,link,time > DIR.secure | | 862 | # mtree -cx -pDIR -kmd5,uid,gid,mode,nlink,size,link,time > DIR.secure |
863 | # chown root:wheel DIR.secure | | 863 | # chown root:wheel DIR.secure |
864 | # chmod u+r,go= DIR.secure | | 864 | # chmod u+r,go= DIR.secure |
865 | # | | 865 | # |
866 | # Note, this is not complete protection against Trojan horsed binaries, as | | 866 | # Note, this is not complete protection against Trojan horsed binaries, as |
867 | # the hacker can modify the tree specification to match the replaced binary. | | 867 | # the hacker can modify the tree specification to match the replaced binary. |
868 | # For details on really protecting yourself against modified binaries, see | | 868 | # For details on really protecting yourself against modified binaries, see |
869 | # the mtree(8) manual page. | | 869 | # the mtree(8) manual page. |
870 | # | | 870 | # |
871 | if checkyesno check_mtree; then | | 871 | if checkyesno check_mtree; then |
872 | if checkyesno check_mtree_follow_symlinks; then | | 872 | if checkyesno check_mtree_follow_symlinks; then |
873 | check_mtree_flags="-L" | | 873 | check_mtree_flags="-L" |
874 | else | | 874 | else |
875 | check_mtree_flags="" | | 875 | check_mtree_flags="" |
876 | fi | | 876 | fi |
877 | mtree -e -l -p / $check_mtree_flags -f $SPECIALSPEC 3>&1 >$OUTPUT 2>&3 | | | 877 | mtree -e -l -p / $check_mtree_flags -f $SPECIALSPEC 3>&1 >$OUTPUT 2>&3 | |
878 | grep -v '^mtree: dev/tty: Device not configured$' >&2 | | 878 | grep -v '^mtree: dev/tty: Device not configured$' >&2 |
879 | if [ -s $OUTPUT ]; then | | 879 | if [ -s $OUTPUT ]; then |
880 | printf "\nChecking special files and directories.\n" | | 880 | printf "\nChecking special files and directories.\n" |
881 | cat $OUTPUT | | 881 | cat $OUTPUT |
882 | fi | | 882 | fi |
883 | | | 883 | |
884 | for file in /etc/mtree/*.secure; do | | 884 | for file in /etc/mtree/*.secure; do |
885 | [ $file = '/etc/mtree/*.secure' ] && continue | | 885 | [ $file = '/etc/mtree/*.secure' ] && continue |
886 | tree=$(sed -n -e '3s/.* //p' -e 3q $file) | | 886 | tree=$(sed -n -e '3s/.* //p' -e 3q $file) |
887 | mtree $check_mtree_flags -f $file -p $tree > $TMP1 | | 887 | mtree $check_mtree_flags -f $file -p $tree > $TMP1 |
888 | if [ -s $TMP1 ]; then | | 888 | if [ -s $TMP1 ]; then |
889 | printf "\nChecking $tree:\n" | | 889 | printf "\nChecking $tree:\n" |
890 | cat $TMP1 | | 890 | cat $TMP1 |
891 | fi | | 891 | fi |
892 | done > $OUTPUT | | 892 | done > $OUTPUT |
893 | if [ -s $OUTPUT ]; then | | 893 | if [ -s $OUTPUT ]; then |
894 | printf "\nChecking system binaries:\n" | | 894 | printf "\nChecking system binaries:\n" |
895 | cat $OUTPUT | | 895 | cat $OUTPUT |
896 | fi | | 896 | fi |
897 | fi | | 897 | fi |
898 | | | 898 | |
899 | # Backup disklabels of available disks | | 899 | # Backup disklabels of available disks |
900 | # | | 900 | # |
901 | if checkyesno check_disklabels; then | | 901 | if checkyesno check_disklabels; then |
902 | # migrate old disklabels | | 902 | # migrate old disklabels |
903 | for file in $(ls -1d $backup_dir/$backup_dir/disklabel.* \ | | 903 | for file in $(ls -1d $backup_dir/$backup_dir/disklabel.* \ |
904 | $backup_dir/disklabel.* 2>/dev/null); do | | 904 | $backup_dir/disklabel.* 2>/dev/null); do |
905 | migrate_file "$file" "$work_dir/${file##*/}" | | 905 | migrate_file "$file" "$work_dir/${file##*/}" |
906 | done | | 906 | done |
907 | | | 907 | |
908 | # generate list of old disklabels, fdisks & wedges, | | 908 | # generate list of old disklabels, fdisks & wedges, |
909 | # and remove them | | 909 | # and remove them |
910 | ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ | | 910 | ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ |
911 | 2>/dev/null | | | 911 | 2>/dev/null | |
912 | egrep -v '\.(backup|current)(,v)?$' > $LABELS | | 912 | egrep -v '\.(backup|current)(,v)?$' > $LABELS |
913 | xargs rm < $LABELS | | 913 | xargs rm < $LABELS |
914 | | | 914 | |
915 | disks="$(/sbin/sysctl -n hw.iostatnames)" | | 915 | disks="$(/sbin/sysctl -n hw.iostatnames)" |
916 | | | 916 | |
917 | # generate disklabels of all disks excluding: cd fd md dk st | | 917 | # generate disklabels of all disks excluding: cd fd md dk st |
918 | # nfs and "device" (the header of iostat) | | 918 | # nfs and "device" (the header of iostat) |
919 | for i in $disks; do | | 919 | for i in $disks; do |
920 | case $i in | | 920 | case $i in |
921 | [cfm]d[0-9]*|dk[0-9]*|st[0-9]*|nfs[0-9]*) | | 921 | [cfm]d[0-9]*|dk[0-9]*|st[0-9]*|nfs[0-9]*) |
922 | ;; | | 922 | ;; |
923 | *) | | 923 | *) |
924 | if disklabel $i > /dev/null 2>&1; then | | 924 | if disklabel $i > /dev/null 2>&1; then |
925 | disklabel $i > "$work_dir/disklabel.$i" | | 925 | disklabel $i > "$work_dir/disklabel.$i" |
926 | fi | | 926 | fi |
927 | ;; | | 927 | ;; |
928 | esac | | 928 | esac |
929 | done | | 929 | done |
930 | | | 930 | |
931 | # if fdisk is available, generate fdisks for: ed ld sd wd | | 931 | # if fdisk is available, generate fdisks for: ed ld sd wd |
932 | if [ -x /sbin/fdisk ]; then | | 932 | if [ -x /sbin/fdisk ]; then |
933 | for i in $disks; do | | 933 | for i in $disks; do |
934 | case $i in | | 934 | case $i in |
935 | [elsw]d[0-9]*) | | 935 | [elsw]d[0-9]*) |
936 | /sbin/fdisk $i > "$work_dir/fdisk.$i" \ | | 936 | /sbin/fdisk $i > "$work_dir/fdisk.$i" \ |
937 | 2>/dev/null | | 937 | 2>/dev/null |
938 | ;; | | 938 | ;; |
939 | esac | | 939 | esac |
940 | done | | 940 | done |
941 | fi | | 941 | fi |
942 | | | 942 | |
943 | # if dkctl is available, generate dkctl listwedges | | 943 | # if dkctl is available, generate dkctl listwedges |
944 | # for: ed ld sd wd cgd ofdisk ra rl raid | | 944 | # for: ed ld sd wd cgd ofdisk ra rl raid |
945 | if [ -x /sbin/dkctl ]; then | | 945 | if [ -x /sbin/dkctl ]; then |
946 | for i in $disks; do | | 946 | for i in $disks; do |
947 | case $i in | | 947 | case $i in |
948 | [elsw]d[0-9]*|cgd[0-9]*|ofdisk[0-9]*|r[al][0-9]*|raid[0-9]*) | | 948 | [elsw]d[0-9]*|cgd[0-9]*|ofdisk[0-9]*|r[al][0-9]*|raid[0-9]*) |
949 | if /sbin/dkctl $i listwedges | | | 949 | if /sbin/dkctl $i listwedges | |
950 | grep -qe '[0-9] wedges:'; then | | 950 | grep -qe '[0-9] wedges:'; then |
951 | /sbin/dkctl $i listwedges \ | | 951 | /sbin/dkctl $i listwedges \ |
952 | > "$work_dir/wedges.$i" 2>/dev/null | | 952 | > "$work_dir/wedges.$i" 2>/dev/null |
953 | fi | | 953 | fi |
954 | ;; | | 954 | ;; |
955 | esac | | 955 | esac |
956 | done | | 956 | done |
957 | fi | | 957 | fi |
958 | | | 958 | |
959 | # if raidctl is available, generate raidctls for: raid | | 959 | # if raidctl is available, generate raidctls for: raid |
960 | if [ -x /sbin/raidctl ]; then | | 960 | if [ -x /sbin/raidctl ]; then |
961 | disks=$(iostat -x | awk 'NR > 1 && $1 ~ /^raid/ { print $1; }') | | 961 | disks=$(iostat -x | awk 'NR > 1 && $1 ~ /^raid/ { print $1; }') |
962 | for i in $disks; do | | 962 | for i in $disks; do |
963 | /sbin/raidctl -G $i > "$work_dir/raidconf.$i" \ | | 963 | /sbin/raidctl -G $i > "$work_dir/raidconf.$i" \ |
964 | 2>/dev/null | | 964 | 2>/dev/null |
965 | done | | 965 | done |
966 | fi | | 966 | fi |
967 | | | 967 | |
968 | # append list of new disklabels, fdisks and wedges | | 968 | # append list of new disklabels, fdisks and wedges |
969 | ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ | | 969 | ls -1d $work_dir/disklabel.* $work_dir/fdisk.* $work_dir/wedges.* \ |
970 | $work_dir/raidconf.* 2>/dev/null | | | 970 | $work_dir/raidconf.* 2>/dev/null | |
971 | egrep -v '\.(backup|current)(,v)?$' >> $LABELS | | 971 | egrep -v '\.(backup|current)(,v)?$' >> $LABELS |
972 | CHANGELIST="$LABELS $CHANGELIST" | | 972 | CHANGELIST="$LABELS $CHANGELIST" |
973 | fi | | 973 | fi |
974 | | | 974 | |
975 | if checkyesno check_lvm; then | | 975 | if checkyesno check_lvm; then |
976 | # generate list of existing LVM elements Physical Volumes, | | 976 | # generate list of existing LVM elements Physical Volumes, |
977 | # Volume Groups and Logical Volumes. | | 977 | # Volume Groups and Logical Volumes. |
978 | if [ -x /sbin/lvm ]; then | | 978 | if [ -x /sbin/lvm ]; then |
979 | lvm pvdisplay -m >"$work_dir/lvm.pv" 2>/dev/null | | 979 | lvm pvdisplay -m >"$work_dir/lvm.pv" 2>/dev/null |
980 | lvm vgdisplay -m >"$work_dir/lvm.vg" 2>/dev/null | | 980 | lvm vgdisplay -m >"$work_dir/lvm.vg" 2>/dev/null |
981 | lvm lvdisplay -m >"$work_dir/lvm.lv" 2>/dev/null | | 981 | lvm lvdisplay -m >"$work_dir/lvm.lv" 2>/dev/null |
982 | fi | | 982 | fi |
983 | ls -1d $work_dir/lvm.* 2>/dev/null | | | 983 | ls -1d $work_dir/lvm.* 2>/dev/null | |
984 | egrep -v '\.(backup|current)(,v)?$'>> $LVM_LABELS | | 984 | egrep -v '\.(backup|current)(,v)?$'>> $LVM_LABELS |
985 | CHANGELIST="$CHANGELIST $LVM_LABELS" | | 985 | CHANGELIST="$CHANGELIST $LVM_LABELS" |
986 | fi | | 986 | fi |
987 | | | 987 | |
988 | # Check for changes in the list of installed pkgs | | 988 | # Check for changes in the list of installed pkgs |
989 | # | | 989 | # |
990 | if checkyesno check_pkgs && have_pkgs; then | | 990 | if checkyesno check_pkgs && have_pkgs; then |
991 | pkgs=$work_dir/pkgs | | 991 | pkgs=$work_dir/pkgs |
992 | migrate_file "$backup_dir/pkgs" "$pkgs" | | 992 | migrate_file "$backup_dir/pkgs" "$pkgs" |
993 | pkg_dbdir=$(${pkg_admin} config-var PKG_DBDIR) | | 993 | pkg_dbdir=$(${pkg_admin} config-var PKG_DBDIR) |
994 | : ${pkg_dbdir:=/var/db/pkg} | | 994 | : ${pkg_dbdir:=/var/db/pkg} |
995 | ( cd $pkg_dbdir | | 995 | ( cd $pkg_dbdir |
996 | $pkg_info | sort | | 996 | $pkg_info | sort |
997 | echo "" | | 997 | echo "" |
998 | find . \( -name +REQUIRED_BY -o -name +CONTENTS \) -print0 | | | 998 | find . \( -name +REQUIRED_BY -o -name +CONTENTS \) -print0 | |
999 | xargs -0 ls -ldgTq | sort -t. +1 | sed -e 's, \./, ,' | | 999 | xargs -0 ls -ldgTq | sort -t. +1 | sed -e 's, \./, ,' |
1000 | ) > $pkgs | | 1000 | ) > $pkgs |
1001 | echo "$pkgs" > $PKGS | | 1001 | echo "$pkgs" > $PKGS |
1002 | CHANGELIST="$PKGS $CHANGELIST" | | 1002 | CHANGELIST="$PKGS $CHANGELIST" |
1003 | fi | | 1003 | fi |
1004 | | | 1004 | |
1005 | # List of files that get backed up and checked for any modifications. | | 1005 | # List of files that get backed up and checked for any modifications. |
1006 | # Any changes cause the files to rotate. | | 1006 | # Any changes cause the files to rotate. |
1007 | # | | 1007 | # |
1008 | if checkyesno check_changelist ; then | | 1008 | if checkyesno check_changelist ; then |
1009 | mtree -D -k type -f $SPECIALSPEC -E exclude | | | 1009 | mtree -D -k type -f $SPECIALSPEC -E exclude | |
1010 | sed '/^type=file/!d ; s/type=file \.//' | unvis > $CHANGEFILES | | 1010 | sed '/^type=file/!d ; s/type=file \.//' | unvis > $CHANGEFILES |
1011 | | | 1011 | |
1012 | ( | | 1012 | ( |
1013 | # Add other files which might dynamically exist: | | 1013 | # Add other files which might dynamically exist: |
1014 | # /etc/ifconfig.* | | 1014 | # /etc/ifconfig.* |
1015 | # /etc/raid*.conf | | 1015 | # /etc/raid*.conf |
1016 | # /etc/rc.d/* | | 1016 | # /etc/rc.d/* |
1017 | # /etc/rc.conf.d/* | | 1017 | # /etc/rc.conf.d/* |
1018 | # | | 1018 | # |
1019 | echo "/etc/ifconfig.*" | | 1019 | echo "/etc/ifconfig.*" |
1020 | echo "/etc/raid*.conf" | | 1020 | echo "/etc/raid*.conf" |
1021 | echo "/etc/rc.d/*" | | 1021 | echo "/etc/rc.d/*" |
1022 | echo "/etc/rc.conf.d/*" | | 1022 | echo "/etc/rc.conf.d/*" |
1023 | echo "/etc/lvm/backup/*" | | 1023 | echo "/etc/lvm/backup/*" |
1024 | echo "/etc/lvm/archive/*" | | 1024 | echo "/etc/lvm/archive/*" |
1025 | | | 1025 | |
1026 | # Add /etc/changelist | | 1026 | # Add /etc/changelist |
1027 | # | | 1027 | # |
1028 | if [ -s /etc/changelist ]; then | | 1028 | if [ -s /etc/changelist ]; then |
1029 | grep -v '^#' /etc/changelist | | 1029 | grep -v '^#' /etc/changelist |
1030 | fi | | 1030 | fi |
1031 | ) | while read file; do | | 1031 | ) | while read file; do |
1032 | case "$file" in | | 1032 | case "$file" in |
1033 | *[\*\?\[]*) # If changelist line is a glob ... | | 1033 | *[\*\?\[]*) # If changelist line is a glob ... |
1034 | # ... expand possible backup files | | 1034 | # ... expand possible backup files |
1035 | # | | 1035 | # |
1036 | ls -1d $backup_dir/${file}.current 2>/dev/null \ | | 1036 | ls -1d $backup_dir/${file}.current 2>/dev/null \ |
1037 | | sed "s,^$backup_dir/,, ; s,\.current$,," | | 1037 | | sed "s,^$backup_dir/,, ; s,\.current$,," |
1038 | | | 1038 | |
1039 | # ... expand possible files | | 1039 | # ... expand possible files |
1040 | # | | 1040 | # |
1041 | ls -1d $file 2>/dev/null | | 1041 | ls -1d $file 2>/dev/null |
1042 | ;; | | 1042 | ;; |
1043 | *) | | 1043 | *) |
1044 | # Otherwise, just print the filename | | 1044 | # Otherwise, just print the filename |
1045 | echo $file | | 1045 | echo $file |
1046 | ;; | | 1046 | ;; |
1047 | esac | | 1047 | esac |
1048 | done >> $CHANGEFILES | | 1048 | done >> $CHANGEFILES |
1049 | CHANGELIST="$CHANGEFILES $CHANGELIST" | | 1049 | CHANGELIST="$CHANGEFILES $CHANGELIST" |
1050 | fi | | 1050 | fi |
1051 | | | 1051 | |
| | | 1052 | # Save entropy to ${random_file} if defined, like |
| | | 1053 | # /etc/rc.d/random_seed. |
| | | 1054 | # |
| | | 1055 | if [ -n "${random_file:-}" ]; then |
| | | 1056 | rndctl -S "$random_file" |
| | | 1057 | fi |
| | | 1058 | |
1052 | # Special case backups, including the master password file and | | 1059 | # Special case backups, including the master password file and |
1053 | # ssh private host keys. The normal backup mechanisms for | | 1060 | # ssh private host keys. The normal backup mechanisms for |
1054 | # $check_changelist (see below) also print out the actual file | | 1061 | # $check_changelist (see below) also print out the actual file |
1055 | # differences and we don't want to do that for these files | | 1062 | # differences and we don't want to do that for these files |
1056 | # | | 1063 | # |
1057 | echo $MP > $TMP1 # always add /etc/master.passwd | | 1064 | echo $MP > $TMP1 # always add /etc/master.passwd |
1058 | mtree -D -k type -f $SPECIALSPEC -I nodiff | | | 1065 | mtree -D -k type -f $SPECIALSPEC -I nodiff | |
1059 | sed '/^type=file/!d ; s/type=file \.//' | unvis >> $TMP1 | | 1066 | sed '/^type=file/!d ; s/type=file \.//' | unvis >> $TMP1 |
1060 | grep -v '^$' $TMP1 | sort -u > $TMP2 | | 1067 | grep -v '^$' $TMP1 | sort -u > $TMP2 |
1061 | | | 1068 | |
1062 | while read file; do | | 1069 | while read file; do |
1063 | backup_and_diff "$file" no | | 1070 | backup_and_diff "$file" no |
1064 | done < $TMP2 | | 1071 | done < $TMP2 |
1065 | | | 1072 | |
1066 | | | 1073 | |
1067 | if [ -n "$CHANGELIST" ]; then | | 1074 | if [ -n "$CHANGELIST" ]; then |
1068 | grep -h -v '^$' $CHANGELIST | sort -u > $TMP1 | | 1075 | grep -h -v '^$' $CHANGELIST | sort -u > $TMP1 |
1069 | comm -23 $TMP1 $TMP2 | while read file; do | | 1076 | comm -23 $TMP1 $TMP2 | while read file; do |
1070 | backup_and_diff "$file" yes | | 1077 | backup_and_diff "$file" yes |
1071 | done | | 1078 | done |
1072 | fi | | 1079 | fi |
1073 | | | 1080 | |
1074 | if have_pkgs; then | | 1081 | if have_pkgs; then |
1075 | if checkyesno check_pkg_vulnerabilities; then | | 1082 | if checkyesno check_pkg_vulnerabilities; then |
1076 | ${pkg_admin} ${_compat_K_flag} audit >${OUTPUT} 2>&1 | | 1083 | ${pkg_admin} ${_compat_K_flag} audit >${OUTPUT} 2>&1 |
1077 | if [ -s ${OUTPUT} ]; then | | 1084 | if [ -s ${OUTPUT} ]; then |
1078 | printf "\nInstalled vulnerable packages:\n" | | 1085 | printf "\nInstalled vulnerable packages:\n" |
1079 | cat ${OUTPUT} | | 1086 | cat ${OUTPUT} |
1080 | fi | | 1087 | fi |
1081 | fi | | 1088 | fi |
1082 | | | 1089 | |
1083 | if checkyesno check_pkg_signatures; then | | 1090 | if checkyesno check_pkg_signatures; then |
1084 | ${pkg_admin} ${_compat_K_flag} check >${OUTPUT} 2>&1 | | 1091 | ${pkg_admin} ${_compat_K_flag} check >${OUTPUT} 2>&1 |
1085 | if [ $? -ne 0 ]; then | | 1092 | if [ $? -ne 0 ]; then |
1086 | printf "\nFiles with invalid signatures:\n" | | 1093 | printf "\nFiles with invalid signatures:\n" |
1087 | cat ${OUTPUT} | | 1094 | cat ${OUTPUT} |
1088 | fi | | 1095 | fi |
1089 | fi | | 1096 | fi |
1090 | fi | | 1097 | fi |
1091 | | | 1098 | |
1092 | if [ -f /etc/security.local ]; then | | 1099 | if [ -f /etc/security.local ]; then |
1093 | . /etc/security.local > $OUTPUT 2>&1 | | 1100 | . /etc/security.local > $OUTPUT 2>&1 |
1094 | if [ -s $OUTPUT ] ; then | | 1101 | if [ -s $OUTPUT ] ; then |
1095 | printf "\nRunning /etc/security.local:\n" | | 1102 | printf "\nRunning /etc/security.local:\n" |
1096 | cat $OUTPUT | | 1103 | cat $OUTPUT |
1097 | fi | | 1104 | fi |
1098 | fi | | 1105 | fi |