2 * Copyright (c) 2004-2009 Apple Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#50 $
32 #include <sys/types.h>
34 #include <config/config.h>
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 */
43 #include <sys/param.h>
47 #include <bsm/audit.h>
48 #include <bsm/audit_uevents.h>
49 #include <bsm/auditd_lib.h>
50 #include <bsm/libbsm.h>
66 #include <compat/strlcpy.h>
70 * XXX The following are temporary until these can be added to the kernel
73 #ifndef AUDIT_TRIGGER_INITIALIZE
74 #define AUDIT_TRIGGER_INITIALIZE 7
76 #ifndef AUDIT_TRIGGER_EXPIRE_TRAILS
77 #define AUDIT_TRIGGER_EXPIRE_TRAILS 8
82 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and
83 * http://wiki.freebsd.org/launchd for more information.
85 * In order for auditd to work "on demand" with launchd(8) it can't:
87 * call fork and having the parent process exit
88 * change uids or gids.
89 * set up the current working directory or chroot.
91 * change stdio to /dev/null.
95 * auditd (in 'launchd mode') is launched on demand so it must catch
96 * SIGTERM to exit cleanly.
98 static int launchd_flag = 0;
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").
105 static gid_t audit_review_gid = -1;
108 * The path and file name of the last audit trail file.
110 static char *lastfile = NULL;
113 * Error starting auditd. Run warn script and exit.
119 audit_warn_nostart();
124 * Follow the 'current' symlink to get the active trail file name.
132 cf = malloc(MAXPATHLEN);
134 auditd_log_err("malloc failed: %m");
138 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1);
144 /* readlink() doesn't terminate string. */
151 * Close the previous audit trail file.
154 close_lastfile(char *TS)
159 /* If lastfile is NULL try to get it from the 'current' link. */
160 if (lastfile == NULL)
161 lastfile = get_curfile();
163 if (lastfile != NULL) {
164 oldname = strdup(lastfile);
168 /* Rename the last file -- append timestamp. */
169 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
170 memcpy(ptr, TS, POSTFIX_LEN);
171 if (auditd_rename(oldname, lastfile) != 0)
173 "Could not rename %s to %s: %m", oldname,
177 * Remove the 'current' symlink since the link
180 (void) unlink(AUDIT_CURRENT_LINK);
181 auditd_log_notice("renamed %s to %s",
183 audit_warn_closefile(lastfile);
186 auditd_log_err("Could not rename %s to %s", oldname,
196 * Create the new file name, swap with existing audit file.
199 swap_audit_file(void)
202 char *newfile, *name;
203 char TS[TIMESTAMP_LEN + 1];
206 if (getTSstr(tt, TS, sizeof(TS)) != 0)
209 * If prefix and suffix are the same, it means that records are
210 * being produced too fast. We don't want to rename now, because
211 * next trail file can get the same name and once that one is
212 * terminated also within one second it will overwrite the current
213 * one. Just keep writing to the same trail and wait for the next
214 * trigger from the kernel.
215 * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT
216 * NOT BE THE CASE FOR OTHER OSES.
217 * If the kernel will not keep sending triggers, trail file will not
220 if (lastfile == NULL) {
223 name = strrchr(lastfile, '/');
227 if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) {
228 auditd_log_debug("Not ready to terminate trail file yet.");
231 err = auditd_swap_trail(TS, &newfile, audit_review_gid,
232 audit_warn_getacdir);
233 if (err != ADE_NOERR) {
234 auditd_log_err("%s: %m", auditd_strerror(err));
240 * Only close the last file if were in an auditing state before
241 * calling swap_audit_file(). We may need to recover from a crash.
243 if (auditd_get_state() == AUD_STATE_ENABLED)
248 * auditd_swap_trail() potentially enables auditing (if not already
249 * enabled) so updated the cached state as well.
251 auditd_set_state(AUD_STATE_ENABLED);
254 * Create 'current' symlink. Recover from crash, if needed.
256 if (auditd_new_curlink(newfile) != 0)
257 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m",
258 newfile, auditd_strerror(err));
261 auditd_log_notice("New audit file is %s", newfile);
267 * Create a new audit log trail file and swap with the current one, if any.
275 * First, refresh the list of audit log directories.
277 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
279 auditd_log_err("auditd_read_dirs(): %s",
280 auditd_strerror(err));
281 if (err == ADE_HARDLIM)
282 audit_warn_allhard();
283 if (err != ADE_SOFTLIM)
286 audit_warn_allsoft();
287 /* continue on with soft limit error */
291 * Create a new file and swap with the one being used in kernel.
293 if (swap_audit_file() == -1) {
295 * XXX Faulty directory listing? - user should be given
296 * XXX an opportunity to change the audit_control file
297 * XXX switch to a reduced mode of auditing?
303 * Finally, see if there are any trail files to expire.
305 err = auditd_expire_trails(audit_warn_expired);
307 auditd_log_err("auditd_expire_trails(): %s",
308 auditd_strerror(err));
321 /* Configure trail files distribution. */
322 err = auditd_set_dist();
324 auditd_log_err("auditd_set_dist() %s: %m",
325 auditd_strerror(err));
327 auditd_log_debug("Configured trail files distribution.");
329 if (do_trail_file() == -1) {
330 auditd_log_err("Error creating audit trail file");
334 /* Generate an audit record. */
335 err = auditd_gen_record(AUE_audit_startup, NULL);
337 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m",
338 auditd_strerror(err));
340 if (auditd_config_controls() == 0)
341 auditd_log_info("Audit controls init successful");
343 auditd_log_err("Audit controls init failed");
348 * Close auditd pid file and trigger mechanism.
355 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) {
356 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
361 if (auditd_close_trigger() != 0) {
362 auditd_log_err("Error closing trigger messaging mechanism");
369 * Close all log files, control files, and tell the audit system.
375 char TS[TIMESTAMP_LEN + 1];
380 err = auditd_gen_record(AUE_audit_shutdown, NULL);
382 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m",
383 auditd_strerror(err));
385 /* Flush contents. */
387 err_ret = audit_set_cond(&cond);
389 auditd_log_err("Disabling audit failed! : %s", strerror(errno));
394 * Updated the cached state that auditing has been disabled.
396 auditd_set_state(AUD_STATE_DISABLED);
398 if (getTSstr(tt, TS, sizeof(TS)) == 0)
400 if (lastfile != NULL)
403 err_ret += close_misc();
406 auditd_log_err("Could not unregister");
407 audit_warn_postsigterm();
410 auditd_log_info("Finished");
415 * Register the daemon with the signal handler and the auditd pid file.
418 register_daemon(void)
424 /* Set up the signal hander. */
425 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
427 "Could not set signal handler for SIGTERM");
430 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
432 "Could not set signal handler for SIGCHLD");
435 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) {
437 "Could not set signal handler for SIGHUP");
440 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) {
442 "Could not set signal handler for SIGALRM");
446 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
447 auditd_log_err("Could not open PID file");
448 audit_warn_tmpfile();
452 /* Attempt to lock the pid file; if a lock is present, exit. */
453 fd = fileno(pidfile);
454 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
456 "PID file is locked (is another auditd running?).");
463 if (fprintf(pidfile, "%u\n", pid) < 0) {
464 /* Should not start the daemon. */
473 * Handle the audit trigger event.
475 * We suppress (ignore) duplicated triggers in close succession in order to
476 * try to avoid thrashing-like behavior. However, not all triggers can be
477 * ignored, as triggers generally represent edge triggers, not level
478 * triggers, and won't be retransmitted if the condition persists. Of
479 * specific concern is the rotate trigger -- if one is dropped, then it will
480 * not be retransmitted, and the log file will grow in an unbounded fashion.
482 #define DUPLICATE_INTERVAL 30
484 auditd_handle_trigger(int trigger)
486 static int last_trigger, last_warning;
487 static time_t last_time;
495 * Suppress duplicate messages from the kernel within the specified
498 if (gettimeofday(&ts, &tzp) == 0) {
499 tt = (time_t)ts.tv_sec;
501 case AUDIT_TRIGGER_LOW_SPACE:
502 case AUDIT_TRIGGER_NO_SPACE:
504 * Triggers we can suppress. Of course, we also need
505 * to rate limit the warnings, so apply the same
506 * interval limit on syslog messages.
508 if ((trigger == last_trigger) &&
509 (tt < (last_time + DUPLICATE_INTERVAL))) {
510 if (tt >= (last_warning + DUPLICATE_INTERVAL))
512 "Suppressing duplicate trigger %d",
519 case AUDIT_TRIGGER_ROTATE_KERNEL:
520 case AUDIT_TRIGGER_ROTATE_USER:
521 case AUDIT_TRIGGER_READ_FILE:
522 case AUDIT_TRIGGER_CLOSE_AND_DIE:
523 case AUDIT_TRIGGER_INITIALIZE:
525 * Triggers that we cannot suppress.
531 * Only update last_trigger after aborting due to a duplicate
532 * trigger, not before, or we will never allow that trigger
535 last_trigger = trigger;
539 au_state = auditd_get_state();
542 * Message processing is done here.
545 case AUDIT_TRIGGER_LOW_SPACE:
546 auditd_log_notice("Got low space trigger");
547 if (do_trail_file() == -1)
548 auditd_log_err("Error swapping audit file");
551 case AUDIT_TRIGGER_NO_SPACE:
552 auditd_log_notice("Got no space trigger");
553 if (do_trail_file() == -1)
554 auditd_log_err("Error swapping audit file");
557 case AUDIT_TRIGGER_ROTATE_KERNEL:
558 case AUDIT_TRIGGER_ROTATE_USER:
559 auditd_log_info("Got open new trigger from %s", trigger ==
560 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
561 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
562 auditd_log_err("Error swapping audit file");
565 case AUDIT_TRIGGER_READ_FILE:
566 auditd_log_info("Got read file trigger");
567 if (au_state == AUD_STATE_ENABLED) {
568 if (auditd_config_controls() == -1)
569 auditd_log_err("Error setting audit controls");
570 else if (do_trail_file() == -1)
571 auditd_log_err("Error swapping audit file");
575 case AUDIT_TRIGGER_CLOSE_AND_DIE:
576 auditd_log_info("Got close and die trigger");
577 if (au_state == AUD_STATE_ENABLED)
580 * Running under launchd don't exit. Wait for launchd to
584 auditd_log_info("auditd exiting.");
589 case AUDIT_TRIGGER_INITIALIZE:
590 auditd_log_info("Got audit initialize trigger");
591 if (au_state == AUD_STATE_DISABLED)
595 case AUDIT_TRIGGER_EXPIRE_TRAILS:
596 auditd_log_info("Got audit expire trails trigger");
597 err = auditd_expire_trails(audit_warn_expired);
599 auditd_log_err("auditd_expire_trails(): %s",
600 auditd_strerror(err));
604 auditd_log_err("Got unknown trigger %d", trigger);
613 auditd_reap_children(void)
618 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
621 auditd_log_info("warn process [pid=%d] %s %d.", child,
622 ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
623 "exited as a result of signal"),
624 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
630 * Reap any children and terminate. If under launchd don't shutdown auditing
631 * but just the other stuff.
634 auditd_terminate(void)
638 auditd_reap_children();
649 * Configure the audit controls in the kernel: the event to class mapping,
650 * kernel preselection mask, etc.
653 auditd_config_controls(void)
659 * Configure event to class mappings in kernel.
661 cnt = auditd_set_evcmap();
663 auditd_log_err("auditd_set_evcmap() failed: %m");
665 } else if (cnt == 0) {
666 auditd_log_err("No events to class mappings registered.");
669 auditd_log_debug("Registered %d event to class mappings.", cnt);
672 * Configure non-attributable event mask in kernel.
674 err = auditd_set_namask();
676 auditd_log_err("auditd_set_namask() %s: %m",
677 auditd_strerror(err));
680 auditd_log_debug("Registered non-attributable event mask.");
683 * Configure audit policy in kernel.
685 err = auditd_set_policy();
687 auditd_log_err("auditd_set_policy() %s: %m",
688 auditd_strerror(err));
691 auditd_log_debug("Set audit policy in kernel.");
694 * Configure audit trail log size in kernel.
696 err = auditd_set_fsize();
698 auditd_log_err("audit_set_fsize() %s: %m",
699 auditd_strerror(err));
702 auditd_log_debug("Set audit trail size in kernel.");
705 * Configure audit trail volume minimum free percentage of blocks in
708 err = auditd_set_minfree();
710 auditd_log_err("auditd_set_minfree() %s: %m",
711 auditd_strerror(err));
715 "Set audit trail min free percent in kernel.");
718 * Configure host address in the audit kernel information.
720 err = auditd_set_host();
722 if (err == ADE_PARSE) {
724 "audit_control(5) may be missing 'host:' field");
726 auditd_log_err("auditd_set_host() %s: %m",
727 auditd_strerror(err));
732 "Set audit host address information in kernel.");
738 * Setup and initialize auditd.
745 if (auditd_open_trigger(launchd_flag) < 0) {
746 auditd_log_err("Error opening trigger messaging mechanism");
751 * To prevent event feedback cycles and avoid auditd becoming
752 * stalled if auditing is suspended, auditd and its children run
753 * without their events being audited. We allow the uid, tid, and
754 * mask fields to be implicitly set to zero, but do set the pid. We
755 * run this after opening the trigger device to avoid configuring
756 * audit state without audit present in the system.
758 err = auditd_prevent_audit();
760 auditd_log_err("auditd_prevent_audit() %s: %m",
761 auditd_strerror(err));
766 * Make sure auditd auditing state is correct.
768 auditd_set_state(AUD_STATE_INIT);
771 * If under launchd, don't start auditing. Wait for a trigger to
779 main(int argc, char **argv)
783 #ifdef AUDIT_REVIEW_GROUP
787 while ((ch = getopt(argc, argv, "dl")) != -1) {
795 /* Be launchd friendly. */
801 (void)fprintf(stderr,
802 "usage: auditd [-d] [-l]\n");
807 audit_review_gid = getgid();
809 #ifdef AUDIT_REVIEW_GROUP
811 * XXXRW: Currently, this code falls back to the daemon gid, which is
812 * likely the wheel group. Is there a better way to deal with this?
814 grp = getgrnam(AUDIT_REVIEW_GROUP);
816 audit_review_gid = grp->gr_gid;
819 auditd_openlog(debug, audit_review_gid);
822 auditd_log_info("started by launchd...");
824 auditd_log_info("starting...");
826 #ifdef AUDIT_REVIEW_GROUP
829 "Audit review group '%s' not available, using daemon gid (%d)",
830 AUDIT_REVIEW_GROUP, audit_review_gid);
832 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) {
833 auditd_log_err("Failed to daemonize");
837 if (register_daemon() == -1) {
838 auditd_log_err("Could not register as daemon");
845 * auditd_wait_for_events() shouldn't return unless something is wrong.
847 auditd_wait_for_events();
849 auditd_log_err("abnormal exit.");