2 * Copyright (c) 2004 Apple Computer, Inc.
5 * @APPLE_BSD_LICENSE_HEADER_START@
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * @APPLE_BSD_LICENSE_HEADER_END@
33 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#16 $
36 #include <sys/types.h>
37 #include <sys/dirent.h>
39 #include <sys/queue.h>
43 #include <bsm/audit.h>
44 #include <bsm/audit_uevents.h>
45 #include <bsm/libbsm.h>
61 #define NA_EVENT_STR_SIZE 25
63 static int ret, minval;
64 static char *lastfile = NULL;
65 static int allhardcount = 0;
66 static int triggerfd = 0;
67 static int sigchlds, sigchlds_handled;
68 static int sighups, sighups_handled;
69 static int sigterms, sigterms_handled;
70 static long global_flags;
72 static TAILQ_HEAD(, dir_ent) dir_q;
74 static int config_audit_controls(void);
77 * Error starting auditd
88 * Free our local list of directory names.
93 struct dir_ent *dirent;
95 while ((dirent = TAILQ_FIRST(&dir_q))) {
96 TAILQ_REMOVE(&dir_q, dirent, dirs);
97 free(dirent->dirname);
103 * Generate the timestamp string.
106 getTSstr(char *buf, int len)
112 if (gettimeofday(&ts, &tzp) != 0)
114 tt = (time_t)ts.tv_sec;
115 if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt)))
121 * Concat the directory name to the given file name.
122 * XXX We should affix the hostname also
125 affixdir(char *name, struct dir_ent *dirent)
129 const char *sep = "/";
131 curdir = dirent->dirname;
132 syslog(LOG_DEBUG, "dir = %s", dirent->dirname);
134 fn = malloc(strlen(curdir) + strlen(sep) + (2 * POSTFIX_LEN) + 1);
144 * Close the previous audit trail file.
147 close_lastfile(char *TS)
152 if (lastfile != NULL) {
153 oldname = (char *)malloc(strlen(lastfile) + 1);
156 strcpy(oldname, lastfile);
158 /* Rename the last file -- append timestamp. */
159 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
162 if (rename(oldname, lastfile) != 0)
163 syslog(LOG_ERR, "Could not rename %s to %s",
166 syslog(LOG_INFO, "renamed %s to %s",
177 * Create the new audit file with appropriate permissions and ownership. Try
178 * to clean up if something goes wrong.
181 #ifdef AUDIT_REVIEW_GROUP
182 open_trail(const char *fname, uid_t uid, gid_t gid)
184 open_trail(const char *fname)
189 fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
192 #ifdef AUDIT_REVIEW_GROUP
193 if (fchown(fd, uid, gid) < 0) {
205 * Create the new file name, swap with existing audit file.
208 swap_audit_file(void)
210 char timestr[2 * POSTFIX_LEN];
212 char TS[POSTFIX_LEN];
213 struct dir_ent *dirent;
214 #ifdef AUDIT_REVIEW_GROUP
221 if (getTSstr(TS, POSTFIX_LEN) != 0)
225 strcat(timestr, NOT_TERMINATED);
227 #ifdef AUDIT_REVIEW_GROUP
229 * XXXRW: Currently, this code falls back to the daemon gid, which is
230 * likely the wheel group. Is there a better way to deal with this?
232 grp = getgrnam(AUDIT_REVIEW_GROUP);
235 "Audit review group '%s' not available, using daemon gid",
243 /* Try until we succeed. */
244 while ((dirent = TAILQ_FIRST(&dir_q))) {
245 if ((fn = affixdir(timestr, dirent)) == NULL) {
246 syslog(LOG_INFO, "Failed to swap log at time %s",
252 * Create and open the file; then close and pass to the
253 * kernel if all went well.
255 syslog(LOG_INFO, "New audit file is %s", fn);
256 #ifdef AUDIT_REVIEW_GROUP
257 fd = open_trail(fn, uid, gid);
262 warn("open(%s)", fn);
264 error = auditctl(fn);
267 "auditctl failed setting log file! : %s",
280 * Tell the administrator about lack of permissions for dir.
282 audit_warn_getacdir(dirent->dirname);
284 /* Try again with a different directory. */
285 TAILQ_REMOVE(&dir_q, dirent, dirs);
286 free(dirent->dirname);
289 syslog(LOG_ERR, "Log directories exhausted\n");
294 * Read the audit_control file contents.
297 read_control_file(void)
299 char cur_dir[MAXNAMLEN];
300 struct dir_ent *dirent;
304 * Clear old values. Force a re-read of the file the next time.
310 * Read the list of directories into a local linked list.
312 * XXX We should use the reentrant interfaces once they are
315 while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
316 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
320 dirent->dirname = (char *) malloc(MAXNAMLEN);
321 if (dirent->dirname == NULL) {
325 strcpy(dirent->dirname, cur_dir);
326 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
330 if (swap_audit_file() == -1) {
331 syslog(LOG_ERR, "Could not swap audit file");
333 * XXX Faulty directory listing? - user should be given
334 * XXX an opportunity to change the audit_control file
335 * XXX switch to a reduced mode of auditing?
341 * XXX There are synchronization problems here
342 * XXX what should we do if a trigger for the earlier limit
343 * XXX is generated here?
345 if (0 == (ret = getacmin(&minval))) {
346 syslog(LOG_DEBUG, "min free = %d\n", minval);
347 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
349 "could not get audit queue settings");
352 qctrl.aq_minfree = minval;
353 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
355 "could not set audit queue settings");
364 * Close all log files, control files, and tell the audit system.
370 char TS[POSTFIX_LEN];
375 /* Generate an audit record. */
376 if ((aufd = au_open()) == -1)
377 syslog(LOG_ERR, "Could not create audit shutdown event.");
379 if ((tok = au_to_text("auditd::Audit shutdown")) != NULL)
381 if (au_close(aufd, 1, AUE_audit_shutdown) == -1)
383 "Could not close audit shutdown event.");
386 /* Flush contents. */
388 err_ret = auditon(A_SETCOND, &cond, sizeof(cond));
390 syslog(LOG_ERR, "Disabling audit failed! : %s",
394 if (getTSstr(TS, POSTFIX_LEN) == 0)
396 if (lastfile != NULL)
400 if ((remove(AUDITD_PIDFILE) == -1) || err_ret) {
401 syslog(LOG_ERR, "Could not unregister");
402 audit_warn_postsigterm();
407 if (close(triggerfd) != 0)
408 syslog(LOG_ERR, "Error closing control file");
409 syslog(LOG_INFO, "Finished");
414 * When we get a signal, we are often not at a clean point. So, little can
415 * be done in the signal handler itself. Instead, we send a message to the
416 * main servicing loop to do proper handling from a non-signal-handler
420 relay_signal(int signal)
423 if (signal == SIGHUP)
425 if (signal == SIGTERM)
427 if (signal == SIGCHLD)
432 * Registering the daemon.
435 register_daemon(void)
441 /* Set up the signal hander. */
442 if (signal(SIGTERM, relay_signal) == SIG_ERR) {
444 "Could not set signal handler for SIGTERM");
447 if (signal(SIGCHLD, relay_signal) == SIG_ERR) {
449 "Could not set signal handler for SIGCHLD");
452 if (signal(SIGHUP, relay_signal) == SIG_ERR) {
454 "Could not set signal handler for SIGHUP");
458 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
459 syslog(LOG_ERR, "Could not open PID file");
460 audit_warn_tmpfile();
464 /* Attempt to lock the pid file; if a lock is present, exit. */
465 fd = fileno(pidfile);
466 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
468 "PID file is locked (is another auditd running?).");
475 if (fprintf(pidfile, "%u\n", pid) < 0) {
476 /* Should not start the daemon. */
485 * Suppress duplicate messages within a 30 second interval. This should be
486 * enough to time to rotate log files without thrashing from soft warnings
487 * generated before the log is actually rotated.
489 #define DUPLICATE_INTERVAL 30
491 handle_audit_trigger(int trigger)
493 static int last_trigger;
494 static time_t last_time;
495 struct dir_ent *dirent;
498 * Suppres duplicate messages from the kernel within the specified
505 if (gettimeofday(&ts, &tzp) == 0) {
506 tt = (time_t)ts.tv_sec;
507 if ((trigger == last_trigger) &&
508 (tt < (last_time + DUPLICATE_INTERVAL)))
510 last_trigger = trigger;
515 * Message processing is done here.
517 dirent = TAILQ_FIRST(&dir_q);
520 case AUDIT_TRIGGER_LOW_SPACE:
521 syslog(LOG_INFO, "Got low space trigger");
522 if (dirent && (dirent->softlim != 1)) {
523 TAILQ_REMOVE(&dir_q, dirent, dirs);
524 /* Add this node to the end of the list. */
525 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
526 audit_warn_soft(dirent->dirname);
529 if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL &&
530 swap_audit_file() == -1)
531 syslog(LOG_ERR, "Error swapping audit file");
534 * Check if the next dir has already reached its soft
537 dirent = TAILQ_FIRST(&dir_q);
538 if (dirent->softlim == 1) {
539 /* All dirs have reached their soft limit. */
540 audit_warn_allsoft();
544 * Continue auditing to the current file. Also
545 * generate an allsoft warning.
546 * XXX do we want to do this ?
548 audit_warn_allsoft();
552 case AUDIT_TRIGGER_NO_SPACE:
553 syslog(LOG_INFO, "Got no space trigger");
555 /* Delete current dir, go on to next. */
556 TAILQ_REMOVE(&dir_q, dirent, dirs);
557 audit_warn_hard(dirent->dirname);
558 free(dirent->dirname);
561 if (swap_audit_file() == -1)
562 syslog(LOG_ERR, "Error swapping audit file");
564 /* We are out of log directories. */
565 audit_warn_allhard(++allhardcount);
568 case AUDIT_TRIGGER_OPEN_NEW:
570 * Create a new file and swap with the one being used in
573 syslog(LOG_INFO, "Got open new trigger");
574 if (swap_audit_file() == -1)
575 syslog(LOG_ERR, "Error swapping audit file");
578 case AUDIT_TRIGGER_READ_FILE:
579 syslog(LOG_INFO, "Got read file trigger");
580 if (read_control_file() == -1)
581 syslog(LOG_ERR, "Error in audit control file");
582 if (config_audit_controls() == -1)
583 syslog(LOG_ERR, "Error setting audit controls");
587 syslog(LOG_ERR, "Got unknown trigger %d", trigger);
596 sighups_handled = sighups;
597 config_audit_controls();
609 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
612 syslog(LOG_INFO, "warn process [pid=%d] %s %d.", child,
613 ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
614 "exited as a result of signal"),
615 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
624 sigchlds_handled = sigchlds;
629 * Read the control file for triggers/signals and handle appropriately.
632 wait_for_events(void)
635 unsigned int trigger;
638 num = read(triggerfd, &trigger, sizeof(trigger));
639 if ((num == -1) && (errno != EINTR)) {
640 syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno);
643 if (sigterms != sigterms_handled) {
644 syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__);
647 if (sigchlds != sigchlds_handled) {
648 syslog(LOG_DEBUG, "%s: SIGCHLD", __FUNCTION__);
651 if (sighups != sighups_handled) {
652 syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__);
655 if ((num == -1) && (errno == EINTR))
658 syslog(LOG_ERR, "%s: read EOF", __FUNCTION__);
661 syslog(LOG_DEBUG, "%s: read %d", __FUNCTION__, trigger);
662 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE)
665 handle_audit_trigger(trigger);
667 return (close_all());
671 * Configure the audit controls in the kernel: the event to class mapping,
672 * kernel preselection mask, etc.
675 config_audit_controls(void)
677 au_event_ent_t ev, *evp;
678 au_evclass_map_t evc_map;
681 char naeventstr[NA_EVENT_STR_SIZE];
684 * Process the audit event file, obtaining a class mapping for each
685 * event, and send that mapping into the kernel.
686 * XXX There's a risk here that the BSM library will return NULL
687 * for an event when it can't properly map it to a class. In that
688 * case, we will not process any events beyond the one that failed,
689 * but should. We need a way to get a count of the events.
691 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
692 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
693 if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
695 "Memory allocation error when configuring audit controls.");
700 while ((evp = getauevent_r(evp)) != NULL) {
701 evc_map.ec_number = evp->ae_number;
702 evc_map.ec_class = evp->ae_class;
703 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
706 "Failed to register class mapping for event %s",
715 syslog(LOG_ERR, "No events to class mappings registered.");
717 syslog(LOG_DEBUG, "Registered %d event to class mappings.",
721 * Get the non-attributable event string and set the kernel mask from
724 if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) &&
725 (getauditflagsbin(naeventstr, &aumask) == 0)) {
726 if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t)))
728 "Failed to register non-attributable event mask.");
731 "Registered non-attributable event mask.");
734 "Failed to obtain non-attributable event mask.");
737 * Set the audit policy flags based on passed in parameter values.
739 if (auditon(A_SETPOLICY, &global_flags, sizeof(global_flags)))
740 syslog(LOG_ERR, "Failed to set audit policy.");
752 if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) {
753 syslog(LOG_ERR, "Error opening trigger file");
758 * To provide event feedback cycles and avoid auditd becoming
759 * stalled if auditing is suspended, auditd and its children run
760 * without their events being audited. We allow the uid, tid, and
761 * mask fields to be implicitly set to zero, but do set the pid. We
762 * run this after opening the trigger device to avoid configuring
763 * audit state without audit present in the system.
765 * XXXRW: Is there more to it than this?
767 bzero(&auinfo, sizeof(auinfo));
768 auinfo.ai_asid = getpid();
769 if (setaudit(&auinfo) == -1) {
770 syslog(LOG_ERR, "Error setting audit stat");
775 if (read_control_file() == -1) {
776 syslog(LOG_ERR, "Error reading control file");
780 /* Generate an audit record. */
781 if ((aufd = au_open()) == -1)
782 syslog(LOG_ERR, "Could not create audit startup event.");
784 if ((tok = au_to_text("auditd::Audit startup")) != NULL)
786 if (au_close(aufd, 1, AUE_audit_startup) == -1)
788 "Could not close audit startup event.");
791 if (config_audit_controls() == 0)
792 syslog(LOG_INFO, "Audit controls init successful");
794 syslog(LOG_ERR, "Audit controls init failed");
798 main(int argc, char **argv)
804 global_flags |= AUDIT_CNT;
805 while ((ch = getopt(argc, argv, "dhs")) != -1) {
813 /* Fail-stop option. */
814 global_flags &= ~(AUDIT_CNT);
818 /* Halt-stop option. */
819 global_flags |= AUDIT_AHLT;
824 (void)fprintf(stderr,
825 "usage: auditd [-h | -s] [-d] \n");
831 openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY);
833 openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH);
835 syslog(LOG_INFO, "starting...");
837 if (debug == 0 && daemon(0, 0) == -1) {
838 syslog(LOG_ERR, "Failed to daemonize");
842 if (register_daemon() == -1) {
843 syslog(LOG_ERR, "Could not register as daemon");
849 rc = wait_for_events();
850 syslog(LOG_INFO, "auditd exiting.");