Deleted Added
full compact
auditd.c (187214) auditd.c (189279)
1/*-
1/*-
2 * Copyright (c) 2004-2008 Apple Inc.
2 * Copyright (c) 2004-2009 Apple Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#41 $
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#43 $
30 */
31
32#include <sys/types.h>
33
34#include <config/config.h>
35
36#include <sys/dirent.h>
37#ifdef HAVE_FULL_QUEUE_H
38#include <sys/queue.h>
39#else /* !HAVE_FULL_QUEUE_H */
40#include <compat/queue.h>
41#endif /* !HAVE_FULL_QUEUE_H */
42#include <sys/mman.h>
43#include <sys/param.h>
44#include <sys/stat.h>
45#include <sys/wait.h>
46
47#include <bsm/audit.h>
48#include <bsm/audit_uevents.h>
49#include <bsm/auditd_lib.h>
50#include <bsm/libbsm.h>
51
52#include <err.h>
53#include <errno.h>
54#include <fcntl.h>
55#include <grp.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <time.h>
59#include <unistd.h>
60#include <signal.h>
61#include <string.h>
62
63#include "auditd.h"
64
65#ifndef HAVE_STRLCPY
66#include <compat/strlcpy.h>
67#endif
68
69/*
30 */
31
32#include <sys/types.h>
33
34#include <config/config.h>
35
36#include <sys/dirent.h>
37#ifdef HAVE_FULL_QUEUE_H
38#include <sys/queue.h>
39#else /* !HAVE_FULL_QUEUE_H */
40#include <compat/queue.h>
41#endif /* !HAVE_FULL_QUEUE_H */
42#include <sys/mman.h>
43#include <sys/param.h>
44#include <sys/stat.h>
45#include <sys/wait.h>
46
47#include <bsm/audit.h>
48#include <bsm/audit_uevents.h>
49#include <bsm/auditd_lib.h>
50#include <bsm/libbsm.h>
51
52#include <err.h>
53#include <errno.h>
54#include <fcntl.h>
55#include <grp.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <time.h>
59#include <unistd.h>
60#include <signal.h>
61#include <string.h>
62
63#include "auditd.h"
64
65#ifndef HAVE_STRLCPY
66#include <compat/strlcpy.h>
67#endif
68
69/*
70 * XXX the following is temporary until this can be added to the kernel
70 * XXX The following are temporary until these can be added to the kernel
71 * audit.h header.
72 */
73#ifndef AUDIT_TRIGGER_INITIALIZE
74#define AUDIT_TRIGGER_INITIALIZE 7
75#endif
71 * audit.h header.
72 */
73#ifndef AUDIT_TRIGGER_INITIALIZE
74#define AUDIT_TRIGGER_INITIALIZE 7
75#endif
76#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS
77#define AUDIT_TRIGGER_EXPIRE_TRAILS 8
78#endif
76
79
80
77/*
78 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and
79 * http://wiki.freebsd.org/launchd for more information.
80 *
81 * In order for auditd to work "on demand" with launchd(8) it can't:
82 * call daemon(3)
83 * call fork and having the parent process exit
84 * change uids or gids.
85 * set up the current working directory or chroot.
86 * set the session id
87 * change stdio to /dev/null.
88 * call setrusage(2)
89 * call setpriority(2)
90 * Ignore SIGTERM.
91 * auditd (in 'launchd mode') is launched on demand so it must catch
92 * SIGTERM to exit cleanly.
93 */
94static int launchd_flag = 0;
95
96/*
97 * The GID of the audit review group (if used). The audit trail files and
98 * system logs (Mac OS X only) can only be reviewed by members of this group
99 * or the audit administrator (aka. "root").
100 */
101static gid_t audit_review_gid = -1;
102
103/*
104 * The path and file name of the last audit trail file.
105 */
106static char *lastfile = NULL;
107
108/*
109 * Error starting auditd. Run warn script and exit.
110 */
111static void
112fail_exit(void)
113{
114
115 audit_warn_nostart();
116 exit(1);
117}
118
119/*
120 * Follow the 'current' symlink to get the active trail file name.
121 */
122static char *
123get_curfile(void)
124{
125 char *cf;
126 int len;
127
128 cf = malloc(MAXPATHLEN);
129 if (cf == NULL) {
130 auditd_log_err("malloc failed: %m");
131 return (NULL);
132 }
133
134 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1);
135 if (len < 0) {
136 free(cf);
137 return (NULL);
138 }
139
140 /* readlink() doesn't terminate string. */
141 cf[len] = '\0';
142
143 return (cf);
144}
145
146/*
147 * Close the previous audit trail file.
148 */
149static int
150close_lastfile(char *TS)
151{
152 char *ptr;
153 char *oldname;
154 size_t len;
155
156 /* If lastfile is NULL try to get it from the 'current' link. */
157 if (lastfile == NULL)
158 lastfile = get_curfile();
159
160 if (lastfile != NULL) {
161 len = strlen(lastfile) + 1;
162 oldname = (char *)malloc(len);
163 if (oldname == NULL)
164 return (-1);
165 strlcpy(oldname, lastfile, len);
166
167 /* Rename the last file -- append timestamp. */
168 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
81/*
82 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and
83 * http://wiki.freebsd.org/launchd for more information.
84 *
85 * In order for auditd to work "on demand" with launchd(8) it can't:
86 * call daemon(3)
87 * call fork and having the parent process exit
88 * change uids or gids.
89 * set up the current working directory or chroot.
90 * set the session id
91 * change stdio to /dev/null.
92 * call setrusage(2)
93 * call setpriority(2)
94 * Ignore SIGTERM.
95 * auditd (in 'launchd mode') is launched on demand so it must catch
96 * SIGTERM to exit cleanly.
97 */
98static int launchd_flag = 0;
99
100/*
101 * The GID of the audit review group (if used). The audit trail files and
102 * system logs (Mac OS X only) can only be reviewed by members of this group
103 * or the audit administrator (aka. "root").
104 */
105static gid_t audit_review_gid = -1;
106
107/*
108 * The path and file name of the last audit trail file.
109 */
110static char *lastfile = NULL;
111
112/*
113 * Error starting auditd. Run warn script and exit.
114 */
115static void
116fail_exit(void)
117{
118
119 audit_warn_nostart();
120 exit(1);
121}
122
123/*
124 * Follow the 'current' symlink to get the active trail file name.
125 */
126static char *
127get_curfile(void)
128{
129 char *cf;
130 int len;
131
132 cf = malloc(MAXPATHLEN);
133 if (cf == NULL) {
134 auditd_log_err("malloc failed: %m");
135 return (NULL);
136 }
137
138 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1);
139 if (len < 0) {
140 free(cf);
141 return (NULL);
142 }
143
144 /* readlink() doesn't terminate string. */
145 cf[len] = '\0';
146
147 return (cf);
148}
149
150/*
151 * Close the previous audit trail file.
152 */
153static int
154close_lastfile(char *TS)
155{
156 char *ptr;
157 char *oldname;
158 size_t len;
159
160 /* If lastfile is NULL try to get it from the 'current' link. */
161 if (lastfile == NULL)
162 lastfile = get_curfile();
163
164 if (lastfile != NULL) {
165 len = strlen(lastfile) + 1;
166 oldname = (char *)malloc(len);
167 if (oldname == NULL)
168 return (-1);
169 strlcpy(oldname, lastfile, len);
170
171 /* Rename the last file -- append timestamp. */
172 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
169 strlcpy(ptr, TS, TIMESTAMP_LEN);
173 memcpy(ptr, TS, POSTFIX_LEN);
170 if (rename(oldname, lastfile) != 0)
171 auditd_log_err(
172 "Could not rename %s to %s: %m", oldname,
173 lastfile);
174 else {
175 /*
176 * Remove the 'current' symlink since the link
177 * is now invalid.
178 */
179 (void) unlink(AUDIT_CURRENT_LINK);
180 auditd_log_notice( "renamed %s to %s",
181 oldname, lastfile);
182 audit_warn_closefile(lastfile);
183 }
184 } else
185 auditd_log_err( "Could not rename %s to %s", oldname,
186 lastfile);
187 free(lastfile);
188 free(oldname);
189 lastfile = NULL;
190 }
191 return (0);
192}
193
194/*
195 * Create the new file name, swap with existing audit file.
196 */
197static int
198swap_audit_file(void)
199{
200 int err;
201 char *newfile;
202 char TS[TIMESTAMP_LEN];
203 time_t tt;
204
205 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
206 return (-1);
207 err = auditd_swap_trail(TS, &newfile, audit_review_gid,
208 audit_warn_getacdir);
209 if (err != ADE_NOERR) {
210 auditd_log_err( "%s: %m", auditd_strerror(err));
211 if (err != ADE_ACTL)
212 return (-1);
213 }
214
215 /*
216 * Only close the last file if were in an auditing state before
217 * calling swap_audit_file(). We may need to recover from a crash.
218 */
219 if (auditd_get_state() == AUD_STATE_ENABLED)
220 close_lastfile(TS);
221
222
223 /*
224 * auditd_swap_trail() potentially enables auditing (if not already
225 * enabled) so updated the cached state as well.
226 */
227 auditd_set_state(AUD_STATE_ENABLED);
228
229 /*
230 * Create 'current' symlink. Recover from crash, if needed.
231 */
232 if (auditd_new_curlink(newfile) != 0)
233 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m",
234 newfile, auditd_strerror(err));
235
236 lastfile = newfile;
237 auditd_log_notice("New audit file is %s", newfile);
238
239 return (0);
240}
241
242/*
243 * Create a new audit log trail file and swap with the current one, if any.
244 */
245static int
246do_trail_file(void)
247{
248 int err;
249
250 /*
251 * First, refresh the list of audit log directories.
252 */
253 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
254 if (err) {
255 auditd_log_err("auditd_read_dirs(): %s",
256 auditd_strerror(err));
257 if (err == ADE_HARDLIM)
258 audit_warn_allhard();
259 if (err != ADE_SOFTLIM)
260 return (-1);
261 else
262 audit_warn_allsoft();
263 /* continue on with soft limit error */
264 }
265
266 /*
267 * Create a new file and swap with the one being used in kernel.
268 */
269 if (swap_audit_file() == -1) {
270 /*
271 * XXX Faulty directory listing? - user should be given
272 * XXX an opportunity to change the audit_control file
273 * XXX switch to a reduced mode of auditing?
274 */
275 return (-1);
276 }
277
174 if (rename(oldname, lastfile) != 0)
175 auditd_log_err(
176 "Could not rename %s to %s: %m", oldname,
177 lastfile);
178 else {
179 /*
180 * Remove the 'current' symlink since the link
181 * is now invalid.
182 */
183 (void) unlink(AUDIT_CURRENT_LINK);
184 auditd_log_notice( "renamed %s to %s",
185 oldname, lastfile);
186 audit_warn_closefile(lastfile);
187 }
188 } else
189 auditd_log_err( "Could not rename %s to %s", oldname,
190 lastfile);
191 free(lastfile);
192 free(oldname);
193 lastfile = NULL;
194 }
195 return (0);
196}
197
198/*
199 * Create the new file name, swap with existing audit file.
200 */
201static int
202swap_audit_file(void)
203{
204 int err;
205 char *newfile;
206 char TS[TIMESTAMP_LEN];
207 time_t tt;
208
209 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
210 return (-1);
211 err = auditd_swap_trail(TS, &newfile, audit_review_gid,
212 audit_warn_getacdir);
213 if (err != ADE_NOERR) {
214 auditd_log_err( "%s: %m", auditd_strerror(err));
215 if (err != ADE_ACTL)
216 return (-1);
217 }
218
219 /*
220 * Only close the last file if were in an auditing state before
221 * calling swap_audit_file(). We may need to recover from a crash.
222 */
223 if (auditd_get_state() == AUD_STATE_ENABLED)
224 close_lastfile(TS);
225
226
227 /*
228 * auditd_swap_trail() potentially enables auditing (if not already
229 * enabled) so updated the cached state as well.
230 */
231 auditd_set_state(AUD_STATE_ENABLED);
232
233 /*
234 * Create 'current' symlink. Recover from crash, if needed.
235 */
236 if (auditd_new_curlink(newfile) != 0)
237 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m",
238 newfile, auditd_strerror(err));
239
240 lastfile = newfile;
241 auditd_log_notice("New audit file is %s", newfile);
242
243 return (0);
244}
245
246/*
247 * Create a new audit log trail file and swap with the current one, if any.
248 */
249static int
250do_trail_file(void)
251{
252 int err;
253
254 /*
255 * First, refresh the list of audit log directories.
256 */
257 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
258 if (err) {
259 auditd_log_err("auditd_read_dirs(): %s",
260 auditd_strerror(err));
261 if (err == ADE_HARDLIM)
262 audit_warn_allhard();
263 if (err != ADE_SOFTLIM)
264 return (-1);
265 else
266 audit_warn_allsoft();
267 /* continue on with soft limit error */
268 }
269
270 /*
271 * Create a new file and swap with the one being used in kernel.
272 */
273 if (swap_audit_file() == -1) {
274 /*
275 * XXX Faulty directory listing? - user should be given
276 * XXX an opportunity to change the audit_control file
277 * XXX switch to a reduced mode of auditing?
278 */
279 return (-1);
280 }
281
282 /*
283 * Finally, see if there are any trail files to expire.
284 */
285 err = auditd_expire_trails(audit_warn_expired);
286 if (err)
287 auditd_log_err("auditd_expire_trails(): %s",
288 auditd_strerror(err));
289
278 return (0);
279}
280
281/*
282 * Start up auditing.
283 */
284static void
285audit_setup(void)
286{
287 int err;
288
289 if (do_trail_file() == -1) {
290 auditd_log_err("Error creating audit trail file");
291 fail_exit();
292 }
293
294 /* Generate an audit record. */
295 err = auditd_gen_record(AUE_audit_startup, NULL);
296 if (err)
297 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m",
298 auditd_strerror(err));
299
300 if (auditd_config_controls() == 0)
301 auditd_log_info("Audit controls init successful");
302 else
303 auditd_log_err("Audit controls init failed");
304
305}
306
307
308/*
309 * Close auditd pid file and trigger mechanism.
310 */
311static int
312close_misc(void)
313{
314
315 auditd_close_dirs();
316 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) {
317 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
318 return (1);
319 }
320 endac();
321
322 if (auditd_close_trigger() != 0) {
323 auditd_log_err("Error closing trigger messaging mechanism");
324 return (1);
325 }
326 return (0);
327}
328
329/*
330 * Close all log files, control files, and tell the audit system.
331 */
332static int
333close_all(void)
334{
335 int err_ret = 0;
336 char TS[TIMESTAMP_LEN];
337 int err;
338 long cond;
339 time_t tt;
340
341 err = auditd_gen_record(AUE_audit_shutdown, NULL);
342 if (err)
343 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m",
344 auditd_strerror(err));
345
346 /* Flush contents. */
347 cond = AUC_DISABLED;
348 err_ret = auditon(A_SETCOND, &cond, sizeof(cond));
349 if (err_ret != 0) {
350 auditd_log_err("Disabling audit failed! : %s", strerror(errno));
351 err_ret = 1;
352 }
353
354 /*
355 * Updated the cached state that auditing has been disabled.
356 */
357 auditd_set_state(AUD_STATE_DISABLED);
358
359 if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0)
360 close_lastfile(TS);
361 if (lastfile != NULL)
362 free(lastfile);
363
364 err_ret += close_misc();
365
366 if (err_ret) {
367 auditd_log_err("Could not unregister");
368 audit_warn_postsigterm();
369 }
370
371 auditd_log_info("Finished");
372 return (err_ret);
373}
374
375/*
376 * Register the daemon with the signal handler and the auditd pid file.
377 */
378static int
379register_daemon(void)
380{
381 FILE * pidfile;
382 int fd;
383 pid_t pid;
384
385 /* Set up the signal hander. */
386 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
387 auditd_log_err(
388 "Could not set signal handler for SIGTERM");
389 fail_exit();
390 }
391 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
392 auditd_log_err(
393 "Could not set signal handler for SIGCHLD");
394 fail_exit();
395 }
396 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) {
397 auditd_log_err(
398 "Could not set signal handler for SIGHUP");
399 fail_exit();
400 }
401 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) {
402 auditd_log_err(
403 "Could not set signal handler for SIGALRM");
404 fail_exit();
405 }
406
407 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
408 auditd_log_err("Could not open PID file");
409 audit_warn_tmpfile();
410 return (-1);
411 }
412
413 /* Attempt to lock the pid file; if a lock is present, exit. */
414 fd = fileno(pidfile);
415 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
416 auditd_log_err(
417 "PID file is locked (is another auditd running?).");
418 audit_warn_ebusy();
419 return (-1);
420 }
421
422 pid = getpid();
423 ftruncate(fd, 0);
424 if (fprintf(pidfile, "%u\n", pid) < 0) {
425 /* Should not start the daemon. */
426 fail_exit();
427 }
428
429 fflush(pidfile);
430 return (0);
431}
432
433/*
434 * Handle the audit trigger event.
435 *
436 * We suppress (ignore) duplicated triggers in close succession in order to
437 * try to avoid thrashing-like behavior. However, not all triggers can be
438 * ignored, as triggers generally represent edge triggers, not level
439 * triggers, and won't be retransmitted if the condition persists. Of
440 * specific concern is the rotate trigger -- if one is dropped, then it will
441 * not be retransmitted, and the log file will grow in an unbounded fashion.
442 */
443#define DUPLICATE_INTERVAL 30
444void
445auditd_handle_trigger(int trigger)
446{
447 static int last_trigger, last_warning;
448 static time_t last_time;
449 struct timeval ts;
450 struct timezone tzp;
451 time_t tt;
452 int au_state;
453 int err = 0;
454
455 /*
456 * Suppress duplicate messages from the kernel within the specified
457 * interval.
458 */
459 if (gettimeofday(&ts, &tzp) == 0) {
460 tt = (time_t)ts.tv_sec;
461 switch (trigger) {
462 case AUDIT_TRIGGER_LOW_SPACE:
463 case AUDIT_TRIGGER_NO_SPACE:
464 /*
465 * Triggers we can suppress. Of course, we also need
466 * to rate limit the warnings, so apply the same
467 * interval limit on syslog messages.
468 */
469 if ((trigger == last_trigger) &&
470 (tt < (last_time + DUPLICATE_INTERVAL))) {
471 if (tt >= (last_warning + DUPLICATE_INTERVAL))
472 auditd_log_info(
473 "Suppressing duplicate trigger %d",
474 trigger);
475 return;
476 }
477 last_warning = tt;
478 break;
479
480 case AUDIT_TRIGGER_ROTATE_KERNEL:
481 case AUDIT_TRIGGER_ROTATE_USER:
482 case AUDIT_TRIGGER_READ_FILE:
483 case AUDIT_TRIGGER_CLOSE_AND_DIE:
484 case AUDIT_TRIGGER_INITIALIZE:
485 /*
486 * Triggers that we cannot suppress.
487 */
488 break;
489 }
490
491 /*
492 * Only update last_trigger after aborting due to a duplicate
493 * trigger, not before, or we will never allow that trigger
494 * again.
495 */
496 last_trigger = trigger;
497 last_time = tt;
498 }
499
500 au_state = auditd_get_state();
501
502 /*
503 * Message processing is done here.
504 */
505 switch(trigger) {
506 case AUDIT_TRIGGER_LOW_SPACE:
507 auditd_log_notice("Got low space trigger");
508 if (do_trail_file() == -1)
509 auditd_log_err("Error swapping audit file");
510 break;
511
512 case AUDIT_TRIGGER_NO_SPACE:
513 auditd_log_notice("Got no space trigger");
514 if (do_trail_file() == -1)
515 auditd_log_err("Error swapping audit file");
516 break;
517
518 case AUDIT_TRIGGER_ROTATE_KERNEL:
519 case AUDIT_TRIGGER_ROTATE_USER:
520 auditd_log_info("Got open new trigger from %s", trigger ==
521 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
522 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
523 auditd_log_err("Error swapping audit file");
524 break;
525
526 case AUDIT_TRIGGER_READ_FILE:
527 auditd_log_info("Got read file trigger");
528 if (au_state == AUD_STATE_ENABLED &&
529 auditd_config_controls() == -1)
530 auditd_log_err("Error setting audit controls");
531 break;
532
533 case AUDIT_TRIGGER_CLOSE_AND_DIE:
534 auditd_log_info("Got close and die trigger");
535 if (au_state == AUD_STATE_ENABLED)
536 err = close_all();
537 /*
538 * Running under launchd don't exit. Wait for launchd to
539 * send SIGTERM.
540 */
541 if (!launchd_flag) {
542 auditd_log_info("auditd exiting.");
543 exit (err);
544 }
545 break;
546
547 case AUDIT_TRIGGER_INITIALIZE:
548 auditd_log_info("Got audit initialize trigger");
549 if (au_state == AUD_STATE_DISABLED)
550 audit_setup();
551 break;
552
290 return (0);
291}
292
293/*
294 * Start up auditing.
295 */
296static void
297audit_setup(void)
298{
299 int err;
300
301 if (do_trail_file() == -1) {
302 auditd_log_err("Error creating audit trail file");
303 fail_exit();
304 }
305
306 /* Generate an audit record. */
307 err = auditd_gen_record(AUE_audit_startup, NULL);
308 if (err)
309 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m",
310 auditd_strerror(err));
311
312 if (auditd_config_controls() == 0)
313 auditd_log_info("Audit controls init successful");
314 else
315 auditd_log_err("Audit controls init failed");
316
317}
318
319
320/*
321 * Close auditd pid file and trigger mechanism.
322 */
323static int
324close_misc(void)
325{
326
327 auditd_close_dirs();
328 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) {
329 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
330 return (1);
331 }
332 endac();
333
334 if (auditd_close_trigger() != 0) {
335 auditd_log_err("Error closing trigger messaging mechanism");
336 return (1);
337 }
338 return (0);
339}
340
341/*
342 * Close all log files, control files, and tell the audit system.
343 */
344static int
345close_all(void)
346{
347 int err_ret = 0;
348 char TS[TIMESTAMP_LEN];
349 int err;
350 long cond;
351 time_t tt;
352
353 err = auditd_gen_record(AUE_audit_shutdown, NULL);
354 if (err)
355 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m",
356 auditd_strerror(err));
357
358 /* Flush contents. */
359 cond = AUC_DISABLED;
360 err_ret = auditon(A_SETCOND, &cond, sizeof(cond));
361 if (err_ret != 0) {
362 auditd_log_err("Disabling audit failed! : %s", strerror(errno));
363 err_ret = 1;
364 }
365
366 /*
367 * Updated the cached state that auditing has been disabled.
368 */
369 auditd_set_state(AUD_STATE_DISABLED);
370
371 if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0)
372 close_lastfile(TS);
373 if (lastfile != NULL)
374 free(lastfile);
375
376 err_ret += close_misc();
377
378 if (err_ret) {
379 auditd_log_err("Could not unregister");
380 audit_warn_postsigterm();
381 }
382
383 auditd_log_info("Finished");
384 return (err_ret);
385}
386
387/*
388 * Register the daemon with the signal handler and the auditd pid file.
389 */
390static int
391register_daemon(void)
392{
393 FILE * pidfile;
394 int fd;
395 pid_t pid;
396
397 /* Set up the signal hander. */
398 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
399 auditd_log_err(
400 "Could not set signal handler for SIGTERM");
401 fail_exit();
402 }
403 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
404 auditd_log_err(
405 "Could not set signal handler for SIGCHLD");
406 fail_exit();
407 }
408 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) {
409 auditd_log_err(
410 "Could not set signal handler for SIGHUP");
411 fail_exit();
412 }
413 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) {
414 auditd_log_err(
415 "Could not set signal handler for SIGALRM");
416 fail_exit();
417 }
418
419 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
420 auditd_log_err("Could not open PID file");
421 audit_warn_tmpfile();
422 return (-1);
423 }
424
425 /* Attempt to lock the pid file; if a lock is present, exit. */
426 fd = fileno(pidfile);
427 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
428 auditd_log_err(
429 "PID file is locked (is another auditd running?).");
430 audit_warn_ebusy();
431 return (-1);
432 }
433
434 pid = getpid();
435 ftruncate(fd, 0);
436 if (fprintf(pidfile, "%u\n", pid) < 0) {
437 /* Should not start the daemon. */
438 fail_exit();
439 }
440
441 fflush(pidfile);
442 return (0);
443}
444
445/*
446 * Handle the audit trigger event.
447 *
448 * We suppress (ignore) duplicated triggers in close succession in order to
449 * try to avoid thrashing-like behavior. However, not all triggers can be
450 * ignored, as triggers generally represent edge triggers, not level
451 * triggers, and won't be retransmitted if the condition persists. Of
452 * specific concern is the rotate trigger -- if one is dropped, then it will
453 * not be retransmitted, and the log file will grow in an unbounded fashion.
454 */
455#define DUPLICATE_INTERVAL 30
456void
457auditd_handle_trigger(int trigger)
458{
459 static int last_trigger, last_warning;
460 static time_t last_time;
461 struct timeval ts;
462 struct timezone tzp;
463 time_t tt;
464 int au_state;
465 int err = 0;
466
467 /*
468 * Suppress duplicate messages from the kernel within the specified
469 * interval.
470 */
471 if (gettimeofday(&ts, &tzp) == 0) {
472 tt = (time_t)ts.tv_sec;
473 switch (trigger) {
474 case AUDIT_TRIGGER_LOW_SPACE:
475 case AUDIT_TRIGGER_NO_SPACE:
476 /*
477 * Triggers we can suppress. Of course, we also need
478 * to rate limit the warnings, so apply the same
479 * interval limit on syslog messages.
480 */
481 if ((trigger == last_trigger) &&
482 (tt < (last_time + DUPLICATE_INTERVAL))) {
483 if (tt >= (last_warning + DUPLICATE_INTERVAL))
484 auditd_log_info(
485 "Suppressing duplicate trigger %d",
486 trigger);
487 return;
488 }
489 last_warning = tt;
490 break;
491
492 case AUDIT_TRIGGER_ROTATE_KERNEL:
493 case AUDIT_TRIGGER_ROTATE_USER:
494 case AUDIT_TRIGGER_READ_FILE:
495 case AUDIT_TRIGGER_CLOSE_AND_DIE:
496 case AUDIT_TRIGGER_INITIALIZE:
497 /*
498 * Triggers that we cannot suppress.
499 */
500 break;
501 }
502
503 /*
504 * Only update last_trigger after aborting due to a duplicate
505 * trigger, not before, or we will never allow that trigger
506 * again.
507 */
508 last_trigger = trigger;
509 last_time = tt;
510 }
511
512 au_state = auditd_get_state();
513
514 /*
515 * Message processing is done here.
516 */
517 switch(trigger) {
518 case AUDIT_TRIGGER_LOW_SPACE:
519 auditd_log_notice("Got low space trigger");
520 if (do_trail_file() == -1)
521 auditd_log_err("Error swapping audit file");
522 break;
523
524 case AUDIT_TRIGGER_NO_SPACE:
525 auditd_log_notice("Got no space trigger");
526 if (do_trail_file() == -1)
527 auditd_log_err("Error swapping audit file");
528 break;
529
530 case AUDIT_TRIGGER_ROTATE_KERNEL:
531 case AUDIT_TRIGGER_ROTATE_USER:
532 auditd_log_info("Got open new trigger from %s", trigger ==
533 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
534 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
535 auditd_log_err("Error swapping audit file");
536 break;
537
538 case AUDIT_TRIGGER_READ_FILE:
539 auditd_log_info("Got read file trigger");
540 if (au_state == AUD_STATE_ENABLED &&
541 auditd_config_controls() == -1)
542 auditd_log_err("Error setting audit controls");
543 break;
544
545 case AUDIT_TRIGGER_CLOSE_AND_DIE:
546 auditd_log_info("Got close and die trigger");
547 if (au_state == AUD_STATE_ENABLED)
548 err = close_all();
549 /*
550 * Running under launchd don't exit. Wait for launchd to
551 * send SIGTERM.
552 */
553 if (!launchd_flag) {
554 auditd_log_info("auditd exiting.");
555 exit (err);
556 }
557 break;
558
559 case AUDIT_TRIGGER_INITIALIZE:
560 auditd_log_info("Got audit initialize trigger");
561 if (au_state == AUD_STATE_DISABLED)
562 audit_setup();
563 break;
564
565 case AUDIT_TRIGGER_EXPIRE_TRAILS:
566 auditd_log_info("Got audit expire trails trigger");
567 err = auditd_expire_trails(audit_warn_expired);
568 if (err)
569 auditd_log_err("auditd_expire_trails(): %s",
570 auditd_strerror(err));
571 break;
572
553 default:
554 auditd_log_err("Got unknown trigger %d", trigger);
555 break;
556 }
557}
558
559/*
560 * Reap our children.
561 */
562void
563auditd_reap_children(void)
564{
565 pid_t child;
566 int wstatus;
567
568 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
569 if (!wstatus)
570 continue;
571 auditd_log_info("warn process [pid=%d] %s %d.", child,
572 ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
573 "exited as a result of signal"),
574 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
575 WTERMSIG(wstatus)));
576 }
577}
578
579/*
580 * Reap any children and terminate. If under launchd don't shutdown auditing
581 * but just the other stuff.
582 */
583void
584auditd_terminate(void)
585{
586 int ret;
587
588 auditd_reap_children();
589
590 if (launchd_flag)
591 ret = close_misc();
592 else
593 ret = close_all();
594
595 exit(ret);
596}
597
598/*
599 * Configure the audit controls in the kernel: the event to class mapping,
600 * kernel preselection mask, etc.
601 */
602int
603auditd_config_controls(void)
604{
605 int cnt, err;
606 int ret = 0;
607
608 /*
609 * Configure event to class mappings in kernel.
610 */
611 cnt = auditd_set_evcmap();
612 if (cnt < 0) {
613 auditd_log_err("auditd_set_evcmap() failed: %m");
614 ret = -1;
615 } else if (cnt == 0) {
616 auditd_log_err("No events to class mappings registered.");
617 ret = -1;
618 } else
619 auditd_log_debug("Registered %d event to class mappings.", cnt);
620
621 /*
622 * Configure non-attributable event mask in kernel.
623 */
624 err = auditd_set_namask();
625 if (err) {
626 auditd_log_err("auditd_set_namask() %s: %m",
627 auditd_strerror(err));
628 ret = -1;
629 } else
630 auditd_log_debug("Registered non-attributable event mask.");
631
632 /*
633 * Configure audit policy in kernel.
634 */
635 err = auditd_set_policy();
636 if (err) {
637 auditd_log_err("auditd_set_policy() %s: %m",
638 auditd_strerror(err));
639 ret = -1;
640 } else
641 auditd_log_debug("Set audit policy in kernel.");
642
643 /*
644 * Configure audit trail log size in kernel.
645 */
646 err = auditd_set_fsize();
647 if (err) {
648 auditd_log_err("audit_set_fsize() %s: %m",
649 auditd_strerror(err));
650 ret = -1;
651 } else
652 auditd_log_debug("Set audit trail size in kernel.");
653
654 /*
655 * Configure audit trail volume minimum free percentage of blocks in
656 * kernel.
657 */
658 err = auditd_set_minfree();
659 if (err) {
660 auditd_log_err("auditd_set_minfree() %s: %m",
661 auditd_strerror(err));
662 ret = -1;
663 } else
664 auditd_log_debug(
665 "Set audit trail min free percent in kernel.");
666
667 /*
668 * Configure host address in the audit kernel information.
669 */
670 err = auditd_set_host();
671 if (err) {
573 default:
574 auditd_log_err("Got unknown trigger %d", trigger);
575 break;
576 }
577}
578
579/*
580 * Reap our children.
581 */
582void
583auditd_reap_children(void)
584{
585 pid_t child;
586 int wstatus;
587
588 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
589 if (!wstatus)
590 continue;
591 auditd_log_info("warn process [pid=%d] %s %d.", child,
592 ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
593 "exited as a result of signal"),
594 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
595 WTERMSIG(wstatus)));
596 }
597}
598
599/*
600 * Reap any children and terminate. If under launchd don't shutdown auditing
601 * but just the other stuff.
602 */
603void
604auditd_terminate(void)
605{
606 int ret;
607
608 auditd_reap_children();
609
610 if (launchd_flag)
611 ret = close_misc();
612 else
613 ret = close_all();
614
615 exit(ret);
616}
617
618/*
619 * Configure the audit controls in the kernel: the event to class mapping,
620 * kernel preselection mask, etc.
621 */
622int
623auditd_config_controls(void)
624{
625 int cnt, err;
626 int ret = 0;
627
628 /*
629 * Configure event to class mappings in kernel.
630 */
631 cnt = auditd_set_evcmap();
632 if (cnt < 0) {
633 auditd_log_err("auditd_set_evcmap() failed: %m");
634 ret = -1;
635 } else if (cnt == 0) {
636 auditd_log_err("No events to class mappings registered.");
637 ret = -1;
638 } else
639 auditd_log_debug("Registered %d event to class mappings.", cnt);
640
641 /*
642 * Configure non-attributable event mask in kernel.
643 */
644 err = auditd_set_namask();
645 if (err) {
646 auditd_log_err("auditd_set_namask() %s: %m",
647 auditd_strerror(err));
648 ret = -1;
649 } else
650 auditd_log_debug("Registered non-attributable event mask.");
651
652 /*
653 * Configure audit policy in kernel.
654 */
655 err = auditd_set_policy();
656 if (err) {
657 auditd_log_err("auditd_set_policy() %s: %m",
658 auditd_strerror(err));
659 ret = -1;
660 } else
661 auditd_log_debug("Set audit policy in kernel.");
662
663 /*
664 * Configure audit trail log size in kernel.
665 */
666 err = auditd_set_fsize();
667 if (err) {
668 auditd_log_err("audit_set_fsize() %s: %m",
669 auditd_strerror(err));
670 ret = -1;
671 } else
672 auditd_log_debug("Set audit trail size in kernel.");
673
674 /*
675 * Configure audit trail volume minimum free percentage of blocks in
676 * kernel.
677 */
678 err = auditd_set_minfree();
679 if (err) {
680 auditd_log_err("auditd_set_minfree() %s: %m",
681 auditd_strerror(err));
682 ret = -1;
683 } else
684 auditd_log_debug(
685 "Set audit trail min free percent in kernel.");
686
687 /*
688 * Configure host address in the audit kernel information.
689 */
690 err = auditd_set_host();
691 if (err) {
672 auditd_log_err("auditd_set_host() %s: %m",
673 auditd_strerror(err));
674 ret = -1;
692 if (err == ADE_PARSE) {
693 auditd_log_notice(
694 "audit_control(5) may be missing 'host:' field");
695 } else {
696 auditd_log_err("auditd_set_host() %s: %m",
697 auditd_strerror(err));
698 ret = -1;
699 }
675 } else
676 auditd_log_debug(
677 "Set audit host address information in kernel.");
700 } else
701 auditd_log_debug(
702 "Set audit host address information in kernel.");
678
703
679 return (ret);
680}
681
682/*
683 * Setup and initialize auditd.
684 */
685static void
686setup(void)
687{
688 int err;
689
690 if (auditd_open_trigger(launchd_flag) < 0) {
691 auditd_log_err("Error opening trigger messaging mechanism");
692 fail_exit();
693 }
694
695 /*
696 * To prevent event feedback cycles and avoid auditd becoming
697 * stalled if auditing is suspended, auditd and its children run
698 * without their events being audited. We allow the uid, tid, and
699 * mask fields to be implicitly set to zero, but do set the pid. We
700 * run this after opening the trigger device to avoid configuring
701 * audit state without audit present in the system.
702 */
703 err = auditd_prevent_audit();
704 if (err) {
705 auditd_log_err("auditd_prevent_audit() %s: %m",
706 auditd_strerror(err));
707 fail_exit();
708 }
709
710 /*
711 * Make sure auditd auditing state is correct.
712 */
713 auditd_set_state(AUD_STATE_INIT);
714
715 /*
716 * If under launchd, don't start auditing. Wait for a trigger to
717 * do so.
718 */
719 if (!launchd_flag)
720 audit_setup();
721}
722
723int
724main(int argc, char **argv)
725{
726 int ch;
727 int debug = 0;
728#ifdef AUDIT_REVIEW_GROUP
729 struct group *grp;
730#endif
731
732 while ((ch = getopt(argc, argv, "dl")) != -1) {
733 switch(ch) {
734 case 'd':
735 /* Debug option. */
736 debug = 1;
737 break;
738
739 case 'l':
740 /* Be launchd friendly. */
741 launchd_flag = 1;
742 break;
743
744 case '?':
745 default:
746 (void)fprintf(stderr,
747 "usage: auditd [-d] [-l]\n");
748 exit(1);
749 }
750 }
751
752 audit_review_gid = getgid();
753
754#ifdef AUDIT_REVIEW_GROUP
755 /*
756 * XXXRW: Currently, this code falls back to the daemon gid, which is
757 * likely the wheel group. Is there a better way to deal with this?
758 */
759 grp = getgrnam(AUDIT_REVIEW_GROUP);
760 if (grp != NULL)
761 audit_review_gid = grp->gr_gid;
762#endif
763
764 auditd_openlog(debug, audit_review_gid);
765
766 if (launchd_flag)
767 auditd_log_info("started by launchd...");
768 else
769 auditd_log_info("starting...");
770
771#ifdef AUDIT_REVIEW_GROUP
772 if (grp == NULL)
773 auditd_log_info(
774 "Audit review group '%s' not available, using daemon gid (%d)",
775 AUDIT_REVIEW_GROUP, audit_review_gid);
776#endif
777 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) {
778 auditd_log_err("Failed to daemonize");
779 exit(1);
780 }
781
782 if (register_daemon() == -1) {
783 auditd_log_err("Could not register as daemon");
784 exit(1);
785 }
786
787 setup();
788
789 /*
790 * auditd_wait_for_events() shouldn't return unless something is wrong.
791 */
792 auditd_wait_for_events();
793
794 auditd_log_err("abnormal exit.");
795 close_all();
796 exit(-1);
797}
704 return (ret);
705}
706
707/*
708 * Setup and initialize auditd.
709 */
710static void
711setup(void)
712{
713 int err;
714
715 if (auditd_open_trigger(launchd_flag) < 0) {
716 auditd_log_err("Error opening trigger messaging mechanism");
717 fail_exit();
718 }
719
720 /*
721 * To prevent event feedback cycles and avoid auditd becoming
722 * stalled if auditing is suspended, auditd and its children run
723 * without their events being audited. We allow the uid, tid, and
724 * mask fields to be implicitly set to zero, but do set the pid. We
725 * run this after opening the trigger device to avoid configuring
726 * audit state without audit present in the system.
727 */
728 err = auditd_prevent_audit();
729 if (err) {
730 auditd_log_err("auditd_prevent_audit() %s: %m",
731 auditd_strerror(err));
732 fail_exit();
733 }
734
735 /*
736 * Make sure auditd auditing state is correct.
737 */
738 auditd_set_state(AUD_STATE_INIT);
739
740 /*
741 * If under launchd, don't start auditing. Wait for a trigger to
742 * do so.
743 */
744 if (!launchd_flag)
745 audit_setup();
746}
747
748int
749main(int argc, char **argv)
750{
751 int ch;
752 int debug = 0;
753#ifdef AUDIT_REVIEW_GROUP
754 struct group *grp;
755#endif
756
757 while ((ch = getopt(argc, argv, "dl")) != -1) {
758 switch(ch) {
759 case 'd':
760 /* Debug option. */
761 debug = 1;
762 break;
763
764 case 'l':
765 /* Be launchd friendly. */
766 launchd_flag = 1;
767 break;
768
769 case '?':
770 default:
771 (void)fprintf(stderr,
772 "usage: auditd [-d] [-l]\n");
773 exit(1);
774 }
775 }
776
777 audit_review_gid = getgid();
778
779#ifdef AUDIT_REVIEW_GROUP
780 /*
781 * XXXRW: Currently, this code falls back to the daemon gid, which is
782 * likely the wheel group. Is there a better way to deal with this?
783 */
784 grp = getgrnam(AUDIT_REVIEW_GROUP);
785 if (grp != NULL)
786 audit_review_gid = grp->gr_gid;
787#endif
788
789 auditd_openlog(debug, audit_review_gid);
790
791 if (launchd_flag)
792 auditd_log_info("started by launchd...");
793 else
794 auditd_log_info("starting...");
795
796#ifdef AUDIT_REVIEW_GROUP
797 if (grp == NULL)
798 auditd_log_info(
799 "Audit review group '%s' not available, using daemon gid (%d)",
800 AUDIT_REVIEW_GROUP, audit_review_gid);
801#endif
802 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) {
803 auditd_log_err("Failed to daemonize");
804 exit(1);
805 }
806
807 if (register_daemon() == -1) {
808 auditd_log_err("Could not register as daemon");
809 exit(1);
810 }
811
812 setup();
813
814 /*
815 * auditd_wait_for_events() shouldn't return unless something is wrong.
816 */
817 auditd_wait_for_events();
818
819 auditd_log_err("abnormal exit.");
820 close_all();
821 exit(-1);
822}