diff options
Diffstat (limited to 'contrib/openbsm/bin')
| -rw-r--r-- | contrib/openbsm/bin/Makefile.in | 2 | ||||
| -rw-r--r-- | contrib/openbsm/bin/audit/Makefile.am | 10 | ||||
| -rw-r--r-- | contrib/openbsm/bin/audit/Makefile.in | 16 | ||||
| -rw-r--r-- | contrib/openbsm/bin/audit/audit.8 | 23 | ||||
| -rw-r--r-- | contrib/openbsm/bin/audit/audit.c | 33 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/Makefile.am | 18 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/Makefile.in | 41 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/audit_warn.c | 15 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/auditd.8 | 55 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/auditd.c | 1188 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/auditd.h | 39 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/auditd_darwin.c | 484 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditd/auditd_fbsd.c | 272 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditfilterd/Makefile.in | 2 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditreduce/Makefile.in | 2 | ||||
| -rw-r--r-- | contrib/openbsm/bin/auditreduce/auditreduce.c | 4 | ||||
| -rw-r--r-- | contrib/openbsm/bin/praudit/Makefile.in | 2 |
17 files changed, 1297 insertions, 909 deletions
diff --git a/contrib/openbsm/bin/Makefile.in b/contrib/openbsm/bin/Makefile.in index ddace5819f425..06ef9a75dc47b 100644 --- a/contrib/openbsm/bin/Makefile.in +++ b/contrib/openbsm/bin/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/Makefile.in#8 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/Makefile.in#10 $ # VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ diff --git a/contrib/openbsm/bin/audit/Makefile.am b/contrib/openbsm/bin/audit/Makefile.am index ed62929ca00e1..1b5d554ac62b7 100644 --- a/contrib/openbsm/bin/audit/Makefile.am +++ b/contrib/openbsm/bin/audit/Makefile.am @@ -1,5 +1,5 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/audit/Makefile.am#4 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/audit/Makefile.am#6 $ # if USE_NATIVE_INCLUDES @@ -13,11 +13,11 @@ audit_LDADD = $(top_builddir)/libbsm/libbsm.la man8_MANS = audit.8 if USE_MACH_IPC -audit_SOURCES = auditd_control_user.c audit.c -CLEANFILES = auditd_control_user.c auditd_control_user.h +audit_SOURCES = auditd_controlUser.c audit.c +CLEANFILES = auditd_controlUser.c auditd_control.h -auditd_control_user.c: $(top_srcdir)/bin/auditd/auditd_control.defs - $(MIG) -user auditd_control_user.c -header auditd_control_user.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs +auditd_controlUser.c auditd_control.h: $(top_srcdir)/bin/auditd/auditd_control.defs + $(MIG) -user auditd_controlUser.c -header auditd_control.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs else audit_SOURCES = audit.c endif diff --git a/contrib/openbsm/bin/audit/Makefile.in b/contrib/openbsm/bin/audit/Makefile.in index edaf018170cd6..ae2dd6ec6bcf4 100644 --- a/contrib/openbsm/bin/audit/Makefile.in +++ b/contrib/openbsm/bin/audit/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/audit/Makefile.in#9 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/audit/Makefile.in#11 $ # VPATH = @srcdir@ @@ -49,9 +49,9 @@ CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(sbin_PROGRAMS) -am__audit_SOURCES_DIST = audit.c auditd_control_user.c +am__audit_SOURCES_DIST = audit.c auditd_controlUser.c @USE_MACH_IPC_FALSE@am_audit_OBJECTS = audit.$(OBJEXT) -@USE_MACH_IPC_TRUE@am_audit_OBJECTS = auditd_control_user.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@am_audit_OBJECTS = auditd_controlUser.$(OBJEXT) \ @USE_MACH_IPC_TRUE@ audit.$(OBJEXT) audit_OBJECTS = $(am_audit_OBJECTS) audit_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la @@ -188,8 +188,8 @@ top_srcdir = @top_srcdir@ audit_LDADD = $(top_builddir)/libbsm/libbsm.la man8_MANS = audit.8 @USE_MACH_IPC_FALSE@audit_SOURCES = audit.c -@USE_MACH_IPC_TRUE@audit_SOURCES = auditd_control_user.c audit.c -@USE_MACH_IPC_TRUE@CLEANFILES = auditd_control_user.c auditd_control_user.h +@USE_MACH_IPC_TRUE@audit_SOURCES = auditd_controlUser.c audit.c +@USE_MACH_IPC_TRUE@CLEANFILES = auditd_controlUser.c auditd_control.h all: all-am .SUFFIXES: @@ -262,7 +262,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_control_user.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_controlUser.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -521,8 +521,8 @@ uninstall-man: uninstall-man8 uninstall-sbinPROGRAMS -@USE_MACH_IPC_TRUE@auditd_control_user.c: $(top_srcdir)/bin/auditd/auditd_control.defs -@USE_MACH_IPC_TRUE@ $(MIG) -user auditd_control_user.c -header auditd_control_user.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs +@USE_MACH_IPC_TRUE@auditd_controlUser.c auditd_control.h: $(top_srcdir)/bin/auditd/auditd_control.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user auditd_controlUser.c -header auditd_control.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/contrib/openbsm/bin/audit/audit.8 b/contrib/openbsm/bin/audit/audit.8 index 4aaa494b30dad..b0276d40da6ab 100644 --- a/contrib/openbsm/bin/audit/audit.8 +++ b/contrib/openbsm/bin/audit/audit.8 @@ -25,9 +25,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.8#11 $ +.\" $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.8#13 $ .\" -.Dd October 2, 2006 +.Dd December 11, 2008 .Dt AUDIT 8 .Os .Sh NAME @@ -35,7 +35,7 @@ .Nd audit management utility .Sh SYNOPSIS .Nm -.Fl n | s | t +.Fl i | n | s | t .Sh DESCRIPTION The .Nm @@ -43,6 +43,13 @@ utility controls the state of the audit system. One of the following flags is required as an argument to .Nm : .Bl -tag -width indent +.It Fl i +Initializes and starts auditing. +This option is currently for Mac OS X only +and requires +.Xr auditd 8 +to be configured to run under +.Xr launchd 8 . .It Fl n Forces the audit system to close the existing audit log file and rotate to a new log file in a location specified in the audit control file. @@ -59,6 +66,13 @@ and renamed to indicate the time of the shutdown. The .Xr auditd 8 daemon must already be running. +Optionally, it can be configured to be started +on-demand by +.Xr launchd 8 +(Mac OS X only). +The +.Nm +utility requires audit administrator privileges for successful operation. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_control" -compact .It Pa /etc/security/audit_control @@ -67,7 +81,8 @@ Audit policy file used to configure the auditing system. .Sh SEE ALSO .Xr audit 4 , .Xr audit_control 5 , -.Xr auditd 8 +.Xr auditd 8 , +.Xr launchd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. diff --git a/contrib/openbsm/bin/audit/audit.c b/contrib/openbsm/bin/audit/audit.c index b1415a64a80b3..3a07aa75966da 100644 --- a/contrib/openbsm/bin/audit/audit.c +++ b/contrib/openbsm/bin/audit/audit.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.c#11 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.c#13 $ */ /* * Program to trigger the audit daemon with a message that is either: @@ -47,6 +47,7 @@ #include <bsm/libbsm.h> +#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> @@ -64,7 +65,15 @@ static int send_trigger(unsigned int); #include <mach/host_special_ports.h> #include <servers/bootstrap.h> -#include "auditd_control_user.h" +#include "auditd_control.h" + +/* + * XXX the following is temporary until this can be added to the kernel + * audit.h header. + */ +#ifndef AUDIT_TRIGGER_INITIALIZE +#define AUDIT_TRIGGER_INITIALIZE 7 +#endif static int send_trigger(unsigned int trigger) @@ -74,7 +83,12 @@ send_trigger(unsigned int trigger) error = host_get_audit_control_port(mach_host_self(), &serverPort); if (error != KERN_SUCCESS) { - mach_error("Cannot get auditd_control Mach port: ", error); + if (geteuid() != 0) { + errno = EPERM; + perror("audit requires root privileges"); + } else + mach_error("Cannot get auditd_control Mach port:", + error); return (-1); } @@ -96,7 +110,10 @@ send_trigger(unsigned int trigger) error = auditon(A_SENDTRIGGER, &trigger, sizeof(trigger)); if (error != 0) { - perror("Error sending trigger"); + if (error == EPERM) + perror("audit requires root privileges"); + else + perror("Error sending trigger"); return (-1); } @@ -108,7 +125,7 @@ static void usage(void) { - (void)fprintf(stderr, "Usage: audit -n | -s | -t \n"); + (void)fprintf(stderr, "Usage: audit -i | -n | -s | -t \n"); exit(-1); } @@ -124,9 +141,13 @@ main(int argc, char **argv) if (argc != 2) usage(); - while ((ch = getopt(argc, argv, "nst")) != -1) { + while ((ch = getopt(argc, argv, "inst")) != -1) { switch(ch) { + case 'i': + trigger = AUDIT_TRIGGER_INITIALIZE; + break; + case 'n': trigger = AUDIT_TRIGGER_ROTATE_USER; break; diff --git a/contrib/openbsm/bin/auditd/Makefile.am b/contrib/openbsm/bin/auditd/Makefile.am index f65b1556bdff4..2372fa6e7fd10 100644 --- a/contrib/openbsm/bin/auditd/Makefile.am +++ b/contrib/openbsm/bin/auditd/Makefile.am @@ -1,5 +1,5 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/Makefile.am#4 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/Makefile.am#5 $ # if USE_NATIVE_INCLUDES @@ -9,18 +9,18 @@ INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = auditd -auditd_LDADD = $(top_builddir)/libbsm/libbsm.la +auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la man8_MANS = auditd.8 if USE_MACH_IPC -auditd_SOURCES = auditd_control_server.c audit_triggers_server.c audit_warn.c auditd.c -CLEANFILES = auditd_control_server.c auditd_control_server.h audit_triggers_server.c audit_triggers_server.h +auditd_SOURCES = auditd_controlServer.c audit_triggersServer.c audit_warn.c auditd.c auditd_darwin.c +CLEANFILES = auditd_control_server.c auditd_controlServer.h audit_triggersServer.c audit_triggersServer.h -auditd_control_server.c: auditd_control.defs - $(MIG) -user /dev/null -header /dev/null -server auditd_control_server.c -sheader auditd_control_server.h $(top_srcdir)/bin/auditd/auditd_control.defs +auditd_controlServer.c auditd_controlServer.h: auditd_control.defs + $(MIG) -user /dev/null -header /dev/null -server auditd_controlServer.c -sheader auditd_controlServer.h $(top_srcdir)/bin/auditd/auditd_control.defs -audit_triggers_server.c: audit_triggers.defs - $(MIG) -user /dev/null -header /dev/null -server audit_triggers_server.c -sheader audit_triggers_server.h $(top_srcdir)/bin/auditd/audit_triggers.defs +audit_triggersServer.c audit_triggersServer.h: audit_triggers.defs + $(MIG) -user /dev/null -header /dev/null -server audit_triggersServer.c -sheader audit_triggersServer.h $(top_srcdir)/bin/auditd/audit_triggers.defs else -auditd_SOURCES = audit_warn.c auditd.c +auditd_SOURCES = audit_warn.c auditd.c auditd_fbsd.c endif diff --git a/contrib/openbsm/bin/auditd/Makefile.in b/contrib/openbsm/bin/auditd/Makefile.in index 731607cc54f4b..44240d6be37c3 100644 --- a/contrib/openbsm/bin/auditd/Makefile.in +++ b/contrib/openbsm/bin/auditd/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/Makefile.in#9 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/Makefile.in#10 $ # VPATH = @srcdir@ @@ -49,16 +49,17 @@ CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(sbin_PROGRAMS) -am__auditd_SOURCES_DIST = audit_warn.c auditd.c \ - auditd_control_server.c audit_triggers_server.c +am__auditd_SOURCES_DIST = audit_warn.c auditd.c auditd_fbsd.c \ + auditd_controlServer.c audit_triggersServer.c auditd_darwin.c @USE_MACH_IPC_FALSE@am_auditd_OBJECTS = audit_warn.$(OBJEXT) \ -@USE_MACH_IPC_FALSE@ auditd.$(OBJEXT) -@USE_MACH_IPC_TRUE@am_auditd_OBJECTS = \ -@USE_MACH_IPC_TRUE@ auditd_control_server.$(OBJEXT) \ -@USE_MACH_IPC_TRUE@ audit_triggers_server.$(OBJEXT) \ -@USE_MACH_IPC_TRUE@ audit_warn.$(OBJEXT) auditd.$(OBJEXT) +@USE_MACH_IPC_FALSE@ auditd.$(OBJEXT) auditd_fbsd.$(OBJEXT) +@USE_MACH_IPC_TRUE@am_auditd_OBJECTS = auditd_controlServer.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ audit_triggersServer.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ audit_warn.$(OBJEXT) auditd.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ auditd_darwin.$(OBJEXT) auditd_OBJECTS = $(am_auditd_OBJECTS) -auditd_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la +auditd_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la \ + $(top_builddir)/libauditd/libauditd.la DEFAULT_INCLUDES = -I. -I$(top_builddir)/config@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles @@ -189,11 +190,11 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys @USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -auditd_LDADD = $(top_builddir)/libbsm/libbsm.la +auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la man8_MANS = auditd.8 -@USE_MACH_IPC_FALSE@auditd_SOURCES = audit_warn.c auditd.c -@USE_MACH_IPC_TRUE@auditd_SOURCES = auditd_control_server.c audit_triggers_server.c audit_warn.c auditd.c -@USE_MACH_IPC_TRUE@CLEANFILES = auditd_control_server.c auditd_control_server.h audit_triggers_server.c audit_triggers_server.h +@USE_MACH_IPC_FALSE@auditd_SOURCES = audit_warn.c auditd.c auditd_fbsd.c +@USE_MACH_IPC_TRUE@auditd_SOURCES = auditd_controlServer.c audit_triggersServer.c audit_warn.c auditd.c auditd_darwin.c +@USE_MACH_IPC_TRUE@CLEANFILES = auditd_control_server.c auditd_controlServer.h audit_triggersServer.c audit_triggersServer.h all: all-am .SUFFIXES: @@ -265,10 +266,12 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_triggers_server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_triggersServer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_warn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_control_server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_controlServer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_darwin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_fbsd.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -527,11 +530,11 @@ uninstall-man: uninstall-man8 uninstall-sbinPROGRAMS -@USE_MACH_IPC_TRUE@auditd_control_server.c: auditd_control.defs -@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server auditd_control_server.c -sheader auditd_control_server.h $(top_srcdir)/bin/auditd/auditd_control.defs +@USE_MACH_IPC_TRUE@auditd_controlServer.c auditd_controlServer.h: auditd_control.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server auditd_controlServer.c -sheader auditd_controlServer.h $(top_srcdir)/bin/auditd/auditd_control.defs -@USE_MACH_IPC_TRUE@audit_triggers_server.c: audit_triggers.defs -@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server audit_triggers_server.c -sheader audit_triggers_server.h $(top_srcdir)/bin/auditd/audit_triggers.defs +@USE_MACH_IPC_TRUE@audit_triggersServer.c audit_triggersServer.h: audit_triggers.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server audit_triggersServer.c -sheader audit_triggersServer.h $(top_srcdir)/bin/auditd/audit_triggers.defs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/contrib/openbsm/bin/auditd/audit_warn.c b/contrib/openbsm/bin/auditd/audit_warn.c index 7bc7a14572b77..6dfb3bd2f7b05 100644 --- a/contrib/openbsm/bin/auditd/audit_warn.c +++ b/contrib/openbsm/bin/auditd/audit_warn.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/audit_warn.c#9 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/audit_warn.c#10 $ */ #include <sys/types.h> @@ -71,20 +71,15 @@ auditwarnlog(char *args[]) } /* - * Indicates that the hard limit for all filesystems has been exceeded count - * times. + * Indicates that the hard limit for all filesystems has been exceeded. */ int -audit_warn_allhard(int count) +audit_warn_allhard(void) { - char intstr[12]; - char *args[3]; - - snprintf(intstr, 12, "%d", count); + char *args[2]; args[0] = HARDLIM_ALL_WARN; - args[1] = intstr; - args[2] = NULL; + args[1] = NULL; return (auditwarnlog(args)); } diff --git a/contrib/openbsm/bin/auditd/auditd.8 b/contrib/openbsm/bin/auditd/auditd.8 index 199b9ccbdbe31..49cf9eaeaf5e5 100644 --- a/contrib/openbsm/bin/auditd/auditd.8 +++ b/contrib/openbsm/bin/auditd/auditd.8 @@ -25,9 +25,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.8#14 $ +.\" $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.8#16 $ .\" -.Dd October 2, 2006 +.Dd December 11, 2008 .Dt AUDITD 8 .Os .Sh NAME @@ -35,7 +35,7 @@ .Nd audit log management daemon .Sh SYNOPSIS .Nm -.Op Fl d +.Op Fl d | l .Sh DESCRIPTION The .Nm @@ -50,7 +50,16 @@ The options are as follows: .Bl -tag -width indent .It Fl d Starts the daemon in debug mode \[em] it will not daemonize. +.It Fl l +This option is for when +.Nm +is configured to start on-demand using +.Xr launchd 8 . .El +.Pp +Optionally, the audit review group "audit" may be created. +Non-privileged +users that are members of this group may read the audit trail log files. .Sh NOTE To assure uninterrupted audit support, the .Nm @@ -63,20 +72,33 @@ the .Pa audit_control file. .Pp -.\" Sending a -.\" .Dv SIGHUP -.\" to a running -.\" .Nm -.\" daemon will force it to exit. -Sending a -.Dv SIGTERM -to a running +If +.Nm +is started on-demand by +.Xr launchd 8 +then auditing should only be started and stopped with +.Xr audit 8 . +.Pp +On Mac OS X, .Nm -daemon will force it to exit. +uses the +.Xr asl 3 +API for writing system log messages. +Therefore, only the audit administrator +and members of the audit review group will be able to read the +system log entries. .Sh FILES -.Bl -tag -width ".Pa /var/audit" -compact +.Bl -tag -width ".Pa /etc/security" -compact .It Pa /var/audit Default directory for storing audit log files. +.Pp +.It Pa /etc/security +The directory containing the auditing configuration files +.Xr audit_class 5 , +.Xr audit_control 5 , +.Xr audit_event 5 , +and +.Xr audit_warn 5 . .El .Sh COMPATIBILITY The historical @@ -92,9 +114,14 @@ and and are no longer available as arguments to .Nm . .Sh SEE ALSO +.Xr asl 3 , .Xr audit 4 , +.Xr audit_class 5 , .Xr audit_control 5 , -.Xr audit 8 +.Xr audit_event 5 , +.Xr audit_warn 5 , +.Xr audit 8 , +.Xr launchd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. diff --git a/contrib/openbsm/bin/auditd/auditd.c b/contrib/openbsm/bin/auditd/auditd.c index e0c03d0bf6a17..316402a85b027 100644 --- a/contrib/openbsm/bin/auditd/auditd.c +++ b/contrib/openbsm/bin/auditd/auditd.c @@ -26,30 +26,29 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#39 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#40 $ */ -#include <sys/param.h> +#include <sys/types.h> #include <config/config.h> #include <sys/dirent.h> -#include <sys/mman.h> -#include <sys/socket.h> #ifdef HAVE_FULL_QUEUE_H #include <sys/queue.h> #else /* !HAVE_FULL_QUEUE_H */ #include <compat/queue.h> #endif /* !HAVE_FULL_QUEUE_H */ +#include <sys/mman.h> +#include <sys/param.h> #include <sys/stat.h> #include <sys/wait.h> #include <bsm/audit.h> #include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> #include <bsm/libbsm.h> -#include <netinet/in.h> - #include <err.h> #include <errno.h> #include <fcntl.h> @@ -60,115 +59,88 @@ #include <unistd.h> #include <signal.h> #include <string.h> -#include <syslog.h> -#include <netdb.h> #include "auditd.h" -#ifdef USE_MACH_IPC -#include <notify.h> -#include <mach/port.h> -#include <mach/mach_error.h> -#include <mach/mach_traps.h> -#include <mach/mach.h> -#include <mach/host_special_ports.h> - -#include "auditd_control_server.h" -#include "audit_triggers_server.h" -#endif /* USE_MACH_IPC */ #ifndef HAVE_STRLCPY #include <compat/strlcpy.h> #endif -#define NA_EVENT_STR_SIZE 25 -#define POL_STR_SIZE 128 -static int ret, minval; -static char *lastfile = NULL; -static int allhardcount = 0; -static int sigchlds, sigchlds_handled; -static int sighups, sighups_handled; -#ifndef USE_MACH_IPC -static int sigterms, sigterms_handled; -static int triggerfd = 0; - -#else /* USE_MACH_IPC */ - -static mach_port_t control_port = MACH_PORT_NULL; -static mach_port_t signal_port = MACH_PORT_NULL; -static mach_port_t port_set = MACH_PORT_NULL; - -#ifndef __BSM_INTERNAL_NOTIFY_KEY -#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" -#endif /* __BSM_INTERNAL_NOTIFY_KEY */ -#endif /* USE_MACH_IPC */ - -static TAILQ_HEAD(, dir_ent) dir_q; - -static int config_audit_controls(void); - /* - * Error starting auditd + * XXX the following is temporary until this can be added to the kernel + * audit.h header. */ -static void -fail_exit(void) -{ +#ifndef AUDIT_TRIGGER_INITIALIZE +#define AUDIT_TRIGGER_INITIALIZE 7 +#endif - audit_warn_nostart(); - exit(1); -} +/* + * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and + * http://wiki.freebsd.org/launchd for more information. + * + * In order for auditd to work "on demand" with launchd(8) it can't: + * call daemon(3) + * call fork and having the parent process exit + * change uids or gids. + * set up the current working directory or chroot. + * set the session id + * change stdio to /dev/null. + * call setrusage(2) + * call setpriority(2) + * Ignore SIGTERM. + * auditd (in 'launchd mode') is launched on demand so it must catch + * SIGTERM to exit cleanly. + */ +static int launchd_flag = 0; /* - * Free our local list of directory names. + * The GID of the audit review group (if used). The audit trail files and + * system logs (Mac OS X only) can only be reviewed by members of this group + * or the audit administrator (aka. "root"). */ -static void -free_dir_q(void) -{ - struct dir_ent *dirent; +static gid_t audit_review_gid = -1; - while ((dirent = TAILQ_FIRST(&dir_q))) { - TAILQ_REMOVE(&dir_q, dirent, dirs); - free(dirent->dirname); - free(dirent); - } -} +/* + * The path and file name of the last audit trail file. + */ +static char *lastfile = NULL; /* - * Generate the timestamp string. + * Error starting auditd. Run warn script and exit. */ -static int -getTSstr(char *buf, int len) +static void +fail_exit(void) { - struct timeval ts; - struct timezone tzp; - time_t tt; - if (gettimeofday(&ts, &tzp) != 0) - return (-1); - tt = (time_t)ts.tv_sec; - if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt))) - return (-1); - return (0); + audit_warn_nostart(); + exit(1); } /* - * Concat the directory name to the given file name. - * XXX We should affix the hostname also + * Follow the 'current' symlink to get the active trail file name. */ static char * -affixdir(char *name, struct dir_ent *dirent) +get_curfile(void) { - char *fn = NULL; + char *cf; + int len; - syslog(LOG_DEBUG, "dir = %s", dirent->dirname); - /* - * Sanity check on file name. - */ - if (strlen(name) != (FILENAME_LEN - 1)) { - syslog(LOG_ERR, "Invalid file name: %s", name); + cf = malloc(MAXPATHLEN); + if (cf == NULL) { + auditd_log_err("malloc failed: %m"); + return (NULL); + } + + len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); + if (len < 0) { + free(cf); return (NULL); } - asprintf(&fn, "%s/%s", dirent->dirname, name); - return (fn); + + /* readlink() doesn't terminate string. */ + cf[len] = '\0'; + + return (cf); } /* @@ -181,6 +153,10 @@ close_lastfile(char *TS) char *oldname; size_t len; + /* If lastfile is NULL try to get it from the 'current' link. */ + if (lastfile == NULL) + lastfile = get_curfile(); + if (lastfile != NULL) { len = strlen(lastfile) + 1; oldname = (char *)malloc(len); @@ -192,16 +168,21 @@ close_lastfile(char *TS) if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { strlcpy(ptr, TS, TIMESTAMP_LEN); if (rename(oldname, lastfile) != 0) - syslog(LOG_ERR, + auditd_log_err( "Could not rename %s to %s: %m", oldname, lastfile); else { - syslog(LOG_INFO, "renamed %s to %s", + /* + * Remove the 'current' symlink since the link + * is now invalid. + */ + (void) unlink(AUDIT_CURRENT_LINK); + auditd_log_notice( "renamed %s to %s", oldname, lastfile); audit_warn_closefile(lastfile); } } else - syslog(LOG_ERR, "Could not rename %s to %s", oldname, + auditd_log_err( "Could not rename %s to %s", oldname, lastfile); free(lastfile); free(oldname); @@ -211,168 +192,81 @@ close_lastfile(char *TS) } /* - * Create the new audit file with appropriate permissions and ownership. Try - * to clean up if something goes wrong. - */ -static int -#ifdef AUDIT_REVIEW_GROUP -open_trail(const char *fname, uid_t uid, gid_t gid) -#else -open_trail(const char *fname) -#endif -{ - int error, fd; - - fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP); - if (fd < 0) - return (-1); -#ifdef AUDIT_REVIEW_GROUP - if (fchown(fd, uid, gid) < 0) { - error = errno; - close(fd); - (void)unlink(fname); - errno = error; - return (-1); - } -#endif - return (fd); -} - -/* * Create the new file name, swap with existing audit file. */ static int swap_audit_file(void) { - char timestr[FILENAME_LEN]; - char *fn; + int err; + char *newfile; char TS[TIMESTAMP_LEN]; - struct dir_ent *dirent; -#ifdef AUDIT_REVIEW_GROUP - struct group *grp; - gid_t gid; - uid_t uid; -#endif - int error, fd; + time_t tt; - if (getTSstr(TS, TIMESTAMP_LEN) != 0) + if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) return (-1); + err = auditd_swap_trail(TS, &newfile, audit_review_gid, + audit_warn_getacdir); + if (err != ADE_NOERR) { + auditd_log_err( "%s: %m", auditd_strerror(err)); + if (err != ADE_ACTL) + return (-1); + } - snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED); - -#ifdef AUDIT_REVIEW_GROUP /* - * XXXRW: Currently, this code falls back to the daemon gid, which is - * likely the wheel group. Is there a better way to deal with this? + * Only close the last file if were in an auditing state before + * calling swap_audit_file(). We may need to recover from a crash. */ - grp = getgrnam(AUDIT_REVIEW_GROUP); - if (grp == NULL) { - syslog(LOG_INFO, - "Audit review group '%s' not available, using daemon gid", - AUDIT_REVIEW_GROUP); - gid = -1; - } else - gid = grp->gr_gid; - uid = getuid(); -#endif + if (auditd_get_state() == AUD_STATE_ENABLED) + close_lastfile(TS); - /* Try until we succeed. */ - while ((dirent = TAILQ_FIRST(&dir_q))) { - if ((fn = affixdir(timestr, dirent)) == NULL) { - syslog(LOG_INFO, "Failed to swap log at time %s", - timestr); - return (-1); - } - /* - * Create and open the file; then close and pass to the - * kernel if all went well. - */ - syslog(LOG_INFO, "New audit file is %s", fn); -#ifdef AUDIT_REVIEW_GROUP - fd = open_trail(fn, uid, gid); -#else - fd = open_trail(fn); -#endif - if (fd < 0) - warn("open(%s)", fn); - if (fd >= 0) { - error = auditctl(fn); - if (error) { - syslog(LOG_ERR, - "auditctl failed setting log file! : %s", - strerror(errno)); - close(fd); - } else { - /* Success. */ -#ifdef USE_MACH_IPC - /* - * auditctl() potentially changes the audit - * state so post that the audit config (may - * have) changed. - */ - notify_post(__BSM_INTERNAL_NOTIFY_KEY); -#endif - close_lastfile(TS); - lastfile = fn; - close(fd); - return (0); - } - } + /* + * auditd_swap_trail() potentially enables auditing (if not already + * enabled) so updated the cached state as well. + */ + auditd_set_state(AUD_STATE_ENABLED); + + /* + * Create 'current' symlink. Recover from crash, if needed. + */ + if (auditd_new_curlink(newfile) != 0) + auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", + newfile, auditd_strerror(err)); - /* - * Tell the administrator about lack of permissions for dir. - */ - audit_warn_getacdir(dirent->dirname); + lastfile = newfile; + auditd_log_notice("New audit file is %s", newfile); - /* Try again with a different directory. */ - TAILQ_REMOVE(&dir_q, dirent, dirs); - free(dirent->dirname); - free(dirent); - } - syslog(LOG_ERR, "Log directories exhausted"); - return (-1); + return (0); } /* - * Read the audit_control file contents. + * Create a new audit log trail file and swap with the current one, if any. */ static int -read_control_file(void) +do_trail_file(void) { - char cur_dir[MAXNAMLEN]; - struct dir_ent *dirent; - au_qctrl_t qctrl; + int err; /* - * Clear old values. Force a re-read of the file the next time. + * First, refresh the list of audit log directories. */ - free_dir_q(); - endac(); - - /* - * Read the list of directories into a local linked list. - * - * XXX We should use the reentrant interfaces once they are - * available. - */ - while (getacdir(cur_dir, MAXNAMLEN) >= 0) { - dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); - if (dirent == NULL) - return (-1); - dirent->softlim = 0; - dirent->dirname = (char *) malloc(MAXNAMLEN); - if (dirent->dirname == NULL) { - free(dirent); + err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); + if (err) { + auditd_log_err("auditd_read_dirs() %s: %m", + auditd_strerror(err)); + if (err == ADE_HARDLIM) + audit_warn_allhard(); + if (err != ADE_SOFTLIM) return (-1); - } - strlcpy(dirent->dirname, cur_dir, MAXNAMLEN); - TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); + else + audit_warn_allsoft(); + /* continue on with soft limit error */ } - allhardcount = 0; + /* + * Create a new file and swap with the one being used in kernel. + */ if (swap_audit_file() == -1) { - syslog(LOG_ERR, "Could not swap audit file"); /* * XXX Faulty directory listing? - user should be given * XXX an opportunity to change the audit_control file @@ -381,26 +275,54 @@ read_control_file(void) return (-1); } - /* - * XXX There are synchronization problems here - * XXX what should we do if a trigger for the earlier limit - * XXX is generated here? - */ - if (0 == (ret = getacmin(&minval))) { - syslog(LOG_DEBUG, "min free = %d", minval); - if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { - syslog(LOG_ERR, - "could not get audit queue settings"); - return (-1); - } - qctrl.aq_minfree = minval; - if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { - syslog(LOG_ERR, - "could not set audit queue settings"); - return (-1); - } + return (0); +} + +/* + * Start up auditing. + */ +static void +audit_setup(void) +{ + int err; + + if (do_trail_file() == -1) { + auditd_log_err("Error creating audit trail file"); + fail_exit(); + } + + /* Generate an audit record. */ + err = auditd_gen_record(AUE_audit_startup, NULL); + if (err) + auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", + auditd_strerror(err)); + + if (auditd_config_controls() == 0) + auditd_log_info("Audit controls init successful"); + else + auditd_log_err("Audit controls init failed"); + +} + + +/* + * Close auditd pid file and trigger mechanism. + */ +static int +close_misc(void) +{ + + auditd_close_dirs(); + if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { + auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); + return (1); } + endac(); + if (auditd_close_trigger() != 0) { + auditd_log_err("Error closing trigger messaging mechanism"); + return (1); + } return (0); } @@ -410,107 +332,48 @@ read_control_file(void) static int close_all(void) { - struct auditinfo ai; int err_ret = 0; char TS[TIMESTAMP_LEN]; - int aufd; - token_t *tok; + int err; long cond; + time_t tt; - /* Generate an audit record. */ - if ((aufd = au_open()) == -1) - syslog(LOG_ERR, "Could not create audit shutdown event."); - else { - if ((tok = au_to_text("auditd::Audit shutdown")) != NULL) - au_write(aufd, tok); - /* - * XXX we need to implement extended subject tokens so we can - * effectively represent terminal lines with this token type. - */ - bzero(&ai, sizeof(ai)); - if ((tok = au_to_subject32(getuid(), geteuid(), getegid(), - getuid(), getgid(), getpid(), getpid(), &ai.ai_termid)) - != NULL) - au_write(aufd, tok); - if ((tok = au_to_return32(0, 0)) != NULL) - au_write(aufd, tok); - if (au_close(aufd, 1, AUE_audit_shutdown) == -1) - syslog(LOG_ERR, - "Could not close audit shutdown event."); - } + err = auditd_gen_record(AUE_audit_shutdown, NULL); + if (err) + auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", + auditd_strerror(err)); /* Flush contents. */ cond = AUC_DISABLED; err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); if (err_ret != 0) { - syslog(LOG_ERR, "Disabling audit failed! : %s", - strerror(errno)); + auditd_log_err("Disabling audit failed! : %s", strerror(errno)); err_ret = 1; } -#ifdef USE_MACH_IPC - /* - * Post a notification that the audit config changed. + + /* + * Updated the cached state that auditing has been disabled. */ - notify_post(__BSM_INTERNAL_NOTIFY_KEY); -#endif - if (getTSstr(TS, TIMESTAMP_LEN) == 0) + auditd_set_state(AUD_STATE_DISABLED); + + if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0) close_lastfile(TS); if (lastfile != NULL) free(lastfile); - free_dir_q(); - if ((remove(AUDITD_PIDFILE) == -1) || err_ret) { - syslog(LOG_ERR, "Could not unregister"); + err_ret += close_misc(); + + if (err_ret) { + auditd_log_err("Could not unregister"); audit_warn_postsigterm(); - return (1); } - endac(); - -#ifndef USE_MACH_IPC - if (close(triggerfd) != 0) - syslog(LOG_ERR, "Error closing control file"); -#endif - syslog(LOG_INFO, "Finished"); - return (0); -} -/* - * When we get a signal, we are often not at a clean point. So, little can - * be done in the signal handler itself. Instead, we send a message to the - * main servicing loop to do proper handling from a non-signal-handler - * context. - */ -#ifdef USE_MACH_IPC -static void -relay_signal(int signal) -{ - mach_msg_empty_send_t msg; - - msg.header.msgh_id = signal; - msg.header.msgh_remote_port = signal_port; - msg.header.msgh_local_port = MACH_PORT_NULL; - msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); - mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), - 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + auditd_log_info("Finished"); + return (err_ret); } -#else /* ! USE_MACH_IPC */ - -static void -relay_signal(int signal) -{ - - if (signal == SIGHUP) - sighups++; - if (signal == SIGTERM) - sigterms++; - if (signal == SIGCHLD) - sigchlds++; -} -#endif /* ! USE_MACH_IPC */ - /* - * Registering the daemon. + * Register the daemon with the signal handler and the auditd pid file. */ static int register_daemon(void) @@ -520,24 +383,29 @@ register_daemon(void) pid_t pid; /* Set up the signal hander. */ - if (signal(SIGTERM, relay_signal) == SIG_ERR) { - syslog(LOG_ERR, + if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( "Could not set signal handler for SIGTERM"); fail_exit(); } - if (signal(SIGCHLD, relay_signal) == SIG_ERR) { - syslog(LOG_ERR, + if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( "Could not set signal handler for SIGCHLD"); fail_exit(); } - if (signal(SIGHUP, relay_signal) == SIG_ERR) { - syslog(LOG_ERR, + if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( "Could not set signal handler for SIGHUP"); fail_exit(); } + if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( + "Could not set signal handler for SIGALRM"); + fail_exit(); + } if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { - syslog(LOG_ERR, "Could not open PID file"); + auditd_log_err("Could not open PID file"); audit_warn_tmpfile(); return (-1); } @@ -545,7 +413,7 @@ register_daemon(void) /* Attempt to lock the pid file; if a lock is present, exit. */ fd = fileno(pidfile); if (flock(fd, LOCK_EX | LOCK_NB) < 0) { - syslog(LOG_ERR, + auditd_log_err( "PID file is locked (is another auditd running?)."); audit_warn_ebusy(); return (-1); @@ -562,48 +430,6 @@ register_daemon(void) return (0); } -#ifdef USE_MACH_IPC -/* - * Implementation of the auditd_control() MIG simpleroutine. - * - * React to input from the audit(1) tool. - */ - -/* ARGSUSED */ -kern_return_t -auditd_control(mach_port_t __unused auditd_port, int trigger) -{ - int err_ret = 0; - - switch (trigger) { - - case AUDIT_TRIGGER_ROTATE_USER: - /* - * Create a new file and swap with the one - * being used in kernel. - */ - if (swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file"); - break; - - case AUDIT_TRIGGER_READ_FILE: - if (read_control_file() == -1) - syslog(LOG_ERR, "Error in audit control file"); - break; - - case AUDIT_TRIGGER_CLOSE_AND_DIE: - err_ret = close_all(); - exit (err_ret); - break; - - default: - break; - } - - return (KERN_SUCCESS); -} -#endif /* USE_MACH_IPC */ - /* * Handle the audit trigger event. * @@ -615,25 +441,16 @@ auditd_control(mach_port_t __unused auditd_port, int trigger) * not be retransmitted, and the log file will grow in an unbounded fashion. */ #define DUPLICATE_INTERVAL 30 -#ifdef USE_MACH_IPC -#define AT_SUCCESS KERN_SUCCESS - -/* ARGSUSED */ -kern_return_t -audit_triggers(mach_port_t __unused audit_port, int trigger) -#else -#define AT_SUCCESS 0 - -static int -handle_audit_trigger(int trigger) -#endif +void +auditd_handle_trigger(int trigger) { static int last_trigger, last_warning; static time_t last_time; - struct dir_ent *dirent; struct timeval ts; struct timezone tzp; time_t tt; + int au_state; + int err = 0; /* * Suppress duplicate messages from the kernel within the specified @@ -652,10 +469,10 @@ handle_audit_trigger(int trigger) if ((trigger == last_trigger) && (tt < (last_time + DUPLICATE_INTERVAL))) { if (tt >= (last_warning + DUPLICATE_INTERVAL)) - syslog(LOG_INFO, + auditd_log_info( "Suppressing duplicate trigger %d", trigger); - return (AT_SUCCESS); + return; } last_warning = tt; break; @@ -663,6 +480,8 @@ handle_audit_trigger(int trigger) case AUDIT_TRIGGER_ROTATE_KERNEL: case AUDIT_TRIGGER_ROTATE_USER: case AUDIT_TRIGGER_READ_FILE: + case AUDIT_TRIGGER_CLOSE_AND_DIE: + case AUDIT_TRIGGER_INITIALIZE: /* * Triggers that we cannot suppress. */ @@ -678,166 +497,70 @@ handle_audit_trigger(int trigger) last_time = tt; } + au_state = auditd_get_state(); + /* * Message processing is done here. */ - dirent = TAILQ_FIRST(&dir_q); switch(trigger) { case AUDIT_TRIGGER_LOW_SPACE: - syslog(LOG_INFO, "Got low space trigger"); - if (dirent && (dirent->softlim != 1)) { - TAILQ_REMOVE(&dir_q, dirent, dirs); - /* Add this node to the end of the list. */ - TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); - audit_warn_soft(dirent->dirname); - dirent->softlim = 1; - - if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && - swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file"); - - /* - * Check if the next dir has already reached its soft - * limit. - */ - dirent = TAILQ_FIRST(&dir_q); - if (dirent->softlim == 1) { - /* All dirs have reached their soft limit. */ - audit_warn_allsoft(); - } - } else { - /* - * Continue auditing to the current file. Also - * generate an allsoft warning. - * - * XXX do we want to do this ? - */ - audit_warn_allsoft(); - } + auditd_log_notice("Got low space trigger"); + if (do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_NO_SPACE: - syslog(LOG_INFO, "Got no space trigger"); - - /* Delete current dir, go on to next. */ - TAILQ_REMOVE(&dir_q, dirent, dirs); - audit_warn_hard(dirent->dirname); - free(dirent->dirname); - free(dirent); - - if (swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file"); - - /* We are out of log directories. */ - audit_warn_allhard(++allhardcount); + auditd_log_notice("Got no space trigger"); + if (do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_ROTATE_KERNEL: case AUDIT_TRIGGER_ROTATE_USER: - /* - * Create a new file and swap with the one being used in - * kernel - */ - syslog(LOG_INFO, "Got open new trigger from %s", trigger == + auditd_log_info("Got open new trigger from %s", trigger == AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); - if (swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file"); + if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_READ_FILE: - syslog(LOG_INFO, "Got read file trigger"); - if (read_control_file() == -1) - syslog(LOG_ERR, "Error in audit control file"); - if (config_audit_controls() == -1) - syslog(LOG_ERR, "Error setting audit controls"); + auditd_log_info("Got read file trigger"); + if (au_state == AUD_STATE_ENABLED && + auditd_config_controls() == -1) + auditd_log_err("Error setting audit controls"); break; - default: - syslog(LOG_ERR, "Got unknown trigger %d", trigger); - break; - } - - return (AT_SUCCESS); -} - -#undef AT_SUCCESS - -static void -handle_sighup(void) -{ - - sighups_handled = sighups; - config_audit_controls(); -} - -static int -config_audit_host(void) -{ - char hoststr[MAXHOSTNAMELEN]; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - struct addrinfo *res; - struct auditinfo_addr aia; - int error; - - if (getachost(hoststr, MAXHOSTNAMELEN) != 0) { - syslog(LOG_WARNING, - "warning: failed to read 'host' param in control file"); + case AUDIT_TRIGGER_CLOSE_AND_DIE: + auditd_log_info("Got close and die trigger"); + if (au_state == AUD_STATE_ENABLED) + err = close_all(); /* - * To maintain reverse compatability with older audit_control - * files, simply drop a warning if the host parameter has not - * been set. However, we will explicitly disable the - * generation of extended audit header by passing in a zeroed - * termid structure. + * Running under launchd don't exit. Wait for launchd to + * send SIGTERM. */ - bzero(&aia, sizeof(aia)); - aia.ai_termid.at_type = AU_IPv4; - error = auditon(A_SETKAUDIT, &aia, sizeof(aia)); - if (error < 0 && errno == ENOSYS) - return (0); - else if (error < 0) { - syslog(LOG_ERR, - "Failed to set audit host info"); - return (-1); + if (!launchd_flag) { + auditd_log_info("auditd exiting."); + exit (err); } - return (0); - } - error = getaddrinfo(hoststr, NULL, NULL, &res); - if (error) { - syslog(LOG_ERR, "Failed to lookup hostname: %s", hoststr); - return (-1); - } - switch (res->ai_family) { - case PF_INET6: - sin6 = (struct sockaddr_in6 *) res->ai_addr; - bcopy(&sin6->sin6_addr.s6_addr, - &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); - aia.ai_termid.at_type = AU_IPv6; break; - case PF_INET: - sin = (struct sockaddr_in *) res->ai_addr; - bcopy(&sin->sin_addr.s_addr, - &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); - aia.ai_termid.at_type = AU_IPv4; + + case AUDIT_TRIGGER_INITIALIZE: + auditd_log_info("Got audit initialize trigger"); + if (au_state == AUD_STATE_DISABLED) + audit_setup(); break; + default: - syslog(LOG_ERR, - "Un-supported address family in host parameter"); - return (-1); - } - if (auditon(A_SETKAUDIT, &aia, sizeof(aia)) < 0) { - syslog(LOG_ERR, - "auditon: failed to set audit host information"); - return (-1); + auditd_log_err("Got unknown trigger %d", trigger); + break; } - return (0); } /* * Reap our children. */ -static void -reap_children(void) +void +auditd_reap_children(void) { pid_t child; int wstatus; @@ -845,7 +568,7 @@ reap_children(void) while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { if (!wstatus) continue; - syslog(LOG_INFO, "warn process [pid=%d] %s %d.", child, + auditd_log_info("warn process [pid=%d] %s %d.", child, ((WIFEXITED(wstatus)) ? "exited with non-zero status" : "exited as a result of signal"), ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : @@ -853,287 +576,121 @@ reap_children(void) } } -static void -handle_sigchld(void) -{ - - sigchlds_handled = sigchlds; - reap_children(); -} - /* - * Read the control file for triggers/signals and handle appropriately. + * Reap any children and terminate. If under launchd don't shutdown auditing + * but just the other stuff. */ -#ifdef USE_MACH_IPC -#define MAX_MSG_SIZE 4096 - -static boolean_t -auditd_combined_server(mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP) -{ - mach_port_t local_port = InHeadP->msgh_local_port; - - if (local_port == signal_port) { - int signo = InHeadP->msgh_id; - int ret; - - switch(signo) { - case SIGTERM: - ret = close_all(); - exit(ret); - - case SIGCHLD: - handle_sigchld(); - return (TRUE); - - case SIGHUP: - handle_sighup(); - return (TRUE); - - default: - syslog(LOG_INFO, "Received signal %d", signo); - return (TRUE); - } - } else if (local_port == control_port) { - boolean_t result; - - result = audit_triggers_server(InHeadP, OutHeadP); - if (!result) - result = auditd_control_server(InHeadP, OutHeadP); - return (result); - } - syslog(LOG_INFO, "Recevied msg on bad port 0x%x.", local_port); - return (FALSE); -} - -static int -wait_for_events(void) +void +auditd_terminate(void) { - kern_return_t result; + int ret; - result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, - port_set, MACH_MSG_OPTION_NONE); - syslog(LOG_ERR, "abnormal exit\n"); - return (close_all()); -} - -#else /* ! USE_MACH_IPC */ - -static int -wait_for_events(void) -{ - int num; - unsigned int trigger; + auditd_reap_children(); + + if (launchd_flag) + ret = close_misc(); + else + ret = close_all(); - for (;;) { - num = read(triggerfd, &trigger, sizeof(trigger)); - if ((num == -1) && (errno != EINTR)) { - syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno); - return (-1); - } - if (sigterms != sigterms_handled) { - syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__); - break; - } - if (sigchlds != sigchlds_handled) - handle_sigchld(); - if (sighups != sighups_handled) { - syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__); - handle_sighup(); - } - if ((num == -1) && (errno == EINTR)) - continue; - if (num == 0) { - syslog(LOG_ERR, "%s: read EOF", __FUNCTION__); - return (-1); - } - if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE) - break; - else - (void)handle_audit_trigger(trigger); - } - return (close_all()); + exit(ret); } -#endif /* ! USE_MACH_IPC */ /* * Configure the audit controls in the kernel: the event to class mapping, * kernel preselection mask, etc. */ -static int -config_audit_controls(void) +int +auditd_config_controls(void) { - au_event_ent_t ev, *evp; - au_evclass_map_t evc_map; - au_mask_t aumask; - int ctr = 0; - char naeventstr[NA_EVENT_STR_SIZE]; - char polstr[POL_STR_SIZE]; - long policy; - au_fstat_t au_fstat; - size_t filesz; - - /* - * Process the audit event file, obtaining a class mapping for each - * event, and send that mapping into the kernel. - * - * XXX There's a risk here that the BSM library will return NULL - * for an event when it can't properly map it to a class. In that - * case, we will not process any events beyond the one that failed, - * but should. We need a way to get a count of the events. - */ - ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); - ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); - if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) { - if (ev.ae_name != NULL) - free(ev.ae_name); - syslog(LOG_ERR, - "Memory allocation error when configuring audit controls."); - return (-1); - } + int cnt, err; + int ret = 0; /* - * XXXRW: Currently we have no way to remove mappings from the kernel - * when they are removed from the file-based mappings. - */ - evp = &ev; - setauevent(); - while ((evp = getauevent_r(evp)) != NULL) { - evc_map.ec_number = evp->ae_number; - evc_map.ec_class = evp->ae_class; - if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) - != 0) - syslog(LOG_ERR, - "Failed to register class mapping for event %s", - evp->ae_name); - else - ctr++; - } - endauevent(); - free(ev.ae_name); - free(ev.ae_desc); - if (ctr == 0) - syslog(LOG_ERR, "No events to class mappings registered."); - else - syslog(LOG_DEBUG, "Registered %d event to class mappings.", - ctr); - - /* - * Get the non-attributable event string and set the kernel mask from - * that. - */ - if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) && - (getauditflagsbin(naeventstr, &aumask) == 0)) { - if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))) - syslog(LOG_ERR, - "Failed to register non-attributable event mask."); - else - syslog(LOG_DEBUG, - "Registered non-attributable event mask."); + * Configure event to class mappings in kernel. + */ + cnt = auditd_set_evcmap(); + if (cnt < 0) { + auditd_log_err("auditd_set_evcmap() failed: %m"); + ret = -1; + } else if (cnt == 0) { + auditd_log_err("No events to class mappings registered."); + ret = -1; } else - syslog(LOG_ERR, - "Failed to obtain non-attributable event mask."); + auditd_log_debug("Registered %d event to class mappings.", cnt); /* - * If a policy is configured in audit_control(5), implement the - * policy. However, if one isn't defined, set AUDIT_CNT to avoid - * leaving the system in a fragile state. + * Configure non-attributable event mask in kernel. */ - if ((getacpol(polstr, POL_STR_SIZE) == 0) && - (au_strtopol(polstr, &policy) == 0)) { - if (auditon(A_SETPOLICY, &policy, sizeof(policy))) - syslog(LOG_ERR, "Failed to set audit policy: %m"); - } else { - syslog(LOG_ERR, "Failed to obtain policy flags: %m"); - policy = AUDIT_CNT; - if (auditon(A_SETPOLICY, &policy, sizeof(policy))) - syslog(LOG_ERR, - "Failed to set default audit policy: %m"); - } + err = auditd_set_namask(); + if (err) { + auditd_log_err("auditd_set_namask() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug("Registered non-attributable event mask."); /* - * Set trail rotation size. + * Configure audit policy in kernel. */ - if (getacfilesz(&filesz) == 0) { - bzero(&au_fstat, sizeof(au_fstat)); - au_fstat.af_filesz = filesz; - if (auditon(A_SETFSIZE, &au_fstat, sizeof(au_fstat)) < 0) - syslog(LOG_ERR, "Failed to set filesz: %m"); + err = auditd_set_policy(); + if (err) { + auditd_log_err("auditd_set_policy() %s: %m", + auditd_strerror(err)); + ret = -1; } else - syslog(LOG_ERR, "Failed to obtain filesz: %m"); - - return (config_audit_host()); -} - -#ifdef USE_MACH_IPC -static void -mach_setup(void) -{ - mach_msg_type_name_t poly; - + auditd_log_debug("Set audit policy in kernel."); + /* - * Allocate a port set + * Configure audit trail log size in kernel. */ - if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, - &port_set) != KERN_SUCCESS) { - syslog(LOG_ERR, "Allocation of port set failed"); - fail_exit(); - } - + err = auditd_set_fsize(); + if (err) { + auditd_log_err("audit_set_fsize() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug("Set audit trail size in kernel."); + /* - * Allocate a signal reflection port + * Configure audit trail volume minimum free percentage of blocks in + * kernel. */ - if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, - &signal_port) != KERN_SUCCESS || - mach_port_move_member(mach_task_self(), signal_port, port_set) != - KERN_SUCCESS) { - syslog(LOG_ERR, "Allocation of signal port failed"); - fail_exit(); - } + err = auditd_set_minfree(); + if (err) { + auditd_log_err("auditd_set_minfree() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug( + "Set audit trail min free percent in kernel."); /* - * Allocate a trigger port - */ - if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, - &control_port) != KERN_SUCCESS || - mach_port_move_member(mach_task_self(), control_port, port_set) - != KERN_SUCCESS) - syslog(LOG_ERR, "Allocation of trigger port failed"); - - /* - * Create a send right on our trigger port. + * Configure host address in the audit kernel information. */ - mach_port_extract_right(mach_task_self(), control_port, - MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); - - /* - * Register the trigger port with the kernel. - */ - if (host_set_audit_control_port(mach_host_self(), control_port) != - KERN_SUCCESS) { - syslog(LOG_ERR, "Cannot set Mach control port"); - fail_exit(); + err = auditd_set_host(); + if (err) { + auditd_log_err("auditd_set_host() %s: %m", + auditd_strerror(err)); + ret = -1; } else - syslog(LOG_DEBUG, "Mach control port registered"); + auditd_log_debug( + "Set audit host address information in kernel."); + + return (ret); } -#endif /* USE_MACH_IPC */ +/* + * Setup and initialize auditd. + */ static void setup(void) { - struct auditinfo ai; - auditinfo_t auinfo; - int aufd; - token_t *tok; + int err; -#ifdef USE_MACH_IPC - mach_setup(); -#else - if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) { - syslog(LOG_ERR, "Error opening trigger file"); + if (auditd_open_trigger(launchd_flag) < 0) { + auditd_log_err("Error opening trigger messaging mechanism"); fail_exit(); } -#endif /* * To prevent event feedback cycles and avoid auditd becoming @@ -1142,49 +699,25 @@ setup(void) * mask fields to be implicitly set to zero, but do set the pid. We * run this after opening the trigger device to avoid configuring * audit state without audit present in the system. - * - * XXXRW: Is there more to it than this? */ - bzero(&auinfo, sizeof(auinfo)); - auinfo.ai_asid = getpid(); - if (setaudit(&auinfo) == -1) { - syslog(LOG_ERR, "Error setting audit stat"); + err = auditd_prevent_audit(); + if (err) { + auditd_log_err("auditd_prevent_audit() %s: %m", + auditd_strerror(err)); fail_exit(); } - TAILQ_INIT(&dir_q); - if (read_control_file() == -1) { - syslog(LOG_ERR, "Error reading control file"); - fail_exit(); - } - - /* Generate an audit record. */ - if ((aufd = au_open()) == -1) - syslog(LOG_ERR, "Could not create audit startup event."); - else { - /* - * XXXCSJP Perhaps we want more robust audit records for - * audit start up and shutdown. This might include capturing - * failures to initialize the audit subsystem? - */ - bzero(&ai, sizeof(ai)); - if ((tok = au_to_subject32(getuid(), geteuid(), getegid(), - getuid(), getgid(), getpid(), getpid(), &ai.ai_termid)) - != NULL) - au_write(aufd, tok); - if ((tok = au_to_text("auditd::Audit startup")) != NULL) - au_write(aufd, tok); - if ((tok = au_to_return32(0, 0)) != NULL) - au_write(aufd, tok); - if (au_close(aufd, 1, AUE_audit_startup) == -1) - syslog(LOG_ERR, - "Could not close audit startup event."); - } + /* + * Make sure auditd auditing state is correct. + */ + auditd_set_state(AUD_STATE_INIT); - if (config_audit_controls() == 0) - syslog(LOG_INFO, "Audit controls init successful"); - else - syslog(LOG_ERR, "Audit controls init failed"); + /* + * If under launchd, don't start auditing. Wait for a trigger to + * do so. + */ + if (!launchd_flag) + audit_setup(); } int @@ -1192,48 +725,73 @@ main(int argc, char **argv) { int ch; int debug = 0; - int rc, logopts; +#ifdef AUDIT_REVIEW_GROUP + struct group *grp; +#endif - while ((ch = getopt(argc, argv, "d")) != -1) { + while ((ch = getopt(argc, argv, "dl")) != -1) { switch(ch) { case 'd': /* Debug option. */ debug = 1; break; + case 'l': + /* Be launchd friendly. */ + launchd_flag = 1; + break; + case '?': default: (void)fprintf(stderr, - "usage: auditd [-d] \n"); + "usage: auditd [-d] [-l]\n"); exit(1); } } - logopts = LOG_CONS | LOG_PID; - if (debug != 0) - logopts |= LOG_PERROR; + audit_review_gid = getgid(); -#ifdef LOG_SECURITY - openlog("auditd", logopts, LOG_SECURITY); -#else - openlog("auditd", logopts, LOG_AUTH); +#ifdef AUDIT_REVIEW_GROUP + /* + * XXXRW: Currently, this code falls back to the daemon gid, which is + * likely the wheel group. Is there a better way to deal with this? + */ + grp = getgrnam(AUDIT_REVIEW_GROUP); + if (grp != NULL) + audit_review_gid = grp->gr_gid; #endif - syslog(LOG_INFO, "starting..."); - if (debug == 0 && daemon(0, 0) == -1) { - syslog(LOG_ERR, "Failed to daemonize"); + auditd_openlog(debug, audit_review_gid); + + if (launchd_flag) + auditd_log_info("started by launchd..."); + else + auditd_log_info("starting..."); + +#ifdef AUDIT_REVIEW_GROUP + if (grp == NULL) + auditd_log_info( + "Audit review group '%s' not available, using daemon gid (%d)", + AUDIT_REVIEW_GROUP, audit_review_gid); +#endif + if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { + auditd_log_err("Failed to daemonize"); exit(1); } if (register_daemon() == -1) { - syslog(LOG_ERR, "Could not register as daemon"); + auditd_log_err("Could not register as daemon"); exit(1); } setup(); - rc = wait_for_events(); - syslog(LOG_INFO, "auditd exiting."); + /* + * auditd_wait_for_events() shouldn't return unless something is wrong. + */ + auditd_wait_for_events(); - exit(rc); + auditd_log_err("abnormal exit."); + close_all(); + exit(-1); } diff --git a/contrib/openbsm/bin/auditd/auditd.h b/contrib/openbsm/bin/auditd/auditd.h index 688aea39400f6..0351a0ec1507b 100644 --- a/contrib/openbsm/bin/auditd/auditd.h +++ b/contrib/openbsm/bin/auditd/auditd.h @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.h#11 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.h#12 $ */ #ifndef _AUDITD_H_ @@ -46,17 +46,6 @@ */ #define AUDIT_REVIEW_GROUP "audit" -#define NOT_TERMINATED "not_terminated" -#define POSTFIX_LEN (sizeof("YYYYMMDDhhmmss") - 1) -#define FILENAME_LEN ((2 * POSTFIX_LEN) + 2) -#define TIMESTAMP_LEN (POSTFIX_LEN + 1) - -struct dir_ent { - char *dirname; - char softlim; - TAILQ_ENTRY(dir_ent) dirs; -}; - #define HARDLIM_ALL_WARN "allhard" #define SOFTLIM_ALL_WARN "allsoft" #define AUDITOFF_WARN "auditoff" @@ -72,7 +61,11 @@ struct dir_ent { #define AUDITWARN_SCRIPT "/etc/security/audit_warn" #define AUDITD_PIDFILE "/var/run/auditd.pid" -int audit_warn_allhard(int count); +#define AUD_STATE_INIT -1 +#define AUD_STATE_DISABLED 0 +#define AUD_STATE_ENABLED 1 + +int audit_warn_allhard(void); int audit_warn_allsoft(void); int audit_warn_auditoff(void); int audit_warn_closefile(char *filename); @@ -84,4 +77,24 @@ int audit_warn_postsigterm(void); int audit_warn_soft(char *filename); int audit_warn_tmpfile(void); +void auditd_openlog(int debug, gid_t gid); +void auditd_log_err(const char *fmt, ...); +void auditd_log_debug(const char *fmt, ...); +void auditd_log_info(const char *fmt, ...); +void auditd_log_notice(const char *fmt, ...); + +void auditd_set_state(int state); +int auditd_get_state(void); + +int auditd_open_trigger(int launchd_flag); +int auditd_close_trigger(void); +void auditd_handle_trigger(int trigger); + +void auditd_wait_for_events(void); +void auditd_relay_signal(int signal); +void auditd_terminate(void); +int auditd_config_controls(void); +void auditd_reap_children(void); + + #endif /* !_AUDITD_H_ */ diff --git a/contrib/openbsm/bin/auditd/auditd_darwin.c b/contrib/openbsm/bin/auditd/auditd_darwin.c new file mode 100644 index 0000000000000..55d79f4f155ad --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd_darwin.c @@ -0,0 +1,484 @@ +/*- + * Copyright (c) 2004-2008 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_darwin.c#2 $ + */ + +#include <sys/types.h> + +#include <config/config.h> + +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> + +#include <bsm/audit.h> +#include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> +#include <bsm/libbsm.h> + +#include <asl.h> +#include <launch.h> +#include <notify.h> +#include <mach/port.h> +#include <mach/mach_error.h> +#include <mach/mach_traps.h> +#include <mach/mach.h> +#include <mach/host_special_ports.h> + +#include "auditd.h" + +#include "auditd_controlServer.h" +#include "audit_triggersServer.h" + +/* + * Apple System Logger Handles. + */ +static aslmsg au_aslmsg = NULL; +static aslclient au_aslclient = NULL; + +static mach_port_t control_port = MACH_PORT_NULL; +static mach_port_t signal_port = MACH_PORT_NULL; +static mach_port_t port_set = MACH_PORT_NULL; + +/* + * Current auditing state (cache). + */ +static int auditing_state = AUD_STATE_INIT; + +/* + * Maximum idle time before auditd terminates under launchd. + * If it is zero then auditd does not timeout while idle. + */ +static int max_idletime = 0; + +#ifndef __BSM_INTERNAL_NOTIFY_KEY +#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" +#endif /* __BSM_INTERNAL_NOTIFY_KEY */ + +#ifndef __AUDIT_LAUNCHD_LABEL +#define __AUDIT_LAUNCHD_LABEL "org.trustedbsd.auditd" +#endif /* __AUDIT_LAUNCHD_LABEL */ + +#define MAX_MSG_SIZE 4096 + +/* + * Open and set up system logging. + */ +void +auditd_openlog(int debug, gid_t gid) +{ + uint32_t opt = 0; + char *cp = NULL; + + if (debug) + opt = ASL_OPT_STDERR; + + au_aslclient = asl_open("auditd", "org.trustedbsd.auditd", opt); + au_aslmsg = asl_new(ASL_TYPE_MSG); + +#ifdef ASL_KEY_READ_UID + /* + * Make it only so the audit administrator and members of the audit + * review group (if used) have access to the auditd system log messages. + */ + asl_set(au_aslmsg, ASL_KEY_READ_UID, "0"); + asprintf(&cp, "%u", gid); + if (cp != NULL) { +#ifdef ASL_KEY_READ_GID + asl_set(au_aslmsg, ASL_KEY_READ_GID, cp); +#endif + free(cp); + } +#endif + + /* + * Set the client-side system log filtering. + */ + if (debug) + asl_set_filter(au_aslclient, + ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); + else + asl_set_filter(au_aslclient, + ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO)); +} + +/* + * Log messages at different priority levels. + */ +void +auditd_log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_ERR, fmt, ap); + va_end(ap); +} + +void +auditd_log_notice(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_NOTICE, fmt, ap); + va_end(ap); +} + +void +auditd_log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_INFO, fmt, ap); + va_end(ap); +} + +void +auditd_log_debug(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_DEBUG, fmt, ap); + va_end(ap); +} + +/* + * Get the auditing state from the kernel and cache it. + */ +static void +init_audit_state(void) +{ + long au_cond; + + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno != ENOSYS) { + auditd_log_err("Audit status check failed (%s)", + strerror(errno)); + } + auditing_state = AUD_STATE_DISABLED; + } else + if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) + auditing_state = AUD_STATE_DISABLED; + else + auditing_state = AUD_STATE_ENABLED; +} + +/* + * Update the cached auditing state. Let other tasks that may be caching it + * as well to update their state via notify(3). + */ +void +auditd_set_state(int state) +{ + int old_auditing_state = auditing_state; + + if (state == AUD_STATE_INIT) + init_audit_state(); + else + auditing_state = state; + + if (auditing_state != old_auditing_state) { + notify_post(__BSM_INTERNAL_NOTIFY_KEY); + + if (auditing_state == AUD_STATE_ENABLED) + auditd_log_notice("Auditing enabled"); + if (auditing_state == AUD_STATE_DISABLED) + auditd_log_notice("Auditing disabled"); + } +} + +/* + * Get the cached auditing state. + */ +int +auditd_get_state(void) +{ + + if (auditing_state == AUD_STATE_INIT) { + init_audit_state(); + notify_post(__BSM_INTERNAL_NOTIFY_KEY); + } + + return (auditing_state); +} + +/* + * Lookup the audit mach port in the launchd dictionary. + */ +static mach_port_t +lookup_machport(const char *label) +{ + launch_data_t msg, msd, ld, cdict, to; + mach_port_t mp = MACH_PORT_NULL; + + msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); + + cdict = launch_msg(msg); + if (cdict == NULL) { + auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN + "\") IPC failure: %m"); + return (MACH_PORT_NULL); + } + + if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { + errno = launch_data_get_errno(cdict); + auditd_log_err("launch_data_get_type() can't get dict: %m"); + return (MACH_PORT_NULL); + } + + to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); + if (to) { + max_idletime = launch_data_get_integer(to); + auditd_log_debug("launchd timeout set to %d", max_idletime); + } else { + auditd_log_debug("launchd timeout not set, setting to 60"); + max_idletime = 60; + } + + msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); + if (msd == NULL) { + auditd_log_err( + "launch_data_dict_lookup() can't get mach services"); + return (MACH_PORT_NULL); + } + + ld = launch_data_dict_lookup(msd, label); + if (ld == NULL) { + auditd_log_err("launch_data_dict_lookup can't find %s", label); + return (MACH_PORT_NULL); + } + + mp = launch_data_get_machport(ld); + + return (mp); +} + +static int +mach_setup(int launchd_flag) +{ + mach_msg_type_name_t poly; + + /* + * Allocate a port set. + */ + if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, + &port_set) != KERN_SUCCESS) { + auditd_log_err("Allocation of port set failed"); + return (-1); + } + + + /* + * Allocate a signal reflection port. + */ + if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, + &signal_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), signal_port, port_set) != + KERN_SUCCESS) { + auditd_log_err("Allocation of signal port failed"); + return (-1); + } + + /* + * Allocate a trigger port. + */ + if (launchd_flag) { + /* + * If started under launchd, lookup port in launchd dictionary. + */ + if ((control_port = lookup_machport(__AUDIT_LAUNCHD_LABEL)) == + MACH_PORT_NULL || mach_port_move_member(mach_task_self(), + control_port, port_set) != KERN_SUCCESS) { + auditd_log_err("Cannot get Mach control port" + " via launchd"); + return (-1); + } else + auditd_log_debug("Mach control port registered" + " via launchd"); + } else { + /* + * If not started under launchd, allocate port and register. + */ + if (mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, &control_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), control_port, + port_set) != KERN_SUCCESS) + auditd_log_err("Allocation of trigger port failed"); + + /* + * Create a send right on our trigger port. + */ + mach_port_extract_right(mach_task_self(), control_port, + MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); + + /* + * Register the trigger port with the kernel. + */ + if (host_set_audit_control_port(mach_host_self(), + control_port) != KERN_SUCCESS) { + auditd_log_err("Cannot set Mach control port"); + return (-1); + } else + auditd_log_debug("Mach control port registered"); + } + + return (0); +} + +/* + * Open the trigger messaging mechanism. + */ +int +auditd_open_trigger(int launchd_flag) +{ + + return (mach_setup(launchd_flag)); +} + +/* + * Close the trigger messaging mechanism. + */ +int +auditd_close_trigger(void) +{ + + return (0); +} + +/* + * Combined server handler. Called by the mach message loop when there is + * a trigger or signal message. + */ +static boolean_t +auditd_combined_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + mach_port_t local_port = InHeadP->msgh_local_port; + + /* Reset the idle time alarm, if used. */ + if (max_idletime) + alarm(max_idletime); + + if (local_port == signal_port) { + int signo = InHeadP->msgh_id; + + switch(signo) { + case SIGTERM: + case SIGALRM: + auditd_terminate(); + /* Not reached. */ + + case SIGCHLD: + auditd_reap_children(); + return (TRUE); + + case SIGHUP: + auditd_config_controls(); + return (TRUE); + + default: + auditd_log_info("Received signal %d", signo); + return (TRUE); + } + } else if (local_port == control_port) { + boolean_t result; + + result = audit_triggers_server(InHeadP, OutHeadP); + if (!result) + result = auditd_control_server(InHeadP, OutHeadP); + return (result); + } + auditd_log_info("Recevied msg on bad port 0x%x.", local_port); + return (FALSE); +} + +/* + * The main event loop. Wait for trigger messages or signals and handle them. + * It should not return unless there is a problem. + */ +void +auditd_wait_for_events(void) +{ + kern_return_t result; + + /* + * Call the mach messaging server loop. + */ + result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, + port_set, MACH_MSG_OPTION_NONE); +} + +/* + * Implementation of the audit_triggers() MIG simpleroutine. Simply a + * wrapper function. This handles input from the kernel on the host + * special mach port. + */ +kern_return_t +audit_triggers(mach_port_t __unused audit_port, int trigger) +{ + + auditd_handle_trigger(trigger); + + return (KERN_SUCCESS); +} + +/* + * Implementation of the auditd_control() MIG simpleroutine. Simply a + * wrapper function. This handles input from the audit(1) tool. + */ +kern_return_t +auditd_control(mach_port_t __unused auditd_port, int trigger) +{ + + auditd_handle_trigger(trigger); + + return (KERN_SUCCESS); +} + +/* + * When we get a signal, we are often not at a clean point. So, little can + * be done in the signal handler itself. Instead, we send a message to the + * main servicing loop to do proper handling from a non-signal-handler + * context. + */ +void +auditd_relay_signal(int signal) +{ + mach_msg_empty_send_t msg; + + msg.header.msgh_id = signal; + msg.header.msgh_remote_port = signal_port; + msg.header.msgh_local_port = MACH_PORT_NULL; + msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); + mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), + 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); +} diff --git a/contrib/openbsm/bin/auditd/auditd_fbsd.c b/contrib/openbsm/bin/auditd/auditd_fbsd.c new file mode 100644 index 0000000000000..945e6d2b9e6e9 --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd_fbsd.c @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2004-2008 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_fbsd.c#1 $ + */ + +#include <sys/types.h> + +#include <config/config.h> + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <syslog.h> +#include <stdarg.h> + +#include <bsm/audit.h> +#include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> +#include <bsm/libbsm.h> + +#include "auditd.h" + +/* + * Current auditing state (cache). + */ +static int auditing_state = AUD_STATE_INIT; + +/* + * Maximum idle time before auditd terminates under launchd. + * If it is zero then auditd does not timeout while idle. + */ +static int max_idletime = 0; + +static int sigchlds, sigchlds_handled; +static int sighups, sighups_handled; +static int sigterms, sigterms_handled; +static int sigalrms, sigalrms_handled; + +static int triggerfd = 0; + +/* + * Open and set up system logging. + */ +void +auditd_openlog(int debug, gid_t __unused gid) +{ + int logopts = LOG_CONS | LOG_PID; + + if (debug) + logopts |= LOG_PERROR; + +#ifdef LOG_SECURITY + openlog("auditd", logopts, LOG_SECURITY); +#else + openlog("auditd", logopts, LOG_AUTH); +#endif +} + +/* + * Log messages at different priority levels. + */ +void +auditd_log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); +} + +void +auditd_log_notice(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_NOTICE, fmt, ap); + va_end(ap); +} + +void +auditd_log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_INFO, fmt, ap); + va_end(ap); +} + +void +auditd_log_debug(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_DEBUG, fmt, ap); + va_end(ap); +} + +/* + * Get the auditing state from the kernel and cache it. + */ +static void +init_audit_state(void) +{ + long au_cond; + + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno != ENOSYS) { + auditd_log_err("Audit status check failed (%s)", + strerror(errno)); + } + auditing_state = AUD_STATE_DISABLED; + } else + if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) + auditing_state = AUD_STATE_DISABLED; + else + auditing_state = AUD_STATE_ENABLED; +} + +/* + * Update the cached auditing state. + */ +void +auditd_set_state(int state) +{ + int old_auditing_state = auditing_state; + + if (state == AUD_STATE_INIT) + init_audit_state(); + else + auditing_state = state; + + if (auditing_state != old_auditing_state) { + if (auditing_state == AUD_STATE_ENABLED) + auditd_log_notice("Auditing enabled"); + if (auditing_state == AUD_STATE_DISABLED) + auditd_log_notice("Auditing disabled"); + } +} + +/* + * Get the cached auditing state. + */ +int +auditd_get_state(void) +{ + + if (auditing_state == AUD_STATE_INIT) + init_audit_state(); + + return (auditing_state); +} + +/* + * Open the trigger messaging mechanism. + */ +int +auditd_open_trigger(int __unused launchd_flag) +{ + + return ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0))); +} + +/* + * Close the trigger messaging mechanism. + */ +int +auditd_close_trigger(void) +{ + + return (close(triggerfd)); +} + +/* + * The main event loop. Wait for trigger messages or signals and handle them. + * It should not return unless there is a problem. + */ +void +auditd_wait_for_events(void) +{ + int num; + unsigned int trigger; + + for (;;) { + num = read(triggerfd, &trigger, sizeof(trigger)); + if ((num == -1) && (errno != EINTR)) { + auditd_log_err("%s: error %d", __FUNCTION__, errno); + return; + } + + /* Reset the idle time alarm, if used. */ + if (max_idletime) + alarm(max_idletime); + + if (sigterms != sigterms_handled) { + auditd_log_debug("%s: SIGTERM", __FUNCTION__); + auditd_terminate(); + /* not reached */ + } + if (sigalrms != sigalrms_handled) { + auditd_log_debug("%s: SIGALRM", __FUNCTION__); + auditd_terminate(); + /* not reached */ + } + if (sigchlds != sigchlds_handled) { + sigchlds_handled = sigchlds; + auditd_reap_children(); + } + if (sighups != sighups_handled) { + auditd_log_debug("%s: SIGHUP", __FUNCTION__); + sighups_handled = sighups; + auditd_config_controls(); + } + + if ((num == -1) && (errno == EINTR)) + continue; + if (num == 0) { + auditd_log_err("%s: read EOF", __FUNCTION__); + return; + } + auditd_handle_trigger(trigger); + } +} + +/* + * When we get a signal, we are often not at a clean point. So, little can + * be done in the signal handler itself. Instead, we send a message to the + * main servicing loop to do proper handling from a non-signal-handler + * context. + */ +void +auditd_relay_signal(int signal) +{ + if (signal == SIGHUP) + sighups++; + if (signal == SIGTERM) + sigterms++; + if (signal == SIGCHLD) + sigchlds++; + if (signal == SIGALRM) + sigalrms++; +} + diff --git a/contrib/openbsm/bin/auditfilterd/Makefile.in b/contrib/openbsm/bin/auditfilterd/Makefile.in index 874e1062cd466..07926da574e50 100644 --- a/contrib/openbsm/bin/auditfilterd/Makefile.in +++ b/contrib/openbsm/bin/auditfilterd/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/Makefile.in#6 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/Makefile.in#7 $ # VPATH = @srcdir@ diff --git a/contrib/openbsm/bin/auditreduce/Makefile.in b/contrib/openbsm/bin/auditreduce/Makefile.in index b18513f2c84e6..1030a837a7912 100644 --- a/contrib/openbsm/bin/auditreduce/Makefile.in +++ b/contrib/openbsm/bin/auditreduce/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/Makefile.in#8 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/Makefile.in#9 $ # VPATH = @srcdir@ diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.c b/contrib/openbsm/bin/auditreduce/auditreduce.c index f22f4546a4efd..215852563dc81 100644 --- a/contrib/openbsm/bin/auditreduce/auditreduce.c +++ b/contrib/openbsm/bin/auditreduce/auditreduce.c @@ -26,7 +26,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.c#28 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.c#29 $ */ /* @@ -567,7 +567,7 @@ select_records(FILE *fp) * The -o option has the form object_type=object_value. Identify the object * components. */ -void +static void parse_object_type(char *name, char *val) { if (val == NULL) diff --git a/contrib/openbsm/bin/praudit/Makefile.in b/contrib/openbsm/bin/praudit/Makefile.in index 4472757506442..025b48fbb8627 100644 --- a/contrib/openbsm/bin/praudit/Makefile.in +++ b/contrib/openbsm/bin/praudit/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $P4: //depot/projects/trustedbsd/openbsm/bin/praudit/Makefile.in#8 $ +# $P4: //depot/projects/trustedbsd/openbsm/bin/praudit/Makefile.in#9 $ # VPATH = @srcdir@ |
