Deleted Added
full compact
auditd.c (161863) auditd.c (162503)
1/*
2 * Copyright (c) 2004 Apple Computer, Inc.
3 * All rights reserved.
4 *
5 * @APPLE_BSD_LICENSE_HEADER_START@
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

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.
30 *
31 * @APPLE_BSD_LICENSE_HEADER_END@
32 *
1/*
2 * Copyright (c) 2004 Apple Computer, Inc.
3 * All rights reserved.
4 *
5 * @APPLE_BSD_LICENSE_HEADER_START@
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

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.
30 *
31 * @APPLE_BSD_LICENSE_HEADER_END@
32 *
33 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#18 $
33 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#21 $
34 */
35
36#include <sys/types.h>
37#include <sys/dirent.h>
38#include <sys/mman.h>
39#include <sys/queue.h>
40#include <sys/stat.h>
41#include <sys/wait.h>

--- 12 unchanged lines hidden (view full) ---

54#include <unistd.h>
55#include <signal.h>
56#include <string.h>
57#include <syslog.h>
58
59#include "auditd.h"
60
61#define NA_EVENT_STR_SIZE 25
34 */
35
36#include <sys/types.h>
37#include <sys/dirent.h>
38#include <sys/mman.h>
39#include <sys/queue.h>
40#include <sys/stat.h>
41#include <sys/wait.h>

--- 12 unchanged lines hidden (view full) ---

54#include <unistd.h>
55#include <signal.h>
56#include <string.h>
57#include <syslog.h>
58
59#include "auditd.h"
60
61#define NA_EVENT_STR_SIZE 25
62#define POL_STR_SIZE 128
62
63static int ret, minval;
64static char *lastfile = NULL;
65static int allhardcount = 0;
66static int triggerfd = 0;
67static int sigchlds, sigchlds_handled;
68static int sighups, sighups_handled;
69static int sigterms, sigterms_handled;
63
64static int ret, minval;
65static char *lastfile = NULL;
66static int allhardcount = 0;
67static int triggerfd = 0;
68static int sigchlds, sigchlds_handled;
69static int sighups, sighups_handled;
70static int sigterms, sigterms_handled;
70static long global_flags;
71
72static TAILQ_HEAD(, dir_ent) dir_q;
73
74static int config_audit_controls(void);
75
76/*
77 * Error starting auditd
78 */

--- 76 unchanged lines hidden (view full) ---

155 return (-1);
156 strcpy(oldname, lastfile);
157
158 /* Rename the last file -- append timestamp. */
159 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
160 *ptr = '.';
161 strcpy(ptr+1, TS);
162 if (rename(oldname, lastfile) != 0)
71
72static TAILQ_HEAD(, dir_ent) dir_q;
73
74static int config_audit_controls(void);
75
76/*
77 * Error starting auditd
78 */

--- 76 unchanged lines hidden (view full) ---

155 return (-1);
156 strcpy(oldname, lastfile);
157
158 /* Rename the last file -- append timestamp. */
159 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
160 *ptr = '.';
161 strcpy(ptr+1, TS);
162 if (rename(oldname, lastfile) != 0)
163 syslog(LOG_ERR, "Could not rename %s to %s",
164 oldname, lastfile);
163 syslog(LOG_ERR,
164 "Could not rename %s to %s: %m", oldname,
165 lastfile);
165 else
166 syslog(LOG_INFO, "renamed %s to %s",
167 oldname, lastfile);
168 }
169 free(lastfile);
170 free(oldname);
171 lastfile = NULL;
172 }

--- 108 unchanged lines hidden (view full) ---

281 */
282 audit_warn_getacdir(dirent->dirname);
283
284 /* Try again with a different directory. */
285 TAILQ_REMOVE(&dir_q, dirent, dirs);
286 free(dirent->dirname);
287 free(dirent);
288 }
166 else
167 syslog(LOG_INFO, "renamed %s to %s",
168 oldname, lastfile);
169 }
170 free(lastfile);
171 free(oldname);
172 lastfile = NULL;
173 }

--- 108 unchanged lines hidden (view full) ---

282 */
283 audit_warn_getacdir(dirent->dirname);
284
285 /* Try again with a different directory. */
286 TAILQ_REMOVE(&dir_q, dirent, dirs);
287 free(dirent->dirname);
288 free(dirent);
289 }
289 syslog(LOG_ERR, "Log directories exhausted\n");
290 syslog(LOG_ERR, "Log directories exhausted");
290 return (-1);
291}
292
293/*
294 * Read the audit_control file contents.
295 */
296static int
297read_control_file(void)

--- 40 unchanged lines hidden (view full) ---

338 }
339
340 /*
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?
344 */
345 if (0 == (ret = getacmin(&minval))) {
291 return (-1);
292}
293
294/*
295 * Read the audit_control file contents.
296 */
297static int
298read_control_file(void)

--- 40 unchanged lines hidden (view full) ---

339 }
340
341 /*
342 * XXX There are synchronization problems here
343 * XXX what should we do if a trigger for the earlier limit
344 * XXX is generated here?
345 */
346 if (0 == (ret = getacmin(&minval))) {
346 syslog(LOG_DEBUG, "min free = %d\n", minval);
347 syslog(LOG_DEBUG, "min free = %d", minval);
347 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
348 syslog(LOG_ERR,
349 "could not get audit queue settings");
350 return (-1);
351 }
352 qctrl.aq_minfree = minval;
353 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
354 syslog(LOG_ERR,

--- 134 unchanged lines hidden (view full) ---

489 fail_exit();
490 }
491
492 fflush(pidfile);
493 return (0);
494}
495
496/*
348 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
349 syslog(LOG_ERR,
350 "could not get audit queue settings");
351 return (-1);
352 }
353 qctrl.aq_minfree = minval;
354 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
355 syslog(LOG_ERR,

--- 134 unchanged lines hidden (view full) ---

490 fail_exit();
491 }
492
493 fflush(pidfile);
494 return (0);
495}
496
497/*
497 * Suppress duplicate messages within a 30 second interval. This should be
498 * enough to time to rotate log files without thrashing from soft warnings
499 * generated before the log is actually rotated.
498 * Handle the audit trigger event.
499 *
500 * We suppress (ignore) duplicated triggers in close succession in order to
501 * try to avoid thrashing-like behavior. However, not all triggers can be
502 * ignored, as triggers generally represent edge triggers, not level
503 * triggers, and won't be retransmitted if the condition persists. Of
504 * specific concern is the rotate trigger -- if one is dropped, then it will
505 * not be retransmitted, and the log file will grow in an unbounded fashion.
500 */
501#define DUPLICATE_INTERVAL 30
502static void
503handle_audit_trigger(int trigger)
504{
506 */
507#define DUPLICATE_INTERVAL 30
508static void
509handle_audit_trigger(int trigger)
510{
505 static int last_trigger;
511 static int last_trigger, last_warning;
506 static time_t last_time;
507 struct dir_ent *dirent;
512 static time_t last_time;
513 struct dir_ent *dirent;
508
509 /*
510 * Suppres duplicate messages from the kernel within the specified
511 * interval.
512 */
513 struct timeval ts;
514 struct timezone tzp;
515 time_t tt;
516
514 struct timeval ts;
515 struct timezone tzp;
516 time_t tt;
517
518 /*
519 * Suppress duplicate messages from the kernel within the specified
520 * interval.
521 */
517 if (gettimeofday(&ts, &tzp) == 0) {
518 tt = (time_t)ts.tv_sec;
522 if (gettimeofday(&ts, &tzp) == 0) {
523 tt = (time_t)ts.tv_sec;
519 if ((trigger == last_trigger) &&
520 (tt < (last_time + DUPLICATE_INTERVAL)))
521 return;
524 switch (trigger) {
525 case AUDIT_TRIGGER_LOW_SPACE:
526 case AUDIT_TRIGGER_NO_SPACE:
527 /*
528 * Triggers we can suppress. Of course, we also need
529 * to rate limit the warnings, so apply the same
530 * interval limit on syslog messages.
531 */
532 if ((trigger == last_trigger) &&
533 (tt < (last_time + DUPLICATE_INTERVAL))) {
534 if (tt >= (last_warning + DUPLICATE_INTERVAL))
535 syslog(LOG_INFO,
536 "Suppressing duplicate trigger %d",
537 trigger);
538 return;
539 }
540 last_warning = tt;
541 break;
542
543 case AUDIT_TRIGGER_ROTATE_KERNEL:
544 case AUDIT_TRIGGER_ROTATE_USER:
545 case AUDIT_TRIGGER_READ_FILE:
546 /*
547 * Triggers that we cannot suppress.
548 */
549 break;
550 }
551
552 /*
553 * Only update last_trigger after aborting due to a duplicate
554 * trigger, not before, or we will never allow that trigger
555 * again.
556 */
522 last_trigger = trigger;
523 last_time = tt;
524 }
525
526 /*
527 * Message processing is done here.
528 */
529 dirent = TAILQ_FIRST(&dir_q);
530 switch(trigger) {
557 last_trigger = trigger;
558 last_time = tt;
559 }
560
561 /*
562 * Message processing is done here.
563 */
564 dirent = TAILQ_FIRST(&dir_q);
565 switch(trigger) {
531
532 case AUDIT_TRIGGER_LOW_SPACE:
533 syslog(LOG_INFO, "Got low space trigger");
534 if (dirent && (dirent->softlim != 1)) {
535 TAILQ_REMOVE(&dir_q, dirent, dirs);
536 /* Add this node to the end of the list. */
537 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
538 audit_warn_soft(dirent->dirname);
539 dirent->softlim = 1;

--- 9 unchanged lines hidden (view full) ---

549 dirent = TAILQ_FIRST(&dir_q);
550 if (dirent->softlim == 1) {
551 /* All dirs have reached their soft limit. */
552 audit_warn_allsoft();
553 }
554 } else {
555 /*
556 * Continue auditing to the current file. Also
566 case AUDIT_TRIGGER_LOW_SPACE:
567 syslog(LOG_INFO, "Got low space trigger");
568 if (dirent && (dirent->softlim != 1)) {
569 TAILQ_REMOVE(&dir_q, dirent, dirs);
570 /* Add this node to the end of the list. */
571 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
572 audit_warn_soft(dirent->dirname);
573 dirent->softlim = 1;

--- 9 unchanged lines hidden (view full) ---

583 dirent = TAILQ_FIRST(&dir_q);
584 if (dirent->softlim == 1) {
585 /* All dirs have reached their soft limit. */
586 audit_warn_allsoft();
587 }
588 } else {
589 /*
590 * Continue auditing to the current file. Also
557 * generate an allsoft warning.
591 * generate an allsoft warning.
592 *
558 * XXX do we want to do this ?
559 */
560 audit_warn_allsoft();
561 }
562 break;
563
564 case AUDIT_TRIGGER_NO_SPACE:
565 syslog(LOG_INFO, "Got no space trigger");

--- 6 unchanged lines hidden (view full) ---

572
573 if (swap_audit_file() == -1)
574 syslog(LOG_ERR, "Error swapping audit file");
575
576 /* We are out of log directories. */
577 audit_warn_allhard(++allhardcount);
578 break;
579
593 * XXX do we want to do this ?
594 */
595 audit_warn_allsoft();
596 }
597 break;
598
599 case AUDIT_TRIGGER_NO_SPACE:
600 syslog(LOG_INFO, "Got no space trigger");

--- 6 unchanged lines hidden (view full) ---

607
608 if (swap_audit_file() == -1)
609 syslog(LOG_ERR, "Error swapping audit file");
610
611 /* We are out of log directories. */
612 audit_warn_allhard(++allhardcount);
613 break;
614
580 case AUDIT_TRIGGER_OPEN_NEW:
615 case AUDIT_TRIGGER_ROTATE_KERNEL:
616 case AUDIT_TRIGGER_ROTATE_USER:
581 /*
582 * Create a new file and swap with the one being used in
583 * kernel
584 */
617 /*
618 * Create a new file and swap with the one being used in
619 * kernel
620 */
585 syslog(LOG_INFO, "Got open new trigger");
621 syslog(LOG_INFO, "Got open new trigger from %s", trigger ==
622 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
586 if (swap_audit_file() == -1)
587 syslog(LOG_ERR, "Error swapping audit file");
588 break;
589
590 case AUDIT_TRIGGER_READ_FILE:
591 syslog(LOG_INFO, "Got read file trigger");
592 if (read_control_file() == -1)
593 syslog(LOG_ERR, "Error in audit control file");

--- 57 unchanged lines hidden (view full) ---

651 if ((num == -1) && (errno != EINTR)) {
652 syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno);
653 return (-1);
654 }
655 if (sigterms != sigterms_handled) {
656 syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__);
657 break;
658 }
623 if (swap_audit_file() == -1)
624 syslog(LOG_ERR, "Error swapping audit file");
625 break;
626
627 case AUDIT_TRIGGER_READ_FILE:
628 syslog(LOG_INFO, "Got read file trigger");
629 if (read_control_file() == -1)
630 syslog(LOG_ERR, "Error in audit control file");

--- 57 unchanged lines hidden (view full) ---

688 if ((num == -1) && (errno != EINTR)) {
689 syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno);
690 return (-1);
691 }
692 if (sigterms != sigterms_handled) {
693 syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__);
694 break;
695 }
659 if (sigchlds != sigchlds_handled) {
660 syslog(LOG_DEBUG, "%s: SIGCHLD", __FUNCTION__);
696 if (sigchlds != sigchlds_handled)
661 handle_sigchld();
697 handle_sigchld();
662 }
663 if (sighups != sighups_handled) {
664 syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__);
665 handle_sighup();
666 }
667 if ((num == -1) && (errno == EINTR))
668 continue;
669 if (num == 0) {
670 syslog(LOG_ERR, "%s: read EOF", __FUNCTION__);
671 return (-1);
672 }
698 if (sighups != sighups_handled) {
699 syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__);
700 handle_sighup();
701 }
702 if ((num == -1) && (errno == EINTR))
703 continue;
704 if (num == 0) {
705 syslog(LOG_ERR, "%s: read EOF", __FUNCTION__);
706 return (-1);
707 }
673 syslog(LOG_DEBUG, "%s: read %d", __FUNCTION__, trigger);
674 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE)
675 break;
676 else
677 handle_audit_trigger(trigger);
678 }
679 return (close_all());
680}
681

--- 4 unchanged lines hidden (view full) ---

686static int
687config_audit_controls(void)
688{
689 au_event_ent_t ev, *evp;
690 au_evclass_map_t evc_map;
691 au_mask_t aumask;
692 int ctr = 0;
693 char naeventstr[NA_EVENT_STR_SIZE];
708 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE)
709 break;
710 else
711 handle_audit_trigger(trigger);
712 }
713 return (close_all());
714}
715

--- 4 unchanged lines hidden (view full) ---

720static int
721config_audit_controls(void)
722{
723 au_event_ent_t ev, *evp;
724 au_evclass_map_t evc_map;
725 au_mask_t aumask;
726 int ctr = 0;
727 char naeventstr[NA_EVENT_STR_SIZE];
728 char polstr[POL_STR_SIZE];
729 long policy;
694
695 /*
696 * Process the audit event file, obtaining a class mapping for each
697 * event, and send that mapping into the kernel.
730
731 /*
732 * Process the audit event file, obtaining a class mapping for each
733 * event, and send that mapping into the kernel.
734 *
698 * XXX There's a risk here that the BSM library will return NULL
699 * for an event when it can't properly map it to a class. In that
700 * case, we will not process any events beyond the one that failed,
701 * but should. We need a way to get a count of the events.
702 */
703 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
704 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
705 if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
735 * XXX There's a risk here that the BSM library will return NULL
736 * for an event when it can't properly map it to a class. In that
737 * case, we will not process any events beyond the one that failed,
738 * but should. We need a way to get a count of the events.
739 */
740 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
741 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
742 if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
743 if (ev.ae_name != NULL)
744 free(ev.ae_name);
706 syslog(LOG_ERR,
707 "Memory allocation error when configuring audit controls.");
708 return (-1);
709 }
745 syslog(LOG_ERR,
746 "Memory allocation error when configuring audit controls.");
747 return (-1);
748 }
749
750 /*
751 * XXXRW: Currently we have no way to remove mappings from the kernel
752 * when they are removed from the file-based mappings.
753 */
710 evp = &ev;
711 setauevent();
712 while ((evp = getauevent_r(evp)) != NULL) {
713 evc_map.ec_number = evp->ae_number;
714 evc_map.ec_class = evp->ae_class;
715 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
716 != 0)
717 syslog(LOG_ERR,

--- 23 unchanged lines hidden (view full) ---

741 else
742 syslog(LOG_DEBUG,
743 "Registered non-attributable event mask.");
744 } else
745 syslog(LOG_ERR,
746 "Failed to obtain non-attributable event mask.");
747
748 /*
754 evp = &ev;
755 setauevent();
756 while ((evp = getauevent_r(evp)) != NULL) {
757 evc_map.ec_number = evp->ae_number;
758 evc_map.ec_class = evp->ae_class;
759 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
760 != 0)
761 syslog(LOG_ERR,

--- 23 unchanged lines hidden (view full) ---

785 else
786 syslog(LOG_DEBUG,
787 "Registered non-attributable event mask.");
788 } else
789 syslog(LOG_ERR,
790 "Failed to obtain non-attributable event mask.");
791
792 /*
749 * Set the audit policy flags based on passed in parameter values.
793 * If a policy is configured in audit_control(5), implement the
794 * policy. However, if one isn't defined, set AUDIT_CNT to avoid
795 * leaving the system in a fragile state.
750 */
796 */
751 if (auditon(A_SETPOLICY, &global_flags, sizeof(global_flags)))
752 syslog(LOG_ERR, "Failed to set audit policy.");
797 if ((getacpol(polstr, POL_STR_SIZE) == 0) &&
798 (au_strtopol(polstr, &policy) == 0)) {
799 if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
800 syslog(LOG_ERR, "Failed to set audit policy: %m");
801 } else {
802 syslog(LOG_ERR, "Failed to obtain policy flags: %m");
803 policy = AUDIT_CNT;
804 if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
805 syslog(LOG_ERR,
806 "Failed to set default audit policy: %m");
807 }
753
754 return (0);
755}
756
757static void
758setup(void)
759{
760 struct auditinfo ai;

--- 60 unchanged lines hidden (view full) ---

821
822int
823main(int argc, char **argv)
824{
825 int ch;
826 int debug = 0;
827 int rc;
828
808
809 return (0);
810}
811
812static void
813setup(void)
814{
815 struct auditinfo ai;

--- 60 unchanged lines hidden (view full) ---

876
877int
878main(int argc, char **argv)
879{
880 int ch;
881 int debug = 0;
882 int rc;
883
829 global_flags |= AUDIT_CNT;
830 while ((ch = getopt(argc, argv, "dhs")) != -1) {
831 switch(ch) {
832 case 'd':
833 /* Debug option. */
834 debug = 1;
835 break;
836
884 while ((ch = getopt(argc, argv, "dhs")) != -1) {
885 switch(ch) {
886 case 'd':
887 /* Debug option. */
888 debug = 1;
889 break;
890
837 case 's':
838 /* Fail-stop option. */
839 global_flags &= ~(AUDIT_CNT);
840 break;
841
842 case 'h':
843 /* Halt-stop option. */
844 global_flags |= AUDIT_AHLT;
845 break;
846
847 case '?':
848 default:
849 (void)fprintf(stderr,
891 case '?':
892 default:
893 (void)fprintf(stderr,
850 "usage: auditd [-h | -s] [-d] \n");
894 "usage: auditd [-d] \n");
851 exit(1);
852 }
853 }
854
855#ifdef LOG_SECURITY
856 openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY);
857#else
858 openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH);

--- 20 unchanged lines hidden ---
895 exit(1);
896 }
897 }
898
899#ifdef LOG_SECURITY
900 openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY);
901#else
902 openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH);

--- 20 unchanged lines hidden ---