summaryrefslogtreecommitdiffstats
path: root/contrib/openbsm/bin
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/openbsm/bin')
-rw-r--r--contrib/openbsm/bin/Makefile.am11
-rw-r--r--contrib/openbsm/bin/Makefile.in579
-rw-r--r--contrib/openbsm/bin/audit/Makefile.am19
-rw-r--r--contrib/openbsm/bin/audit/Makefile.in657
-rw-r--r--contrib/openbsm/bin/audit/audit.8105
-rw-r--r--contrib/openbsm/bin/audit/audit.c179
-rw-r--r--contrib/openbsm/bin/auditd/Makefile.am22
-rw-r--r--contrib/openbsm/bin/auditd/Makefile.in669
-rw-r--r--contrib/openbsm/bin/auditd/audit_triggers.defs1
-rw-r--r--contrib/openbsm/bin/auditd/audit_warn.c251
-rw-r--r--contrib/openbsm/bin/auditd/auditd.8140
-rw-r--r--contrib/openbsm/bin/auditd/auditd.c850
-rw-r--r--contrib/openbsm/bin/auditd/auditd.h100
-rw-r--r--contrib/openbsm/bin/auditd/auditd_control.defs47
-rw-r--r--contrib/openbsm/bin/auditd/auditd_darwin.c482
-rw-r--r--contrib/openbsm/bin/auditd/auditd_fbsd.c272
-rw-r--r--contrib/openbsm/bin/auditdistd/Makefile.am29
-rw-r--r--contrib/openbsm/bin/auditdistd/Makefile.in753
-rw-r--r--contrib/openbsm/bin/auditdistd/auditdistd.8106
-rw-r--r--contrib/openbsm/bin/auditdistd/auditdistd.c798
-rw-r--r--contrib/openbsm/bin/auditdistd/auditdistd.conf.5364
-rw-r--r--contrib/openbsm/bin/auditdistd/auditdistd.h274
-rw-r--r--contrib/openbsm/bin/auditdistd/faccessat.h67
-rw-r--r--contrib/openbsm/bin/auditdistd/fstatat.h67
-rw-r--r--contrib/openbsm/bin/auditdistd/openat.h73
-rw-r--r--contrib/openbsm/bin/auditdistd/parse.y854
-rw-r--r--contrib/openbsm/bin/auditdistd/pjdlog.c619
-rw-r--r--contrib/openbsm/bin/auditdistd/pjdlog.h117
-rw-r--r--contrib/openbsm/bin/auditdistd/proto.c527
-rw-r--r--contrib/openbsm/bin/auditdistd/proto.h61
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_common.c231
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_impl.h82
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_socketpair.c264
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_tcp.c721
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_tls.c1074
-rw-r--r--contrib/openbsm/bin/auditdistd/proto_uds.c360
-rw-r--r--contrib/openbsm/bin/auditdistd/receiver.c712
-rw-r--r--contrib/openbsm/bin/auditdistd/renameat.h66
-rw-r--r--contrib/openbsm/bin/auditdistd/sandbox.c232
-rw-r--r--contrib/openbsm/bin/auditdistd/sandbox.h37
-rw-r--r--contrib/openbsm/bin/auditdistd/sender.c845
-rw-r--r--contrib/openbsm/bin/auditdistd/sigtimedwait.h90
-rw-r--r--contrib/openbsm/bin/auditdistd/strndup.h53
-rw-r--r--contrib/openbsm/bin/auditdistd/subr.c304
-rw-r--r--contrib/openbsm/bin/auditdistd/subr.h58
-rw-r--r--contrib/openbsm/bin/auditdistd/synch.h204
-rw-r--r--contrib/openbsm/bin/auditdistd/token.l82
-rw-r--r--contrib/openbsm/bin/auditdistd/trail.c609
-rw-r--r--contrib/openbsm/bin/auditdistd/trail.h60
-rw-r--r--contrib/openbsm/bin/auditdistd/unlinkat.h66
-rw-r--r--contrib/openbsm/bin/auditfilterd/Makefile.am10
-rw-r--r--contrib/openbsm/bin/auditfilterd/Makefile.in649
-rw-r--r--contrib/openbsm/bin/auditfilterd/auditfilterd.884
-rw-r--r--contrib/openbsm/bin/auditfilterd/auditfilterd.c352
-rw-r--r--contrib/openbsm/bin/auditfilterd/auditfilterd.h77
-rw-r--r--contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c511
-rw-r--r--contrib/openbsm/bin/auditreduce/Makefile.am10
-rw-r--r--contrib/openbsm/bin/auditreduce/Makefile.in647
-rw-r--r--contrib/openbsm/bin/auditreduce/auditreduce.1195
-rw-r--r--contrib/openbsm/bin/auditreduce/auditreduce.c801
-rw-r--r--contrib/openbsm/bin/auditreduce/auditreduce.h73
-rw-r--r--contrib/openbsm/bin/praudit/Makefile.am10
-rw-r--r--contrib/openbsm/bin/praudit/Makefile.in647
-rw-r--r--contrib/openbsm/bin/praudit/praudit.1119
-rw-r--r--contrib/openbsm/bin/praudit/praudit.c173
65 files changed, 19601 insertions, 0 deletions
diff --git a/contrib/openbsm/bin/Makefile.am b/contrib/openbsm/bin/Makefile.am
new file mode 100644
index 0000000..15a3dbc
--- /dev/null
+++ b/contrib/openbsm/bin/Makefile.am
@@ -0,0 +1,11 @@
+SUBDIRS = \
+ auditdistd \
+ auditfilterd \
+ auditreduce \
+ praudit
+
+if HAVE_AUDIT_SYSCALLS
+SUBDIRS += \
+ audit \
+ auditd
+endif
diff --git a/contrib/openbsm/bin/Makefile.in b/contrib/openbsm/bin/Makefile.in
new file mode 100644
index 0000000..e2b3754
--- /dev/null
+++ b/contrib/openbsm/bin/Makefile.in
@@ -0,0 +1,579 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_AUDIT_SYSCALLS_TRUE@am__append_1 = \
+@HAVE_AUDIT_SYSCALLS_TRUE@ audit \
+@HAVE_AUDIT_SYSCALLS_TRUE@ auditd
+
+subdir = bin
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = auditdistd auditfilterd auditreduce praudit audit \
+ auditd
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = auditdistd auditfilterd auditreduce praudit $(am__append_1)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+cscopelist-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \
+ cscopelist-recursive ctags-recursive install-am install-strip \
+ tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist cscopelist-recursive ctags ctags-recursive \
+ distclean distclean-generic distclean-libtool distclean-tags \
+ distdir dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-recursive uninstall uninstall-am
+
+
+# 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/Makefile.am b/contrib/openbsm/bin/audit/Makefile.am
new file mode 100644
index 0000000..d0af56c
--- /dev/null
+++ b/contrib/openbsm/bin/audit/Makefile.am
@@ -0,0 +1,19 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = audit
+audit_LDADD = $(top_builddir)/libbsm/libbsm.la
+man8_MANS = audit.8
+
+if USE_MACH_IPC
+audit_SOURCES = auditd_controlUser.c audit.c
+CLEANFILES = auditd_controlUser.c auditd_control.h
+
+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
new file mode 100644
index 0000000..b7b8361
--- /dev/null
+++ b/contrib/openbsm/bin/audit/Makefile.in
@@ -0,0 +1,657 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = audit$(EXEEXT)
+subdir = bin/audit
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+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_controlUser.$(OBJEXT) \
+@USE_MACH_IPC_TRUE@ audit.$(OBJEXT)
+audit_OBJECTS = $(am_audit_OBJECTS)
+audit_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(audit_SOURCES)
+DIST_SOURCES = $(am__audit_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man8_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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)
+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_controlUser.c audit.c
+@USE_MACH_IPC_TRUE@CLEANFILES = auditd_controlUser.c auditd_control.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/audit/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/audit/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+audit$(EXEEXT): $(audit_OBJECTS) $(audit_DEPENDENCIES) $(EXTRA_audit_DEPENDENCIES)
+ @rm -f audit$(EXEEXT)
+ $(LINK) $(audit_OBJECTS) $(audit_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+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_controlUser.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man8: $(man8_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man8_MANS)'; \
+ list2=''; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man8 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+
+@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
new file mode 100644
index 0000000..b9f98b3
--- /dev/null
+++ b/contrib/openbsm/bin/audit/audit.8
@@ -0,0 +1,105 @@
+.\" Copyright (c) 2004-2009 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.
+.\"
+.Dd July 25, 2015
+.Dt AUDIT 8
+.Os
+.Sh NAME
+.Nm audit
+.Nd audit management utility
+.Sh SYNOPSIS
+.Nm
+.Fl e | i | n | s | t
+.Sh DESCRIPTION
+The
+.Nm
+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 e
+Forces the audit system to immediately remove audit log files that
+meet the expiration criteria specified in the audit control file without
+doing a log rotation.
+.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.
+Also, audit log files that meet the expiration criteria specified in the
+audit control file will be removed.
+.It Fl s
+Specifies that the audit system should [re]synchronize its
+configuration from the audit control file.
+A new log file will be created.
+.It Fl t
+Specifies that the audit system should terminate.
+Log files are closed
+and renamed to indicate the time of the shutdown.
+.El
+.Sh NOTES
+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
+Audit policy file used to configure the auditing system.
+.El
+.Sh SEE ALSO
+.Xr audit 4 ,
+.Xr audit_control 5 ,
+.Xr auditd 8 ,
+.Xr launchd 8 (Mac OS X)
+.Sh HISTORY
+The OpenBSM implementation was created by McAfee Research, the security
+division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004.
+It was subsequently adopted by the TrustedBSD Project as the foundation for
+the OpenBSM distribution.
+.Sh AUTHORS
+.An -nosplit
+This software was created by McAfee Research, the security research division
+of McAfee, Inc., under contract to Apple Computer Inc.
+Additional authors include
+.An Wayne Salamon ,
+.An Robert Watson ,
+and SPARTA Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
diff --git a/contrib/openbsm/bin/audit/audit.c b/contrib/openbsm/bin/audit/audit.c
new file mode 100644
index 0000000..dfe956f
--- /dev/null
+++ b/contrib/openbsm/bin/audit/audit.c
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2005-2009 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.
+ */
+/*
+ * Program to trigger the audit daemon with a message that is either:
+ * - Open a new audit log file
+ * - Read the audit control file and take action on it
+ * - Close the audit log file and exit
+ *
+ */
+
+#include <sys/types.h>
+#include <config/config.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/uio.h>
+
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int send_trigger(int);
+
+#ifdef USE_MACH_IPC
+#include <mach/mach.h>
+#include <servers/netname.h>
+#include <mach/message.h>
+#include <mach/port.h>
+#include <mach/mach_error.h>
+#include <mach/host_special_ports.h>
+#include <servers/bootstrap.h>
+
+#include "auditd_control.h"
+
+/*
+ * XXX The following are temporary until these can be added to the kernel
+ * audit.h header.
+ */
+#ifndef AUDIT_TRIGGER_INITIALIZE
+#define AUDIT_TRIGGER_INITIALIZE 7
+#endif
+#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS
+#define AUDIT_TRIGGER_EXPIRE_TRAILS 8
+#endif
+
+static int
+send_trigger(int trigger)
+{
+ mach_port_t serverPort;
+ kern_return_t error;
+
+ error = host_get_audit_control_port(mach_host_self(), &serverPort);
+ if (error != KERN_SUCCESS) {
+ if (geteuid() != 0) {
+ errno = EPERM;
+ perror("audit requires root privileges");
+ } else
+ mach_error("Cannot get auditd_control Mach port:",
+ error);
+ return (-1);
+ }
+
+ error = auditd_control(serverPort, trigger);
+ if (error != KERN_SUCCESS) {
+ mach_error("Error sending trigger: ", error);
+ return (-1);
+ }
+
+ return (0);
+}
+
+#else /* ! USE_MACH_IPC */
+
+static int
+send_trigger(int trigger)
+{
+ int error;
+
+ error = audit_send_trigger(&trigger);
+ if (error != 0) {
+ if (error == EPERM)
+ perror("audit requires root privileges");
+ else
+ perror("Error sending trigger");
+ return (-1);
+ }
+
+ return (0);
+}
+#endif /* ! USE_MACH_IPC */
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "Usage: audit -e | -i | -n | -s | -t \n");
+ exit(-1);
+}
+
+/*
+ * Main routine to process command line options.
+ */
+int
+main(int argc, char **argv)
+{
+ int ch;
+ unsigned int trigger = 0;
+
+ if (argc != 2)
+ usage();
+
+ while ((ch = getopt(argc, argv, "einst")) != -1) {
+ switch(ch) {
+
+ case 'e':
+ trigger = AUDIT_TRIGGER_EXPIRE_TRAILS;
+ break;
+
+ case 'i':
+ trigger = AUDIT_TRIGGER_INITIALIZE;
+ break;
+
+ case 'n':
+ trigger = AUDIT_TRIGGER_ROTATE_USER;
+ break;
+
+ case 's':
+ trigger = AUDIT_TRIGGER_READ_FILE;
+ break;
+
+ case 't':
+ trigger = AUDIT_TRIGGER_CLOSE_AND_DIE;
+ break;
+
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ if (send_trigger(trigger) < 0)
+ exit(-1);
+
+ printf("Trigger sent.\n");
+ exit (0);
+}
diff --git a/contrib/openbsm/bin/auditd/Makefile.am b/contrib/openbsm/bin/auditd/Makefile.am
new file mode 100644
index 0000000..8a2a9df
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/Makefile.am
@@ -0,0 +1,22 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = auditd
+auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la
+man8_MANS = auditd.8
+
+if USE_MACH_IPC
+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_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_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_fbsd.c
+endif
diff --git a/contrib/openbsm/bin/auditd/Makefile.in b/contrib/openbsm/bin/auditd/Makefile.in
new file mode 100644
index 0000000..3fa44f1
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/Makefile.in
@@ -0,0 +1,669 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = auditd$(EXEEXT)
+subdir = bin/auditd
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+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) 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 \
+ $(top_builddir)/libauditd/libauditd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(auditd_SOURCES)
+DIST_SOURCES = $(am__auditd_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man8_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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 $(top_builddir)/libauditd/libauditd.la
+man8_MANS = auditd.8
+@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:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/auditd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+auditd$(EXEEXT): $(auditd_OBJECTS) $(auditd_DEPENDENCIES) $(EXTRA_auditd_DEPENDENCIES)
+ @rm -f auditd$(EXEEXT)
+ $(LINK) $(auditd_OBJECTS) $(auditd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@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_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 $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man8: $(man8_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man8_MANS)'; \
+ list2=''; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man8 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+
+@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_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_triggers.defs b/contrib/openbsm/bin/auditd/audit_triggers.defs
new file mode 100644
index 0000000..9fe2c35
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/audit_triggers.defs
@@ -0,0 +1 @@
+#include <mach/audit_triggers.defs>
diff --git a/contrib/openbsm/bin/auditd/audit_warn.c b/contrib/openbsm/bin/auditd/audit_warn.c
new file mode 100644
index 0000000..6bd2b84
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/audit_warn.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 2005-2009 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.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "auditd.h"
+
+/*
+ * Write an audit-related error to the system log via syslog(3).
+ */
+static int
+auditwarnlog(char *args[])
+{
+ char *loc_args[9];
+ pid_t pid;
+ int i;
+
+ loc_args[0] = AUDITWARN_SCRIPT;
+ for (i = 0; args[i] != NULL && i < 8; i++)
+ loc_args[i+1] = args[i];
+ loc_args[i+1] = NULL;
+
+ pid = fork();
+ if (pid == -1)
+ return (-1);
+ if (pid == 0) {
+ /*
+ * Child.
+ */
+ execv(AUDITWARN_SCRIPT, loc_args);
+ syslog(LOG_ERR, "Could not exec %s (%m)\n",
+ AUDITWARN_SCRIPT);
+ exit(1);
+ }
+ /*
+ * Parent.
+ */
+ return (0);
+}
+
+/*
+ * Indicates that the hard limit for all filesystems has been exceeded.
+ */
+int
+audit_warn_allhard(void)
+{
+ char *args[2];
+
+ args[0] = HARDLIM_ALL_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that the soft limit for all filesystems has been exceeded.
+ */
+int
+audit_warn_allsoft(void)
+{
+ char *args[2];
+
+ args[0] = SOFTLIM_ALL_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that someone other than the audit daemon turned off auditing.
+ * XXX Its not clear at this point how this function will be invoked.
+ *
+ * XXXRW: This function is not used.
+ */
+int
+audit_warn_auditoff(void)
+{
+ char *args[2];
+
+ args[0] = AUDITOFF_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicate that a trail file has been closed, so can now be post-processed.
+ */
+int
+audit_warn_closefile(char *filename)
+{
+ char *args[3];
+
+ args[0] = CLOSEFILE_WARN;
+ args[1] = filename;
+ args[2] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that the audit deammn is already running
+ */
+int
+audit_warn_ebusy(void)
+{
+ char *args[2];
+
+ args[0] = EBUSY_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that there is a problem getting the directory from
+ * audit_control.
+ *
+ * XXX Note that we take the filename instead of a count as the argument here
+ * (different from BSM).
+ */
+int
+audit_warn_getacdir(char *filename)
+{
+ char *args[3];
+
+ args[0] = GETACDIR_WARN;
+ args[1] = filename;
+ args[2] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that the hard limit for this file has been exceeded.
+ */
+int
+audit_warn_hard(char *filename)
+{
+ char *args[3];
+
+ args[0] = HARDLIM_WARN;
+ args[1] = filename;
+ args[2] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that auditing could not be started.
+ */
+int
+audit_warn_nostart(void)
+{
+ char *args[2];
+
+ args[0] = NOSTART_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicaes that an error occrred during the orderly shutdown of the audit
+ * daemon.
+ */
+int
+audit_warn_postsigterm(void)
+{
+ char *args[2];
+
+ args[0] = POSTSIGTERM_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that the soft limit for this file has been exceeded.
+ */
+int
+audit_warn_soft(char *filename)
+{
+ char *args[3];
+
+ args[0] = SOFTLIM_WARN;
+ args[1] = filename;
+ args[2] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that the temporary audit file already exists indicating a fatal
+ * error.
+ */
+int
+audit_warn_tmpfile(void)
+{
+ char *args[2];
+
+ args[0] = TMPFILE_WARN;
+ args[1] = NULL;
+
+ return (auditwarnlog(args));
+}
+
+/*
+ * Indicates that this trail file has expired and was removed.
+ */
+int
+audit_warn_expired(char *filename)
+{
+ char *args[3];
+
+ args[0] = EXPIRED_WARN;
+ args[1] = filename;
+ args[2] = NULL;
+
+ return (auditwarnlog(args));
+}
diff --git a/contrib/openbsm/bin/auditd/auditd.8 b/contrib/openbsm/bin/auditd/auditd.8
new file mode 100644
index 0000000..c76dfca
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd.8
@@ -0,0 +1,140 @@
+.\" Copyright (c) 2004 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.
+.\"
+.Dd July 25, 2015
+.Dt AUDITD 8
+.Os
+.Sh NAME
+.Nm auditd
+.Nd audit log management daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl d | l
+.Sh DESCRIPTION
+The
+.Nm
+daemon responds to requests from the
+.Xr audit 8
+utility and notifications
+from the kernel.
+It manages the resulting audit log files and specified
+log file locations.
+.Pp
+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
+daemon should not be started and stopped manually.
+Instead, the
+.Xr audit 8
+command
+should be used to inform the daemon to change state/configuration after altering
+the
+.Pa audit_control
+file.
+.Pp
+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
+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 /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
+.Fl h
+and
+.Fl s
+flags are now configured using
+.Xr audit_control 5
+policy flags
+.Cm ahlt
+and
+.Cm cnt ,
+and are no longer available as arguments to
+.Nm .
+.Sh SEE ALSO
+.Xr asl 3 ,
+.Xr libauditd 3 ,
+.Xr audit 4 ,
+.Xr audit_class 5 ,
+.Xr audit_control 5 ,
+.Xr audit_event 5 ,
+.Xr audit_warn 5 ,
+.Xr audit 8 ,
+.Xr auditdistd 8 ,
+.Xr launchd 8 (Mac OS X)
+.Sh HISTORY
+The OpenBSM implementation was created by McAfee Research, the security
+division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004.
+It was subsequently adopted by the TrustedBSD Project as the foundation for
+the OpenBSM distribution.
+.Sh AUTHORS
+.An -nosplit
+This software was created by McAfee Research, the security research division
+of McAfee, Inc., under contract to Apple Computer Inc.
+Additional authors include
+.An Wayne Salamon ,
+.An Robert Watson ,
+and SPARTA Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
diff --git a/contrib/openbsm/bin/auditd/auditd.c b/contrib/openbsm/bin/auditd/auditd.c
new file mode 100644
index 0000000..a4357bd
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd.c
@@ -0,0 +1,850 @@
+/*-
+ * Copyright (c) 2004-2009 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.
+ */
+
+#include <sys/types.h>
+
+#include <config/config.h>
+
+#include <sys/dirent.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 <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+#include "auditd.h"
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+/*
+ * XXX The following are temporary until these can be added to the kernel
+ * audit.h header.
+ */
+#ifndef AUDIT_TRIGGER_INITIALIZE
+#define AUDIT_TRIGGER_INITIALIZE 7
+#endif
+#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS
+#define AUDIT_TRIGGER_EXPIRE_TRAILS 8
+#endif
+
+
+/*
+ * 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;
+
+/*
+ * 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 gid_t audit_review_gid = -1;
+
+/*
+ * The path and file name of the last audit trail file.
+ */
+static char *lastfile = NULL;
+
+/*
+ * Error starting auditd. Run warn script and exit.
+ */
+static void
+fail_exit(void)
+{
+
+ audit_warn_nostart();
+ exit(1);
+}
+
+/*
+ * Follow the 'current' symlink to get the active trail file name.
+ */
+static char *
+get_curfile(void)
+{
+ char *cf;
+ int len;
+
+ 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);
+ }
+
+ /* readlink() doesn't terminate string. */
+ cf[len] = '\0';
+
+ return (cf);
+}
+
+/*
+ * Close the previous audit trail file.
+ */
+static int
+close_lastfile(char *TS)
+{
+ char *ptr;
+ char *oldname;
+
+ /* If lastfile is NULL try to get it from the 'current' link. */
+ if (lastfile == NULL)
+ lastfile = get_curfile();
+
+ if (lastfile != NULL) {
+ oldname = strdup(lastfile);
+ if (oldname == NULL)
+ return (-1);
+
+ /* Rename the last file -- append timestamp. */
+ if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
+ memcpy(ptr, TS, POSTFIX_LEN);
+ if (auditd_rename(oldname, lastfile) != 0)
+ auditd_log_err(
+ "Could not rename %s to %s: %m", oldname,
+ lastfile);
+ else {
+ /*
+ * 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
+ auditd_log_err("Could not rename %s to %s", oldname,
+ lastfile);
+ free(lastfile);
+ free(oldname);
+ lastfile = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Create the new file name, swap with existing audit file.
+ */
+static int
+swap_audit_file(void)
+{
+ int err;
+ char *newfile, *name;
+ char TS[TIMESTAMP_LEN + 1];
+ time_t tt;
+
+ if (getTSstr(tt, TS, sizeof(TS)) != 0)
+ return (-1);
+ /*
+ * If prefix and suffix are the same, it means that records are
+ * being produced too fast. We don't want to rename now, because
+ * next trail file can get the same name and once that one is
+ * terminated also within one second it will overwrite the current
+ * one. Just keep writing to the same trail and wait for the next
+ * trigger from the kernel.
+ * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT
+ * NOT BE THE CASE FOR OTHER OSES.
+ * If the kernel will not keep sending triggers, trail file will not
+ * be terminated.
+ */
+ if (lastfile == NULL) {
+ name = NULL;
+ } else {
+ name = strrchr(lastfile, '/');
+ if (name != NULL)
+ name++;
+ }
+ if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) {
+ auditd_log_debug("Not ready to terminate trail file yet.");
+ return (0);
+ }
+ 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);
+ }
+
+ /*
+ * Only close the last file if were in an auditing state before
+ * calling swap_audit_file(). We may need to recover from a crash.
+ */
+ if (auditd_get_state() == AUD_STATE_ENABLED)
+ close_lastfile(TS);
+
+
+ /*
+ * 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));
+
+ lastfile = newfile;
+ auditd_log_notice("New audit file is %s", newfile);
+
+ return (0);
+}
+
+/*
+ * Create a new audit log trail file and swap with the current one, if any.
+ */
+static int
+do_trail_file(void)
+{
+ int err;
+
+ /*
+ * First, refresh the list of audit log directories.
+ */
+ err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
+ if (err) {
+ auditd_log_err("auditd_read_dirs(): %s",
+ auditd_strerror(err));
+ if (err == ADE_HARDLIM)
+ audit_warn_allhard();
+ if (err != ADE_SOFTLIM)
+ return (-1);
+ else
+ audit_warn_allsoft();
+ /* continue on with soft limit error */
+ }
+
+ /*
+ * Create a new file and swap with the one being used in kernel.
+ */
+ if (swap_audit_file() == -1) {
+ /*
+ * XXX Faulty directory listing? - user should be given
+ * XXX an opportunity to change the audit_control file
+ * XXX switch to a reduced mode of auditing?
+ */
+ return (-1);
+ }
+
+ /*
+ * Finally, see if there are any trail files to expire.
+ */
+ err = auditd_expire_trails(audit_warn_expired);
+ if (err)
+ auditd_log_err("auditd_expire_trails(): %s",
+ auditd_strerror(err));
+
+ return (0);
+}
+
+/*
+ * Start up auditing.
+ */
+static void
+audit_setup(void)
+{
+ int err;
+
+ /* Configure trail files distribution. */
+ err = auditd_set_dist();
+ if (err) {
+ auditd_log_err("auditd_set_dist() %s: %m",
+ auditd_strerror(err));
+ } else
+ auditd_log_debug("Configured trail files distribution.");
+
+ 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);
+}
+
+/*
+ * Close all log files, control files, and tell the audit system.
+ */
+static int
+close_all(void)
+{
+ int err_ret = 0;
+ char TS[TIMESTAMP_LEN + 1];
+ int err;
+ int cond;
+ time_t tt;
+
+ 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 = audit_set_cond(&cond);
+ if (err_ret != 0) {
+ auditd_log_err("Disabling audit failed! : %s", strerror(errno));
+ err_ret = 1;
+ }
+
+ /*
+ * Updated the cached state that auditing has been disabled.
+ */
+ auditd_set_state(AUD_STATE_DISABLED);
+
+ if (getTSstr(tt, TS, sizeof(TS)) == 0)
+ close_lastfile(TS);
+ if (lastfile != NULL)
+ free(lastfile);
+
+ err_ret += close_misc();
+
+ if (err_ret) {
+ auditd_log_err("Could not unregister");
+ audit_warn_postsigterm();
+ }
+
+ auditd_log_info("Finished");
+ return (err_ret);
+}
+
+/*
+ * Register the daemon with the signal handler and the auditd pid file.
+ */
+static int
+register_daemon(void)
+{
+ FILE * pidfile;
+ int fd;
+ pid_t pid;
+
+ /* Set up the signal hander. */
+ if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
+ auditd_log_err(
+ "Could not set signal handler for SIGTERM");
+ fail_exit();
+ }
+ if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
+ auditd_log_err(
+ "Could not set signal handler for SIGCHLD");
+ fail_exit();
+ }
+ 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) {
+ auditd_log_err("Could not open PID file");
+ audit_warn_tmpfile();
+ return (-1);
+ }
+
+ /* Attempt to lock the pid file; if a lock is present, exit. */
+ fd = fileno(pidfile);
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+ auditd_log_err(
+ "PID file is locked (is another auditd running?).");
+ audit_warn_ebusy();
+ return (-1);
+ }
+
+ pid = getpid();
+ ftruncate(fd, 0);
+ if (fprintf(pidfile, "%u\n", pid) < 0) {
+ /* Should not start the daemon. */
+ fail_exit();
+ }
+
+ fflush(pidfile);
+ return (0);
+}
+
+/*
+ * Handle the audit trigger event.
+ *
+ * We suppress (ignore) duplicated triggers in close succession in order to
+ * try to avoid thrashing-like behavior. However, not all triggers can be
+ * ignored, as triggers generally represent edge triggers, not level
+ * triggers, and won't be retransmitted if the condition persists. Of
+ * specific concern is the rotate trigger -- if one is dropped, then it will
+ * not be retransmitted, and the log file will grow in an unbounded fashion.
+ */
+#define DUPLICATE_INTERVAL 30
+void
+auditd_handle_trigger(int trigger)
+{
+ static int last_trigger, last_warning;
+ static time_t last_time;
+ struct timeval ts;
+ struct timezone tzp;
+ time_t tt;
+ int au_state;
+ int err = 0;
+
+ /*
+ * Suppress duplicate messages from the kernel within the specified
+ * interval.
+ */
+ if (gettimeofday(&ts, &tzp) == 0) {
+ tt = (time_t)ts.tv_sec;
+ switch (trigger) {
+ case AUDIT_TRIGGER_LOW_SPACE:
+ case AUDIT_TRIGGER_NO_SPACE:
+ /*
+ * Triggers we can suppress. Of course, we also need
+ * to rate limit the warnings, so apply the same
+ * interval limit on syslog messages.
+ */
+ if ((trigger == last_trigger) &&
+ (tt < (last_time + DUPLICATE_INTERVAL))) {
+ if (tt >= (last_warning + DUPLICATE_INTERVAL))
+ auditd_log_info(
+ "Suppressing duplicate trigger %d",
+ trigger);
+ return;
+ }
+ last_warning = tt;
+ break;
+
+ 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.
+ */
+ break;
+ }
+
+ /*
+ * Only update last_trigger after aborting due to a duplicate
+ * trigger, not before, or we will never allow that trigger
+ * again.
+ */
+ last_trigger = trigger;
+ last_time = tt;
+ }
+
+ au_state = auditd_get_state();
+
+ /*
+ * Message processing is done here.
+ */
+ switch(trigger) {
+ case AUDIT_TRIGGER_LOW_SPACE:
+ 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:
+ 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:
+ auditd_log_info("Got open new trigger from %s", trigger ==
+ AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
+ if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
+ auditd_log_err("Error swapping audit file");
+ break;
+
+ case AUDIT_TRIGGER_READ_FILE:
+ auditd_log_info("Got read file trigger");
+ if (au_state == AUD_STATE_ENABLED) {
+ if (auditd_config_controls() == -1)
+ auditd_log_err("Error setting audit controls");
+ else if (do_trail_file() == -1)
+ auditd_log_err("Error swapping audit file");
+ }
+ break;
+
+ case AUDIT_TRIGGER_CLOSE_AND_DIE:
+ auditd_log_info("Got close and die trigger");
+ if (au_state == AUD_STATE_ENABLED)
+ err = close_all();
+ /*
+ * Running under launchd don't exit. Wait for launchd to
+ * send SIGTERM.
+ */
+ if (!launchd_flag) {
+ auditd_log_info("auditd exiting.");
+ exit (err);
+ }
+ break;
+
+ case AUDIT_TRIGGER_INITIALIZE:
+ auditd_log_info("Got audit initialize trigger");
+ if (au_state == AUD_STATE_DISABLED)
+ audit_setup();
+ break;
+
+ case AUDIT_TRIGGER_EXPIRE_TRAILS:
+ auditd_log_info("Got audit expire trails trigger");
+ err = auditd_expire_trails(audit_warn_expired);
+ if (err)
+ auditd_log_err("auditd_expire_trails(): %s",
+ auditd_strerror(err));
+ break;
+
+ default:
+ auditd_log_err("Got unknown trigger %d", trigger);
+ break;
+ }
+}
+
+/*
+ * Reap our children.
+ */
+void
+auditd_reap_children(void)
+{
+ pid_t child;
+ int wstatus;
+
+ while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
+ if (!wstatus)
+ continue;
+ 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) :
+ WTERMSIG(wstatus)));
+ }
+}
+
+/*
+ * Reap any children and terminate. If under launchd don't shutdown auditing
+ * but just the other stuff.
+ */
+void
+auditd_terminate(void)
+{
+ int ret;
+
+ auditd_reap_children();
+
+ if (launchd_flag)
+ ret = close_misc();
+ else
+ ret = close_all();
+
+ exit(ret);
+}
+
+/*
+ * Configure the audit controls in the kernel: the event to class mapping,
+ * kernel preselection mask, etc.
+ */
+int
+auditd_config_controls(void)
+{
+ int cnt, err;
+ int ret = 0;
+
+ /*
+ * 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
+ auditd_log_debug("Registered %d event to class mappings.", cnt);
+
+ /*
+ * Configure non-attributable event mask in kernel.
+ */
+ 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.");
+
+ /*
+ * Configure audit policy in kernel.
+ */
+ err = auditd_set_policy();
+ if (err) {
+ auditd_log_err("auditd_set_policy() %s: %m",
+ auditd_strerror(err));
+ ret = -1;
+ } else
+ auditd_log_debug("Set audit policy in kernel.");
+
+ /*
+ * Configure audit trail log size in kernel.
+ */
+ 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.");
+
+ /*
+ * Configure audit trail volume minimum free percentage of blocks in
+ * kernel.
+ */
+ 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.");
+
+ /*
+ * Configure host address in the audit kernel information.
+ */
+ err = auditd_set_host();
+ if (err) {
+ if (err == ADE_PARSE) {
+ auditd_log_notice(
+ "audit_control(5) may be missing 'host:' field");
+ } else {
+ auditd_log_err("auditd_set_host() %s: %m",
+ auditd_strerror(err));
+ ret = -1;
+ }
+ } else
+ auditd_log_debug(
+ "Set audit host address information in kernel.");
+
+ return (ret);
+}
+
+/*
+ * Setup and initialize auditd.
+ */
+static void
+setup(void)
+{
+ int err;
+
+ if (auditd_open_trigger(launchd_flag) < 0) {
+ auditd_log_err("Error opening trigger messaging mechanism");
+ fail_exit();
+ }
+
+ /*
+ * To prevent event feedback cycles and avoid auditd becoming
+ * stalled if auditing is suspended, auditd and its children run
+ * without their events being audited. We allow the uid, tid, and
+ * 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.
+ */
+ err = auditd_prevent_audit();
+ if (err) {
+ auditd_log_err("auditd_prevent_audit() %s: %m",
+ auditd_strerror(err));
+ fail_exit();
+ }
+
+ /*
+ * Make sure auditd auditing state is correct.
+ */
+ auditd_set_state(AUD_STATE_INIT);
+
+ /*
+ * If under launchd, don't start auditing. Wait for a trigger to
+ * do so.
+ */
+ if (!launchd_flag)
+ audit_setup();
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ int debug = 0;
+#ifdef AUDIT_REVIEW_GROUP
+ struct group *grp;
+#endif
+
+ 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] [-l]\n");
+ exit(1);
+ }
+ }
+
+ audit_review_gid = getgid();
+
+#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
+
+ 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) {
+ auditd_log_err("Could not register as daemon");
+ exit(1);
+ }
+
+ setup();
+
+ /*
+ * auditd_wait_for_events() shouldn't return unless something is wrong.
+ */
+ auditd_wait_for_events();
+
+ 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
new file mode 100644
index 0000000..20afd75
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd.h
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2005-2009 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.
+ */
+
+#ifndef _AUDITD_H_
+#define _AUDITD_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <syslog.h>
+
+#define MAX_DIR_SIZE 255
+#define AUDITD_NAME "auditd"
+
+/*
+ * If defined, then the audit daemon will attempt to chown newly created logs
+ * to this group. Otherwise, they will be the default for the user running
+ * auditd, likely the audit group.
+ */
+#define AUDIT_REVIEW_GROUP "audit"
+
+#define HARDLIM_ALL_WARN "allhard"
+#define SOFTLIM_ALL_WARN "allsoft"
+#define AUDITOFF_WARN "auditoff"
+#define CLOSEFILE_WARN "closefile"
+#define EBUSY_WARN "ebusy"
+#define GETACDIR_WARN "getacdir"
+#define HARDLIM_WARN "hard"
+#define NOSTART_WARN "nostart"
+#define POSTSIGTERM_WARN "postsigterm"
+#define SOFTLIM_WARN "soft"
+#define TMPFILE_WARN "tmpfile"
+#define EXPIRED_WARN "expired"
+
+#define AUDITWARN_SCRIPT "/etc/security/audit_warn"
+#define AUDITD_PIDFILE "/var/run/auditd.pid"
+
+#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);
+int audit_warn_ebusy(void);
+int audit_warn_getacdir(char *filename);
+int audit_warn_hard(char *filename);
+int audit_warn_nostart(void);
+int audit_warn_postsigterm(void);
+int audit_warn_soft(char *filename);
+int audit_warn_tmpfile(void);
+int audit_warn_expired(char *filename);
+
+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_control.defs b/contrib/openbsm/bin/auditd/auditd_control.defs
new file mode 100644
index 0000000..84f37df
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd_control.defs
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1999-2007 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.
+ */
+
+/*
+ * Exported client calls to the auditd facility.
+ */
+
+Subsystem
+ KernelUser
+ auditd_control 456;
+
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+simpleroutine auditd_control(
+ auditd_port : mach_port_t;
+ in trigger : int);
diff --git a/contrib/openbsm/bin/auditd/auditd_darwin.c b/contrib/openbsm/bin/auditd/auditd_darwin.c
new file mode 100644
index 0000000..702eb94
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd_darwin.c
@@ -0,0 +1,482 @@
+/*-
+ * Copyright (c) 2004-2009 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.
+ */
+
+#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 "com.apple.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", "com.apple.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)
+{
+ int au_cond;
+
+ if (audit_get_cond(&au_cond) < 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 0000000..d8f040f
--- /dev/null
+++ b/contrib/openbsm/bin/auditd/auditd_fbsd.c
@@ -0,0 +1,272 @@
+/*-
+ * Copyright (c) 2004-2009 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.
+ */
+
+#include <sys/types.h>
+
+#include <config/config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.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)
+{
+ int au_cond;
+
+ if (audit_get_cond(&au_cond) < 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/auditdistd/Makefile.am b/contrib/openbsm/bin/auditdistd/Makefile.am
new file mode 100644
index 0000000..263cb2d
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/Makefile.am
@@ -0,0 +1,29 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = auditdistd
+man5_MANS = auditdistd.conf.5
+man8_MANS = auditdistd.8
+CFLAGS = -Wno-format
+YFLAGS = -d
+auditdistd_LDFLAGS = -lcrypto
+
+auditdistd_SOURCES = \
+ auditdistd.c \
+ parse.y \
+ pjdlog.c \
+ proto.c \
+ proto_common.c \
+ proto_socketpair.c \
+ proto_tcp.c \
+ proto_tls.c \
+ proto_uds.c \
+ receiver.c \
+ sandbox.c \
+ sender.c \
+ subr.c \
+ token.l \
+ trail.c
diff --git a/contrib/openbsm/bin/auditdistd/Makefile.in b/contrib/openbsm/bin/auditdistd/Makefile.in
new file mode 100644
index 0000000..b6228fd
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/Makefile.in
@@ -0,0 +1,753 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = auditdistd$(EXEEXT)
+subdir = bin/auditdistd
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp $(top_srcdir)/config/ylwrap \
+ parse.c parse.h token.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_auditdistd_OBJECTS = auditdistd.$(OBJEXT) parse.$(OBJEXT) \
+ pjdlog.$(OBJEXT) proto.$(OBJEXT) proto_common.$(OBJEXT) \
+ proto_socketpair.$(OBJEXT) proto_tcp.$(OBJEXT) \
+ proto_tls.$(OBJEXT) proto_uds.$(OBJEXT) receiver.$(OBJEXT) \
+ sandbox.$(OBJEXT) sender.$(OBJEXT) subr.$(OBJEXT) \
+ token.$(OBJEXT) trail.$(OBJEXT)
+auditdistd_OBJECTS = $(am_auditdistd_OBJECTS)
+auditdistd_LDADD = $(LDADD)
+auditdistd_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(auditdistd_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+YLWRAP = $(top_srcdir)/config/ylwrap
+@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
+am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
+ -e s/c++$$/h++/ -e s/c$$/h/
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+SOURCES = $(auditdistd_SOURCES)
+DIST_SOURCES = $(auditdistd_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man5_MANS) $(man8_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = -Wno-format
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = -d
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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)
+man5_MANS = auditdistd.conf.5
+man8_MANS = auditdistd.8
+auditdistd_LDFLAGS = -lcrypto
+auditdistd_SOURCES = \
+ auditdistd.c \
+ parse.y \
+ pjdlog.c \
+ proto.c \
+ proto_common.c \
+ proto_socketpair.c \
+ proto_tcp.c \
+ proto_tls.c \
+ proto_uds.c \
+ receiver.c \
+ sandbox.c \
+ sender.c \
+ subr.c \
+ token.l \
+ trail.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditdistd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/auditdistd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+parse.h: parse.c
+ @if test ! -f $@; then rm -f parse.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) parse.c; else :; fi
+auditdistd$(EXEEXT): $(auditdistd_OBJECTS) $(auditdistd_DEPENDENCIES) $(EXTRA_auditdistd_DEPENDENCIES)
+ @rm -f auditdistd$(EXEEXT)
+ $(auditdistd_LINK) $(auditdistd_OBJECTS) $(auditdistd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditdistd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pjdlog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_socketpair.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_tcp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_tls.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_uds.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sandbox.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trail.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+ $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+ $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man5: $(man5_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man5_MANS)'; \
+ list2=''; \
+ test -n "$(man5dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.5[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man5:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(man8_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man8_MANS)'; \
+ list2=''; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f parse.c
+ -rm -f parse.h
+ -rm -f token.c
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man5 install-man8 install-pdf install-pdf-am \
+ install-ps install-ps-am install-sbinPROGRAMS install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man5 \
+ uninstall-man8 uninstall-sbinPROGRAMS
+
+
+# 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/auditdistd/auditdistd.8 b/contrib/openbsm/bin/auditdistd/auditdistd.8
new file mode 100644
index 0000000..71a6575
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/auditdistd.8
@@ -0,0 +1,106 @@
+.\" Copyright (c) 2012 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 5, 2012
+.Dt AUDITDISTD 8
+.Os
+.Sh NAME
+.Nm auditdistd
+.Nd "Audit trail files distribution daemon"
+.Sh SYNOPSIS
+.Nm
+.Op Fl dFhl
+.Op Fl c Ar config
+.Op Fl P Ar pidfile
+.Sh DESCRIPTION
+The
+.Nm
+daemon is responsible for distributing audit trail files over a TCP/IP network in
+a secure and reliable way.
+.Pp
+The
+.Nm
+daemon can be started with the following command line arguments:
+.Bl -tag -width ".Fl P Ar pidfile"
+.It Fl c Ar config
+Specify an alternative location of the configuration file.
+The default location is
+.Pa /etc/security/auditdistd.conf .
+Note: the configuration file may contain passwords.
+Care should be taken to configure proper permissions on this file
+.Li ( eg. 0600 ) .
+.It Fl d
+Print or log debugging information.
+This option can be specified multiple times to raise the verbosity
+level.
+.It Fl F
+Start the
+.Nm
+daemon in the foreground.
+By default
+.Nm
+starts in the background.
+.It Fl h
+Print the
+.Nm
+usage message.
+.It Fl l
+Start in a launchd-friendly mode, ie. do not use
+.Xr daemon 3 .
+.It Fl P Ar pidfile
+Specify an alternative location of a file where main process PID will be
+stored.
+The default location is
+.Pa /var/run/auditdistd.pid .
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact
+.It Pa /etc/security/auditdistd.conf
+The configuration file for
+.Nm .
+.It Pa /var/run/auditdistd.pid
+The default location of the
+.Nm
+PID file.
+.El
+.Sh EXIT STATUS
+Exit status is 0 on success, or one of the values described in
+.Xr sysexits 3
+on failure.
+.Sh SEE ALSO
+.Xr sysexits 3 ,
+.Xr audit 4 ,
+.Xr auditdistd.conf 5 ,
+.Xr auditd 8
+.Sh AUTHORS
+The
+.Nm
+was developed by
+.An Pawel Jakub Dawidek Aq pawel@dawidek.net
+under sponsorship of the FreeBSD Foundation.
diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.c b/contrib/openbsm/bin/auditdistd/auditdistd.c
new file mode 100644
index 0000000..696f048
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/auditdistd.c
@@ -0,0 +1,798 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h>
+#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP)
+#include <sys/endian.h>
+#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else /* !HAVE_MACHINE_ENDIAN_H */
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else /* !HAVE_ENDIAN_H */
+#error "No supported endian.h"
+#endif /* !HAVE_ENDIAN_H */
+#endif /* !HAVE_MACHINE_ENDIAN_H */
+#include <compat/endian.h>
+#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <openssl/hmac.h>
+
+#ifndef HAVE_PIDFILE_OPEN
+#include <compat/pidfile.h>
+#endif
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+#ifndef HAVE_SIGTIMEDWAIT
+#include "sigtimedwait.h"
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+#include "proto.h"
+#include "subr.h"
+#include "synch.h"
+
+/* Path to configuration file. */
+const char *cfgpath = ADIST_CONFIG;
+/* Auditdistd configuration. */
+static struct adist_config *adcfg;
+/* Was SIGINT or SIGTERM signal received? */
+bool sigexit_received = false;
+/* PID file handle. */
+struct pidfh *pfh;
+
+/* How often check for hooks running for too long. */
+#define SIGNALS_CHECK_INTERVAL 5
+
+static void
+usage(void)
+{
+
+ errx(EX_USAGE, "[-dFhl] [-c config] [-P pidfile]");
+}
+
+void
+descriptors_cleanup(struct adist_host *adhost)
+{
+ struct adist_host *adh;
+ struct adist_listen *lst;
+
+ TAILQ_FOREACH(adh, &adcfg->adc_hosts, adh_next) {
+ if (adh == adhost)
+ continue;
+ if (adh->adh_remote != NULL) {
+ proto_close(adh->adh_remote);
+ adh->adh_remote = NULL;
+ }
+ }
+ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
+ if (lst->adl_conn != NULL)
+ proto_close(lst->adl_conn);
+ }
+ (void)pidfile_close(pfh);
+ pjdlog_fini();
+}
+
+static void
+child_cleanup(struct adist_host *adhost)
+{
+
+ if (adhost->adh_conn != NULL) {
+ PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER);
+ proto_close(adhost->adh_conn);
+ adhost->adh_conn = NULL;
+ }
+ adhost->adh_worker_pid = 0;
+}
+
+static void
+child_exit_log(const char *type, unsigned int pid, int status)
+{
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ pjdlog_debug(1, "%s process exited gracefully (pid=%u).",
+ type, pid);
+ } else if (WIFSIGNALED(status)) {
+ pjdlog_error("%s process killed (pid=%u, signal=%d).",
+ type, pid, WTERMSIG(status));
+ } else {
+ pjdlog_error("%s process exited ungracefully (pid=%u, exitcode=%d).",
+ type, pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1);
+ }
+}
+
+static void
+child_exit(void)
+{
+ struct adist_host *adhost;
+ bool restart;
+ int status;
+ pid_t pid;
+
+ restart = false;
+ while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
+ /* Find host related to the process that just exited. */
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (pid == adhost->adh_worker_pid)
+ break;
+ }
+ if (adhost == NULL) {
+ child_exit_log("Sandbox", pid, status);
+ } else {
+ if (adhost->adh_role == ADIST_ROLE_SENDER)
+ restart = true;
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+ child_exit_log("Worker", pid, status);
+ child_cleanup(adhost);
+ pjdlog_prefix_set("%s", "");
+ }
+ }
+ if (!restart)
+ return;
+ /* We have some sender processes to restart. */
+ sleep(1);
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role != ADIST_ROLE_SENDER)
+ continue;
+ if (adhost->adh_worker_pid != 0)
+ continue;
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+ pjdlog_info("Restarting sender process.");
+ adist_sender(adcfg, adhost);
+ pjdlog_prefix_set("%s", "");
+ }
+}
+
+/* TODO */
+static void
+adist_reload(void)
+{
+
+ pjdlog_info("Reloading configuration is not yet implemented.");
+}
+
+static void
+terminate_workers(void)
+{
+ struct adist_host *adhost;
+
+ pjdlog_info("Termination signal received, exiting.");
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_worker_pid == 0)
+ continue;
+ pjdlog_info("Terminating worker process (adhost=%s, role=%s, pid=%u).",
+ adhost->adh_name, role2str(adhost->adh_role),
+ adhost->adh_worker_pid);
+ if (kill(adhost->adh_worker_pid, SIGTERM) == 0)
+ continue;
+ pjdlog_errno(LOG_WARNING,
+ "Unable to send signal to worker process (adhost=%s, role=%s, pid=%u).",
+ adhost->adh_name, role2str(adhost->adh_role),
+ adhost->adh_worker_pid);
+ }
+}
+
+static void
+listen_accept(struct adist_listen *lst)
+{
+ unsigned char rnd[32], hash[32], resp[32];
+ struct adist_host *adhost;
+ struct proto_conn *conn;
+ char adname[ADIST_HOSTSIZE];
+ char laddr[256], raddr[256];
+ char welcome[8];
+ int status, version;
+ pid_t pid;
+
+ proto_local_address(lst->adl_conn, laddr, sizeof(laddr));
+ pjdlog_debug(1, "Accepting connection to %s.", laddr);
+
+ if (proto_accept(lst->adl_conn, &conn) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to accept connection to %s",
+ laddr);
+ return;
+ }
+
+ proto_local_address(conn, laddr, sizeof(laddr));
+ proto_remote_address(conn, raddr, sizeof(raddr));
+ pjdlog_info("Connection from %s to %s.", raddr, laddr);
+
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(conn, ADIST_TIMEOUT) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+
+ /*
+ * Before receiving any data see if remote host is known.
+ */
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role != ADIST_ROLE_RECEIVER)
+ continue;
+ if (!proto_address_match(conn, adhost->adh_remoteaddr))
+ continue;
+ break;
+ }
+ if (adhost == NULL) {
+ pjdlog_error("Client %s is not known.", raddr);
+ goto close;
+ }
+ /* Ok, remote host is known. */
+
+ /* Exchange welcome message, which include version number. */
+ bzero(welcome, sizeof(welcome));
+ if (proto_recv(conn, welcome, sizeof(welcome)) == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to receive welcome message from %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) ||
+ !isdigit(welcome[6]) || welcome[7] != '\0') {
+ pjdlog_warning("Invalid welcome message from %s.",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+
+ version = MIN(ADIST_VERSION, atoi(welcome + 5));
+
+ (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", version);
+ if (proto_send(conn, welcome, sizeof(welcome)) == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to send welcome message to %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+
+ if (proto_recv(conn, adname, sizeof(adhost->adh_name)) < 0) {
+ pjdlog_errno(LOG_ERR, "Unable to receive hostname from %s",
+ raddr);
+ goto close;
+ }
+
+ /* Find host now that we have hostname. */
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role != ADIST_ROLE_RECEIVER)
+ continue;
+ if (!proto_address_match(conn, adhost->adh_remoteaddr))
+ continue;
+ if (strcmp(adhost->adh_name, adname) != 0)
+ continue;
+ break;
+ }
+ if (adhost == NULL) {
+ pjdlog_error("No configuration for host %s from address %s.",
+ adname, raddr);
+ goto close;
+ }
+
+ adhost->adh_version = version;
+ pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version,
+ adhost->adh_remoteaddr);
+
+ /* Now that we know host name setup log prefix. */
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+
+ if (adist_random(rnd, sizeof(rnd)) == -1) {
+ pjdlog_error("Unable to generate challenge.");
+ goto close;
+ }
+ pjdlog_debug(1, "Challenge generated.");
+
+ if (proto_send(conn, rnd, sizeof(rnd)) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to send challenge to %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ pjdlog_debug(1, "Challenge sent.");
+
+ if (proto_recv(conn, resp, sizeof(resp)) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to receive response from %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ pjdlog_debug(1, "Response received.");
+
+ if (HMAC(EVP_sha256(), adhost->adh_password,
+ (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
+ NULL) == NULL) {
+ pjdlog_error("Unable to generate hash.");
+ goto close;
+ }
+ pjdlog_debug(1, "Hash generated.");
+
+ if (memcmp(resp, hash, sizeof(hash)) != 0) {
+ pjdlog_error("Invalid response from %s (wrong password?).",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ pjdlog_info("Sender authenticated.");
+
+ if (proto_recv(conn, rnd, sizeof(rnd)) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to receive challenge from %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ pjdlog_debug(1, "Challenge received.");
+
+ if (HMAC(EVP_sha256(), adhost->adh_password,
+ (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
+ NULL) == NULL) {
+ pjdlog_error("Unable to generate response.");
+ goto close;
+ }
+ pjdlog_debug(1, "Response generated.");
+
+ if (proto_send(conn, hash, sizeof(hash)) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to send response to %s",
+ adhost->adh_remoteaddr);
+ goto close;
+ }
+ pjdlog_debug(1, "Response sent.");
+
+ if (adhost->adh_worker_pid != 0) {
+ pjdlog_debug(1,
+ "Receiver process exists (pid=%u), stopping it.",
+ (unsigned int)adhost->adh_worker_pid);
+ /* Stop child process. */
+ if (kill(adhost->adh_worker_pid, SIGINT) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to stop worker process (pid=%u)",
+ (unsigned int)adhost->adh_worker_pid);
+ /*
+ * Other than logging the problem we
+ * ignore it - nothing smart to do.
+ */
+ }
+ /* Wait for it to exit. */
+ else if ((pid = waitpid(adhost->adh_worker_pid,
+ &status, 0)) != adhost->adh_worker_pid) {
+ /* We can only log the problem. */
+ pjdlog_errno(LOG_ERR,
+ "Waiting for worker process (pid=%u) failed",
+ (unsigned int)adhost->adh_worker_pid);
+ } else {
+ child_exit_log("Worker", adhost->adh_worker_pid,
+ status);
+ }
+ child_cleanup(adhost);
+ }
+
+ adhost->adh_remote = conn;
+ adist_receiver(adcfg, adhost);
+
+ pjdlog_prefix_set("%s", "");
+ return;
+close:
+ proto_close(conn);
+ pjdlog_prefix_set("%s", "");
+}
+
+static void
+connection_migrate(struct adist_host *adhost)
+{
+ struct proto_conn *conn;
+ int16_t val = 0;
+
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+
+ PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER);
+
+ if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to receive connection command");
+ return;
+ }
+ if (proto_set("tls:fingerprint", adhost->adh_fingerprint) == -1) {
+ val = errno;
+ pjdlog_errno(LOG_WARNING, "Unable to set fingerprint");
+ goto out;
+ }
+ if (proto_connect(adhost->adh_localaddr[0] != '\0' ?
+ adhost->adh_localaddr : NULL,
+ adhost->adh_remoteaddr, -1, &conn) < 0) {
+ val = errno;
+ pjdlog_errno(LOG_WARNING, "Unable to connect to %s",
+ adhost->adh_remoteaddr);
+ goto out;
+ }
+ val = 0;
+out:
+ if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to send reply to connection request");
+ }
+ if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to send connection");
+
+ pjdlog_prefix_set("%s", "");
+}
+
+static void
+check_signals(void)
+{
+ struct timespec sigtimeout;
+ sigset_t mask;
+ int signo;
+
+ sigtimeout.tv_sec = 0;
+ sigtimeout.tv_nsec = 0;
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0);
+
+ while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) {
+ switch (signo) {
+ case SIGINT:
+ case SIGTERM:
+ sigexit_received = true;
+ terminate_workers();
+ exit(EX_OK);
+ break;
+ case SIGCHLD:
+ child_exit();
+ break;
+ case SIGHUP:
+ adist_reload();
+ break;
+ default:
+ PJDLOG_ABORT("Unexpected signal (%d).", signo);
+ }
+ }
+}
+
+static void
+main_loop(void)
+{
+ struct adist_host *adhost;
+ struct adist_listen *lst;
+ struct timeval seltimeout;
+ int fd, maxfd, ret;
+ fd_set rfds;
+
+ seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL;
+ seltimeout.tv_usec = 0;
+
+ pjdlog_info("Started successfully.");
+
+ for (;;) {
+ check_signals();
+
+ /* Setup descriptors for select(2). */
+ FD_ZERO(&rfds);
+ maxfd = -1;
+ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
+ if (lst->adl_conn == NULL)
+ continue;
+ fd = proto_descriptor(lst->adl_conn);
+ PJDLOG_ASSERT(fd >= 0);
+ FD_SET(fd, &rfds);
+ maxfd = fd > maxfd ? fd : maxfd;
+ }
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role == ADIST_ROLE_SENDER) {
+ /* Only sender workers asks for connections. */
+ PJDLOG_ASSERT(adhost->adh_conn != NULL);
+ fd = proto_descriptor(adhost->adh_conn);
+ PJDLOG_ASSERT(fd >= 0);
+ FD_SET(fd, &rfds);
+ maxfd = fd > maxfd ? fd : maxfd;
+ } else {
+ PJDLOG_ASSERT(adhost->adh_conn == NULL);
+ }
+ }
+
+ PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
+ ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout);
+ if (ret == 0) {
+ /*
+ * select(2) timed out, so there should be no
+ * descriptors to check.
+ */
+ continue;
+ } else if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ KEEP_ERRNO((void)pidfile_remove(pfh));
+ pjdlog_exit(EX_OSERR, "select() failed");
+ }
+ PJDLOG_ASSERT(ret > 0);
+
+ /*
+ * Check for signals before we do anything to update our
+ * info about terminated workers in the meantime.
+ */
+ check_signals();
+
+ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
+ if (lst->adl_conn == NULL)
+ continue;
+ if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds))
+ listen_accept(lst);
+ }
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role == ADIST_ROLE_SENDER) {
+ PJDLOG_ASSERT(adhost->adh_conn != NULL);
+ if (FD_ISSET(proto_descriptor(adhost->adh_conn),
+ &rfds)) {
+ connection_migrate(adhost);
+ }
+ } else {
+ PJDLOG_ASSERT(adhost->adh_conn == NULL);
+ }
+ }
+ }
+}
+
+static void
+adist_config_dump(struct adist_config *cfg)
+{
+ struct adist_host *adhost;
+ struct adist_listen *lst;
+
+ pjdlog_debug(2, "Configuration:");
+ pjdlog_debug(2, " Global:");
+ pjdlog_debug(2, " pidfile: %s", cfg->adc_pidfile);
+ pjdlog_debug(2, " timeout: %d", cfg->adc_timeout);
+ if (TAILQ_EMPTY(&cfg->adc_listen)) {
+ pjdlog_debug(2, " Sender only, not listening.");
+ } else {
+ pjdlog_debug(2, " Listening on:");
+ TAILQ_FOREACH(lst, &cfg->adc_listen, adl_next) {
+ pjdlog_debug(2, " listen: %s", lst->adl_addr);
+ pjdlog_debug(2, " conn: %p", lst->adl_conn);
+ }
+ }
+ pjdlog_debug(2, " Hosts:");
+ TAILQ_FOREACH(adhost, &cfg->adc_hosts, adh_next) {
+ pjdlog_debug(2, " name: %s", adhost->adh_name);
+ pjdlog_debug(2, " role: %s", role2str(adhost->adh_role));
+ pjdlog_debug(2, " version: %d", adhost->adh_version);
+ pjdlog_debug(2, " localaddr: %s", adhost->adh_localaddr);
+ pjdlog_debug(2, " remoteaddr: %s", adhost->adh_remoteaddr);
+ pjdlog_debug(2, " remote: %p", adhost->adh_remote);
+ pjdlog_debug(2, " directory: %s", adhost->adh_directory);
+ pjdlog_debug(2, " compression: %d", adhost->adh_compression);
+ pjdlog_debug(2, " checksum: %d", adhost->adh_checksum);
+ pjdlog_debug(2, " pid: %ld", (long)adhost->adh_worker_pid);
+ pjdlog_debug(2, " conn: %p", adhost->adh_conn);
+ }
+}
+
+static void
+dummy_sighandler(int sig __unused)
+{
+ /* Nothing to do. */
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct adist_host *adhost;
+ struct adist_listen *lst;
+ const char *execpath, *pidfile;
+ bool foreground, launchd;
+ pid_t otherpid;
+ int debuglevel;
+ sigset_t mask;
+
+ execpath = argv[0];
+ if (execpath[0] != '/') {
+ errx(EX_USAGE,
+ "auditdistd requires execution with an absolute path.");
+ }
+
+ /*
+ * We are executed from proto to create sandbox.
+ */
+ if (argc > 1 && strcmp(argv[1], "proto") == 0) {
+ argc -= 2;
+ argv += 2;
+ if (proto_exec(argc, argv) == -1)
+ err(EX_USAGE, "Unable to execute proto");
+ }
+
+ foreground = false;
+ debuglevel = 0;
+ launchd = false;
+ pidfile = NULL;
+
+ for (;;) {
+ int ch;
+
+ ch = getopt(argc, argv, "c:dFhlP:");
+ if (ch == -1)
+ break;
+ switch (ch) {
+ case 'c':
+ cfgpath = optarg;
+ break;
+ case 'd':
+ debuglevel++;
+ break;
+ case 'F':
+ foreground = true;
+ break;
+ case 'l':
+ launchd = true;
+ break;
+ case 'P':
+ pidfile = optarg;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ pjdlog_init(PJDLOG_MODE_STD);
+ pjdlog_debug_set(debuglevel);
+
+ if (proto_set("execpath", execpath) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "Unable to set executable name");
+ if (proto_set("user", ADIST_USER) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "Unable to set proto user");
+ if (proto_set("tcp:port", ADIST_TCP_PORT) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "Unable to set default TCP port");
+
+ /*
+ * When path to the configuration file is relative, obtain full path,
+ * so we can always find the file, even after daemonizing and changing
+ * working directory to /.
+ */
+ if (cfgpath[0] != '/') {
+ const char *newcfgpath;
+
+ newcfgpath = realpath(cfgpath, NULL);
+ if (newcfgpath == NULL) {
+ pjdlog_exit(EX_CONFIG,
+ "Unable to obtain full path of %s", cfgpath);
+ }
+ cfgpath = newcfgpath;
+ }
+
+ adcfg = yy_config_parse(cfgpath, true);
+ PJDLOG_ASSERT(adcfg != NULL);
+ adist_config_dump(adcfg);
+
+ if (proto_set("tls:certfile", adcfg->adc_certfile) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "Unable to set certfile path");
+ if (proto_set("tls:keyfile", adcfg->adc_keyfile) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "Unable to set keyfile path");
+
+ if (pidfile != NULL) {
+ if (strlcpy(adcfg->adc_pidfile, pidfile,
+ sizeof(adcfg->adc_pidfile)) >=
+ sizeof(adcfg->adc_pidfile)) {
+ pjdlog_exitx(EX_CONFIG, "Pidfile path is too long.");
+ }
+ }
+ if (foreground && pidfile == NULL) {
+ pfh = NULL;
+ } else {
+ pfh = pidfile_open(adcfg->adc_pidfile, 0600, &otherpid);
+ if (pfh == NULL) {
+ if (errno == EEXIST) {
+ pjdlog_exitx(EX_TEMPFAIL,
+ "Another auditdistd is already running, pid: %jd.",
+ (intmax_t)otherpid);
+ }
+ /*
+ * If we cannot create pidfile from other reasons,
+ * only warn.
+ */
+ pjdlog_errno(LOG_WARNING,
+ "Unable to open or create pidfile %s",
+ adcfg->adc_pidfile);
+ }
+ }
+
+ /*
+ * Restore default actions for interesting signals in case parent
+ * process (like init(8)) decided to ignore some of them (like SIGHUP).
+ */
+ PJDLOG_VERIFY(signal(SIGHUP, SIG_DFL) != SIG_ERR);
+ PJDLOG_VERIFY(signal(SIGINT, SIG_DFL) != SIG_ERR);
+ PJDLOG_VERIFY(signal(SIGTERM, SIG_DFL) != SIG_ERR);
+ /*
+ * Because SIGCHLD is ignored by default, setup dummy handler for it,
+ * so we can mask it.
+ */
+ PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR);
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0);
+ PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
+
+ /* Listen for remote connections. */
+ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
+ if (proto_server(lst->adl_addr, &lst->adl_conn) == -1) {
+ KEEP_ERRNO((void)pidfile_remove(pfh));
+ pjdlog_exit(EX_OSERR, "Unable to listen on address %s",
+ lst->adl_addr);
+ }
+ }
+
+ if (!foreground) {
+ if (!launchd && daemon(0, 0) == -1) {
+ KEEP_ERRNO((void)pidfile_remove(pfh));
+ pjdlog_exit(EX_OSERR, "Unable to daemonize");
+ }
+
+ /* Start logging to syslog. */
+ pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
+ }
+ if (pfh != NULL) {
+ /* Write PID to a file. */
+ if (pidfile_write(pfh) < 0) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to write PID to a file");
+ }
+ }
+
+ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
+ if (adhost->adh_role == ADIST_ROLE_SENDER)
+ adist_sender(adcfg, adhost);
+ }
+
+ main_loop();
+
+ exit(0);
+}
diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 b/contrib/openbsm/bin/auditdistd/auditdistd.conf.5
new file mode 100644
index 0000000..c6ed2b5
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/auditdistd.conf.5
@@ -0,0 +1,364 @@
+.\" Copyright (c) 2012 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 1, 2015
+.Dt AUDITDISTD.CONF 5
+.Os
+.Sh NAME
+.Nm auditdistd.conf
+.Nd configuration file for the
+.Xr auditdistd 8
+daemon.
+.Sh DESCRIPTION
+Note: the configuration file may contain passwords.
+Care should be taken to configure proper permissions for this file
+.Li ( e.g., 0600 ) .
+.Pp
+Every line starting with
+.Li #
+gets treated as a comment and is ignored.
+.Sh CONFIGURATION FILE SYNTAX
+The general syntax of the
+.Nm
+file is as follows:
+.Bd -literal
+## Global section.
+
+# Our name.
+# The default is the first part of the hostname.
+name "<name>"
+
+# Connection timeout.
+# The default is 5.
+timeout <seconds>
+
+# Path to pidfile.
+# The default is "/var/run/auditdistd.pid".
+pidfile "<path>"
+
+sender {
+ ## Sender section.
+
+ # Source address for connections.
+ # Optional.
+ source "<addr>"
+
+ # Directory with audit trail files managed by auditdistd.
+ # The default is /var/audit/dist.
+ directory "<dir>"
+.\"
+.\" # Checksum algorithm for data sent over the wire.
+.\" # The default is none.
+.\" checksum "<algorithm>"
+.\"
+.\" # Compression algorithm for data sent over the wire.
+.\" # The default is none.
+.\" compression "<algorithm>"
+
+ # Configuration for the target system we want to send audit trail
+ # files to.
+ host "<name>" {
+ # Source address for connections.
+ # Optional.
+ source "<addr>"
+
+ # Address of the auditdistd receiver.
+ # No default. Obligatory.
+ remote "<addr>"
+
+ # Directory with audit trail files managed by auditdistd.
+ # The default is /var/audit/dist.
+ directory "<dir>"
+
+ # Fingerprint of the receiver's public key when using TLS
+ # for connections.
+ # Example fingerprint:
+ # SHA256=8F:0A:FC:8A:3D:09:80:AF:D9:AA:38:CC:8A:86:53:E6:8F:B6:1C:55:30:14:D7:F9:AA:8B:3E:73:CD:F5:76:2B
+ fingerprint "<algorithm=hash>"
+
+ # Password used to authenticate in front of the receiver.
+ password "<password>"
+.\"
+.\" # Checksum algorithm for data sent over the wire.
+.\" # The default is none.
+.\" checksum "<algorithm>"
+.\"
+.\" # Compression algorithm for data sent over the wire.
+.\" # The default is none.
+.\" compression "<algorithm>"
+ }
+
+ # Currently local audit trail files can be sent only to one remote
+ # auditdistd receiver, but this can change in the future.
+}
+
+receiver {
+ ## Receiver section.
+
+ # Address to listen on. Multiple listen addresses may be specified.
+ # The defaults are "tcp4://0.0.0.0:7878" and "tcp6://[::]:7878".
+ listen "<addr>"
+
+ # Base directory.
+ # If the directory in the host section is not absolute, it will be
+ # concatenated with this base directory.
+ # The default is "/var/audit/remote".
+ directory "<basedir>"
+
+ # Path to the receiver's certificate file.
+ # The default is "/etc/security/auditdistd.cert.pem".
+ certfile "<path>"
+
+ # Path to the receiver's private key file.
+ # The default is "/etc/security/auditdistd.key.pem".
+ keyfile "<path>"
+
+ # Configuration for a source system we want to receive audit trail
+ # files from.
+ host "<name>" {
+ # Sender address.
+ # No default. Obligatory.
+ remote "<addr>"
+
+ # Directory where to store audit trail files received
+ # from system <name>.
+ # The default is "<basedir>/<name>".
+ directory "<dir>"
+
+ # Password used by the sender to authenticate.
+ password "<password>"
+ }
+
+ # Multiple hosts to receive from can be configured.
+}
+.Ed
+.Pp
+Most of the various available configuration parameters are optional.
+If a parameter is not defined in the particular section, it will be
+inherited from the parent section if possible.
+For example, if the
+.Ic source
+parameter is not defined in the
+.Ic host
+section, it will be inherited from the
+.Ic sender
+section.
+In case the
+.Ic global
+section does not define the
+.Ic source
+parameter at all, the default value will be used.
+.Sh CONFIGURATION OPTION DESCRIPTION
+The following statements are available:
+.Bl -tag -width ".Ic xxxx"
+.It Ic name Aq name
+.Pp
+This host's name.
+It is sent to the receiver, so it can properly recognize us if there are
+multiple senders coming from the same IP address.
+.It Ic timeout Aq seconds
+.Pp
+Connection timeout in seconds.
+The default value is
+.Va 5 .
+.It Ic pidfile Aq path
+.Pp
+File in which to store the process ID of the main
+.Xr auditdistd 8
+process.
+.Pp
+The default value is
+.Pa /var/run/auditdistd.pid .
+.It Ic source Aq addr
+.Pp
+Local address to bind to before connecting to the remote
+.Nm auditdistd
+daemon.
+The format is the same as for the
+.Ic listen
+statement.
+.It Ic directory Aq path
+.Pp
+The directory where to look for audit trail files in case of sender mode, or
+the directory where to store received audit trail files.
+The provided path has to be an absolute path.
+The only exception is when the directory is provided in the
+.Ic receiver
+section; then the path provided in the
+.Ic host
+subsections can be relative to the directory in the
+.Ic receiver
+section.
+The default value is
+.Pa /var/audit/dist
+for the entire
+.Ic sender
+section,
+.Pa /var/audit/remote
+for the non-host
+.Ic receiver
+section and
+.Pa /var/audit/remote/<name>
+for the
+.Ic host
+subsections in the
+.Ic receiver
+section where
+.Aq name
+is the host's name.
+.\".It Ic checksum Aq algorithm
+.\".Pp
+.\"Checksum algorithm should be one of the following:
+.\".Bl -tag -width ".Ic sha256"
+.\".It Ic none
+.\"No checksum will be calculated for the data being sent over the network.
+.\"This is the default setting.
+.\".It Ic crc32
+.\"CRC32 checksum will be calculated.
+.\".It Ic sha256
+.\"SHA256 checksum will be calculated.
+.\".El
+.\".It Ic compression Aq algorithm
+.\".Pp
+.\"Compression algorithm should be one of the following:
+.\".Bl -tag -width ".Ic none"
+.\".It Ic none
+.\"Data sent over the network will not be compressed.
+.\"This is the default setting.
+.\".It Ic lzf
+.\"The
+.\".Nm LZF
+.\"algorithm by
+.\".An Marc Alexander Lehmann
+.\"will be used to compress the data sent over the network.
+.\".Nm LZF
+.\"is a very fast, general purpose compression algorithm.
+.\".El
+.It Ic remote Aq addr
+.Pp
+Address of the remote
+.Nm auditdistd
+daemon.
+The format is the same as for the
+.Ic listen
+statement.
+When operating in
+.Ic sender
+mode this address will be used to connect to the
+.Ic receiver .
+When operating in
+.Ic receiver
+mode only connections from this address will be accepted.
+.It Ic listen Aq addr
+.Pp
+Address to listen on in form of:
+.Bd -literal -offset indent
+protocol://protocol-specific-address
+.Ed
+.Pp
+Each of the following examples defines the same listen address:
+.Bd -literal -offset indent
+0.0.0.0
+0.0.0.0:7878
+tcp://0.0.0.0
+tcp://0.0.0.0:7878
+tcp4://0.0.0.0
+tcp4://0.0.0.0:7878
+.Ed
+.Pp
+Multiple listen addresses can be specified.
+By default
+.Nm auditdistd
+listens on
+.Pa tcp4://0.0.0.0:7878
+and
+.Pa tcp6://[::]:7878 ,
+if the kernel supports IPv4 and IPv6 respectively.
+.It Ic keyfile Aq path
+.Pp
+Path to a file that contains the private key for TLS communication.
+.It Ic certfile Aq path
+.Pp
+Path to a file that contains the certificate for TLS communication.
+.It Ic fingerprint Aq algo=hash
+.Pp
+Fingerprint of the receiver's public key.
+Currently only the SHA256 algorithm is supported.
+The certificate public key's fingerprint ready to be pasted into the
+.Nm auditdistd
+configuration file can be obtained by running:
+.Bd -literal
+# openssl x509 -in /etc/security/auditdistd.cert.pem -noout -fingerprint -sha256 | awk -F '[ =]' '{printf("%s=%s\\n", $1, $3)}'
+.Ed
+.It Ic password Aq password
+.Pp
+Password used to authenticate the sender in front of the receiver.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact
+.It Pa /etc/security/auditdistd.conf
+The default
+.Nm auditdistd
+configuration file.
+.El
+.Sh EXAMPLES
+The example configuration files can look as follows.
+.Pp
+Web server:
+.Bd -literal -offset indent
+sender {
+ host backup {
+ remote 10.0.0.4
+ }
+}
+.Ed
+.Pp
+Audit backup server:
+.Bd -literal -offset indent
+receiver {
+ host webserv {
+ remote 10.0.0.1
+ }
+ host mailserv {
+ remote 10.0.0.2
+ }
+ host dnsserv {
+ remote 10.0.0.3
+ }
+}
+.Ed
+.Sh SEE ALSO
+.Xr audit 4 ,
+.Xr auditdistd 8
+.Sh AUTHORS
+The
+.Nm auditdistd
+daemon was developed by
+.An Pawel Jakub Dawidek Aq pawel@dawidek.net
+under sponsorship of the FreeBSD Foundation.
diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.h b/contrib/openbsm/bin/auditdistd/auditdistd.h
new file mode 100644
index 0000000..d0594f2
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/auditdistd.h
@@ -0,0 +1,274 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _AUDITDISTD_H_
+#define _AUDITDISTD_H_
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+
+#include <dirent.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <compat/compat.h>
+
+#include "proto.h"
+
+/*
+ * Version history:
+ * 0 - initial version
+ */
+#define ADIST_VERSION 0
+
+#define ADIST_ROLE_UNDEF 0
+#define ADIST_ROLE_SENDER 1
+#define ADIST_ROLE_RECEIVER 2
+
+#define ADIST_USER "auditdistd"
+#define ADIST_TIMEOUT 20
+#define ADIST_CONFIG "/etc/security/auditdistd.conf"
+#define ADIST_TCP_PORT "7878"
+#define ADIST_LISTEN_TLS_TCP4 "tls://0.0.0.0:" ADIST_TCP_PORT
+#define ADIST_LISTEN_TLS_TCP6 "tls://[::]:" ADIST_TCP_PORT
+#define ADIST_PIDFILE "/var/run/auditdistd.pid"
+#define ADIST_DIRECTORY_SENDER "/var/audit/dist"
+#define ADIST_DIRECTORY_RECEIVER "/var/audit/remote"
+#define ADIST_CERTFILE "/etc/security/auditdistd.cert.pem"
+#define ADIST_KEYFILE "/etc/security/auditdistd.key.pem"
+
+#define ADIST_ERROR_WRONG_ORDER 1
+#define ADIST_ERROR_INVALID_NAME 2
+#define ADIST_ERROR_OPEN_OLD 3
+#define ADIST_ERROR_CREATE 4
+#define ADIST_ERROR_OPEN 5
+#define ADIST_ERROR_READ 6
+#define ADIST_ERROR_WRITE 7
+#define ADIST_ERROR_RENAME 8
+
+#define ADIST_ADDRSIZE 1024
+#define ADIST_HOSTSIZE 256
+#define ADIST_PATHSIZE 256
+#define ADIST_PASSWORDSIZE 128
+#define ADIST_FINGERPRINTSIZE 256
+
+/* Number of seconds to sleep between reconnect retries or keepalive packets. */
+#define ADIST_KEEPALIVE 10
+
+struct adist_listen {
+ /* Address to listen on. */
+ char adl_addr[ADIST_ADDRSIZE];
+ /* Protocol-specific data. */
+ struct proto_conn *adl_conn;
+ TAILQ_ENTRY(adist_listen) adl_next;
+};
+
+struct adist_config {
+ /* Our name. */
+ char adc_name[ADIST_HOSTSIZE];
+ /* PID file path. */
+ char adc_pidfile[PATH_MAX];
+ /* Connection timeout. */
+ int adc_timeout;
+ /* Path to receiver's certificate file. */
+ char adc_certfile[PATH_MAX];
+ /* Path to receiver's private key file. */
+ char adc_keyfile[PATH_MAX];
+ /* List of addresses to listen on. */
+ TAILQ_HEAD(, adist_listen) adc_listen;
+ /* List of hosts. */
+ TAILQ_HEAD(, adist_host) adc_hosts;
+};
+
+#define ADIST_COMPRESSION_NONE 0
+#define ADIST_COMPRESSION_LZF 1
+
+#define ADIST_CHECKSUM_NONE 0
+#define ADIST_CHECKSUM_CRC32 1
+#define ADIST_CHECKSUM_SHA256 2
+
+/*
+ * Structure that describes single host (either sender or receiver).
+ */
+struct adist_host {
+ /* Host name. */
+ char adh_name[ADIST_HOSTSIZE];
+ /* Host role: ADIST_ROLE_{SENDER,RECEIVER}. */
+ int adh_role;
+ /* Protocol version negotiated. */
+ int adh_version;
+
+ /* Local address to bind to. */
+ char adh_localaddr[ADIST_ADDRSIZE];
+ /* Address of the remote component. */
+ char adh_remoteaddr[ADIST_ADDRSIZE];
+ /* Connection with remote host. */
+ struct proto_conn *adh_remote;
+ /* Connection was reestablished, reset the state. */
+ bool adh_reset;
+
+ /*
+ * Directory from which audit trail files should be send in
+ * ADIST_ROLE_SENDER case or stored into in ADIST_ROLE_RECEIVER case.
+ */
+ char adh_directory[PATH_MAX];
+ /* Compression algorithm. Currently unused. */
+ int adh_compression;
+ /* Checksum algorithm. Currently unused. */
+ int adh_checksum;
+
+ /* Sender's password. */
+ char adh_password[ADIST_PASSWORDSIZE];
+ /* Fingerprint of receiver's public key. */
+ char adh_fingerprint[ADIST_FINGERPRINTSIZE];
+
+ /* PID of child worker process. 0 - no child. */
+ pid_t adh_worker_pid;
+ /* Connection requests from sender to main. */
+ struct proto_conn *adh_conn;
+
+ /* Receiver-specific fields. */
+ char adh_trail_name[ADIST_PATHSIZE];
+ int adh_trail_fd;
+ int adh_trail_dirfd;
+ DIR *adh_trail_dirfp;
+ /* Sender-specific fields. */
+ uint64_t adh_trail_offset;
+
+ /* Next resource. */
+ TAILQ_ENTRY(adist_host) adh_next;
+};
+
+#define ADIST_BYTEORDER_UNDEFINED 0
+#define ADIST_BYTEORDER_LITTLE_ENDIAN 1
+#define ADIST_BYTEORDER_BIG_ENDIAN 2
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define ADIST_BYTEORDER ADIST_BYTEORDER_LITTLE_ENDIAN
+#elif _BYTE_ORDER == _BIG_ENDIAN
+#define ADIST_BYTEORDER ADIST_BYTEORDER_BIG_ENDIAN
+#else
+#error Unknown byte order.
+#endif
+
+struct adpkt {
+ uint8_t adp_byteorder;
+#define ADIST_CMD_UNDEFINED 0
+#define ADIST_CMD_OPEN 1
+#define ADIST_CMD_APPEND 2
+#define ADIST_CMD_CLOSE 3
+#define ADIST_CMD_KEEPALIVE 4
+#define ADIST_CMD_ERROR 5
+ uint8_t adp_cmd;
+ uint64_t adp_seq;
+ uint32_t adp_datasize;
+ unsigned char adp_data[0];
+} __packed;
+
+struct adreq {
+ int adr_error;
+ TAILQ_ENTRY(adreq) adr_next;
+ struct adpkt adr_packet;
+};
+
+#define adr_byteorder adr_packet.adp_byteorder
+#define adr_cmd adr_packet.adp_cmd
+#define adr_seq adr_packet.adp_seq
+#define adr_datasize adr_packet.adp_datasize
+#define adr_data adr_packet.adp_data
+
+#define ADPKT_SIZE(adreq) (sizeof((adreq)->adr_packet) + (adreq)->adr_datasize)
+
+struct adrep {
+ uint8_t adrp_byteorder;
+ uint64_t adrp_seq;
+ uint16_t adrp_error;
+} __packed;
+
+#define ADIST_QUEUE_SIZE 16
+#define ADIST_BUF_SIZE 65536
+
+#define QUEUE_TAKE(adreq, list, timeout) do { \
+ mtx_lock(list##_lock); \
+ if ((timeout) == 0) { \
+ while (((adreq) = TAILQ_FIRST(list)) == NULL) \
+ cv_wait(list##_cond, list##_lock); \
+ } else { \
+ (adreq) = TAILQ_FIRST(list); \
+ if ((adreq) == NULL) { \
+ cv_timedwait(list##_cond, list##_lock, \
+ (timeout)); \
+ (adreq) = TAILQ_FIRST(list); \
+ } \
+ } \
+ if ((adreq) != NULL) \
+ TAILQ_REMOVE((list), (adreq), adr_next); \
+ mtx_unlock(list##_lock); \
+} while (0)
+#define QUEUE_INSERT(adreq, list) do { \
+ bool _wakeup; \
+ \
+ mtx_lock(list##_lock); \
+ _wakeup = TAILQ_EMPTY(list); \
+ TAILQ_INSERT_TAIL((list), (adreq), adr_next); \
+ mtx_unlock(list##_lock); \
+ if (_wakeup) \
+ cv_signal(list##_cond); \
+} while (0)
+#define QUEUE_WAIT(list) do { \
+ mtx_lock(list##_lock); \
+ while (TAILQ_EMPTY(list)) \
+ cv_wait(list##_cond, list##_lock); \
+ mtx_unlock(list##_lock); \
+} while (0)
+
+extern const char *cfgpath;
+extern bool sigexit_received;
+extern struct pidfh *pfh;
+
+void descriptors_cleanup(struct adist_host *adhost);
+void descriptors_assert(const struct adist_host *adhost, int pjdlogmode);
+
+void adist_sender(struct adist_config *config, struct adist_host *adhost);
+void adist_receiver(struct adist_config *config, struct adist_host *adhost);
+
+struct adist_config *yy_config_parse(const char *config, bool exitonerror);
+void yy_config_free(struct adist_config *config);
+
+void yyerror(const char *);
+int yylex(void);
+
+#endif /* !_AUDITDISTD_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/faccessat.h b/contrib/openbsm/bin/auditdistd/faccessat.h
new file mode 100644
index 0000000..568a6b7
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/faccessat.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _FACCESSAT_H_
+#define _FACCESSAT_H_
+
+#include <unistd.h>
+
+#define AT_EACCESS 0x01
+
+static int
+faccessat(int fd, const char *path, int mode, int flag)
+{
+ int cfd, error, ret;
+
+ if (flag == AT_EACCESS) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ cfd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cfd == -1)
+ return (-1);
+
+ if (fchdir(fd) == -1) {
+ error = errno;
+ (void)close(cfd);
+ errno = error;
+ return (-1);
+ }
+
+ ret = access(path, mode);
+
+ error = errno;
+ (void)fchdir(cfd);
+ (void)close(cfd);
+ errno = error;
+ return (ret);
+}
+
+#endif /* !_FACCESSAT_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/fstatat.h b/contrib/openbsm/bin/auditdistd/fstatat.h
new file mode 100644
index 0000000..5327a7c
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/fstatat.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _FSTATAT_H_
+#define _FSTATAT_H_
+
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#define AT_SYMLINK_NOFOLLOW 0x01
+
+static int
+fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+ int cfd, error, ret;
+
+ cfd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cfd == -1)
+ return (-1);
+
+ if (fchdir(fd) == -1) {
+ error = errno;
+ (void)close(cfd);
+ errno = error;
+ return (-1);
+ }
+
+ if (flag == AT_SYMLINK_NOFOLLOW)
+ ret = lstat(path, buf);
+ else
+ ret = stat(path, buf);
+
+ error = errno;
+ (void)fchdir(cfd);
+ (void)close(cfd);
+ errno = error;
+ return (ret);
+}
+
+#endif /* !_FSTATAT_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/openat.h b/contrib/openbsm/bin/auditdistd/openat.h
new file mode 100644
index 0000000..1d98014
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/openat.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _OPENAT_H_
+#define _OPENAT_H_
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+static int
+openat(int fd, const char *path, int flags, ...)
+{
+ int cfd, ffd, error;
+
+ cfd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cfd == -1)
+ return (-1);
+
+ if (fchdir(fd) == -1) {
+ error = errno;
+ (void)close(cfd);
+ errno = error;
+ return (-1);
+ }
+
+ if ((flags & O_CREAT) != 0) {
+ va_list ap;
+ int mode;
+
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+
+ ffd = open(path, flags, mode);
+ } else {
+ ffd = open(path, flags);
+ }
+
+ error = errno;
+ (void)fchdir(cfd);
+ (void)close(cfd);
+ errno = error;
+ return (ffd);
+}
+
+#endif /* !_OPENAT_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/parse.y b/contrib/openbsm/bin/auditdistd/parse.y
new file mode 100644
index 0000000..1f80d50
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/parse.y
@@ -0,0 +1,854 @@
+%{
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+
+extern int depth;
+extern int lineno;
+
+extern FILE *yyin;
+extern char *yytext;
+
+static struct adist_config *lconfig;
+static struct adist_host *curhost;
+#define SECTION_GLOBAL 0
+#define SECTION_SENDER 1
+#define SECTION_RECEIVER 2
+static int cursection;
+
+/* Sender section. */
+static char depth1_source[ADIST_ADDRSIZE];
+static int depth1_checksum;
+static int depth1_compression;
+/* Sender and receiver sections. */
+static char depth1_directory[PATH_MAX];
+
+static bool adjust_directory(char *path);
+static bool family_supported(int family);
+
+extern void yyrestart(FILE *);
+%}
+
+%token CB
+%token CERTFILE
+%token DIRECTORY
+%token FINGERPRINT
+%token HOST
+%token KEYFILE
+%token LISTEN
+%token NAME
+%token OB
+%token PASSWORD
+%token PIDFILE
+%token RECEIVER REMOTE
+%token SENDER SOURCE
+%token TIMEOUT
+
+/*
+%type <num> checksum_type
+%type <num> compression_type
+*/
+
+%union
+{
+ int num;
+ char *str;
+}
+
+%token <num> NUM
+%token <str> STR
+
+%%
+
+statements:
+ |
+ statements statement
+ ;
+
+statement:
+ name_statement
+ |
+ pidfile_statement
+ |
+ timeout_statement
+ |
+ sender_statement
+ |
+ receiver_statement
+ ;
+
+name_statement: NAME STR
+ {
+ PJDLOG_RASSERT(depth == 0,
+ "The name variable can only be specificed in the global section.");
+
+ if (lconfig->adc_name[0] != '\0') {
+ pjdlog_error("The name variable is specified twice.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lconfig->adc_name, $2,
+ sizeof(lconfig->adc_name)) >=
+ sizeof(lconfig->adc_name)) {
+ pjdlog_error("The name value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+pidfile_statement: PIDFILE STR
+ {
+ PJDLOG_RASSERT(depth == 0,
+ "The pidfile variable can only be specificed in the global section.");
+
+ if (lconfig->adc_pidfile[0] != '\0') {
+ pjdlog_error("The pidfile variable is specified twice.");
+ free($2);
+ return (1);
+ }
+ if (strcmp($2, "none") != 0 && $2[0] != '/') {
+ pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\".");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lconfig->adc_pidfile, $2,
+ sizeof(lconfig->adc_pidfile)) >=
+ sizeof(lconfig->adc_pidfile)) {
+ pjdlog_error("The pidfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+timeout_statement: TIMEOUT NUM
+ {
+ PJDLOG_ASSERT(depth == 0);
+
+ lconfig->adc_timeout = $2;
+ }
+ ;
+
+sender_statement: SENDER sender_start sender_entries CB
+ {
+ PJDLOG_ASSERT(depth == 0);
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ /* Configure defaults. */
+ if (depth1_checksum == -1)
+ depth1_checksum = ADIST_CHECKSUM_NONE;
+ if (depth1_compression == -1)
+ depth1_compression = ADIST_COMPRESSION_NONE;
+ if (depth1_directory[0] == '\0') {
+ (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER,
+ sizeof(depth1_directory));
+ }
+ /* Empty depth1_source is ok. */
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (curhost->adh_role != ADIST_ROLE_SENDER)
+ continue;
+ if (curhost->adh_checksum == -1)
+ curhost->adh_checksum = depth1_checksum;
+ if (curhost->adh_compression == -1)
+ curhost->adh_compression = depth1_compression;
+ if (curhost->adh_directory[0] == '\0') {
+ (void)strlcpy(curhost->adh_directory,
+ depth1_directory,
+ sizeof(curhost->adh_directory));
+ }
+ if (curhost->adh_localaddr[0] == '\0') {
+ (void)strlcpy(curhost->adh_localaddr,
+ depth1_source,
+ sizeof(curhost->adh_localaddr));
+ }
+ }
+ cursection = SECTION_GLOBAL;
+ }
+ ;
+
+sender_start: OB
+ {
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
+
+ cursection = SECTION_SENDER;
+ depth1_checksum = -1;
+ depth1_compression = -1;
+ depth1_source[0] = '\0';
+ depth1_directory[0] = '\0';
+
+#ifndef HAVE_AUDIT_SYSCALLS
+ pjdlog_error("Sender functionality is not available.");
+ return (1);
+#endif
+ }
+ ;
+
+sender_entries:
+ |
+ sender_entries sender_entry
+ ;
+
+sender_entry:
+ source_statement
+ |
+ directory_statement
+/*
+ |
+ checksum_statement
+ |
+ compression_statement
+*/
+ |
+ sender_host_statement
+ ;
+
+receiver_statement: RECEIVER receiver_start receiver_entries CB
+ {
+ PJDLOG_ASSERT(depth == 0);
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+
+ /*
+ * If not listen addresses were specified,
+ * configure default ones.
+ */
+ if (TAILQ_EMPTY(&lconfig->adc_listen)) {
+ struct adist_listen *lst;
+
+ if (family_supported(AF_INET)) {
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ return (1);
+ }
+ (void)strlcpy(lst->adl_addr,
+ ADIST_LISTEN_TLS_TCP4,
+ sizeof(lst->adl_addr));
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ } else {
+ pjdlog_debug(1,
+ "No IPv4 support in the kernel, not listening on IPv4 address.");
+ }
+ if (family_supported(AF_INET6)) {
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ return (1);
+ }
+ (void)strlcpy(lst->adl_addr,
+ ADIST_LISTEN_TLS_TCP6,
+ sizeof(lst->adl_addr));
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ } else {
+ pjdlog_debug(1,
+ "No IPv6 support in the kernel, not listening on IPv6 address.");
+ }
+ if (TAILQ_EMPTY(&lconfig->adc_listen)) {
+ pjdlog_error("No address to listen on.");
+ return (1);
+ }
+ }
+ /* Configure defaults. */
+ if (depth1_directory[0] == '\0') {
+ (void)strlcpy(depth1_directory,
+ ADIST_DIRECTORY_RECEIVER,
+ sizeof(depth1_directory));
+ }
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (curhost->adh_role != ADIST_ROLE_RECEIVER)
+ continue;
+ if (curhost->adh_directory[0] == '\0') {
+ if (snprintf(curhost->adh_directory,
+ sizeof(curhost->adh_directory), "%s/%s",
+ depth1_directory, curhost->adh_name) >=
+ (ssize_t)sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ return (1);
+ }
+ }
+ }
+ cursection = SECTION_GLOBAL;
+ }
+ ;
+
+receiver_start: OB
+ {
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
+
+ cursection = SECTION_RECEIVER;
+ depth1_directory[0] = '\0';
+ }
+ ;
+
+receiver_entries:
+ |
+ receiver_entries receiver_entry
+ ;
+
+receiver_entry:
+ listen_statement
+ |
+ directory_statement
+ |
+ certfile_statement
+ |
+ keyfile_statement
+ |
+ receiver_host_statement
+ ;
+
+/*
+checksum_statement: CHECKSUM checksum_type
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ switch (depth) {
+ case 1:
+ depth1_checksum = $2;
+ break;
+ case 2:
+ PJDLOG_ASSERT(curhost != NULL);
+ curhost->adh_checksum = $2;
+ break;
+ default:
+ PJDLOG_ABORT("checksum at wrong depth level");
+ }
+ }
+ ;
+
+checksum_type:
+ NONE { $$ = ADIST_CHECKSUM_NONE; }
+ |
+ CRC32 { $$ = ADIST_CHECKSUM_CRC32; }
+ |
+ SHA256 { $$ = ADIST_CHECKSUM_SHA256; }
+ ;
+
+compression_statement: COMPRESSION compression_type
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ switch (depth) {
+ case 1:
+ depth1_compression = $2;
+ break;
+ case 2:
+ PJDLOG_ASSERT(curhost != NULL);
+ curhost->adh_compression = $2;
+ break;
+ default:
+ PJDLOG_ABORT("compression at wrong depth level");
+ }
+ }
+ ;
+
+compression_type:
+ NONE { $$ = ADIST_COMPRESSION_NONE; }
+ |
+ LZF { $$ = ADIST_COMPRESSION_LZF; }
+ ;
+*/
+
+directory_statement: DIRECTORY STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+
+ switch (depth) {
+ case 1:
+ if (strlcpy(depth1_directory, $2,
+ sizeof(depth1_directory)) >=
+ sizeof(depth1_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ if (!adjust_directory(depth1_directory))
+ return (1);
+ break;
+ case 2:
+ if (cursection == SECTION_SENDER || $2[0] == '/') {
+ if (strlcpy(curhost->adh_directory, $2,
+ sizeof(curhost->adh_directory)) >=
+ sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ } else /* if (cursection == SECTION_RECEIVER) */ {
+ if (depth1_directory[0] == '\0') {
+ pjdlog_error("Directory path must be absolute.");
+ free($2);
+ return (1);
+ }
+ if (snprintf(curhost->adh_directory,
+ sizeof(curhost->adh_directory), "%s/%s",
+ depth1_directory, $2) >=
+ (ssize_t)sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ }
+ break;
+ default:
+ PJDLOG_ABORT("directory at wrong depth level");
+ }
+ free($2);
+ }
+ ;
+
+source_statement: SOURCE STR
+ {
+ PJDLOG_RASSERT(cursection == SECTION_SENDER,
+ "The source variable must be in sender section.");
+
+ switch (depth) {
+ case 1:
+ if (strlcpy(depth1_source, $2,
+ sizeof(depth1_source)) >=
+ sizeof(depth1_source)) {
+ pjdlog_error("Source value is too long.");
+ free($2);
+ return (1);
+ }
+ break;
+ case 2:
+ if (strlcpy(curhost->adh_localaddr, $2,
+ sizeof(curhost->adh_localaddr)) >=
+ sizeof(curhost->adh_localaddr)) {
+ pjdlog_error("Source value is too long.");
+ free($2);
+ return (1);
+ }
+ break;
+ }
+ free($2);
+ }
+ ;
+
+fingerprint_statement: FINGERPRINT STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+ PJDLOG_ASSERT(depth == 2);
+
+ if (strncasecmp($2, "SHA256=", 7) != 0) {
+ pjdlog_error("Invalid fingerprint value.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(curhost->adh_fingerprint, $2,
+ sizeof(curhost->adh_fingerprint)) >=
+ sizeof(curhost->adh_fingerprint)) {
+ pjdlog_error("Fingerprint value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+password_statement: PASSWORD STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 2);
+
+ if (strlcpy(curhost->adh_password, $2,
+ sizeof(curhost->adh_password)) >=
+ sizeof(curhost->adh_password)) {
+ pjdlog_error("Password value is too long.");
+ bzero($2, strlen($2));
+ free($2);
+ return (1);
+ }
+ bzero($2, strlen($2));
+ free($2);
+ }
+ ;
+
+certfile_statement: CERTFILE STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 1);
+
+ if (strlcpy(lconfig->adc_certfile, $2,
+ sizeof(lconfig->adc_certfile)) >=
+ sizeof(lconfig->adc_certfile)) {
+ pjdlog_error("Certfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+keyfile_statement: KEYFILE STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 1);
+
+ if (strlcpy(lconfig->adc_keyfile, $2,
+ sizeof(lconfig->adc_keyfile)) >=
+ sizeof(lconfig->adc_keyfile)) {
+ pjdlog_error("Keyfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+listen_statement: LISTEN STR
+ {
+ struct adist_listen *lst;
+
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >=
+ sizeof(lst->adl_addr)) {
+ pjdlog_error("listen argument is too long.");
+ free($2);
+ free(lst);
+ return (1);
+ }
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ free($2);
+ }
+ ;
+
+sender_host_statement: HOST host_start OB sender_host_entries CB
+ {
+ /* Put it onto host list. */
+ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
+ curhost = NULL;
+ }
+ ;
+
+receiver_host_statement: HOST host_start OB receiver_host_entries CB
+ {
+ /* Put it onto host list. */
+ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
+ curhost = NULL;
+ }
+ ;
+
+host_start: STR
+ {
+ /* Check if there is no duplicate entry. */
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (strcmp(curhost->adh_name, $1) != 0)
+ continue;
+ if (curhost->adh_role == ADIST_ROLE_SENDER &&
+ cursection == SECTION_RECEIVER) {
+ continue;
+ }
+ if (curhost->adh_role == ADIST_ROLE_RECEIVER &&
+ cursection == SECTION_SENDER) {
+ continue;
+ }
+ pjdlog_error("%s host %s is configured more than once.",
+ curhost->adh_role == ADIST_ROLE_SENDER ?
+ "Sender" : "Receiver", curhost->adh_name);
+ free($1);
+ return (1);
+ }
+
+ curhost = calloc(1, sizeof(*curhost));
+ if (curhost == NULL) {
+ pjdlog_error("Unable to allocate memory for host configuration.");
+ free($1);
+ return (1);
+ }
+ if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >=
+ sizeof(curhost->adh_name)) {
+ pjdlog_error("Host name is too long.");
+ free($1);
+ return (1);
+ }
+ free($1);
+ curhost->adh_role = cursection == SECTION_SENDER ?
+ ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER;
+ curhost->adh_version = ADIST_VERSION;
+ curhost->adh_localaddr[0] = '\0';
+ curhost->adh_remoteaddr[0] = '\0';
+ curhost->adh_remote = NULL;
+ curhost->adh_directory[0] = '\0';
+ curhost->adh_password[0] = '\0';
+ curhost->adh_fingerprint[0] = '\0';
+ curhost->adh_worker_pid = 0;
+ curhost->adh_conn = NULL;
+ }
+ ;
+
+sender_host_entries:
+ |
+ sender_host_entries sender_host_entry
+ ;
+
+sender_host_entry:
+ source_statement
+ |
+ remote_statement
+ |
+ directory_statement
+ |
+ fingerprint_statement
+ |
+ password_statement
+/*
+ |
+ checksum_statement
+ |
+ compression_statement
+*/
+ ;
+
+receiver_host_entries:
+ |
+ receiver_host_entries receiver_host_entry
+ ;
+
+receiver_host_entry:
+ remote_statement
+ |
+ directory_statement
+ |
+ password_statement
+ ;
+
+remote_statement: REMOTE STR
+ {
+ PJDLOG_ASSERT(depth == 2);
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+
+ if (strlcpy(curhost->adh_remoteaddr, $2,
+ sizeof(curhost->adh_remoteaddr)) >=
+ sizeof(curhost->adh_remoteaddr)) {
+ pjdlog_error("Remote value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+%%
+
+static bool
+family_supported(int family)
+{
+ int sock;
+
+ sock = socket(family, SOCK_STREAM, 0);
+ if (sock == -1 && errno == EPROTONOSUPPORT)
+ return (false);
+ if (sock >= 0)
+ (void)close(sock);
+ return (true);
+}
+
+static bool
+adjust_directory(char *path)
+{
+ size_t len;
+
+ len = strlen(path);
+ for (;;) {
+ if (len == 0) {
+ pjdlog_error("Directory path is empty.");
+ return (false);
+ }
+ if (path[len - 1] != '/')
+ break;
+ len--;
+ path[len] = '\0';
+ }
+ if (path[0] != '/') {
+ pjdlog_error("Directory path must be absolute.");
+ return (false);
+ }
+ return (true);
+}
+
+static int
+my_name(char *name, size_t size)
+{
+ char buf[MAXHOSTNAMELEN];
+ char *pos;
+
+ if (gethostname(buf, sizeof(buf)) < 0) {
+ pjdlog_errno(LOG_ERR, "gethostname() failed");
+ return (-1);
+ }
+
+ /* First component of the host name. */
+ pos = strchr(buf, '.');
+ if (pos == NULL)
+ (void)strlcpy(name, buf, size);
+ else
+ (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size));
+
+ if (name[0] == '\0') {
+ pjdlog_error("Empty host name.");
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+yyerror(const char *str)
+{
+
+ pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
+ lineno, yytext, str);
+}
+
+struct adist_config *
+yy_config_parse(const char *config, bool exitonerror)
+{
+ int ret;
+
+ curhost = NULL;
+ cursection = SECTION_GLOBAL;
+ depth = 0;
+ lineno = 0;
+
+ lconfig = calloc(1, sizeof(*lconfig));
+ if (lconfig == NULL) {
+ pjdlog_error("Unable to allocate memory for configuration.");
+ if (exitonerror)
+ exit(EX_TEMPFAIL);
+ return (NULL);
+ }
+ TAILQ_INIT(&lconfig->adc_hosts);
+ TAILQ_INIT(&lconfig->adc_listen);
+ lconfig->adc_name[0] = '\0';
+ lconfig->adc_timeout = -1;
+ lconfig->adc_pidfile[0] = '\0';
+ lconfig->adc_certfile[0] = '\0';
+ lconfig->adc_keyfile[0] = '\0';
+
+ yyin = fopen(config, "r");
+ if (yyin == NULL) {
+ pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
+ config);
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_OSFILE);
+ return (NULL);
+ }
+ yyrestart(yyin);
+ ret = yyparse();
+ fclose(yyin);
+ if (ret != 0) {
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_CONFIG);
+ return (NULL);
+ }
+
+ /*
+ * Let's see if everything is set up.
+ */
+ if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name,
+ sizeof(lconfig->adc_name)) == -1) {
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_CONFIG);
+ return (NULL);
+ }
+ if (lconfig->adc_timeout == -1)
+ lconfig->adc_timeout = ADIST_TIMEOUT;
+ if (lconfig->adc_pidfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE,
+ sizeof(lconfig->adc_pidfile));
+ }
+ if (lconfig->adc_certfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE,
+ sizeof(lconfig->adc_certfile));
+ }
+ if (lconfig->adc_keyfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE,
+ sizeof(lconfig->adc_keyfile));
+ }
+
+ return (lconfig);
+}
+
+void
+yy_config_free(struct adist_config *config)
+{
+ struct adist_host *adhost;
+ struct adist_listen *lst;
+
+ while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) {
+ TAILQ_REMOVE(&config->adc_listen, lst, adl_next);
+ free(lst);
+ }
+ while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) {
+ TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next);
+ bzero(adhost, sizeof(*adhost));
+ free(adhost);
+ }
+ free(config);
+}
diff --git a/contrib/openbsm/bin/auditdistd/pjdlog.c b/contrib/openbsm/bin/auditdistd/pjdlog.c
new file mode 100644
index 0000000..16f176e
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/pjdlog.c
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <errno.h>
+#ifdef __FreeBSD__
+#include <libutil.h>
+#include <printf.h>
+#endif
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "pjdlog.h"
+
+#define PJDLOG_NEVER_INITIALIZED 0
+#define PJDLOG_NOT_INITIALIZED 1
+#define PJDLOG_INITIALIZED 2
+
+static int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED;
+static int pjdlog_mode, pjdlog_debug_level;
+static char pjdlog_prefix[128];
+
+#ifdef __FreeBSD__
+static int
+pjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused,
+ size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_INT | PA_FLAG_INTMAX;
+ return (1);
+}
+
+static int
+pjdlog_printf_render_humanized_number(struct __printf_io *io,
+ const struct printf_info *pi, const void * const *arg)
+{
+ char buf[5];
+ intmax_t num;
+ int ret;
+
+ num = *(const intmax_t *)arg[0];
+ humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL);
+ ret = __printf_out(io, pi, buf, strlen(buf));
+ __printf_flush(io);
+ return (ret);
+}
+
+static int
+pjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused,
+ size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+
+static int
+pjdlog_printf_render_sockaddr(struct __printf_io *io,
+ const struct printf_info *pi, const void * const *arg)
+{
+ const struct sockaddr_storage *ss;
+ char buf[64];
+ int ret;
+
+ ss = *(const struct sockaddr_storage * const *)arg[0];
+ switch (ss->ss_family) {
+ case AF_INET:
+ {
+ char addr[INET_ADDRSTRLEN];
+ const struct sockaddr_in *sin;
+ unsigned int port;
+
+ sin = (const struct sockaddr_in *)ss;
+ port = ntohs(sin->sin_port);
+ if (inet_ntop(ss->ss_family, &sin->sin_addr, addr,
+ sizeof(addr)) == NULL) {
+ PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.",
+ strerror(errno));
+ }
+ snprintf(buf, sizeof(buf), "%s:%u", addr, port);
+ break;
+ }
+ case AF_INET6:
+ {
+ char addr[INET6_ADDRSTRLEN];
+ const struct sockaddr_in6 *sin;
+ unsigned int port;
+
+ sin = (const struct sockaddr_in6 *)ss;
+ port = ntohs(sin->sin6_port);
+ if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr,
+ sizeof(addr)) == NULL) {
+ PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.",
+ strerror(errno));
+ }
+ snprintf(buf, sizeof(buf), "[%s]:%u", addr, port);
+ break;
+ }
+ default:
+ snprintf(buf, sizeof(buf), "[unsupported family %hhu]",
+ ss->ss_family);
+ break;
+ }
+ ret = __printf_out(io, pi, buf, strlen(buf));
+ __printf_flush(io);
+ return (ret);
+}
+#endif /* __FreeBSD__ */
+
+void
+pjdlog_init(int mode)
+{
+ int saved_errno;
+
+ assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED ||
+ pjdlog_initialized == PJDLOG_NOT_INITIALIZED);
+ assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
+
+ saved_errno = errno;
+
+ if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) {
+#ifdef __FreeBSD__
+ __use_xprintf = 1;
+ register_printf_render_std("T");
+ register_printf_render('N',
+ pjdlog_printf_render_humanized_number,
+ pjdlog_printf_arginfo_humanized_number);
+ register_printf_render('S',
+ pjdlog_printf_render_sockaddr,
+ pjdlog_printf_arginfo_sockaddr);
+#endif
+ }
+
+ if (mode == PJDLOG_MODE_SYSLOG)
+ openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+ pjdlog_mode = mode;
+ pjdlog_debug_level = 0;
+ bzero(pjdlog_prefix, sizeof(pjdlog_prefix));
+
+ pjdlog_initialized = PJDLOG_INITIALIZED;
+
+ errno = saved_errno;
+}
+
+void
+pjdlog_fini(void)
+{
+ int saved_errno;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ saved_errno = errno;
+
+ if (pjdlog_mode == PJDLOG_MODE_SYSLOG)
+ closelog();
+
+ pjdlog_initialized = PJDLOG_NOT_INITIALIZED;
+
+ errno = saved_errno;
+}
+
+/*
+ * Configure where the logs should go.
+ * By default they are send to stdout/stderr, but after going into background
+ * (eg. by calling daemon(3)) application is responsible for changing mode to
+ * PJDLOG_MODE_SYSLOG, so logs will be send to syslog.
+ */
+void
+pjdlog_mode_set(int mode)
+{
+ int saved_errno;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+ assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
+
+ if (pjdlog_mode == mode)
+ return;
+
+ saved_errno = errno;
+
+ if (mode == PJDLOG_MODE_SYSLOG)
+ openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+ else /* if (mode == PJDLOG_MODE_STD) */
+ closelog();
+
+ pjdlog_mode = mode;
+
+ errno = saved_errno;
+}
+
+/*
+ * Return current mode.
+ */
+int
+pjdlog_mode_get(void)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ return (pjdlog_mode);
+}
+
+/*
+ * Set debug level. All the logs above the level specified here will be
+ * ignored.
+ */
+void
+pjdlog_debug_set(int level)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+ assert(level >= 0);
+
+ pjdlog_debug_level = level;
+}
+
+/*
+ * Return current debug level.
+ */
+int
+pjdlog_debug_get(void)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ return (pjdlog_debug_level);
+}
+
+/*
+ * Set prefix that will be used before each log.
+ * Setting prefix to NULL will remove it.
+ */
+void
+pjdlog_prefix_set(const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_prefix_set(fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Set prefix that will be used before each log.
+ * Setting prefix to NULL will remove it.
+ */
+void
+pjdlogv_prefix_set(const char *fmt, va_list ap)
+{
+ int saved_errno;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+ assert(fmt != NULL);
+
+ saved_errno = errno;
+
+ vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap);
+
+ errno = saved_errno;
+}
+
+/*
+ * Convert log level into string.
+ */
+static const char *
+pjdlog_level_string(int loglevel)
+{
+
+ switch (loglevel) {
+ case LOG_EMERG:
+ return ("EMERG");
+ case LOG_ALERT:
+ return ("ALERT");
+ case LOG_CRIT:
+ return ("CRIT");
+ case LOG_ERR:
+ return ("ERROR");
+ case LOG_WARNING:
+ return ("WARNING");
+ case LOG_NOTICE:
+ return ("NOTICE");
+ case LOG_INFO:
+ return ("INFO");
+ case LOG_DEBUG:
+ return ("DEBUG");
+ }
+ assert(!"Invalid log level.");
+ abort(); /* XXX: gcc */
+}
+
+/*
+ * Common log routine.
+ */
+void
+pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_common(loglevel, debuglevel, error, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Common log routine, which can handle regular log level as well as debug
+ * level. We decide here where to send the logs (stdout/stderr or syslog).
+ */
+void
+pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
+ va_list ap)
+{
+ int saved_errno;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+ assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
+ loglevel == LOG_CRIT || loglevel == LOG_ERR ||
+ loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
+ loglevel == LOG_INFO || loglevel == LOG_DEBUG);
+ assert(loglevel != LOG_DEBUG || debuglevel > 0);
+ assert(error >= -1);
+
+ /* Ignore debug above configured level. */
+ if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level)
+ return;
+
+ saved_errno = errno;
+
+ switch (pjdlog_mode) {
+ case PJDLOG_MODE_STD:
+ {
+ FILE *out;
+
+ /*
+ * We send errors and warning to stderr and the rest to stdout.
+ */
+ switch (loglevel) {
+ case LOG_EMERG:
+ case LOG_ALERT:
+ case LOG_CRIT:
+ case LOG_ERR:
+ case LOG_WARNING:
+ out = stderr;
+ break;
+ case LOG_NOTICE:
+ case LOG_INFO:
+ case LOG_DEBUG:
+ out = stdout;
+ break;
+ default:
+ assert(!"Invalid loglevel.");
+ abort(); /* XXX: gcc */
+ }
+
+ fprintf(out, "(%d) ", getpid());
+ fprintf(out, "[%s]", pjdlog_level_string(loglevel));
+ /* Attach debuglevel if this is debug log. */
+ if (loglevel == LOG_DEBUG)
+ fprintf(out, "[%d]", debuglevel);
+ fprintf(out, " %s", pjdlog_prefix);
+ vfprintf(out, fmt, ap);
+ if (error != -1)
+ fprintf(out, ": %s.", strerror(error));
+ fprintf(out, "\n");
+ fflush(out);
+ break;
+ }
+ case PJDLOG_MODE_SYSLOG:
+ {
+ char log[1024];
+ int len;
+
+ len = snprintf(log, sizeof(log), "%s", pjdlog_prefix);
+ if ((size_t)len < sizeof(log))
+ len += vsnprintf(log + len, sizeof(log) - len, fmt, ap);
+ if (error != -1 && (size_t)len < sizeof(log)) {
+ (void)snprintf(log + len, sizeof(log) - len, ": %s.",
+ strerror(error));
+ }
+ syslog(loglevel, "%s", log);
+ break;
+ }
+ default:
+ assert(!"Invalid mode.");
+ }
+
+ errno = saved_errno;
+}
+
+/*
+ * Regular logs.
+ */
+void
+pjdlogv(int loglevel, const char *fmt, va_list ap)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */
+ assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
+ loglevel == LOG_CRIT || loglevel == LOG_ERR ||
+ loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
+ loglevel == LOG_INFO);
+
+ pjdlogv_common(loglevel, 0, -1, fmt, ap);
+}
+
+/*
+ * Regular logs.
+ */
+void
+pjdlog(int loglevel, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv(loglevel, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Debug logs.
+ */
+void
+pjdlogv_debug(int debuglevel, const char *fmt, va_list ap)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap);
+}
+
+/*
+ * Debug logs.
+ */
+void
+pjdlog_debug(int debuglevel, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_debug(debuglevel, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Error logs with errno logging.
+ */
+void
+pjdlogv_errno(int loglevel, const char *fmt, va_list ap)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ pjdlogv_common(loglevel, 0, errno, fmt, ap);
+}
+
+/*
+ * Error logs with errno logging.
+ */
+void
+pjdlog_errno(int loglevel, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_errno(loglevel, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Log error, errno and exit.
+ */
+void
+pjdlogv_exit(int exitcode, const char *fmt, va_list ap)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ pjdlogv_errno(LOG_ERR, fmt, ap);
+ exit(exitcode);
+ /* NOTREACHED */
+}
+
+/*
+ * Log error, errno and exit.
+ */
+void
+pjdlog_exit(int exitcode, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_exit(exitcode, fmt, ap);
+ /* NOTREACHED */
+ va_end(ap);
+}
+
+/*
+ * Log error and exit.
+ */
+void
+pjdlogv_exitx(int exitcode, const char *fmt, va_list ap)
+{
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ pjdlogv(LOG_ERR, fmt, ap);
+ exit(exitcode);
+ /* NOTREACHED */
+}
+
+/*
+ * Log error and exit.
+ */
+void
+pjdlog_exitx(int exitcode, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ va_start(ap, fmt);
+ pjdlogv_exitx(exitcode, fmt, ap);
+ /* NOTREACHED */
+ va_end(ap);
+}
+
+/*
+ * Log failure message and exit.
+ */
+void
+pjdlog_abort(const char *func, const char *file, int line,
+ const char *failedexpr, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(pjdlog_initialized == PJDLOG_INITIALIZED);
+
+ /*
+ * When there is no message we pass __func__ as 'fmt'.
+ * It would be cleaner to pass NULL or "", but gcc generates a warning
+ * for both of those.
+ */
+ if (fmt != func) {
+ va_start(ap, fmt);
+ pjdlogv_critical(fmt, ap);
+ va_end(ap);
+ }
+ if (failedexpr == NULL) {
+ if (func == NULL) {
+ pjdlog_critical("Aborted at file %s, line %d.", file,
+ line);
+ } else {
+ pjdlog_critical("Aborted at function %s, file %s, line %d.",
+ func, file, line);
+ }
+ } else {
+ if (func == NULL) {
+ pjdlog_critical("Assertion failed: (%s), file %s, line %d.",
+ failedexpr, file, line);
+ } else {
+ pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.",
+ failedexpr, func, file, line);
+ }
+ }
+ abort();
+}
diff --git a/contrib/openbsm/bin/auditdistd/pjdlog.h b/contrib/openbsm/bin/auditdistd/pjdlog.h
new file mode 100644
index 0000000..d6f217f
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/pjdlog.h
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _PJDLOG_H_
+#define _PJDLOG_H_
+
+#include <sys/cdefs.h>
+
+#include <stdarg.h>
+#include <sysexits.h>
+#include <syslog.h>
+
+#include <compat/compat.h>
+
+#define PJDLOG_MODE_STD 0
+#define PJDLOG_MODE_SYSLOG 1
+
+void pjdlog_init(int mode);
+void pjdlog_fini(void);
+
+void pjdlog_mode_set(int mode);
+int pjdlog_mode_get(void);
+
+void pjdlog_debug_set(int level);
+int pjdlog_debug_get(void);
+
+void pjdlog_prefix_set(const char *fmt, ...) __printflike(1, 2);
+void pjdlogv_prefix_set(const char *fmt, va_list ap) __printflike(1, 0);
+
+void pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt,
+ ...) __printflike(4, 5);
+void pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
+ va_list ap) __printflike(4, 0);
+
+void pjdlog(int loglevel, const char *fmt, ...) __printflike(2, 3);
+void pjdlogv(int loglevel, const char *fmt, va_list ap) __printflike(2, 0);
+
+#define pjdlogv_emergency(fmt, ap) pjdlogv(LOG_EMERG, (fmt), (ap))
+#define pjdlog_emergency(...) pjdlog(LOG_EMERG, __VA_ARGS__)
+#define pjdlogv_alert(fmt, ap) pjdlogv(LOG_ALERT, (fmt), (ap))
+#define pjdlog_alert(...) pjdlog(LOG_ALERT, __VA_ARGS__)
+#define pjdlogv_critical(fmt, ap) pjdlogv(LOG_CRIT, (fmt), (ap))
+#define pjdlog_critical(...) pjdlog(LOG_CRIT, __VA_ARGS__)
+#define pjdlogv_error(fmt, ap) pjdlogv(LOG_ERR, (fmt), (ap))
+#define pjdlog_error(...) pjdlog(LOG_ERR, __VA_ARGS__)
+#define pjdlogv_warning(fmt, ap) pjdlogv(LOG_WARNING, (fmt), (ap))
+#define pjdlog_warning(...) pjdlog(LOG_WARNING, __VA_ARGS__)
+#define pjdlogv_notice(fmt, ap) pjdlogv(LOG_NOTICE, (fmt), (ap))
+#define pjdlog_notice(...) pjdlog(LOG_NOTICE, __VA_ARGS__)
+#define pjdlogv_info(fmt, ap) pjdlogv(LOG_INFO, (fmt), (ap))
+#define pjdlog_info(...) pjdlog(LOG_INFO, __VA_ARGS__)
+
+void pjdlog_debug(int debuglevel, const char *fmt, ...) __printflike(2, 3);
+void pjdlogv_debug(int debuglevel, const char *fmt, va_list ap) __printflike(2, 0);
+
+void pjdlog_errno(int loglevel, const char *fmt, ...) __printflike(2, 3);
+void pjdlogv_errno(int loglevel, const char *fmt, va_list ap) __printflike(2, 0);
+
+void pjdlog_exit(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2;
+void pjdlogv_exit(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2;
+
+void pjdlog_exitx(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2;
+void pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2;
+
+void pjdlog_abort(const char *func, const char *file, int line,
+ const char *failedexpr, const char *fmt, ...) __printflike(5, 6) __dead2;
+
+#define PJDLOG_VERIFY(expr) do { \
+ if (!(expr)) { \
+ pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \
+ "%s", __func__); \
+ } \
+} while (0)
+#define PJDLOG_RVERIFY(expr, ...) do { \
+ if (!(expr)) { \
+ pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \
+ __VA_ARGS__); \
+ } \
+} while (0)
+#define PJDLOG_ABORT(...) pjdlog_abort(__func__, __FILE__, \
+ __LINE__, NULL, __VA_ARGS__)
+#ifdef NDEBUG
+#define PJDLOG_ASSERT(expr) do { } while (0)
+#define PJDLOG_RASSERT(...) do { } while (0)
+#else
+#define PJDLOG_ASSERT(expr) PJDLOG_VERIFY(expr)
+#define PJDLOG_RASSERT(...) PJDLOG_RVERIFY(__VA_ARGS__)
+#endif
+
+#endif /* !_PJDLOG_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/proto.c b/contrib/openbsm/bin/auditdistd/proto.c
new file mode 100644
index 0000000..4e9bea0
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto.c
@@ -0,0 +1,527 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+
+#include "pjdlog.h"
+#include "proto.h"
+#include "proto_impl.h"
+
+#define PROTO_CONN_MAGIC 0x907041c
+struct proto_conn {
+ int pc_magic;
+ struct proto *pc_proto;
+ void *pc_ctx;
+ int pc_side;
+#define PROTO_SIDE_CLIENT 0
+#define PROTO_SIDE_SERVER_LISTEN 1
+#define PROTO_SIDE_SERVER_WORK 2
+};
+
+static TAILQ_HEAD(, proto) protos = TAILQ_HEAD_INITIALIZER(protos);
+
+void
+proto_register(struct proto *proto, bool isdefault)
+{
+ static bool seen_default = false;
+
+ if (!isdefault)
+ TAILQ_INSERT_HEAD(&protos, proto, prt_next);
+ else {
+ PJDLOG_ASSERT(!seen_default);
+ seen_default = true;
+ TAILQ_INSERT_TAIL(&protos, proto, prt_next);
+ }
+}
+
+static struct proto_conn *
+proto_alloc(struct proto *proto, int side)
+{
+ struct proto_conn *conn;
+
+ PJDLOG_ASSERT(proto != NULL);
+ PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT ||
+ side == PROTO_SIDE_SERVER_LISTEN ||
+ side == PROTO_SIDE_SERVER_WORK);
+
+ conn = malloc(sizeof(*conn));
+ if (conn != NULL) {
+ conn->pc_proto = proto;
+ conn->pc_side = side;
+ conn->pc_magic = PROTO_CONN_MAGIC;
+ }
+ return (conn);
+}
+
+static void
+proto_free(struct proto_conn *conn)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT ||
+ conn->pc_side == PROTO_SIDE_SERVER_LISTEN ||
+ conn->pc_side == PROTO_SIDE_SERVER_WORK);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+
+ bzero(conn, sizeof(*conn));
+ free(conn);
+}
+
+static int
+proto_common_setup(const char *srcaddr, const char *dstaddr, int timeout,
+ int side, struct proto_conn **connp)
+{
+ struct proto *proto;
+ struct proto_conn *conn;
+ void *ctx;
+ int ret;
+
+ PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT ||
+ side == PROTO_SIDE_SERVER_LISTEN);
+
+ TAILQ_FOREACH(proto, &protos, prt_next) {
+ if (side == PROTO_SIDE_CLIENT) {
+ if (proto->prt_connect == NULL) {
+ ret = -1;
+ } else {
+ ret = proto->prt_connect(srcaddr, dstaddr,
+ timeout, &ctx);
+ }
+ } else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ {
+ if (proto->prt_server == NULL)
+ ret = -1;
+ else
+ ret = proto->prt_server(dstaddr, &ctx);
+ }
+ /*
+ * ret == 0 - success
+ * ret == -1 - dstaddr is not for this protocol
+ * ret > 0 - right protocol, but an error occured
+ */
+ if (ret >= 0)
+ break;
+ }
+ if (proto == NULL) {
+ /* Unrecognized address. */
+ errno = EINVAL;
+ return (-1);
+ }
+ if (ret > 0) {
+ /* An error occured. */
+ errno = ret;
+ return (-1);
+ }
+ conn = proto_alloc(proto, side);
+ if (conn == NULL) {
+ if (proto->prt_close != NULL)
+ proto->prt_close(ctx);
+ errno = ENOMEM;
+ return (-1);
+ }
+ conn->pc_ctx = ctx;
+ *connp = conn;
+
+ return (0);
+}
+
+int
+proto_connect(const char *srcaddr, const char *dstaddr, int timeout,
+ struct proto_conn **connp)
+{
+
+ PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
+ PJDLOG_ASSERT(dstaddr != NULL);
+ PJDLOG_ASSERT(timeout >= -1);
+
+ return (proto_common_setup(srcaddr, dstaddr, timeout,
+ PROTO_SIDE_CLIENT, connp));
+}
+
+int
+proto_connect_wait(struct proto_conn *conn, int timeout)
+{
+ int error;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_connect_wait != NULL);
+ PJDLOG_ASSERT(timeout >= 0);
+
+ error = conn->pc_proto->prt_connect_wait(conn->pc_ctx, timeout);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+proto_server(const char *addr, struct proto_conn **connp)
+{
+
+ PJDLOG_ASSERT(addr != NULL);
+
+ return (proto_common_setup(NULL, addr, -1, PROTO_SIDE_SERVER_LISTEN,
+ connp));
+}
+
+int
+proto_accept(struct proto_conn *conn, struct proto_conn **newconnp)
+{
+ struct proto_conn *newconn;
+ int error;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_SERVER_LISTEN);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_accept != NULL);
+
+ newconn = proto_alloc(conn->pc_proto, PROTO_SIDE_SERVER_WORK);
+ if (newconn == NULL)
+ return (-1);
+
+ error = conn->pc_proto->prt_accept(conn->pc_ctx, &newconn->pc_ctx);
+ if (error != 0) {
+ proto_free(newconn);
+ errno = error;
+ return (-1);
+ }
+
+ *newconnp = newconn;
+
+ return (0);
+}
+
+int
+proto_send(const struct proto_conn *conn, const void *data, size_t size)
+{
+ int error;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL);
+
+ error = conn->pc_proto->prt_send(conn->pc_ctx, data, size, -1);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+proto_recv(const struct proto_conn *conn, void *data, size_t size)
+{
+ int error;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL);
+
+ error = conn->pc_proto->prt_recv(conn->pc_ctx, data, size, NULL);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn)
+{
+ const char *protoname;
+ int error, fd;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL);
+ PJDLOG_ASSERT(mconn != NULL);
+ PJDLOG_ASSERT(mconn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(mconn->pc_proto != NULL);
+ fd = proto_descriptor(mconn);
+ PJDLOG_ASSERT(fd >= 0);
+ protoname = mconn->pc_proto->prt_name;
+ PJDLOG_ASSERT(protoname != NULL);
+
+ error = conn->pc_proto->prt_send(conn->pc_ctx,
+ (const unsigned char *)protoname, strlen(protoname) + 1, fd);
+ proto_close(mconn);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+proto_wrap(const char *protoname, bool client, int fd,
+ struct proto_conn **newconnp)
+{
+ struct proto *proto;
+ struct proto_conn *newconn;
+ int error;
+
+ TAILQ_FOREACH(proto, &protos, prt_next) {
+ if (strcmp(proto->prt_name, protoname) == 0)
+ break;
+ }
+ if (proto == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ newconn = proto_alloc(proto,
+ client ? PROTO_SIDE_CLIENT : PROTO_SIDE_SERVER_WORK);
+ if (newconn == NULL)
+ return (-1);
+ PJDLOG_ASSERT(newconn->pc_proto->prt_wrap != NULL);
+ error = newconn->pc_proto->prt_wrap(fd, client, &newconn->pc_ctx);
+ if (error != 0) {
+ proto_free(newconn);
+ errno = error;
+ return (-1);
+ }
+
+ *newconnp = newconn;
+
+ return (0);
+}
+
+int
+proto_connection_recv(const struct proto_conn *conn, bool client,
+ struct proto_conn **newconnp)
+{
+ char protoname[128];
+ int error, fd;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL);
+ PJDLOG_ASSERT(newconnp != NULL);
+
+ bzero(protoname, sizeof(protoname));
+
+ error = conn->pc_proto->prt_recv(conn->pc_ctx,
+ (unsigned char *)protoname, sizeof(protoname) - 1, &fd);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+
+ PJDLOG_ASSERT(fd >= 0);
+
+ return (proto_wrap(protoname, client, fd, newconnp));
+}
+
+int
+proto_descriptor(const struct proto_conn *conn)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_descriptor != NULL);
+
+ return (conn->pc_proto->prt_descriptor(conn->pc_ctx));
+}
+
+bool
+proto_address_match(const struct proto_conn *conn, const char *addr)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_address_match != NULL);
+
+ return (conn->pc_proto->prt_address_match(conn->pc_ctx, addr));
+}
+
+void
+proto_local_address(const struct proto_conn *conn, char *addr, size_t size)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_local_address != NULL);
+
+ conn->pc_proto->prt_local_address(conn->pc_ctx, addr, size);
+}
+
+void
+proto_remote_address(const struct proto_conn *conn, char *addr, size_t size)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_remote_address != NULL);
+
+ conn->pc_proto->prt_remote_address(conn->pc_ctx, addr, size);
+}
+
+int
+proto_timeout(const struct proto_conn *conn, int timeout)
+{
+ struct timeval tv;
+ int fd;
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+
+ fd = proto_descriptor(conn);
+ if (fd < 0)
+ return (-1);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
+ return (-1);
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
+ return (-1);
+
+ return (0);
+}
+
+void
+proto_close(struct proto_conn *conn)
+{
+
+ PJDLOG_ASSERT(conn != NULL);
+ PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
+ PJDLOG_ASSERT(conn->pc_proto != NULL);
+ PJDLOG_ASSERT(conn->pc_proto->prt_close != NULL);
+
+ conn->pc_proto->prt_close(conn->pc_ctx);
+ proto_free(conn);
+}
+
+int
+proto_exec(int argc, char *argv[])
+{
+ struct proto *proto;
+ int error;
+
+ if (argc == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ TAILQ_FOREACH(proto, &protos, prt_next) {
+ if (strcmp(proto->prt_name, argv[0]) == 0)
+ break;
+ }
+ if (proto == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (proto->prt_exec == NULL) {
+ errno = EOPNOTSUPP;
+ return (-1);
+ }
+ error = proto->prt_exec(argc, argv);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ /* NOTREACHED */
+ return (0);
+}
+
+struct proto_nvpair {
+ char *pnv_name;
+ char *pnv_value;
+ TAILQ_ENTRY(proto_nvpair) pnv_next;
+};
+
+static TAILQ_HEAD(, proto_nvpair) proto_nvpairs =
+ TAILQ_HEAD_INITIALIZER(proto_nvpairs);
+
+int
+proto_set(const char *name, const char *value)
+{
+ struct proto_nvpair *pnv;
+
+ TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) {
+ if (strcmp(pnv->pnv_name, name) == 0)
+ break;
+ }
+ if (pnv != NULL) {
+ TAILQ_REMOVE(&proto_nvpairs, pnv, pnv_next);
+ free(pnv->pnv_value);
+ } else {
+ pnv = malloc(sizeof(*pnv));
+ if (pnv == NULL)
+ return (-1);
+ pnv->pnv_name = strdup(name);
+ if (pnv->pnv_name == NULL) {
+ free(pnv);
+ return (-1);
+ }
+ }
+ pnv->pnv_value = strdup(value);
+ if (pnv->pnv_value == NULL) {
+ free(pnv->pnv_name);
+ free(pnv);
+ return (-1);
+ }
+ TAILQ_INSERT_TAIL(&proto_nvpairs, pnv, pnv_next);
+ return (0);
+}
+
+const char *
+proto_get(const char *name)
+{
+ struct proto_nvpair *pnv;
+
+ TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) {
+ if (strcmp(pnv->pnv_name, name) == 0)
+ break;
+ }
+ if (pnv != NULL)
+ return (pnv->pnv_value);
+ return (NULL);
+}
diff --git a/contrib/openbsm/bin/auditdistd/proto.h b/contrib/openbsm/bin/auditdistd/proto.h
new file mode 100644
index 0000000..f26c0ad
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _PROTO_H_
+#define _PROTO_H_
+
+#include <stdbool.h> /* bool */
+#include <stdlib.h> /* size_t */
+
+struct proto_conn;
+
+int proto_connect(const char *srcaddr, const char *dstaddr, int timeout,
+ struct proto_conn **connp);
+int proto_connect_wait(struct proto_conn *conn, int timeout);
+int proto_server(const char *addr, struct proto_conn **connp);
+int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp);
+int proto_send(const struct proto_conn *conn, const void *data, size_t size);
+int proto_recv(const struct proto_conn *conn, void *data, size_t size);
+int proto_connection_send(const struct proto_conn *conn,
+ struct proto_conn *mconn);
+int proto_connection_recv(const struct proto_conn *conn, bool client,
+ struct proto_conn **newconnp);
+int proto_descriptor(const struct proto_conn *conn);
+bool proto_address_match(const struct proto_conn *conn, const char *addr);
+void proto_local_address(const struct proto_conn *conn, char *addr,
+ size_t size);
+void proto_remote_address(const struct proto_conn *conn, char *addr,
+ size_t size);
+int proto_timeout(const struct proto_conn *conn, int timeout);
+void proto_close(struct proto_conn *conn);
+int proto_exec(int argc, char *argv[]);
+int proto_set(const char *name, const char *value);
+const char *proto_get(const char *name);
+
+#endif /* !_PROTO_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/proto_common.c b/contrib/openbsm/bin/auditdistd/proto_common.c
new file mode 100644
index 0000000..acd2294
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_common.c
@@ -0,0 +1,231 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <compat/compat.h>
+
+#include "pjdlog.h"
+#include "proto_impl.h"
+
+/* Maximum size of packet we want to use when sending data. */
+#ifndef MAX_SEND_SIZE
+#define MAX_SEND_SIZE 32768
+#endif
+
+static bool
+blocking_socket(int sock)
+{
+ int flags;
+
+ flags = fcntl(sock, F_GETFL);
+ PJDLOG_ASSERT(flags >= 0);
+ return ((flags & O_NONBLOCK) == 0);
+}
+
+static int
+proto_descriptor_send(int sock, int fd)
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(fd))];
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(fd >= 0);
+
+ bzero(&msg, sizeof(msg));
+ bzero(&ctrl, sizeof(ctrl));
+
+ msg.msg_iov = NULL;
+ msg.msg_iovlen = 0;
+ msg.msg_control = ctrl;
+ msg.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd));
+
+ if (sendmsg(sock, &msg, 0) == -1)
+ return (errno);
+
+ return (0);
+}
+
+int
+proto_common_send(int sock, const unsigned char *data, size_t size, int fd)
+{
+ ssize_t done;
+ size_t sendsize;
+ int errcount = 0;
+
+ PJDLOG_ASSERT(sock >= 0);
+
+ if (data == NULL) {
+ /* The caller is just trying to decide about direction. */
+
+ PJDLOG_ASSERT(size == 0);
+
+ if (shutdown(sock, SHUT_RD) == -1)
+ return (errno);
+ return (0);
+ }
+
+ PJDLOG_ASSERT(data != NULL);
+ PJDLOG_ASSERT(size > 0);
+
+ do {
+ sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE;
+ done = send(sock, data, sendsize, MSG_NOSIGNAL);
+ if (done == 0) {
+ return (ENOTCONN);
+ } else if (done < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == ENOBUFS) {
+ /*
+ * If there are no buffers we retry.
+ * After each try we increase delay before the
+ * next one and we give up after fifteen times.
+ * This gives 11s of total wait time.
+ */
+ if (errcount == 15) {
+ pjdlog_warning("Getting ENOBUFS errors for 11s on send(), giving up.");
+ } else {
+ if (errcount == 0)
+ pjdlog_warning("Got ENOBUFS error on send(), retrying for a bit.");
+ errcount++;
+ usleep(100000 * errcount);
+ continue;
+ }
+ }
+ /*
+ * If this is blocking socket and we got EAGAIN, this
+ * means the request timed out. Translate errno to
+ * ETIMEDOUT, to give administrator a hint to
+ * eventually increase timeout.
+ */
+ if (errno == EAGAIN && blocking_socket(sock))
+ errno = ETIMEDOUT;
+ return (errno);
+ }
+ data += done;
+ size -= done;
+ } while (size > 0);
+ if (errcount > 0) {
+ pjdlog_info("Data sent successfully after %d ENOBUFS error%s.",
+ errcount, errcount == 1 ? "" : "s");
+ }
+
+ if (fd == -1)
+ return (0);
+ return (proto_descriptor_send(sock, fd));
+}
+
+static int
+proto_descriptor_recv(int sock, int *fdp)
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))];
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(fdp != NULL);
+
+ bzero(&msg, sizeof(msg));
+ bzero(&ctrl, sizeof(ctrl));
+
+ msg.msg_iov = NULL;
+ msg.msg_iovlen = 0;
+ msg.msg_control = ctrl;
+ msg.msg_controllen = sizeof(ctrl);
+
+ if (recvmsg(sock, &msg, 0) == -1)
+ return (errno);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS) {
+ return (EINVAL);
+ }
+ bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp));
+
+ return (0);
+}
+
+int
+proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp)
+{
+ ssize_t done;
+
+ PJDLOG_ASSERT(sock >= 0);
+
+ if (data == NULL) {
+ /* The caller is just trying to decide about direction. */
+
+ PJDLOG_ASSERT(size == 0);
+
+ if (shutdown(sock, SHUT_WR) == -1)
+ return (errno);
+ return (0);
+ }
+
+ PJDLOG_ASSERT(data != NULL);
+ PJDLOG_ASSERT(size > 0);
+
+ do {
+ done = recv(sock, data, size, MSG_WAITALL);
+ } while (done == -1 && errno == EINTR);
+ if (done == 0) {
+ return (ENOTCONN);
+ } else if (done < 0) {
+ /*
+ * If this is blocking socket and we got EAGAIN, this
+ * means the request timed out. Translate errno to
+ * ETIMEDOUT, to give administrator a hint to
+ * eventually increase timeout.
+ */
+ if (errno == EAGAIN && blocking_socket(sock))
+ errno = ETIMEDOUT;
+ return (errno);
+ }
+ if (fdp == NULL)
+ return (0);
+ return (proto_descriptor_recv(sock, fdp));
+}
diff --git a/contrib/openbsm/bin/auditdistd/proto_impl.h b/contrib/openbsm/bin/auditdistd/proto_impl.h
new file mode 100644
index 0000000..7915ee9
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_impl.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _PROTO_IMPL_H_
+#define _PROTO_IMPL_H_
+
+#include <sys/queue.h>
+
+#include <stdbool.h> /* bool */
+#include <stdlib.h> /* size_t */
+
+#define __constructor __attribute__((constructor))
+
+struct proto_conn;
+
+typedef int prt_connect_t(const char *, const char *, int, void **);
+typedef int prt_connect_wait_t(void *, int);
+typedef int prt_server_t(const char *, void **);
+typedef int prt_accept_t(void *, void **);
+typedef int prt_wrap_t(int, bool, void **);
+typedef int prt_send_t(void *, const unsigned char *, size_t, int);
+typedef int prt_recv_t(void *, unsigned char *, size_t, int *);
+typedef int prt_descriptor_t(const void *);
+typedef bool prt_address_match_t(const void *, const char *);
+typedef void prt_local_address_t(const void *, char *, size_t);
+typedef void prt_remote_address_t(const void *, char *, size_t);
+typedef void prt_close_t(void *);
+typedef int prt_exec_t(int, char *[]);
+
+struct proto {
+ const char *prt_name;
+ prt_connect_t *prt_connect;
+ prt_connect_wait_t *prt_connect_wait;
+ prt_server_t *prt_server;
+ prt_accept_t *prt_accept;
+ prt_wrap_t *prt_wrap;
+ prt_send_t *prt_send;
+ prt_recv_t *prt_recv;
+ prt_descriptor_t *prt_descriptor;
+ prt_address_match_t *prt_address_match;
+ prt_local_address_t *prt_local_address;
+ prt_remote_address_t *prt_remote_address;
+ prt_close_t *prt_close;
+ prt_exec_t *prt_exec;
+ TAILQ_ENTRY(proto) prt_next;
+};
+
+void proto_register(struct proto *proto, bool isdefault);
+
+int proto_wrap(const char *protoname, bool client, int fd,
+ struct proto_conn **newconnp);
+
+int proto_common_send(int sock, const unsigned char *data, size_t size, int fd);
+int proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp);
+
+#endif /* !_PROTO_IMPL_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/proto_socketpair.c b/contrib/openbsm/bin/auditdistd/proto_socketpair.c
new file mode 100644
index 0000000..fc65c76
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_socketpair.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pjdlog.h"
+#include "proto_impl.h"
+
+#define SP_CTX_MAGIC 0x50c3741
+struct sp_ctx {
+ int sp_magic;
+ int sp_fd[2];
+ int sp_side;
+#define SP_SIDE_UNDEF 0
+#define SP_SIDE_CLIENT 1
+#define SP_SIDE_SERVER 2
+};
+
+static void sp_close(void *ctx);
+
+static int
+sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
+{
+ struct sp_ctx *spctx;
+ int error;
+
+ PJDLOG_ASSERT(dstaddr != NULL);
+ PJDLOG_ASSERT(timeout >= -1);
+
+ if (strcmp(dstaddr, "socketpair://") != 0)
+ return (-1);
+
+ PJDLOG_ASSERT(srcaddr == NULL);
+
+ spctx = malloc(sizeof(*spctx));
+ if (spctx == NULL)
+ return (errno);
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) {
+ error = errno;
+ free(spctx);
+ return (error);
+ }
+
+ spctx->sp_side = SP_SIDE_UNDEF;
+ spctx->sp_magic = SP_CTX_MAGIC;
+ *ctxp = spctx;
+
+ return (0);
+}
+
+static int
+sp_wrap(int fd, bool client, void **ctxp)
+{
+ struct sp_ctx *spctx;
+
+ PJDLOG_ASSERT(fd >= 0);
+
+ spctx = malloc(sizeof(*spctx));
+ if (spctx == NULL)
+ return (errno);
+
+ if (client) {
+ spctx->sp_side = SP_SIDE_CLIENT;
+ spctx->sp_fd[0] = fd;
+ spctx->sp_fd[1] = -1;
+ } else {
+ spctx->sp_side = SP_SIDE_SERVER;
+ spctx->sp_fd[0] = -1;
+ spctx->sp_fd[1] = fd;
+ }
+ spctx->sp_magic = SP_CTX_MAGIC;
+ *ctxp = spctx;
+
+ return (0);
+}
+
+static int
+sp_send(void *ctx, const unsigned char *data, size_t size, int fd)
+{
+ struct sp_ctx *spctx = ctx;
+ int sock;
+
+ PJDLOG_ASSERT(spctx != NULL);
+ PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
+
+ switch (spctx->sp_side) {
+ case SP_SIDE_UNDEF:
+ /*
+ * If the first operation done by the caller is proto_send(),
+ * we assume this is the client.
+ */
+ /* FALLTHROUGH */
+ spctx->sp_side = SP_SIDE_CLIENT;
+ /* Close other end. */
+ close(spctx->sp_fd[1]);
+ spctx->sp_fd[1] = -1;
+ case SP_SIDE_CLIENT:
+ PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
+ sock = spctx->sp_fd[0];
+ break;
+ case SP_SIDE_SERVER:
+ PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
+ sock = spctx->sp_fd[1];
+ break;
+ default:
+ PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
+ }
+
+ /* Someone is just trying to decide about side. */
+ if (data == NULL)
+ return (0);
+
+ return (proto_common_send(sock, data, size, fd));
+}
+
+static int
+sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
+{
+ struct sp_ctx *spctx = ctx;
+ int sock;
+
+ PJDLOG_ASSERT(spctx != NULL);
+ PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
+
+ switch (spctx->sp_side) {
+ case SP_SIDE_UNDEF:
+ /*
+ * If the first operation done by the caller is proto_recv(),
+ * we assume this is the server.
+ */
+ /* FALLTHROUGH */
+ spctx->sp_side = SP_SIDE_SERVER;
+ /* Close other end. */
+ close(spctx->sp_fd[0]);
+ spctx->sp_fd[0] = -1;
+ case SP_SIDE_SERVER:
+ PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
+ sock = spctx->sp_fd[1];
+ break;
+ case SP_SIDE_CLIENT:
+ PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
+ sock = spctx->sp_fd[0];
+ break;
+ default:
+ PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
+ }
+
+ /* Someone is just trying to decide about side. */
+ if (data == NULL)
+ return (0);
+
+ return (proto_common_recv(sock, data, size, fdp));
+}
+
+static int
+sp_descriptor(const void *ctx)
+{
+ const struct sp_ctx *spctx = ctx;
+
+ PJDLOG_ASSERT(spctx != NULL);
+ PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
+ PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT ||
+ spctx->sp_side == SP_SIDE_SERVER);
+
+ switch (spctx->sp_side) {
+ case SP_SIDE_CLIENT:
+ PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
+ return (spctx->sp_fd[0]);
+ case SP_SIDE_SERVER:
+ PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
+ return (spctx->sp_fd[1]);
+ }
+
+ PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
+}
+
+static void
+sp_close(void *ctx)
+{
+ struct sp_ctx *spctx = ctx;
+
+ PJDLOG_ASSERT(spctx != NULL);
+ PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
+
+ switch (spctx->sp_side) {
+ case SP_SIDE_UNDEF:
+ PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
+ close(spctx->sp_fd[0]);
+ spctx->sp_fd[0] = -1;
+ PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
+ close(spctx->sp_fd[1]);
+ spctx->sp_fd[1] = -1;
+ break;
+ case SP_SIDE_CLIENT:
+ PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
+ close(spctx->sp_fd[0]);
+ spctx->sp_fd[0] = -1;
+ PJDLOG_ASSERT(spctx->sp_fd[1] == -1);
+ break;
+ case SP_SIDE_SERVER:
+ PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
+ close(spctx->sp_fd[1]);
+ spctx->sp_fd[1] = -1;
+ PJDLOG_ASSERT(spctx->sp_fd[0] == -1);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
+ }
+
+ spctx->sp_magic = 0;
+ free(spctx);
+}
+
+static struct proto sp_proto = {
+ .prt_name = "socketpair",
+ .prt_connect = sp_connect,
+ .prt_wrap = sp_wrap,
+ .prt_send = sp_send,
+ .prt_recv = sp_recv,
+ .prt_descriptor = sp_descriptor,
+ .prt_close = sp_close
+};
+
+static __constructor void
+sp_ctor(void)
+{
+
+ proto_register(&sp_proto, false);
+}
diff --git a/contrib/openbsm/bin/auditdistd/proto_tcp.c b/contrib/openbsm/bin/auditdistd/proto_tcp.c
new file mode 100644
index 0000000..465221d
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_tcp.c
@@ -0,0 +1,721 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h> /* MAXHOSTNAMELEN */
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "pjdlog.h"
+#include "proto_impl.h"
+#include "subr.h"
+
+#define TCP_CTX_MAGIC 0x7c41c
+struct tcp_ctx {
+ int tc_magic;
+ struct sockaddr_storage tc_sa;
+ int tc_fd;
+ int tc_side;
+#define TCP_SIDE_CLIENT 0
+#define TCP_SIDE_SERVER_LISTEN 1
+#define TCP_SIDE_SERVER_WORK 2
+ bool tc_wait_called;
+};
+
+static int tcp_connect_wait(void *ctx, int timeout);
+static void tcp_close(void *ctx);
+
+/*
+ * Function converts the given string to unsigned number.
+ */
+static int
+numfromstr(const char *str, intmax_t minnum, intmax_t maxnum, intmax_t *nump)
+{
+ intmax_t digit, num;
+
+ if (str[0] == '\0')
+ goto invalid; /* Empty string. */
+ num = 0;
+ for (; *str != '\0'; str++) {
+ if (*str < '0' || *str > '9')
+ goto invalid; /* Non-digit character. */
+ digit = *str - '0';
+ if (num > num * 10 + digit)
+ goto invalid; /* Overflow. */
+ num = num * 10 + digit;
+ if (num > maxnum)
+ goto invalid; /* Too big. */
+ }
+ if (num < minnum)
+ goto invalid; /* Too small. */
+ *nump = num;
+ return (0);
+invalid:
+ errno = EINVAL;
+ return (-1);
+}
+
+static int
+tcp_addr(const char *addr, int defport, struct sockaddr_storage *sap)
+{
+ char iporhost[MAXHOSTNAMELEN], portstr[6];
+ struct addrinfo hints;
+ struct addrinfo *res;
+ const char *pp;
+ intmax_t port;
+ size_t size;
+ int error;
+
+ if (addr == NULL)
+ return (-1);
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ if (strncasecmp(addr, "tcp4://", 7) == 0) {
+ addr += 7;
+ hints.ai_family = PF_INET;
+ } else if (strncasecmp(addr, "tcp6://", 7) == 0) {
+ addr += 7;
+ hints.ai_family = PF_INET6;
+ } else if (strncasecmp(addr, "tcp://", 6) == 0) {
+ addr += 6;
+ } else {
+ /*
+ * Because TCP is the default assume IP or host is given without
+ * prefix.
+ */
+ }
+
+ /*
+ * Extract optional port.
+ * There are three cases to consider.
+ * 1. hostname with port, eg. freefall.freebsd.org:8457
+ * 2. IPv4 address with port, eg. 192.168.0.101:8457
+ * 3. IPv6 address with port, eg. [fe80::1]:8457
+ * We discover IPv6 address by checking for two colons and if port is
+ * given, the address has to start with [.
+ */
+ pp = NULL;
+ if (strchr(addr, ':') != strrchr(addr, ':')) {
+ if (addr[0] == '[')
+ pp = strrchr(addr, ':');
+ } else {
+ pp = strrchr(addr, ':');
+ }
+ if (pp == NULL) {
+ /* Port not given, use the default. */
+ port = defport;
+ } else {
+ if (numfromstr(pp + 1, 1, 65535, &port) < 0)
+ return (errno);
+ }
+ (void)snprintf(portstr, sizeof(portstr), "%jd", (intmax_t)port);
+ /* Extract host name or IP address. */
+ if (pp == NULL) {
+ size = sizeof(iporhost);
+ if (strlcpy(iporhost, addr, size) >= size)
+ return (ENAMETOOLONG);
+ } else if (addr[0] == '[' && pp[-1] == ']') {
+ size = (size_t)(pp - addr - 2 + 1);
+ if (size > sizeof(iporhost))
+ return (ENAMETOOLONG);
+ (void)strlcpy(iporhost, addr + 1, size);
+ } else {
+ size = (size_t)(pp - addr + 1);
+ if (size > sizeof(iporhost))
+ return (ENAMETOOLONG);
+ (void)strlcpy(iporhost, addr, size);
+ }
+
+ error = getaddrinfo(iporhost, portstr, &hints, &res);
+ if (error != 0) {
+ pjdlog_debug(1, "getaddrinfo(%s, %s) failed: %s.", iporhost,
+ portstr, gai_strerror(error));
+ return (EINVAL);
+ }
+ if (res == NULL)
+ return (ENOENT);
+
+ memcpy(sap, res->ai_addr, res->ai_addrlen);
+
+ freeaddrinfo(res);
+
+ return (0);
+}
+
+static int
+tcp_setup_new(const char *addr, int side, struct tcp_ctx **tctxp)
+{
+ struct tcp_ctx *tctx;
+ int error, nodelay;
+
+ PJDLOG_ASSERT(addr != NULL);
+ PJDLOG_ASSERT(side == TCP_SIDE_CLIENT ||
+ side == TCP_SIDE_SERVER_LISTEN);
+ PJDLOG_ASSERT(tctxp != NULL);
+
+ tctx = malloc(sizeof(*tctx));
+ if (tctx == NULL)
+ return (errno);
+
+ /* Parse given address. */
+ error = tcp_addr(addr, atoi(proto_get("tcp:port")), &tctx->tc_sa);
+ if (error != 0) {
+ free(tctx);
+ return (error);
+ }
+
+ PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);
+
+ tctx->tc_fd = socket(tctx->tc_sa.ss_family, SOCK_STREAM, 0);
+ if (tctx->tc_fd == -1) {
+ error = errno;
+ free(tctx);
+ return (error);
+ }
+
+ PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);
+
+ /* Socket settings. */
+ nodelay = 1;
+ if (setsockopt(tctx->tc_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
+ sizeof(nodelay)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to set TCP_NOELAY");
+ }
+
+ tctx->tc_wait_called = (side == TCP_SIDE_CLIENT ? false : true);
+ tctx->tc_side = side;
+ tctx->tc_magic = TCP_CTX_MAGIC;
+ *tctxp = tctx;
+
+ return (0);
+}
+
+static socklen_t
+sockaddr_len(const struct sockaddr_storage *ss)
+{
+
+#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN
+ return (ss->ss_len);
+#else
+ switch (ss->ss_family) {
+ case AF_INET:
+ return (sizeof(struct sockaddr_in));
+ case AF_INET6:
+ return (sizeof(struct sockaddr_in6));
+ default:
+ PJDLOG_ABORT("Unexpected family %hhu.", ss->ss_family);
+ }
+#endif
+}
+
+static int
+tcp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
+{
+ struct tcp_ctx *tctx;
+ struct sockaddr_storage sa;
+ int error, flags, ret;
+
+ PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
+ PJDLOG_ASSERT(dstaddr != NULL);
+ PJDLOG_ASSERT(timeout >= -1);
+
+ error = tcp_setup_new(dstaddr, TCP_SIDE_CLIENT, &tctx);
+ if (error != 0)
+ return (error);
+ if (srcaddr != NULL) {
+ error = tcp_addr(srcaddr, 0, &sa);
+ if (error != 0)
+ goto fail;
+ if (bind(tctx->tc_fd, (struct sockaddr *)&sa,
+ sockaddr_len(&sa)) == -1) {
+ error = errno;
+ goto fail;
+ }
+ }
+
+ flags = fcntl(tctx->tc_fd, F_GETFL);
+ if (flags == -1) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed");
+ goto fail;
+ }
+ /*
+ * We make socket non-blocking so we can handle connection timeout
+ * manually.
+ */
+ flags |= O_NONBLOCK;
+ if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_SETFL, O_NONBLOCK) failed");
+ goto fail;
+ }
+
+ ret = connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa,
+ sockaddr_len(&tctx->tc_sa));
+ if (ret == -1 && errno != EINPROGRESS) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "connect() failed");
+ goto fail;
+ }
+
+ if (timeout >= 0) {
+ if (ret == -1) {
+ /* Connection still in progress. Wait for it. */
+ error = tcp_connect_wait(tctx, timeout);
+ if (error != 0)
+ goto fail;
+ } else {
+ /* Connection already complete. */
+ flags &= ~O_NONBLOCK;
+ if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_SETFL, ~O_NONBLOCK) failed");
+ goto fail;
+ }
+ }
+ }
+
+ *ctxp = tctx;
+ return (0);
+fail:
+ tcp_close(tctx);
+ return (error);
+}
+
+static int
+tcp_connect_wait(void *ctx, int timeout)
+{
+ struct tcp_ctx *tctx = ctx;
+ struct timeval tv;
+ fd_set fdset;
+ socklen_t esize;
+ int error, flags, ret;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+ PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT);
+ PJDLOG_ASSERT(!tctx->tc_wait_called);
+ PJDLOG_ASSERT(tctx->tc_fd >= 0);
+ PJDLOG_ASSERT(timeout >= 0);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+again:
+ FD_ZERO(&fdset);
+ FD_SET(tctx->tc_fd, &fdset);
+ ret = select(tctx->tc_fd + 1, NULL, &fdset, NULL, &tv);
+ if (ret == 0) {
+ error = ETIMEDOUT;
+ goto done;
+ } else if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "select() failed");
+ goto done;
+ }
+ PJDLOG_ASSERT(ret > 0);
+ PJDLOG_ASSERT(FD_ISSET(tctx->tc_fd, &fdset));
+ esize = sizeof(error);
+ if (getsockopt(tctx->tc_fd, SOL_SOCKET, SO_ERROR, &error,
+ &esize) == -1) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "getsockopt(SO_ERROR) failed");
+ goto done;
+ }
+ if (error != 0) {
+ pjdlog_common(LOG_DEBUG, 1, error,
+ "getsockopt(SO_ERROR) returned error");
+ goto done;
+ }
+ error = 0;
+ tctx->tc_wait_called = true;
+done:
+ flags = fcntl(tctx->tc_fd, F_GETFL);
+ if (flags == -1) {
+ if (error == 0)
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed");
+ return (error);
+ }
+ flags &= ~O_NONBLOCK;
+ if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) {
+ if (error == 0)
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_SETFL, ~O_NONBLOCK) failed");
+ }
+ return (error);
+}
+
+static int
+tcp_server(const char *addr, void **ctxp)
+{
+ struct tcp_ctx *tctx;
+ int error, val;
+
+ error = tcp_setup_new(addr, TCP_SIDE_SERVER_LISTEN, &tctx);
+ if (error != 0)
+ return (error);
+
+ val = 1;
+ /* Ignore failure. */
+ (void)setsockopt(tctx->tc_fd, SOL_SOCKET, SO_REUSEADDR, &val,
+ sizeof(val));
+
+ PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);
+
+ if (bind(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa,
+ sockaddr_len(&tctx->tc_sa)) == -1) {
+ error = errno;
+ tcp_close(tctx);
+ return (error);
+ }
+ if (listen(tctx->tc_fd, 8) == -1) {
+ error = errno;
+ tcp_close(tctx);
+ return (error);
+ }
+
+ *ctxp = tctx;
+
+ return (0);
+}
+
+static int
+tcp_accept(void *ctx, void **newctxp)
+{
+ struct tcp_ctx *tctx = ctx;
+ struct tcp_ctx *newtctx;
+ socklen_t fromlen;
+ int ret;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+ PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_SERVER_LISTEN);
+ PJDLOG_ASSERT(tctx->tc_fd >= 0);
+ PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);
+
+ newtctx = malloc(sizeof(*newtctx));
+ if (newtctx == NULL)
+ return (errno);
+
+ fromlen = sockaddr_len(&tctx->tc_sa);
+ newtctx->tc_fd = accept(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa,
+ &fromlen);
+ if (newtctx->tc_fd < 0) {
+ ret = errno;
+ free(newtctx);
+ return (ret);
+ }
+
+ newtctx->tc_wait_called = true;
+ newtctx->tc_side = TCP_SIDE_SERVER_WORK;
+ newtctx->tc_magic = TCP_CTX_MAGIC;
+ *newctxp = newtctx;
+
+ return (0);
+}
+
+static int
+tcp_wrap(int fd, bool client, void **ctxp)
+{
+ struct tcp_ctx *tctx;
+
+ PJDLOG_ASSERT(fd >= 0);
+ PJDLOG_ASSERT(ctxp != NULL);
+
+ tctx = malloc(sizeof(*tctx));
+ if (tctx == NULL)
+ return (errno);
+
+ tctx->tc_fd = fd;
+ tctx->tc_sa.ss_family = AF_UNSPEC;
+ tctx->tc_wait_called = (client ? false : true);
+ tctx->tc_side = (client ? TCP_SIDE_CLIENT : TCP_SIDE_SERVER_WORK);
+ tctx->tc_magic = TCP_CTX_MAGIC;
+ *ctxp = tctx;
+
+ return (0);
+}
+
+static int
+tcp_send(void *ctx, const unsigned char *data, size_t size, int fd)
+{
+ struct tcp_ctx *tctx = ctx;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+ PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT ||
+ tctx->tc_side == TCP_SIDE_SERVER_WORK);
+ PJDLOG_ASSERT(tctx->tc_wait_called);
+ PJDLOG_ASSERT(tctx->tc_fd >= 0);
+ PJDLOG_ASSERT(fd == -1);
+
+ return (proto_common_send(tctx->tc_fd, data, size, -1));
+}
+
+static int
+tcp_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
+{
+ struct tcp_ctx *tctx = ctx;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+ PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT ||
+ tctx->tc_side == TCP_SIDE_SERVER_WORK);
+ PJDLOG_ASSERT(tctx->tc_wait_called);
+ PJDLOG_ASSERT(tctx->tc_fd >= 0);
+ PJDLOG_ASSERT(fdp == NULL);
+
+ return (proto_common_recv(tctx->tc_fd, data, size, NULL));
+}
+
+static int
+tcp_descriptor(const void *ctx)
+{
+ const struct tcp_ctx *tctx = ctx;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+
+ return (tctx->tc_fd);
+}
+
+static bool
+tcp_address_match(const void *ctx, const char *addr)
+{
+ const struct tcp_ctx *tctx = ctx;
+ struct sockaddr_storage sa1, sa2;
+ socklen_t salen;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+
+ if (tcp_addr(addr, atoi(proto_get("tcp:port")), &sa1) != 0)
+ return (false);
+
+ salen = sizeof(sa2);
+ if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa2, &salen) < 0)
+ return (false);
+
+ if (sa1.ss_family != sa2.ss_family)
+ return (false);
+
+#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN
+ if (sa1.ss_len != sa2.ss_len)
+ return (false);
+#endif
+
+ switch (sa1.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in *)&sa1;
+ sin2 = (struct sockaddr_in *)&sa2;
+
+ return (memcmp(&sin1->sin_addr, &sin2->sin_addr,
+ sizeof(sin1->sin_addr)) == 0);
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in6 *)&sa1;
+ sin2 = (struct sockaddr_in6 *)&sa2;
+
+ return (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
+ sizeof(sin1->sin6_addr)) == 0);
+ }
+ default:
+ return (false);
+ }
+}
+
+#ifndef __FreeBSD__
+static void
+sockaddr_to_string(const void *sa, char *buf, size_t size)
+{
+ const struct sockaddr_storage *ss;
+
+ ss = (const struct sockaddr_storage * const *)sa;
+ switch (ss->ss_family) {
+ case AF_INET:
+ {
+ char addr[INET_ADDRSTRLEN];
+ const struct sockaddr_in *sin;
+ unsigned int port;
+
+ sin = (const struct sockaddr_in *)ss;
+ port = ntohs(sin->sin_port);
+ if (inet_ntop(ss->ss_family, &sin->sin_addr, addr,
+ sizeof(addr)) == NULL) {
+ PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.",
+ strerror(errno));
+ }
+ snprintf(buf, size, "%s:%u", addr, port);
+ break;
+ }
+ case AF_INET6:
+ {
+ char addr[INET6_ADDRSTRLEN];
+ const struct sockaddr_in6 *sin;
+ unsigned int port;
+
+ sin = (const struct sockaddr_in6 *)ss;
+ port = ntohs(sin->sin6_port);
+ if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr,
+ sizeof(addr)) == NULL) {
+ PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.",
+ strerror(errno));
+ }
+ snprintf(buf, size, "[%s]:%u", addr, port);
+ break;
+ }
+ default:
+ snprintf(buf, size, "[unsupported family %hhu]",
+ ss->ss_family);
+ break;
+ }
+}
+#endif /* !__FreeBSD__ */
+
+static void
+tcp_local_address(const void *ctx, char *addr, size_t size)
+{
+ const struct tcp_ctx *tctx = ctx;
+ struct sockaddr_storage sa;
+ socklen_t salen;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+
+ salen = sizeof(sa);
+ if (getsockname(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+#ifdef __FreeBSD__
+ PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size);
+#else
+ strlcpy(addr, "tcp://", size);
+ if (size > 6)
+ sockaddr_to_string(&sa, addr + 6, size - 6);
+#endif
+}
+
+static void
+tcp_remote_address(const void *ctx, char *addr, size_t size)
+{
+ const struct tcp_ctx *tctx = ctx;
+ struct sockaddr_storage sa;
+ socklen_t salen;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+
+ salen = sizeof(sa);
+ if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+#ifdef __FreeBSD__
+ PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size);
+#else
+ strlcpy(addr, "tcp://", size);
+ if (size > 6)
+ sockaddr_to_string(&sa, addr + 6, size - 6);
+#endif
+}
+
+static void
+tcp_close(void *ctx)
+{
+ struct tcp_ctx *tctx = ctx;
+
+ PJDLOG_ASSERT(tctx != NULL);
+ PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);
+
+ if (tctx->tc_fd >= 0)
+ close(tctx->tc_fd);
+ tctx->tc_magic = 0;
+ free(tctx);
+}
+
+static struct proto tcp_proto = {
+ .prt_name = "tcp",
+ .prt_connect = tcp_connect,
+ .prt_connect_wait = tcp_connect_wait,
+ .prt_server = tcp_server,
+ .prt_accept = tcp_accept,
+ .prt_wrap = tcp_wrap,
+ .prt_send = tcp_send,
+ .prt_recv = tcp_recv,
+ .prt_descriptor = tcp_descriptor,
+ .prt_address_match = tcp_address_match,
+ .prt_local_address = tcp_local_address,
+ .prt_remote_address = tcp_remote_address,
+ .prt_close = tcp_close
+};
+
+static __constructor void
+tcp_ctor(void)
+{
+
+ proto_register(&tcp_proto, true);
+}
diff --git a/contrib/openbsm/bin/auditdistd/proto_tls.c b/contrib/openbsm/bin/auditdistd/proto_tls.c
new file mode 100644
index 0000000..de89147
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_tls.c
@@ -0,0 +1,1074 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h> /* MAXHOSTNAMELEN */
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include <compat/compat.h>
+#ifndef HAVE_CLOSEFROM
+#include <compat/closefrom.h>
+#endif
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "pjdlog.h"
+#include "proto_impl.h"
+#include "sandbox.h"
+#include "subr.h"
+
+#define TLS_CTX_MAGIC 0x715c7
+struct tls_ctx {
+ int tls_magic;
+ struct proto_conn *tls_sock;
+ struct proto_conn *tls_tcp;
+ char tls_laddr[256];
+ char tls_raddr[256];
+ int tls_side;
+#define TLS_SIDE_CLIENT 0
+#define TLS_SIDE_SERVER_LISTEN 1
+#define TLS_SIDE_SERVER_WORK 2
+ bool tls_wait_called;
+};
+
+#define TLS_DEFAULT_TIMEOUT 30
+
+static int tls_connect_wait(void *ctx, int timeout);
+static void tls_close(void *ctx);
+
+static void
+block(int fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
+ flags &= ~O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
+}
+
+static void
+nonblock(int fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
+}
+
+static int
+wait_for_fd(int fd, int timeout)
+{
+ struct timeval tv;
+ fd_set fdset;
+ int error, ret;
+
+ error = 0;
+
+ for (;;) {
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ ret = select(fd + 1, NULL, &fdset, NULL,
+ timeout == -1 ? NULL : &tv);
+ if (ret == 0) {
+ error = ETIMEDOUT;
+ break;
+ } else if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ error = errno;
+ break;
+ }
+ PJDLOG_ASSERT(ret > 0);
+ PJDLOG_ASSERT(FD_ISSET(fd, &fdset));
+ break;
+ }
+
+ return (error);
+}
+
+static void
+ssl_log_errors(void)
+{
+ unsigned long error;
+
+ while ((error = ERR_get_error()) != 0)
+ pjdlog_error("SSL error: %s", ERR_error_string(error, NULL));
+}
+
+static int
+ssl_check_error(SSL *ssl, int ret)
+{
+ int error;
+
+ error = SSL_get_error(ssl, ret);
+
+ switch (error) {
+ case SSL_ERROR_NONE:
+ return (0);
+ case SSL_ERROR_WANT_READ:
+ pjdlog_debug(2, "SSL_ERROR_WANT_READ");
+ return (-1);
+ case SSL_ERROR_WANT_WRITE:
+ pjdlog_debug(2, "SSL_ERROR_WANT_WRITE");
+ return (-1);
+ case SSL_ERROR_ZERO_RETURN:
+ pjdlog_exitx(EX_OK, "Connection closed.");
+ case SSL_ERROR_SYSCALL:
+ ssl_log_errors();
+ pjdlog_exitx(EX_TEMPFAIL, "SSL I/O error.");
+ case SSL_ERROR_SSL:
+ ssl_log_errors();
+ pjdlog_exitx(EX_TEMPFAIL, "SSL protocol error.");
+ default:
+ ssl_log_errors();
+ pjdlog_exitx(EX_TEMPFAIL, "Unknown SSL error (%d).", error);
+ }
+}
+
+static void
+tcp_recv_ssl_send(int recvfd, SSL *sendssl)
+{
+ static unsigned char buf[65536];
+ ssize_t tcpdone;
+ int sendfd, ssldone;
+
+ sendfd = SSL_get_fd(sendssl);
+ PJDLOG_ASSERT(sendfd >= 0);
+ pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
+ for (;;) {
+ tcpdone = recv(recvfd, buf, sizeof(buf), 0);
+ pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone);
+ if (tcpdone == 0) {
+ pjdlog_debug(1, "Connection terminated.");
+ exit(0);
+ } else if (tcpdone == -1) {
+ if (errno == EINTR)
+ continue;
+ else if (errno == EAGAIN)
+ break;
+ pjdlog_exit(EX_TEMPFAIL, "recv() failed");
+ }
+ for (;;) {
+ ssldone = SSL_write(sendssl, buf, (int)tcpdone);
+ pjdlog_debug(2, "%s: send() returned %d", __func__,
+ ssldone);
+ if (ssl_check_error(sendssl, ssldone) == -1) {
+ (void)wait_for_fd(sendfd, -1);
+ continue;
+ }
+ PJDLOG_ASSERT(ssldone == tcpdone);
+ break;
+ }
+ }
+ pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
+}
+
+static void
+ssl_recv_tcp_send(SSL *recvssl, int sendfd)
+{
+ static unsigned char buf[65536];
+ unsigned char *ptr;
+ ssize_t tcpdone;
+ size_t todo;
+ int recvfd, ssldone;
+
+ recvfd = SSL_get_fd(recvssl);
+ PJDLOG_ASSERT(recvfd >= 0);
+ pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
+ for (;;) {
+ ssldone = SSL_read(recvssl, buf, sizeof(buf));
+ pjdlog_debug(2, "%s: SSL_read() returned %d", __func__,
+ ssldone);
+ if (ssl_check_error(recvssl, ssldone) == -1)
+ break;
+ todo = (size_t)ssldone;
+ ptr = buf;
+ do {
+ tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL);
+ pjdlog_debug(2, "%s: send() returned %zd", __func__,
+ tcpdone);
+ if (tcpdone == 0) {
+ pjdlog_debug(1, "Connection terminated.");
+ exit(0);
+ } else if (tcpdone == -1) {
+ if (errno == EINTR || errno == ENOBUFS)
+ continue;
+ if (errno == EAGAIN) {
+ (void)wait_for_fd(sendfd, -1);
+ continue;
+ }
+ pjdlog_exit(EX_TEMPFAIL, "send() failed");
+ }
+ todo -= tcpdone;
+ ptr += tcpdone;
+ } while (todo > 0);
+ }
+ pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
+}
+
+static void
+tls_loop(int sockfd, SSL *tcpssl)
+{
+ fd_set fds;
+ int maxfd, tcpfd;
+
+ tcpfd = SSL_get_fd(tcpssl);
+ PJDLOG_ASSERT(tcpfd >= 0);
+
+ for (;;) {
+ FD_ZERO(&fds);
+ FD_SET(sockfd, &fds);
+ FD_SET(tcpfd, &fds);
+ maxfd = MAX(sockfd, tcpfd);
+
+ PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
+ if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
+ if (errno == EINTR)
+ continue;
+ pjdlog_exit(EX_TEMPFAIL, "select() failed");
+ }
+ if (FD_ISSET(sockfd, &fds))
+ tcp_recv_ssl_send(sockfd, tcpssl);
+ if (FD_ISSET(tcpfd, &fds))
+ ssl_recv_tcp_send(tcpssl, sockfd);
+ }
+}
+
+static void
+tls_certificate_verify(SSL *ssl, const char *fingerprint)
+{
+ unsigned char md[EVP_MAX_MD_SIZE];
+ char mdstr[sizeof("SHA256=") - 1 + EVP_MAX_MD_SIZE * 3];
+ char *mdstrp;
+ unsigned int i, mdsize;
+ X509 *cert;
+
+ if (fingerprint[0] == '\0') {
+ pjdlog_debug(1, "No fingerprint verification requested.");
+ return;
+ }
+
+ cert = SSL_get_peer_certificate(ssl);
+ if (cert == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "No peer certificate received.");
+
+ if (X509_digest(cert, EVP_sha256(), md, &mdsize) != 1)
+ pjdlog_exitx(EX_TEMPFAIL, "X509_digest() failed.");
+ PJDLOG_ASSERT(mdsize <= EVP_MAX_MD_SIZE);
+
+ X509_free(cert);
+
+ (void)strlcpy(mdstr, "SHA256=", sizeof(mdstr));
+ mdstrp = mdstr + strlen(mdstr);
+ for (i = 0; i < mdsize; i++) {
+ PJDLOG_VERIFY(mdstrp + 3 <= mdstr + sizeof(mdstr));
+ (void)sprintf(mdstrp, "%02hhX:", md[i]);
+ mdstrp += 3;
+ }
+ /* Clear last colon. */
+ mdstrp[-1] = '\0';
+ if (strcasecmp(mdstr, fingerprint) != 0) {
+ pjdlog_exitx(EX_NOPERM,
+ "Finger print doesn't match. Received \"%s\", expected \"%s\"",
+ mdstr, fingerprint);
+ }
+}
+
+static void
+tls_exec_client(const char *user, int startfd, const char *srcaddr,
+ const char *dstaddr, const char *fingerprint, const char *defport,
+ int timeout, int debuglevel)
+{
+ struct proto_conn *tcp;
+ char *saddr, *daddr;
+ SSL_CTX *sslctx;
+ SSL *ssl;
+ long ret;
+ int sockfd, tcpfd;
+ uint8_t connected;
+
+ pjdlog_debug_set(debuglevel);
+ pjdlog_prefix_set("[TLS sandbox] (client) ");
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("[TLS sandbox] (client) ");
+#endif
+ proto_set("tcp:port", defport);
+
+ sockfd = startfd;
+
+ /* Change tls:// to tcp://. */
+ if (srcaddr == NULL) {
+ saddr = NULL;
+ } else {
+ saddr = strdup(srcaddr);
+ if (saddr == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
+ bcopy("tcp://", saddr, 6);
+ }
+ daddr = strdup(dstaddr);
+ if (daddr == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
+ bcopy("tcp://", daddr, 6);
+
+ /* Establish TCP connection. */
+ if (proto_connect(saddr, daddr, timeout, &tcp) == -1)
+ exit(EX_TEMPFAIL);
+
+ SSL_load_error_strings();
+ SSL_library_init();
+
+ /*
+ * TODO: On FreeBSD we could move this below sandbox() once libc and
+ * libcrypto use sysctl kern.arandom to obtain random data
+ * instead of /dev/urandom and friends.
+ */
+ sslctx = SSL_CTX_new(TLSv1_client_method());
+ if (sslctx == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
+
+ if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0)
+ pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client.");
+ pjdlog_debug(1, "Privileges successfully dropped.");
+
+ SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+ /* Load CA certs. */
+ /* TODO */
+ //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL);
+
+ ssl = SSL_new(sslctx);
+ if (ssl == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
+
+ tcpfd = proto_descriptor(tcp);
+
+ block(tcpfd);
+
+ if (SSL_set_fd(ssl, tcpfd) != 1)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
+
+ ret = SSL_connect(ssl);
+ ssl_check_error(ssl, (int)ret);
+
+ nonblock(sockfd);
+ nonblock(tcpfd);
+
+ tls_certificate_verify(ssl, fingerprint);
+
+ /*
+ * The following byte is send to make proto_connect_wait() to work.
+ */
+ connected = 1;
+ for (;;) {
+ switch (send(sockfd, &connected, sizeof(connected), 0)) {
+ case -1:
+ if (errno == EINTR || errno == ENOBUFS)
+ continue;
+ if (errno == EAGAIN) {
+ (void)wait_for_fd(sockfd, -1);
+ continue;
+ }
+ pjdlog_exit(EX_TEMPFAIL, "send() failed");
+ case 0:
+ pjdlog_debug(1, "Connection terminated.");
+ exit(0);
+ case 1:
+ break;
+ }
+ break;
+ }
+
+ tls_loop(sockfd, ssl);
+}
+
+static void
+tls_call_exec_client(struct proto_conn *sock, const char *srcaddr,
+ const char *dstaddr, int timeout)
+{
+ char *timeoutstr, *startfdstr, *debugstr;
+ int startfd;
+
+ /* Declare that we are receiver. */
+ proto_recv(sock, NULL, 0);
+
+ if (pjdlog_mode_get() == PJDLOG_MODE_STD)
+ startfd = 3;
+ else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
+ startfd = 0;
+
+ if (proto_descriptor(sock) != startfd) {
+ /* Move socketpair descriptor to descriptor number startfd. */
+ if (dup2(proto_descriptor(sock), startfd) == -1)
+ pjdlog_exit(EX_OSERR, "dup2() failed");
+ proto_close(sock);
+ } else {
+ /*
+ * The FD_CLOEXEC is cleared by dup2(2), so when we not
+ * call it, we have to clear it by hand in case it is set.
+ */
+ if (fcntl(startfd, F_SETFD, 0) == -1)
+ pjdlog_exit(EX_OSERR, "fcntl() failed");
+ }
+
+ closefrom(startfd + 1);
+
+ if (asprintf(&startfdstr, "%d", startfd) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
+ if (timeout == -1)
+ timeout = TLS_DEFAULT_TIMEOUT;
+ if (asprintf(&timeoutstr, "%d", timeout) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
+ if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
+
+ execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
+ proto_get("user"), "client", startfdstr,
+ srcaddr == NULL ? "" : srcaddr, dstaddr,
+ proto_get("tls:fingerprint"), proto_get("tcp:port"), timeoutstr,
+ debugstr, NULL);
+ pjdlog_exit(EX_SOFTWARE, "execl() failed");
+}
+
+static int
+tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
+{
+ struct tls_ctx *tlsctx;
+ struct proto_conn *sock;
+ pid_t pid;
+ int error;
+
+ PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
+ PJDLOG_ASSERT(dstaddr != NULL);
+ PJDLOG_ASSERT(timeout >= -1);
+ PJDLOG_ASSERT(ctxp != NULL);
+
+ if (strncmp(dstaddr, "tls://", 6) != 0)
+ return (-1);
+ if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0)
+ return (-1);
+
+ if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
+ return (errno);
+
+#if 0
+ /*
+ * We use rfork() with the following flags to disable SIGCHLD
+ * delivery upon the sandbox process exit.
+ */
+ pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0));
+#else
+ /*
+ * We don't use rfork() to be able to log information about sandbox
+ * process exiting.
+ */
+ pid = fork();
+#endif
+ switch (pid) {
+ case -1:
+ /* Failure. */
+ error = errno;
+ proto_close(sock);
+ return (error);
+ case 0:
+ /* Child. */
+ pjdlog_prefix_set("[TLS sandbox] (client) ");
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("[TLS sandbox] (client) ");
+#endif
+ tls_call_exec_client(sock, srcaddr, dstaddr, timeout);
+ /* NOTREACHED */
+ default:
+ /* Parent. */
+ tlsctx = calloc(1, sizeof(*tlsctx));
+ if (tlsctx == NULL) {
+ error = errno;
+ proto_close(sock);
+ (void)kill(pid, SIGKILL);
+ return (error);
+ }
+ proto_send(sock, NULL, 0);
+ tlsctx->tls_sock = sock;
+ tlsctx->tls_tcp = NULL;
+ tlsctx->tls_side = TLS_SIDE_CLIENT;
+ tlsctx->tls_wait_called = false;
+ tlsctx->tls_magic = TLS_CTX_MAGIC;
+ if (timeout >= 0) {
+ error = tls_connect_wait(tlsctx, timeout);
+ if (error != 0) {
+ (void)kill(pid, SIGKILL);
+ tls_close(tlsctx);
+ return (error);
+ }
+ }
+ *ctxp = tlsctx;
+ return (0);
+ }
+}
+
+static int
+tls_connect_wait(void *ctx, int timeout)
+{
+ struct tls_ctx *tlsctx = ctx;
+ int error, sockfd;
+ uint8_t connected;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT);
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+ PJDLOG_ASSERT(!tlsctx->tls_wait_called);
+ PJDLOG_ASSERT(timeout >= 0);
+
+ sockfd = proto_descriptor(tlsctx->tls_sock);
+ error = wait_for_fd(sockfd, timeout);
+ if (error != 0)
+ return (error);
+
+ for (;;) {
+ switch (recv(sockfd, &connected, sizeof(connected),
+ MSG_WAITALL)) {
+ case -1:
+ if (errno == EINTR || errno == ENOBUFS)
+ continue;
+ error = errno;
+ break;
+ case 0:
+ pjdlog_debug(1, "Connection terminated.");
+ error = ENOTCONN;
+ break;
+ case 1:
+ tlsctx->tls_wait_called = true;
+ break;
+ }
+ break;
+ }
+
+ return (error);
+}
+
+static int
+tls_server(const char *lstaddr, void **ctxp)
+{
+ struct proto_conn *tcp;
+ struct tls_ctx *tlsctx;
+ char *laddr;
+ int error;
+
+ if (strncmp(lstaddr, "tls://", 6) != 0)
+ return (-1);
+
+ tlsctx = malloc(sizeof(*tlsctx));
+ if (tlsctx == NULL) {
+ pjdlog_warning("Unable to allocate memory.");
+ return (ENOMEM);
+ }
+
+ laddr = strdup(lstaddr);
+ if (laddr == NULL) {
+ free(tlsctx);
+ pjdlog_warning("Unable to allocate memory.");
+ return (ENOMEM);
+ }
+ bcopy("tcp://", laddr, 6);
+
+ if (proto_server(laddr, &tcp) == -1) {
+ error = errno;
+ free(tlsctx);
+ free(laddr);
+ return (error);
+ }
+ free(laddr);
+
+ tlsctx->tls_sock = NULL;
+ tlsctx->tls_tcp = tcp;
+ tlsctx->tls_side = TLS_SIDE_SERVER_LISTEN;
+ tlsctx->tls_wait_called = true;
+ tlsctx->tls_magic = TLS_CTX_MAGIC;
+ *ctxp = tlsctx;
+
+ return (0);
+}
+
+static void
+tls_exec_server(const char *user, int startfd, const char *privkey,
+ const char *cert, int debuglevel)
+{
+ SSL_CTX *sslctx;
+ SSL *ssl;
+ int sockfd, tcpfd, ret;
+
+ pjdlog_debug_set(debuglevel);
+ pjdlog_prefix_set("[TLS sandbox] (server) ");
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("[TLS sandbox] (server) ");
+#endif
+
+ sockfd = startfd;
+ tcpfd = startfd + 1;
+
+ SSL_load_error_strings();
+ SSL_library_init();
+
+ sslctx = SSL_CTX_new(TLSv1_server_method());
+ if (sslctx == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
+
+ SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+ ssl = SSL_new(sslctx);
+ if (ssl == NULL)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
+
+ if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) {
+ ssl_log_errors();
+ pjdlog_exitx(EX_CONFIG,
+ "SSL_use_RSAPrivateKey_file(%s) failed.", privkey);
+ }
+
+ if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) {
+ ssl_log_errors();
+ pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.",
+ cert);
+ }
+
+ if (sandbox(user, true, "proto_tls server") != 0)
+ pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server.");
+ pjdlog_debug(1, "Privileges successfully dropped.");
+
+ nonblock(sockfd);
+ nonblock(tcpfd);
+
+ if (SSL_set_fd(ssl, tcpfd) != 1)
+ pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
+
+ ret = SSL_accept(ssl);
+ ssl_check_error(ssl, ret);
+
+ tls_loop(sockfd, ssl);
+}
+
+static void
+tls_call_exec_server(struct proto_conn *sock, struct proto_conn *tcp)
+{
+ int startfd, sockfd, tcpfd, safefd;
+ char *startfdstr, *debugstr;
+
+ if (pjdlog_mode_get() == PJDLOG_MODE_STD)
+ startfd = 3;
+ else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
+ startfd = 0;
+
+ /* Declare that we are receiver. */
+ proto_send(sock, NULL, 0);
+
+ sockfd = proto_descriptor(sock);
+ tcpfd = proto_descriptor(tcp);
+
+ safefd = MAX(sockfd, tcpfd);
+ safefd = MAX(safefd, startfd);
+ safefd++;
+
+ /* Move sockfd and tcpfd to safe numbers first. */
+ if (dup2(sockfd, safefd) == -1)
+ pjdlog_exit(EX_OSERR, "dup2() failed");
+ proto_close(sock);
+ sockfd = safefd;
+ if (dup2(tcpfd, safefd + 1) == -1)
+ pjdlog_exit(EX_OSERR, "dup2() failed");
+ proto_close(tcp);
+ tcpfd = safefd + 1;
+
+ /* Move socketpair descriptor to descriptor number startfd. */
+ if (dup2(sockfd, startfd) == -1)
+ pjdlog_exit(EX_OSERR, "dup2() failed");
+ (void)close(sockfd);
+ /* Move tcp descriptor to descriptor number startfd + 1. */
+ if (dup2(tcpfd, startfd + 1) == -1)
+ pjdlog_exit(EX_OSERR, "dup2() failed");
+ (void)close(tcpfd);
+
+ closefrom(startfd + 2);
+
+ /*
+ * Even if FD_CLOEXEC was set on descriptors before dup2(), it should
+ * have been cleared on dup2(), but better be safe than sorry.
+ */
+ if (fcntl(startfd, F_SETFD, 0) == -1)
+ pjdlog_exit(EX_OSERR, "fcntl() failed");
+ if (fcntl(startfd + 1, F_SETFD, 0) == -1)
+ pjdlog_exit(EX_OSERR, "fcntl() failed");
+
+ if (asprintf(&startfdstr, "%d", startfd) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
+ if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
+ pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
+
+ execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
+ proto_get("user"), "server", startfdstr, proto_get("tls:keyfile"),
+ proto_get("tls:certfile"), debugstr, NULL);
+ pjdlog_exit(EX_SOFTWARE, "execl() failed");
+}
+
+static int
+tls_accept(void *ctx, void **newctxp)
+{
+ struct tls_ctx *tlsctx = ctx;
+ struct tls_ctx *newtlsctx;
+ struct proto_conn *sock, *tcp;
+ pid_t pid;
+ int error;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN);
+
+ if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
+ return (errno);
+
+ /* Accept TCP connection. */
+ if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) {
+ error = errno;
+ proto_close(sock);
+ return (error);
+ }
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ /* Failure. */
+ error = errno;
+ proto_close(sock);
+ return (error);
+ case 0:
+ /* Child. */
+ pjdlog_prefix_set("[TLS sandbox] (server) ");
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("[TLS sandbox] (server) ");
+#endif
+ /* Close listen socket. */
+ proto_close(tlsctx->tls_tcp);
+ tls_call_exec_server(sock, tcp);
+ /* NOTREACHED */
+ PJDLOG_ABORT("Unreachable.");
+ default:
+ /* Parent. */
+ newtlsctx = calloc(1, sizeof(*tlsctx));
+ if (newtlsctx == NULL) {
+ error = errno;
+ proto_close(sock);
+ proto_close(tcp);
+ (void)kill(pid, SIGKILL);
+ return (error);
+ }
+ proto_local_address(tcp, newtlsctx->tls_laddr,
+ sizeof(newtlsctx->tls_laddr));
+ PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0);
+ bcopy("tls://", newtlsctx->tls_laddr, 6);
+ *strrchr(newtlsctx->tls_laddr, ':') = '\0';
+ proto_remote_address(tcp, newtlsctx->tls_raddr,
+ sizeof(newtlsctx->tls_raddr));
+ PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0);
+ bcopy("tls://", newtlsctx->tls_raddr, 6);
+ *strrchr(newtlsctx->tls_raddr, ':') = '\0';
+ proto_close(tcp);
+ proto_recv(sock, NULL, 0);
+ newtlsctx->tls_sock = sock;
+ newtlsctx->tls_tcp = NULL;
+ newtlsctx->tls_wait_called = true;
+ newtlsctx->tls_side = TLS_SIDE_SERVER_WORK;
+ newtlsctx->tls_magic = TLS_CTX_MAGIC;
+ *newctxp = newtlsctx;
+ return (0);
+ }
+}
+
+static int
+tls_wrap(int fd, bool client, void **ctxp)
+{
+ struct tls_ctx *tlsctx;
+ struct proto_conn *sock;
+ int error;
+
+ tlsctx = calloc(1, sizeof(*tlsctx));
+ if (tlsctx == NULL)
+ return (errno);
+
+ if (proto_wrap("socketpair", client, fd, &sock) == -1) {
+ error = errno;
+ free(tlsctx);
+ return (error);
+ }
+
+ tlsctx->tls_sock = sock;
+ tlsctx->tls_tcp = NULL;
+ tlsctx->tls_wait_called = (client ? false : true);
+ tlsctx->tls_side = (client ? TLS_SIDE_CLIENT : TLS_SIDE_SERVER_WORK);
+ tlsctx->tls_magic = TLS_CTX_MAGIC;
+ *ctxp = tlsctx;
+
+ return (0);
+}
+
+static int
+tls_send(void *ctx, const unsigned char *data, size_t size, int fd)
+{
+ struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
+ tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_wait_called);
+ PJDLOG_ASSERT(fd == -1);
+
+ if (proto_send(tlsctx->tls_sock, data, size) == -1)
+ return (errno);
+
+ return (0);
+}
+
+static int
+tls_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
+{
+ struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
+ tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_wait_called);
+ PJDLOG_ASSERT(fdp == NULL);
+
+ if (proto_recv(tlsctx->tls_sock, data, size) == -1)
+ return (errno);
+
+ return (0);
+}
+
+static int
+tls_descriptor(const void *ctx)
+{
+ const struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+
+ switch (tlsctx->tls_side) {
+ case TLS_SIDE_CLIENT:
+ case TLS_SIDE_SERVER_WORK:
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+
+ return (proto_descriptor(tlsctx->tls_sock));
+ case TLS_SIDE_SERVER_LISTEN:
+ PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
+
+ return (proto_descriptor(tlsctx->tls_tcp));
+ default:
+ PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
+ }
+}
+
+static bool
+tcp_address_match(const void *ctx, const char *addr)
+{
+ const struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+
+ return (strcmp(tlsctx->tls_raddr, addr) == 0);
+}
+
+static void
+tls_local_address(const void *ctx, char *addr, size_t size)
+{
+ const struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_wait_called);
+
+ switch (tlsctx->tls_side) {
+ case TLS_SIDE_CLIENT:
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+
+ PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
+ break;
+ case TLS_SIDE_SERVER_WORK:
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+
+ PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_laddr, size) < size);
+ break;
+ case TLS_SIDE_SERVER_LISTEN:
+ PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
+
+ proto_local_address(tlsctx->tls_tcp, addr, size);
+ PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
+ /* Replace tcp:// prefix with tls:// */
+ bcopy("tls://", addr, 6);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
+ }
+}
+
+static void
+tls_remote_address(const void *ctx, char *addr, size_t size)
+{
+ const struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+ PJDLOG_ASSERT(tlsctx->tls_wait_called);
+
+ switch (tlsctx->tls_side) {
+ case TLS_SIDE_CLIENT:
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+
+ PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
+ break;
+ case TLS_SIDE_SERVER_WORK:
+ PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
+
+ PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size);
+ break;
+ case TLS_SIDE_SERVER_LISTEN:
+ PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
+
+ proto_remote_address(tlsctx->tls_tcp, addr, size);
+ PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
+ /* Replace tcp:// prefix with tls:// */
+ bcopy("tls://", addr, 6);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
+ }
+}
+
+static void
+tls_close(void *ctx)
+{
+ struct tls_ctx *tlsctx = ctx;
+
+ PJDLOG_ASSERT(tlsctx != NULL);
+ PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
+
+ if (tlsctx->tls_sock != NULL) {
+ proto_close(tlsctx->tls_sock);
+ tlsctx->tls_sock = NULL;
+ }
+ if (tlsctx->tls_tcp != NULL) {
+ proto_close(tlsctx->tls_tcp);
+ tlsctx->tls_tcp = NULL;
+ }
+ tlsctx->tls_side = 0;
+ tlsctx->tls_magic = 0;
+ free(tlsctx);
+}
+
+static int
+tls_exec(int argc, char *argv[])
+{
+
+ PJDLOG_ASSERT(argc > 3);
+ PJDLOG_ASSERT(strcmp(argv[0], "tls") == 0);
+
+ pjdlog_init(atoi(argv[3]) == 0 ? PJDLOG_MODE_SYSLOG : PJDLOG_MODE_STD);
+
+ if (strcmp(argv[2], "client") == 0) {
+ if (argc != 10)
+ return (EINVAL);
+ tls_exec_client(argv[1], atoi(argv[3]),
+ argv[4][0] == '\0' ? NULL : argv[4], argv[5], argv[6],
+ argv[7], atoi(argv[8]), atoi(argv[9]));
+ } else if (strcmp(argv[2], "server") == 0) {
+ if (argc != 7)
+ return (EINVAL);
+ tls_exec_server(argv[1], atoi(argv[3]), argv[4], argv[5],
+ atoi(argv[6]));
+ }
+ return (EINVAL);
+}
+
+static struct proto tls_proto = {
+ .prt_name = "tls",
+ .prt_connect = tls_connect,
+ .prt_connect_wait = tls_connect_wait,
+ .prt_server = tls_server,
+ .prt_accept = tls_accept,
+ .prt_wrap = tls_wrap,
+ .prt_send = tls_send,
+ .prt_recv = tls_recv,
+ .prt_descriptor = tls_descriptor,
+ .prt_address_match = tcp_address_match,
+ .prt_local_address = tls_local_address,
+ .prt_remote_address = tls_remote_address,
+ .prt_close = tls_close,
+ .prt_exec = tls_exec
+};
+
+static __constructor void
+tls_ctor(void)
+{
+
+ proto_register(&tls_proto, false);
+}
diff --git a/contrib/openbsm/bin/auditdistd/proto_uds.c b/contrib/openbsm/bin/auditdistd/proto_uds.c
new file mode 100644
index 0000000..3168bbf
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/proto_uds.c
@@ -0,0 +1,360 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+/* UDS - UNIX Domain Socket */
+
+#include <config/config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "pjdlog.h"
+#include "proto_impl.h"
+
+#define UDS_CTX_MAGIC 0xd541c
+struct uds_ctx {
+ int uc_magic;
+ struct sockaddr_un uc_sun;
+ int uc_fd;
+ int uc_side;
+#define UDS_SIDE_CLIENT 0
+#define UDS_SIDE_SERVER_LISTEN 1
+#define UDS_SIDE_SERVER_WORK 2
+ pid_t uc_owner;
+};
+
+static void uds_close(void *ctx);
+
+static int
+uds_addr(const char *addr, struct sockaddr_un *sunp)
+{
+
+ if (addr == NULL)
+ return (-1);
+
+ if (strncasecmp(addr, "uds://", 6) == 0)
+ addr += 6;
+ else if (strncasecmp(addr, "unix://", 7) == 0)
+ addr += 7;
+ else if (addr[0] == '/' && /* If it starts from /... */
+ strstr(addr, "://") == NULL)/* ...and there is no prefix... */
+ ; /* ...we assume its us. */
+ else
+ return (-1);
+
+ sunp->sun_family = AF_UNIX;
+ if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >=
+ sizeof(sunp->sun_path)) {
+ return (ENAMETOOLONG);
+ }
+#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN
+ sunp->sun_len = SUN_LEN(sunp);
+#endif
+
+ return (0);
+}
+
+static int
+uds_common_setup(const char *addr, int side, struct uds_ctx **uctxp)
+{
+ struct uds_ctx *uctx;
+ int error;
+
+ uctx = malloc(sizeof(*uctx));
+ if (uctx == NULL)
+ return (errno);
+
+ /* Parse given address. */
+ error = uds_addr(addr, &uctx->uc_sun);
+ if (error != 0) {
+ free(uctx);
+ return (error);
+ }
+
+ uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (uctx->uc_fd == -1) {
+ error = errno;
+ free(uctx);
+ return (error);
+ }
+
+ uctx->uc_side = side;
+ uctx->uc_owner = 0;
+ uctx->uc_magic = UDS_CTX_MAGIC;
+ *uctxp = uctx;
+
+ return (0);
+}
+
+static int
+uds_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
+{
+ struct uds_ctx *uctx;
+ int error;
+
+ PJDLOG_ASSERT(dstaddr != NULL);
+ PJDLOG_ASSERT(timeout >= -1);
+
+ error = uds_common_setup(dstaddr, UDS_SIDE_CLIENT, &uctx);
+ if (error != 0)
+ return (error);
+
+ PJDLOG_ASSERT(srcaddr == NULL);
+
+ if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
+ sizeof(uctx->uc_sun)) == -1) {
+ error = errno;
+ uds_close(uctx);
+ return (error);
+ }
+
+ *ctxp = uctx;
+
+ return (0);
+}
+
+static int
+uds_connect_wait(void *ctx, int timeout)
+{
+ struct uds_ctx *uctx = ctx;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
+ PJDLOG_ASSERT(uctx->uc_fd >= 0);
+ PJDLOG_ASSERT(timeout >= 0);
+
+ return (0);
+}
+
+static int
+uds_server(const char *addr, void **ctxp)
+{
+ struct uds_ctx *uctx;
+ int error;
+
+ error = uds_common_setup(addr, UDS_SIDE_SERVER_LISTEN, &uctx);
+ if (error != 0)
+ return (error);
+
+ (void)unlink(uctx->uc_sun.sun_path);
+ if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
+ sizeof(uctx->uc_sun)) == -1) {
+ error = errno;
+ uds_close(uctx);
+ return (error);
+ }
+ uctx->uc_owner = getpid();
+ if (listen(uctx->uc_fd, 8) == -1) {
+ error = errno;
+ uds_close(uctx);
+ return (error);
+ }
+
+ *ctxp = uctx;
+
+ return (0);
+}
+
+static int
+uds_accept(void *ctx, void **newctxp)
+{
+ struct uds_ctx *uctx = ctx;
+ struct uds_ctx *newuctx;
+ socklen_t fromlen;
+ int error;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN);
+ PJDLOG_ASSERT(uctx->uc_fd >= 0);
+
+ newuctx = malloc(sizeof(*newuctx));
+ if (newuctx == NULL)
+ return (errno);
+
+ fromlen = sizeof(newuctx->uc_sun);
+ newuctx->uc_fd = accept(uctx->uc_fd,
+ (struct sockaddr *)&newuctx->uc_sun, &fromlen);
+ if (newuctx->uc_fd < 0) {
+ error = errno;
+ free(newuctx);
+ return (error);
+ }
+
+ newuctx->uc_side = UDS_SIDE_SERVER_WORK;
+ newuctx->uc_magic = UDS_CTX_MAGIC;
+ *newctxp = newuctx;
+
+ return (0);
+}
+
+static int
+uds_send(void *ctx, const unsigned char *data, size_t size, int fd)
+{
+ struct uds_ctx *uctx = ctx;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(uctx->uc_fd >= 0);
+
+ return (proto_common_send(uctx->uc_fd, data, size, fd));
+}
+
+static int
+uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
+{
+ struct uds_ctx *uctx = ctx;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(uctx->uc_fd >= 0);
+
+ return (proto_common_recv(uctx->uc_fd, data, size, fdp));
+}
+
+static int
+uds_descriptor(const void *ctx)
+{
+ const struct uds_ctx *uctx = ctx;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+
+ return (uctx->uc_fd);
+}
+
+static void
+uds_local_address(const void *ctx, char *addr, size_t size)
+{
+ const struct uds_ctx *uctx = ctx;
+ struct sockaddr_un sun;
+ socklen_t sunlen;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(addr != NULL);
+
+ sunlen = sizeof(sun);
+ if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+ PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
+ if (sun.sun_path[0] == '\0') {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+ PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size);
+}
+
+static void
+uds_remote_address(const void *ctx, char *addr, size_t size)
+{
+ const struct uds_ctx *uctx = ctx;
+ struct sockaddr_un sun;
+ socklen_t sunlen;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+ PJDLOG_ASSERT(addr != NULL);
+
+ sunlen = sizeof(sun);
+ if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+ PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
+ if (sun.sun_path[0] == '\0') {
+ PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
+ return;
+ }
+ snprintf(addr, size, "uds://%s", sun.sun_path);
+}
+
+static void
+uds_close(void *ctx)
+{
+ struct uds_ctx *uctx = ctx;
+
+ PJDLOG_ASSERT(uctx != NULL);
+ PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
+
+ if (uctx->uc_fd >= 0)
+ close(uctx->uc_fd);
+ /*
+ * Unlink the socket only if we are the owner and this is descriptor
+ * we listen on.
+ */
+ if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN &&
+ uctx->uc_owner == getpid()) {
+ PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0');
+ if (unlink(uctx->uc_sun.sun_path) == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to unlink socket file %s",
+ uctx->uc_sun.sun_path);
+ }
+ }
+ uctx->uc_owner = 0;
+ uctx->uc_magic = 0;
+ free(uctx);
+}
+
+static struct proto uds_proto = {
+ .prt_name = "uds",
+ .prt_connect = uds_connect,
+ .prt_connect_wait = uds_connect_wait,
+ .prt_server = uds_server,
+ .prt_accept = uds_accept,
+ .prt_send = uds_send,
+ .prt_recv = uds_recv,
+ .prt_descriptor = uds_descriptor,
+ .prt_local_address = uds_local_address,
+ .prt_remote_address = uds_remote_address,
+ .prt_close = uds_close
+};
+
+static __constructor void
+uds_ctor(void)
+{
+
+ proto_register(&uds_proto, false);
+}
diff --git a/contrib/openbsm/bin/auditdistd/receiver.c b/contrib/openbsm/bin/auditdistd/receiver.c
new file mode 100644
index 0000000..9dc3b018
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/receiver.c
@@ -0,0 +1,712 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h>
+#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP)
+#include <sys/endian.h>
+#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else /* !HAVE_MACHINE_ENDIAN_H */
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else /* !HAVE_ENDIAN_H */
+#error "No supported endian.h"
+#endif /* !HAVE_ENDIAN_H */
+#endif /* !HAVE_MACHINE_ENDIAN_H */
+#include <compat/endian.h>
+#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+#ifndef HAVE_FSTATAT
+#include "fstatat.h"
+#endif
+#ifndef HAVE_OPENAT
+#include "openat.h"
+#endif
+#ifndef HAVE_RENAMEAT
+#include "renameat.h"
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+#include "proto.h"
+#include "sandbox.h"
+#include "subr.h"
+#include "synch.h"
+#include "trail.h"
+
+static struct adist_config *adcfg;
+static struct adist_host *adhost;
+
+static TAILQ_HEAD(, adreq) adist_free_list;
+static pthread_mutex_t adist_free_list_lock;
+static pthread_cond_t adist_free_list_cond;
+static TAILQ_HEAD(, adreq) adist_disk_list;
+static pthread_mutex_t adist_disk_list_lock;
+static pthread_cond_t adist_disk_list_cond;
+static TAILQ_HEAD(, adreq) adist_send_list;
+static pthread_mutex_t adist_send_list_lock;
+static pthread_cond_t adist_send_list_cond;
+
+static void
+adreq_clear(struct adreq *adreq)
+{
+
+ adreq->adr_error = -1;
+ adreq->adr_byteorder = ADIST_BYTEORDER_UNDEFINED;
+ adreq->adr_cmd = ADIST_CMD_UNDEFINED;
+ adreq->adr_seq = 0;
+ adreq->adr_datasize = 0;
+}
+
+static void
+init_environment(void)
+{
+ struct adreq *adreq;
+ unsigned int ii;
+
+ TAILQ_INIT(&adist_free_list);
+ mtx_init(&adist_free_list_lock);
+ cv_init(&adist_free_list_cond);
+ TAILQ_INIT(&adist_disk_list);
+ mtx_init(&adist_disk_list_lock);
+ cv_init(&adist_disk_list_cond);
+ TAILQ_INIT(&adist_send_list);
+ mtx_init(&adist_send_list_lock);
+ cv_init(&adist_send_list_cond);
+
+ for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) {
+ adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE);
+ if (adreq == NULL) {
+ pjdlog_exitx(EX_TEMPFAIL,
+ "Unable to allocate %zu bytes of memory for adreq object.",
+ sizeof(*adreq) + ADIST_BUF_SIZE);
+ }
+ adreq_clear(adreq);
+ TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next);
+ }
+}
+
+static void
+adreq_decode_and_validate_header(struct adreq *adreq)
+{
+
+ /* Byte-swap only is the sender is using different byte order. */
+ if (adreq->adr_byteorder != ADIST_BYTEORDER) {
+ adreq->adr_byteorder = ADIST_BYTEORDER;
+ adreq->adr_seq = bswap64(adreq->adr_seq);
+ adreq->adr_datasize = bswap32(adreq->adr_datasize);
+ }
+
+ /* Validate packet header. */
+
+ if (adreq->adr_datasize > ADIST_BUF_SIZE) {
+ pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).",
+ (uintmax_t)adreq->adr_datasize);
+ }
+
+ switch (adreq->adr_cmd) {
+ case ADIST_CMD_OPEN:
+ case ADIST_CMD_APPEND:
+ case ADIST_CMD_CLOSE:
+ if (adreq->adr_datasize == 0) {
+ pjdlog_exitx(EX_PROTOCOL,
+ "Invalid datasize received (%ju).",
+ (uintmax_t)adreq->adr_datasize);
+ }
+ break;
+ case ADIST_CMD_KEEPALIVE:
+ case ADIST_CMD_ERROR:
+ if (adreq->adr_datasize > 0) {
+ pjdlog_exitx(EX_PROTOCOL,
+ "Invalid datasize received (%ju).",
+ (uintmax_t)adreq->adr_datasize);
+ }
+ break;
+ default:
+ pjdlog_exitx(EX_PROTOCOL, "Invalid command received (%hhu).",
+ adreq->adr_cmd);
+ }
+}
+
+static void
+adreq_validate_data(const struct adreq *adreq)
+{
+
+ /* Validate packet data. */
+
+ switch (adreq->adr_cmd) {
+ case ADIST_CMD_OPEN:
+ case ADIST_CMD_CLOSE:
+ /*
+ * File name must end up with '\0' and there must be no '\0'
+ * in the middle.
+ */
+ if (adreq->adr_data[adreq->adr_datasize - 1] != '\0' ||
+ strchr(adreq->adr_data, '\0') !=
+ (const char *)adreq->adr_data + adreq->adr_datasize - 1) {
+ pjdlog_exitx(EX_PROTOCOL,
+ "Invalid file name received.");
+ }
+ break;
+ }
+}
+
+/*
+ * Thread receives requests from the sender.
+ */
+static void *
+recv_thread(void *arg __unused)
+{
+ struct adreq *adreq;
+
+ for (;;) {
+ pjdlog_debug(3, "recv: Taking free request.");
+ QUEUE_TAKE(adreq, &adist_free_list, 0);
+ pjdlog_debug(3, "recv: (%p) Got request.", adreq);
+
+ if (proto_recv(adhost->adh_remote, &adreq->adr_packet,
+ sizeof(adreq->adr_packet)) == -1) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to receive request header");
+ }
+ adreq_decode_and_validate_header(adreq);
+
+ switch (adreq->adr_cmd) {
+ case ADIST_CMD_KEEPALIVE:
+ adreq->adr_error = 0;
+ adreq_log(LOG_DEBUG, 2, -1, adreq,
+ "recv: (%p) Got request header: ", adreq);
+ pjdlog_debug(3,
+ "recv: (%p) Moving request to the send queue.",
+ adreq);
+ QUEUE_INSERT(adreq, &adist_send_list);
+ continue;
+ case ADIST_CMD_ERROR:
+ pjdlog_error("An error occured on the sender while reading \"%s/%s\".",
+ adhost->adh_directory, adhost->adh_trail_name);
+ adreq_log(LOG_DEBUG, 2, ADIST_ERROR_READ, adreq,
+ "recv: (%p) Got request header: ", adreq);
+ pjdlog_debug(3,
+ "recv: (%p) Moving request to the send queue.",
+ adreq);
+ QUEUE_INSERT(adreq, &adist_disk_list);
+ continue;
+ case ADIST_CMD_OPEN:
+ case ADIST_CMD_APPEND:
+ case ADIST_CMD_CLOSE:
+ if (proto_recv(adhost->adh_remote, adreq->adr_data,
+ adreq->adr_datasize) == -1) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to receive request data");
+ }
+ adreq_validate_data(adreq);
+ adreq_log(LOG_DEBUG, 2, -1, adreq,
+ "recv: (%p) Got request header: ", adreq);
+ pjdlog_debug(3,
+ "recv: (%p) Moving request to the disk queue.",
+ adreq);
+ QUEUE_INSERT(adreq, &adist_disk_list);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid condition.");
+ }
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+/*
+ * Function that opens trail file requested by the sender.
+ * If the file already exist, it has to be the most recent file and it can
+ * only be open for append.
+ * If the file doesn't already exist, it has to be "older" than all existing
+ * files.
+ */
+static int
+receiver_open(const char *filename)
+{
+ int fd;
+
+ /*
+ * Previous file should be closed by now. Sending OPEN request without
+ * sending CLOSE for the previous file is a sender bug.
+ */
+ if (adhost->adh_trail_fd != -1) {
+ pjdlog_error("Sender requested opening file \"%s\" without first closing \"%s\".",
+ filename, adhost->adh_trail_name);
+ return (ADIST_ERROR_WRONG_ORDER);
+ }
+
+ if (!trail_validate_name(filename, NULL)) {
+ pjdlog_error("Sender wants to open file \"%s\", which has invalid name.",
+ filename);
+ return (ADIST_ERROR_INVALID_NAME);
+ }
+
+ switch (trail_name_compare(filename, adhost->adh_trail_name)) {
+ case TRAIL_RENAMED:
+ if (!trail_is_not_terminated(adhost->adh_trail_name)) {
+ pjdlog_error("Terminated trail \"%s/%s\" was unterminated on the sender as \"%s/%s\"?",
+ adhost->adh_directory, adhost->adh_trail_name,
+ adhost->adh_directory, filename);
+ return (ADIST_ERROR_INVALID_NAME);
+ }
+ if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name,
+ adhost->adh_trail_dirfd, filename) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to rename file \"%s/%s\" to \"%s/%s\"",
+ adhost->adh_directory, adhost->adh_trail_name,
+ adhost->adh_directory, filename);
+ PJDLOG_ASSERT(errno > 0);
+ return (ADIST_ERROR_RENAME);
+ }
+ pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".",
+ adhost->adh_directory, adhost->adh_trail_name,
+ adhost->adh_directory, filename);
+ /* FALLTHROUGH */
+ case TRAIL_IDENTICAL:
+ /* Opening existing file. */
+ fd = openat(adhost->adh_trail_dirfd, filename,
+ O_WRONLY | O_APPEND | O_NOFOLLOW);
+ if (fd == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to open file \"%s/%s\" for append",
+ adhost->adh_directory, filename);
+ PJDLOG_ASSERT(errno > 0);
+ return (ADIST_ERROR_OPEN);
+ }
+ pjdlog_debug(1, "Opened file \"%s/%s\".",
+ adhost->adh_directory, filename);
+ break;
+ case TRAIL_NEWER:
+ /* Opening new file. */
+ fd = openat(adhost->adh_trail_dirfd, filename,
+ O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
+ if (fd == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to create file \"%s/%s\"",
+ adhost->adh_directory, filename);
+ PJDLOG_ASSERT(errno > 0);
+ return (ADIST_ERROR_CREATE);
+ }
+ pjdlog_debug(1, "Created file \"%s/%s\".",
+ adhost->adh_directory, filename);
+ break;
+ case TRAIL_OLDER:
+ /* Trying to open old file. */
+ pjdlog_error("Sender wants to open an old file \"%s\".", filename);
+ return (ADIST_ERROR_OPEN_OLD);
+ default:
+ PJDLOG_ABORT("Unknown return value from trail_name_compare().");
+ }
+ PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename,
+ sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name));
+ adhost->adh_trail_fd = fd;
+ return (0);
+}
+
+/*
+ * Function appends data to the trail file that is currently open.
+ */
+static int
+receiver_append(const unsigned char *data, size_t size)
+{
+ ssize_t done;
+ size_t osize;
+
+ /* We should have opened trail file. */
+ if (adhost->adh_trail_fd == -1) {
+ pjdlog_error("Sender requested append without first opening file.");
+ return (ADIST_ERROR_WRONG_ORDER);
+ }
+
+ osize = size;
+ while (size > 0) {
+ done = write(adhost->adh_trail_fd, data, size);
+ if (done == -1) {
+ if (errno == EINTR)
+ continue;
+ pjdlog_errno(LOG_ERR, "Write to \"%s/%s\" failed",
+ adhost->adh_directory, adhost->adh_trail_name);
+ PJDLOG_ASSERT(errno > 0);
+ return (ADIST_ERROR_WRITE);
+ }
+ pjdlog_debug(3, "Wrote %zd bytes into \"%s/%s\".", done,
+ adhost->adh_directory, adhost->adh_trail_name);
+ size -= done;
+ }
+ pjdlog_debug(2, "Appended %zu bytes to file \"%s/%s\".",
+ osize, adhost->adh_directory, adhost->adh_trail_name);
+ return (0);
+}
+
+static int
+receiver_close(const char *filename)
+{
+
+ /* We should have opened trail file. */
+ if (adhost->adh_trail_fd == -1) {
+ pjdlog_error("Sender requested closing file without first opening it.");
+ return (ADIST_ERROR_WRONG_ORDER);
+ }
+
+ /* Validate if we can do the rename. */
+ if (!trail_validate_name(adhost->adh_trail_name, filename)) {
+ pjdlog_error("Sender wants to close file \"%s\" using name \"%s\".",
+ adhost->adh_trail_name, filename);
+ return (ADIST_ERROR_INVALID_NAME);
+ }
+
+ PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0);
+ adhost->adh_trail_fd = -1;
+
+ pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory,
+ adhost->adh_trail_name);
+
+ if (strcmp(adhost->adh_trail_name, filename) == 0) {
+ /* File name didn't change, we are done here. */
+ return (0);
+ }
+
+ if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name,
+ adhost->adh_trail_dirfd, filename) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to rename \"%s\" to \"%s\"",
+ adhost->adh_trail_name, filename);
+ PJDLOG_ASSERT(errno > 0);
+ return (ADIST_ERROR_RENAME);
+ }
+ pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".",
+ adhost->adh_directory, adhost->adh_trail_name,
+ adhost->adh_directory, filename);
+ PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename,
+ sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name));
+
+ return (0);
+}
+
+static int
+receiver_error(void)
+{
+
+ /* We should have opened trail file. */
+ if (adhost->adh_trail_fd == -1) {
+ pjdlog_error("Sender send read error, but file is not open.");
+ return (ADIST_ERROR_WRONG_ORDER);
+ }
+
+ PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0);
+ adhost->adh_trail_fd = -1;
+
+ pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory,
+ adhost->adh_trail_name);
+
+ return (0);
+}
+
+static void *
+disk_thread(void *arg __unused)
+{
+ struct adreq *adreq;
+
+ for (;;) {
+ pjdlog_debug(3, "disk: Taking request.");
+ QUEUE_TAKE(adreq, &adist_disk_list, 0);
+ adreq_log(LOG_DEBUG, 3, -1, adreq, "disk: (%p) Got request: ",
+ adreq);
+ /* Handle the actual request. */
+ switch (adreq->adr_cmd) {
+ case ADIST_CMD_OPEN:
+ adreq->adr_error = receiver_open(adreq->adr_data);
+ break;
+ case ADIST_CMD_APPEND:
+ adreq->adr_error = receiver_append(adreq->adr_data,
+ adreq->adr_datasize);
+ break;
+ case ADIST_CMD_CLOSE:
+ adreq->adr_error = receiver_close(adreq->adr_data);
+ break;
+ case ADIST_CMD_ERROR:
+ adreq->adr_error = receiver_error();
+ break;
+ default:
+ PJDLOG_ABORT("Unexpected command (cmd=%hhu).",
+ adreq->adr_cmd);
+ }
+ if (adreq->adr_error != 0) {
+ adreq_log(LOG_ERR, 0, adreq->adr_error, adreq,
+ "Request failed: ");
+ }
+ pjdlog_debug(3, "disk: (%p) Moving request to the send queue.",
+ adreq);
+ QUEUE_INSERT(adreq, &adist_send_list);
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+/*
+ * Thread sends requests back to primary node.
+ */
+static void *
+send_thread(void *arg __unused)
+{
+ struct adreq *adreq;
+ struct adrep adrep;
+
+ for (;;) {
+ pjdlog_debug(3, "send: Taking request.");
+ QUEUE_TAKE(adreq, &adist_send_list, 0);
+ adreq_log(LOG_DEBUG, 3, -1, adreq, "send: (%p) Got request: ",
+ adreq);
+ adrep.adrp_byteorder = ADIST_BYTEORDER;
+ adrep.adrp_seq = adreq->adr_seq;
+ adrep.adrp_error = adreq->adr_error;
+ if (proto_send(adhost->adh_remote, &adrep,
+ sizeof(adrep)) == -1) {
+ pjdlog_exit(EX_TEMPFAIL, "Unable to send reply");
+ }
+ pjdlog_debug(3, "send: (%p) Moving request to the free queue.",
+ adreq);
+ adreq_clear(adreq);
+ QUEUE_INSERT(adreq, &adist_free_list);
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+static void
+receiver_directory_create(void)
+{
+ struct passwd *pw;
+
+ /*
+ * According to getpwnam(3) we have to clear errno before calling the
+ * function to be able to distinguish between an error and missing
+ * entry (with is not treated as error by getpwnam(3)).
+ */
+ errno = 0;
+ pw = getpwnam(ADIST_USER);
+ if (pw == NULL) {
+ if (errno != 0) {
+ pjdlog_exit(EX_NOUSER,
+ "Unable to find info about '%s' user", ADIST_USER);
+ } else {
+ pjdlog_exitx(EX_NOUSER, "User '%s' doesn't exist.",
+ ADIST_USER);
+ }
+ }
+
+ if (mkdir(adhost->adh_directory, 0700) == -1) {
+ pjdlog_exit(EX_OSFILE, "Unable to create directory \"%s\"",
+ adhost->adh_directory);
+ }
+ if (chown(adhost->adh_directory, pw->pw_uid, pw->pw_gid) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to change owner of the directory \"%s\"",
+ adhost->adh_directory);
+ (void)rmdir(adhost->adh_directory);
+ exit(EX_OSFILE);
+ }
+}
+
+static void
+receiver_directory_open(void)
+{
+
+#ifdef HAVE_FDOPENDIR
+ adhost->adh_trail_dirfd = open(adhost->adh_directory,
+ O_RDONLY | O_DIRECTORY);
+ if (adhost->adh_trail_dirfd == -1) {
+ if (errno == ENOENT) {
+ receiver_directory_create();
+ adhost->adh_trail_dirfd = open(adhost->adh_directory,
+ O_RDONLY | O_DIRECTORY);
+ }
+ if (adhost->adh_trail_dirfd == -1) {
+ pjdlog_exit(EX_CONFIG,
+ "Unable to open directory \"%s\"",
+ adhost->adh_directory);
+ }
+ }
+ adhost->adh_trail_dirfp = fdopendir(adhost->adh_trail_dirfd);
+ if (adhost->adh_trail_dirfp == NULL) {
+ pjdlog_exit(EX_CONFIG, "Unable to fdopen directory \"%s\"",
+ adhost->adh_directory);
+ }
+#else
+ struct stat sb;
+
+ if (stat(adhost->adh_directory, &sb) == -1) {
+ if (errno == ENOENT) {
+ receiver_directory_create();
+ } else {
+ pjdlog_exit(EX_CONFIG,
+ "Unable to stat directory \"%s\"",
+ adhost->adh_directory);
+ }
+ }
+ adhost->adh_trail_dirfp = opendir(adhost->adh_directory);
+ if (adhost->adh_trail_dirfp == NULL) {
+ pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"",
+ adhost->adh_directory);
+ }
+ adhost->adh_trail_dirfd = dirfd(adhost->adh_trail_dirfp);
+#endif
+}
+
+static void
+receiver_connect(void)
+{
+ uint64_t trail_size;
+ struct stat sb;
+
+ PJDLOG_ASSERT(adhost->adh_trail_dirfp != NULL);
+
+ trail_last(adhost->adh_trail_dirfp, adhost->adh_trail_name,
+ sizeof(adhost->adh_trail_name));
+
+ if (adhost->adh_trail_name[0] == '\0') {
+ trail_size = 0;
+ } else {
+ if (fstatat(adhost->adh_trail_dirfd, adhost->adh_trail_name,
+ &sb, AT_SYMLINK_NOFOLLOW) == -1) {
+ pjdlog_exit(EX_CONFIG, "Unable to stat \"%s/%s\"",
+ adhost->adh_directory, adhost->adh_trail_name);
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ pjdlog_exitx(EX_CONFIG,
+ "File \"%s/%s\" is not a regular file.",
+ adhost->adh_directory, adhost->adh_trail_name);
+ }
+ trail_size = sb.st_size;
+ }
+ trail_size = htole64(trail_size);
+ if (proto_send(adhost->adh_remote, &trail_size,
+ sizeof(trail_size)) == -1) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to send size of the most recent trail file");
+ }
+ if (proto_send(adhost->adh_remote, adhost->adh_trail_name,
+ sizeof(adhost->adh_trail_name)) == -1) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to send name of the most recent trail file");
+ }
+}
+
+void
+adist_receiver(struct adist_config *config, struct adist_host *adh)
+{
+ sigset_t mask;
+ pthread_t td;
+ pid_t pid;
+ int error, mode, debuglevel;
+
+ pid = fork();
+ if (pid == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to fork");
+ proto_close(adh->adh_remote);
+ adh->adh_remote = NULL;
+ return;
+ }
+
+ if (pid > 0) {
+ /* This is parent. */
+ proto_close(adh->adh_remote);
+ adh->adh_remote = NULL;
+ adh->adh_worker_pid = pid;
+ return;
+ }
+
+ adcfg = config;
+ adhost = adh;
+ mode = pjdlog_mode_get();
+ debuglevel = pjdlog_debug_get();
+
+ descriptors_cleanup(adhost);
+
+// descriptors_assert(adhost, mode);
+
+ pjdlog_init(mode);
+ pjdlog_debug_set(debuglevel);
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("%s (%s)", adhost->adh_name, role2str(adhost->adh_role));
+#endif
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
+
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(adhost->adh_remote, adcfg->adc_timeout) == -1)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+
+ init_environment();
+
+ adhost->adh_trail_fd = -1;
+ receiver_directory_open();
+
+ if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)",
+ role2str(adhost->adh_role), adhost->adh_name) != 0) {
+ exit(EX_CONFIG);
+ }
+ pjdlog_info("Privileges successfully dropped.");
+
+ receiver_connect();
+
+ error = pthread_create(&td, NULL, recv_thread, adhost);
+ PJDLOG_ASSERT(error == 0);
+ error = pthread_create(&td, NULL, disk_thread, adhost);
+ PJDLOG_ASSERT(error == 0);
+ (void)send_thread(adhost);
+}
diff --git a/contrib/openbsm/bin/auditdistd/renameat.h b/contrib/openbsm/bin/auditdistd/renameat.h
new file mode 100644
index 0000000..0becb8a
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/renameat.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _RENAMEAT_H_
+#define _RENAMEAT_H_
+
+#include <stdio.h>
+#include <unistd.h>
+
+static int
+renameat(int fromfd, const char *from, int tofd, const char *to)
+{
+ int cfd, error, ret;
+
+ if (fromfd != tofd) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ cfd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cfd == -1)
+ return (-1);
+
+ if (fchdir(fromfd) == -1) {
+ error = errno;
+ (void)close(cfd);
+ errno = error;
+ return (-1);
+ }
+
+ ret = rename(from, to);
+
+ error = errno;
+ (void)fchdir(cfd);
+ (void)close(cfd);
+ errno = error;
+ return (ret);
+}
+
+#endif /* !_RENAMEAT_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/sandbox.c b/contrib/openbsm/bin/auditdistd/sandbox.c
new file mode 100644
index 0000000..53cd6b3
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/sandbox.c
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h>
+#ifdef HAVE_JAIL
+#include <sys/jail.h>
+#endif
+#ifdef HAVE_CAP_ENTER
+#include <sys/capability.h>
+#endif
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "pjdlog.h"
+#include "sandbox.h"
+
+static int
+groups_compare(const void *grp0, const void *grp1)
+{
+ gid_t gr0 = *(const gid_t *)grp0;
+ gid_t gr1 = *(const gid_t *)grp1;
+
+ return (gr0 <= gr1 ? (gr0 < gr1 ? -1 : 0) : 1);
+
+}
+
+int
+sandbox(const char *user, bool capsicum, const char *fmt, ...)
+{
+#ifdef HAVE_JAIL
+ struct jail jailst;
+ char *jailhost;
+ va_list ap;
+#endif
+ struct passwd *pw;
+ uid_t ruid, euid;
+ gid_t rgid, egid;
+#ifdef HAVE_GETRESUID
+ uid_t suid;
+#endif
+#ifdef HAVE_GETRESGID
+ gid_t sgid;
+#endif
+ gid_t *groups, *ggroups;
+ bool jailed;
+ int ngroups, ret;
+
+ PJDLOG_ASSERT(user != NULL);
+ PJDLOG_ASSERT(fmt != NULL);
+
+ ret = -1;
+ groups = NULL;
+ ggroups = NULL;
+
+ /*
+ * According to getpwnam(3) we have to clear errno before calling the
+ * function to be able to distinguish between an error and missing
+ * entry (with is not treated as error by getpwnam(3)).
+ */
+ errno = 0;
+ pw = getpwnam(user);
+ if (pw == NULL) {
+ if (errno != 0) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to find info about '%s' user", user);
+ goto out;
+ } else {
+ pjdlog_error("'%s' user doesn't exist.", user);
+ errno = ENOENT;
+ goto out;
+ }
+ }
+
+ ngroups = sysconf(_SC_NGROUPS_MAX);
+ if (ngroups == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to obtain maximum number of groups");
+ ngroups = NGROUPS_MAX;
+ }
+ ngroups++; /* For base gid. */
+ groups = malloc(sizeof(groups[0]) * ngroups);
+ if (groups == NULL) {
+ pjdlog_error("Unable to allocate memory for %d groups.",
+ ngroups);
+ goto out;
+ }
+ if (getgrouplist(user, pw->pw_gid, groups, &ngroups) == -1) {
+ pjdlog_error("Unable to obtain groups of user %s.", user);
+ goto out;
+ }
+
+#ifdef HAVE_JAIL
+ va_start(ap, fmt);
+ (void)vasprintf(&jailhost, fmt, ap);
+ va_end(ap);
+ if (jailhost == NULL) {
+ pjdlog_error("Unable to allocate memory for jail host name.");
+ goto out;
+ }
+ bzero(&jailst, sizeof(jailst));
+ jailst.version = JAIL_API_VERSION;
+ jailst.path = pw->pw_dir;
+ jailst.hostname = jailhost;
+ if (jail(&jailst) >= 0) {
+ jailed = true;
+ } else {
+ jailed = false;
+ pjdlog_errno(LOG_WARNING,
+ "Unable to jail to directory %s", pw->pw_dir);
+ }
+ free(jailhost);
+#else /* !HAVE_JAIL */
+ jailed = false;
+#endif /* !HAVE_JAIL */
+
+ if (!jailed) {
+ if (chroot(pw->pw_dir) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to change root directory to %s",
+ pw->pw_dir);
+ goto out;
+ }
+ }
+ PJDLOG_VERIFY(chdir("/") == 0);
+
+ if (setgroups(ngroups, groups) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to set groups");
+ goto out;
+ }
+ if (setgid(pw->pw_gid) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to set gid to %u",
+ (unsigned int)pw->pw_gid);
+ goto out;
+ }
+ if (setuid(pw->pw_uid) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to set uid to %u",
+ (unsigned int)pw->pw_uid);
+ goto out;
+ }
+
+#ifdef HAVE_CAP_ENTER
+ if (capsicum) {
+ capsicum = (cap_enter() == 0);
+ if (!capsicum) {
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "Unable to sandbox using capsicum");
+ }
+ }
+#else /* !HAVE_CAP_ENTER */
+ capsicum = false;
+#endif /* !HAVE_CAP_ENTER */
+
+ /*
+ * Better be sure that everything succeeded.
+ */
+#ifdef HAVE_GETRESUID
+ PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0);
+ PJDLOG_VERIFY(suid == pw->pw_uid);
+#else
+ ruid = getuid();
+ euid = geteuid();
+#endif
+ PJDLOG_VERIFY(ruid == pw->pw_uid);
+ PJDLOG_VERIFY(euid == pw->pw_uid);
+#ifdef HAVE_GETRESGID
+ PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0);
+ PJDLOG_VERIFY(sgid == pw->pw_gid);
+#else
+ rgid = getgid();
+ egid = getegid();
+#endif
+ PJDLOG_VERIFY(rgid == pw->pw_gid);
+ PJDLOG_VERIFY(egid == pw->pw_gid);
+ PJDLOG_VERIFY(getgroups(0, NULL) == ngroups);
+ ggroups = malloc(sizeof(ggroups[0]) * ngroups);
+ if (ggroups == NULL) {
+ pjdlog_error("Unable to allocate memory for %d groups.",
+ ngroups);
+ goto out;
+ }
+ PJDLOG_VERIFY(getgroups(ngroups, ggroups) == ngroups);
+ qsort(groups, (size_t)ngroups, sizeof(groups[0]), groups_compare);
+ qsort(ggroups, (size_t)ngroups, sizeof(ggroups[0]), groups_compare);
+ PJDLOG_VERIFY(bcmp(groups, ggroups, sizeof(groups[0]) * ngroups) == 0);
+
+ pjdlog_debug(1,
+ "Privileges successfully dropped using %s%s+setgid+setuid.",
+ capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot");
+
+ ret = 0;
+out:
+ if (groups != NULL)
+ free(groups);
+ if (ggroups != NULL)
+ free(ggroups);
+ return (ret);
+}
diff --git a/contrib/openbsm/bin/auditdistd/sandbox.h b/contrib/openbsm/bin/auditdistd/sandbox.h
new file mode 100644
index 0000000..7bcde25
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/sandbox.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _SANDBOX_H_
+#define _SANDBOX_H_
+
+#include <stdbool.h>
+
+int sandbox(const char *user, bool capsicum, const char *fmt, ...);
+
+#endif /* !_SANDBOX_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/sender.c b/contrib/openbsm/bin/auditdistd/sender.c
new file mode 100644
index 0000000..4349b0f
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/sender.c
@@ -0,0 +1,845 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h>
+#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP)
+#include <sys/endian.h>
+#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else /* !HAVE_MACHINE_ENDIAN_H */
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else /* !HAVE_ENDIAN_H */
+#error "No supported endian.h"
+#endif /* !HAVE_ENDIAN_H */
+#endif /* !HAVE_MACHINE_ENDIAN_H */
+#include <compat/endian.h>
+#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <signal.h>
+#include <string.h>
+#include <strings.h>
+
+#include <openssl/hmac.h>
+
+#ifndef HAVE_SIGTIMEDWAIT
+#include "sigtimedwait.h"
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+#include "proto.h"
+#include "sandbox.h"
+#include "subr.h"
+#include "synch.h"
+#include "trail.h"
+
+static struct adist_config *adcfg;
+static struct adist_host *adhost;
+
+static pthread_rwlock_t adist_remote_lock;
+static pthread_mutex_t adist_remote_mtx;
+static pthread_cond_t adist_remote_cond;
+static struct trail *adist_trail;
+
+static TAILQ_HEAD(, adreq) adist_free_list;
+static pthread_mutex_t adist_free_list_lock;
+static pthread_cond_t adist_free_list_cond;
+static TAILQ_HEAD(, adreq) adist_send_list;
+static pthread_mutex_t adist_send_list_lock;
+static pthread_cond_t adist_send_list_cond;
+static TAILQ_HEAD(, adreq) adist_recv_list;
+static pthread_mutex_t adist_recv_list_lock;
+static pthread_cond_t adist_recv_list_cond;
+
+static void
+init_environment(void)
+{
+ struct adreq *adreq;
+ unsigned int ii;
+
+ rw_init(&adist_remote_lock);
+ mtx_init(&adist_remote_mtx);
+ cv_init(&adist_remote_cond);
+ TAILQ_INIT(&adist_free_list);
+ mtx_init(&adist_free_list_lock);
+ cv_init(&adist_free_list_cond);
+ TAILQ_INIT(&adist_send_list);
+ mtx_init(&adist_send_list_lock);
+ cv_init(&adist_send_list_cond);
+ TAILQ_INIT(&adist_recv_list);
+ mtx_init(&adist_recv_list_lock);
+ cv_init(&adist_recv_list_cond);
+
+ for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) {
+ adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE);
+ if (adreq == NULL) {
+ pjdlog_exitx(EX_TEMPFAIL,
+ "Unable to allocate %zu bytes of memory for adreq object.",
+ sizeof(*adreq) + ADIST_BUF_SIZE);
+ }
+ adreq->adr_byteorder = ADIST_BYTEORDER;
+ adreq->adr_cmd = ADIST_CMD_UNDEFINED;
+ adreq->adr_seq = 0;
+ adreq->adr_datasize = 0;
+ TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next);
+ }
+}
+
+static int
+sender_connect(void)
+{
+ unsigned char rnd[32], hash[32], resp[32];
+ struct proto_conn *conn;
+ char welcome[8];
+ int16_t val;
+
+ val = 1;
+ if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to send connection request to parent");
+ }
+ if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to receive reply to connection request from parent");
+ }
+ if (val != 0) {
+ errno = val;
+ pjdlog_errno(LOG_WARNING, "Unable to connect to %s",
+ adhost->adh_remoteaddr);
+ return (-1);
+ }
+ if (proto_connection_recv(adhost->adh_conn, true, &conn) < 0) {
+ pjdlog_exit(EX_TEMPFAIL,
+ "Unable to receive connection from parent");
+ }
+ if (proto_connect_wait(conn, adcfg->adc_timeout) < 0) {
+ pjdlog_errno(LOG_WARNING, "Unable to connect to %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Connected to %s.", adhost->adh_remoteaddr);
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(conn, adcfg->adc_timeout) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+ else
+ pjdlog_debug(1, "Timeout set to %d.", adcfg->adc_timeout);
+
+ /* Exchange welcome message, which includes version number. */
+ (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", ADIST_VERSION);
+ if (proto_send(conn, welcome, sizeof(welcome)) < 0) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to send welcome message to %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Welcome message sent (%s).", welcome);
+ bzero(welcome, sizeof(welcome));
+ if (proto_recv(conn, welcome, sizeof(welcome)) < 0) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to receive welcome message from %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) ||
+ !isdigit(welcome[6]) || welcome[7] != '\0') {
+ pjdlog_warning("Invalid welcome message from %s.",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Welcome message received (%s).", welcome);
+ /*
+ * Receiver can only reply with version number lower or equal to
+ * the one we sent.
+ */
+ adhost->adh_version = atoi(welcome + 5);
+ if (adhost->adh_version > ADIST_VERSION) {
+ pjdlog_warning("Invalid version number from %s (%d received, up to %d supported).",
+ adhost->adh_remoteaddr, adhost->adh_version, ADIST_VERSION);
+ proto_close(conn);
+ return (-1);
+ }
+
+ pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version,
+ adhost->adh_remoteaddr);
+
+ if (proto_send(conn, adcfg->adc_name, sizeof(adcfg->adc_name)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to send name to %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Name (%s) sent.", adcfg->adc_name);
+
+ if (proto_recv(conn, rnd, sizeof(rnd)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to receive challenge from %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Challenge received.");
+
+ if (HMAC(EVP_sha256(), adhost->adh_password,
+ (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
+ NULL) == NULL) {
+ pjdlog_warning("Unable to generate response.");
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Response generated.");
+
+ if (proto_send(conn, hash, sizeof(hash)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to send response to %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Response sent.");
+
+ if (adist_random(rnd, sizeof(rnd)) == -1) {
+ pjdlog_warning("Unable to generate challenge.");
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Challenge generated.");
+
+ if (proto_send(conn, rnd, sizeof(rnd)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to send challenge to %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Challenge sent.");
+
+ if (proto_recv(conn, resp, sizeof(resp)) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to receive response from %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Response received.");
+
+ if (HMAC(EVP_sha256(), adhost->adh_password,
+ (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
+ NULL) == NULL) {
+ pjdlog_warning("Unable to generate hash.");
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Hash generated.");
+
+ if (memcmp(resp, hash, sizeof(hash)) != 0) {
+ pjdlog_warning("Invalid response from %s (wrong password?).",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_info("Receiver authenticated.");
+
+ if (proto_recv(conn, &adhost->adh_trail_offset,
+ sizeof(adhost->adh_trail_offset)) == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to receive size of the most recent trail file from %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ adhost->adh_trail_offset = le64toh(adhost->adh_trail_offset);
+ if (proto_recv(conn, &adhost->adh_trail_name,
+ sizeof(adhost->adh_trail_name)) == -1) {
+ pjdlog_errno(LOG_WARNING,
+ "Unable to receive name of the most recent trail file from %s",
+ adhost->adh_remoteaddr);
+ proto_close(conn);
+ return (-1);
+ }
+ pjdlog_debug(1, "Trail name (%s) and offset (%ju) received.",
+ adhost->adh_trail_name, (uintmax_t)adhost->adh_trail_offset);
+
+ rw_wlock(&adist_remote_lock);
+ mtx_lock(&adist_remote_mtx);
+ PJDLOG_ASSERT(adhost->adh_remote == NULL);
+ PJDLOG_ASSERT(conn != NULL);
+ adhost->adh_remote = conn;
+ mtx_unlock(&adist_remote_mtx);
+ rw_unlock(&adist_remote_lock);
+ cv_signal(&adist_remote_cond);
+
+ return (0);
+}
+
+static void
+sender_disconnect(void)
+{
+
+ rw_wlock(&adist_remote_lock);
+ /*
+ * Check for a race between dropping rlock and acquiring wlock -
+ * another thread can close connection in-between.
+ */
+ if (adhost->adh_remote == NULL) {
+ rw_unlock(&adist_remote_lock);
+ return;
+ }
+ pjdlog_debug(2, "Closing connection to %s.", adhost->adh_remoteaddr);
+ proto_close(adhost->adh_remote);
+ mtx_lock(&adist_remote_mtx);
+ adhost->adh_remote = NULL;
+ adhost->adh_reset = true;
+ adhost->adh_trail_name[0] = '\0';
+ adhost->adh_trail_offset = 0;
+ mtx_unlock(&adist_remote_mtx);
+ rw_unlock(&adist_remote_lock);
+
+ pjdlog_warning("Disconnected from %s.", adhost->adh_remoteaddr);
+
+ /* Move all in-flight requests back onto free list. */
+ mtx_lock(&adist_free_list_lock);
+ mtx_lock(&adist_send_list_lock);
+ TAILQ_CONCAT(&adist_free_list, &adist_send_list, adr_next);
+ mtx_unlock(&adist_send_list_lock);
+ mtx_lock(&adist_recv_list_lock);
+ TAILQ_CONCAT(&adist_free_list, &adist_recv_list, adr_next);
+ mtx_unlock(&adist_recv_list_lock);
+ mtx_unlock(&adist_free_list_lock);
+}
+
+static void
+adreq_fill(struct adreq *adreq, uint8_t cmd, const unsigned char *data,
+ size_t size)
+{
+ static uint64_t seq = 1;
+
+ PJDLOG_ASSERT(size <= ADIST_BUF_SIZE);
+
+ switch (cmd) {
+ case ADIST_CMD_OPEN:
+ case ADIST_CMD_CLOSE:
+ PJDLOG_ASSERT(data != NULL && size == 0);
+ size = strlen(data) + 1;
+ break;
+ case ADIST_CMD_APPEND:
+ PJDLOG_ASSERT(data != NULL && size > 0);
+ break;
+ case ADIST_CMD_KEEPALIVE:
+ case ADIST_CMD_ERROR:
+ PJDLOG_ASSERT(data == NULL && size == 0);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid command (%hhu).", cmd);
+ }
+
+ adreq->adr_cmd = cmd;
+ adreq->adr_seq = seq++;
+ adreq->adr_datasize = size;
+ /* Don't copy if data is already in out buffer. */
+ if (data != NULL && data != adreq->adr_data)
+ bcopy(data, adreq->adr_data, size);
+}
+
+static bool
+read_thread_wait(void)
+{
+ bool newfile = false;
+
+ mtx_lock(&adist_remote_mtx);
+ if (adhost->adh_reset) {
+reset:
+ adhost->adh_reset = false;
+ if (trail_filefd(adist_trail) != -1)
+ trail_close(adist_trail);
+ trail_reset(adist_trail);
+ while (adhost->adh_remote == NULL)
+ cv_wait(&adist_remote_cond, &adist_remote_mtx);
+ trail_start(adist_trail, adhost->adh_trail_name,
+ adhost->adh_trail_offset);
+ newfile = true;
+ }
+ mtx_unlock(&adist_remote_mtx);
+ while (trail_filefd(adist_trail) == -1) {
+ newfile = true;
+ wait_for_dir();
+ /*
+ * We may have been disconnected and reconnected in the
+ * meantime, check if reset is set.
+ */
+ mtx_lock(&adist_remote_mtx);
+ if (adhost->adh_reset)
+ goto reset;
+ mtx_unlock(&adist_remote_mtx);
+ if (trail_filefd(adist_trail) == -1)
+ trail_next(adist_trail);
+ }
+ if (newfile) {
+ pjdlog_debug(1, "Trail file \"%s/%s\" opened.",
+ adhost->adh_directory,
+ trail_filename(adist_trail));
+ (void)wait_for_file_init(trail_filefd(adist_trail));
+ }
+ return (newfile);
+}
+
+static void *
+read_thread(void *arg __unused)
+{
+ struct adreq *adreq;
+ ssize_t done;
+ bool newfile;
+
+ pjdlog_debug(1, "%s started.", __func__);
+
+ for (;;) {
+ newfile = read_thread_wait();
+ QUEUE_TAKE(adreq, &adist_free_list, 0);
+ if (newfile) {
+ adreq_fill(adreq, ADIST_CMD_OPEN,
+ trail_filename(adist_trail), 0);
+ newfile = false;
+ goto move;
+ }
+
+ done = read(trail_filefd(adist_trail), adreq->adr_data,
+ ADIST_BUF_SIZE);
+ if (done == -1) {
+ off_t offset;
+ int error;
+
+ error = errno;
+ offset = lseek(trail_filefd(adist_trail), 0, SEEK_CUR);
+ errno = error;
+ pjdlog_errno(LOG_ERR,
+ "Error while reading \"%s/%s\" at offset %jd",
+ adhost->adh_directory, trail_filename(adist_trail),
+ offset);
+ trail_close(adist_trail);
+ adreq_fill(adreq, ADIST_CMD_ERROR, NULL, 0);
+ goto move;
+ } else if (done == 0) {
+ /* End of file. */
+ pjdlog_debug(3, "End of \"%s/%s\".",
+ adhost->adh_directory, trail_filename(adist_trail));
+ if (!trail_switch(adist_trail)) {
+ /* More audit records can arrive. */
+ mtx_lock(&adist_free_list_lock);
+ TAILQ_INSERT_TAIL(&adist_free_list, adreq,
+ adr_next);
+ mtx_unlock(&adist_free_list_lock);
+ wait_for_file();
+ continue;
+ }
+ adreq_fill(adreq, ADIST_CMD_CLOSE,
+ trail_filename(adist_trail), 0);
+ trail_close(adist_trail);
+ goto move;
+ }
+
+ adreq_fill(adreq, ADIST_CMD_APPEND, adreq->adr_data, done);
+move:
+ pjdlog_debug(3,
+ "read thread: Moving request %p to the send queue (%hhu).",
+ adreq, adreq->adr_cmd);
+ QUEUE_INSERT(adreq, &adist_send_list);
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+static void
+keepalive_send(void)
+{
+ struct adreq *adreq;
+
+ rw_rlock(&adist_remote_lock);
+ if (adhost->adh_remote == NULL) {
+ rw_unlock(&adist_remote_lock);
+ return;
+ }
+ rw_unlock(&adist_remote_lock);
+
+ mtx_lock(&adist_free_list_lock);
+ adreq = TAILQ_FIRST(&adist_free_list);
+ if (adreq != NULL)
+ TAILQ_REMOVE(&adist_free_list, adreq, adr_next);
+ mtx_unlock(&adist_free_list_lock);
+ if (adreq == NULL)
+ return;
+
+ adreq_fill(adreq, ADIST_CMD_KEEPALIVE, NULL, 0);
+
+ QUEUE_INSERT(adreq, &adist_send_list);
+
+ pjdlog_debug(3, "keepalive_send: Request sent.");
+}
+
+/*
+ * Thread sends request to secondary node.
+ */
+static void *
+send_thread(void *arg __unused)
+{
+ time_t lastcheck, now;
+ struct adreq *adreq;
+
+ pjdlog_debug(1, "%s started.", __func__);
+
+ lastcheck = time(NULL);
+
+ for (;;) {
+ pjdlog_debug(3, "send thread: Taking request.");
+ for (;;) {
+ QUEUE_TAKE(adreq, &adist_send_list, ADIST_KEEPALIVE);
+ if (adreq != NULL)
+ break;
+ now = time(NULL);
+ if (lastcheck + ADIST_KEEPALIVE <= now) {
+ keepalive_send();
+ lastcheck = now;
+ }
+ }
+ PJDLOG_ASSERT(adreq != NULL);
+ pjdlog_debug(3, "send thread: (%p) Got request %hhu.", adreq,
+ adreq->adr_cmd);
+ /*
+ * Protect connection from disappearing.
+ */
+ rw_rlock(&adist_remote_lock);
+ /*
+ * Move the request to the recv queue first to avoid race
+ * where the recv thread receives the reply before we move
+ * the request to the recv queue.
+ */
+ QUEUE_INSERT(adreq, &adist_recv_list);
+ if (adhost->adh_remote == NULL ||
+ proto_send(adhost->adh_remote, &adreq->adr_packet,
+ ADPKT_SIZE(adreq)) == -1) {
+ rw_unlock(&adist_remote_lock);
+ pjdlog_debug(1,
+ "send thread: (%p) Unable to send request.", adreq);
+ if (adhost->adh_remote != NULL)
+ sender_disconnect();
+ continue;
+ } else {
+ pjdlog_debug(3, "Request %p sent successfully.", adreq);
+ adreq_log(LOG_DEBUG, 2, -1, adreq,
+ "send: (%p) Request sent: ", adreq);
+ rw_unlock(&adist_remote_lock);
+ }
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+static void
+adrep_decode_header(struct adrep *adrep)
+{
+
+ /* Byte-swap only is the receiver is using different byte order. */
+ if (adrep->adrp_byteorder != ADIST_BYTEORDER) {
+ adrep->adrp_byteorder = ADIST_BYTEORDER;
+ adrep->adrp_seq = bswap64(adrep->adrp_seq);
+ adrep->adrp_error = bswap16(adrep->adrp_error);
+ }
+}
+
+/*
+ * Thread receives answer from secondary node and passes it to ggate_send
+ * thread.
+ */
+static void *
+recv_thread(void *arg __unused)
+{
+ struct adrep adrep;
+ struct adreq *adreq;
+
+ pjdlog_debug(1, "%s started.", __func__);
+
+ for (;;) {
+ /* Wait until there is anything to receive. */
+ QUEUE_WAIT(&adist_recv_list);
+ pjdlog_debug(3, "recv thread: Got something.");
+ rw_rlock(&adist_remote_lock);
+ if (adhost->adh_remote == NULL) {
+ /*
+ * Connection is dead.
+ * XXX: We shouldn't be here.
+ */
+ rw_unlock(&adist_remote_lock);
+ continue;
+ }
+ if (proto_recv(adhost->adh_remote, &adrep,
+ sizeof(adrep)) == -1) {
+ rw_unlock(&adist_remote_lock);
+ pjdlog_errno(LOG_ERR, "Unable to receive reply");
+ sender_disconnect();
+ continue;
+ }
+ rw_unlock(&adist_remote_lock);
+ adrep_decode_header(&adrep);
+ /*
+ * Find the request that was just confirmed.
+ */
+ mtx_lock(&adist_recv_list_lock);
+ TAILQ_FOREACH(adreq, &adist_recv_list, adr_next) {
+ if (adreq->adr_seq == adrep.adrp_seq) {
+ TAILQ_REMOVE(&adist_recv_list, adreq,
+ adr_next);
+ break;
+ }
+ }
+ if (adreq == NULL) {
+ /*
+ * If we disconnected in the meantime, just continue.
+ * On disconnect sender_disconnect() clears the queue,
+ * we can use that.
+ */
+ if (TAILQ_EMPTY(&adist_recv_list)) {
+ mtx_unlock(&adist_recv_list_lock);
+ continue;
+ }
+ mtx_unlock(&adist_recv_list_lock);
+ pjdlog_error("Found no request matching received 'seq' field (%ju).",
+ (uintmax_t)adrep.adrp_seq);
+ sender_disconnect();
+ continue;
+ }
+ mtx_unlock(&adist_recv_list_lock);
+ adreq_log(LOG_DEBUG, 2, -1, adreq,
+ "recv thread: (%p) Request confirmed: ", adreq);
+ pjdlog_debug(3, "recv thread: (%p) Got request %hhu.", adreq,
+ adreq->adr_cmd);
+ if (adrep.adrp_error != 0) {
+ pjdlog_error("Receiver returned error (%s), disconnecting.",
+ adist_errstr((int)adrep.adrp_error));
+ sender_disconnect();
+ continue;
+ }
+ if (adreq->adr_cmd == ADIST_CMD_CLOSE)
+ trail_unlink(adist_trail, adreq->adr_data);
+ pjdlog_debug(3, "Request received successfully.");
+ QUEUE_INSERT(adreq, &adist_free_list);
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+static void
+guard_check_connection(void)
+{
+
+ PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER);
+
+ rw_rlock(&adist_remote_lock);
+ if (adhost->adh_remote != NULL) {
+ rw_unlock(&adist_remote_lock);
+ pjdlog_debug(3, "remote_guard: Connection to %s is ok.",
+ adhost->adh_remoteaddr);
+ return;
+ }
+
+ /*
+ * Upgrade the lock. It doesn't have to be atomic as no other thread
+ * can change connection status from disconnected to connected.
+ */
+ rw_unlock(&adist_remote_lock);
+ pjdlog_debug(1, "remote_guard: Reconnecting to %s.",
+ adhost->adh_remoteaddr);
+ if (sender_connect() == 0) {
+ pjdlog_info("Successfully reconnected to %s.",
+ adhost->adh_remoteaddr);
+ } else {
+ pjdlog_debug(1, "remote_guard: Reconnect to %s failed.",
+ adhost->adh_remoteaddr);
+ }
+}
+
+/*
+ * Thread guards remote connections and reconnects when needed, handles
+ * signals, etc.
+ */
+static void *
+guard_thread(void *arg __unused)
+{
+ struct timespec timeout;
+ time_t lastcheck, now;
+ sigset_t mask;
+ int signo;
+
+ lastcheck = time(NULL);
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0);
+
+ timeout.tv_sec = ADIST_KEEPALIVE;
+ timeout.tv_nsec = 0;
+ signo = -1;
+
+ for (;;) {
+ switch (signo) {
+ case SIGINT:
+ case SIGTERM:
+ sigexit_received = true;
+ pjdlog_exitx(EX_OK,
+ "Termination signal received, exiting.");
+ break;
+ default:
+ break;
+ }
+
+ pjdlog_debug(3, "remote_guard: Checking connections.");
+ now = time(NULL);
+ if (lastcheck + ADIST_KEEPALIVE <= now) {
+ guard_check_connection();
+ lastcheck = now;
+ }
+ signo = sigtimedwait(&mask, NULL, &timeout);
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+void
+adist_sender(struct adist_config *config, struct adist_host *adh)
+{
+ pthread_t td;
+ pid_t pid;
+ int error, mode, debuglevel;
+
+ /*
+ * Create communication channel for sending connection requests from
+ * child to parent.
+ */
+ if (proto_connect(NULL, "socketpair://", -1, &adh->adh_conn) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to create connection sockets between child and parent");
+ return;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to fork");
+ proto_close(adh->adh_conn);
+ adh->adh_conn = NULL;
+ return;
+ }
+
+ if (pid > 0) {
+ /* This is parent. */
+ adh->adh_worker_pid = pid;
+ /* Declare that we are receiver. */
+ proto_recv(adh->adh_conn, NULL, 0);
+ return;
+ }
+
+ adcfg = config;
+ adhost = adh;
+
+ mode = pjdlog_mode_get();
+ debuglevel = pjdlog_debug_get();
+
+ /* Declare that we are sender. */
+ proto_send(adhost->adh_conn, NULL, 0);
+
+ descriptors_cleanup(adhost);
+
+#ifdef TODO
+ descriptors_assert(adhost, mode);
+#endif
+
+ pjdlog_init(mode);
+ pjdlog_debug_set(debuglevel);
+ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("[%s] (%s) ", adhost->adh_name,
+ role2str(adhost->adh_role));
+#endif
+
+ /*
+ * The sender process should be able to remove entries from its
+ * trail directory, but it should not be able to write to the
+ * trail files, only read from them.
+ */
+ adist_trail = trail_new(adhost->adh_directory, false);
+ if (adist_trail == NULL)
+ exit(EX_OSFILE);
+
+ if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)",
+ role2str(adhost->adh_role), adhost->adh_name) != 0) {
+ exit(EX_CONFIG);
+ }
+ pjdlog_info("Privileges successfully dropped.");
+
+ /*
+ * We can ignore wait_for_dir_init() failures. It will fall back to
+ * using sleep(3).
+ */
+ (void)wait_for_dir_init(trail_dirfd(adist_trail));
+
+ init_environment();
+ if (sender_connect() == 0) {
+ pjdlog_info("Successfully connected to %s.",
+ adhost->adh_remoteaddr);
+ }
+ adhost->adh_reset = true;
+
+ /*
+ * Create the guard thread first, so we can handle signals from the
+ * very begining.
+ */
+ error = pthread_create(&td, NULL, guard_thread, NULL);
+ PJDLOG_ASSERT(error == 0);
+ error = pthread_create(&td, NULL, send_thread, NULL);
+ PJDLOG_ASSERT(error == 0);
+ error = pthread_create(&td, NULL, recv_thread, NULL);
+ PJDLOG_ASSERT(error == 0);
+ (void)read_thread(NULL);
+}
diff --git a/contrib/openbsm/bin/auditdistd/sigtimedwait.h b/contrib/openbsm/bin/auditdistd/sigtimedwait.h
new file mode 100644
index 0000000..06a4d13
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/sigtimedwait.h
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _SIGTIMEDWAIT_H_
+#define _SIGTIMEDWAIT_H_
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pjdlog.h"
+
+static int
+sigtimedwait(const sigset_t *set, siginfo_t *info,
+ const struct timespec *timeout)
+{
+ struct itimerval it;
+ sigset_t mask;
+ int error, signo;
+
+ PJDLOG_ASSERT(info == NULL);
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0);
+ PJDLOG_VERIFY(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
+
+ timerclear(&it.it_interval);
+ it.it_value.tv_sec = timeout->tv_sec;
+ it.it_value.tv_usec = timeout->tv_nsec / 1000;
+ if (it.it_value.tv_sec == 0 && it.it_value.tv_usec == 0)
+ it.it_value.tv_usec = 1;
+ PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0);
+
+ bcopy(set, &mask, sizeof(mask));
+ PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0);
+
+ PJDLOG_VERIFY(sigwait(&mask, &signo) == 0);
+ error = errno;
+
+ timerclear(&it.it_interval);
+ timerclear(&it.it_value);
+ PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0);
+
+ PJDLOG_VERIFY(sigemptyset(&mask) == 0);
+ PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0);
+ PJDLOG_VERIFY(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0);
+
+ if (signo == SIGALRM) {
+ errno = EAGAIN;
+ signo = -1;
+ } else {
+ errno = error;
+ }
+
+ return (signo);
+}
+
+#endif /* !_SIGTIMEDWAIT_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/strndup.h b/contrib/openbsm/bin/auditdistd/strndup.h
new file mode 100644
index 0000000..c36a950
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/strndup.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _STRNDUP_H_
+#define _STRNDUP_H_
+
+#include <stdlib.h>
+#include <string.h>
+
+static char *
+strndup(const char *str, size_t len)
+{
+ size_t outlen;
+ char *outstr;
+
+ outlen = strlen(str);
+ if (outlen > len)
+ outlen = len;
+ outstr = malloc(outlen + 1);
+ if (outstr != NULL) {
+ memcpy(outstr, str, outlen);
+ outstr[outlen] = '\0';
+ }
+ return (outstr);
+}
+
+#endif /* !_STRNDUP_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/subr.c b/contrib/openbsm/bin/auditdistd/subr.c
new file mode 100644
index 0000000..ecc626c
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/subr.c
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#ifdef HAVE_KQUEUE
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#endif
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_ARC4RANDOM
+#include <openssl/rand.h>
+#endif
+
+#ifndef HAVE_STRLCAT
+#include <compat/strlcat.h>
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+#include "subr.h"
+
+int
+vsnprlcat(char *str, size_t size, const char *fmt, va_list ap)
+{
+ size_t len;
+
+ len = strlen(str);
+ return (vsnprintf(str + len, size - len, fmt, ap));
+}
+
+int
+snprlcat(char *str, size_t size, const char *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = vsnprlcat(str, size, fmt, ap);
+ va_end(ap);
+ return (result);
+}
+
+const char *
+role2str(int role)
+{
+
+ switch (role) {
+ case ADIST_ROLE_SENDER:
+ return ("sender");
+ case ADIST_ROLE_RECEIVER:
+ return ("receiver");
+ }
+ return ("unknown");
+}
+
+const char *
+adist_errstr(int error)
+{
+
+ switch (error) {
+ case ADIST_ERROR_WRONG_ORDER:
+ return ("wrong operations order");
+ case ADIST_ERROR_INVALID_NAME:
+ return ("invalid trail file name");
+ case ADIST_ERROR_OPEN_OLD:
+ return ("attempt to open an old trail file");
+ case ADIST_ERROR_CREATE:
+ return ("creation of new trail file failed");
+ case ADIST_ERROR_OPEN:
+ return ("open of existing trail file failed");
+ case ADIST_ERROR_READ:
+ return ("read failed");
+ case ADIST_ERROR_WRITE:
+ return ("write failed");
+ case ADIST_ERROR_RENAME:
+ return ("rename of a trail file failed");
+ default:
+ return ("unknown error");
+ }
+}
+
+void
+adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq,
+ const char *fmt, ...)
+{
+ char msg[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void)vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+ (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ",
+ (uintmax_t)adreq->adr_seq);
+ switch (adreq->adr_cmd) {
+ case ADIST_CMD_OPEN:
+ (void)snprlcat(msg, sizeof(msg), "OPEN(%s)",
+ adreq->adr_data);
+ break;
+ case ADIST_CMD_APPEND:
+ (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)",
+ (uintmax_t)adreq->adr_datasize);
+ break;
+ case ADIST_CMD_CLOSE:
+ (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)",
+ adreq->adr_data);
+ break;
+ case ADIST_CMD_KEEPALIVE:
+ (void)snprlcat(msg, sizeof(msg), "KEEPALIVE");
+ break;
+ case ADIST_CMD_ERROR:
+ (void)snprlcat(msg, sizeof(msg), "ERROR");
+ break;
+ default:
+ (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)",
+ adreq->adr_cmd);
+ break;
+ }
+ if (error != -1)
+ (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error));
+ (void)strlcat(msg, ".", sizeof(msg));
+ pjdlog_common(loglevel, debuglevel, -1, "%s", msg);
+}
+
+int
+adist_random(unsigned char *buf, size_t size)
+{
+#ifdef HAVE_ARC4RANDOM_BUF
+ arc4random_buf(buf, size);
+ return (0);
+#elif defined(HAVE_ARC4RANDOM)
+ uint32_t val;
+
+ PJDLOG_ASSERT(size > 0);
+ PJDLOG_ASSERT((size % sizeof(val)) == 0);
+
+ do {
+ val = arc4random();
+ bcopy(&val, buf, sizeof(val));
+ buf += sizeof(val);
+ size -= sizeof(val);
+ } while (size > 0);
+
+ return (0);
+#else
+ if (RAND_bytes(buf, (int)size) == 0)
+ return (-1);
+ return (0);
+#endif
+}
+
+static int wait_for_dir_kq = -1;
+static int wait_for_file_kq = -1;
+
+int
+wait_for_dir_init(int fd)
+{
+#ifdef HAVE_KQUEUE
+ struct kevent ev;
+ int error, kq;
+
+ PJDLOG_ASSERT(wait_for_dir_kq == -1);
+#endif
+
+ PJDLOG_ASSERT(fd != -1);
+
+#ifdef HAVE_KQUEUE
+ kq = kqueue();
+ if (kq == -1) {
+ pjdlog_errno(LOG_WARNING, "kqueue() failed");
+ return (-1);
+ }
+ EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_WRITE, 0, 0);
+ if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) {
+ error = errno;
+ pjdlog_errno(LOG_WARNING, "kevent() failed");
+ (void)close(kq);
+ errno = error;
+ return (-1);
+ }
+ wait_for_dir_kq = kq;
+#endif
+
+ return (0);
+}
+
+int
+wait_for_file_init(int fd)
+{
+#ifdef HAVE_KQUEUE
+ struct kevent ev[2];
+ int error, kq;
+#endif
+
+ PJDLOG_ASSERT(fd != -1);
+
+#ifdef HAVE_KQUEUE
+ if (wait_for_file_kq != -1) {
+ close(wait_for_file_kq);
+ wait_for_file_kq = -1;
+ }
+
+ kq = kqueue();
+ if (kq == -1) {
+ pjdlog_errno(LOG_WARNING, "kqueue() failed");
+ return (-1);
+ }
+ EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_RENAME, 0, 0);
+ EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
+ 0, 0, 0);
+ if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) {
+ error = errno;
+ pjdlog_errno(LOG_WARNING, "kevent() failed");
+ (void)close(kq);
+ errno = error;
+ return (-1);
+ }
+ wait_for_file_kq = kq;
+#endif
+
+ return (0);
+}
+
+/*
+ * Wait for new file to appear in directory.
+ */
+void
+wait_for_dir(void)
+{
+#ifdef HAVE_KQUEUE
+ struct kevent ev;
+#endif
+
+ if (wait_for_dir_kq == -1) {
+ sleep(1);
+ return;
+ }
+
+#ifdef HAVE_KQUEUE
+ PJDLOG_ASSERT(wait_for_dir_kq != -1);
+
+ if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) {
+ pjdlog_errno(LOG_WARNING, "kevent() failed");
+ sleep(1);
+ }
+#endif
+}
+
+/*
+ * Wait for file growth or rename.
+ */
+void
+wait_for_file(void)
+{
+#ifdef HAVE_KQUEUE
+ struct kevent ev[2];
+#endif
+
+ if (wait_for_file_kq == -1) {
+ sleep(1);
+ return;
+ }
+
+#ifdef HAVE_KQUEUE
+ PJDLOG_ASSERT(wait_for_file_kq != -1);
+
+ if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) {
+ pjdlog_errno(LOG_WARNING, "kevent() failed");
+ sleep(1);
+ }
+#endif
+}
diff --git a/contrib/openbsm/bin/auditdistd/subr.h b/contrib/openbsm/bin/auditdistd/subr.h
new file mode 100644
index 0000000..7e2ddeb
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/subr.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _AUDITDISTD_SUBR_H_
+#define _AUDITDISTD_SUBR_H_
+
+#include <sys/types.h>
+
+#include "auditdistd.h"
+
+#define KEEP_ERRNO(work) do { \
+ int _rerrno; \
+ \
+ _rerrno = errno; \
+ work; \
+ errno = _rerrno; \
+} while (0)
+
+int vsnprlcat(char *str, size_t size, const char *fmt, va_list ap);
+int snprlcat(char *str, size_t size, const char *fmt, ...);
+
+const char *role2str(int role);
+const char *adist_errstr(int error);
+
+void adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq,
+ const char *fmt, ...);
+
+int adist_random(unsigned char *buf, size_t size);
+
+int wait_for_dir_init(int fd);
+int wait_for_file_init(int fd);
+void wait_for_dir(void);
+void wait_for_file(void);
+
+#endif /* !_AUDITDISTD_SUBR_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/synch.h b/contrib/openbsm/bin/auditdistd/synch.h
new file mode 100644
index 0000000..6d83a9b
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/synch.h
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _SYNCH_H_
+#define _SYNCH_H_
+
+#include <errno.h>
+#include <pthread.h>
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
+#include <stdbool.h>
+#include <time.h>
+
+#include "pjdlog.h"
+
+#ifndef PJDLOG_ASSERT
+#include <assert.h>
+#define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
+#endif
+
+static __inline void
+mtx_init(pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_mutex_init(lock, NULL);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+mtx_destroy(pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_mutex_destroy(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+mtx_lock(pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_mutex_lock(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline bool
+mtx_trylock(pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_mutex_trylock(lock);
+ PJDLOG_ASSERT(error == 0 || error == EBUSY);
+ return (error == 0);
+}
+static __inline void
+mtx_unlock(pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_mutex_unlock(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline bool
+mtx_owned(pthread_mutex_t *lock)
+{
+
+ return (pthread_mutex_isowned_np(lock) != 0);
+}
+
+static __inline void
+rw_init(pthread_rwlock_t *lock)
+{
+ int error;
+
+ error = pthread_rwlock_init(lock, NULL);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+rw_destroy(pthread_rwlock_t *lock)
+{
+ int error;
+
+ error = pthread_rwlock_destroy(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+rw_rlock(pthread_rwlock_t *lock)
+{
+ int error;
+
+ error = pthread_rwlock_rdlock(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+rw_wlock(pthread_rwlock_t *lock)
+{
+ int error;
+
+ error = pthread_rwlock_wrlock(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+rw_unlock(pthread_rwlock_t *lock)
+{
+ int error;
+
+ error = pthread_rwlock_unlock(lock);
+ PJDLOG_ASSERT(error == 0);
+}
+
+static __inline void
+cv_init(pthread_cond_t *cv)
+{
+ pthread_condattr_t attr;
+ int error;
+
+ error = pthread_condattr_init(&attr);
+ PJDLOG_ASSERT(error == 0);
+#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
+ error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+ PJDLOG_ASSERT(error == 0);
+#endif
+ error = pthread_cond_init(cv, &attr);
+ PJDLOG_ASSERT(error == 0);
+ error = pthread_condattr_destroy(&attr);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+cv_wait(pthread_cond_t *cv, pthread_mutex_t *lock)
+{
+ int error;
+
+ error = pthread_cond_wait(cv, lock);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline bool
+cv_timedwait(pthread_cond_t *cv, pthread_mutex_t *lock, int timeout)
+{
+ struct timespec ts;
+ int error;
+
+ if (timeout == 0) {
+ cv_wait(cv, lock);
+ return (false);
+ }
+
+#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
+ error = clock_gettime(CLOCK_MONOTONIC, &ts);
+ PJDLOG_ASSERT(error == 0);
+ ts.tv_sec += timeout;
+ error = pthread_cond_timedwait(cv, lock, &ts);
+#elif HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ ts.tv_sec = timeout;
+ ts.tv_nsec = 0;
+ error = pthread_cond_timedwait_relative_np(cv, lock, &ts);
+#else
+#error Neither pthread_condattr_setclock nor pthread_cond_timedwait_relative_np is available.
+#endif
+ PJDLOG_ASSERT(error == 0 || error == ETIMEDOUT);
+ return (error == ETIMEDOUT);
+}
+static __inline void
+cv_signal(pthread_cond_t *cv)
+{
+ int error;
+
+ error = pthread_cond_signal(cv);
+ PJDLOG_ASSERT(error == 0);
+}
+static __inline void
+cv_broadcast(pthread_cond_t *cv)
+{
+ int error;
+
+ error = pthread_cond_broadcast(cv);
+ PJDLOG_ASSERT(error == 0);
+}
+#endif /* !_SYNCH_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/token.l b/contrib/openbsm/bin/auditdistd/token.l
new file mode 100644
index 0000000..e3c4624
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/token.l
@@ -0,0 +1,82 @@
+%{
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAVE_STRNDUP
+#include "strndup.h"
+#endif
+
+#include "auditdistd.h"
+
+#include "parse.h"
+
+#define SECTION_GLOBAL 0
+#define SECTION_SENDER 1
+#define SECTION_RECEIVER 2
+
+int cursection;
+int depth;
+int lineno;
+
+#define DP do { } while (0)
+#define YY_DECL int yylex(void)
+%}
+
+%option noinput
+%option nounput
+%option noyywrap
+
+%%
+certfile { DP; return CERTFILE; }
+directory { DP; return DIRECTORY; }
+fingerprint { DP; return FINGERPRINT; }
+host { DP; return HOST; }
+keyfile { DP; return KEYFILE; }
+listen { DP; return LISTEN; }
+name { DP; return NAME; }
+password { DP; return PASSWORD; }
+pidfile { DP; return PIDFILE; }
+receiver { DP; return RECEIVER; }
+remote { DP; return REMOTE; }
+sender { DP; return SENDER; }
+source { DP; return SOURCE; }
+timeout { DP; return TIMEOUT; }
+[0-9]+ { DP; yylval.num = atoi(yytext); return NUM; }
+\"[a-zA-Z0-9_/ !@#\$%\^\&\*\(\)\+\=\|\;\?\,\.\[\]\-\:]*\" { DP; yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; }
+\{ { DP; depth++; return OB; }
+\} { DP; depth--; return CB; }
+#.*$ /* ignore comments */;
+\n { lineno++; }
+[ \t]+ /* ignore whitespace */;
+%%
diff --git a/contrib/openbsm/bin/auditdistd/trail.c b/contrib/openbsm/bin/auditdistd/trail.c
new file mode 100644
index 0000000..b8a9881
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/trail.c
@@ -0,0 +1,609 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#include <config/config.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <compat/compat.h>
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+#ifndef HAVE_FACCESSAT
+#include "faccessat.h"
+#endif
+#ifndef HAVE_FSTATAT
+#include "fstatat.h"
+#endif
+#ifndef HAVE_OPENAT
+#include "openat.h"
+#endif
+#ifndef HAVE_UNLINKAT
+#include "unlinkat.h"
+#endif
+
+#include "pjdlog.h"
+#include "trail.h"
+
+#define TRAIL_MAGIC 0x79a11
+struct trail {
+ int tr_magic;
+ /* Path usually to /var/audit/dist/ directory. */
+ char tr_dirname[PATH_MAX];
+ /* Descriptor to td_dirname directory. */
+ DIR *tr_dirfp;
+ /* Path to audit trail file. */
+ char tr_filename[PATH_MAX];
+ /* Descriptor to audit trail file. */
+ int tr_filefd;
+};
+
+#define HALF_LEN 14
+
+bool
+trail_is_not_terminated(const char *filename)
+{
+
+ return (strcmp(filename + HALF_LEN, ".not_terminated") == 0);
+}
+
+bool
+trail_is_crash_recovery(const char *filename)
+{
+
+ return (strcmp(filename + HALF_LEN, ".crash_recovery") == 0);
+}
+
+struct trail *
+trail_new(const char *dirname, bool create)
+{
+ struct trail *trail;
+
+ trail = calloc(1, sizeof(*trail));
+
+ if (strlcpy(trail->tr_dirname, dirname, sizeof(trail->tr_dirname)) >=
+ sizeof(trail->tr_dirname)) {
+ free(trail);
+ pjdlog_error("Directory name too long (\"%s\").", dirname);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ trail->tr_dirfp = opendir(dirname);
+ if (trail->tr_dirfp == NULL) {
+ if (create && errno == ENOENT) {
+ if (mkdir(dirname, 0700) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to create directory \"%s\"",
+ dirname);
+ free(trail);
+ return (NULL);
+ }
+ /* TODO: Set directory ownership. */
+ } else {
+ pjdlog_errno(LOG_ERR,
+ "Unable to open directory \"%s\"",
+ dirname);
+ free(trail);
+ return (NULL);
+ }
+ trail->tr_dirfp = opendir(dirname);
+ if (trail->tr_dirfp == NULL) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to open directory \"%s\"",
+ dirname);
+ free(trail);
+ return (NULL);
+ }
+ }
+ trail->tr_filefd = -1;
+ trail->tr_magic = TRAIL_MAGIC;
+ return (trail);
+}
+
+void
+trail_free(struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+
+ if (trail->tr_filefd != -1)
+ trail_close(trail);
+ closedir(trail->tr_dirfp);
+ bzero(trail, sizeof(*trail));
+ trail->tr_magic = 0;
+ trail->tr_filefd = -1;
+ free(trail);
+}
+
+static uint8_t
+trail_type(DIR *dirfp, const char *filename)
+{
+ struct stat sb;
+ int dfd;
+
+ PJDLOG_ASSERT(dirfp != NULL);
+
+ dfd = dirfd(dirfp);
+ PJDLOG_ASSERT(dfd >= 0);
+ if (fstatat(dfd, filename, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to stat \"%s\"", filename);
+ return (DT_UNKNOWN);
+ }
+ return (IFTODT(sb.st_mode));
+}
+
+/*
+ * Find trail file by first part of the name in case it was renamed.
+ * First part of the trail file name never changes, but trail file
+ * can be renamed when hosts are disconnected from .not_terminated
+ * to .[0-9]{14} or to .crash_recovery.
+ */
+static bool
+trail_find(struct trail *trail)
+{
+ struct dirent *dp;
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(trail_is_not_terminated(trail->tr_filename));
+
+ rewinddir(trail->tr_dirfp);
+ while ((dp = readdir(trail->tr_dirfp)) != NULL) {
+ if (strncmp(dp->d_name, trail->tr_filename, HALF_LEN + 1) == 0)
+ break;
+ }
+ if (dp == NULL)
+ return (false);
+ PJDLOG_VERIFY(strlcpy(trail->tr_filename, dp->d_name,
+ sizeof(trail->tr_filename)) < sizeof(trail->tr_filename));
+ return (true);
+}
+
+/*
+ * Open the given trail file and move pointer at the given offset, as this is
+ * where receiver finished the last time.
+ * If the file doesn't exist or the given offset is equal to the file size,
+ * move to the next trail file.
+ */
+void
+trail_start(struct trail *trail, const char *filename, off_t offset)
+{
+ struct stat sb;
+ int dfd, fd;
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+
+ PJDLOG_VERIFY(strlcpy(trail->tr_filename, filename,
+ sizeof(trail->tr_filename)) < sizeof(trail->tr_filename));
+ trail->tr_filefd = -1;
+
+ if (trail->tr_filename[0] == '\0') {
+ PJDLOG_ASSERT(offset == 0);
+ trail_next(trail);
+ return;
+ }
+
+ dfd = dirfd(trail->tr_dirfp);
+ PJDLOG_ASSERT(dfd >= 0);
+again:
+ fd = openat(dfd, trail->tr_filename, O_RDONLY);
+ if (fd == -1) {
+ if (errno == ENOENT &&
+ trail_is_not_terminated(trail->tr_filename) &&
+ trail_find(trail)) {
+ /* File was renamed. Retry with new name. */
+ pjdlog_debug(1,
+ "Trail file was renamed since last connection to \"%s/%s\".",
+ trail->tr_dirname, trail->tr_filename);
+ goto again;
+ } else if (errno == ENOENT) {
+ /* File disappeared. */
+ pjdlog_debug(1, "File \"%s/%s\" doesn't exist.",
+ trail->tr_dirname, trail->tr_filename);
+ } else {
+ pjdlog_errno(LOG_ERR,
+ "Unable to open file \"%s/%s\", skipping",
+ trail->tr_dirname, trail->tr_filename);
+ }
+ trail_next(trail);
+ return;
+ }
+ if (fstat(fd, &sb) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to stat file \"%s/%s\", skipping",
+ trail->tr_dirname, trail->tr_filename);
+ close(fd);
+ trail_next(trail);
+ return;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ pjdlog_warning("File \"%s/%s\" is not a regular file, skipping.",
+ trail->tr_dirname, trail->tr_filename);
+ close(fd);
+ trail_next(trail);
+ return;
+ }
+ /*
+ * We continue sending requested file if:
+ * 1. It is not fully sent yet, or
+ * 2. It is fully sent, but is not terminated, so new data can be
+ * appended still, or
+ * 3. It is fully sent but file name has changed.
+ *
+ * Note that we are fine if our .not_terminated or .crash_recovery file
+ * is smaller than the one on the receiver side, as it is possible that
+ * more data was send to the receiver than was safely stored on disk.
+ * We accept .not_terminated only because auditdistd can start before
+ * auditd manage to rename it to .crash_recovery.
+ */
+ if (offset < sb.st_size ||
+ (offset >= sb.st_size &&
+ trail_is_not_terminated(trail->tr_filename)) ||
+ (offset >= sb.st_size && trail_is_not_terminated(filename) &&
+ trail_is_crash_recovery(trail->tr_filename))) {
+ /* File was not fully send. Let's finish it. */
+ if (lseek(fd, offset, SEEK_SET) == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to move to offset %jd within file \"%s/%s\", skipping",
+ (intmax_t)offset, trail->tr_dirname,
+ trail->tr_filename);
+ close(fd);
+ trail_next(trail);
+ return;
+ }
+ if (!trail_is_crash_recovery(trail->tr_filename)) {
+ pjdlog_debug(1,
+ "Restarting file \"%s/%s\" at offset %jd.",
+ trail->tr_dirname, trail->tr_filename,
+ (intmax_t)offset);
+ }
+ trail->tr_filefd = fd;
+ return;
+ }
+ close(fd);
+ if (offset > sb.st_size) {
+ pjdlog_warning("File \"%s/%s\" shrinked, removing it.",
+ trail->tr_dirname, trail->tr_filename);
+ } else {
+ pjdlog_debug(1, "File \"%s/%s\" is already sent, removing it.",
+ trail->tr_dirname, trail->tr_filename);
+ }
+ /* Entire file is already sent or it shirnked, we can remove it. */
+ if (unlinkat(dfd, trail->tr_filename, 0) == -1) {
+ pjdlog_errno(LOG_WARNING, "Unable to remove file \"%s/%s\"",
+ trail->tr_dirname, trail->tr_filename);
+ }
+ trail_next(trail);
+}
+
+/*
+ * Set next file in the trail->tr_dirname directory and open it for reading.
+ */
+void
+trail_next(struct trail *trail)
+{
+ char curfile[PATH_MAX];
+ struct dirent *dp;
+ int dfd;
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(trail->tr_filefd == -1);
+
+again:
+ curfile[0] = '\0';
+
+ rewinddir(trail->tr_dirfp);
+ while ((dp = readdir(trail->tr_dirfp)) != NULL) {
+ if (dp->d_name[0] < '0' || dp->d_name[0] > '9')
+ continue;
+ if (dp->d_type == DT_UNKNOWN)
+ dp->d_type = trail_type(trail->tr_dirfp, dp->d_name);
+ /* We are only interested in regular files, skip the rest. */
+ if (dp->d_type != DT_REG) {
+ pjdlog_debug(1,
+ "File \"%s/%s\" is not a regular file, skipping.",
+ trail->tr_dirname, dp->d_name);
+ continue;
+ }
+ /* Skip all files "greater" than curfile. */
+ if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) > 0)
+ continue;
+ /* Skip all files "smaller" than the current trail_filename. */
+ if (trail->tr_filename[0] != '\0' &&
+ strcmp(dp->d_name, trail->tr_filename) <= 0) {
+ continue;
+ }
+ PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) <
+ sizeof(curfile));
+ }
+ if (curfile[0] == '\0') {
+ /*
+ * There are no new trail files, so we return.
+ * We don't clear trail_filename string, to know where to
+ * start when new file appears.
+ */
+ PJDLOG_ASSERT(trail->tr_filefd == -1);
+ pjdlog_debug(1, "No new trail files.");
+ return;
+ }
+ PJDLOG_VERIFY(strlcpy(trail->tr_filename, curfile,
+ sizeof(trail->tr_filename)) < sizeof(trail->tr_filename));
+ dfd = dirfd(trail->tr_dirfp);
+ PJDLOG_ASSERT(dfd >= 0);
+ trail->tr_filefd = openat(dfd, trail->tr_filename, O_RDONLY);
+ if (trail->tr_filefd == -1) {
+ pjdlog_errno(LOG_ERR,
+ "Unable to open file \"%s/%s\", skipping",
+ trail->tr_dirname, trail->tr_filename);
+ goto again;
+ }
+ pjdlog_debug(1, "Found next trail file: \"%s/%s\".", trail->tr_dirname,
+ trail->tr_filename);
+}
+
+/*
+ * Close current trial file.
+ */
+void
+trail_close(struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(trail->tr_filefd >= 0);
+ PJDLOG_ASSERT(trail->tr_filename[0] != '\0');
+
+ PJDLOG_VERIFY(close(trail->tr_filefd) == 0);
+ trail->tr_filefd = -1;
+}
+
+/*
+ * Reset trail state. Used when connection is disconnected and we will
+ * need to start over after reconnect. Trail needs to be already closed.
+ */
+void
+trail_reset(struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(trail->tr_filefd == -1);
+
+ trail->tr_filename[0] = '\0';
+}
+
+/*
+ * Unlink current trial file.
+ */
+void
+trail_unlink(struct trail *trail, const char *filename)
+{
+ int dfd;
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(filename != NULL);
+ PJDLOG_ASSERT(filename[0] != '\0');
+
+ dfd = dirfd(trail->tr_dirfp);
+ PJDLOG_ASSERT(dfd >= 0);
+
+ if (unlinkat(dfd, filename, 0) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to remove \"%s/%s\"",
+ trail->tr_dirname, filename);
+ } else {
+ pjdlog_debug(1, "Trail file \"%s/%s\" removed.",
+ trail->tr_dirname, filename);
+ }
+}
+
+/*
+ * Return true if we should switch to next trail file.
+ * We don't switch if our file name ends with ".not_terminated" and it
+ * exists (ie. wasn't renamed).
+ */
+bool
+trail_switch(struct trail *trail)
+{
+ char filename[PATH_MAX];
+ int fd;
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+ PJDLOG_ASSERT(trail->tr_filefd >= 0);
+
+ if (!trail_is_not_terminated(trail->tr_filename))
+ return (true);
+ fd = dirfd(trail->tr_dirfp);
+ PJDLOG_ASSERT(fd >= 0);
+ if (faccessat(fd, trail->tr_filename, F_OK, 0) == 0)
+ return (false);
+ if (errno != ENOENT) {
+ pjdlog_errno(LOG_ERR, "Unable to access file \"%s/%s\"",
+ trail->tr_dirname, trail->tr_filename);
+ }
+ strlcpy(filename, trail->tr_filename, sizeof(filename));
+ if (!trail_find(trail)) {
+ pjdlog_error("Trail file \"%s/%s\" disappeared.",
+ trail->tr_dirname, trail->tr_filename);
+ return (true);
+ }
+ pjdlog_debug(1, "Trail file \"%s/%s\" was renamed to \"%s/%s\".",
+ trail->tr_dirname, filename, trail->tr_dirname,
+ trail->tr_filename);
+ return (true);
+}
+
+const char *
+trail_filename(const struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+
+ return (trail->tr_filename);
+}
+
+int
+trail_filefd(const struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+
+ return (trail->tr_filefd);
+}
+
+int
+trail_dirfd(const struct trail *trail)
+{
+
+ PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC);
+
+ return (dirfd(trail->tr_dirfp));
+}
+
+/*
+ * Find the last file in the directory opened under dirfp.
+ */
+void
+trail_last(DIR *dirfp, char *filename, size_t filenamesize)
+{
+ char curfile[PATH_MAX];
+ struct dirent *dp;
+
+ PJDLOG_ASSERT(dirfp != NULL);
+
+ curfile[0] = '\0';
+
+ rewinddir(dirfp);
+ while ((dp = readdir(dirfp)) != NULL) {
+ if (dp->d_name[0] < '0' || dp->d_name[0] > '9')
+ continue;
+ if (dp->d_type == DT_UNKNOWN)
+ dp->d_type = trail_type(dirfp, dp->d_name);
+ /* We are only interested in regular files, skip the rest. */
+ if (dp->d_type != DT_REG)
+ continue;
+ /* Skip all files "greater" than curfile. */
+ if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) < 0)
+ continue;
+ PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) <
+ sizeof(curfile));
+ }
+ if (curfile[0] == '\0') {
+ /*
+ * There are no trail files, so we return.
+ */
+ pjdlog_debug(1, "No trail files.");
+ bzero(filename, filenamesize);
+ return;
+ }
+ PJDLOG_VERIFY(strlcpy(filename, curfile, filenamesize) < filenamesize);
+ pjdlog_debug(1, "Found the most recent trail file: \"%s\".", filename);
+}
+
+/*
+ * Check if the given file name is a valid audit trail file name.
+ * Possible names:
+ * 20120106132657.20120106132805
+ * 20120106132657.not_terminated
+ * 20120106132657.crash_recovery
+ * If two names are given, check if the first name can be renamed
+ * to the second name. When renaming, first part of the name has
+ * to be identical and only the following renames are valid:
+ * 20120106132657.not_terminated -> 20120106132657.20120106132805
+ * 20120106132657.not_terminated -> 20120106132657.crash_recovery
+ */
+bool
+trail_validate_name(const char *srcname, const char *dstname)
+{
+ int i;
+
+ PJDLOG_ASSERT(srcname != NULL);
+
+ if (strlen(srcname) != 2 * HALF_LEN + 1)
+ return (false);
+ if (srcname[HALF_LEN] != '.')
+ return (false);
+ for (i = 0; i < HALF_LEN; i++) {
+ if (srcname[i] < '0' || srcname[i] > '9')
+ return (false);
+ }
+ for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) {
+ if (srcname[i] < '0' || srcname[i] > '9')
+ break;
+ }
+ if (i < 2 * HALF_LEN - 1 &&
+ strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0 &&
+ strcmp(srcname + HALF_LEN + 1, "crash_recovery") != 0) {
+ return (false);
+ }
+
+ if (dstname == NULL)
+ return (true);
+
+ /* We tolarate if both names are identical. */
+ if (strcmp(srcname, dstname) == 0)
+ return (true);
+
+ /* We can only rename not_terminated files. */
+ if (strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0)
+ return (false);
+ if (strlen(dstname) != 2 * HALF_LEN + 1)
+ return (false);
+ if (strncmp(srcname, dstname, HALF_LEN + 1) != 0)
+ return (false);
+ for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) {
+ if (dstname[i] < '0' || dstname[i] > '9')
+ break;
+ }
+ if (i < 2 * HALF_LEN - 1 &&
+ strcmp(dstname + HALF_LEN + 1, "crash_recovery") != 0) {
+ return (false);
+ }
+
+ return (true);
+}
+
+int
+trail_name_compare(const char *name0, const char *name1)
+{
+ int ret;
+
+ ret = strcmp(name0, name1);
+ if (ret == 0)
+ return (TRAIL_IDENTICAL);
+ if (strncmp(name0, name1, HALF_LEN + 1) == 0)
+ return (TRAIL_RENAMED);
+ return (ret < 0 ? TRAIL_OLDER : TRAIL_NEWER);
+}
diff --git a/contrib/openbsm/bin/auditdistd/trail.h b/contrib/openbsm/bin/auditdistd/trail.h
new file mode 100644
index 0000000..204ea2b
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/trail.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _AUDITDISTD_TRAIL_H_
+#define _AUDITDISTD_TRAIL_H_
+
+#include <stdbool.h>
+#include <unistd.h> /* off_t */
+
+#define TRAIL_IDENTICAL 0
+#define TRAIL_RENAMED 1
+#define TRAIL_OLDER 2
+#define TRAIL_NEWER 3
+
+struct trail;
+
+struct trail *trail_new(const char *dirname, bool create);
+void trail_free(struct trail *trail);
+bool trail_is_not_terminated(const char *filename);
+bool trail_is_crash_recovery(const char *filename);
+void trail_start(struct trail *trail, const char *filename, off_t offset);
+void trail_next(struct trail *trail);
+void trail_close(struct trail *trail);
+void trail_reset(struct trail *trail);
+void trail_unlink(struct trail *trail, const char *filename);
+bool trail_switch(struct trail *trail);
+const char *trail_filename(const struct trail *trail);
+int trail_filefd(const struct trail *trail);
+int trail_dirfd(const struct trail *trail);
+void trail_last(DIR *dirfp, char *filename, size_t filenamesize);
+bool trail_validate_name(const char *srcname, const char *dstname);
+int trail_name_compare(const char *name0, const char *name1);
+
+#endif /* !_AUDITDISTD_TRAIL_H_ */
diff --git a/contrib/openbsm/bin/auditdistd/unlinkat.h b/contrib/openbsm/bin/auditdistd/unlinkat.h
new file mode 100644
index 0000000..6364208
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/unlinkat.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND 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 THE AUTHORS OR 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.
+ */
+
+#ifndef _UNLINKAT_H_
+#define _UNLINKAT_H_
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#define AT_REMOVEDIR 0x01
+
+static int
+unlinkat(int fd, const char *path, int flag)
+{
+ int cfd, error, ret;
+
+ cfd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cfd == -1)
+ return (-1);
+
+ if (fchdir(fd) == -1) {
+ error = errno;
+ (void)close(cfd);
+ errno = error;
+ return (-1);
+ }
+
+ if (flag == AT_REMOVEDIR)
+ ret = rmdir(path);
+ else
+ ret = unlink(path);
+
+ error = errno;
+ (void)fchdir(cfd);
+ (void)close(cfd);
+ errno = error;
+ return (ret);
+}
+
+#endif /* !_UNLINKAT_H_ */
diff --git a/contrib/openbsm/bin/auditfilterd/Makefile.am b/contrib/openbsm/bin/auditfilterd/Makefile.am
new file mode 100644
index 0000000..400a1d9
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/Makefile.am
@@ -0,0 +1,10 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = auditfilterd
+auditfilterd_SOURCES = auditfilterd_conf.c auditfilterd.c
+auditfilterd_LDADD = $(top_builddir)/libbsm/libbsm.la
+man8_MANS = auditfilterd.8
diff --git a/contrib/openbsm/bin/auditfilterd/Makefile.in b/contrib/openbsm/bin/auditfilterd/Makefile.in
new file mode 100644
index 0000000..e90f7d7
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/Makefile.in
@@ -0,0 +1,649 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = auditfilterd$(EXEEXT)
+subdir = bin/auditfilterd
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_auditfilterd_OBJECTS = auditfilterd_conf.$(OBJEXT) \
+ auditfilterd.$(OBJEXT)
+auditfilterd_OBJECTS = $(am_auditfilterd_OBJECTS)
+auditfilterd_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(auditfilterd_SOURCES)
+DIST_SOURCES = $(auditfilterd_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man8_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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)
+auditfilterd_SOURCES = auditfilterd_conf.c auditfilterd.c
+auditfilterd_LDADD = $(top_builddir)/libbsm/libbsm.la
+man8_MANS = auditfilterd.8
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditfilterd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/auditfilterd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+auditfilterd$(EXEEXT): $(auditfilterd_OBJECTS) $(auditfilterd_DEPENDENCIES) $(EXTRA_auditfilterd_DEPENDENCIES)
+ @rm -f auditfilterd$(EXEEXT)
+ $(LINK) $(auditfilterd_OBJECTS) $(auditfilterd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditfilterd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditfilterd_conf.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man8: $(man8_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man8_MANS)'; \
+ list2=''; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man8 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+
+# 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/auditfilterd/auditfilterd.8 b/contrib/openbsm/bin/auditfilterd/auditfilterd.8
new file mode 100644
index 0000000..f78c664
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.8
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2006 Robert N. M. Watson
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+.\"
+.Dd October 3, 2006
+.Dt AUDITFILTERD 8
+.Os
+.Sh NAME
+.Nm auditfilterd
+.Nd audit filter daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl c Ar conffile
+.Op Fl p Ar pipefile
+.Op Fl t Ar trailfile
+.Sh DESCRIPTION
+The
+.Nm
+daemon is an extensible audit event monitoring daemon, allowing pluggable
+modules to track audit events from a live audit source.
+It is configured using the audit_filter configuration file.
+The source can either be a pipe or a file.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl c Ar conffile
+Specify an alternative configuration file.
+.It Fl d
+Starts the daemon in debug mode \[em] it will not daemonize.
+.It Fl p Ar pipefile
+Specify a pipe as an alternative source of audit event records.
+Default is
+.Pa /dev/auditpipe .
+.It Fl t Ar trailfile
+Specify a file as an alternative source of audit event records.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /etc/security/audit_filterd" -compact
+.It Pa /etc/security/audit_filterd
+Default configuration file for
+.Nm .
+.It Pa /dev/auditpipe
+Default audit record source for
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr audit 8 ,
+.Xr auditd 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.
+It was subsequently adopted by the TrustedBSD Project as the foundation for
+the OpenBSM distribution.
+.Sh AUTHORS
+The
+.Nm
+daemon and audit filter APIs were created by
+.An Robert Watson .
+.Sh BUGS
+.Nm
+is experimental, and should not be relied on in production.
+APIs and services it offers can and will change in future OpenBSM releases.
diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd.c b/contrib/openbsm/bin/auditfilterd/auditfilterd.c
new file mode 100644
index 0000000..46c86b2
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.c
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+ */
+
+/*
+ * Main file for the audit filter daemon, which presents audit records to a
+ * set of run-time registered loadable modules. This is the main event loop
+ * of the daemon, which handles starting up, waiting for records, and
+ * presenting records to configured modules. auditfilterd_conf.c handles the
+ * reading and management of the configuration, module list and module state,
+ * etc.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <config/config.h>
+#ifdef HAVE_FULL_QUEUE_H
+#include <sys/queue.h>
+#else
+#include <compat/queue.h>
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+#include <compat/clock_gettime.h>
+#endif
+
+#include <bsm/libbsm.h>
+#include <bsm/audit_filter.h>
+#include <bsm/audit_internal.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "auditfilterd.h"
+
+/*
+ * Global list of registered filters.
+ */
+struct auditfilter_module_list filter_list;
+
+/*
+ * Configuration and signal->main flags.
+ */
+int debug; /* Debugging mode requested, don't detach. */
+int reread_config; /* SIGHUP has been received. */
+int quit; /* SIGQUIT/TERM/INT has been received. */
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "auditfilterd [-d] [-c conffile] [-p pipefile]"
+ " [-t trailfile]\n");
+ fprintf(stderr, " -c Specify configuration file (default: %s)\n",
+ AUDITFILTERD_CONFFILE);
+ fprintf(stderr, " -d Debugging mode, don't daemonize\n");
+ fprintf(stderr, " -p Specify pipe file (default: %s)\n",
+ AUDITFILTERD_PIPEFILE);
+ fprintf(stderr, " -t Specify audit trail file (default: none)\n");
+ exit(-1);
+}
+
+static void
+auditfilterd_init(void)
+{
+
+ TAILQ_INIT(&filter_list);
+}
+
+static void
+signal_handler(int signum)
+{
+
+ switch (signum) {
+ case SIGHUP:
+ reread_config++;
+ break;
+
+ case SIGINT:
+ case SIGTERM:
+ case SIGQUIT:
+ quit++;
+ break;
+ }
+}
+
+/*
+ * Present raw BSM to a set of registered and interested filters.
+ */
+static void
+present_rawrecord(struct timespec *ts, u_char *data, u_int len)
+{
+ struct auditfilter_module *am;
+
+ TAILQ_FOREACH(am, &filter_list, am_list) {
+ if (am->am_rawrecord != NULL)
+ (am->am_rawrecord)(am, ts, data, len);
+ }
+}
+
+/*
+ * Parse the BSM into a set of tokens, which will be passed to registered
+ * and interested filters.
+ */
+#define MAX_TOKENS 128 /* Maximum tokens we handle per record. */
+static void
+present_tokens(struct timespec *ts, u_char *data, u_int len)
+{
+ struct auditfilter_module *am;
+ tokenstr_t tokens[MAX_TOKENS];
+ u_int bytesread;
+ int tokencount;
+
+ tokencount = 0;
+ while (bytesread < len) {
+ if (au_fetch_tok(&tokens[tokencount], data + bytesread,
+ len - bytesread) == -1)
+ break;
+ bytesread += tokens[tokencount].len;
+ tokencount++;
+ }
+
+ TAILQ_FOREACH(am, &filter_list, am_list) {
+ if (am->am_record != NULL)
+ (am->am_record)(am, ts, tokencount, tokens);
+ }
+}
+
+/*
+ * The main loop spins pulling records out of the record source and passing
+ * them to modules for processing.
+ */
+static void
+mainloop_file(const char *conffile, const char *trailfile, FILE *trail_fp)
+{
+ struct timespec ts;
+ FILE *conf_fp;
+ u_char *buf;
+ int reclen;
+
+ while (1) {
+ /*
+ * On SIGHUP, we reread the configuration file and reopen
+ * the trail file.
+ */
+ if (reread_config) {
+ reread_config = 0;
+ warnx("rereading configuration");
+ conf_fp = fopen(conffile, "r");
+ if (conf_fp == NULL)
+ err(-1, "%s", conffile);
+ auditfilterd_conf(conffile, conf_fp);
+ fclose(conf_fp);
+
+ fclose(trail_fp);
+ trail_fp = fopen(trailfile, "r");
+ if (trail_fp == NULL)
+ err(-1, "%s", trailfile);
+ }
+ if (quit) {
+ warnx("quitting");
+ break;
+ }
+
+ /*
+ * For now, be relatively unrobust about incomplete records,
+ * but in the future will want to do better. Need to look
+ * more at the right blocking and signal behavior here.
+ */
+ reclen = au_read_rec(trail_fp, &buf);
+ if (reclen == -1)
+ continue;
+ if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
+ err(-1, "clock_gettime");
+ present_rawrecord(&ts, buf, reclen);
+ present_tokens(&ts, buf, reclen);
+ free(buf);
+ }
+}
+
+/*
+ * The main loop spins pulling records out of the record source and passing
+ * them to modules for processing. This version of the function accepts
+ * discrete record input from a file descriptor, as opposed to buffered input
+ * from a file stream.
+ */
+static void
+mainloop_pipe(const char *conffile, const char *pipefile __unused, int pipe_fd)
+{
+ u_char record[MAX_AUDIT_RECORD_SIZE];
+ struct timespec ts;
+ FILE *conf_fp;
+ int reclen;
+
+ while (1) {
+ /*
+ * On SIGHUP, we reread the configuration file. Unlike with
+ * a trail file, we don't reopen the pipe, as we don't want
+ * to miss records which will be flushed if we do.
+ */
+ if (reread_config) {
+ reread_config = 0;
+ warnx("rereading configuration");
+ conf_fp = fopen(conffile, "r");
+ if (conf_fp == NULL)
+ err(-1, "%s", conffile);
+ auditfilterd_conf(conffile, conf_fp);
+ fclose(conf_fp);
+ }
+ if (quit) {
+ warnx("quitting");
+ break;
+ }
+
+ /*
+ * For now, be relatively unrobust about incomplete records,
+ * but in the future will want to do better. Need to look
+ * more at the right blocking and signal behavior here.
+ */
+ reclen = read(pipe_fd, record, MAX_AUDIT_RECORD_SIZE);
+ if (reclen < 0)
+ continue;
+ if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
+ err(-1, "clock_gettime");
+ present_rawrecord(&ts, record, reclen);
+ present_tokens(&ts, record, reclen);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *pipefile, *trailfile, *conffile;
+ FILE *trail_fp, *conf_fp;
+ struct stat sb;
+ int pipe_fd;
+ int ch;
+
+ conffile = AUDITFILTERD_CONFFILE;
+ trailfile = NULL;
+ pipefile = NULL;
+ while ((ch = getopt(argc, argv, "c:dp:t:")) != -1) {
+ switch (ch) {
+ case 'c':
+ conffile = optarg;
+ break;
+
+ case 'd':
+ debug++;
+ break;
+
+ case 't':
+ if (trailfile != NULL || pipefile != NULL)
+ usage();
+ trailfile = optarg;
+ break;
+
+ case 'p':
+ if (pipefile != NULL || trailfile != NULL)
+ usage();
+ pipefile = optarg;
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ usage();
+
+ /*
+ * We allow only one of a pipe or a trail to be used. If none is
+ * specified, we provide a default pipe path.
+ */
+ if (pipefile == NULL && trailfile == NULL)
+ pipefile = AUDITFILTERD_PIPEFILE;
+
+ if (pipefile != NULL) {
+ pipe_fd = open(pipefile, O_RDONLY);
+ if (pipe_fd < 0)
+ err(-1, "open:%s", pipefile);
+ if (fstat(pipe_fd, &sb) < 0)
+ err(-1, "stat: %s", pipefile);
+ if (!S_ISCHR(sb.st_mode))
+ errx(-1, "fstat: %s not device", pipefile);
+ } else {
+ trail_fp = fopen(trailfile, "r");
+ if (trail_fp == NULL)
+ err(-1, "%s", trailfile);
+ }
+
+ conf_fp = fopen(conffile, "r");
+ if (conf_fp == NULL)
+ err(-1, "%s", conffile);
+
+ auditfilterd_init();
+ if (auditfilterd_conf(conffile, conf_fp) < 0)
+ exit(-1);
+ fclose(conf_fp);
+
+ if (!debug) {
+ if (daemon(0, 0) < 0)
+ err(-1, "daemon");
+ }
+
+ signal(SIGHUP, signal_handler);
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ if (pipefile != NULL)
+ mainloop_pipe(conffile, pipefile, pipe_fd);
+ else
+ mainloop_file(conffile, trailfile, trail_fp);
+
+ auditfilterd_conf_shutdown();
+ return (0);
+}
diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd.h b/contrib/openbsm/bin/auditfilterd/auditfilterd.h
new file mode 100644
index 0000000..c178b82
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.h
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+ */
+
+#define AUDITFILTERD_CONFFILE "/etc/security/audit_filter"
+#define AUDITFILTERD_PIPEFILE "/dev/auditpipe"
+
+/*
+ * Limit on the number of arguments that can appear in an audit_filterd
+ * configuration line.
+ */
+#define AUDITFILTERD_CONF_MAXARGS 256
+
+/*
+ * Data structure description each instantiated module.
+ */
+struct auditfilter_module {
+ /*
+ * Fields from configuration file and dynamic linker.
+ */
+ char *am_modulename;
+ char *am_arg_buffer;
+ int am_argc;
+ char **am_argv;
+ void *am_dlhandle;
+
+ /*
+ * Fields provided by or extracted from the module.
+ */
+ void *am_cookie;
+ audit_filter_attach_t am_attach;
+ audit_filter_reinit_t am_reinit;
+ audit_filter_record_t am_record;
+ audit_filter_rawrecord_t am_rawrecord;
+ audit_filter_detach_t am_detach;
+
+ /*
+ * Fields for maintaining the list of modules.
+ */
+ TAILQ_ENTRY(auditfilter_module) am_list;
+};
+TAILQ_HEAD(auditfilter_module_list, auditfilter_module);
+
+/*
+ * List of currently registered modules.
+ */
+extern struct auditfilter_module_list filter_list;
+
+/*
+ * Function definitions.
+ */
+int auditfilterd_conf(const char *filename, FILE *fp);
+void auditfilterd_conf_shutdown(void);
diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c b/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c
new file mode 100644
index 0000000..bf3b3bb
--- /dev/null
+++ b/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c
@@ -0,0 +1,511 @@
+/*-
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+ */
+
+/*
+ * Configuration file parser for auditfilterd. The configuration file is a
+ * very simple format, similar to other BSM configuration files, consisting
+ * of configuration entries of one line each. The configuration function is
+ * aware of previous runs, and will update the current configuration as
+ * needed.
+ *
+ * Modules are in one of two states: attached, or detached. If attach fails,
+ * detach is not called because it was not attached. If a module is attached
+ * and a call to its reinit method fails, we will detach it.
+ *
+ * Modules are passed a (void *) reference to their configuration state so
+ * that they may pass this into any common APIs we provide which may rely on
+ * that state. Currently, the only such API is the cookie API, which allows
+ * per-instance state to be maintained by a module. In the future, this will
+ * also be used to support per-instance preselection state.
+ */
+
+#include <sys/types.h>
+
+#include <config/config.h>
+#ifdef HAVE_FULL_QUEUE_H
+#include <sys/queue.h>
+#else
+#include <compat/queue.h>
+#endif
+
+#include <bsm/libbsm.h>
+#include <bsm/audit_filter.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "auditfilterd.h"
+
+/*
+ * Free an individual auditfilter_module structure. Will not shut down the
+ * module, just frees the memory. Does so conditional on pointers being
+ * non-NULL so that it can be used on partially allocated structures.
+ */
+static void
+auditfilter_module_free(struct auditfilter_module *am)
+{
+
+ if (am->am_modulename != NULL)
+ free(am->am_modulename);
+ if (am->am_arg_buffer != NULL)
+ free(am->am_arg_buffer);
+ if (am->am_argv != NULL)
+ free(am->am_argv);
+}
+
+/*
+ * Free all memory associated with an auditfilter_module list. Does not
+ * dlclose() or shut down the modules, just free the memory. Use
+ * auditfilter_module_list_detach() for that, if required.
+ */
+static void
+auditfilter_module_list_free(struct auditfilter_module_list *list)
+{
+ struct auditfilter_module *am;
+
+ while (!(TAILQ_EMPTY(list))) {
+ am = TAILQ_FIRST(list);
+ TAILQ_REMOVE(list, am, am_list);
+ auditfilter_module_free(am);
+ }
+}
+
+/*
+ * Detach an attached module from an auditfilter_module structure. Does not
+ * free the data structure itself.
+ */
+static void
+auditfilter_module_detach(struct auditfilter_module *am)
+{
+
+ if (am->am_detach != NULL)
+ am->am_detach(am);
+ am->am_cookie = NULL;
+ (void)dlclose(am->am_dlhandle);
+ am->am_dlhandle = NULL;
+}
+
+/*
+ * Walk an auditfilter_module list, detaching each module. Intended to be
+ * combined with auditfilter_module_list_free().
+ */
+static void
+auditfilter_module_list_detach(struct auditfilter_module_list *list)
+{
+ struct auditfilter_module *am;
+
+ TAILQ_FOREACH(am, list, am_list)
+ auditfilter_module_detach(am);
+}
+
+/*
+ * Given a filled out auditfilter_module, use dlopen() and dlsym() to attach
+ * the module. If we fail, leave fields in the state we found them.
+ *
+ * XXXRW: Need a better way to report errors.
+ */
+static int
+auditfilter_module_attach(struct auditfilter_module *am)
+{
+
+ am->am_dlhandle = dlopen(am->am_modulename, RTLD_NOW);
+ if (am->am_dlhandle == NULL) {
+ warnx("auditfilter_module_attach: %s: %s", am->am_modulename,
+ dlerror());
+ return (-1);
+ }
+
+ /*
+ * Not implementing these is not considered a failure condition,
+ * although we might want to consider warning if obvious stuff is
+ * not implemented, such as am_record.
+ */
+ am->am_attach = dlsym(am->am_dlhandle, AUDIT_FILTER_ATTACH_STRING);
+ am->am_reinit = dlsym(am->am_dlhandle, AUDIT_FILTER_REINIT_STRING);
+ am->am_record = dlsym(am->am_dlhandle, AUDIT_FILTER_RECORD_STRING);
+ am->am_rawrecord = dlsym(am->am_dlhandle,
+ AUDIT_FILTER_RAWRECORD_STRING);
+ am->am_detach = dlsym(am->am_dlhandle, AUDIT_FILTER_DETACH_STRING);
+
+ if (am->am_attach != NULL) {
+ if (am->am_attach(am, am->am_argc, am->am_argv)
+ != AUDIT_FILTER_SUCCESS) {
+ warnx("auditfilter_module_attach: %s: failed",
+ am->am_modulename);
+ dlclose(am->am_dlhandle);
+ am->am_dlhandle = NULL;
+ am->am_cookie = NULL;
+ am->am_attach = NULL;
+ am->am_reinit = NULL;
+ am->am_record = NULL;
+ am->am_rawrecord = NULL;
+ am->am_detach = NULL;
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * When the arguments for a module are changed, we notify the module through
+ * a call to its reinit method, if any. Return 0 on success, or -1 on
+ * failure.
+ */
+static int
+auditfilter_module_reinit(struct auditfilter_module *am)
+{
+
+ if (am->am_reinit == NULL)
+ return (0);
+
+ if (am->am_reinit(am, am->am_argc, am->am_argv) !=
+ AUDIT_FILTER_SUCCESS) {
+ warnx("auditfilter_module_reinit: %s: failed",
+ am->am_modulename);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Given a configuration line, generate an auditfilter_module structure that
+ * describes it; caller will not pass comments in, so they are not looked
+ * for. Do not attempt to instantiate it. Will destroy the contents of
+ * 'buffer'.
+ *
+ * Configuration lines consist of two parts: the module name and arguments
+ * separated by a ':', and then a ','-delimited list of arguments.
+ *
+ * XXXRW: Need to decide where to send the warning output -- stderr for now.
+ */
+struct auditfilter_module *
+auditfilter_module_parse(const char *filename, int linenumber, char *buffer)
+{
+ char *arguments, *module, **ap;
+ struct auditfilter_module *am;
+
+ am = malloc(sizeof(*am));
+ if (am == NULL) {
+ warn("auditfilter_module_parse: %s:%d", filename, linenumber);
+ return (NULL);
+ }
+ bzero(am, sizeof(*am));
+
+ /*
+ * First, break out the module and arguments strings. We look for
+ * one extra argument to make sure there are no more :'s in the line.
+ * That way, we prevent modules from using argument strings that, in
+ * the future, may cause problems for adding additional columns.
+ */
+ arguments = buffer;
+ module = strsep(&arguments, ":");
+ if (module == NULL || arguments == NULL) {
+ warnx("auditfilter_module_parse: %s:%d: parse error",
+ filename, linenumber);
+ return (NULL);
+ }
+
+ am->am_modulename = strdup(module);
+ if (am->am_modulename == NULL) {
+ warn("auditfilter_module_parse: %s:%d", filename, linenumber);
+ auditfilter_module_free(am);
+ return (NULL);
+ }
+
+ am->am_arg_buffer = strdup(buffer);
+ if (am->am_arg_buffer == NULL) {
+ warn("auditfilter_module_parse: %s:%d", filename, linenumber);
+ auditfilter_module_free(am);
+ return (NULL);
+ }
+
+ /*
+ * Now, break out the arguments string into a series of arguments.
+ * This is a bit more complicated, and requires cleanup if things go
+ * wrong.
+ */
+ am->am_argv = malloc(sizeof(char *) * AUDITFILTERD_CONF_MAXARGS);
+ if (am->am_argv == NULL) {
+ warn("auditfilter_module_parse: %s:%d", filename, linenumber);
+ auditfilter_module_free(am);
+ return (NULL);
+ }
+ bzero(am->am_argv, sizeof(char *) * AUDITFILTERD_CONF_MAXARGS);
+ am->am_argc = 0;
+ for (ap = am->am_argv; (*ap = strsep(&arguments, " \t")) != NULL;) {
+ if (**ap != '\0') {
+ am->am_argc++;
+ if (++ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS])
+ break;
+ }
+ }
+ if (ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS]) {
+ warnx("auditfilter_module_parse: %s:%d: too many arguments",
+ filename, linenumber);
+ auditfilter_module_free(am);
+ return (NULL);
+ }
+
+ return (am);
+}
+
+/*
+ * Read a configuration file, and populate 'list' with the configuration
+ * lines. Does not attempt to instantiate the configuration, just read it
+ * into a useful set of data structures.
+ */
+static int
+auditfilterd_conf_read(const char *filename, FILE *fp,
+ struct auditfilter_module_list *list)
+{
+ int error, linenumber, syntaxerror;
+ struct auditfilter_module *am;
+ char buffer[LINE_MAX];
+
+ syntaxerror = 0;
+ linenumber = 0;
+ while (!feof(fp) && !ferror(fp)) {
+ if (fgets(buffer, LINE_MAX, fp) == NULL)
+ break;
+ linenumber++;
+ if (buffer[0] == '#' || strlen(buffer) < 1)
+ continue;
+ buffer[strlen(buffer)-1] = '\0';
+ am = auditfilter_module_parse(filename, linenumber, buffer);
+ if (am == NULL) {
+ syntaxerror = 1;
+ break;
+ }
+ TAILQ_INSERT_HEAD(list, am, am_list);
+ }
+
+ /*
+ * File I/O error.
+ */
+ if (ferror(fp)) {
+ error = errno;
+ auditfilter_module_list_free(list);
+ errno = error;
+ return (-1);
+ }
+
+ /*
+ * Syntax error.
+ */
+ if (syntaxerror) {
+ auditfilter_module_list_free(list);
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Apply changes necessary to bring a new configuration into force. The new
+ * configuration data is passed in, and the current configuration is updated
+ * to match it. The contents of 'list' are freed or otherwise disposed of
+ * before return.
+ *
+ * The algorithms here are not very efficient, but this is an infrequent
+ * operation on very short lists.
+ */
+static void
+auditfilterd_conf_apply(struct auditfilter_module_list *list)
+{
+ struct auditfilter_module *am1, *am2, *am_tmp;
+ int argc_tmp, found;
+ char **argv_tmp;
+
+ /*
+ * First, remove remove and detach any entries that appear in the
+ * current configuration, but not the new configuration.
+ */
+ TAILQ_FOREACH_SAFE(am1, &filter_list, am_list, am_tmp) {
+ found = 0;
+ TAILQ_FOREACH(am2, list, am_list) {
+ if (strcmp(am1->am_modulename, am2->am_modulename)
+ == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ /*
+ * am1 appears in filter_list, but not the new list, detach
+ * and free the module.
+ */
+ warnx("detaching module %s", am1->am_modulename);
+ TAILQ_REMOVE(&filter_list, am1, am_list);
+ auditfilter_module_detach(am1);
+ auditfilter_module_free(am1);
+ }
+
+ /*
+ * Next, update the configuration of any modules that appear in both
+ * lists. We do this by swapping the two argc and argv values and
+ * freeing the new one, rather than detaching the old one and
+ * attaching the new one. That way module state is preserved.
+ */
+ TAILQ_FOREACH(am1, &filter_list, am_list) {
+ found = 0;
+ TAILQ_FOREACH(am2, list, am_list) {
+ if (strcmp(am1->am_modulename, am2->am_modulename)
+ == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+ /*
+ * Swap the arguments.
+ */
+ argc_tmp = am1->am_argc;
+ argv_tmp = am1->am_argv;
+ am1->am_argc = am2->am_argc;
+ am1->am_argv = am2->am_argv;
+ am2->am_argc = argc_tmp;
+ am2->am_argv = argv_tmp;
+
+ /*
+ * The reinit is a bit tricky: if reinit fails, we actually
+ * remove the old entry and detach that, as we don't allow
+ * running modules to be out of sync with the configuration
+ * file.
+ */
+ warnx("reiniting module %s", am1->am_modulename);
+ if (auditfilter_module_reinit(am1) != 0) {
+ warnx("reinit failed for module %s, detaching",
+ am1->am_modulename);
+ TAILQ_REMOVE(&filter_list, am1, am_list);
+ auditfilter_module_detach(am1);
+ auditfilter_module_free(am1);
+ }
+
+ /*
+ * Free the entry from the new list, which will discard the
+ * old arguments. No need to detach, as it was never
+ * attached in the first place.
+ */
+ TAILQ_REMOVE(list, am2, am_list);
+ auditfilter_module_free(am2);
+ }
+
+ /*
+ * Finally, attach any new entries that don't appear in the old
+ * configuration, and if they attach successfully, move them to the
+ * real configuration list.
+ */
+ TAILQ_FOREACH(am1, list, am_list) {
+ found = 0;
+ TAILQ_FOREACH(am2, &filter_list, am_list) {
+ if (strcmp(am1->am_modulename, am2->am_modulename)
+ == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ /*
+ * Attach the entry. If it succeeds, add to filter_list,
+ * otherwise, free. No need to detach if attach failed.
+ */
+ warnx("attaching module %s", am1->am_modulename);
+ TAILQ_REMOVE(list, am1, am_list);
+ if (auditfilter_module_attach(am1) != 0) {
+ warnx("attaching module %s failed",
+ am1->am_modulename);
+ auditfilter_module_free(am1);
+ } else
+ TAILQ_INSERT_HEAD(&filter_list, am1, am_list);
+ }
+
+ if (TAILQ_FIRST(list) != NULL)
+ warnx("auditfilterd_conf_apply: new list not empty\n");
+}
+
+/*
+ * Read the new configuration file into a local list. If the configuration
+ * file is parsed OK, then apply the changes.
+ */
+int
+auditfilterd_conf(const char *filename, FILE *fp)
+{
+ struct auditfilter_module_list list;
+
+ TAILQ_INIT(&list);
+ if (auditfilterd_conf_read(filename, fp, &list) < 0)
+ return (-1);
+
+ auditfilterd_conf_apply(&list);
+
+ return (0);
+}
+
+/*
+ * Detach and free all active filter modules for daemon shutdown.
+ */
+void
+auditfilterd_conf_shutdown(void)
+{
+
+ auditfilter_module_list_detach(&filter_list);
+ auditfilter_module_list_free(&filter_list);
+}
+
+/*
+ * APIs to allow modules to query and set their per-instance cookie.
+ */
+void
+audit_filter_getcookie(void *instance, void **cookie)
+{
+ struct auditfilter_module *am;
+
+ am = (struct auditfilter_module *)instance;
+ *cookie = am->am_cookie;
+}
+
+void
+audit_filter_setcookie(void *instance, void *cookie)
+{
+ struct auditfilter_module *am;
+
+ am = (struct auditfilter_module *)instance;
+ am->am_cookie = cookie;
+}
diff --git a/contrib/openbsm/bin/auditreduce/Makefile.am b/contrib/openbsm/bin/auditreduce/Makefile.am
new file mode 100644
index 0000000..b5e2433
--- /dev/null
+++ b/contrib/openbsm/bin/auditreduce/Makefile.am
@@ -0,0 +1,10 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = auditreduce
+auditreduce_SOURCES = auditreduce.c
+auditreduce_LDADD = $(top_builddir)/libbsm/libbsm.la
+man1_MANS = auditreduce.1
diff --git a/contrib/openbsm/bin/auditreduce/Makefile.in b/contrib/openbsm/bin/auditreduce/Makefile.in
new file mode 100644
index 0000000..53090e2
--- /dev/null
+++ b/contrib/openbsm/bin/auditreduce/Makefile.in
@@ -0,0 +1,647 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = auditreduce$(EXEEXT)
+subdir = bin/auditreduce
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_auditreduce_OBJECTS = auditreduce.$(OBJEXT)
+auditreduce_OBJECTS = $(am_auditreduce_OBJECTS)
+auditreduce_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(auditreduce_SOURCES)
+DIST_SOURCES = $(auditreduce_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man1_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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)
+auditreduce_SOURCES = auditreduce.c
+auditreduce_LDADD = $(top_builddir)/libbsm/libbsm.la
+man1_MANS = auditreduce.1
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditreduce/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/auditreduce/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+auditreduce$(EXEEXT): $(auditreduce_OBJECTS) $(auditreduce_DEPENDENCIES) $(EXTRA_auditreduce_DEPENDENCIES)
+ @rm -f auditreduce$(EXEEXT)
+ $(LINK) $(auditreduce_OBJECTS) $(auditreduce_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditreduce.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(man1_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man1_MANS)'; \
+ list2=''; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man1
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man1 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man1 \
+ uninstall-sbinPROGRAMS
+
+
+# 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/auditreduce/auditreduce.1 b/contrib/openbsm/bin/auditreduce/auditreduce.1
new file mode 100644
index 0000000..3266ad9
--- /dev/null
+++ b/contrib/openbsm/bin/auditreduce/auditreduce.1
@@ -0,0 +1,195 @@
+.\" Copyright (c) 2004 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.
+.\"
+.Dd January 24, 2004
+.Dt AUDITREDUCE 1
+.Os
+.Sh NAME
+.Nm auditreduce
+.Nd "select records from audit trail files"
+.Sh SYNOPSIS
+.Nm
+.Op Fl A
+.Op Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS
+.Op Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS
+.Op Fl c Ar flags
+.Op Fl d Ar YYYYMMDD
+.Op Fl e Ar euid
+.Op Fl f Ar egid
+.Op Fl g Ar rgid
+.Op Fl j Ar id
+.Op Fl m Ar event
+.Op Fl o Ar object Ns = Ns Ar value
+.Op Fl r Ar ruid
+.Op Fl u Ar auid
+.Op Fl v
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility selects records from the audit trail files based on the specified
+criteria.
+Matching audit records are printed to the standard output in
+their raw binary form.
+If no
+.Ar file
+argument is specified, the standard input is used
+by default.
+Use the
+.Xr praudit 1
+utility to print the selected audit records in human-readable form.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl A
+Select all records.
+.It Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS
+Select records that occurred after or on the given datetime.
+.It Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS
+Select records that occurred before the given datetime.
+.It Fl c Ar flags
+Select records matching the given audit classes specified as a comma
+separated list of audit flags.
+See
+.Xr audit_control 5
+for a description of audit flags.
+.It Fl d Ar YYYYMMDD
+Select records that occurred on a given date.
+This option cannot be used with
+.Fl a
+or
+.Fl b .
+.It Fl e Ar euid
+Select records with the given effective user ID or name.
+.It Fl f Ar egid
+Select records with the given effective group ID or name.
+.It Fl g Ar rgid
+Select records with the given real group ID or name.
+.It Fl j Ar id
+Select records having a subject token with matching ID, where ID is a process ID.
+.It Fl m Ar event
+Select records with the given event name or number. This option can
+be used more then once to select records of multiple event types.
+See
+.Xr audit_event 5
+for a description of audit event names and numbers.
+.It Fl o Ar object Ns = Ns Ar value
+.Bl -tag -width ".Cm msgqid"
+.It Cm file
+Select records containing path tokens, where the pathname matches
+one of the comma delimited extended regular expression contained in
+given specification.
+Regular expressions which are prefixed with a tilde
+.Pq Ql ~
+are excluded
+from the search results.
+These extended regular expressions are processed from left to right,
+and a path will either be selected or deslected based on the first match.
+.Pp
+Since commas are used to delimit the regular expressions, a backslash
+.Pq Ql \e
+character should be used to escape the comma if it is a part of the search
+pattern.
+.It Cm msgqid
+Select records containing the given message queue ID.
+.It Cm pid
+Select records containing the given process ID.
+.It Cm semid
+Select records containing the given semaphore ID.
+.It Cm shmid
+Select records containing the given shared memory ID.
+.El
+.It Fl r Ar ruid
+Select records with the given real user ID or name.
+.It Fl u Ar auid
+Select records with the given audit ID.
+.It Fl v
+Invert sense of matching, to select records that do not match.
+.El
+.Sh EXAMPLES
+To select all records associated with effective user ID root from the audit
+log
+.Pa /var/audit/20031016184719.20031017122634 :
+.Bd -literal -offset indent
+auditreduce -e root \e
+ /var/audit/20031016184719.20031017122634
+.Ed
+.Pp
+To select all
+.Xr setlogin 2
+events from that log:
+.Bd -literal -offset indent
+auditreduce -m AUE_SETLOGIN \e
+ /var/audit/20031016184719.20031017122634
+.Ed
+.Pp
+Output from the above command lines will typically be piped to a new trail
+file, or via standard output to the
+.Xr praudit 1
+command.
+.Pp
+Select all records containing a path token where the pathname contains
+.Pa /etc/master.passwd :
+.Bd -literal -offset indent
+auditreduce -o file="/etc/master.passwd" \e
+ /var/audit/20031016184719.20031017122634
+.Ed
+.Pp
+Select all records containing path tokens, where the pathname is a TTY
+device:
+.Bd -literal -offset indent
+auditreduce -o file="/dev/tty[a-zA-Z][0-9]+" \e
+ /var/audit/20031016184719.20031017122634
+.Ed
+.Pp
+Select all records containing path tokens, where the pathname is a TTY
+except for
+.Pa /dev/ttyp2 :
+.Bd -literal -offset indent
+auditreduce -o file="~/dev/ttyp2,/dev/tty[a-zA-Z][0-9]+" \e
+ /var/audit/20031016184719.20031017122634
+.Ed
+.Sh SEE ALSO
+.Xr praudit 1 ,
+.Xr audit_control 5 ,
+.Xr audit_event 5
+.Sh HISTORY
+The OpenBSM implementation was created by McAfee Research, the security
+division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004.
+It was subsequently adopted by the TrustedBSD Project as the foundation for
+the OpenBSM distribution.
+.Sh AUTHORS
+.An -nosplit
+This software was created by McAfee Research, the security research division
+of McAfee, Inc., under contract to Apple Computer Inc.
+Additional authors include
+.An Wayne Salamon ,
+.An Robert Watson ,
+and SPARTA Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.c b/contrib/openbsm/bin/auditreduce/auditreduce.c
new file mode 100644
index 0000000..f73d341
--- /dev/null
+++ b/contrib/openbsm/bin/auditreduce/auditreduce.c
@@ -0,0 +1,801 @@
+/*-
+ * 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.
+ */
+
+/*
+ * Tool used to merge and select audit records from audit trail files
+ */
+
+/*
+ * XXX Currently we do not support merging of records from multiple
+ * XXX audit trail files
+ * XXX We assume that records are sorted chronologically - both wrt to
+ * XXX the records present within the file and between the files themselves
+ */
+
+#include <config/config.h>
+
+#define _GNU_SOURCE /* Required for strptime() on glibc2. */
+
+#ifdef HAVE_FULL_QUEUE_H
+#include <sys/queue.h>
+#else
+#include <compat/queue.h>
+#endif
+
+#include <bsm/libbsm.h>
+
+#include <err.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <regex.h>
+#include <errno.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "auditreduce.h"
+
+static TAILQ_HEAD(tailhead, re_entry) re_head =
+ TAILQ_HEAD_INITIALIZER(re_head);
+
+extern char *optarg;
+extern int optind, optopt, opterr,optreset;
+
+static au_mask_t maskp; /* Class. */
+static time_t p_atime; /* Created after this time. */
+static time_t p_btime; /* Created before this time. */
+static int p_auid; /* Audit id. */
+static int p_euid; /* Effective user id. */
+static int p_egid; /* Effective group id. */
+static int p_rgid; /* Real group id. */
+static int p_ruid; /* Real user id. */
+static int p_subid; /* Subject id. */
+
+/*
+ * Maintain a dynamically sized array of events for -m
+ */
+static uint16_t *p_evec; /* Event type list */
+static int p_evec_used; /* Number of events used */
+static int p_evec_alloc; /* Number of events allocated */
+
+/*
+ * Following are the objects (-o option) that we can select upon.
+ */
+static char *p_fileobj = NULL;
+static char *p_msgqobj = NULL;
+static char *p_pidobj = NULL;
+static char *p_semobj = NULL;
+static char *p_shmobj = NULL;
+static char *p_sockobj = NULL;
+
+static uint32_t opttochk = 0;
+
+static void
+parse_regexp(char *re_string)
+{
+ char *orig, *copy, re_error[64];
+ struct re_entry *rep;
+ int error, nstrs, i, len;
+
+ copy = strdup(re_string);
+ orig = copy;
+ len = strlen(copy);
+ for (nstrs = 0, i = 0; i < len; i++) {
+ if (copy[i] == ',' && i > 0) {
+ if (copy[i - 1] == '\\')
+ strlcpy(&copy[i - 1], &copy[i], len);
+ else {
+ nstrs++;
+ copy[i] = '\0';
+ }
+ }
+ }
+ TAILQ_INIT(&re_head);
+ for (i = 0; i < nstrs + 1; i++) {
+ rep = calloc(1, sizeof(*rep));
+ if (rep == NULL) {
+ (void) fprintf(stderr, "calloc: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ if (*copy == '~') {
+ copy++;
+ rep->re_negate = 1;
+ }
+ rep->re_pattern = strdup(copy);
+ error = regcomp(&rep->re_regexp, rep->re_pattern,
+ REG_EXTENDED | REG_NOSUB);
+ if (error != 0) {
+ regerror(error, &rep->re_regexp, re_error, 64);
+ (void) fprintf(stderr, "regcomp: %s\n", re_error);
+ exit(1);
+ }
+ TAILQ_INSERT_TAIL(&re_head, rep, re_glue);
+ len = strlen(copy);
+ copy += len + 1;
+ }
+ free(orig);
+}
+
+static void
+usage(const char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ fprintf(stderr, "Usage: auditreduce [options] [file ...]\n");
+ fprintf(stderr, "\tOptions are : \n");
+ fprintf(stderr, "\t-A : all records\n");
+ fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n");
+ fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n");
+ fprintf(stderr, "\t-c <flags> : matching class\n");
+ fprintf(stderr, "\t-d YYYYMMDD : on date\n");
+ fprintf(stderr, "\t-e <uid|name> : effective user\n");
+ fprintf(stderr, "\t-f <gid|group> : effective group\n");
+ fprintf(stderr, "\t-g <gid|group> : real group\n");
+ fprintf(stderr, "\t-j <pid> : subject id \n");
+ fprintf(stderr, "\t-m <evno|evname> : matching event\n");
+ fprintf(stderr, "\t-o objecttype=objectvalue\n");
+ fprintf(stderr, "\t\t file=<pathname>\n");
+ fprintf(stderr, "\t\t msgqid=<ID>\n");
+ fprintf(stderr, "\t\t pid=<ID>\n");
+ fprintf(stderr, "\t\t semid=<ID>\n");
+ fprintf(stderr, "\t\t shmid=<ID>\n");
+ fprintf(stderr, "\t-r <uid|name> : real user\n");
+ fprintf(stderr, "\t-u <uid|name> : audit user\n");
+ fprintf(stderr, "\t-v : select non-matching records\n");
+ exit(EX_USAGE);
+}
+
+/*
+ * Check if the given auid matches the selection criteria.
+ */
+static int
+select_auid(int au)
+{
+
+ /* Check if we want to select on auid. */
+ if (ISOPTSET(opttochk, OPT_u)) {
+ if (au != p_auid)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given euid matches the selection criteria.
+ */
+static int
+select_euid(int euser)
+{
+
+ /* Check if we want to select on euid. */
+ if (ISOPTSET(opttochk, OPT_e)) {
+ if (euser != p_euid)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given egid matches the selection criteria.
+ */
+static int
+select_egid(int egrp)
+{
+
+ /* Check if we want to select on egid. */
+ if (ISOPTSET(opttochk, OPT_f)) {
+ if (egrp != p_egid)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given rgid matches the selection criteria.
+ */
+static int
+select_rgid(int grp)
+{
+
+ /* Check if we want to select on rgid. */
+ if (ISOPTSET(opttochk, OPT_g)) {
+ if (grp != p_rgid)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given ruid matches the selection criteria.
+ */
+static int
+select_ruid(int user)
+{
+
+ /* Check if we want to select on rgid. */
+ if (ISOPTSET(opttochk, OPT_r)) {
+ if (user != p_ruid)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given subject id (pid) matches the selection criteria.
+ */
+static int
+select_subid(int subid)
+{
+
+ /* Check if we want to select on subject uid. */
+ if (ISOPTSET(opttochk, OPT_j)) {
+ if (subid != p_subid)
+ return (0);
+ }
+ return (1);
+}
+
+
+/*
+ * Check if object's pid maches the given pid.
+ */
+static int
+select_pidobj(uint32_t pid)
+{
+
+ if (ISOPTSET(opttochk, OPT_op)) {
+ if (pid != (uint32_t)strtol(p_pidobj, (char **)NULL, 10))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Check if the given ipc object with the given type matches the selection
+ * criteria.
+ */
+static int
+select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd)
+{
+
+ if (type == AT_IPC_MSG) {
+ SETOPT((*optchkd), OPT_om);
+ if (ISOPTSET(opttochk, OPT_om)) {
+ if (id != (uint32_t)strtol(p_msgqobj, (char **)NULL,
+ 10))
+ return (0);
+ }
+ return (1);
+ } else if (type == AT_IPC_SEM) {
+ SETOPT((*optchkd), OPT_ose);
+ if (ISOPTSET(opttochk, OPT_ose)) {
+ if (id != (uint32_t)strtol(p_semobj, (char **)NULL, 10))
+ return (0);
+ }
+ return (1);
+ } else if (type == AT_IPC_SHM) {
+ SETOPT((*optchkd), OPT_osh);
+ if (ISOPTSET(opttochk, OPT_osh)) {
+ if (id != (uint32_t)strtol(p_shmobj, (char **)NULL, 10))
+ return (0);
+ }
+ return (1);
+ }
+
+ /* Unknown type -- filter if *any* ipc filtering is required. */
+ if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose)
+ || ISOPTSET(opttochk, OPT_osh))
+ return (0);
+
+ return (1);
+}
+
+
+/*
+ * Check if the file name matches selection criteria.
+ */
+static int
+select_filepath(char *path, uint32_t *optchkd)
+{
+ struct re_entry *rep;
+ int match;
+
+ SETOPT((*optchkd), OPT_of);
+ match = 1;
+ if (ISOPTSET(opttochk, OPT_of)) {
+ match = 0;
+ TAILQ_FOREACH(rep, &re_head, re_glue) {
+ if (regexec(&rep->re_regexp, path, 0, NULL,
+ 0) != REG_NOMATCH)
+ return (!rep->re_negate);
+ }
+ }
+ return (match);
+}
+
+/*
+ * Returns 1 if the following pass the selection rules:
+ *
+ * before-time,
+ * after time,
+ * date,
+ * class,
+ * event
+ */
+static int
+select_hdr32(tokenstr_t tok, uint32_t *optchkd)
+{
+ uint16_t *ev;
+ int match;
+
+ SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m | OPT_v));
+
+ /* The A option overrides a, b and d. */
+ if (!ISOPTSET(opttochk, OPT_A)) {
+ if (ISOPTSET(opttochk, OPT_a)) {
+ if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) {
+ /* Record was created before p_atime. */
+ return (0);
+ }
+ }
+
+ if (ISOPTSET(opttochk, OPT_b)) {
+ if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) {
+ /* Record was created after p_btime. */
+ return (0);
+ }
+ }
+ }
+
+ if (ISOPTSET(opttochk, OPT_c)) {
+ /*
+ * Check if the classes represented by the event matches
+ * given class.
+ */
+ if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH,
+ AU_PRS_USECACHE) != 1)
+ return (0);
+ }
+
+ /* Check if event matches. */
+ if (ISOPTSET(opttochk, OPT_m)) {
+ match = 0;
+ for (ev = p_evec; ev < &p_evec[p_evec_used]; ev++)
+ if (tok.tt.hdr32.e_type == *ev)
+ match = 1;
+ if (match == 0)
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+select_return32(tokenstr_t tok_ret32, tokenstr_t tok_hdr32, uint32_t *optchkd)
+{
+ int sorf;
+
+ SETOPT((*optchkd), (OPT_c));
+ if (tok_ret32.tt.ret32.status == 0)
+ sorf = AU_PRS_SUCCESS;
+ else
+ sorf = AU_PRS_FAILURE;
+ if (ISOPTSET(opttochk, OPT_c)) {
+ if (au_preselect(tok_hdr32.tt.hdr32.e_type, &maskp, sorf,
+ AU_PRS_USECACHE) != 1)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Return 1 if checks for the the following succeed
+ * auid,
+ * euid,
+ * egid,
+ * rgid,
+ * ruid,
+ * process id
+ */
+static int
+select_proc32(tokenstr_t tok, uint32_t *optchkd)
+{
+
+ SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op));
+
+ if (!select_auid(tok.tt.proc32.auid))
+ return (0);
+ if (!select_euid(tok.tt.proc32.euid))
+ return (0);
+ if (!select_egid(tok.tt.proc32.egid))
+ return (0);
+ if (!select_rgid(tok.tt.proc32.rgid))
+ return (0);
+ if (!select_ruid(tok.tt.proc32.ruid))
+ return (0);
+ if (!select_pidobj(tok.tt.proc32.pid))
+ return (0);
+ return (1);
+}
+
+/*
+ * Return 1 if checks for the the following succeed
+ * auid,
+ * euid,
+ * egid,
+ * rgid,
+ * ruid,
+ * subject id
+ */
+static int
+select_subj32(tokenstr_t tok, uint32_t *optchkd)
+{
+
+ SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j));
+
+ if (!select_auid(tok.tt.subj32.auid))
+ return (0);
+ if (!select_euid(tok.tt.subj32.euid))
+ return (0);
+ if (!select_egid(tok.tt.subj32.egid))
+ return (0);
+ if (!select_rgid(tok.tt.subj32.rgid))
+ return (0);
+ if (!select_ruid(tok.tt.subj32.ruid))
+ return (0);
+ if (!select_subid(tok.tt.subj32.pid))
+ return (0);
+ return (1);
+}
+
+/*
+ * Read each record from the audit trail. Check if it is selected after
+ * passing through each of the options
+ */
+static int
+select_records(FILE *fp)
+{
+ tokenstr_t tok_hdr32_copy;
+ u_char *buf;
+ tokenstr_t tok;
+ int reclen;
+ int bytesread;
+ int selected;
+ uint32_t optchkd;
+ int print;
+
+ int err = 0;
+ while ((reclen = au_read_rec(fp, &buf)) != -1) {
+ optchkd = 0;
+ bytesread = 0;
+ selected = 1;
+ while ((selected == 1) && (bytesread < reclen)) {
+ if (-1 == au_fetch_tok(&tok, buf + bytesread,
+ reclen - bytesread)) {
+ /* Is this an incomplete record? */
+ err = 1;
+ break;
+ }
+
+ /*
+ * For each token type we have have different
+ * selection criteria.
+ */
+ switch(tok.id) {
+ case AUT_HEADER32:
+ selected = select_hdr32(tok,
+ &optchkd);
+ bcopy(&tok, &tok_hdr32_copy,
+ sizeof(tok));
+ break;
+
+ case AUT_PROCESS32:
+ selected = select_proc32(tok,
+ &optchkd);
+ break;
+
+ case AUT_SUBJECT32:
+ selected = select_subj32(tok,
+ &optchkd);
+ break;
+
+ case AUT_IPC:
+ selected = select_ipcobj(
+ tok.tt.ipc.type, tok.tt.ipc.id,
+ &optchkd);
+ break;
+
+ case AUT_PATH:
+ selected = select_filepath(
+ tok.tt.path.path, &optchkd);
+ break;
+
+ case AUT_RETURN32:
+ selected = select_return32(tok,
+ tok_hdr32_copy, &optchkd);
+ break;
+
+ default:
+ break;
+ }
+ bytesread += tok.len;
+ }
+ /* Check if all the options were matched. */
+ print = ((selected == 1) && (!err) && (!(opttochk & ~optchkd)));
+ if (ISOPTSET(opttochk, OPT_v))
+ print = !print;
+ if (print)
+ (void) fwrite(buf, 1, reclen, stdout);
+ free(buf);
+ }
+ return (0);
+}
+
+/*
+ * The -o option has the form object_type=object_value. Identify the object
+ * components.
+ */
+static void
+parse_object_type(char *name, char *val)
+{
+ if (val == NULL)
+ return;
+
+ if (!strcmp(name, FILEOBJ)) {
+ p_fileobj = val;
+ parse_regexp(val);
+ SETOPT(opttochk, OPT_of);
+ } else if (!strcmp(name, MSGQIDOBJ)) {
+ p_msgqobj = val;
+ SETOPT(opttochk, OPT_om);
+ } else if (!strcmp(name, PIDOBJ)) {
+ p_pidobj = val;
+ SETOPT(opttochk, OPT_op);
+ } else if (!strcmp(name, SEMIDOBJ)) {
+ p_semobj = val;
+ SETOPT(opttochk, OPT_ose);
+ } else if (!strcmp(name, SHMIDOBJ)) {
+ p_shmobj = val;
+ SETOPT(opttochk, OPT_osh);
+ } else if (!strcmp(name, SOCKOBJ)) {
+ p_sockobj = val;
+ SETOPT(opttochk, OPT_oso);
+ } else
+ usage("unknown value for -o");
+}
+
+int
+main(int argc, char **argv)
+{
+ struct group *grp;
+ struct passwd *pw;
+ struct tm tm;
+ au_event_t *n;
+ FILE *fp;
+ int i;
+ char *objval, *converr;
+ int ch;
+ char timestr[128];
+ char *fname;
+ uint16_t *etp;
+
+ converr = NULL;
+
+ while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:v")) != -1) {
+ switch(ch) {
+ case 'A':
+ SETOPT(opttochk, OPT_A);
+ break;
+
+ case 'a':
+ if (ISOPTSET(opttochk, OPT_a)) {
+ usage("d is exclusive with a and b");
+ }
+ SETOPT(opttochk, OPT_a);
+ bzero(&tm, sizeof(tm));
+ strptime(optarg, "%Y%m%d%H%M%S", &tm);
+ strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
+ &tm);
+ /* fprintf(stderr, "Time converted = %s\n", timestr); */
+ p_atime = mktime(&tm);
+ break;
+
+ case 'b':
+ if (ISOPTSET(opttochk, OPT_b)) {
+ usage("d is exclusive with a and b");
+ }
+ SETOPT(opttochk, OPT_b);
+ bzero(&tm, sizeof(tm));
+ strptime(optarg, "%Y%m%d%H%M%S", &tm);
+ strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
+ &tm);
+ /* fprintf(stderr, "Time converted = %s\n", timestr); */
+ p_btime = mktime(&tm);
+ break;
+
+ case 'c':
+ if (0 != getauditflagsbin(optarg, &maskp)) {
+ /* Incorrect class */
+ usage("Incorrect class");
+ }
+ SETOPT(opttochk, OPT_c);
+ break;
+
+ case 'd':
+ if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk,
+ OPT_a))
+ usage("'d' is exclusive with 'a' and 'b'");
+ SETOPT(opttochk, OPT_d);
+ bzero(&tm, sizeof(tm));
+ strptime(optarg, "%Y%m%d", &tm);
+ strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
+ /* fprintf(stderr, "Time converted = %s\n", timestr); */
+ p_atime = mktime(&tm);
+ tm.tm_hour = 23;
+ tm.tm_min = 59;
+ tm.tm_sec = 59;
+ strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
+ /* fprintf(stderr, "Time converted = %s\n", timestr); */
+ p_btime = mktime(&tm);
+ break;
+
+ case 'e':
+ p_euid = strtol(optarg, &converr, 10);
+ if (*converr != '\0') {
+ /* Try the actual name */
+ if ((pw = getpwnam(optarg)) == NULL)
+ break;
+ p_euid = pw->pw_uid;
+ }
+ SETOPT(opttochk, OPT_e);
+ break;
+
+ case 'f':
+ p_egid = strtol(optarg, &converr, 10);
+ if (*converr != '\0') {
+ /* Try actual group name. */
+ if ((grp = getgrnam(optarg)) == NULL)
+ break;
+ p_egid = grp->gr_gid;
+ }
+ SETOPT(opttochk, OPT_f);
+ break;
+
+ case 'g':
+ p_rgid = strtol(optarg, &converr, 10);
+ if (*converr != '\0') {
+ /* Try actual group name. */
+ if ((grp = getgrnam(optarg)) == NULL)
+ break;
+ p_rgid = grp->gr_gid;
+ }
+ SETOPT(opttochk, OPT_g);
+ break;
+
+ case 'j':
+ p_subid = strtol(optarg, (char **)NULL, 10);
+ SETOPT(opttochk, OPT_j);
+ break;
+
+ case 'm':
+ if (p_evec == NULL) {
+ p_evec_alloc = 32;
+ p_evec = malloc(sizeof(*etp) * p_evec_alloc);
+ if (p_evec == NULL)
+ err(1, "malloc");
+ } else if (p_evec_alloc == p_evec_used) {
+ p_evec_alloc <<= 1;
+ p_evec = realloc(p_evec,
+ sizeof(*p_evec) * p_evec_alloc);
+ if (p_evec == NULL)
+ err(1, "realloc");
+ }
+ etp = &p_evec[p_evec_used++];
+ *etp = strtol(optarg, (char **)NULL, 10);
+ if (*etp == 0) {
+ /* Could be the string representation. */
+ n = getauevnonam(optarg);
+ if (n == NULL)
+ usage("Incorrect event name");
+ *etp = *n;
+ }
+ SETOPT(opttochk, OPT_m);
+ break;
+
+ case 'o':
+ objval = strchr(optarg, '=');
+ if (objval != NULL) {
+ *objval = '\0';
+ objval += 1;
+ parse_object_type(optarg, objval);
+ }
+ break;
+
+ case 'r':
+ p_ruid = strtol(optarg, &converr, 10);
+ if (*converr != '\0') {
+ if ((pw = getpwnam(optarg)) == NULL)
+ break;
+ p_ruid = pw->pw_uid;
+ }
+ SETOPT(opttochk, OPT_r);
+ break;
+
+ case 'u':
+ p_auid = strtol(optarg, &converr, 10);
+ if (*converr != '\0') {
+ if ((pw = getpwnam(optarg)) == NULL)
+ break;
+ p_auid = pw->pw_uid;
+ }
+ SETOPT(opttochk, OPT_u);
+ break;
+
+ case 'v':
+ SETOPT(opttochk, OPT_v);
+ break;
+
+ case '?':
+ default:
+ usage("Unknown option");
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc == 0) {
+ if (select_records(stdin) == -1)
+ errx(EXIT_FAILURE,
+ "Couldn't select records from stdin");
+ exit(EXIT_SUCCESS);
+ }
+
+ /*
+ * XXX: We should actually be merging records here.
+ */
+ for (i = 0; i < argc; i++) {
+ fname = argv[i];
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ errx(EXIT_FAILURE, "Couldn't open %s", fname);
+ if (select_records(fp) == -1) {
+ errx(EXIT_FAILURE, "Couldn't select records %s",
+ fname);
+ }
+ fclose(fp);
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.h b/contrib/openbsm/bin/auditreduce/auditreduce.h
new file mode 100644
index 0000000..655b45d
--- /dev/null
+++ b/contrib/openbsm/bin/auditreduce/auditreduce.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2004 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.
+ */
+
+#ifndef _AUDITREDUCE_H_
+#define _AUDITREDUCE_H_
+
+
+struct re_entry {
+ char *re_pattern;
+ int re_negate;
+ regex_t re_regexp;
+ TAILQ_ENTRY(re_entry) re_glue;
+};
+
+#define OPT_a 0x00000001
+#define OPT_b 0x00000002
+#define OPT_c 0x00000004
+#define OPT_d (OPT_a | OPT_b)
+#define OPT_e 0x00000010
+#define OPT_f 0x00000020
+#define OPT_g 0x00000040
+#define OPT_j 0x00000080
+#define OPT_m 0x00000100
+#define OPT_of 0x00000200
+#define OPT_om 0x00000400
+#define OPT_op 0x00000800
+#define OPT_ose 0x00001000
+#define OPT_osh 0x00002000
+#define OPT_oso 0x00004000
+#define OPT_r 0x00008000
+#define OPT_u 0x00010000
+#define OPT_A 0x00020000
+#define OPT_v 0x00040000
+
+#define FILEOBJ "file"
+#define MSGQIDOBJ "msgqid"
+#define PIDOBJ "pid"
+#define SEMIDOBJ "semid"
+#define SHMIDOBJ "shmid"
+#define SOCKOBJ "sock"
+
+
+#define SETOPT(optmask, bit) (optmask |= bit)
+#define ISOPTSET(optmask, bit) (optmask & bit)
+
+
+#endif /* !_AUDITREDUCE_H_ */
diff --git a/contrib/openbsm/bin/praudit/Makefile.am b/contrib/openbsm/bin/praudit/Makefile.am
new file mode 100644
index 0000000..4643b7c
--- /dev/null
+++ b/contrib/openbsm/bin/praudit/Makefile.am
@@ -0,0 +1,10 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+sbin_PROGRAMS = praudit
+praudit_SOURCES = praudit.c
+praudit_LDADD = $(top_builddir)/libbsm/libbsm.la
+man1_MANS = praudit.1
diff --git a/contrib/openbsm/bin/praudit/Makefile.in b/contrib/openbsm/bin/praudit/Makefile.in
new file mode 100644
index 0000000..d8469bb
--- /dev/null
+++ b/contrib/openbsm/bin/praudit/Makefile.in
@@ -0,0 +1,647 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = praudit$(EXEEXT)
+subdir = bin/praudit
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_praudit_OBJECTS = praudit.$(OBJEXT)
+praudit_OBJECTS = $(am_praudit_OBJECTS)
+praudit_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(praudit_SOURCES)
+DIST_SOURCES = $(praudit_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man1_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIG = @MIG@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+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)
+praudit_SOURCES = praudit.c
+praudit_LDADD = $(top_builddir)/libbsm/libbsm.la
+man1_MANS = praudit.1
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/praudit/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/praudit/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+praudit$(EXEEXT): $(praudit_OBJECTS) $(praudit_DEPENDENCIES) $(EXTRA_praudit_DEPENDENCIES)
+ @rm -f praudit$(EXEEXT)
+ $(LINK) $(praudit_OBJECTS) $(praudit_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/praudit.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(man1_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man1_MANS)'; \
+ list2=''; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+cscopelist: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically 'make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man1
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man1 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man1 \
+ uninstall-sbinPROGRAMS
+
+
+# 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/praudit/praudit.1 b/contrib/openbsm/bin/praudit/praudit.1
new file mode 100644
index 0000000..2954ba3
--- /dev/null
+++ b/contrib/openbsm/bin/praudit/praudit.1
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2004-2009 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.
+.\"
+.Dd August 4, 2009
+.Dt PRAUDIT 1
+.Os
+.Sh NAME
+.Nm praudit
+.Nd "print the contents of audit trail files"
+.Sh SYNOPSIS
+.Nm
+.Op Fl lnpx
+.Op Fl r | s
+.Op Fl d Ar del
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility prints the contents of the audit trail files to the standard output in
+human-readable form.
+If no
+.Ar file
+argument is specified, the standard input is used
+by default.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar del
+Specifies the delimiter.
+The default delimiter is the comma.
+.It Fl l
+Prints the entire record on the same line.
+If this option is not specified,
+every token is displayed on a different line.
+.It Fl n
+Do not convert user and group IDs to their names but leave in their
+numeric forms.
+.It Fl p
+Specify this option if input to
+.Nm
+is piped from the
+.Xr tail 1
+utility.
+This causes
+.Nm
+to sync to the start of the next record.
+.It Fl r
+Prints the records in their raw, numeric form.
+This option is exclusive from
+.Fl s .
+.It Fl s
+Prints the tokens in their short form.
+Short text representations for
+record and event type are displayed.
+This option is exclusive from
+.Fl r .
+.It Fl x
+Print audit records in the XML output format.
+.El
+.Pp
+If the raw or short forms are not specified, the default is to print the tokens
+in their long form.
+Events are displayed as per their descriptions given in
+.Pa /etc/security/audit_event ;
+UIDs and GIDs are expanded to their names;
+dates and times are displayed in human-readable format.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/security/audit_control" -compact
+.It Pa /etc/security/audit_class
+Descriptions of audit event classes.
+.It Pa /etc/security/audit_event
+Descriptions of audit events.
+.El
+.Sh SEE ALSO
+.Xr auditreduce 1 ,
+.Xr audit 4 ,
+.Xr auditpipe 4 ,
+.Xr audit_class 5 ,
+.Xr audit_event 5
+.Sh HISTORY
+The OpenBSM implementation was created by McAfee Research, the security
+division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004.
+It was subsequently adopted by the TrustedBSD Project as the foundation for
+the OpenBSM distribution.
+.Sh AUTHORS
+.An -nosplit
+This software was created by McAfee Research, the security research division
+of McAfee, Inc., under contract to Apple Computer Inc.
+Additional authors include
+.An Wayne Salamon ,
+.An Robert Watson ,
+and SPARTA Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
diff --git a/contrib/openbsm/bin/praudit/praudit.c b/contrib/openbsm/bin/praudit/praudit.c
new file mode 100644
index 0000000..f795434
--- /dev/null
+++ b/contrib/openbsm/bin/praudit/praudit.c
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2004-2009 Apple Inc.
+ * Copyright (c) 2006 Martin Voros
+ * 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.
+ */
+
+/*
+ * Tool used to parse audit records conforming to the BSM structure.
+ */
+
+/*
+ * praudit [-lnpx] [-r | -s] [-d del] [file ...]
+ */
+
+#include <bsm/libbsm.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern char *optarg;
+extern int optind, optopt, opterr,optreset;
+
+static char *del = ","; /* Default delimiter. */
+static int oneline = 0;
+static int partial = 0;
+static int oflags = AU_OFLAG_NONE;
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: praudit [-lnpx] [-r | -s] [-d del] "
+ "[file ...]\n");
+ exit(1);
+}
+
+/*
+ * Token printing for each token type .
+ */
+static int
+print_tokens(FILE *fp)
+{
+ u_char *buf;
+ tokenstr_t tok;
+ int reclen;
+ int bytesread;
+
+ /* Allow tail -f | praudit to work. */
+ if (partial) {
+ u_char type = 0;
+ /* Record must begin with a header token. */
+ do {
+ type = fgetc(fp);
+ } while(type != AUT_HEADER32);
+ ungetc(type, fp);
+ }
+
+ while ((reclen = au_read_rec(fp, &buf)) != -1) {
+ bytesread = 0;
+ while (bytesread < reclen) {
+ /* Is this an incomplete record? */
+ if (-1 == au_fetch_tok(&tok, buf + bytesread,
+ reclen - bytesread))
+ break;
+ au_print_flags_tok(stdout, &tok, del, oflags);
+ bytesread += tok.len;
+ if (oneline) {
+ if (!(oflags & AU_OFLAG_XML))
+ printf("%s", del);
+ } else
+ printf("\n");
+ }
+ free(buf);
+ if (oneline)
+ printf("\n");
+ fflush(stdout);
+ }
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ int i;
+ FILE *fp;
+
+ while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) {
+ switch(ch) {
+ case 'd':
+ del = optarg;
+ break;
+
+ case 'l':
+ oneline = 1;
+ break;
+
+ case 'n':
+ oflags |= AU_OFLAG_NORESOLVE;
+ break;
+
+ case 'p':
+ partial = 1;
+ break;
+
+ case 'r':
+ if (oflags & AU_OFLAG_SHORT)
+ usage(); /* Exclusive from shortfrm. */
+ oflags |= AU_OFLAG_RAW;
+ break;
+
+ case 's':
+ if (oflags & AU_OFLAG_RAW)
+ usage(); /* Exclusive from raw. */
+ oflags |= AU_OFLAG_SHORT;
+ break;
+
+ case 'x':
+ oflags |= AU_OFLAG_XML;
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ if (oflags & AU_OFLAG_XML)
+ au_print_xml_header(stdout);
+
+ /* For each of the files passed as arguments dump the contents. */
+ if (optind == argc) {
+ print_tokens(stdin);
+ return (1);
+ }
+ for (i = optind; i < argc; i++) {
+ fp = fopen(argv[i], "r");
+ if ((fp == NULL) || (print_tokens(fp) == -1))
+ perror(argv[i]);
+ if (fp != NULL)
+ fclose(fp);
+ }
+
+ if (oflags & AU_OFLAG_XML)
+ au_print_xml_footer(stdout);
+
+ return (1);
+}
OpenPOWER on IntegriCloud