summaryrefslogtreecommitdiffstats
path: root/contrib/openbsm/libbsm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/openbsm/libbsm')
-rw-r--r--contrib/openbsm/libbsm/Makefile.am157
-rw-r--r--contrib/openbsm/libbsm/Makefile.in792
-rw-r--r--contrib/openbsm/libbsm/au_class.3118
-rw-r--r--contrib/openbsm/libbsm/au_control.3258
-rw-r--r--contrib/openbsm/libbsm/au_domain.386
-rw-r--r--contrib/openbsm/libbsm/au_errno.3110
-rw-r--r--contrib/openbsm/libbsm/au_event.3169
-rw-r--r--contrib/openbsm/libbsm/au_fcntl_cmd.395
-rw-r--r--contrib/openbsm/libbsm/au_free_token.395
-rw-r--r--contrib/openbsm/libbsm/au_io.3173
-rw-r--r--contrib/openbsm/libbsm/au_mask.3154
-rw-r--r--contrib/openbsm/libbsm/au_notify.3118
-rw-r--r--contrib/openbsm/libbsm/au_open.3156
-rw-r--r--contrib/openbsm/libbsm/au_socket_type.391
-rw-r--r--contrib/openbsm/libbsm/au_token.3252
-rw-r--r--contrib/openbsm/libbsm/au_user.3154
-rw-r--r--contrib/openbsm/libbsm/audit_submit.3151
-rw-r--r--contrib/openbsm/libbsm/bsm_audit.c449
-rw-r--r--contrib/openbsm/libbsm/bsm_class.c300
-rw-r--r--contrib/openbsm/libbsm/bsm_control.c708
-rw-r--r--contrib/openbsm/libbsm/bsm_domain.c490
-rw-r--r--contrib/openbsm/libbsm/bsm_errno.c771
-rw-r--r--contrib/openbsm/libbsm/bsm_event.c361
-rw-r--r--contrib/openbsm/libbsm/bsm_fcntl.c287
-rw-r--r--contrib/openbsm/libbsm/bsm_flags.c180
-rw-r--r--contrib/openbsm/libbsm/bsm_io.c4612
-rw-r--r--contrib/openbsm/libbsm/bsm_mask.c212
-rw-r--r--contrib/openbsm/libbsm/bsm_notify.c179
-rw-r--r--contrib/openbsm/libbsm/bsm_socket_type.c102
-rw-r--r--contrib/openbsm/libbsm/bsm_token.c1645
-rw-r--r--contrib/openbsm/libbsm/bsm_user.c294
-rw-r--r--contrib/openbsm/libbsm/bsm_wrappers.c821
-rw-r--r--contrib/openbsm/libbsm/libbsm.3248
33 files changed, 14788 insertions, 0 deletions
diff --git a/contrib/openbsm/libbsm/Makefile.am b/contrib/openbsm/libbsm/Makefile.am
new file mode 100644
index 0000000..278f228
--- /dev/null
+++ b/contrib/openbsm/libbsm/Makefile.am
@@ -0,0 +1,157 @@
+if USE_NATIVE_INCLUDES
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)
+else
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys
+endif
+
+lib_LTLIBRARIES = libbsm.la
+
+libbsm_la_SOURCES = \
+ bsm_audit.c \
+ bsm_class.c \
+ bsm_control.c \
+ bsm_domain.c \
+ bsm_errno.c \
+ bsm_event.c \
+ bsm_fcntl.c \
+ bsm_flags.c \
+ bsm_io.c \
+ bsm_mask.c \
+ bsm_socket_type.c \
+ bsm_token.c \
+ bsm_user.c
+
+if HAVE_AUDIT_SYSCALLS
+libbsm_la_SOURCES += \
+ bsm_notify.c \
+ bsm_wrappers.c
+endif
+
+man3_MANS = \
+ au_class.3 \
+ au_control.3 \
+ au_domain.3 \
+ au_errno.3 \
+ au_event.3 \
+ au_fcntl_cmd.3 \
+ au_free_token.3 \
+ au_io.3 \
+ au_mask.3 \
+ au_notify.3 \
+ au_open.3 \
+ au_socket_type.3 \
+ au_token.3 \
+ au_user.3 \
+ libbsm.3
+
+install-exec-hook:
+ cd $(DESTDIR)$(mandir) && \
+ $(LN_S) -f au_class.3 getauclassent.3 && \
+ $(LN_S) -f au_class.3 getauclassent_r.3 && \
+ $(LN_S) -f au_class.3 getauclassnam.3 && \
+ $(LN_S) -f au_class.3 getauclassnam_r.3 && \
+ $(LN_S) -f au_class.3 setauclass.3 && \
+ $(LN_S) -f au_class.3 endauclass.3 && \
+ $(LN_S) -f au_control.3 setac.3 && \
+ $(LN_S) -f au_control.3 endac.3 && \
+ $(LN_S) -f au_control.3 getacdir.3 && \
+ $(LN_S) -f au_control.3 getacdist.3 && \
+ $(LN_S) -f au_control.3 getacexpire.3 && \
+ $(LN_S) -f au_control.3 getacfilesz.3 && \
+ $(LN_S) -f au_control.3 getacflg.3 && \
+ $(LN_S) -f au_control.3 getachost.3 && \
+ $(LN_S) -f au_control.3 getacmin.3 && \
+ $(LN_S) -f au_control.3 getacna.3 && \
+ $(LN_S) -f au_control.3 getacpol.3 && \
+ $(LN_S) -f au_control.3 au_poltostr.3 && \
+ $(LN_S) -f au_control.3 ac_strtopol.3 && \
+ $(LN_S) -f au_domain.3 au_bsm_to_domain.3 && \
+ $(LN_S) -f au_domain.3 au_domain_to_bsm.3 && \
+ $(LN_S) -f au_errno.3 au_bsm_to_errno.3 && \
+ $(LN_S) -f au_errno.3 au_errno_to_bsm.3 && \
+ $(LN_S) -f au_errno.3 au_strerror.3 && \
+ $(LN_S) -f au_event.3 setauevent.3 && \
+ $(LN_S) -f au_event.3 endauevent.3 && \
+ $(LN_S) -f au_event.3 getauevent.3 && \
+ $(LN_S) -f au_event.3 getauevent_r.3 && \
+ $(LN_S) -f au_event.3 getauevnam.3 && \
+ $(LN_S) -f au_event.3 getauevnam_r.3 && \
+ $(LN_S) -f au_event.3 getauevnum.3 && \
+ $(LN_S) -f au_event.3 getauevnum_r.3 && \
+ $(LN_S) -f au_event.3 getauevnonam.3 && \
+ $(LN_S) -f au_event.3 getauevnonam_r.3 && \
+ $(LN_S) -f au_fcntl.3 au_bsm_to_fcntl_cmd.3 && \
+ $(LN_S) -f au_fcntl.3 au_fcntl_cmd_to_bsm.3 && \
+ $(LN_S) -f au_io.3 au_fetch_tok.3 && \
+ $(LN_S) -f au_io.3 au_print_tok.3 && \
+ $(LN_S) -f au_io.3 au_print_flags_tok.3 && \
+ $(LN_S) -f au_io.3 au_read_rec.3 && \
+ $(LN_S) -f au_mask.3 au_preselect.3 && \
+ $(LN_S) -f au_mask.3 getauditflagsbin.3 && \
+ $(LN_S) -f au_mask.3 getauditflagschar.3 && \
+ $(LN_S) -f au_notify.3 au_get_state.3 && \
+ $(LN_S) -f au_notify.3 au_notify_initialize.3 && \
+ $(LN_S) -f au_notify.3 au_notify_terminate.3 && \
+ $(LN_S) -f au_open.3 au_open.3 && \
+ $(LN_S) -f au_open.3 au_write.3 && \
+ $(LN_S) -f au_open.3 au_close.3 && \
+ $(LN_S) -f au_open.3 au_close_buffer.3 && \
+ $(LN_S) -f au_open.3 au_close_token.3 && \
+ $(LN_S) -f au_socket_type.3 au_bsm_to_socket_type.3 && \
+ $(LN_S) -f au_socket_type.3 au_socket_type_to_bsm.3 && \
+ $(LN_S) -f au_token.3 au_to_arg32.3 && \
+ $(LN_S) -f au_token.3 au_to_arg64.3 && \
+ $(LN_S) -f au_token.3 au_to_arg.3 && \
+ $(LN_S) -f au_token.3 au_to_attr64.3 && \
+ $(LN_S) -f au_token.3 au_to_data.3 && \
+ $(LN_S) -f au_token.3 au_to_exit.3 && \
+ $(LN_S) -f au_token.3 au_to_groups.3 && \
+ $(LN_S) -f au_token.3 au_to_newgroups.3 && \
+ $(LN_S) -f au_token.3 au_to_in_addr.3 && \
+ $(LN_S) -f au_token.3 au_to_in_addr_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_ip.3 && \
+ $(LN_S) -f au_token.3 au_to_ipc.3 && \
+ $(LN_S) -f au_token.3 au_to_ipc_perm.3 && \
+ $(LN_S) -f au_token.3 au_to_iport.3 && \
+ $(LN_S) -f au_token.3 au_to_opaque.3 && \
+ $(LN_S) -f au_token.3 au_to_file.3 && \
+ $(LN_S) -f au_token.3 au_to_text.3 && \
+ $(LN_S) -f au_token.3 au_to_path.3 && \
+ $(LN_S) -f au_token.3 au_to_process32.3 && \
+ $(LN_S) -f au_token.3 au_to_process64.3 && \
+ $(LN_S) -f au_token.3 au_to_process.3 && \
+ $(LN_S) -f au_token.3 au_to_process32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_process64_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_process_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_return32.3 && \
+ $(LN_S) -f au_token.3 au_to_return64.3 && \
+ $(LN_S) -f au_token.3 au_to_return.3 && \
+ $(LN_S) -f au_token.3 au_to_seq.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet32.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet128.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet.3 && \
+ $(LN_S) -f au_token.3 au_to_socket_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject32.3 && \
+ $(LN_S) -f au_token.3 au_to_subject64.3 && \
+ $(LN_S) -f au_token.3 au_to_subject.3 && \
+ $(LN_S) -f au_token.3 au_to_subject32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject64_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_me.3 && \
+ $(LN_S) -f au_token.3 au_to_exec_args.3 && \
+ $(LN_S) -f au_token.3 au_to_exec_env.3 && \
+ $(LN_S) -f au_token.3 au_to_header.3 && \
+ $(LN_S) -f au_token.3 au_to_header32.3 && \
+ $(LN_S) -f au_token.3 au_to_header64.3 && \
+ $(LN_S) -f au_token.3 au_to_header_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_header32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_trailer.3 && \
+ $(LN_S) -f au_token.3 au_to_zonename.3 && \
+ $(LN_S) -f au_user.3 setauuser.3 && \
+ $(LN_S) -f au_user.3 endauuser.3 && \
+ $(LN_S) -f au_user.3 getauuserent.3 && \
+ $(LN_S) -f au_user.3 getauuserent_r.3 && \
+ $(LN_S) -f au_user.3 getauusernam.3 && \
+ $(LN_S) -f au_user.3 getauusernam_r.3 && \
+ $(LN_S) -f au_user.3 au_user_mask.3 && \
+ $(LN_S) -f au_user.3 getfauditflags.3
diff --git a/contrib/openbsm/libbsm/Makefile.in b/contrib/openbsm/libbsm/Makefile.in
new file mode 100644
index 0000000..0549153
--- /dev/null
+++ b/contrib/openbsm/libbsm/Makefile.in
@@ -0,0 +1,792 @@
+# 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@ bsm_notify.c \
+@HAVE_AUDIT_SYSCALLS_TRUE@ bsm_wrappers.c
+
+subdir = libbsm
+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__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; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libbsm_la_LIBADD =
+am__libbsm_la_SOURCES_DIST = bsm_audit.c bsm_class.c bsm_control.c \
+ bsm_domain.c bsm_errno.c bsm_event.c bsm_fcntl.c bsm_flags.c \
+ bsm_io.c bsm_mask.c bsm_socket_type.c bsm_token.c bsm_user.c \
+ bsm_notify.c bsm_wrappers.c
+@HAVE_AUDIT_SYSCALLS_TRUE@am__objects_1 = bsm_notify.lo \
+@HAVE_AUDIT_SYSCALLS_TRUE@ bsm_wrappers.lo
+am_libbsm_la_OBJECTS = bsm_audit.lo bsm_class.lo bsm_control.lo \
+ bsm_domain.lo bsm_errno.lo bsm_event.lo bsm_fcntl.lo \
+ bsm_flags.lo bsm_io.lo bsm_mask.lo bsm_socket_type.lo \
+ bsm_token.lo bsm_user.lo $(am__objects_1)
+libbsm_la_OBJECTS = $(am_libbsm_la_OBJECTS)
+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 = $(libbsm_la_SOURCES)
+DIST_SOURCES = $(am__libbsm_la_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+man3dir = $(mandir)/man3
+NROFF = nroff
+MANS = $(man3_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)
+lib_LTLIBRARIES = libbsm.la
+libbsm_la_SOURCES = bsm_audit.c bsm_class.c bsm_control.c bsm_domain.c \
+ bsm_errno.c bsm_event.c bsm_fcntl.c bsm_flags.c bsm_io.c \
+ bsm_mask.c bsm_socket_type.c bsm_token.c bsm_user.c \
+ $(am__append_1)
+man3_MANS = \
+ au_class.3 \
+ au_control.3 \
+ au_domain.3 \
+ au_errno.3 \
+ au_event.3 \
+ au_fcntl_cmd.3 \
+ au_free_token.3 \
+ au_io.3 \
+ au_mask.3 \
+ au_notify.3 \
+ au_open.3 \
+ au_socket_type.3 \
+ au_token.3 \
+ au_user.3 \
+ libbsm.3
+
+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 libbsm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign libbsm/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-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+libbsm.la: $(libbsm_la_OBJECTS) $(libbsm_la_DEPENDENCIES) $(EXTRA_libbsm_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libbsm_la_OBJECTS) $(libbsm_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_audit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_class.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_control.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_domain.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_errno.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_event.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_fcntl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_flags.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_mask.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_notify.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_socket_type.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_token.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_user.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_wrappers.Plo@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-man3: $(man3_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man3_MANS)'; \
+ list2=''; \
+ test -n "$(man3dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man3dir)" || 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 '/\.3[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,^[^3][0-9a-z]*$$,3,;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)$(man3dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$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)$(man3dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man3:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man3_MANS)'; test -n "$(man3dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man3dir)'; $(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 $(LTLIBRARIES) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)"; 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-libLTLIBRARIES clean-libtool \
+ 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-libLTLIBRARIES
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man3
+
+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-libLTLIBRARIES uninstall-man
+
+uninstall-man: uninstall-man3
+
+.MAKE: install-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool 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-exec-hook \
+ install-html install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-man3 install-pdf \
+ install-pdf-am install-ps install-ps-am 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-libLTLIBRARIES \
+ uninstall-man uninstall-man3
+
+
+install-exec-hook:
+ cd $(DESTDIR)$(mandir) && \
+ $(LN_S) -f au_class.3 getauclassent.3 && \
+ $(LN_S) -f au_class.3 getauclassent_r.3 && \
+ $(LN_S) -f au_class.3 getauclassnam.3 && \
+ $(LN_S) -f au_class.3 getauclassnam_r.3 && \
+ $(LN_S) -f au_class.3 setauclass.3 && \
+ $(LN_S) -f au_class.3 endauclass.3 && \
+ $(LN_S) -f au_control.3 setac.3 && \
+ $(LN_S) -f au_control.3 endac.3 && \
+ $(LN_S) -f au_control.3 getacdir.3 && \
+ $(LN_S) -f au_control.3 getacdist.3 && \
+ $(LN_S) -f au_control.3 getacexpire.3 && \
+ $(LN_S) -f au_control.3 getacfilesz.3 && \
+ $(LN_S) -f au_control.3 getacflg.3 && \
+ $(LN_S) -f au_control.3 getachost.3 && \
+ $(LN_S) -f au_control.3 getacmin.3 && \
+ $(LN_S) -f au_control.3 getacna.3 && \
+ $(LN_S) -f au_control.3 getacpol.3 && \
+ $(LN_S) -f au_control.3 au_poltostr.3 && \
+ $(LN_S) -f au_control.3 ac_strtopol.3 && \
+ $(LN_S) -f au_domain.3 au_bsm_to_domain.3 && \
+ $(LN_S) -f au_domain.3 au_domain_to_bsm.3 && \
+ $(LN_S) -f au_errno.3 au_bsm_to_errno.3 && \
+ $(LN_S) -f au_errno.3 au_errno_to_bsm.3 && \
+ $(LN_S) -f au_errno.3 au_strerror.3 && \
+ $(LN_S) -f au_event.3 setauevent.3 && \
+ $(LN_S) -f au_event.3 endauevent.3 && \
+ $(LN_S) -f au_event.3 getauevent.3 && \
+ $(LN_S) -f au_event.3 getauevent_r.3 && \
+ $(LN_S) -f au_event.3 getauevnam.3 && \
+ $(LN_S) -f au_event.3 getauevnam_r.3 && \
+ $(LN_S) -f au_event.3 getauevnum.3 && \
+ $(LN_S) -f au_event.3 getauevnum_r.3 && \
+ $(LN_S) -f au_event.3 getauevnonam.3 && \
+ $(LN_S) -f au_event.3 getauevnonam_r.3 && \
+ $(LN_S) -f au_fcntl.3 au_bsm_to_fcntl_cmd.3 && \
+ $(LN_S) -f au_fcntl.3 au_fcntl_cmd_to_bsm.3 && \
+ $(LN_S) -f au_io.3 au_fetch_tok.3 && \
+ $(LN_S) -f au_io.3 au_print_tok.3 && \
+ $(LN_S) -f au_io.3 au_print_flags_tok.3 && \
+ $(LN_S) -f au_io.3 au_read_rec.3 && \
+ $(LN_S) -f au_mask.3 au_preselect.3 && \
+ $(LN_S) -f au_mask.3 getauditflagsbin.3 && \
+ $(LN_S) -f au_mask.3 getauditflagschar.3 && \
+ $(LN_S) -f au_notify.3 au_get_state.3 && \
+ $(LN_S) -f au_notify.3 au_notify_initialize.3 && \
+ $(LN_S) -f au_notify.3 au_notify_terminate.3 && \
+ $(LN_S) -f au_open.3 au_open.3 && \
+ $(LN_S) -f au_open.3 au_write.3 && \
+ $(LN_S) -f au_open.3 au_close.3 && \
+ $(LN_S) -f au_open.3 au_close_buffer.3 && \
+ $(LN_S) -f au_open.3 au_close_token.3 && \
+ $(LN_S) -f au_socket_type.3 au_bsm_to_socket_type.3 && \
+ $(LN_S) -f au_socket_type.3 au_socket_type_to_bsm.3 && \
+ $(LN_S) -f au_token.3 au_to_arg32.3 && \
+ $(LN_S) -f au_token.3 au_to_arg64.3 && \
+ $(LN_S) -f au_token.3 au_to_arg.3 && \
+ $(LN_S) -f au_token.3 au_to_attr64.3 && \
+ $(LN_S) -f au_token.3 au_to_data.3 && \
+ $(LN_S) -f au_token.3 au_to_exit.3 && \
+ $(LN_S) -f au_token.3 au_to_groups.3 && \
+ $(LN_S) -f au_token.3 au_to_newgroups.3 && \
+ $(LN_S) -f au_token.3 au_to_in_addr.3 && \
+ $(LN_S) -f au_token.3 au_to_in_addr_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_ip.3 && \
+ $(LN_S) -f au_token.3 au_to_ipc.3 && \
+ $(LN_S) -f au_token.3 au_to_ipc_perm.3 && \
+ $(LN_S) -f au_token.3 au_to_iport.3 && \
+ $(LN_S) -f au_token.3 au_to_opaque.3 && \
+ $(LN_S) -f au_token.3 au_to_file.3 && \
+ $(LN_S) -f au_token.3 au_to_text.3 && \
+ $(LN_S) -f au_token.3 au_to_path.3 && \
+ $(LN_S) -f au_token.3 au_to_process32.3 && \
+ $(LN_S) -f au_token.3 au_to_process64.3 && \
+ $(LN_S) -f au_token.3 au_to_process.3 && \
+ $(LN_S) -f au_token.3 au_to_process32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_process64_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_process_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_return32.3 && \
+ $(LN_S) -f au_token.3 au_to_return64.3 && \
+ $(LN_S) -f au_token.3 au_to_return.3 && \
+ $(LN_S) -f au_token.3 au_to_seq.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet32.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet128.3 && \
+ $(LN_S) -f au_token.3 au_to_sock_inet.3 && \
+ $(LN_S) -f au_token.3 au_to_socket_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject32.3 && \
+ $(LN_S) -f au_token.3 au_to_subject64.3 && \
+ $(LN_S) -f au_token.3 au_to_subject.3 && \
+ $(LN_S) -f au_token.3 au_to_subject32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject64_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_subject_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_me.3 && \
+ $(LN_S) -f au_token.3 au_to_exec_args.3 && \
+ $(LN_S) -f au_token.3 au_to_exec_env.3 && \
+ $(LN_S) -f au_token.3 au_to_header.3 && \
+ $(LN_S) -f au_token.3 au_to_header32.3 && \
+ $(LN_S) -f au_token.3 au_to_header64.3 && \
+ $(LN_S) -f au_token.3 au_to_header_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_header32_ex.3 && \
+ $(LN_S) -f au_token.3 au_to_trailer.3 && \
+ $(LN_S) -f au_token.3 au_to_zonename.3 && \
+ $(LN_S) -f au_user.3 setauuser.3 && \
+ $(LN_S) -f au_user.3 endauuser.3 && \
+ $(LN_S) -f au_user.3 getauuserent.3 && \
+ $(LN_S) -f au_user.3 getauuserent_r.3 && \
+ $(LN_S) -f au_user.3 getauusernam.3 && \
+ $(LN_S) -f au_user.3 getauusernam_r.3 && \
+ $(LN_S) -f au_user.3 au_user_mask.3 && \
+ $(LN_S) -f au_user.3 getfauditflags.3
+
+# 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/libbsm/au_class.3 b/contrib/openbsm/libbsm/au_class.3
new file mode 100644
index 0000000..acdac62
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_class.3
@@ -0,0 +1,118 @@
+.\"-
+.\" Copyright (c) 2005-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 April 19, 2005
+.Dt AU_CLASS 3
+.Os
+.Sh NAME
+.Nm getauclassent ,
+.Nm getauclassent_r ,
+.Nm getauclassnam ,
+.Nm getauclassnam_r ,
+.Nm setauclass ,
+.Nm endauclass
+.Nd "look up information from the audit_class database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft "struct au_class_ent *"
+.Fn getauclassent void
+.Ft "struct au_class_ent *"
+.Fn getauclassent_r "struct au_class_ent *e"
+.Ft "struct au_class_ent *"
+.Fn getauclassnam "const char *name"
+.Ft "struct au_class_ent *"
+.Fn getauclassnam_r "struct au_class_ent *e" "const char *name"
+.Ft void
+.Fn setauclass void
+.Ft void
+.Fn endauclass void
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_class 5
+database, which describes audit event classes.
+Audit event classes are described by
+.Vt "struct au_class_ent" .
+.Pp
+The
+.Fn getauclassent
+function
+will return the next class found in the
+.Xr audit_class 5
+database, or the first if the function has not yet been called.
+.Dv NULL
+will be returned if no further records are available.
+.Pp
+The
+.Fn getauclassnam
+function
+looks up a class by name.
+.Dv NULL
+will be returned if no matching class can be found.
+.Pp
+The
+.Fn setauclass
+function
+resets the iterator through the
+.Xr audit_class 5
+database, causing the next call to
+.Fn getauclassent
+to start again from the beginning of the file.
+.Pp
+The
+.Fn endauclass
+function
+closes the
+.Xr audit_class 5
+database, if open.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_class 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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
diff --git a/contrib/openbsm/libbsm/au_control.3 b/contrib/openbsm/libbsm/au_control.3
new file mode 100644
index 0000000..d4d4450
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_control.3
@@ -0,0 +1,258 @@
+.\"-
+.\" Copyright (c) 2005-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 April 19, 2005
+.Dt AU_CONTROL 3
+.Os
+.Sh NAME
+.Nm setac ,
+.Nm endac ,
+.Nm getacdir ,
+.Nm getacdist ,
+.Nm getacexpire ,
+.Nm getacfilesz ,
+.Nm getacflg ,
+.Nm getachost ,
+.Nm getacmin ,
+.Nm getacna ,
+.Nm getacpol ,
+.Nm au_poltostr ,
+.Nm au_strtopol
+.Nd "look up information from the audit_control database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft void
+.Fn setac void
+.Ft void
+.Fn endac void
+.Ft int
+.Fn getacdir "char *name" "int len"
+.Ft int
+.Fn getacdist "void"
+.Ft int
+.Fn getacexpire "int *andflg" "time_t *age" "size_t *size"
+.Ft int
+.Fn getacfilesz "size_t *size_val"
+.Ft int
+.Fn getacflg "char *auditstr" "int len"
+.Ft int
+.Fn getachost "char *auditstr" "int len"
+.Ft int
+.Fn getacmin "int *min_val"
+.Ft int
+.Fn getacna "char *auditstr" "int len"
+.Ft int
+.Fn getacpol "char *auditstr" "size_t len"
+.Ft ssize_t
+.Fn au_poltostr "int policy" "size_t maxsize" "char *buf"
+.Ft int
+.Fn au_strtopol "const char *polstr" "int *policy"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_control 5
+database, which contains various audit-related administrative parameters.
+.Pp
+The
+.Fn setac
+function
+resets the database iterator to the beginning of the database; see the
+.Sx BUGS
+section for more information.
+.Pp
+The
+.Fn endac
+function
+closes the
+.Xr audit_control 5
+database.
+.Pp
+The
+.Fn getacdir
+function
+returns the name of the directory where log data is stored via the passed
+character buffer
+.Fa name
+of length
+.Fa len .
+.Pp
+The
+.Fn getacdist
+function returns a value that allows to decide if trail files distribution is
+turned on or off.
+.Pp
+The
+.Fn getacexpire
+function
+returns the audit trail file expiration parameters in the passed
+.Vt int
+buffer
+.Fa andflg ,
+.Vt time_t
+buffer
+.Fa age
+and
+.Vt size_t
+buffer
+.Fa size .
+If the parameter is not specified in the
+.Xr audit_control 5
+file it is set to zero.
+.Pp
+The
+.Fn getacfilesz
+function
+returns the audit trail rotation size in the passed
+.Vt size_t
+buffer
+.Fa size_val .
+.Pp
+The
+.Fn getacflg
+function
+returns the audit system flags via the the passed character buffer
+.Fa auditstr
+of length
+.Fa len .
+.Pp
+The
+.Fn getachost
+function
+returns the local systems's audit host information via the the passed character
+buffer
+.Fa auditstr
+of length
+.Fa len .
+.Pp
+The
+.Fn getacmin
+function
+returns the minimum free disk space for the audit log target file system via
+the passed
+.Fa min_val
+variable.
+.Pp
+The
+.Fn getacna
+function
+returns the non-attributable flags via the passed character buffer
+.Fa auditstr
+of length
+.Fa len .
+.Pp
+The
+.Fn getacpol
+function
+returns the audit policy flags via the passed character buffer
+.Fa auditstr
+of length
+.Fa len .
+.Pp
+The
+.Fn au_poltostr
+function
+converts a numeric audit policy mask,
+.Fa policy ,
+to a string in the passed character buffer
+.Fa buf
+of lenth
+.Fa maxsize .
+.Pp
+The
+.Fn au_strtopol
+function
+converts an audit policy flags string,
+.Fa polstr ,
+to a numeric audit policy mask returned via
+.Fa policy .
+.Sh RETURN VALULES
+The
+.Fn getacfilesz ,
+.Fn getacdir ,
+.Fn getacexpire ,
+.Fn getacflg ,
+.Fn getachost ,
+.Fn getacmin ,
+.Fn getacna ,
+.Fn getacpol ,
+and
+.Fn au_strtopol
+functions
+return 0 on success, or a negative value on failure, along with error
+information in
+.Va errno .
+.Pp
+The
+.Fn au_poltostr
+function
+returns a string length of 0 or more on success, or a negative value on
+if there is a failure.
+.Pp
+The
+.Fn getacdist
+function returns 1 if trail files distribution is turned on, 0 if it is turned
+off or negative value on failure.
+.Pp
+Functions that return a string value will return a failure if there is
+insufficient room in the passed character buffer for the full string.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_control 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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
+.Pp
+There is no reason for the
+.Fn setac
+interface to be exposed as part of the public API, as it is called implicitly
+by other access functions and iteration is not supported.
+.Pp
+These interfaces inconsistently return various negative values depending on
+the failure mode, and do not always set
+.Va errno
+on failure.
diff --git a/contrib/openbsm/libbsm/au_domain.3 b/contrib/openbsm/libbsm/au_domain.3
new file mode 100644
index 0000000..2f16b38
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_domain.3
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright (c) 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.
+.\"
+.Dd December 28, 2008
+.Dt AU_BSM_TO_DOMAIN 3
+.Os
+.Sh NAME
+.Nm au_bsm_to_domain ,
+.Nm au_domain_to_bsm
+.Nd "convert between BSM and local protocol domains"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_bsm_to_domain "u_short bsm_domain" "int *local_domainp"
+.Ft u_short
+.Fn au_domain_to_bsm "int local_domain"
+.Sh DESCRIPTION
+These interfaces may be used to convert between the local and BSM protocol
+domains.
+The
+.Fn au_bsm_to_domain
+function accepts a BSM domain,
+.Fa bsm_domain ,
+and converts it to a local domain, such as those passed to
+.Xr socket 2 ,
+that will be stored in the integer pointed to by
+.Fa local_domainp
+if successful.
+This call will fail if the BSM domain cannot be mapped into a local domain,
+which may occur if the socket token was generated on another operating
+system.
+.Pp
+The
+.Fn au_domain_to_bsm
+function accepts a local domain, and returns the BSM domain for it.
+This call cannot fail, and instead returns a BSM domain indicating to a later
+decoder that the domain could not be encoded.
+.Sh RETURN VALULES
+On success,
+.Fn au_bsm_to_domain
+returns 0 and a converted domain; on failure, it returns -1 but does not set
+.Xr errno 2 .
+.Sh SEE ALSO
+.Xr au_bsm_to_socket_type 3 ,
+.Xr au_socket_type_to_bsm 3 ,
+.Xr au_to_socket_ex 3 ,
+.Xr libbsm 3
+.Sh HISTORY
+.Fn au_bsm_to_domain
+and
+.Fn au_domain_to_bsm
+were introduced in OpenBSM 1.1.
+.Sh AUTHORS
+These functions were implemented by
+.An Robert Watson
+under contract to Apple 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/libbsm/au_errno.3 b/contrib/openbsm/libbsm/au_errno.3
new file mode 100644
index 0000000..93873ce
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_errno.3
@@ -0,0 +1,110 @@
+.\"-
+.\" Copyright (c) 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.
+.\"
+.Dd December 8, 2008
+.Dt AU_BSM_TO_ERRNO 3
+.Os
+.Sh NAME
+.Nm au_bsm_to_errno ,
+.Nm au_errno_to_bsm ,
+.Nm au_strerror
+.Nd "convert between BSM and local error numbers"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_bsm_to_errno "u_char bsm_error" "int *errorp"
+.Ft u_char
+.Fn au_errno_to_bsm "int error"
+.Ft const char *
+.Fn au_strerror "int bsm_error"
+.Sh DESCRIPTION
+These interfaces may be used to convert between the local (
+.Xr errno 2 )
+and BSM error number spaces found in BSM return tokens.
+.Pp
+The
+.Fn au_bsm_to_errno
+function accepts a BSM error value,
+.Fa bsm_error ,
+and converts it to an
+.Xr errno 2
+that will be stored in the integer pointed to by
+.Fa errorp
+if successful.
+This call will fail if the BSM error cannot be mapped into a local error
+number, which may occur if the return token was generated on another
+operating system.
+.Pp
+The
+.Fn au_errno_to_bsm
+function accepts a local
+.Xr errno 2
+value, and returns the BSM error number for it.
+This call cannot fail, and instead returns a BSM error number indicating to
+a later decoder that the error could not be encoded.
+.Pp
+The
+.Fn au_strerror
+function converts a BSM error value to a string, generally by converting first to a
+local error number and using the local
+.Xr strerror 3
+function, but will also work for errors that are not locally defined.
+.Sh RETURN VALULES
+On success,
+.Fn au_bsm_to_errno
+returns 0 and a converted error value; on failure, it returns -1 but does not
+set
+.Xr errno 2 .
+.Pp
+On success,
+.Fn au_strerror
+returns a pointer to an error string; on failure it will return
+.Dv NULL .
+.Sh SEE ALSO
+.Xr au_to_return 3 ,
+.Xr au_to_return32 3 ,
+.Xr au_to_return64 3 ,
+.Xr libbsm 3
+.Sh HISTORY
+.Fn au_bsm_to_errno
+and
+.Fn au_errno_to_bsm
+were introduced in OpenBSM 1.1.
+.Sh AUTHORS
+These functions were implemented by
+.An Robert Watson
+under contract to Apple Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+.Nm au_strerror
+is unable to provide localized strings for errors not available in the local
+operating system.
diff --git a/contrib/openbsm/libbsm/au_event.3 b/contrib/openbsm/libbsm/au_event.3
new file mode 100644
index 0000000..781ba1b
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_event.3
@@ -0,0 +1,169 @@
+.\"-
+.\" Copyright (c) 2005-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 April 19, 2005
+.Dt AU_EVENT 3
+.Os
+.Sh NAME
+.Nm free_au_event_ent ,
+.Nm setauevent ,
+.Nm endauevent ,
+.Nm getauevent ,
+.Nm getauevent_r ,
+.Nm getauevnam ,
+.Nm getauevnam_r ,
+.Nm getauevnum ,
+.Nm getauevnum_r ,
+.Nm getauevnonam ,
+.Nm getauevnonam_r
+.Nd "look up information from the audit_event database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft void
+.Fn setauevent void
+.Ft void
+.Fn endauevent void
+.Ft "struct au_event_ent *"
+.Fn getauevent void
+.Ft "struct au_event_ent *"
+.Fn getauevent_r "struct au_event_ent *e"
+.Ft "struct au_event_ent *"
+.Fn getauevnam "const char *name"
+.Ft "struct au_event_ent *"
+.Fn getauevnam_r "struct au_event_ent *e" "const char *name"
+.Ft "struct au_event_ent *"
+.Fn getauevnum "au_event_t event_number"
+.Ft "struct au_event_ent *"
+.Fn getauevnum_r "struct au_event_ent *e" "au_event_t event_number"
+.Ft "au_event_t *"
+.Fn getauevnonam "const char *event_name"
+.Ft "au_event_t *"
+.Fn getauevnonam_r "au_event_t *ev" "const char *event_name"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_event 5
+database, which describes audit events.
+Entries in the database are described by
+.Vt "struct au_event_ent"
+entries, which are returned by calls to
+.Fn getauevent ,
+.Fn getauevnam ,
+or
+.Fn getauevnum .
+It is also possible to look up an event number via a call to
+.Fn getauevnonam .
+.Pp
+The
+.Fn setauevent
+function
+resets the database access session for
+.Xr audit_event 5 ,
+so that the next call to
+.Fn getauevent
+will start with the first entry in the database.
+.Pp
+The
+.Fn endauevent
+function
+closes the
+.Xr audit_event 5
+database session.
+.Pp
+The
+.Fn getauevent
+function
+returns a reference to the next entry in the
+.Xr audit_event 5
+database.
+.Pp
+The
+.Fn getauevnam
+function
+returns a reference to the entry in the
+.Xr audit_event 5
+database with a name of
+.Fa name .
+.Pp
+.Fn getauevnum
+returns a reference to the entry in the
+.Xr audit_event 5
+database with an event number of
+.Fa event_number .
+.Pp
+The
+.Fn getauevnonam
+function
+returns a reference to an audit event number using the
+.Xr audit_event 5
+database.
+.Sh RETURN VALUES
+Functions
+.Fn getauevent ,
+.Fn getauevent_r ,
+.Fn getauevnam ,
+.Fn getauevnam_r ,
+.Fn getauevnum ,
+.Fn getauevnum_r ,
+and
+.Fn getauevnonam
+will return a reference to a
+.Vt "struct au_event_ent"
+or
+.Vt au_event_t
+on success, or
+.Dv NULL
+on failure, with
+.Va errno
+set to provide further error information.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+The
+.Va errno
+variable
+is not always properly set following a failure.
+.Pp
+These routines are thread-safe, but not re-entrant, so simultaneous or
+interleaved use of these functions will affect the iterator.
diff --git a/contrib/openbsm/libbsm/au_fcntl_cmd.3 b/contrib/openbsm/libbsm/au_fcntl_cmd.3
new file mode 100644
index 0000000..a87c3ec
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_fcntl_cmd.3
@@ -0,0 +1,95 @@
+.\"-
+.\" Copyright (c) 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 March 5, 2009
+.Dt AU_BSM_TO_FCNTL_CMD 3
+.Os
+.Sh NAME
+.Nm au_bsm_to_fcntl_cmd ,
+.Nm au_fcntl_cmd_to_bsm
+.Nd "convert between BSM and local fcntl(2) command values"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_bsm_to_fcntl_cmd "u_short bsm_fcntl_cmd" "int *local_fcntl_cmdp"
+.Ft u_short
+.Fn au_fcntl_cmd_to_bsm "int local_fcntl_cmd"
+.Sh DESCRIPTION
+These interfaces may be used to convert between the local and BSM
+.Xr fcntl 2
+command values.
+The
+.Fn au_bsm_to_fcntl_cmd
+function accepts a BSM command value,
+.Fa bsm_fcntl_cmd ,
+and converts it to a local command value passed to
+.Xr fcntl 2 ,
+that will be stored in the integer pointed to by
+.Fa local_fcntl_cmdp
+if successful.
+This call will fail if the BSM command value cannot be mapped into a local
+.Xr fcntl 2
+command value which may occur if the command token was generated on another
+operating system.
+.Pp
+The
+.Fn au_fcntl_cmd_to_bsm
+function accepts a local
+.Xr fcntl 2
+command value, and returns the BSM
+.Xr fcntl 2
+command value for it. This call cannot fail, and instead returns a BSM
+command value indicating to a later decoder that the command value could
+not be encoded.
+.Sh RETURN VALUES
+On success,
+.Fn au_bsm_to_fcntl_cmd
+returns 0 and a converted command value; on failure, it returns -1 but does
+not set
+.Xr errno 2 .
+.Sh SEE ALSO
+.Xr fcntl 2 ,
+.Xr au_bsm_to_domain 3 ,
+.Xr au_bsm_to_socket_type 3 ,
+.Xr au_domain_to_bsm 3 ,
+.Xr au_socket_type_to_bsm 3 ,
+.Xr libbsm 3
+.Sh HISTORY
+.Fn au_bsm_to_domain
+and
+.Fn au_domain_to_bsm
+were introduced in OpenBSM 1.1.
+.Sh AUTHORS
+These functions were implemented by
+.An Stacey Son
+under contract to Apple 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/libbsm/au_free_token.3 b/contrib/openbsm/libbsm/au_free_token.3
new file mode 100644
index 0000000..8820645
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_free_token.3
@@ -0,0 +1,95 @@
+.\"-
+.\" Copyright (c) 2004 Apple Inc.
+.\" Copyright (c) 2005 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.
+.\" 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,
+.\" STRING 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 April 19, 2005
+.Dt AU_FREE_TOKEN 3
+.Os
+.Sh NAME
+.Nm au_free_token
+.Nd "deallocate a token_t created by any of the au_to_*() BSM API functions"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft void
+.Fn au_free_token "token_t *tok"
+.Sh DESCRIPTION
+The BSM API generally manages deallocation of
+.Vt token_t
+objects.
+However, if
+.Xr au_write 3
+is passed a bad audit descriptor, the
+.Vt "token_t *"
+parameter will be left untouched.
+In that case, the caller can deallocate the
+.Vt token_t
+using
+.Fn au_free_token
+if desired.
+.Pp
+The
+.Fa tok
+argument is a
+.Vt "token_t *"
+generated by one of the
+.Fn au_to_*
+BSM API calls.
+For convenience,
+.Fa tok
+may be
+.Dv NULL ,
+in which case
+.Fn au_free_token
+returns immediately.
+.Sh IMPLEMENTATION NOTES
+This is, in fact, what
+.Xr audit_write 3
+does, in keeping with the existing memory management model of the BSM API.
+.Sh SEE ALSO
+.Xr au_write 3 ,
+.Xr audit_write 3 ,
+.Xr libbsm 3
+.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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, 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/libbsm/au_io.3 b/contrib/openbsm/libbsm/au_io.3
new file mode 100644
index 0000000..bfea1a8
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_io.3
@@ -0,0 +1,173 @@
+.\"-
+.\" Copyright (c) 2009 Apple, Inc.
+.\" Copyright (c) 2005 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 August 4, 2009
+.Dt AU_IO 3
+.Os
+.Sh NAME
+.Nm au_fetch_tok ,
+.Nm au_print_tok ,
+.Nm au_print_flags_tok ,
+.Nm au_read_rec
+.Nd "perform I/O involving an audit record"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_fetch_tok "tokenstr_t *tok" "u_char *buf" "int len"
+.Ft void
+.Fo au_print_tok
+.Fa "FILE *outfp" "tokenstr_t *tok" "char *del" "char raw" "char sfrm"
+.Fc
+.Ft void
+.Fo au_print_flags_tok
+.Fa "FILE *outfp" "tokenstr_t *tok" "char *del" "int oflags"
+.Fc
+.Ft int
+.Fn au_read_rec "FILE *fp" "u_char **buf"
+.Sh DESCRIPTION
+These interfaces support input and output (I/O) involving audit records,
+internalizing an audit record from a byte stream, converting a token to
+either a raw or default string, and reading a single record from a file.
+.Pp
+The
+.Fn au_fetch_tok
+function
+reads a token from the passed buffer
+.Fa buf
+of length
+.Fa len
+bytes, and returns a pointer to the token via
+.Fa tok .
+.Pp
+The
+.Fn au_print_tok
+function
+prints a string form of the token
+.Fa tok
+to the file output stream
+.Fa outfp ,
+either in default mode, or raw mode if
+.Fa raw
+is set non-zero.
+The delimiter
+.Fa del
+is used when printing.
+The
+.Fn au_print_flags_tok
+function is a replacement for
+.Fn au_print_tok .
+The
+.Fa oflags
+controls how the output should be formatted and is specified by
+or'ing the following flags:
+.Pp
+.Bl -tag -width AU_OFLAG_NORESOLVE -compact -offset indent
+.It Li AU_OFLAG_NONE
+Use the default form.
+.It Li AU_OFLAG_NORESOLVE
+Leave user and group IDs in their numeric form.
+.It Li AU_OFLAG_RAW
+Use the raw, numeric form.
+.It Li AU_OFLAG_SHORT
+Use the short form.
+.It Li AU_OFLAG_XML
+Use the XML form.
+.El
+.Pp
+The flags options AU_OFLAG_SHORT and AU_OFLAG_RAW are exclusive and
+should not be used together.
+.Pp
+The
+.Fn au_read_rec
+function
+reads an audit record from the file stream
+.Fa fp ,
+and returns an allocated memory buffer containing the record via
+.Fa *buf ,
+which must be freed by the caller using
+.Xr free 3 .
+.Pp
+A typical use of these routines might open a file with
+.Xr fopen 3 ,
+then read records from the file sequentially by calling
+.Fn au_read_rec .
+Each record would be broken down into components tokens through sequential
+calls to
+.Fn au_fetch_tok
+on the buffer, and then invoking
+.Fn au_print_flags_tok
+to print each token to an output stream such as
+.Dv stdout .
+On completion of the processing of each record, a call to
+.Xr free 3
+would be used to free the record buffer.
+Finally, the source stream would be closed by a call to
+.Xr fclose 3 .
+.Sh RETURN VALUES
+The
+.Fn au_fetch_tok
+and
+.Fn au_read_rec
+functions
+return 0 on success, or \-1 on failure along with additional error information
+returned via
+.Va errno .
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr libbsm 3
+.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.
+.Pp
+The
+.Fn au_print_flags_tok
+function was added by Stacey Son as a replacement for the
+.Fn au_print_tok
+so new output formatting flags can be easily added without changing the API.
+The
+.Fn au_print_tok
+is obsolete but remains in the API to support legacy code.
+.Sh AUTHORS
+.An -nosplit
+This software was created by
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+The
+.Va errno
+variable
+may not always be properly set in the event of an error.
diff --git a/contrib/openbsm/libbsm/au_mask.3 b/contrib/openbsm/libbsm/au_mask.3
new file mode 100644
index 0000000..c2099ea
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_mask.3
@@ -0,0 +1,154 @@
+.\"-
+.\" Copyright (c) 2005 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 April 19, 2005
+.Dt AU_MASK 3
+.Os
+.Sh NAME
+.Nm au_preselect ,
+.Nm getauditflagsbin ,
+.Nm getauditflagschar
+.Nd "convert between string and numeric values of audit masks"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_preselect "au_event_t event" "au_mask_t *mask_p" "int sorf" "int flag"
+.Ft int
+.Fn getauditflagsbin "char *auditstr" "au_mask_t *masks"
+.Ft int
+.Fn getauditflagschar "char *auditstr" "au_mask_t *masks" "int verbose"
+.Sh DESCRIPTION
+These interfaces support processing of an audit mask represented by type
+.Vt au_mask_t ,
+including conversion between numeric and text formats, and computing whether
+or not an event is matched by a mask.
+.Pp
+The
+.Fn au_preselect
+function
+calculates whether or not the audit event passed via
+.Fa event
+is matched by the audit mask passed via
+.Fa mask_p .
+The
+.Fa sorf
+argument indicates whether or not to consider the event as a success,
+if the
+.Dv AU_PRS_SUCCESS
+flag is set, or failure, if the
+.Dv AU_PRS_FAILURE
+flag is set.
+The
+.Fa flag
+argument accepts additional arguments influencing the behavior of
+.Fn au_preselect ,
+including
+.Dv AU_PRS_REREAD ,
+which causes the event to be re-looked up rather than read from the cache,
+or
+.Dv AU_PRS_USECACHE
+which forces use of the cache.
+.Pp
+The
+.Fn getauditflagsbin
+function
+converts a string representation of an audit mask passed via a character
+string pointed to by
+.Fa auditstr ,
+returning the resulting mask, if valid, via
+.Fa *masks .
+.Pp
+The
+.Fn getauditflagschar
+function
+converts the audit event mask passed via
+.Fa *masks
+and converts it to a character string in a buffer pointed to by
+.Fa auditstr .
+See the
+.Sx BUGS
+section for more information on how to provide a buffer of
+sufficient size.
+If the
+.Fa verbose
+flag is set, the class description string retrieved from
+.Xr audit_class 5
+will be used; otherwise, the two-character class name.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn au_preselect
+function
+makes implicit use of various audit database routines, and may influence
+the behavior of simultaneous or interleaved processing of those databases by
+other code.
+.Sh RETURN VALUES
+The
+.Fn au_preselect
+function
+returns 0 on success, or returns \-1 if there is a failure looking up the
+event type or other database access, in which case
+.Va errno
+will be set to indicate the error.
+It returns 1 if the event is matched; 0 if not.
+.Pp
+.Rv -std getauditflagsbin getauditflagschar
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_class 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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+The
+.Va errno
+variable
+may not always be properly set in the event of an error.
+.Pp
+The
+.Fn getauditflagschar
+function
+does not provide a way to indicate how long the character buffer is, in order
+to detect overflow.
+As a result, the caller must always provide a buffer of sufficient length for
+any possible mask, which may be calculated as three times the number of
+non-zero bits in the mask argument in the event non-verbose class names are
+used, and is not trivially predictable for verbose class names.
+This API should be replaced with a more robust one.
diff --git a/contrib/openbsm/libbsm/au_notify.3 b/contrib/openbsm/libbsm/au_notify.3
new file mode 100644
index 0000000..06e63bf
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_notify.3
@@ -0,0 +1,118 @@
+.\"-
+.\" Copyright (c) 2004-2009 Apple Inc.
+.\" Copyright (c) 2015 Christian Brueffer
+.\" 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 the author 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 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 July 29, 2015
+.Dt AU_NOTIFY 3
+.Os
+.Sh NAME
+.Nm au_get_state ,
+.Nm au_notify_initialize ,
+.Nm au_notify_terminate
+.Nd "audit event notification"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_get_state "void"
+.Ft uint32_t
+.Fn au_notify_initialize "void"
+.Ft int
+.Fn au_notify_terminate "void"
+.Sh DESCRIPTION
+The
+.Nm au_notify
+audit notification API tracks audit state in a form permitting efficient
+update, avoiding frequent system calls to check the kernel audit state.
+It is implemented only for Darwin/Mac OS X.
+.Pp
+The
+.Fn au_get_state
+function provides a lightweight way to check whether or not auditing is
+enabled.
+If a client wants to use this function to determine whether an entire
+series of audit calls should be made -- as in the common case of a caller
+building a set of tokens, then writing them -- it should cache the audit
+status in a local variable.
+This function always returns the current state of auditing.
+If audit notification has not already been initialized by calling
+.Fn au_notify_initialize
+it will be automatically initialized on the first call of
+this function.
+.Pp
+The
+.Fn au_notify_initialize
+function initializes audit notification.
+.Pp
+The
+.Fn au_notify_terminate
+function cancels audit notification and frees the resources associated with it.
+Responsible code that no longer needs to use
+.Fn au_get_state
+should call this function.
+.Sh RETURN VALUES
+If no error occurred the
+.Fn au_get_state
+function returns
+.Dv AUC_NOAUDIT
+if auditing is disabled or suspended, and
+.Dv AUC_AUDITING
+if auditing is enabled and active.
+Otherwise, the function can return any of the errno values defined for
+.Xr setaudit 2 ,
+or
+.Dv AU_UNIMPL
+if audit does not appear to be supported by the system.
+.Pp
+The
+.Fn au_notify_initialize
+function returns 0 on success,
+.Dv AU_UNIMPL
+if audit does not appear to be supported by the system,
+or one of the status codes defined in
+.In notify.h
+on Mac OS X to indicate the error.
+.Pp
+The
+.Fn au_notify_terminate
+function returns 0 on success, or \-1 on failure.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr notify 3 (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
+This software was created by
+.An Apple Computer, 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/libbsm/au_open.3 b/contrib/openbsm/libbsm/au_open.3
new file mode 100644
index 0000000..522354f
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_open.3
@@ -0,0 +1,156 @@
+.\"-
+.\" 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 March 4, 2006
+.Dt AU_OPEN 3
+.Os
+.Sh NAME
+.Nm au_close ,
+.Nm au_close_buffer ,
+.Nm au_close_token ,
+.Nm au_open ,
+.Nm au_write
+.Nd "create and commit audit records"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_open void
+.Ft int
+.Fn au_write "int d" "token_t *tok"
+.Ft int
+.Fn au_close "int d" "int keep" "short event"
+.Ft int
+.Fn au_close_buffer "int d" "short event" "u_char *buffer" "size_t *buflen"
+.Ft int
+.Fn au_close_token "token_t *tok" "u_char *buffer" "size_t *buflen"
+.Sh DESCRIPTION
+These interfaces allow applications to allocate audit records, construct a
+record using a series of tokens, and commit the audit record to the system
+event log.
+An extension API is also provided to commit the record to an in-memory
+buffer rather than the system audit log.
+.Pp
+The
+.Fn au_open
+interface allocates a new audit record descriptor.
+.Pp
+The
+.Fn au_write
+interface adds a token to an allocated audit descriptor.
+When a token has been successfully added to a record, the caller no longer
+owns the token memory, and does not need to free it directly via a call to
+.Xr au_free_token 3 .
+.Pp
+The
+.Fn au_close
+function is used to commit an audit record to the system audit log, or
+abandon the record.
+In either cases, all resources associated with the record will be released.
+The
+.Fa keep
+argument determines the behavior: a value of
+.Dv AU_TO_WRITE
+causes the record to be committed; a value of
+.Dv AU_TO_NO_WRITE
+causes it to be abandoned.
+When the audit record is committed, a BSM header will be inserted before
+tokens added to the record, using the event identifier passed via
+.Fa event ,
+and a trailer added to the end.
+Committing a record to the system audit log requires privilege.
+.Pp
+The
+.Fn au_close_buffer
+function writes the resulting record to an in-memory buffer of size
+.Fa *buflen ;
+it will write back the filled buffer length into the same variable.
+The argument
+.Fa event
+is the event identifier to use in the record header.
+.Pp
+The
+.Fn au_close_token
+function generates the BSM stream output for a single token,
+.Fa tok ,
+in the passed buffer
+.Fa buffer .
+The initial buffer size and resulting data size are passed via
+.Fa *buflen .
+The
+.Fn au_close_token
+function
+will free the token before returning.
+.Sh RETURN VALUES
+The function
+.Fn au_open
+returns a non-negative audit record descriptor number on success, or a
+negative value on failure, along with error information in
+.Va errno .
+.Pp
+The functions
+.Fn au_write ,
+.Fn au_close ,
+.Fn au_close_buffer ,
+and
+.Fn au_close_token
+return 0 on success, or a negative value on failure, along with error
+information in
+.Va errno .
+.Sh SEE ALSO
+.Xr audit_submit 3 ,
+.Xr libbsm 3
+.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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+Currently,
+.Fn au_open
+does not reserve kernel resources necessary to commit the record to the
+trail; on systems supporting
+.Fn au_close ,
+the call will block until resources are available to commit the record.
+However, this leads to the possibility of an action being permitted without
+the record being guaranteed to go to disk.
+Ideally,
+.Fn au_open
+would reserve resources necessary to commit any submitted record, releasing
+them on
+.Fn au_close .
diff --git a/contrib/openbsm/libbsm/au_socket_type.3 b/contrib/openbsm/libbsm/au_socket_type.3
new file mode 100644
index 0000000..5668569
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_socket_type.3
@@ -0,0 +1,91 @@
+.\"-
+.\" Copyright (c) 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.
+.\"
+.Dd December 28, 2008
+.Dt AU_BSM_TO_SOCKET_TYPE 3
+.Os
+.Sh NAME
+.Nm au_bsm_to_socket_type ,
+.Nm au_socket_type_to_bsm
+.Nd "convert between BSM and local socket types"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fn au_bsm_to_socket_type "u_short bsm_socket_type" "int *local_socket_typep"
+.Ft u_short
+.Fn au_socket_type_to_bsm "int local_socket_type"
+.Sh DESCRIPTION
+These interfaces may be used to convert between the local and BSM socket
+types.
+The
+.Fn au_bsm_to_socket_type
+function accepts a BSM socket type,
+.Fa bsm_socket_type ,
+and converts it to a local socket type, such as those passed to
+.Xr socket 2 ,
+that will be stored in the integer pointed to by
+.Fa local_socket_typep
+if successful.
+This call will fail if the BSM socket type cannot be mapped into a local
+socket type, which may occur if the socket token was generated on another
+operating system.
+.Pp
+.Fn au_socket_type_to_bsm
+function accepts a local socket type, and returns the BSM socket type for it.
+This call cannot fail, and instead returns a BSM socket type indicating to a
+later decoder that the socket type could not be encoded.
+.Sh RETURN VALULES
+On success,
+.Fn au_bsm_to_socket_type
+returns 0 and a converted socket type; on failure, it returns -1 but does not
+set
+.Xr errno 2 .
+.Pp
+On success,
+.Fn au_strerror
+returns a pointer to an error string; on failure it will return
+.Dv NULL .
+.Sh SEE ALSO
+.Xr au_bsm_to_domain 3 ,
+.Xr au_domain_to_bsm 3 ,
+.Xr au_to_socket_ex 3 ,
+.Xr libbsm 3
+.Sh HISTORY
+.Fn au_bsm_to_socket_type
+and
+.Fn au_socket_type_to_bsm
+were introduced in OpenBSM 1.1.
+.Sh AUTHORS
+These functions were implemented by
+.An Robert Watson
+under contract to Apple 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/libbsm/au_token.3 b/contrib/openbsm/libbsm/au_token.3
new file mode 100644
index 0000000..0459242
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_token.3
@@ -0,0 +1,252 @@
+.\"-
+.\" Copyright (c) 2005-2007 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 April 19, 2005
+.Dt AU_TOKEN 3
+.Os
+.Sh NAME
+.Nm au_to_arg32 ,
+.Nm au_to_arg64 ,
+.Nm au_to_arg ,
+.Nm au_to_attr64 ,
+.Nm au_to_data ,
+.Nm au_to_exit ,
+.Nm au_to_groups ,
+.Nm au_to_newgroups ,
+.Nm au_to_in_addr ,
+.Nm au_to_in_addr_ex ,
+.Nm au_to_ip ,
+.Nm au_to_ipc ,
+.Nm au_to_ipc_perm ,
+.Nm au_to_iport ,
+.Nm au_to_opaque ,
+.Nm au_to_file ,
+.Nm au_to_text ,
+.Nm au_to_path ,
+.Nm au_to_process32 ,
+.Nm au_to_process64 ,
+.Nm au_to_process ,
+.Nm au_to_process32_ex ,
+.Nm au_to_process64_ex ,
+.Nm au_to_process_ex ,
+.Nm au_to_return32 ,
+.Nm au_to_return64 ,
+.Nm au_to_return ,
+.Nm au_to_seq ,
+.Nm au_to_sock_inet32 ,
+.Nm au_to_sock_inet128 ,
+.Nm au_to_sock_inet ,
+.Nm au_to_socket_ex ,
+.Nm au_to_subject32 ,
+.Nm au_to_subject64 ,
+.Nm au_to_subject ,
+.Nm au_to_subject32_ex ,
+.Nm au_to_subject64_ex ,
+.Nm au_to_subject_ex ,
+.Nm au_to_me ,
+.Nm au_to_exec_args ,
+.Nm au_to_exec_env ,
+.Nm au_to_header ,
+.Nm au_to_header32 ,
+.Nm au_to_header64 ,
+.Nm au_to_header_ex ,
+.Nm au_to_header32_ex ,
+.Nm au_to_trailer ,
+.Nm au_to_zonename
+.Nd "routines for generating BSM audit tokens"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft "token_t *"
+.Fn au_to_arg32 "char n" "const char *text" "u_int32_t v"
+.Ft "token_t *"
+.Fn au_to_arg64 "char n" "const char *text" "u_int64_t v"
+.Ft "token_t *"
+.Fn au_to_arg "char n" "const char *text" "u_int32_t v"
+.Ft "token_t *"
+.Fn au_to_attr32 "struct vattr *attr"
+.Ft "token_t *"
+.Fn au_to_attr64 "struct vattr *attr"
+.Ft "token_t *"
+.Fn au_to_attr "struct vattr *attr"
+.Ft "token_t *"
+.Fn au_to_data "char unit_print" "char unit_type" "char unit_count" "const char *p"
+.Ft "token_t *"
+.Fn au_to_exit "int retval" "int err"
+.Ft "token_t *"
+.Fn au_to_groups "int *groups"
+.Ft "token_t *"
+.Fn au_to_newgroups "u_int16_t n" "gid_t *groups"
+.Ft "token_t *"
+.Fn au_to_in_addr "struct in_addr *internet_addr"
+.Ft "token_t *"
+.Fn au_to_in_addr_ex "struct in6_addr *internet_addr"
+.Ft "token_t *"
+.Fn au_to_ip "struct ip *ip"
+.Ft "token_t *"
+.Fn au_to_ipc "char type" "int id"
+.Ft "token_t *"
+.Fn au_to_ipc_perm "struct ipc_perm *perm"
+.Ft "token_t *"
+.Fn au_to_iport "u_int16_t iport"
+.Ft "token_t *"
+.Fn au_to_opaque "const char *data" "u_int16_t bytes"
+.Ft "token_t *"
+.Fn au_to_file "const char *file" "struct timeval tm"
+.Ft "token_t *"
+.Fn au_to_text "const char *text"
+.Ft "token_t *"
+.Fn au_to_path "const char *text"
+.Ft "token_t *"
+.Fo au_to_process32
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_process64
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_process32_ex
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_process64_ex
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Fc
+.Ft "token_t *"
+.Fn au_to_return32 "char status" "u_int32_t ret"
+.Ft "token_t *"
+.Fn au_to_return64 "char status" "u_int64_t ret"
+.Ft "token_t *"
+.Fn au_to_return "char status" "u_int32_t ret"
+.Ft "token_t *"
+.Fn au_to_seq "long audit_count"
+.Ft "token_t *"
+.Fn au_to_sock_inet32 "struct sockaddr_in *so"
+.Ft "token_t *"
+.Fn au_to_sock_inet128 "struct sockaddr_in6 *so"
+.Ft "token_t *"
+.Fn au_to_sock_int "struct sockaddr_in *so"
+.Ft "token_t *"
+.Fn au_to_socket_ex "u_short so_domain" "u_short so_type" "struct sockaddr *sa_local" "struct sockaddr *sa_remote"
+.Ft "token_t *"
+.Fo au_to_subject32
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_subject64
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_subject
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_subject32_ex
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_subject64_ex
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Fc
+.Ft "token_t *"
+.Fo au_to_subject_ex
+.Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid"
+.Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Fc
+.Ft "token_t *"
+.Fn au_to_me void
+.Ft "token_t *"
+.Fn au_to_exec_args "char **argv"
+.Ft "token_t *"
+.Fn au_to_exec_env "char **envp"
+.Ft "token_t *"
+.Fn au_to_header "int rec_size" "au_event_t e_type" "au_emod_t emod"
+.Ft "token_t *"
+.Fn au_to_header32 "int rec_size" "au_event_t e_type" "au_emod_t emod"
+.Ft "token_t *"
+.Fn au_to_header64 "int rec_size" "au_event_t e_type" "au_emod_t e_mod"
+.Ft "token_t *"
+.Fn au_to_header_ex "int rec_size" "au_event_t e_type" "au_emod_t e_mod"
+.Ft "token_t *"
+.Fn au_to_header32_ex "int rec_size" "au_event_t e_type" "au_emod_t e_mod"
+.Ft "token_t *"
+.Fn au_to_trailer "int rec_size"
+.Ft "token_t *"
+.Fn au_to_zonename "const char *zonename"
+.Sh DESCRIPTION
+These interfaces support the allocation of BSM audit tokens, represented by
+.Vt token_t ,
+for various data types.
+.Pp
+.Xr au_errno_to_bsm 3
+must be used to convert local
+.Xr errno 2
+errors to BSM error numbers before they are passed to
+.Fn au_to_return ,
+.Fn au_to_return32 ,
+and
+.Fn au_to_return64 .
+.Sh RETURN VALUES
+On success, a pointer to a
+.Vt token_t
+will be returned; the allocated
+.Vt token_t
+can be freed via a call to
+.Xr au_free_token 3 .
+On failure,
+.Dv NULL
+will be returned, and an error condition returned via
+.Va errno .
+.Sh SEE ALSO
+.Xr au_errno_to_bsm 3 ,
+.Xr libbsm 3
+.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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, 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/libbsm/au_user.3 b/contrib/openbsm/libbsm/au_user.3
new file mode 100644
index 0000000..d2a4fa1
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_user.3
@@ -0,0 +1,154 @@
+.\"-
+.\" Copyright (c) 2005-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 April 19, 2005
+.Dt AU_USER 3
+.Os
+.Sh NAME
+.Nm setauuser ,
+.Nm endauuser ,
+.Nm getauuserent ,
+.Nm getauuserent_r ,
+.Nm getauusernam ,
+.Nm getauusernam_r ,
+.Nm au_user_mask ,
+.Nm getfauditflags
+.Nd "look up information from the audit_user database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft void
+.Fn setauuser void
+.Ft void
+.Fn endauuser void
+.Ft "struct au_user_ent *"
+.Fn getauuserent void
+.Ft "struct au_user_ent *"
+.Fn getauuserent_r "struct au_user_ent *u"
+.Ft "struct au_user_ent *"
+.Fn getauusernam "const char *name"
+.Ft "struct au_user_ent *"
+.Fn getauusernam_r "struct au_user_ent *u" "const char *name"
+.Ft int
+.Fn au_user_mask "char *username" "au_mask_t *mask_p"
+.Ft int
+.Fo getfauditflags
+.Fa "au_mask_t *usremask" "au_mask_t *usrdmask" "au_mask_t *lastmask"
+.Fc
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_user 5
+database, which describes per-user audit configuration.
+Audit user entries are described by a
+.Vt au_user_ent ,
+which stores the user's name in
+.Va au_name ,
+events to always audit in
+.Va au_always ,
+and events never to audit
+.Va au_never .
+.Pp
+The
+.Fn getauuserent
+function
+returns the next user found in the
+.Xr audit_user 5
+database, or the first if the function has not yet been called.
+.Dv NULL
+will be returned if no further records are available.
+.Pp
+The
+.Fn getauusernam
+function
+looks up a user by name.
+.Dv NULL
+will be returned if no matching class can be found.
+.Pp
+The
+.Fn setauuser
+function
+resets the iterator through the
+.Xr audit_user 5
+database, causing the next call to
+.Fn getauuserent
+to start again from the beginning of the file.
+.Pp
+The
+.Fn endauuser
+function
+closes the
+.Xr audit_user 5
+database, if open.
+.Pp
+The
+.Fn au_user_mask
+function
+calculates a new session audit mask to be returned via
+.Fa mask_p
+for the user identified by
+.Fa username .
+If the user audit configuration is not found, the default system audit
+properties returned by
+.Xr getacflg 3
+are used.
+The resulting mask may be set via a call to
+.Xr setaudit 2
+or related variants.
+.Pp
+The
+.Fn getfauditflags
+function generates a new process audit state by combining the audit masks
+passed as parameters with the system audit masks.
+.Sh SEE ALSO
+.Xr setaudit 2 ,
+.Xr getacflg 3 ,
+.Xr libbsm 3 ,
+.Xr audit_user 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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
diff --git a/contrib/openbsm/libbsm/audit_submit.3 b/contrib/openbsm/libbsm/audit_submit.3
new file mode 100644
index 0000000..c3be666
--- /dev/null
+++ b/contrib/openbsm/libbsm/audit_submit.3
@@ -0,0 +1,151 @@
+.\"
+.\" Copyright (c) 2006 Christian S.J. Peron
+.\" 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 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 18, 2008
+.Dt AUDIT_SUBMIT 3
+.Os
+.Sh NAME
+.Nm audit_submit
+.Nd "general purpose audit record submission"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Ft int
+.Fo audit_submit
+.Fa "short au_event" "au_id_t auid" "char status"
+.Fa "int reterr" "const char * restrict format" ...
+.Fc
+.Sh DESCRIPTION
+The
+.Fn audit_submit
+function provides a generic programming interface for audit record submission.
+This audit record will contain a header, subject token, an optional text token,
+return token, and a trailer.
+The header will contain the event class specified by
+.Fa au_event .
+The subject token will be generated based on
+.Fa auid .
+The return token is dependent on the
+.Fa status
+and
+.Fa reterr
+arguments; unlike the argument to
+.Xr au_to_return ,
+.Fa reterr
+should be a local rather than BSM error number.
+Optionally, a text token will be created as a part of this record.
+.Pp
+Text token output is under the control of a
+.Fa format
+string that specifies how subsequent arguments (or arguments accessed via the
+variable-length argument facilities of
+.Xr stdarg 3 )
+are converted for output.
+If
+.Fa format
+is
+.Dv NULL ,
+then no text token is created in the audit record.
+.Pp
+It should be noted that
+.Fn audit_submit
+assumes that
+.Xr setaudit 2 ,
+or
+.Xr setaudit_addr 2
+has already been called.
+As a direct result, the terminal ID for the
+subject will be retrieved from the kernel via
+.Xr getaudit 2 ,
+or
+.Xr getaudit_addr 2 .
+.Sh RETURN VALUES
+If successful,
+.Nm
+will return zero.
+Otherwise a -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+#include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+
+void
+audit_bad_su(char *from_login, char *to_login)
+{
+ struct auditinfo_addr aia;
+ struct auditinfo ai;
+ au_id_t aid;
+ int error;
+
+ error = getaudit_addr(&aia, sizeof(aia));
+ if (error < 0 && errno == ENOSYS) {
+ error = getaudit(&ai);
+ if (error < 0)
+ err(1, "getaudit");
+ aid = ai.ai_auid;
+ } else if (error < 0)
+ err(1, "getaudit_addr");
+ else
+ aid = aia.ai_auid;
+ error = audit_submit(AUE_su, aid, EPERM, 1,
+ "bad su from %s to %s", from_login, to_login);
+ if (error != 0)
+ err(1, "audit_submit");
+}
+.Ed
+.Pp
+Will generate the following audit record:
+.Bd -literal -offset indent
+header,94,1,su(1),0,Mon Apr 17 23:23:59 2006, + 271 msec
+subject,root,root,wheel,root,wheel,652,652,0,0.0.0.0
+text,bad su from from csjp to root
+return,failure : Operation not permitted,1
+trailer,94
+.Ed
+.Sh SEE ALSO
+.Xr auditon 2 ,
+.Xr getaudit 2 ,
+.Xr libbsm 3 ,
+.Xr stdarg 3
+.Sh HISTORY
+The
+.Fn audit_submit
+function first appeared in OpenBSM version 1.0.
+OpenBSM 1.0 was introduced in
+.Fx 7.0 .
+.Sh AUTHORS
+The
+.Fn audit_submit
+function was written by
+.An Christian S.J. Peron Aq csjp@FreeBSD.org .
diff --git a/contrib/openbsm/libbsm/bsm_audit.c b/contrib/openbsm/libbsm/bsm_audit.c
new file mode 100644
index 0000000..f7a00c6
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_audit.c
@@ -0,0 +1,449 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * 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>
+#ifdef HAVE_FULL_QUEUE_H
+#include <sys/queue.h>
+#else
+#include <compat/queue.h>
+#endif
+
+#include <bsm/audit_internal.h>
+#include <bsm/libbsm.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+/* array of used descriptors */
+static au_record_t *open_desc_table[MAX_AUDIT_RECORDS];
+
+/* The current number of active record descriptors */
+static int audit_rec_count = 0;
+
+/*
+ * Records that can be recycled are maintained in the list given below. The
+ * maximum number of elements that can be present in this list is bounded by
+ * MAX_AUDIT_RECORDS. Memory allocated for these records are never freed.
+ */
+static LIST_HEAD(, au_record) audit_free_q;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*
+ * This call frees a token_t and its internal data.
+ */
+void
+au_free_token(token_t *tok)
+{
+
+ if (tok != NULL) {
+ if (tok->t_data)
+ free(tok->t_data);
+ free(tok);
+ }
+}
+
+/*
+ * This call reserves memory for the audit record. Memory must be guaranteed
+ * before any auditable event can be generated. The au_record_t structure
+ * maintains a reference to the memory allocated above and also the list of
+ * tokens associated with this record. Descriptors are recyled once the
+ * records are added to the audit trail following au_close().
+ */
+int
+au_open(void)
+{
+ au_record_t *rec = NULL;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+
+ if (audit_rec_count == 0)
+ LIST_INIT(&audit_free_q);
+
+ /*
+ * Find an unused descriptor, remove it from the free list, mark as
+ * used.
+ */
+ if (!LIST_EMPTY(&audit_free_q)) {
+ rec = LIST_FIRST(&audit_free_q);
+ rec->used = 1;
+ LIST_REMOVE(rec, au_rec_q);
+ }
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+
+ if (rec == NULL) {
+ /*
+ * Create a new au_record_t if no descriptors are available.
+ */
+ rec = malloc (sizeof(au_record_t));
+ if (rec == NULL)
+ return (-1);
+
+ rec->data = malloc (MAX_AUDIT_RECORD_SIZE * sizeof(u_char));
+ if (rec->data == NULL) {
+ free(rec);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+
+ if (audit_rec_count == MAX_AUDIT_RECORDS) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ free(rec->data);
+ free(rec);
+
+ /* XXX We need to increase size of MAX_AUDIT_RECORDS */
+ errno = ENOMEM;
+ return (-1);
+ }
+ rec->desc = audit_rec_count;
+ open_desc_table[audit_rec_count] = rec;
+ audit_rec_count++;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+
+ }
+
+ memset(rec->data, 0, MAX_AUDIT_RECORD_SIZE);
+
+ TAILQ_INIT(&rec->token_q);
+ rec->len = 0;
+ rec->used = 1;
+
+ return (rec->desc);
+}
+
+/*
+ * Store the token with the record descriptor.
+ *
+ * Don't permit writing more to the buffer than would let the trailer be
+ * appended later.
+ */
+int
+au_write(int d, token_t *tok)
+{
+ au_record_t *rec;
+
+ if (tok == NULL) {
+ errno = EINVAL;
+ return (-1); /* Invalid Token */
+ }
+
+ /* Write the token to the record descriptor */
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1); /* Invalid descriptor */
+ }
+
+ if (rec->len + tok->len + AUDIT_TRAILER_SIZE > MAX_AUDIT_RECORD_SIZE) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /* Add the token to the tail */
+ /*
+ * XXX Not locking here -- we should not be writing to
+ * XXX the same descriptor from different threads
+ */
+ TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens);
+
+ rec->len += tok->len; /* grow record length by token size bytes */
+
+ /* Token should not be available after this call */
+ tok = NULL;
+ return (0); /* Success */
+}
+
+/*
+ * Assemble an audit record out of its tokens, including allocating header and
+ * trailer tokens. Does not free the token chain, which must be done by the
+ * caller if desirable.
+ *
+ * XXX: Assumes there is sufficient space for the header and trailer.
+ */
+static int
+au_assemble(au_record_t *rec, short event)
+{
+#ifdef HAVE_AUDIT_SYSCALLS
+ struct in6_addr *aptr;
+ struct auditinfo_addr aia;
+ struct timeval tm;
+ size_t hdrsize;
+#endif /* HAVE_AUDIT_SYSCALLS */
+ token_t *header, *tok, *trailer;
+ size_t tot_rec_size;
+ u_char *dptr;
+ int error;
+
+#ifdef HAVE_AUDIT_SYSCALLS
+ /*
+ * Grab the size of the address family stored in the kernel's audit
+ * state.
+ */
+ aia.ai_termid.at_type = AU_IPv4;
+ aia.ai_termid.at_addr[0] = INADDR_ANY;
+ if (audit_get_kaudit(&aia, sizeof(aia)) != 0) {
+ if (errno != ENOSYS && errno != EPERM)
+ return (-1);
+#endif /* HAVE_AUDIT_SYSCALLS */
+ tot_rec_size = rec->len + AUDIT_HEADER_SIZE +
+ AUDIT_TRAILER_SIZE;
+ header = au_to_header(tot_rec_size, event, 0);
+#ifdef HAVE_AUDIT_SYSCALLS
+ } else {
+ if (gettimeofday(&tm, NULL) < 0)
+ return (-1);
+ switch (aia.ai_termid.at_type) {
+ case AU_IPv4:
+ hdrsize = (aia.ai_termid.at_addr[0] == INADDR_ANY) ?
+ AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia);
+ break;
+ case AU_IPv6:
+ aptr = (struct in6_addr *)&aia.ai_termid.at_addr[0];
+ hdrsize =
+ (IN6_IS_ADDR_UNSPECIFIED(aptr)) ?
+ AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia);
+ break;
+ default:
+ return (-1);
+ }
+ tot_rec_size = rec->len + hdrsize + AUDIT_TRAILER_SIZE;
+ /*
+ * A header size greater then AUDIT_HEADER_SIZE means
+ * that we are using an extended header.
+ */
+ if (hdrsize > AUDIT_HEADER_SIZE)
+ header = au_to_header32_ex_tm(tot_rec_size, event,
+ 0, tm, &aia);
+ else
+ header = au_to_header(tot_rec_size, event, 0);
+ }
+#endif /* HAVE_AUDIT_SYSCALLS */
+ if (header == NULL)
+ return (-1);
+
+ trailer = au_to_trailer(tot_rec_size);
+ if (trailer == NULL) {
+ error = errno;
+ au_free_token(header);
+ errno = error;
+ return (-1);
+ }
+
+ TAILQ_INSERT_HEAD(&rec->token_q, header, tokens);
+ TAILQ_INSERT_TAIL(&rec->token_q, trailer, tokens);
+
+ rec->len = tot_rec_size;
+ dptr = rec->data;
+
+ TAILQ_FOREACH(tok, &rec->token_q, tokens) {
+ memcpy(dptr, tok->t_data, tok->len);
+ dptr += tok->len;
+ }
+
+ return (0);
+}
+
+/*
+ * Given a record that is no longer of interest, tear it down and convert to a
+ * free record.
+ */
+static void
+au_teardown(au_record_t *rec)
+{
+ token_t *tok;
+
+ /* Free the token list */
+ while ((tok = TAILQ_FIRST(&rec->token_q)) != NULL) {
+ TAILQ_REMOVE(&rec->token_q, tok, tokens);
+ free(tok->t_data);
+ free(tok);
+ }
+
+ rec->used = 0;
+ rec->len = 0;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+
+ /* Add the record to the freelist tail */
+ LIST_INSERT_HEAD(&audit_free_q, rec, au_rec_q);
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+#ifdef HAVE_AUDIT_SYSCALLS
+/*
+ * Add the header token, identify any missing tokens. Write out the tokens to
+ * the record memory and finally, call audit.
+ */
+int
+au_close(int d, int keep, short event)
+{
+ au_record_t *rec;
+ size_t tot_rec_size;
+ int retval = 0;
+
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1); /* Invalid descriptor */
+ }
+
+ if (keep == AU_TO_NO_WRITE) {
+ retval = 0;
+ goto cleanup;
+ }
+
+ tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE;
+
+ if (tot_rec_size > MAX_AUDIT_RECORD_SIZE) {
+ /*
+ * XXXRW: Since au_write() is supposed to prevent this, spew
+ * an error here.
+ */
+ fprintf(stderr, "au_close failed");
+ errno = ENOMEM;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (au_assemble(rec, event) < 0) {
+ /*
+ * XXXRW: This is also not supposed to happen, but might if we
+ * are unable to allocate header and trailer memory.
+ */
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Call the kernel interface to audit */
+ retval = audit(rec->data, rec->len);
+
+cleanup:
+ /* CLEANUP */
+ au_teardown(rec);
+ return (retval);
+}
+#endif /* HAVE_AUDIT_SYSCALLS */
+
+/*
+ * au_close(), except onto an in-memory buffer. Buffer size as an argument,
+ * record size returned via same argument on success.
+ */
+int
+au_close_buffer(int d, short event, u_char *buffer, size_t *buflen)
+{
+ size_t tot_rec_size;
+ au_record_t *rec;
+ int retval;
+
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ retval = 0;
+ tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE;
+ if ((tot_rec_size > MAX_AUDIT_RECORD_SIZE) ||
+ (tot_rec_size > *buflen)) {
+ /*
+ * XXXRW: See au_close() comment.
+ */
+ fprintf(stderr, "au_close_buffer failed %zd", tot_rec_size);
+ errno = ENOMEM;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (au_assemble(rec, event) < 0) {
+ /* XXXRW: See au_close() comment. */
+ retval = -1;
+ goto cleanup;
+ }
+
+ memcpy(buffer, rec->data, rec->len);
+ *buflen = rec->len;
+
+cleanup:
+ au_teardown(rec);
+ return (retval);
+}
+
+/*
+ * au_close_token() returns the byte format of a token_t. This won't
+ * generally be used by applications, but is quite useful for writing test
+ * tools. Will free the token on either success or failure.
+ */
+int
+au_close_token(token_t *tok, u_char *buffer, size_t *buflen)
+{
+
+ if (tok->len > *buflen) {
+ au_free_token(tok);
+ errno = ENOMEM;
+ return (EINVAL);
+ }
+
+ memcpy(buffer, tok->t_data, tok->len);
+ *buflen = tok->len;
+ au_free_token(tok);
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_class.c b/contrib/openbsm/libbsm/bsm_class.c
new file mode 100644
index 0000000..8ee193f
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_class.c
@@ -0,0 +1,300 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * 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.
+ * 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 <config/config.h>
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+/*
+ * Parse the contents of the audit_class file to return struct au_class_ent
+ * entries.
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *classdelim = ":";
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*
+ * Parse a single line from the audit_class file passed in str to the struct
+ * au_class_ent elements; store the result in c.
+ */
+static struct au_class_ent *
+classfromstr(char *str, struct au_class_ent *c)
+{
+ char *classname, *classdesc, *classflag;
+ char *last;
+
+ /* Each line contains flag:name:desc. */
+ classflag = strtok_r(str, classdelim, &last);
+ classname = strtok_r(NULL, classdelim, &last);
+ classdesc = strtok_r(NULL, classdelim, &last);
+
+ if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL))
+ return (NULL);
+
+ /*
+ * Check for very large classnames.
+ */
+ if (strlen(classname) >= AU_CLASS_NAME_MAX)
+ return (NULL);
+ strlcpy(c->ac_name, classname, AU_CLASS_NAME_MAX);
+
+ /*
+ * Check for very large class description.
+ */
+ if (strlen(classdesc) >= AU_CLASS_DESC_MAX)
+ return (NULL);
+ strlcpy(c->ac_desc, classdesc, AU_CLASS_DESC_MAX);
+ c->ac_class = strtoul(classflag, (char **) NULL, 0);
+
+ return (c);
+}
+
+/*
+ * Return the next au_class_ent structure from the file setauclass should be
+ * called before invoking this function for the first time.
+ *
+ * Must be called with mutex held.
+ */
+static struct au_class_ent *
+getauclassent_r_locked(struct au_class_ent *c)
+{
+ char *tokptr, *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL))
+ return (NULL);
+
+ /*
+ * Read until next non-comment line is found, or EOF.
+ */
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Remove trailing new line character. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Parse tokptr to au_class_ent components. */
+ tokptr = linestr;
+ if (classfromstr(tokptr, c) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (c);
+}
+
+struct au_class_ent *
+getauclassent_r(struct au_class_ent *c)
+{
+ struct au_class_ent *cp;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ cp = getauclassent_r_locked(c);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (cp);
+}
+
+struct au_class_ent *
+getauclassent(void)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c, *cp;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ cp = getauclassent_r_locked(&c);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (cp);
+}
+
+/*
+ * Rewind to the beginning of the enumeration.
+ *
+ * Must be called with mutex held.
+ */
+static void
+setauclass_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauclass(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setauclass_locked();
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Return the next au_class_entry having the given class name.
+ */
+struct au_class_ent *
+getauclassnam_r(struct au_class_ent *c, const char *name)
+{
+ struct au_class_ent *cp;
+
+ if (name == NULL)
+ return (NULL);
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setauclass_locked();
+ while ((cp = getauclassent_r_locked(c)) != NULL) {
+ if (strcmp(name, cp->ac_name) == 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (cp);
+ }
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (NULL);
+}
+
+struct au_class_ent *
+getauclassnam(const char *name)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ return (getauclassnam_r(&c, name));
+}
+
+
+/*
+ * Return the next au_class_entry having the given class number.
+ *
+ * OpenBSM extension.
+ */
+struct au_class_ent *
+getauclassnum_r(struct au_class_ent *c, au_class_t class_number)
+{
+ struct au_class_ent *cp;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setauclass_locked();
+ while ((cp = getauclassent_r_locked(c)) != NULL) {
+ if (class_number == cp->ac_class)
+ return (cp);
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (NULL);
+}
+
+struct au_class_ent *
+getauclassnum(au_class_t class_number)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ return (getauclassnum_r(&c, class_number));
+}
+
+/*
+ * audit_class processing is complete; close any open files.
+ */
+void
+endauclass(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
diff --git a/contrib/openbsm/libbsm/bsm_control.c b/contrib/openbsm/libbsm/bsm_control.c
new file mode 100644
index 0000000..94d9420
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_control.c
@@ -0,0 +1,708 @@
+/*-
+ * Copyright (c) 2004, 2009 Apple Inc.
+ * 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.
+ * 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 <config/config.h>
+
+#include <bsm/libbsm.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_STRLCAT
+#include <compat/strlcat.h>
+#endif
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include <sys/stat.h>
+
+/*
+ * Parse the contents of the audit_control file to return the audit control
+ * parameters. These static fields are protected by 'mutex'.
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static char *delim = ":";
+
+static char inacdir = 0;
+static char ptrmoved = 0;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*
+ * Audit policy string token table for au_poltostr() and au_strtopol().
+ */
+struct audit_polstr {
+ long ap_policy;
+ const char *ap_str;
+};
+
+static struct audit_polstr au_polstr[] = {
+ { AUDIT_CNT, "cnt" },
+ { AUDIT_AHLT, "ahlt" },
+ { AUDIT_ARGV, "argv" },
+ { AUDIT_ARGE, "arge" },
+ { AUDIT_SEQ, "seq" },
+ { AUDIT_WINDATA, "windata" },
+ { AUDIT_USER, "user" },
+ { AUDIT_GROUP, "group" },
+ { AUDIT_TRAIL, "trail" },
+ { AUDIT_PATH, "path" },
+ { AUDIT_SCNT, "scnt" },
+ { AUDIT_PUBLIC, "public" },
+ { AUDIT_ZONENAME, "zonename" },
+ { AUDIT_PERZONE, "perzone" },
+ { -1, NULL }
+};
+
+/*
+ * Returns the string value corresponding to the given label from the
+ * configuration file.
+ *
+ * Must be called with mutex held.
+ */
+static int
+getstrfromtype_locked(const char *name, char **str)
+{
+ char *type, *nl;
+ char *tokptr;
+ char *last;
+
+ *str = NULL;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
+ return (-1); /* Error */
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
+ if (ferror(fp))
+ return (-1);
+ return (0); /* EOF */
+ }
+
+ if (linestr[0] == '#')
+ continue;
+
+ /* Remove trailing new line character and white space. */
+ nl = strchr(linestr, '\0') - 1;
+ while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
+ '\t' == *nl)) {
+ *nl = '\0';
+ nl--;
+ }
+
+ tokptr = linestr;
+ if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
+ if (strcmp(name, type) == 0) {
+ /* Found matching name. */
+ *str = strtok_r(NULL, delim, &last);
+ if (*str == NULL) {
+ errno = EINVAL;
+ return (-1); /* Parse error in file */
+ }
+ return (0); /* Success */
+ }
+ }
+ }
+}
+
+/*
+ * Convert a given time value with a multiplier (seconds, hours, days, years) to
+ * seconds. Return 0 on success.
+ */
+static int
+au_timetosec(time_t *seconds, u_long value, char mult)
+{
+ if (NULL == seconds)
+ return (-1);
+
+ switch(mult) {
+ case 's':
+ /* seconds */
+ *seconds = (time_t)value;
+ break;
+
+ case 'h':
+ /* hours */
+ *seconds = (time_t)value * 60 * 60;
+ break;
+
+ case 'd':
+ /* days */
+ *seconds = (time_t)value * 60 * 60 * 24;
+ break;
+
+ case 'y':
+ /* years. Add a day for each 4th (leap) year. */
+ *seconds = (time_t)value * 60 * 60 * 24 * 364 +
+ ((time_t)value / 4) * 60 * 60 * 24;
+ break;
+
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Convert a given disk space value with a multiplier (bytes, kilobytes,
+ * megabytes, gigabytes) to bytes. Return 0 on success.
+ */
+static int
+au_spacetobytes(size_t *bytes, u_long value, char mult)
+{
+ if (NULL == bytes)
+ return (-1);
+
+ switch(mult) {
+ case 'B':
+ case ' ':
+ /* Bytes */
+ *bytes = (size_t)value;
+ break;
+
+ case 'K':
+ /* Kilobytes */
+ *bytes = (size_t)value * 1024;
+ break;
+
+ case 'M':
+ /* Megabytes */
+ *bytes = (size_t)value * 1024 * 1024;
+ break;
+
+ case 'G':
+ /* Gigabytes */
+ *bytes = (size_t)value * 1024 * 1024 * 1024;
+ break;
+
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Convert a policy to a string. Return -1 on failure, or >= 0 representing
+ * the actual size of the string placed in the buffer (excluding terminating
+ * nul).
+ */
+ssize_t
+au_poltostr(int policy, size_t maxsize, char *buf)
+{
+ int first = 1;
+ int i = 0;
+
+ if (maxsize < 1)
+ return (-1);
+ buf[0] = '\0';
+
+ do {
+ if (policy & au_polstr[i].ap_policy) {
+ if (!first && strlcat(buf, ",", maxsize) >= maxsize)
+ return (-1);
+ if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
+ maxsize)
+ return (-1);
+ first = 0;
+ }
+ } while (NULL != au_polstr[++i].ap_str);
+
+ return (strlen(buf));
+}
+
+/*
+ * Convert a string to a policy. Return -1 on failure (with errno EINVAL,
+ * ENOMEM) or 0 on success.
+ */
+int
+au_strtopol(const char *polstr, int *policy)
+{
+ char *bufp, *string;
+ char *buffer;
+ int i, matched;
+
+ *policy = 0;
+ buffer = strdup(polstr);
+ if (buffer == NULL)
+ return (-1);
+
+ bufp = buffer;
+ while ((string = strsep(&bufp, ",")) != NULL) {
+ matched = i = 0;
+
+ do {
+ if (strcmp(string, au_polstr[i].ap_str) == 0) {
+ *policy |= au_polstr[i].ap_policy;
+ matched = 1;
+ break;
+ }
+ } while (NULL != au_polstr[++i].ap_str);
+
+ if (!matched) {
+ free(buffer);
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ free(buffer);
+ return (0);
+}
+
+/*
+ * Rewind the file pointer to beginning.
+ */
+static void
+setac_locked(void)
+{
+ static time_t lastctime = 0;
+ struct stat sbuf;
+
+ ptrmoved = 1;
+ if (fp != NULL) {
+ /*
+ * Check to see if the file on disk has changed. If so,
+ * force a re-read of the file by closing it.
+ */
+ if (fstat(fileno(fp), &sbuf) < 0)
+ goto closefp;
+ if (lastctime != sbuf.st_ctime) {
+ lastctime = sbuf.st_ctime;
+closefp:
+ fclose(fp);
+ fp = NULL;
+ return;
+ }
+
+ fseek(fp, 0, SEEK_SET);
+ }
+}
+
+void
+setac(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Close the audit_control file.
+ */
+void
+endac(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ ptrmoved = 1;
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Return audit directory information from the audit control file.
+ */
+int
+getacdir(char *name, int len)
+{
+ char *dir;
+ int ret = 0;
+
+ /*
+ * Check if another function was called between successive calls to
+ * getacdir.
+ */
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ if (inacdir && ptrmoved) {
+ ptrmoved = 0;
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+ ret = 2;
+ }
+ if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (dir == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ if (strlen(dir) >= (size_t)len) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-3);
+ }
+ strlcpy(name, dir, len);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (ret);
+}
+
+/*
+ * Return 1 if dist value is set to 'yes' or 'on'.
+ * Return 0 if dist value is set to something else.
+ * Return negative value on error.
+ */
+int
+getacdist(void)
+{
+ char *str;
+ int ret;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+ if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (str == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (0);
+ }
+ if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
+ ret = 1;
+ else
+ ret = 0;
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (ret);
+}
+
+/*
+ * Return the minimum free diskspace value from the audit control file.
+ */
+int
+getacmin(int *min_val)
+{
+ char *min;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+ if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (min == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ *min_val = atoi(min);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (0);
+}
+
+/*
+ * Return the desired trail rotation size from the audit control file.
+ */
+int
+getacfilesz(size_t *filesz_val)
+{
+ char *str;
+ size_t val;
+ char mult;
+ int nparsed;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+ if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (str == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Trim off any leading white space. */
+ while (*str == ' ' || *str == '\t')
+ str++;
+
+ nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
+
+ switch (nparsed) {
+ case 1:
+ /* If no multiplier then assume 'B' (bytes). */
+ mult = 'B';
+ /* fall through */
+ case 2:
+ if (au_spacetobytes(filesz_val, val, mult) == 0)
+ break;
+ /* fall through */
+ default:
+ errno = EINVAL;
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+
+ /*
+ * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0
+ * indicates no rotation size.
+ */
+ if (*filesz_val < 0 || (*filesz_val > 0 &&
+ *filesz_val < MIN_AUDIT_FILE_SIZE)) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ filesz_val = 0L;
+ errno = EINVAL;
+ return (-1);
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (0);
+}
+
+static int
+getaccommon(const char *name, char *auditstr, int len)
+{
+ char *str;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+ if (getstrfromtype_locked(name, &str) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (str == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ if (strlen(str) >= (size_t)len) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-3);
+ }
+ strlcpy(auditstr, str, len);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (0);
+}
+
+/*
+ * Return the system audit value from the audit contol file.
+ */
+int
+getacflg(char *auditstr, int len)
+{
+
+ return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
+}
+
+/*
+ * Return the non attributable flags from the audit contol file.
+ */
+int
+getacna(char *auditstr, int len)
+{
+
+ return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
+}
+
+/*
+ * Return the policy field from the audit control file.
+ */
+int
+getacpol(char *auditstr, size_t len)
+{
+
+ return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
+}
+
+int
+getachost(char *auditstr, size_t len)
+{
+
+ return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
+}
+
+/*
+ * Set expiration conditions.
+ */
+static int
+setexpirecond(time_t *age, size_t *size, u_long value, char mult)
+{
+
+ if (isupper(mult) || ' ' == mult)
+ return (au_spacetobytes(size, value, mult));
+ else
+ return (au_timetosec(age, value, mult));
+}
+
+/*
+ * Return the expire-after field from the audit control file.
+ */
+int
+getacexpire(int *andflg, time_t *age, size_t *size)
+{
+ char *str;
+ int nparsed;
+ u_long val1, val2;
+ char mult1, mult2;
+ char andor[AU_LINE_MAX];
+
+ *age = 0L;
+ *size = 0LL;
+ *andflg = 0;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setac_locked();
+ if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-2);
+ }
+ if (str == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+
+ /* First, trim off any leading white space. */
+ while (*str == ' ' || *str == '\t')
+ str++;
+
+ nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
+ andor, &val2, &mult2);
+
+ switch (nparsed) {
+ case 1:
+ /* If no multiplier then assume 'B' (Bytes). */
+ mult1 = 'B';
+ /* fall through */
+ case 2:
+ /* One expiration condition. */
+ if (setexpirecond(age, size, val1, mult1) != 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ break;
+
+ case 5:
+ /* Two expiration conditions. */
+ if (setexpirecond(age, size, val1, mult1) != 0 ||
+ setexpirecond(age, size, val2, mult2) != 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ if (strcasestr(andor, "and") != NULL)
+ *andflg = 1;
+ else if (strcasestr(andor, "or") != NULL)
+ *andflg = 0;
+ else {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ break;
+
+ default:
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_domain.c b/contrib/openbsm/libbsm/bsm_domain.c
new file mode 100644
index 0000000..f6aeef6
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_domain.c
@@ -0,0 +1,490 @@
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <config/config.h>
+
+#include <bsm/audit_domain.h>
+#include <bsm/libbsm.h>
+
+struct bsm_domain {
+ u_short bd_bsm_domain;
+ int bd_local_domain;
+};
+
+#define PF_NO_LOCAL_MAPPING -600
+
+static const struct bsm_domain bsm_domains[] = {
+ { BSM_PF_UNSPEC, PF_UNSPEC },
+ { BSM_PF_LOCAL, PF_LOCAL },
+ { BSM_PF_INET, PF_INET },
+ { BSM_PF_IMPLINK,
+#ifdef PF_IMPLINK
+ PF_IMPLINK
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_PUP,
+#ifdef PF_PUP
+ PF_PUP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_CHAOS,
+#ifdef PF_CHAOS
+ PF_CHAOS
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NS,
+#ifdef PF_NS
+ PF_NS
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NBS,
+#ifdef PF_NBS
+ PF_NBS
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ECMA,
+#ifdef PF_ECMA
+ PF_ECMA
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_DATAKIT,
+#ifdef PF_DATAKIT
+ PF_DATAKIT
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_CCITT,
+#ifdef PF_CCITT
+ PF_CCITT
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_SNA, PF_SNA },
+ { BSM_PF_DECnet, PF_DECnet },
+ { BSM_PF_DLI,
+#ifdef PF_DLI
+ PF_DLI
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_LAT,
+#ifdef PF_LAT
+ PF_LAT
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_HYLINK,
+#ifdef PF_HYLINK
+ PF_HYLINK
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_APPLETALK, PF_APPLETALK },
+ { BSM_PF_NIT,
+#ifdef PF_NIT
+ PF_NIT
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_802,
+#ifdef PF_802
+ PF_802
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_OSI,
+#ifdef PF_OSI
+ PF_OSI
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_X25,
+#ifdef PF_X25
+ PF_X25
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_OSINET,
+#ifdef PF_OSINET
+ PF_OSINET
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_GOSIP,
+#ifdef PF_GOSIP
+ PF_GOSIP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_IPX, PF_IPX },
+ { BSM_PF_ROUTE, PF_ROUTE },
+ { BSM_PF_LINK,
+#ifdef PF_LINK
+ PF_LINK
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_INET6, PF_INET6 },
+ { BSM_PF_KEY, PF_KEY },
+ { BSM_PF_NCA,
+#ifdef PF_NCA
+ PF_NCA
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_POLICY,
+#ifdef PF_POLICY
+ PF_POLICY
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_INET_OFFLOAD,
+#ifdef PF_INET_OFFLOAD
+ PF_INET_OFFLOAD
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NETBIOS,
+#ifdef PF_NETBIOS
+ PF_NETBIOS
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ISO,
+#ifdef PF_ISO
+ PF_ISO
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_XTP,
+#ifdef PF_XTP
+ PF_XTP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_COIP,
+#ifdef PF_COIP
+ PF_COIP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_CNT,
+#ifdef PF_CNT
+ PF_CNT
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_RTIP,
+#ifdef PF_RTIP
+ PF_RTIP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_SIP,
+#ifdef PF_SIP
+ PF_SIP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_PIP,
+#ifdef PF_PIP
+ PF_PIP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ISDN,
+#ifdef PF_ISDN
+ PF_ISDN
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_E164,
+#ifdef PF_E164
+ PF_E164
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NATM,
+#ifdef PF_NATM
+ PF_NATM
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ATM,
+#ifdef PF_ATM
+ PF_ATM
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NETGRAPH,
+#ifdef PF_NETGRAPH
+ PF_NETGRAPH
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_SLOW,
+#ifdef PF_SLOW
+ PF_SLOW
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_SCLUSTER,
+#ifdef PF_SCLUSTER
+ PF_SCLUSTER
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ARP,
+#ifdef PF_ARP
+ PF_ARP
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_BLUETOOTH,
+#ifdef PF_BLUETOOTH
+ PF_BLUETOOTH
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_AX25,
+#ifdef PF_AX25
+ PF_AX25
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ROSE,
+#ifdef PF_ROSE
+ PF_ROSE
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_NETBEUI,
+#ifdef PF_NETBEUI
+ PF_NETBEUI
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_SECURITY,
+#ifdef PF_SECURITY
+ PF_SECURITY
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_PACKET,
+#ifdef PF_PACKET
+ PF_PACKET
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ASH,
+#ifdef PF_ASH
+ PF_ASH
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ECONET,
+#ifdef PF_ECONET
+ PF_ECONET
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_ATMSVC,
+#ifdef PF_ATMSVC
+ PF_ATMSVC
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_IRDA,
+#ifdef PF_IRDA
+ PF_IRDA
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_PPPOX,
+#ifdef PF_PPPOX
+ PF_PPPOX
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_WANPIPE,
+#ifdef PF_WANPIPE
+ PF_WANPIPE
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_LLC,
+#ifdef PF_LLC
+ PF_LLC
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_CAN,
+#ifdef PF_CAN
+ PF_CAN
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_TIPC,
+#ifdef PF_TIPC
+ PF_TIPC
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_IUCV,
+#ifdef PF_IUCV
+ PF_IUCV
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_RXRPC,
+#ifdef PF_RXRPC
+ PF_RXRPC
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+ { BSM_PF_PHONET,
+#ifdef PF_PHONET
+ PF_PHONET
+#else
+ PF_NO_LOCAL_MAPPING
+#endif
+ },
+};
+static const int bsm_domains_count = sizeof(bsm_domains) /
+ sizeof(bsm_domains[0]);
+
+static const struct bsm_domain *
+bsm_lookup_local_domain(int local_domain)
+{
+ int i;
+
+ for (i = 0; i < bsm_domains_count; i++) {
+ if (bsm_domains[i].bd_local_domain == local_domain)
+ return (&bsm_domains[i]);
+ }
+ return (NULL);
+}
+
+u_short
+au_domain_to_bsm(int local_domain)
+{
+ const struct bsm_domain *bstp;
+
+ bstp = bsm_lookup_local_domain(local_domain);
+ if (bstp == NULL)
+ return (BSM_PF_UNKNOWN);
+ return (bstp->bd_bsm_domain);
+}
+
+static const struct bsm_domain *
+bsm_lookup_bsm_domain(u_short bsm_domain)
+{
+ int i;
+
+ for (i = 0; i < bsm_domains_count; i++) {
+ if (bsm_domains[i].bd_bsm_domain == bsm_domain)
+ return (&bsm_domains[i]);
+ }
+ return (NULL);
+}
+
+int
+au_bsm_to_domain(u_short bsm_domain, int *local_domainp)
+{
+ const struct bsm_domain *bstp;
+
+ bstp = bsm_lookup_bsm_domain(bsm_domain);
+ if (bstp == NULL || bstp->bd_local_domain)
+ return (-1);
+ *local_domainp = bstp->bd_local_domain;
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_errno.c b/contrib/openbsm/libbsm/bsm_errno.c
new file mode 100644
index 0000000..b4b22f3
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_errno.c
@@ -0,0 +1,771 @@
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+
+#include <config/config.h>
+
+#include <bsm/audit_errno.h>
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <string.h>
+
+/*
+ * Different operating systems use different numeric constants for different
+ * error numbers, and sometimes error numbers don't exist in more than one
+ * operating system. These routines convert between BSM and local error
+ * number spaces, subject to the above realities. BSM error numbers are
+ * stored in a single 8-bit character, so don't have a byte order.
+ *
+ * Don't include string definitions when this code is compiled into a kernel.
+ */
+struct bsm_errno {
+ int be_bsm_errno;
+ int be_local_errno;
+#if !defined(KERNEL) && !defined(_KERNEL)
+ const char *be_strerror;
+#endif
+};
+
+#define ERRNO_NO_LOCAL_MAPPING -600
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+#define ES(x) x
+#else
+#define ES(x)
+#endif
+
+/*
+ * Mapping table -- please maintain in numeric sorted order with respect to
+ * the BSM constant. Today we do a linear lookup, but could switch to a
+ * binary search if it makes sense. We only ifdef errors that aren't
+ * generally available, but it does make the table a lot more ugly.
+ *
+ * XXXRW: It would be nice to have a similar ordered table mapping to BSM
+ * constant from local constant, but the order of local constants varies by
+ * OS. Really we need to build that table at compile-time but don't do that
+ * yet.
+ *
+ * XXXRW: We currently embed English-language error strings here, but should
+ * support catalogues; these are only used if the OS doesn't have an error
+ * string using strerror(3).
+ */
+static const struct bsm_errno bsm_errnos[] = {
+ { BSM_ERRNO_ESUCCESS, 0, ES("Success") },
+ { BSM_ERRNO_EPERM, EPERM, ES("Operation not permitted") },
+ { BSM_ERRNO_ENOENT, ENOENT, ES("No such file or directory") },
+ { BSM_ERRNO_ESRCH, ESRCH, ES("No such process") },
+ { BSM_ERRNO_EINTR, EINTR, ES("Interrupted system call") },
+ { BSM_ERRNO_EIO, EIO, ES("Input/output error") },
+ { BSM_ERRNO_ENXIO, ENXIO, ES("Device not configured") },
+ { BSM_ERRNO_E2BIG, E2BIG, ES("Argument list too long") },
+ { BSM_ERRNO_ENOEXEC, ENOEXEC, ES("Exec format error") },
+ { BSM_ERRNO_EBADF, EBADF, ES("Bad file descriptor") },
+ { BSM_ERRNO_ECHILD, ECHILD, ES("No child processes") },
+ { BSM_ERRNO_EAGAIN, EAGAIN, ES("Resource temporarily unavailable") },
+ { BSM_ERRNO_ENOMEM, ENOMEM, ES("Cannot allocate memory") },
+ { BSM_ERRNO_EACCES, EACCES, ES("Permission denied") },
+ { BSM_ERRNO_EFAULT, EFAULT, ES("Bad address") },
+ { BSM_ERRNO_ENOTBLK, ENOTBLK, ES("Block device required") },
+ { BSM_ERRNO_EBUSY, EBUSY, ES("Device busy") },
+ { BSM_ERRNO_EEXIST, EEXIST, ES("File exists") },
+ { BSM_ERRNO_EXDEV, EXDEV, ES("Cross-device link") },
+ { BSM_ERRNO_ENODEV, ENODEV, ES("Operation not supported by device") },
+ { BSM_ERRNO_ENOTDIR, ENOTDIR, ES("Not a directory") },
+ { BSM_ERRNO_EISDIR, EISDIR, ES("Is a directory") },
+ { BSM_ERRNO_EINVAL, EINVAL, ES("Invalid argument") },
+ { BSM_ERRNO_ENFILE, ENFILE, ES("Too many open files in system") },
+ { BSM_ERRNO_EMFILE, EMFILE, ES("Too many open files") },
+ { BSM_ERRNO_ENOTTY, ENOTTY, ES("Inappropriate ioctl for device") },
+ { BSM_ERRNO_ETXTBSY, ETXTBSY, ES("Text file busy") },
+ { BSM_ERRNO_EFBIG, EFBIG, ES("File too large") },
+ { BSM_ERRNO_ENOSPC, ENOSPC, ES("No space left on device") },
+ { BSM_ERRNO_ESPIPE, ESPIPE, ES("Illegal seek") },
+ { BSM_ERRNO_EROFS, EROFS, ES("Read-only file system") },
+ { BSM_ERRNO_EMLINK, EMLINK, ES("Too many links") },
+ { BSM_ERRNO_EPIPE, EPIPE, ES("Broken pipe") },
+ { BSM_ERRNO_EDOM, EDOM, ES("Numerical argument out of domain") },
+ { BSM_ERRNO_ERANGE, ERANGE, ES("Result too large") },
+ { BSM_ERRNO_ENOMSG, ENOMSG, ES("No message of desired type") },
+ { BSM_ERRNO_EIDRM, EIDRM, ES("Identifier removed") },
+ { BSM_ERRNO_ECHRNG,
+#ifdef ECHRNG
+ ECHRNG,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Channel number out of range") },
+ { BSM_ERRNO_EL2NSYNC,
+#ifdef EL2NSYNC
+ EL2NSYNC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Level 2 not synchronized") },
+ { BSM_ERRNO_EL3HLT,
+#ifdef EL3HLT
+ EL3HLT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Level 3 halted") },
+ { BSM_ERRNO_EL3RST,
+#ifdef EL3RST
+ EL3RST,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Level 3 reset") },
+ { BSM_ERRNO_ELNRNG,
+#ifdef ELNRNG
+ ELNRNG,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Link number out of range") },
+ { BSM_ERRNO_EUNATCH,
+#ifdef EUNATCH
+ EUNATCH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Protocol driver not attached") },
+ { BSM_ERRNO_ENOCSI,
+#ifdef ENOCSI
+ ENOCSI,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("No CSI structure available") },
+ { BSM_ERRNO_EL2HLT,
+#ifdef EL2HLT
+ EL2HLT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Level 2 halted") },
+ { BSM_ERRNO_EDEADLK, EDEADLK, ES("Resource deadlock avoided") },
+ { BSM_ERRNO_ENOLCK, ENOLCK, ES("No locks available") },
+ { BSM_ERRNO_ECANCELED, ECANCELED, ES("Operation canceled") },
+ { BSM_ERRNO_ENOTSUP, ENOTSUP, ES("Operation not supported") },
+ { BSM_ERRNO_EDQUOT, EDQUOT, ES("Disc quota exceeded") },
+ { BSM_ERRNO_EBADE,
+#ifdef EBADE
+ EBADE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Invalid exchange") },
+ { BSM_ERRNO_EBADR,
+#ifdef EBADR
+ EBADR,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Invalid request descriptor") },
+ { BSM_ERRNO_EXFULL,
+#ifdef EXFULL
+ EXFULL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Exchange full") },
+ { BSM_ERRNO_ENOANO,
+#ifdef ENOANO
+ ENOANO,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("No anode") },
+ { BSM_ERRNO_EBADRQC,
+#ifdef EBADRQC
+ EBADRQC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Invalid request descriptor") },
+ { BSM_ERRNO_EBADSLT,
+#ifdef EBADSLT
+ EBADSLT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Invalid slot") },
+ { BSM_ERRNO_EDEADLOCK,
+#ifdef EDEADLOCK
+ EDEADLOCK,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Resource deadlock avoided") },
+ { BSM_ERRNO_EBFONT,
+#ifdef EBFONT
+ EBFONT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Bad font file format") },
+ { BSM_ERRNO_EOWNERDEAD,
+#ifdef EOWNERDEAD
+ EOWNERDEAD,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Process died with the lock") },
+ { BSM_ERRNO_ENOTRECOVERABLE,
+#ifdef ENOTRECOVERABLE
+ ENOTRECOVERABLE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Lock is not recoverable") },
+ { BSM_ERRNO_ENOSTR,
+#ifdef ENOSTR
+ ENOSTR,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Device not a stream") },
+ { BSM_ERRNO_ENONET,
+#ifdef ENONET
+ ENONET,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Machine is not on the network") },
+ { BSM_ERRNO_ENOPKG,
+#ifdef ENOPKG
+ ENOPKG,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Package not installed") },
+ { BSM_ERRNO_EREMOTE, EREMOTE,
+ ES("Too many levels of remote in path") },
+ { BSM_ERRNO_ENOLINK,
+#ifdef ENOLINK
+ ENOLINK,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Link has been severed") },
+ { BSM_ERRNO_EADV,
+#ifdef EADV
+ EADV,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Advertise error") },
+ { BSM_ERRNO_ESRMNT,
+#ifdef ESRMNT
+ ESRMNT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("srmount error") },
+ { BSM_ERRNO_ECOMM,
+#ifdef ECOMM
+ ECOMM,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Communication error on send") },
+ { BSM_ERRNO_EPROTO,
+#ifdef EPROTO
+ EPROTO,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Protocol error") },
+ { BSM_ERRNO_ELOCKUNMAPPED,
+#ifdef ELOCKUNMAPPED
+ ELOCKUNMAPPED,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Locked lock was unmapped") },
+ { BSM_ERRNO_ENOTACTIVE,
+#ifdef ENOTACTIVE
+ ENOTACTIVE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Facility is not active") },
+ { BSM_ERRNO_EMULTIHOP,
+#ifdef EMULTIHOP
+ EMULTIHOP,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Multihop attempted") },
+ { BSM_ERRNO_EBADMSG,
+#ifdef EBADMSG
+ EBADMSG,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Bad message") },
+ { BSM_ERRNO_ENAMETOOLONG, ENAMETOOLONG, ES("File name too long") },
+ { BSM_ERRNO_EOVERFLOW, EOVERFLOW,
+ ES("Value too large to be stored in data type") },
+ { BSM_ERRNO_ENOTUNIQ,
+#ifdef ENOTUNIQ
+ ENOTUNIQ,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Given log name not unique") },
+ { BSM_ERRNO_EBADFD,
+#ifdef EBADFD
+ EBADFD,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Given f.d. invalid for this operation") },
+ { BSM_ERRNO_EREMCHG,
+#ifdef EREMCHG
+ EREMCHG,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Remote address changed") },
+ { BSM_ERRNO_ELIBACC,
+#ifdef ELIBACC
+ ELIBACC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Can't access a needed shared lib") },
+ { BSM_ERRNO_ELIBBAD,
+#ifdef ELIBBAD
+ ELIBBAD,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Accessing a corrupted shared lib") },
+ { BSM_ERRNO_ELIBSCN,
+#ifdef ELIBSCN
+ ELIBSCN,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES(".lib section in a.out corrupted") },
+ { BSM_ERRNO_ELIBMAX,
+#ifdef ELIBMAX
+ ELIBMAX,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Attempting to link in too many libs") },
+ { BSM_ERRNO_ELIBEXEC,
+#ifdef ELIBEXEC
+ ELIBEXEC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Attempting to exec a shared library") },
+ { BSM_ERRNO_EILSEQ, EILSEQ, ES("Illegal byte sequence") },
+ { BSM_ERRNO_ENOSYS, ENOSYS, ES("Function not implemented") },
+ { BSM_ERRNO_ELOOP, ELOOP, ES("Too many levels of symbolic links") },
+ { BSM_ERRNO_ERESTART,
+#ifdef ERESTART
+ ERESTART,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Restart syscall") },
+ { BSM_ERRNO_ESTRPIPE,
+#ifdef ESTRPIPE
+ ESTRPIPE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("If pipe/FIFO, don't sleep in stream head") },
+ { BSM_ERRNO_ENOTEMPTY, ENOTEMPTY, ES("Directory not empty") },
+ { BSM_ERRNO_EUSERS, EUSERS, ES("Too many users") },
+ { BSM_ERRNO_ENOTSOCK, ENOTSOCK,
+ ES("Socket operation on non-socket") },
+ { BSM_ERRNO_EDESTADDRREQ, EDESTADDRREQ,
+ ES("Destination address required") },
+ { BSM_ERRNO_EMSGSIZE, EMSGSIZE, ES("Message too long") },
+ { BSM_ERRNO_EPROTOTYPE, EPROTOTYPE,
+ ES("Protocol wrong type for socket") },
+ { BSM_ERRNO_ENOPROTOOPT, ENOPROTOOPT, ES("Protocol not available") },
+ { BSM_ERRNO_EPROTONOSUPPORT, EPROTONOSUPPORT,
+ ES("Protocol not supported") },
+ { BSM_ERRNO_ESOCKTNOSUPPORT, ESOCKTNOSUPPORT,
+ ES("Socket type not supported") },
+ { BSM_ERRNO_EOPNOTSUPP, EOPNOTSUPP, ES("Operation not supported") },
+ { BSM_ERRNO_EPFNOSUPPORT, EPFNOSUPPORT,
+ ES("Protocol family not supported") },
+ { BSM_ERRNO_EAFNOSUPPORT, EAFNOSUPPORT,
+ ES("Address family not supported by protocol family") },
+ { BSM_ERRNO_EADDRINUSE, EADDRINUSE, ES("Address already in use") },
+ { BSM_ERRNO_EADDRNOTAVAIL, EADDRNOTAVAIL,
+ ES("Can't assign requested address") },
+ { BSM_ERRNO_ENETDOWN, ENETDOWN, ES("Network is down") },
+ { BSM_ERRNO_ENETRESET, ENETRESET,
+ ES("Network dropped connection on reset") },
+ { BSM_ERRNO_ECONNABORTED, ECONNABORTED,
+ ES("Software caused connection abort") },
+ { BSM_ERRNO_ECONNRESET, ECONNRESET, ES("Connection reset by peer") },
+ { BSM_ERRNO_ENOBUFS, ENOBUFS, ES("No buffer space available") },
+ { BSM_ERRNO_EISCONN, EISCONN, ES("Socket is already connected") },
+ { BSM_ERRNO_ENOTCONN, ENOTCONN, ES("Socket is not connected") },
+ { BSM_ERRNO_ESHUTDOWN, ESHUTDOWN,
+ ES("Can't send after socket shutdown") },
+ { BSM_ERRNO_ETOOMANYREFS, ETOOMANYREFS,
+ ES("Too many references: can't splice") },
+ { BSM_ERRNO_ETIMEDOUT, ETIMEDOUT, ES("Operation timed out") },
+ { BSM_ERRNO_ECONNREFUSED, ECONNREFUSED, ES("Connection refused") },
+ { BSM_ERRNO_EHOSTDOWN, EHOSTDOWN, ES("Host is down") },
+ { BSM_ERRNO_EHOSTUNREACH, EHOSTUNREACH, ES("No route to host") },
+ { BSM_ERRNO_EALREADY, EALREADY, ES("Operation already in progress") },
+ { BSM_ERRNO_EINPROGRESS, EINPROGRESS,
+ ES("Operation now in progress") },
+ { BSM_ERRNO_ESTALE, ESTALE, ES("Stale NFS file handle") },
+ { BSM_ERRNO_EPROCLIM,
+#ifdef EPROCLIM
+ EPROCLIM,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Too many processes") },
+ { BSM_ERRNO_EBADRPC,
+#ifdef EBADRPC
+ EBADRPC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("RPC struct is bad") },
+ { BSM_ERRNO_ERPCMISMATCH,
+#ifdef ERPCMISMATCH
+ ERPCMISMATCH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("RPC version wrong") },
+ { BSM_ERRNO_EPROGUNAVAIL,
+#ifdef EPROGUNAVAIL
+ EPROGUNAVAIL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("RPC prog. not avail") },
+ { BSM_ERRNO_EPROGMISMATCH,
+#ifdef EPROGMISMATCH
+ EPROGMISMATCH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("RPC version wrong") },
+ { BSM_ERRNO_EPROCUNAVAIL,
+#ifdef EPROCUNAVAIL
+ EPROCUNAVAIL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Bad procedure for program") },
+ { BSM_ERRNO_EFTYPE,
+#ifdef EFTYPE
+ EFTYPE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Inappropriate file type or format") },
+ { BSM_ERRNO_EAUTH,
+#ifdef EAUTH
+ EAUTH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Authenticateion error") },
+ { BSM_ERRNO_ENEEDAUTH,
+#ifdef ENEEDAUTH
+ ENEEDAUTH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Need authenticator") },
+ { BSM_ERRNO_ENOATTR,
+#ifdef ENOATTR
+ ENOATTR,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Attribute not found") },
+ { BSM_ERRNO_EDOOFUS,
+#ifdef EDOOFUS
+ EDOOFUS,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Programming error") },
+ { BSM_ERRNO_EJUSTRETURN,
+#ifdef EJUSTRETURN
+ EJUSTRETURN,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Just return") },
+ { BSM_ERRNO_ENOIOCTL,
+#ifdef ENOIOCTL
+ ENOIOCTL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("ioctl not handled by this layer") },
+ { BSM_ERRNO_EDIRIOCTL,
+#ifdef EDIRIOCTL
+ EDIRIOCTL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("do direct ioctl in GEOM") },
+ { BSM_ERRNO_EPWROFF,
+#ifdef EPWROFF
+ EPWROFF,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Device power is off") },
+ { BSM_ERRNO_EDEVERR,
+#ifdef EDEVERR
+ EDEVERR,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Device error") },
+ { BSM_ERRNO_EBADEXEC,
+#ifdef EBADEXEC
+ EBADEXEC,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Bad executable") },
+ { BSM_ERRNO_EBADARCH,
+#ifdef EBADARCH
+ EBADARCH,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Bad CPU type in executable") },
+ { BSM_ERRNO_ESHLIBVERS,
+#ifdef ESHLIBVERS
+ ESHLIBVERS,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Shared library version mismatch") },
+ { BSM_ERRNO_EBADMACHO,
+#ifdef EBADMACHO
+ EBADMACHO,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Malformed Macho file") },
+ { BSM_ERRNO_EPOLICY,
+#ifdef EPOLICY
+ EPOLICY,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Operation failed by policy") },
+ { BSM_ERRNO_EDOTDOT,
+#ifdef EDOTDOT
+ EDOTDOT,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("RFS specific error") },
+ { BSM_ERRNO_EUCLEAN,
+#ifdef EUCLEAN
+ EUCLEAN,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Structure needs cleaning") },
+ { BSM_ERRNO_ENOTNAM,
+#ifdef ENOTNAM
+ ENOTNAM,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Not a XENIX named type file") },
+ { BSM_ERRNO_ENAVAIL,
+#ifdef ENAVAIL
+ ENAVAIL,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("No XENIX semaphores available") },
+ { BSM_ERRNO_EISNAM,
+#ifdef EISNAM
+ EISNAM,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Is a named type file") },
+ { BSM_ERRNO_EREMOTEIO,
+#ifdef EREMOTEIO
+ EREMOTEIO,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Remote I/O error") },
+ { BSM_ERRNO_ENOMEDIUM,
+#ifdef ENOMEDIUM
+ ENOMEDIUM,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("No medium found") },
+ { BSM_ERRNO_EMEDIUMTYPE,
+#ifdef EMEDIUMTYPE
+ EMEDIUMTYPE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Wrong medium type") },
+ { BSM_ERRNO_ENOKEY,
+#ifdef ENOKEY
+ ENOKEY,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Required key not available") },
+ { BSM_ERRNO_EKEYEXPIRED,
+#ifdef EKEYEXPIRED
+ EKEYEXPIRED,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Key has expired") },
+ { BSM_ERRNO_EKEYREVOKED,
+#ifdef EKEYREVOKED
+ EKEYREVOKED,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Key has been revoked") },
+ { BSM_ERRNO_EKEYREJECTED,
+#ifdef EKEYREJECTED
+ EKEYREJECTED,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Key was rejected by service") },
+ { BSM_ERRNO_ENOTCAPABLE,
+#ifdef ENOTCAPABLE
+ ENOTCAPABLE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Capabilities insufficient") },
+ { BSM_ERRNO_ECAPMODE,
+#ifdef ECAPMODE
+ ECAPMODE,
+#else
+ ERRNO_NO_LOCAL_MAPPING,
+#endif
+ ES("Not permitted in capability mode") },
+};
+static const int bsm_errnos_count = sizeof(bsm_errnos) / sizeof(bsm_errnos[0]);
+
+static const struct bsm_errno *
+bsm_lookup_errno_local(int local_errno)
+{
+ int i;
+
+ for (i = 0; i < bsm_errnos_count; i++) {
+ if (bsm_errnos[i].be_local_errno == local_errno)
+ return (&bsm_errnos[i]);
+ }
+ return (NULL);
+}
+
+/*
+ * Conversion to the BSM errno space isn't allowed to fail; we simply map to
+ * BSM_ERRNO_UNKNOWN and let the remote endpoint deal with it.
+ */
+u_char
+au_errno_to_bsm(int local_errno)
+{
+ const struct bsm_errno *bsme;
+
+ bsme = bsm_lookup_errno_local(local_errno);
+ if (bsme == NULL)
+ return (BSM_ERRNO_UNKNOWN);
+ return (bsme->be_bsm_errno);
+}
+
+static const struct bsm_errno *
+bsm_lookup_errno_bsm(u_char bsm_errno)
+{
+ int i;
+
+ for (i = 0; i < bsm_errnos_count; i++) {
+ if (bsm_errnos[i].be_bsm_errno == bsm_errno)
+ return (&bsm_errnos[i]);
+ }
+ return (NULL);
+}
+
+/*
+ * Converstion from a BSM error to a local error number may fail if either
+ * OpenBSM doesn't recognize the error on the wire, or because there is no
+ * appropriate local mapping.
+ */
+int
+au_bsm_to_errno(u_char bsm_errno, int *errorp)
+{
+ const struct bsm_errno *bsme;
+
+ bsme = bsm_lookup_errno_bsm(bsm_errno);
+ if (bsme == NULL || bsme->be_local_errno == ERRNO_NO_LOCAL_MAPPING)
+ return (-1);
+ *errorp = bsme->be_local_errno;
+ return (0);
+}
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+const char *
+au_strerror(u_char bsm_errno)
+{
+ const struct bsm_errno *bsme;
+
+ bsme = bsm_lookup_errno_bsm(bsm_errno);
+ if (bsme == NULL)
+ return ("Unrecognized BSM error");
+ if (bsme->be_local_errno != ERRNO_NO_LOCAL_MAPPING)
+ return (strerror(bsme->be_local_errno));
+ return (bsme->be_strerror);
+}
+#endif
diff --git a/contrib/openbsm/libbsm/bsm_event.c b/contrib/openbsm/libbsm/bsm_event.c
new file mode 100644
index 0000000..5499083
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_event.c
@@ -0,0 +1,361 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * 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.
+ * 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 <config/config.h>
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+
+/*
+ * Parse the contents of the audit_event file to return
+ * au_event_ent entries
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *eventdelim = ":";
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*
+ * Parse one line from the audit_event file into the au_event_ent structure.
+ */
+static struct au_event_ent *
+eventfromstr(char *str, struct au_event_ent *e)
+{
+ char *evno, *evname, *evdesc, *evclass;
+ struct au_mask evmask;
+ char *last;
+
+ evno = strtok_r(str, eventdelim, &last);
+ evname = strtok_r(NULL, eventdelim, &last);
+ evdesc = strtok_r(NULL, eventdelim, &last);
+ evclass = strtok_r(NULL, eventdelim, &last);
+
+ if ((evno == NULL) || (evname == NULL))
+ return (NULL);
+
+ if (strlen(evname) >= AU_EVENT_NAME_MAX)
+ return (NULL);
+
+ strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX);
+ if (evdesc != NULL) {
+ if (strlen(evdesc) >= AU_EVENT_DESC_MAX)
+ return (NULL);
+ strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX);
+ } else
+ strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX);
+
+ e->ae_number = atoi(evno);
+
+ /*
+ * Find out the mask that corresponds to the given list of classes.
+ */
+ if (evclass != NULL) {
+ if (getauditflagsbin(evclass, &evmask) != 0)
+ e->ae_class = 0;
+ else
+ e->ae_class = evmask.am_success;
+ } else
+ e->ae_class = 0;
+
+ return (e);
+}
+
+/*
+ * Rewind the audit_event file.
+ */
+static void
+setauevent_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauevent(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setauevent_locked();
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Close the open file pointers.
+ */
+void
+endauevent(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Enumerate the au_event_ent entries.
+ */
+static struct au_event_ent *
+getauevent_r_locked(struct au_event_ent *e)
+{
+ char *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Get the next event structure. */
+ if (eventfromstr(linestr, e) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (e);
+}
+
+struct au_event_ent *
+getauevent_r(struct au_event_ent *e)
+{
+ struct au_event_ent *ep;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ ep = getauevent_r_locked(e);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (ep);
+}
+
+struct au_event_ent *
+getauevent(void)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevent_r(&e));
+}
+
+/*
+ * Search for an audit event structure having the given event name.
+ *
+ * XXXRW: Why accept NULL name?
+ */
+static struct au_event_ent *
+getauevnam_r_locked(struct au_event_ent *e, const char *name)
+{
+ char *nl;
+
+ if (name == NULL)
+ return (NULL);
+
+ /* Rewind to beginning of the file. */
+ setauevent_locked();
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ if (eventfromstr(linestr, e) != NULL) {
+ if (strcmp(name, e->ae_name) == 0)
+ return (e);
+ }
+ }
+
+ return (NULL);
+}
+
+struct au_event_ent *
+getauevnam_r(struct au_event_ent *e, const char *name)
+{
+ struct au_event_ent *ep;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ ep = getauevnam_r_locked(e, name);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (ep);
+}
+
+struct au_event_ent *
+getauevnam(const char *name)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevnam_r(&e, name));
+}
+
+/*
+ * Search for an audit event structure having the given event number.
+ */
+static struct au_event_ent *
+getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number)
+{
+ char *nl;
+
+ /* Rewind to beginning of the file. */
+ setauevent_locked();
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ if (eventfromstr(linestr, e) != NULL) {
+ if (event_number == e->ae_number)
+ return (e);
+ }
+ }
+
+ return (NULL);
+}
+
+struct au_event_ent *
+getauevnum_r(struct au_event_ent *e, au_event_t event_number)
+{
+ struct au_event_ent *ep;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ ep = getauevnum_r_locked(e, event_number);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (ep);
+}
+
+struct au_event_ent *
+getauevnum(au_event_t event_number)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevnum_r(&e, event_number));
+}
+
+/*
+ * Search for an audit_event entry with a given event_name and returns the
+ * corresponding event number.
+ */
+au_event_t *
+getauevnonam_r(au_event_t *ev, const char *event_name)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e, *ep;
+
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ bzero(&e, sizeof(e));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+
+ ep = getauevnam_r(&e, event_name);
+ if (ep == NULL)
+ return (NULL);
+
+ *ev = e.ae_number;
+ return (ev);
+}
+
+au_event_t *
+getauevnonam(const char *event_name)
+{
+ static au_event_t event;
+
+ return (getauevnonam_r(&event, event_name));
+}
diff --git a/contrib/openbsm/libbsm/bsm_fcntl.c b/contrib/openbsm/libbsm/bsm_fcntl.c
new file mode 100644
index 0000000..45ae5da
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_fcntl.c
@@ -0,0 +1,287 @@
+/*-
+ * Copyright (c) 2008-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/param.h>
+#include <sys/fcntl.h>
+
+#include <config/config.h>
+
+#include <bsm/audit_fcntl.h>
+#include <bsm/libbsm.h>
+
+struct bsm_fcntl_cmd {
+ u_short bfc_bsm_fcntl_cmd;
+ int bfc_local_fcntl_cmd;
+};
+typedef struct bsm_fcntl_cmd bsm_fcntl_cmd_t;
+
+static const bsm_fcntl_cmd_t bsm_fcntl_cmdtab[] = {
+ { BSM_F_DUPFD, F_DUPFD },
+ { BSM_F_GETFD, F_GETFD },
+ { BSM_F_SETFD, F_SETFD },
+ { BSM_F_GETFL, F_GETFL },
+ { BSM_F_SETFL, F_SETFL },
+#ifdef F_O_GETLK
+ { BSM_F_O_GETLK, F_O_GETLK },
+#endif
+ { BSM_F_SETLK, F_SETLK },
+ { BSM_F_SETLKW, F_SETLK },
+#ifdef F_CHFL
+ { BSM_F_CHKFL, F_CHKFL },
+#endif
+#ifdef F_DUP2FD
+ { BSM_F_DUP2FD, F_DUP2FD },
+#endif
+#ifdef F_ALLOCSP
+ { BSM_F_ALLOCSP, F_ALLOCSP },
+#endif
+#ifdef F_FREESP
+ { BSM_F_FREESP, F_FREESP },
+#endif
+#ifdef F_ISSTREAM
+ { BSM_F_ISSTREAM, F_ISSTREAM},
+#endif
+ { BSM_F_GETLK, F_GETLK },
+#ifdef F_PRIV
+ { BSM_F_PRIV, F_PRIV },
+#endif
+#ifdef F_NPRIV
+ { BSM_F_NPRIV, F_NPRIV },
+#endif
+#ifdef F_QUOTACTL
+ { BSM_F_QUOTACTL, F_QUOTACTL },
+#endif
+#ifdef F_BLOCKS
+ { BSM_F_BLOCKS, F_BLOCKS },
+#endif
+#ifdef F_BLKSIZE
+ { BSM_F_BLKSIZE, F_BLKSIZE },
+#endif
+ { BSM_F_GETOWN, F_GETOWN },
+ { BSM_F_SETOWN, F_SETOWN },
+#ifdef F_REVOKE
+ { BSM_F_REVOKE, F_REVOKE },
+#endif
+#ifdef F_HASREMOTEBLOCKS
+ { BSM_F_HASREMOTEBLOCKS,
+ F_HASREMOTEBLOCKS },
+#endif
+#ifdef F_FREESP
+ { BSM_F_FREESP, F_FREESP },
+#endif
+#ifdef F_ALLOCSP
+ { BSM_F_ALLOCSP, F_ALLOCSP },
+#endif
+#ifdef F_FREESP64
+ { BSM_F_FREESP64, F_FREESP64 },
+#endif
+#ifdef F_ALLOCSP64
+ { BSM_F_ALLOCSP64, F_ALLOCSP64 },
+#endif
+#ifdef F_GETLK64
+ { BSM_F_GETLK64, F_GETLK64 },
+#endif
+#ifdef F_SETLK64
+ { BSM_F_SETLK64, F_SETLK64 },
+#endif
+#ifdef F_SETLKW64
+ { BSM_F_SETLKW64, F_SETLKW64 },
+#endif
+#ifdef F_SHARE
+ { BSM_F_SHARE, F_SHARE },
+#endif
+#ifdef F_UNSHARE
+ { BSM_F_UNSHARE, F_UNSHARE },
+#endif
+#ifdef F_SETLK_NBMAND
+ { BSM_F_SETLK_NBMAND, F_SETLK_NBMAND },
+#endif
+#ifdef F_SHARE_NBMAND
+ { BSM_F_SHARE_NBMAND, F_SHARE_NBMAND },
+#endif
+#ifdef F_SETLK64_NBMAND
+ { BSM_F_SETLK64_NBMAND, F_SETLK64_NBMAND },
+#endif
+#ifdef F_GETXFL
+ { BSM_F_GETXFL, F_GETXFL },
+#endif
+#ifdef F_BADFD
+ { BSM_F_BADFD, F_BADFD },
+#endif
+#ifdef F_OGETLK
+ { BSM_F_OGETLK, F_OGETLK },
+#endif
+#ifdef F_OSETLK
+ { BSM_F_OSETLK, F_OSETLK },
+#endif
+#ifdef F_OSETLKW
+ { BSM_F_OSETLKW, F_OSETLKW },
+#endif
+#ifdef F_SETLK_REMOTE
+ { BSM_F_SETLK_REMOTE, F_SETLK_REMOTE },
+#endif
+
+#ifdef F_SETSIG
+ { BSM_F_SETSIG, F_SETSIG },
+#endif
+#ifdef F_GETSIG
+ { BSM_F_GETSIG, F_GETSIG },
+#endif
+
+#ifdef F_CHKCLEAN
+ { BSM_F_CHKCLEAN, F_CHKCLEAN },
+#endif
+#ifdef F_PREALLOCATE
+ { BSM_F_PREALLOCATE, F_PREALLOCATE },
+#endif
+#ifdef F_SETSIZE
+ { BSM_F_SETSIZE, F_SETSIZE },
+#endif
+#ifdef F_RDADVISE
+ { BSM_F_RDADVISE, F_RDADVISE },
+#endif
+#ifdef F_RDAHEAD
+ { BSM_F_RDAHEAD, F_RDAHEAD },
+#endif
+#ifdef F_READBOOTSTRAP
+ { BSM_F_READBOOTSTRAP, F_READBOOTSTRAP },
+#endif
+#ifdef F_WRITEBOOTSTRAP
+ { BSM_F_WRITEBOOTSTRAP, F_WRITEBOOTSTRAP },
+#endif
+#ifdef F_NOCACHE
+ { BSM_F_NOCACHE, F_NOCACHE },
+#endif
+#ifdef F_LOG2PHYS
+ { BSM_F_LOG2PHYS, F_LOG2PHYS },
+#endif
+#ifdef F_GETPATH
+ { BSM_F_GETPATH, F_GETPATH },
+#endif
+#ifdef F_FULLFSYNC
+ { BSM_F_FULLFSYNC, F_FULLFSYNC },
+#endif
+#ifdef F_PATHPKG_CHECK
+ { BSM_F_PATHPKG_CHECK, F_PATHPKG_CHECK },
+#endif
+#ifdef F_FREEZE_FS
+ { BSM_F_FREEZE_FS, F_FREEZE_FS },
+#endif
+#ifdef F_THAW_FS
+ { BSM_F_THAW_FS, F_THAW_FS },
+#endif
+#ifdef F_GLOBAL_NOCACHE
+ { BSM_F_GLOBAL_NOCACHE, F_GLOBAL_NOCACHE },
+#endif
+#ifdef F_OPENFROM
+ { BSM_F_OPENFROM, F_OPENFROM },
+#endif
+#ifdef F_UNLINKFROM
+ { BSM_F_UNLINKFROM, F_UNLINKFROM },
+#endif
+#ifdef F_CHECK_OPENEVT
+ { BSM_F_CHECK_OPENEVT, F_CHECK_OPENEVT },
+#endif
+#ifdef F_ADDSIGS
+ { BSM_F_ADDSIGS, F_ADDSIGS },
+#endif
+#ifdef F_MARKDEPENDENCY
+ { BSM_F_MARKDEPENDENCY, F_MARKDEPENDENCY },
+#endif
+
+#ifdef FCNTL_FS_SPECIFIC_BASE
+ { BSM_F_FS_SPECIFIC_0, FCNTL_FS_SPECIFIC_BASE},
+ { BSM_F_FS_SPECIFIC_1, FCNTL_FS_SPECIFIC_BASE + 1},
+ { BSM_F_FS_SPECIFIC_2, FCNTL_FS_SPECIFIC_BASE + 2},
+ { BSM_F_FS_SPECIFIC_3, FCNTL_FS_SPECIFIC_BASE + 3},
+ { BSM_F_FS_SPECIFIC_4, FCNTL_FS_SPECIFIC_BASE + 4},
+ { BSM_F_FS_SPECIFIC_5, FCNTL_FS_SPECIFIC_BASE + 5},
+ { BSM_F_FS_SPECIFIC_6, FCNTL_FS_SPECIFIC_BASE + 6},
+ { BSM_F_FS_SPECIFIC_7, FCNTL_FS_SPECIFIC_BASE + 7},
+ { BSM_F_FS_SPECIFIC_8, FCNTL_FS_SPECIFIC_BASE + 8},
+ { BSM_F_FS_SPECIFIC_9, FCNTL_FS_SPECIFIC_BASE + 9},
+ { BSM_F_FS_SPECIFIC_10, FCNTL_FS_SPECIFIC_BASE + 10},
+ { BSM_F_FS_SPECIFIC_11, FCNTL_FS_SPECIFIC_BASE + 11},
+ { BSM_F_FS_SPECIFIC_12, FCNTL_FS_SPECIFIC_BASE + 12},
+ { BSM_F_FS_SPECIFIC_13, FCNTL_FS_SPECIFIC_BASE + 13},
+ { BSM_F_FS_SPECIFIC_14, FCNTL_FS_SPECIFIC_BASE + 14},
+ { BSM_F_FS_SPECIFIC_15, FCNTL_FS_SPECIFIC_BASE + 15},
+#endif /* FCNTL_FS_SPECIFIC_BASE */
+};
+static const int bsm_fcntl_cmd_count = sizeof(bsm_fcntl_cmdtab) /
+ sizeof(bsm_fcntl_cmdtab[0]);
+
+static const bsm_fcntl_cmd_t *
+bsm_lookup_local_fcntl_cmd(int local_fcntl_cmd)
+{
+ int i;
+
+ for (i = 0; i < bsm_fcntl_cmd_count; i++) {
+ if (bsm_fcntl_cmdtab[i].bfc_local_fcntl_cmd ==
+ local_fcntl_cmd)
+ return (&bsm_fcntl_cmdtab[i]);
+ }
+ return (NULL);
+}
+
+u_short
+au_fcntl_cmd_to_bsm(int local_fcntl_cmd)
+{
+ const bsm_fcntl_cmd_t *bfcp;
+
+ bfcp = bsm_lookup_local_fcntl_cmd(local_fcntl_cmd);
+ if (bfcp == NULL)
+ return (BSM_F_UNKNOWN);
+ return (bfcp->bfc_bsm_fcntl_cmd);
+}
+
+static const bsm_fcntl_cmd_t *
+bsm_lookup_bsm_fcntl_cmd(u_short bsm_fcntl_cmd)
+{
+ int i;
+
+ for (i = 0; i < bsm_fcntl_cmd_count; i++) {
+ if (bsm_fcntl_cmdtab[i].bfc_bsm_fcntl_cmd ==
+ bsm_fcntl_cmd)
+ return (&bsm_fcntl_cmdtab[i]);
+ }
+ return (NULL);
+}
+
+int
+au_bsm_to_fcntl_cmd(u_short bsm_fcntl_cmd, int *local_fcntl_cmdp)
+{
+ const bsm_fcntl_cmd_t *bfcp;
+
+ bfcp = bsm_lookup_bsm_fcntl_cmd(bsm_fcntl_cmd);
+ if (bfcp == NULL || bfcp->bfc_local_fcntl_cmd)
+ return (-1);
+ *local_fcntl_cmdp = bfcp->bfc_local_fcntl_cmd;
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_flags.c b/contrib/openbsm/libbsm/bsm_flags.c
new file mode 100644
index 0000000..46b8a1f
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_flags.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * 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.
+ * 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 <config/config.h>
+
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+static const char *flagdelim = ",";
+
+/*
+ * Convert the character representation of audit values into the au_mask_t
+ * field.
+ */
+int
+getauditflagsbin(char *auditstr, au_mask_t *masks)
+{
+ char class_ent_name[AU_CLASS_NAME_MAX];
+ char class_ent_desc[AU_CLASS_DESC_MAX];
+ struct au_class_ent c;
+ char *tok;
+ char sel, sub;
+ char *last;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ masks->am_success = 0;
+ masks->am_failure = 0;
+
+ tok = strtok_r(auditstr, flagdelim, &last);
+ while (tok != NULL) {
+ /* Check for the events that should not be audited. */
+ if (tok[0] == '^') {
+ sub = 1;
+ tok++;
+ } else
+ sub = 0;
+
+ /* Check for the events to be audited for success. */
+ if (tok[0] == '+') {
+ sel = AU_PRS_SUCCESS;
+ tok++;
+ } else if (tok[0] == '-') {
+ sel = AU_PRS_FAILURE;
+ tok++;
+ } else
+ sel = AU_PRS_BOTH;
+
+ if ((getauclassnam_r(&c, tok)) != NULL) {
+ if (sub)
+ SUB_FROM_MASK(masks, c.ac_class, sel);
+ else
+ ADD_TO_MASK(masks, c.ac_class, sel);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Get the next class. */
+ tok = strtok_r(NULL, flagdelim, &last);
+ }
+ return (0);
+}
+
+/*
+ * Convert the au_mask_t fields into a string value. If verbose is non-zero
+ * the long flag names are used else the short (2-character)flag names are
+ * used.
+ *
+ * XXXRW: If bits are specified that are not matched by any class, they are
+ * omitted rather than rejected with EINVAL.
+ *
+ * XXXRW: This is not thread-safe as it relies on atomicity between
+ * setauclass() and sequential calls to getauclassent(). This could be
+ * fixed by iterating through the bitmask fields rather than iterating
+ * through the classes.
+ */
+int
+getauditflagschar(char *auditstr, au_mask_t *masks, int verbose)
+{
+ char class_ent_name[AU_CLASS_NAME_MAX];
+ char class_ent_desc[AU_CLASS_DESC_MAX];
+ struct au_class_ent c;
+ char *strptr = auditstr;
+ u_char sel;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ /*
+ * Enumerate the class entries, check if each is selected in either
+ * the success or failure masks.
+ */
+ setauclass();
+ while ((getauclassent_r(&c)) != NULL) {
+ sel = 0;
+
+ /* Dont do anything for class = no. */
+ if (c.ac_class == 0)
+ continue;
+
+ sel |= ((c.ac_class & masks->am_success) == c.ac_class) ?
+ AU_PRS_SUCCESS : 0;
+ sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ?
+ AU_PRS_FAILURE : 0;
+
+ /*
+ * No prefix should be attached if both success and failure
+ * are selected.
+ */
+ if ((sel & AU_PRS_BOTH) == 0) {
+ if ((sel & AU_PRS_SUCCESS) != 0) {
+ *strptr = '+';
+ strptr = strptr + 1;
+ } else if ((sel & AU_PRS_FAILURE) != 0) {
+ *strptr = '-';
+ strptr = strptr + 1;
+ }
+ }
+
+ if (sel != 0) {
+ if (verbose) {
+ strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX);
+ strptr += strlen(c.ac_desc);
+ } else {
+ strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX);
+ strptr += strlen(c.ac_name);
+ }
+ *strptr = ','; /* delimiter */
+ strptr = strptr + 1;
+ }
+ }
+
+ /* Overwrite the last delimiter with the string terminator. */
+ if (strptr != auditstr)
+ *(strptr-1) = '\0';
+
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_io.c b/contrib/openbsm/libbsm/bsm_io.c
new file mode 100644
index 0000000..43cf7e9
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_io.c
@@ -0,0 +1,4612 @@
+/*-
+ * Copyright (c) 2004-2009 Apple Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * Copyright (c) 2006 Martin Voros
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * 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>
+
+#ifdef USE_ENDIAN_H
+#include <endian.h>
+#endif
+#ifdef USE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+#ifdef USE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#ifdef USE_COMPAT_ENDIAN_H
+#include <compat/endian.h>
+#endif
+#ifdef USE_COMPAT_ENDIAN_ENC_H
+#include <compat/endian_enc.h>
+#endif
+
+#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/stat.h>
+#include <sys/socket.h>
+
+#include <bsm/libbsm.h>
+
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef HAVE_VIS
+#include <vis.h>
+#else
+#include <compat/vis.h>
+#endif
+
+#include <bsm/audit_internal.h>
+
+#define READ_TOKEN_BYTES(buf, len, dest, size, bytesread, err) do { \
+ if ((bytesread) + (size) > (u_int32_t)(len)) { \
+ (err) = 1; \
+ } else { \
+ memcpy((dest), (buf) + (bytesread), (size)); \
+ bytesread += size; \
+ } \
+} while (0)
+
+#define READ_TOKEN_U_CHAR(buf, len, dest, bytesread, err) do { \
+ if ((bytesread) + sizeof(u_char) <= (u_int32_t)(len)) { \
+ (dest) = buf[(bytesread)]; \
+ (bytesread) += sizeof(u_char); \
+ } else \
+ (err) = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT16(buf, len, dest, bytesread, err) do { \
+ if ((bytesread) + sizeof(u_int16_t) <= (u_int32_t)(len)) { \
+ (dest) = be16dec((buf) + (bytesread)); \
+ (bytesread) += sizeof(u_int16_t); \
+ } else \
+ (err) = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT32(buf, len, dest, bytesread, err) do { \
+ if ((bytesread) + sizeof(u_int32_t) <= (u_int32_t)(len)) { \
+ (dest) = be32dec((buf) + (bytesread)); \
+ (bytesread) += sizeof(u_int32_t); \
+ } else \
+ (err) = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT64(buf, len, dest, bytesread, err) do { \
+ if ((bytesread) + sizeof(u_int64_t) <= (u_int32_t)(len)) { \
+ dest = be64dec((buf) + (bytesread)); \
+ (bytesread) += sizeof(u_int64_t); \
+ } else \
+ (err) = 1; \
+} while (0)
+
+#define SET_PTR(buf, len, ptr, size, bytesread, err) do { \
+ if ((bytesread) + (size) > (u_int32_t)(len)) \
+ (err) = 1; \
+ else { \
+ (ptr) = (buf) + (bytesread); \
+ (bytesread) += (size); \
+ } \
+} while (0)
+
+/*
+ * XML option.
+ */
+#define AU_PLAIN 0
+#define AU_XML 1
+
+/*
+ * Prints the delimiter string.
+ */
+static void
+print_delim(FILE *fp, const char *del)
+{
+
+ fprintf(fp, "%s", del);
+}
+
+/*
+ * Prints a single byte in the given format.
+ */
+static void
+print_1_byte(FILE *fp, u_char val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Print 2 bytes in the given format.
+ */
+static void
+print_2_bytes(FILE *fp, u_int16_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints 4 bytes in the given format.
+ */
+static void
+print_4_bytes(FILE *fp, u_int32_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints 8 bytes in the given format.
+ */
+static void
+print_8_bytes(FILE *fp, u_int64_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints the given size of data bytes in hex.
+ */
+static void
+print_mem(FILE *fp, u_char *data, size_t len)
+{
+ u_int32_t i;
+
+ if (len > 0) {
+ fprintf(fp, "0x");
+ for (i = 0; i < len; i++)
+ fprintf(fp, "%02x", data[i]);
+ }
+}
+
+/*
+ * Prints the given data bytes as a string.
+ */
+static void
+print_string(FILE *fp, const char *str, size_t len)
+{
+ u_int32_t i;
+
+ if (len > 0) {
+ for (i = 0; i < len; i++) {
+ if (str[i] != '\0')
+ fprintf(fp, "%c", str[i]);
+ }
+ }
+}
+
+/*
+ * Prints the given data bytes as an XML-sanitized string.
+ */
+static void
+print_xml_string(FILE *fp, const char *str, size_t len)
+{
+ u_int32_t i;
+ char visbuf[5];
+
+ if (len == 0)
+ return;
+
+ for (i = 0; i < len; i++) {
+ switch (str[i]) {
+ case '\0':
+ return;
+
+ case '&':
+ (void) fprintf(fp, "&amp;");
+ break;
+
+ case '<':
+ (void) fprintf(fp, "&lt;");
+ break;
+
+ case '>':
+ (void) fprintf(fp, "&gt;");
+ break;
+
+ case '\"':
+ (void) fprintf(fp, "&quot;");
+ break;
+
+ case '\'':
+ (void) fprintf(fp, "&apos;");
+ break;
+
+ default:
+ (void) vis(visbuf, str[i], VIS_CSTYLE, 0);
+ (void) fprintf(fp, "%s", visbuf);
+ break;
+ }
+ }
+}
+
+/*
+ * Prints the beginning of an attribute.
+ */
+static void
+open_attr(FILE *fp, const char *str)
+{
+
+ fprintf(fp,"%s=\"", str);
+}
+
+/*
+ * Prints the end of an attribute.
+ */
+static void
+close_attr(FILE *fp)
+{
+
+ fprintf(fp,"\" ");
+}
+
+/*
+ * Prints the end of a tag.
+ */
+static void
+close_tag(FILE *fp, u_char type)
+{
+
+ switch(type) {
+ case AUT_HEADER32:
+ fprintf(fp, ">");
+ break;
+
+ case AUT_HEADER32_EX:
+ fprintf(fp, ">");
+ break;
+
+ case AUT_HEADER64:
+ fprintf(fp, ">");
+ break;
+
+ case AUT_HEADER64_EX:
+ fprintf(fp, ">");
+ break;
+
+ case AUT_ARG32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_ARG64:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_ATTR32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_ATTR64:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_EXIT:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_EXEC_ARGS:
+ fprintf(fp, "</exec_args>");
+ break;
+
+ case AUT_EXEC_ENV:
+ fprintf(fp, "</exec_env>");
+ break;
+
+ case AUT_OTHER_FILE32:
+ fprintf(fp, "</file>");
+ break;
+
+ case AUT_NEWGROUPS:
+ fprintf(fp, "</group>");
+ break;
+
+ case AUT_IN_ADDR:
+ fprintf(fp, "</ip_address>");
+ break;
+
+ case AUT_IN_ADDR_EX:
+ fprintf(fp, "</ip_address>");
+ break;
+
+ case AUT_IP:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_IPC:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_IPC_PERM:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_IPORT:
+ fprintf(fp, "</ip_port>");
+ break;
+
+ case AUT_OPAQUE:
+ fprintf(fp, "</opaque>");
+ break;
+
+ case AUT_PATH:
+ fprintf(fp, "</path>");
+ break;
+
+ case AUT_PROCESS32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_PROCESS32_EX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_PROCESS64:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_PROCESS64_EX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_RETURN32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_RETURN64:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SEQ:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SOCKET:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SOCKINET32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SOCKUNIX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SOCKINET128:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SUBJECT32:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SUBJECT64:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SUBJECT32_EX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_SUBJECT64_EX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_TEXT:
+ fprintf(fp, "</text>");
+ break;
+
+ case AUT_SOCKET_EX:
+ fprintf(fp, "/>");
+ break;
+
+ case AUT_DATA:
+ fprintf(fp, "</arbitrary>");
+ break;
+
+ case AUT_ZONENAME:
+ fprintf(fp, "/>");
+ break;
+ }
+}
+
+/*
+ * Prints the token type in either the raw or the default form.
+ */
+static void
+print_tok_type(FILE *fp, u_char type, const char *tokname, int oflags)
+{
+
+ if (oflags & AU_OFLAG_XML) {
+ switch(type) {
+ case AUT_HEADER32:
+ fprintf(fp, "<record ");
+ break;
+
+ case AUT_HEADER32_EX:
+ fprintf(fp, "<record ");
+ break;
+
+ case AUT_HEADER64:
+ fprintf(fp, "<record ");
+ break;
+
+ case AUT_HEADER64_EX:
+ fprintf(fp, "<record ");
+ break;
+
+ case AUT_TRAILER:
+ fprintf(fp, "</record>");
+ break;
+
+ case AUT_ARG32:
+ fprintf(fp, "<argument ");
+ break;
+
+ case AUT_ARG64:
+ fprintf(fp, "<argument ");
+ break;
+
+ case AUT_ATTR32:
+ fprintf(fp, "<attribute ");
+ break;
+
+ case AUT_ATTR64:
+ fprintf(fp, "<attribute ");
+ break;
+
+ case AUT_EXIT:
+ fprintf(fp, "<exit ");
+ break;
+
+ case AUT_EXEC_ARGS:
+ fprintf(fp, "<exec_args>");
+ break;
+
+ case AUT_EXEC_ENV:
+ fprintf(fp, "<exec_env>");
+ break;
+
+ case AUT_OTHER_FILE32:
+ fprintf(fp, "<file ");
+ break;
+
+ case AUT_NEWGROUPS:
+ fprintf(fp, "<group>");
+ break;
+
+ case AUT_IN_ADDR:
+ fprintf(fp, "<ip_address>");
+ break;
+
+ case AUT_IN_ADDR_EX:
+ fprintf(fp, "<ip_address>");
+ break;
+
+ case AUT_IP:
+ fprintf(fp, "<ip ");
+ break;
+
+ case AUT_IPC:
+ fprintf(fp, "<IPC");
+ break;
+
+ case AUT_IPC_PERM:
+ fprintf(fp, "<IPC_perm ");
+ break;
+
+ case AUT_IPORT:
+ fprintf(fp, "<ip_port>");
+ break;
+
+ case AUT_OPAQUE:
+ fprintf(fp, "<opaque>");
+ break;
+
+ case AUT_PATH:
+ fprintf(fp, "<path>");
+ break;
+
+ case AUT_PROCESS32:
+ fprintf(fp, "<process ");
+ break;
+
+ case AUT_PROCESS32_EX:
+ fprintf(fp, "<process ");
+ break;
+
+ case AUT_PROCESS64:
+ fprintf(fp, "<process ");
+ break;
+
+ case AUT_PROCESS64_EX:
+ fprintf(fp, "<process ");
+ break;
+
+ case AUT_RETURN32:
+ fprintf(fp, "<return ");
+ break;
+
+ case AUT_RETURN64:
+ fprintf(fp, "<return ");
+ break;
+
+ case AUT_SEQ:
+ fprintf(fp, "<sequence ");
+ break;
+
+ case AUT_SOCKET:
+ fprintf(fp, "<socket ");
+ break;
+
+ case AUT_SOCKINET32:
+ fprintf(fp, "<socket-inet ");
+ break;
+
+ case AUT_SOCKUNIX:
+ fprintf(fp, "<socket-unix ");
+ break;
+
+ case AUT_SOCKINET128:
+ fprintf(fp, "<socket-inet6 ");
+ break;
+
+ case AUT_SUBJECT32:
+ fprintf(fp, "<subject ");
+ break;
+
+ case AUT_SUBJECT64:
+ fprintf(fp, "<subject ");
+ break;
+
+ case AUT_SUBJECT32_EX:
+ fprintf(fp, "<subject ");
+ break;
+
+ case AUT_SUBJECT64_EX:
+ fprintf(fp, "<subject ");
+ break;
+
+ case AUT_TEXT:
+ fprintf(fp, "<text>");
+ break;
+
+ case AUT_SOCKET_EX:
+ fprintf(fp, "<socket ");
+ break;
+
+ case AUT_DATA:
+ fprintf(fp, "<arbitrary ");
+ break;
+
+ case AUT_ZONENAME:
+ fprintf(fp, "<zone ");
+ break;
+ }
+ } else {
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", type);
+ else
+ fprintf(fp, "%s", tokname);
+ }
+}
+
+/*
+ * Prints a user value.
+ */
+static void
+print_user(FILE *fp, u_int32_t usr, int oflags)
+{
+ struct passwd *pwent;
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%d", usr);
+ else {
+ pwent = getpwuid(usr);
+ if (pwent != NULL)
+ fprintf(fp, "%s", pwent->pw_name);
+ else
+ fprintf(fp, "%d", usr);
+ }
+}
+
+/*
+ * Prints a group value.
+ */
+static void
+print_group(FILE *fp, u_int32_t grp, int oflags)
+{
+ struct group *grpent;
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%d", grp);
+ else {
+ grpent = getgrgid(grp);
+ if (grpent != NULL)
+ fprintf(fp, "%s", grpent->gr_name);
+ else
+ fprintf(fp, "%d", grp);
+ }
+}
+
+/*
+ * Prints the event from the header token in either the short, default or raw
+ * form.
+ */
+static void
+print_event(FILE *fp, u_int16_t ev, int oflags)
+{
+ char event_ent_name[AU_EVENT_NAME_MAX];
+ char event_ent_desc[AU_EVENT_DESC_MAX];
+ struct au_event_ent e, *ep;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+
+ ep = getauevnum_r(&e, ev);
+ if (ep == NULL) {
+ fprintf(fp, "%u", ev);
+ return;
+ }
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", ev);
+ else if (oflags & AU_OFLAG_SHORT)
+ fprintf(fp, "%s", e.ae_name);
+ else
+ fprintf(fp, "%s", e.ae_desc);
+}
+
+
+/*
+ * Prints the event modifier from the header token in either the default or
+ * raw form.
+ */
+static void
+print_evmod(FILE *fp, u_int16_t evmod, int oflags)
+{
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", evmod);
+ else
+ fprintf(fp, "%u", evmod);
+}
+
+/*
+ * Prints seconds in the ctime format.
+ */
+static void
+print_sec32(FILE *fp, u_int32_t sec, int oflags)
+{
+ time_t timestamp;
+ char timestr[26];
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", sec);
+ else {
+ timestamp = (time_t)sec;
+ ctime_r(&timestamp, timestr);
+ timestr[24] = '\0'; /* No new line */
+ fprintf(fp, "%s", timestr);
+ }
+}
+
+/*
+ * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we
+ * assume a 32-bit time_t, we simply truncate for now.
+ */
+static void
+print_sec64(FILE *fp, u_int64_t sec, int oflags)
+{
+ time_t timestamp;
+ char timestr[26];
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", (u_int32_t)sec);
+ else {
+ timestamp = (time_t)sec;
+ ctime_r(&timestamp, timestr);
+ timestr[24] = '\0'; /* No new line */
+ fprintf(fp, "%s", timestr);
+ }
+}
+
+/*
+ * Prints the excess milliseconds.
+ */
+static void
+print_msec32(FILE *fp, u_int32_t msec, int oflags)
+{
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", msec);
+ else
+ fprintf(fp, " + %u msec", msec);
+}
+
+/*
+ * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we assume
+ * a 32-bit msec, we simply truncate for now.
+ */
+static void
+print_msec64(FILE *fp, u_int64_t msec, int oflags)
+{
+
+ msec &= 0xffffffff;
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", (u_int32_t)msec);
+ else
+ fprintf(fp, " + %u msec", (u_int32_t)msec);
+}
+
+/*
+ * Prints a dotted form for the IP address.
+ */
+static void
+print_ip_address(FILE *fp, u_int32_t ip)
+{
+ struct in_addr ipaddr;
+
+ ipaddr.s_addr = ip;
+ fprintf(fp, "%s", inet_ntoa(ipaddr));
+}
+
+/*
+ * Prints a string value for the given ip address.
+ */
+static void
+print_ip_ex_address(FILE *fp, u_int32_t type, u_int32_t *ipaddr)
+{
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ char dst[INET6_ADDRSTRLEN];
+
+ switch (type) {
+ case AU_IPv4:
+ ipv4.s_addr = (in_addr_t)(ipaddr[0]);
+ fprintf(fp, "%s", inet_ntop(AF_INET, &ipv4, dst,
+ INET6_ADDRSTRLEN));
+ break;
+
+ case AU_IPv6:
+ bcopy(ipaddr, &ipv6, sizeof(ipv6));
+ fprintf(fp, "%s", inet_ntop(AF_INET6, &ipv6, dst,
+ INET6_ADDRSTRLEN));
+ break;
+
+ default:
+ fprintf(fp, "invalid");
+ }
+}
+
+/*
+ * Prints return value as success or failure.
+ */
+static void
+print_retval(FILE *fp, u_char status, int oflags)
+{
+ int error;
+
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", status);
+ else {
+ /*
+ * Convert to a local error number and print the OS's version
+ * of the error string if possible. We may want to provide
+ * an au_strerror(3) in the future so that we can print
+ * strings for non-local errors.
+ */
+ if (au_bsm_to_errno(status, &error) == 0) {
+ if (error == 0)
+ fprintf(fp, "success");
+ else
+ fprintf(fp, "failure : %s", strerror(error));
+ } else
+ fprintf(fp, "failure: Unknown error: %d", status);
+ }
+}
+
+/*
+ * Prints the exit value.
+ */
+static void
+print_errval(FILE *fp, u_int32_t val)
+{
+
+ fprintf(fp, "Error %u", val);
+}
+
+/*
+ * Prints IPC type.
+ */
+static void
+print_ipctype(FILE *fp, u_char type, int oflags)
+{
+ if (oflags & AU_OFLAG_RAW)
+ fprintf(fp, "%u", type);
+ else {
+ if (type == AT_IPC_MSG)
+ fprintf(fp, "Message IPC");
+ else if (type == AT_IPC_SEM)
+ fprintf(fp, "Semaphore IPC");
+ else if (type == AT_IPC_SHM)
+ fprintf(fp, "Shared Memory IPC");
+ else
+ fprintf(fp, "%u", type);
+ }
+}
+
+/*
+ * Print XML header.
+ */
+void
+au_print_xml_header(FILE *outfp)
+{
+
+ fprintf(outfp, "<?xml version='1.0' ?>\n");
+ fprintf(outfp, "<audit>\n");
+}
+
+/*
+ * Print XML footer.
+ */
+void
+au_print_xml_footer(FILE *outfp)
+{
+
+ fprintf(outfp, "</audit>\n");
+}
+
+/*
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+static int
+fetch_header32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "header", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "version");
+ print_1_byte(fp, tok->tt.hdr32.version, "%u");
+ close_attr(fp);
+ open_attr(fp, "event");
+ print_event(fp, tok->tt.hdr32.e_type, oflags);
+ close_attr(fp);
+ open_attr(fp, "modifier");
+ print_evmod(fp, tok->tt.hdr32.e_mod, oflags);
+ close_attr(fp);
+ open_attr(fp, "time");
+ print_sec32(fp, tok->tt.hdr32.s, oflags);
+ close_attr(fp);
+ open_attr(fp, "msec");
+ print_msec32(fp, tok->tt.hdr32.ms, oflags);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr32.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr32.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr32.e_type, oflags);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr32.e_mod, oflags);
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.hdr32.s, oflags);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.hdr32.ms, oflags);
+ }
+}
+
+/*
+ * The Solaris specifications for AUE_HEADER32_EX seem to differ a bit
+ * depending on the bit of the specifications found. The OpenSolaris source
+ * code uses a 4-byte address length, followed by some number of bytes of
+ * address data. This contrasts with the Solaris audit.log.5 man page, which
+ * specifies a 1-byte length field. We use the Solaris 10 definition so that
+ * we can parse audit trails from that system.
+ *
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * [ Solaris man page: address type/length 1 byte]
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32/64-bits)
+ * nanoseconds of time 4 bytes/8 bytes (32/64-bits)
+ */
+static int
+fetch_header32_ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32_ex.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ad_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ bzero(tok->tt.hdr32_ex.addr, sizeof(tok->tt.hdr32_ex.addr));
+ switch (tok->tt.hdr32_ex.ad_type) {
+ case AU_IPv4:
+ READ_TOKEN_BYTES(buf, len, &tok->tt.hdr32_ex.addr[0],
+ sizeof(tok->tt.hdr32_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ break;
+
+ case AU_IPv6:
+ READ_TOKEN_BYTES(buf, len, tok->tt.hdr32_ex.addr,
+ sizeof(tok->tt.hdr32_ex.addr), tok->len, err);
+ break;
+ }
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header32_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "header_ex", oflags);
+ if (oflags & AU_OFLAG_RAW) {
+ open_attr(fp, "version");
+ print_1_byte(fp, tok->tt.hdr32_ex.version, "%u");
+ close_attr(fp);
+ open_attr(fp, "event");
+ print_event(fp, tok->tt.hdr32_ex.e_type, oflags);
+ close_attr(fp);
+ open_attr(fp, "modifier");
+ print_evmod(fp, tok->tt.hdr32_ex.e_mod, oflags);
+ close_attr(fp);
+ open_attr(fp, "host");
+ print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type,
+ tok->tt.hdr32_ex.addr);
+ close_attr(fp);
+ open_attr(fp, "time");
+ print_sec32(fp, tok->tt.hdr32_ex.s, oflags);
+ close_attr(fp);
+ open_attr(fp, "msec");
+ print_msec32(fp, tok->tt.hdr32_ex.ms, oflags);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr32_ex.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr32_ex.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr32_ex.e_type, oflags);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr32_ex.e_mod, oflags);
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type,
+ tok->tt.hdr32_ex.addr);
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.hdr32_ex.s, oflags);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.hdr32_ex.ms, oflags);
+ }
+}
+
+/*
+ * record byte count 4 bytes
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * version #
+ */
+static int
+fetch_header64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "header", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "version");
+ print_1_byte(fp, tok->tt.hdr64.version, "%u");
+ close_attr(fp);
+ open_attr(fp, "event");
+ print_event(fp, tok->tt.hdr64.e_type, oflags);
+ close_attr(fp);
+ open_attr(fp, "modifier");
+ print_evmod(fp, tok->tt.hdr64.e_mod, oflags);
+ close_attr(fp);
+ open_attr(fp, "time");
+ print_sec64(fp, tok->tt.hdr64.s, oflags);
+ close_attr(fp);
+ open_attr(fp, "msec");
+ print_msec64(fp, tok->tt.hdr64.ms, oflags);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr64.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr64.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr64.e_type, oflags);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr64.e_mod, oflags);
+ print_delim(fp, del);
+ print_sec64(fp, tok->tt.hdr64.s, oflags);
+ print_delim(fp, del);
+ print_msec64(fp, tok->tt.hdr64.ms, oflags);
+ }
+}
+
+/*
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * [ Solaris man page: address type/length 1 byte]
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32/64-bits)
+ * nanoseconds of time 4 bytes/8 bytes (32/64-bits)
+ *
+ * XXXAUDIT: See comment by fetch_header32_ex_tok() for details on the
+ * accuracy of the BSM spec.
+ */
+static int
+fetch_header64_ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64_ex.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.ad_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ bzero(tok->tt.hdr64_ex.addr, sizeof(tok->tt.hdr64_ex.addr));
+ switch (tok->tt.hdr64_ex.ad_type) {
+ case AU_IPv4:
+ READ_TOKEN_BYTES(buf, len, &tok->tt.hdr64_ex.addr[0],
+ sizeof(tok->tt.hdr64_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ break;
+
+ case AU_IPv6:
+ READ_TOKEN_BYTES(buf, len, tok->tt.hdr64_ex.addr,
+ sizeof(tok->tt.hdr64_ex.addr), tok->len, err);
+ break;
+ }
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header64_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "header_ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "version");
+ print_1_byte(fp, tok->tt.hdr64_ex.version, "%u");
+ close_attr(fp);
+ open_attr(fp, "event");
+ print_event(fp, tok->tt.hdr64_ex.e_type, oflags);
+ close_attr(fp);
+ open_attr(fp, "modifier");
+ print_evmod(fp, tok->tt.hdr64_ex.e_mod, oflags);
+ close_attr(fp);
+ open_attr(fp, "host");
+ print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type,
+ tok->tt.hdr64_ex.addr);
+ close_attr(fp);
+ open_attr(fp, "time");
+ print_sec64(fp, tok->tt.hdr64_ex.s, oflags);
+ close_attr(fp);
+ open_attr(fp, "msec");
+ print_msec64(fp, tok->tt.hdr64_ex.ms, oflags);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr64_ex.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr64_ex.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr64_ex.e_type, oflags);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr64_ex.e_mod, oflags);
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type,
+ tok->tt.hdr64_ex.addr);
+ print_delim(fp, del);
+ print_sec64(fp, tok->tt.hdr64_ex.s, oflags);
+ print_delim(fp, del);
+ print_msec64(fp, tok->tt.hdr64_ex.ms, oflags);
+ }
+}
+
+/*
+ * trailer magic 2 bytes
+ * record size 4 bytes
+ */
+static int
+fetch_trailer_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.trail.magic, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.trail.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_trailer_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "trailer", oflags);
+ if (!(oflags & AU_OFLAG_XML)) {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.trail.count, "%u");
+ }
+}
+
+/*
+ * argument # 1 byte
+ * argument value 4 bytes/8 bytes (32-bit/64-bit value)
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+static int
+fetch_arg32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arg32.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.arg32.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.arg32.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.arg32.text, tok->tt.arg32.len,
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arg32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "argument", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "arg-num");
+ print_1_byte(fp, tok->tt.arg32.no, "%u");
+ close_attr(fp);
+ open_attr(fp, "value");
+ print_4_bytes(fp, tok->tt.arg32.val, "0x%x");
+ close_attr(fp);
+ open_attr(fp, "desc");
+ print_string(fp, tok->tt.arg32.text, tok->tt.arg32.len);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arg32.no, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.arg32.val, "0x%x");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.arg32.text, tok->tt.arg32.len);
+ }
+}
+
+static int
+fetch_arg64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arg64.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.arg64.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.arg64.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.arg64.text, tok->tt.arg64.len,
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arg64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "argument", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "arg-num");
+ print_1_byte(fp, tok->tt.arg64.no, "%u");
+ close_attr(fp);
+ open_attr(fp, "value");
+ print_8_bytes(fp, tok->tt.arg64.val, "0x%llx");
+ close_attr(fp);
+ open_attr(fp, "desc");
+ print_string(fp, tok->tt.arg64.text, tok->tt.arg64.len);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arg64.no, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.arg64.val, "0x%llx");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.arg64.text, tok->tt.arg64.len);
+ }
+}
+
+/*
+ * how to print 1 byte
+ * basic unit 1 byte
+ * unit count 1 byte
+ * data items (depends on basic unit)
+ */
+static int
+fetch_arb_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+ int datasize;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.howtopr, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.bu, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.uc, tok->len, err);
+ if (err)
+ return (-1);
+
+ /*
+ * Determine the size of the basic unit.
+ */
+ switch(tok->tt.arb.bu) {
+ case AUR_BYTE:
+ /* case AUR_CHAR: */
+ datasize = AUR_BYTE_SIZE;
+ break;
+
+ case AUR_SHORT:
+ datasize = AUR_SHORT_SIZE;
+ break;
+
+ case AUR_INT32:
+ /* case AUR_INT: */
+ datasize = AUR_INT32_SIZE;
+ break;
+
+ case AUR_INT64:
+ datasize = AUR_INT64_SIZE;
+ break;
+
+ default:
+ return (-1);
+ }
+
+ SET_PTR(buf, len, tok->tt.arb.data, datasize * tok->tt.arb.uc,
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arb_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ char *str;
+ char *format;
+ size_t size;
+ int i;
+
+ print_tok_type(fp, tok->id, "arbitrary", oflags);
+ if (!(oflags & AU_OFLAG_XML))
+ print_delim(fp, del);
+
+ switch(tok->tt.arb.howtopr) {
+ case AUP_BINARY:
+ str = "binary";
+ format = " %c";
+ break;
+
+ case AUP_OCTAL:
+ str = "octal";
+ format = " %o";
+ break;
+
+ case AUP_DECIMAL:
+ str = "decimal";
+ format = " %d";
+ break;
+
+ case AUP_HEX:
+ str = "hex";
+ format = " %x";
+ break;
+
+ case AUP_STRING:
+ str = "string";
+ format = "%c";
+ break;
+
+ default:
+ return;
+ }
+
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "print");
+ fprintf(fp, "%s",str);
+ close_attr(fp);
+ } else {
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ }
+ switch(tok->tt.arb.bu) {
+ case AUR_BYTE:
+ /* case AUR_CHAR: */
+ str = "byte";
+ size = AUR_BYTE_SIZE;
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ fprintf(fp, "%zu", size);
+ close_attr(fp);
+ open_attr(fp, "count");
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ close_attr(fp);
+ fprintf(fp, ">");
+ for (i = 0; i<tok->tt.arb.uc; i++)
+ fprintf(fp, format, *(tok->tt.arb.data +
+ (size * i)));
+ close_tag(fp, tok->id);
+ } else {
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i<tok->tt.arb.uc; i++)
+ fprintf(fp, format, *(tok->tt.arb.data +
+ (size * i)));
+ }
+ break;
+
+ case AUR_SHORT:
+ str = "short";
+ size = AUR_SHORT_SIZE;
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ fprintf(fp, "%zu", size);
+ close_attr(fp);
+ open_attr(fp, "count");
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ close_attr(fp);
+ fprintf(fp, ">");
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int16_t *)(tok->tt.arb.data +
+ (size * i))));
+ close_tag(fp, tok->id);
+ } else {
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int16_t *)(tok->tt.arb.data +
+ (size * i))));
+ }
+ break;
+
+ case AUR_INT32:
+ /* case AUR_INT: */
+ str = "int";
+ size = AUR_INT32_SIZE;
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ fprintf(fp, "%zu", size);
+ close_attr(fp);
+ open_attr(fp, "count");
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ close_attr(fp);
+ fprintf(fp, ">");
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int32_t *)(tok->tt.arb.data +
+ (size * i))));
+ close_tag(fp, tok->id);
+ } else {
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int32_t *)(tok->tt.arb.data +
+ (size * i))));
+ }
+ break;
+
+ case AUR_INT64:
+ str = "int64";
+ size = AUR_INT64_SIZE;
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ fprintf(fp, "%zu", size);
+ close_attr(fp);
+ open_attr(fp, "count");
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ close_attr(fp);
+ fprintf(fp, ">");
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int64_t *)(tok->tt.arb.data +
+ (size * i))));
+ close_tag(fp, tok->id);
+ } else {
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i < tok->tt.arb.uc; i++)
+ fprintf(fp, format,
+ *((u_int64_t *)(tok->tt.arb.data +
+ (size * i))));
+ }
+ break;
+
+ default:
+ return;
+ }
+}
+
+/*
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+static int
+fetch_attr32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.fsid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr32.nid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.dev, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_attr32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "attribute", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "mode");
+ print_4_bytes(fp, tok->tt.attr32.mode, "%o");
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.attr32.uid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.attr32.gid, oflags);
+ close_attr(fp);
+ open_attr(fp, "fsid");
+ print_4_bytes(fp, tok->tt.attr32.fsid, "%u");
+ close_attr(fp);
+ open_attr(fp, "nodeid");
+ print_8_bytes(fp, tok->tt.attr32.nid, "%lld");
+ close_attr(fp);
+ open_attr(fp, "device");
+ print_4_bytes(fp, tok->tt.attr32.dev, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.mode, "%o");
+ print_delim(fp, del);
+ print_user(fp, tok->tt.attr32.uid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.attr32.gid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.fsid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr32.nid, "%lld");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.dev, "%u");
+ }
+}
+
+/*
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+static int
+fetch_attr64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.fsid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.nid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.dev, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_attr64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "attribute", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "mode");
+ print_4_bytes(fp, tok->tt.attr64.mode, "%o");
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.attr64.uid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.attr64.gid, oflags);
+ close_attr(fp);
+ open_attr(fp, "fsid");
+ print_4_bytes(fp, tok->tt.attr64.fsid, "%u");
+ close_attr(fp);
+ open_attr(fp, "nodeid");
+ print_8_bytes(fp, tok->tt.attr64.nid, "%lld");
+ close_attr(fp);
+ open_attr(fp, "device");
+ print_8_bytes(fp, tok->tt.attr64.dev, "%llu");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr64.mode, "%o");
+ print_delim(fp, del);
+ print_user(fp, tok->tt.attr64.uid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.attr64.gid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr64.fsid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr64.nid, "%lld");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr64.dev, "%llu");
+ }
+}
+
+/*
+ * status 4 bytes
+ * return value 4 bytes
+ */
+static int
+fetch_exit_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.exit.status, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.exit.ret, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_exit_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "exit", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "errval");
+ print_errval(fp, tok->tt.exit.status);
+ close_attr(fp);
+ open_attr(fp, "retval");
+ print_4_bytes(fp, tok->tt.exit.ret, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_errval(fp, tok->tt.exit.status);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.exit.ret, "%u");
+ }
+}
+
+/*
+ * count 4 bytes
+ * text count null-terminated string(s)
+ */
+static int
+fetch_execarg_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+ u_int32_t i;
+ u_char *bptr;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.execarg.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i < tok->tt.execarg.count; i++) {
+ bptr = buf + tok->len;
+ if (i < AUDIT_MAX_ARGS)
+ tok->tt.execarg.text[i] = (char*)bptr;
+
+ /* Look for a null terminated string. */
+ while (bptr && (*bptr != '\0')) {
+ if (++tok->len >= (u_int32_t)len)
+ return (-1);
+ bptr = buf + tok->len;
+ }
+ if (!bptr)
+ return (-1);
+ tok->len++; /* \0 character */
+ }
+ if (tok->tt.execarg.count > AUDIT_MAX_ARGS)
+ tok->tt.execarg.count = AUDIT_MAX_ARGS;
+
+ return (0);
+}
+
+static void
+print_execarg_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ u_int32_t i;
+
+ print_tok_type(fp, tok->id, "exec arg", oflags);
+ for (i = 0; i < tok->tt.execarg.count; i++) {
+ if (oflags & AU_OFLAG_XML) {
+ fprintf(fp, "<arg>");
+ print_xml_string(fp, tok->tt.execarg.text[i],
+ strlen(tok->tt.execarg.text[i]));
+ fprintf(fp, "</arg>");
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.execarg.text[i],
+ strlen(tok->tt.execarg.text[i]));
+ }
+ }
+ if (oflags & AU_OFLAG_XML)
+ close_tag(fp, tok->id);
+}
+
+/*
+ * count 4 bytes
+ * text count null-terminated string(s)
+ */
+static int
+fetch_execenv_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+ u_int32_t i;
+ u_char *bptr;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.execenv.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i < tok->tt.execenv.count; i++) {
+ bptr = buf + tok->len;
+ if (i < AUDIT_MAX_ENV)
+ tok->tt.execenv.text[i] = (char*)bptr;
+
+ /* Look for a null terminated string. */
+ while (bptr && (*bptr != '\0')) {
+ if (++tok->len >= (u_int32_t)len)
+ return (-1);
+ bptr = buf + tok->len;
+ }
+ if (!bptr)
+ return (-1);
+ tok->len++; /* \0 character */
+ }
+ if (tok->tt.execenv.count > AUDIT_MAX_ENV)
+ tok->tt.execenv.count = AUDIT_MAX_ENV;
+
+ return (0);
+}
+
+static void
+print_execenv_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ u_int32_t i;
+
+ print_tok_type(fp, tok->id, "exec env", oflags);
+ for (i = 0; i< tok->tt.execenv.count; i++) {
+ if (oflags & AU_OFLAG_XML) {
+ fprintf(fp, "<env>");
+ print_xml_string(fp, tok->tt.execenv.text[i],
+ strlen(tok->tt.execenv.text[i]));
+ fprintf(fp, "</env>");
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.execenv.text[i],
+ strlen(tok->tt.execenv.text[i]));
+ }
+ }
+ if (oflags & AU_OFLAG_XML)
+ close_tag(fp, tok->id);
+}
+
+/*
+ * seconds of time 4 bytes
+ * milliseconds of time 4 bytes
+ * file name len 2 bytes
+ * file pathname N bytes + 1 terminating NULL byte
+ */
+static int
+fetch_file_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.file.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.file.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.file.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.file.name, tok->tt.file.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_file_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "file", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "time");
+ print_sec32(fp, tok->tt.file.s, oflags);
+ close_attr(fp);
+ open_attr(fp, "msec");
+ print_msec32(fp, tok->tt.file.ms, oflags);
+ close_attr(fp);
+ fprintf(fp, ">");
+ print_string(fp, tok->tt.file.name, tok->tt.file.len);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.file.s, oflags);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.file.ms, oflags);
+ print_delim(fp, del);
+ print_string(fp, tok->tt.file.name, tok->tt.file.len);
+ }
+}
+
+/*
+ * number groups 2 bytes
+ * group list count * 4 bytes
+ */
+static int
+fetch_newgroups_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int i;
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.grps.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i<tok->tt.grps.no; i++) {
+ READ_TOKEN_U_INT32(buf, len, tok->tt.grps.list[i], tok->len,
+ err);
+ if (err)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+print_newgroups_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ int i;
+
+ print_tok_type(fp, tok->id, "group", oflags);
+ for (i = 0; i < tok->tt.grps.no; i++) {
+ if (oflags & AU_OFLAG_XML) {
+ fprintf(fp, "<gid>");
+ print_group(fp, tok->tt.grps.list[i], oflags);
+ fprintf(fp, "</gid>");
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_group(fp, tok->tt.grps.list[i], oflags);
+ }
+ }
+}
+
+/*
+ * Internet addr 4 bytes
+ */
+static int
+fetch_inaddr_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.inaddr.addr, sizeof(uint32_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+
+}
+
+static void
+print_inaddr_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "ip addr", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_ip_address(fp, tok->tt.inaddr.addr);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.inaddr.addr);
+ }
+}
+
+/*
+ * type 4 bytes
+ * address 16 bytes
+ */
+static int
+fetch_inaddr_ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.inaddr_ex.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.inaddr_ex.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.inaddr_ex.addr[0],
+ sizeof(tok->tt.inaddr_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.inaddr_ex.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.inaddr_ex.addr,
+ sizeof(tok->tt.inaddr_ex.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_inaddr_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "ip addr ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_ip_ex_address(fp, tok->tt.inaddr_ex.type,
+ tok->tt.inaddr_ex.addr);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.inaddr_ex.type,
+ tok->tt.inaddr_ex.addr);
+ }
+}
+
+/*
+ * ip header 20 bytes
+ */
+static int
+fetch_ip_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.tos, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.len, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.id, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.offset, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.ttl, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.prot, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.chksm, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.src, sizeof(tok->tt.ip.src),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.dest, sizeof(tok->tt.ip.dest),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ip_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "ip", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "version");
+ print_mem(fp, (u_char *)(&tok->tt.ip.version),
+ sizeof(u_char));
+ close_attr(fp);
+ open_attr(fp, "service_type");
+ print_mem(fp, (u_char *)(&tok->tt.ip.tos), sizeof(u_char));
+ close_attr(fp);
+ open_attr(fp, "len");
+ print_2_bytes(fp, ntohs(tok->tt.ip.len), "%u");
+ close_attr(fp);
+ open_attr(fp, "id");
+ print_2_bytes(fp, ntohs(tok->tt.ip.id), "%u");
+ close_attr(fp);
+ open_attr(fp, "offset");
+ print_2_bytes(fp, ntohs(tok->tt.ip.offset), "%u");
+ close_attr(fp);
+ open_attr(fp, "time_to_live");
+ print_mem(fp, (u_char *)(&tok->tt.ip.ttl), sizeof(u_char));
+ close_attr(fp);
+ open_attr(fp, "protocol");
+ print_mem(fp, (u_char *)(&tok->tt.ip.prot), sizeof(u_char));
+ close_attr(fp);
+ open_attr(fp, "cksum");
+ print_2_bytes(fp, ntohs(tok->tt.ip.chksm), "%u");
+ close_attr(fp);
+ open_attr(fp, "src_addr");
+ print_ip_address(fp, tok->tt.ip.src);
+ close_attr(fp);
+ open_attr(fp, "dest_addr");
+ print_ip_address(fp, tok->tt.ip.dest);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.version),
+ sizeof(u_char));
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.tos), sizeof(u_char));
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.ip.len), "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.ip.id), "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.ip.offset), "%u");
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.ttl), sizeof(u_char));
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.prot), sizeof(u_char));
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.ip.chksm), "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.ip.src);
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.ip.dest);
+ }
+}
+
+/*
+ * object ID type 1 byte
+ * Object ID 4 bytes
+ */
+static int
+fetch_ipc_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ipc.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipc.id, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ipc_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "IPC", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "ipc-type");
+ print_ipctype(fp, tok->tt.ipc.type, oflags);
+ close_attr(fp);
+ open_attr(fp, "ipc-id");
+ print_4_bytes(fp, tok->tt.ipc.id, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_ipctype(fp, tok->tt.ipc.type, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipc.id, "%u");
+ }
+}
+
+/*
+ * owner user id 4 bytes
+ * owner group id 4 bytes
+ * creator user id 4 bytes
+ * creator group id 4 bytes
+ * access mode 4 bytes
+ * slot seq 4 bytes
+ * key 4 bytes
+ */
+static int
+fetch_ipcperm_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.puid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.pgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.seq, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.key, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ipcperm_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "IPC perm", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.ipcperm.uid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.ipcperm.gid, oflags);
+ close_attr(fp);
+ open_attr(fp, "creator-uid");
+ print_user(fp, tok->tt.ipcperm.puid, oflags);
+ close_attr(fp);
+ open_attr(fp, "creator-gid");
+ print_group(fp, tok->tt.ipcperm.pgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "mode");
+ print_4_bytes(fp, tok->tt.ipcperm.mode, "%o");
+ close_attr(fp);
+ open_attr(fp, "seq");
+ print_4_bytes(fp, tok->tt.ipcperm.seq, "%u");
+ close_attr(fp);
+ open_attr(fp, "key");
+ print_4_bytes(fp, tok->tt.ipcperm.key, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.ipcperm.uid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.ipcperm.gid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.ipcperm.puid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.ipcperm.pgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.mode, "%o");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.seq, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.key, "%u");
+ }
+}
+
+/*
+ * port Ip address 2 bytes
+ */
+static int
+fetch_iport_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.iport.port, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_iport_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "ip port", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_2_bytes(fp, ntohs(tok->tt.iport.port), "%#x");
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.iport.port), "%#x");
+ }
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_opaque_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.opaque.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.opaque.data, tok->tt.opaque.size,
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_opaque_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "opaque", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_mem(fp, (u_char*)tok->tt.opaque.data,
+ tok->tt.opaque.size);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.opaque.size, "%u");
+ print_delim(fp, del);
+ print_mem(fp, (u_char*)tok->tt.opaque.data,
+ tok->tt.opaque.size);
+ }
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_path_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.path.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.path.path, tok->tt.path.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_path_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "path", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_string(fp, tok->tt.path.path, tok->tt.path.len);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.path.path, tok->tt.path.len);
+ }
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes
+ * machine id 4 bytes
+ */
+static int
+fetch_process32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.proc32.tid.addr,
+ sizeof(tok->tt.proc32.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "process", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.proc32.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.proc32.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.proc32.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.proc32.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.proc32.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.proc32.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.proc32.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_4_bytes(fp, tok->tt.proc32.tid.port, "%u");
+ print_ip_address(fp, tok->tt.proc32.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.proc32.tid.addr);
+ }
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 8 bytes
+ * machine id 4 bytes
+ */
+static int
+fetch_process64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.proc64.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.proc64.tid.addr,
+ sizeof(tok->tt.proc64.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ print_tok_type(fp, tok->id, "process", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.proc64.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.proc64.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.proc64.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.proc64.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.proc64.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.proc64.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.proc64.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_8_bytes(fp, tok->tt.proc64.tid.port, "%llu");
+ print_ip_address(fp, tok->tt.proc64.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc64.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc64.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc64.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc64.sid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.proc64.tid.port, "%llu");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.proc64.tid.addr);
+ }
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes
+ * address type-len 4 bytes
+ * machine address 16 bytes
+ */
+static int
+fetch_process32ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.proc32_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.proc32_ex.tid.addr[0],
+ sizeof(tok->tt.proc32_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.proc32_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.proc32_ex.tid.addr,
+ sizeof(tok->tt.proc32_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process32ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "process_ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.proc32_ex.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.proc32_ex.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.proc32_ex.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.proc32_ex.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.proc32_ex.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.proc32_ex.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.proc32_ex.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_4_bytes(fp, tok->tt.proc32_ex.tid.port, "%u");
+ print_ip_ex_address(fp, tok->tt.proc32_ex.tid.type,
+ tok->tt.proc32_ex.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32_ex.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32_ex.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.proc32_ex.tid.type,
+ tok->tt.proc32_ex.tid.addr);
+ }
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 8 bytes
+ * address type-len 4 bytes
+ * machine address 16 bytes
+ */
+static int
+fetch_process64ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.proc64_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.proc64_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.proc64_ex.tid.addr[0],
+ sizeof(tok->tt.proc64_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.proc64_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.proc64_ex.tid.addr,
+ sizeof(tok->tt.proc64_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process64ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ print_tok_type(fp, tok->id, "process_ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.proc64_ex.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.proc64_ex.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.proc64_ex.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.proc64_ex.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.proc64_ex.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.proc64_ex.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.proc64_ex.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_8_bytes(fp, tok->tt.proc64_ex.tid.port, "%llu");
+ print_ip_ex_address(fp, tok->tt.proc64_ex.tid.type,
+ tok->tt.proc64_ex.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64_ex.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64_ex.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc64_ex.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc64_ex.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc64_ex.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc64_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc64_ex.sid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.proc64_ex.tid.port, "%llu");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.proc64_ex.tid.type,
+ tok->tt.proc64_ex.tid.addr);
+ }
+}
+
+/*
+ * errno 1 byte
+ * return value 4 bytes
+ */
+static int
+fetch_return32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ret32.status, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ret32.ret, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_return32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "return", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp ,"errval");
+ print_retval(fp, tok->tt.ret32.status, oflags);
+ close_attr(fp);
+ open_attr(fp, "retval");
+ print_4_bytes(fp, tok->tt.ret32.ret, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_retval(fp, tok->tt.ret32.status, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ret32.ret, "%u");
+ }
+}
+
+static int
+fetch_return64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ret64.err, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.ret64.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_return64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "return", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "errval");
+ print_retval(fp, tok->tt.ret64.err, oflags);
+ close_attr(fp);
+ open_attr(fp, "retval");
+ print_8_bytes(fp, tok->tt.ret64.val, "%lld");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_retval(fp, tok->tt.ret64.err, oflags);
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.ret64.val, "%lld");
+ }
+}
+
+/*
+ * seq 4 bytes
+ */
+static int
+fetch_seq_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.seq.seqno, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_seq_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "sequence", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "seq-num");
+ print_4_bytes(fp, tok->tt.seq.seqno, "%u");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.seq.seqno, "%u");
+ }
+}
+
+/*
+ * socket family 2 bytes
+ * local port 2 bytes
+ * socket address 4 bytes
+ */
+static int
+fetch_sock_inet32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet_ex32.family, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.port,
+ sizeof(uint16_t), tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.addr,
+ sizeof(tok->tt.sockinet_ex32.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_sock_inet32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "socket-inet", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u");
+ close_attr(fp);
+ open_attr(fp, "port");
+ print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u");
+ close_attr(fp);
+ open_attr(fp, "addr");
+ print_ip_address(fp, tok->tt.sockinet_ex32.addr[0]);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.sockinet_ex32.addr[0]);
+ }
+}
+
+/*
+ * socket family 2 bytes
+ * local port 2 bytes
+ * socket address 16 bytes
+ */
+static int
+fetch_sock_inet128_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet_ex32.family, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.port,
+ sizeof(uint16_t), tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.addr,
+ sizeof(tok->tt.sockinet_ex32.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_sock_inet128_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "socket-inet6", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u");
+ close_attr(fp);
+ open_attr(fp, "port");
+ print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u");
+ close_attr(fp);
+ open_attr(fp, "addr");
+ print_ip_ex_address(fp, AU_IPv6, tok->tt.sockinet_ex32.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, AU_IPv6, tok->tt.sockinet_ex32.addr);
+ }
+}
+
+/*
+ * socket family 2 bytes
+ * path (up to) 104 bytes + NULL (NULL terminated string).
+ */
+static int
+fetch_sock_unix_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+ u_char *p;
+ int slen;
+
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockunix.family, tok->len, err);
+ if (err)
+ return (-1);
+
+ /* slen = strnlen((buf + tok->len), 104) + 1; */
+ p = (u_char *)memchr((const void *)(buf + tok->len), '\0', 104);
+ slen = (p ? (int)(p - (buf + tok->len)) : 104) + 1;
+
+ READ_TOKEN_BYTES(buf, len, tok->tt.sockunix.path, slen, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_sock_unix_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "socket-unix", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ print_2_bytes(fp, tok->tt.sockunix.family, "%u");
+ close_attr(fp);
+ open_attr(fp, "port");
+ close_attr(fp);
+ open_attr(fp, "addr");
+ print_string(fp, tok->tt.sockunix.path,
+ strlen(tok->tt.sockunix.path));
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockunix.family, "%u");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.sockunix.path,
+ strlen(tok->tt.sockunix.path));
+ }
+}
+
+/*
+ * socket type 2 bytes
+ * local port 2 bytes
+ * local address 4 bytes
+ * remote port 2 bytes
+ * remote address 4 bytes
+ */
+static int
+fetch_socket_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_port, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr,
+ sizeof(tok->tt.socket.l_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.r_port, sizeof(uint16_t),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr,
+ sizeof(tok->tt.socket.r_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_socket_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "socket", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "sock_type");
+ print_2_bytes(fp, tok->tt.socket.type, "%u");
+ close_attr(fp);
+ open_attr(fp, "lport");
+ print_2_bytes(fp, ntohs(tok->tt.socket.l_port), "%u");
+ close_attr(fp);
+ open_attr(fp, "laddr");
+ print_ip_address(fp, tok->tt.socket.l_addr);
+ close_attr(fp);
+ open_attr(fp, "fport");
+ print_2_bytes(fp, ntohs(tok->tt.socket.r_port), "%u");
+ close_attr(fp);
+ open_attr(fp, "faddr");
+ print_ip_address(fp, tok->tt.socket.r_addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket.type, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.socket.l_port), "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket.l_addr);
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.socket.r_port), "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket.r_addr);
+ }
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine id 4 bytes
+ */
+static int
+fetch_subject32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj32.tid.addr,
+ sizeof(tok->tt.subj32.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "subject", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.subj32.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.subj32.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.subj32.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.subj32.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.subj32.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp,"pid");
+ print_4_bytes(fp, tok->tt.subj32.pid, "%u");
+ close_attr(fp);
+ open_attr(fp,"sid");
+ print_4_bytes(fp, tok->tt.subj32.sid, "%u");
+ close_attr(fp);
+ open_attr(fp,"tid");
+ print_4_bytes(fp, tok->tt.subj32.tid.port, "%u ");
+ print_ip_address(fp, tok->tt.subj32.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.subj32.tid.addr);
+ }
+}
+
+static void
+print_upriv_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "use of privilege", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "status");
+ if (tok->tt.priv.sorf)
+ (void) fprintf(fp, "successful use of priv");
+ else
+ (void) fprintf(fp, "failed use of priv");
+ close_attr(fp);
+ open_attr(fp, "name");
+ print_string(fp, tok->tt.priv.priv, tok->tt.priv.privstrlen);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ if (tok->tt.priv.sorf)
+ (void) fprintf(fp, "successful use of priv");
+ else
+ (void) fprintf(fp, "failed use of priv");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.priv.priv, tok->tt.priv.privstrlen);
+ }
+}
+
+/*
+ * status 1 byte
+ * privstrlen 2 bytes
+ * priv N bytes + 1 (\0 byte)
+ */
+static int
+fetch_priv_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.priv.sorf, tok->len, err);
+ if (err)
+ return (-1);
+ READ_TOKEN_U_INT16(buf, len, tok->tt.priv.privstrlen, tok->len, err);
+ if (err)
+ return (-1);
+ SET_PTR((char *)buf, len, tok->tt.priv.priv, tok->tt.priv.privstrlen,
+ tok->len, err);
+ if (err)
+ return (-1);
+ return (0);
+}
+
+/*
+ * privtstrlen 1 byte
+ * privtstr N bytes + 1
+ * privstrlen 1 byte
+ * privstr N bytes + 1
+ */
+static int
+fetch_privset_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.privset.privtstrlen,
+ tok->len, err);
+ if (err)
+ return (-1);
+ SET_PTR((char *)buf, len, tok->tt.privset.privtstr,
+ tok->tt.privset.privtstrlen, tok->len, err);
+ if (err)
+ return (-1);
+ READ_TOKEN_U_INT16(buf, len, tok->tt.privset.privstrlen,
+ tok->len, err);
+ if (err)
+ return (-1);
+ SET_PTR((char *)buf, len, tok->tt.privset.privstr,
+ tok->tt.privset.privstrlen, tok->len, err);
+ if (err)
+ return (-1);
+ return (0);
+}
+
+static void
+print_privset_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "privilege", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "type");
+ print_string(fp, tok->tt.privset.privtstr,
+ tok->tt.privset.privtstrlen);
+ close_attr(fp);
+ open_attr(fp, "priv");
+ print_string(fp, tok->tt.privset.privstr,
+ tok->tt.privset.privstrlen);
+ close_attr(fp);
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.privset.privtstr,
+ tok->tt.privset.privtstrlen);
+ print_delim(fp, del);
+ print_string(fp, tok->tt.privset.privstr,
+ tok->tt.privset.privstrlen);
+ }
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine id 4 bytes
+ */
+static int
+fetch_subject64_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.subj64.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj64.tid.addr,
+ sizeof(tok->tt.subj64.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "subject", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.subj64.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.subj64.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.subj64.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.subj64.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.subj64.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.subj64.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.subj64.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_8_bytes(fp, tok->tt.subj64.tid.port, "%llu");
+ print_ip_address(fp, tok->tt.subj64.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64.sid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.subj64.tid.port, "%llu");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.subj64.tid.addr);
+ }
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes
+ * type 4 bytes
+ * machine id 16 bytes
+ */
+static int
+fetch_subject32ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.subj32_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj32_ex.tid.addr[0],
+ sizeof(tok->tt.subj32_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.subj32_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.subj32_ex.tid.addr,
+ sizeof(tok->tt.subj32_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject32ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "subject_ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.subj32_ex.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.subj32_ex.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.subj32_ex.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.subj32_ex.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.subj32_ex.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.subj32_ex.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.subj32_ex.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_4_bytes(fp, tok->tt.subj32_ex.tid.port, "%u");
+ print_ip_ex_address(fp, tok->tt.subj32_ex.tid.type,
+ tok->tt.subj32_ex.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32_ex.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32_ex.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.subj32_ex.tid.type,
+ tok->tt.subj32_ex.tid.addr);
+ }
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 8 bytes
+ * type 4 bytes
+ * machine id 16 bytes
+ */
+static int
+fetch_subject64ex_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.subj64_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.subj64_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj64_ex.tid.addr[0],
+ sizeof(tok->tt.subj64_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.subj64_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.subj64_ex.tid.addr,
+ sizeof(tok->tt.subj64_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject64ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+ print_tok_type(fp, tok->id, "subject_ex", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "audit-uid");
+ print_user(fp, tok->tt.subj64_ex.auid, oflags);
+ close_attr(fp);
+ open_attr(fp, "uid");
+ print_user(fp, tok->tt.subj64_ex.euid, oflags);
+ close_attr(fp);
+ open_attr(fp, "gid");
+ print_group(fp, tok->tt.subj64_ex.egid, oflags);
+ close_attr(fp);
+ open_attr(fp, "ruid");
+ print_user(fp, tok->tt.subj64_ex.ruid, oflags);
+ close_attr(fp);
+ open_attr(fp, "rgid");
+ print_group(fp, tok->tt.subj64_ex.rgid, oflags);
+ close_attr(fp);
+ open_attr(fp, "pid");
+ print_4_bytes(fp, tok->tt.subj64_ex.pid, "%u");
+ close_attr(fp);
+ open_attr(fp, "sid");
+ print_4_bytes(fp, tok->tt.subj64_ex.sid, "%u");
+ close_attr(fp);
+ open_attr(fp, "tid");
+ print_8_bytes(fp, tok->tt.subj64_ex.tid.port, "%llu");
+ print_ip_ex_address(fp, tok->tt.subj64_ex.tid.type,
+ tok->tt.subj64_ex.tid.addr);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64_ex.auid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64_ex.euid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64_ex.egid, oflags);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64_ex.ruid, oflags);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64_ex.rgid, oflags);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64_ex.sid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.subj64_ex.tid.port, "%llu");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.subj64_ex.tid.type,
+ tok->tt.subj64_ex.tid.addr);
+ }
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_text_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.text.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR((char*)buf, len, tok->tt.text.text, tok->tt.text.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_text_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "text", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ print_string(fp, tok->tt.text.text, tok->tt.text.len);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.text.text, tok->tt.text.len);
+ }
+}
+
+/*
+ * socket domain 2 bytes
+ * socket type 2 bytes
+ * address type 2 bytes
+ * local port 2 bytes
+ * local Internet address 4/16 bytes
+ * remote port 2 bytes
+ * remote Internet address 4/16 bytes
+ */
+static int
+fetch_socketex32_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.domain, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.atype, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.socket_ex32.atype != AU_IPv4 &&
+ tok->tt.socket_ex32.atype != AU_IPv6)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_port,
+ sizeof(uint16_t), tok->len, err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.socket_ex32.atype == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_addr,
+ sizeof(tok->tt.socket_ex32.l_addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_addr,
+ sizeof(tok->tt.socket_ex32.l_addr), tok->len, err);
+ if (err)
+ return (-1);
+ }
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_port,
+ sizeof(uint16_t), tok->len, err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.socket_ex32.atype == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_addr,
+ sizeof(tok->tt.socket_ex32.r_addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_addr,
+ sizeof(tok->tt.socket_ex32.r_addr), tok->len, err);
+ if (err)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+print_socketex32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ /*
+ * This print routine prints BSM constant space domains and socket
+ * types rather than converting them. If we add string printers for
+ * these constants in the future, we may want to call conversion
+ * routines.
+ */
+ print_tok_type(fp, tok->id, "socket", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "sock_dom");
+ print_2_bytes(fp, tok->tt.socket_ex32.domain, "%#x");
+ close_attr(fp);
+ open_attr(fp, "sock_type");
+ print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x");
+ close_attr(fp);
+ open_attr(fp, "lport");
+ print_2_bytes(fp, ntohs(tok->tt.socket_ex32.l_port), "%#x");
+ close_attr(fp);
+ open_attr(fp, "laddr");
+ print_ip_ex_address(fp, tok->tt.socket_ex32.atype,
+ tok->tt.socket_ex32.l_addr);
+ close_attr(fp);
+ open_attr(fp, "faddr");
+ print_ip_ex_address(fp, tok->tt.socket_ex32.atype,
+ tok->tt.socket_ex32.r_addr);
+ close_attr(fp);
+ open_attr(fp, "fport");
+ print_2_bytes(fp, ntohs(tok->tt.socket_ex32.r_port), "%#x");
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket_ex32.domain, "%#x");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x");
+ print_delim(fp, del);
+ print_2_bytes(fp, ntohs(tok->tt.socket_ex32.l_port), "%#x");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.socket_ex32.atype,
+ tok->tt.socket_ex32.l_addr);
+ print_delim(fp, del);
+ print_4_bytes(fp, ntohs(tok->tt.socket_ex32.r_port), "%#x");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.socket_ex32.atype,
+ tok->tt.socket_ex32.r_addr);
+ }
+}
+
+static int
+fetch_invalid_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+ int recoversize;
+
+ recoversize = len - (tok->len + AUDIT_TRAILER_SIZE);
+ if (recoversize <= 0)
+ return (-1);
+
+ tok->tt.invalid.length = recoversize;
+
+ SET_PTR((char*)buf, len, tok->tt.invalid.data, recoversize, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_invalid_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ if (!(oflags & AU_OFLAG_XML)) {
+ print_tok_type(fp, tok->id, "unknown", oflags);
+ print_delim(fp, del);
+ print_mem(fp, (u_char*)tok->tt.invalid.data,
+ tok->tt.invalid.length);
+ }
+}
+
+
+/*
+ * size 2 bytes;
+ * zonename size bytes;
+ */
+static int
+fetch_zonename_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.zonename.len, tok->len, err);
+ if (err)
+ return (-1);
+ SET_PTR((char *)buf, len, tok->tt.zonename.zonename, tok->tt.zonename.len,
+ tok->len, err);
+ if (err)
+ return (-1);
+ return (0);
+}
+
+static void
+print_zonename_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ print_tok_type(fp, tok->id, "zone", oflags);
+ if (oflags & AU_OFLAG_XML) {
+ open_attr(fp, "name");
+ print_string(fp, tok->tt.zonename.zonename,
+ tok->tt.zonename.len);
+ close_attr(fp);
+ close_tag(fp, tok->id);
+ } else {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.zonename.zonename,
+ tok->tt.zonename.len);
+ }
+}
+
+/*
+ * Reads the token beginning at buf into tok.
+ */
+int
+au_fetch_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+
+ if (len <= 0)
+ return (-1);
+
+ tok->len = 1;
+ tok->data = buf;
+ tok->id = *buf;
+
+ switch(tok->id) {
+ case AUT_HEADER32:
+ return (fetch_header32_tok(tok, buf, len));
+
+ case AUT_HEADER32_EX:
+ return (fetch_header32_ex_tok(tok, buf, len));
+
+ case AUT_HEADER64:
+ return (fetch_header64_tok(tok, buf, len));
+
+ case AUT_HEADER64_EX:
+ return (fetch_header64_ex_tok(tok, buf, len));
+
+ case AUT_TRAILER:
+ return (fetch_trailer_tok(tok, buf, len));
+
+ case AUT_ARG32:
+ return (fetch_arg32_tok(tok, buf, len));
+
+ case AUT_ARG64:
+ return (fetch_arg64_tok(tok, buf, len));
+
+ case AUT_ATTR32:
+ return (fetch_attr32_tok(tok, buf, len));
+
+ case AUT_ATTR64:
+ return (fetch_attr64_tok(tok, buf, len));
+
+ case AUT_EXIT:
+ return (fetch_exit_tok(tok, buf, len));
+
+ case AUT_EXEC_ARGS:
+ return (fetch_execarg_tok(tok, buf, len));
+
+ case AUT_EXEC_ENV:
+ return (fetch_execenv_tok(tok, buf, len));
+
+ case AUT_OTHER_FILE32:
+ return (fetch_file_tok(tok, buf, len));
+
+ case AUT_NEWGROUPS:
+ return (fetch_newgroups_tok(tok, buf, len));
+
+ case AUT_IN_ADDR:
+ return (fetch_inaddr_tok(tok, buf, len));
+
+ case AUT_IN_ADDR_EX:
+ return (fetch_inaddr_ex_tok(tok, buf, len));
+
+ case AUT_IP:
+ return (fetch_ip_tok(tok, buf, len));
+
+ case AUT_IPC:
+ return (fetch_ipc_tok(tok, buf, len));
+
+ case AUT_IPC_PERM:
+ return (fetch_ipcperm_tok(tok, buf, len));
+
+ case AUT_IPORT:
+ return (fetch_iport_tok(tok, buf, len));
+
+ case AUT_OPAQUE:
+ return (fetch_opaque_tok(tok, buf, len));
+
+ case AUT_PATH:
+ return (fetch_path_tok(tok, buf, len));
+
+ case AUT_PROCESS32:
+ return (fetch_process32_tok(tok, buf, len));
+
+ case AUT_PROCESS32_EX:
+ return (fetch_process32ex_tok(tok, buf, len));
+
+ case AUT_PROCESS64:
+ return (fetch_process64_tok(tok, buf, len));
+
+ case AUT_PROCESS64_EX:
+ return (fetch_process64ex_tok(tok, buf, len));
+
+ case AUT_RETURN32:
+ return (fetch_return32_tok(tok, buf, len));
+
+ case AUT_RETURN64:
+ return (fetch_return64_tok(tok, buf, len));
+
+ case AUT_SEQ:
+ return (fetch_seq_tok(tok, buf, len));
+
+ case AUT_SOCKET:
+ return (fetch_socket_tok(tok, buf, len));
+
+ case AUT_SOCKINET32:
+ return (fetch_sock_inet32_tok(tok, buf, len));
+
+ case AUT_SOCKUNIX:
+ return (fetch_sock_unix_tok(tok, buf, len));
+
+ case AUT_SOCKINET128:
+ return (fetch_sock_inet128_tok(tok, buf, len));
+
+ case AUT_SUBJECT32:
+ return (fetch_subject32_tok(tok, buf, len));
+
+ case AUT_SUBJECT32_EX:
+ return (fetch_subject32ex_tok(tok, buf, len));
+
+ case AUT_SUBJECT64:
+ return (fetch_subject64_tok(tok, buf, len));
+
+ case AUT_SUBJECT64_EX:
+ return (fetch_subject64ex_tok(tok, buf, len));
+
+ case AUT_TEXT:
+ return (fetch_text_tok(tok, buf, len));
+
+ case AUT_SOCKET_EX:
+ return (fetch_socketex32_tok(tok, buf, len));
+
+ case AUT_DATA:
+ return (fetch_arb_tok(tok, buf, len));
+
+ case AUT_ZONENAME:
+ return (fetch_zonename_tok(tok, buf, len));
+
+ case AUT_UPRIV:
+ return (fetch_priv_tok(tok, buf, len));
+
+ case AUT_PRIV:
+ return (fetch_privset_tok(tok, buf, len));
+
+ default:
+ return (fetch_invalid_tok(tok, buf, len));
+ }
+}
+
+void
+au_print_flags_tok(FILE *outfp, tokenstr_t *tok, char *del, int oflags)
+{
+
+ switch(tok->id) {
+ case AUT_HEADER32:
+ print_header32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_HEADER32_EX:
+ print_header32_ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_HEADER64:
+ print_header64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_HEADER64_EX:
+ print_header64_ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_TRAILER:
+ print_trailer_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_ARG32:
+ print_arg32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_ARG64:
+ print_arg64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_DATA:
+ print_arb_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_ATTR32:
+ print_attr32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_ATTR64:
+ print_attr64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_EXIT:
+ print_exit_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_EXEC_ARGS:
+ print_execarg_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_EXEC_ENV:
+ print_execenv_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_OTHER_FILE32:
+ print_file_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_NEWGROUPS:
+ print_newgroups_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IN_ADDR:
+ print_inaddr_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IN_ADDR_EX:
+ print_inaddr_ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IP:
+ print_ip_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IPC:
+ print_ipc_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IPC_PERM:
+ print_ipcperm_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_IPORT:
+ print_iport_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_OPAQUE:
+ print_opaque_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PATH:
+ print_path_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PROCESS32:
+ print_process32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PROCESS32_EX:
+ print_process32ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PROCESS64:
+ print_process64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PROCESS64_EX:
+ print_process64ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_RETURN32:
+ print_return32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_RETURN64:
+ print_return64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SEQ:
+ print_seq_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SOCKET:
+ print_socket_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SOCKINET32:
+ print_sock_inet32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SOCKUNIX:
+ print_sock_unix_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SOCKINET128:
+ print_sock_inet128_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SUBJECT32:
+ print_subject32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SUBJECT64:
+ print_subject64_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SUBJECT32_EX:
+ print_subject32ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SUBJECT64_EX:
+ print_subject64ex_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_TEXT:
+ print_text_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_SOCKET_EX:
+ print_socketex32_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_ZONENAME:
+ print_zonename_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_UPRIV:
+ print_upriv_tok(outfp, tok, del, oflags);
+ return;
+
+ case AUT_PRIV:
+ print_privset_tok(outfp, tok, del, oflags);
+ return;
+
+ default:
+ print_invalid_tok(outfp, tok, del, oflags);
+ }
+}
+
+/*
+ * 'prints' the token out to outfp.
+ */
+void
+au_print_tok(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm)
+{
+ int oflags = AU_OFLAG_NONE;
+
+ if (raw)
+ oflags |= AU_OFLAG_RAW;
+ if (sfrm)
+ oflags |= AU_OFLAG_SHORT;
+
+ au_print_flags_tok(outfp, tok, del, oflags);
+}
+
+/*
+ * 'prints' the token out to outfp in XML format.
+ */
+void
+au_print_tok_xml(FILE *outfp, tokenstr_t *tok, char *del, char raw,
+ char sfrm)
+{
+ int oflags = AU_OFLAG_XML;
+
+ if (raw)
+ oflags |= AU_OFLAG_RAW;
+ if (sfrm)
+ oflags |= AU_OFLAG_SHORT;
+
+ au_print_flags_tok(outfp, tok, del, oflags);
+}
+
+/*
+ * Read a record from the file pointer, store data in buf memory for buf is
+ * also allocated in this function and has to be free'd outside this call.
+ *
+ * au_read_rec() handles two possibilities: a stand-alone file token, or a
+ * complete audit record.
+ *
+ * XXXRW: Note that if we hit an error, we leave the stream in an unusable
+ * state, because it will be partly offset into a record. We should rewind
+ * or do something more intelligent. Particularly interesting is the case
+ * where we perform a partial read of a record from a non-blockable file
+ * descriptor. We should return the partial read and continue...?
+ */
+int
+au_read_rec(FILE *fp, u_char **buf)
+{
+ u_char *bptr;
+ u_int32_t recsize;
+ u_int32_t bytestoread;
+ u_char type;
+
+ u_int32_t sec, msec;
+ u_int16_t filenamelen;
+
+ type = fgetc(fp);
+
+ switch (type) {
+ case AUT_HEADER32:
+ case AUT_HEADER32_EX:
+ case AUT_HEADER64:
+ case AUT_HEADER64_EX:
+ /* read the record size from the token */
+ if (fread(&recsize, 1, sizeof(u_int32_t), fp) <
+ sizeof(u_int32_t)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ recsize = be32toh(recsize);
+
+ /* Check for recsize sanity */
+ if (recsize < (sizeof(u_int32_t) + sizeof(u_char))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *buf = calloc(recsize, sizeof(u_char));
+ if (*buf == NULL)
+ return (-1);
+ bptr = *buf;
+
+ /* store the token contents already read, back to the buffer*/
+ *bptr = type;
+ bptr++;
+ be32enc(bptr, recsize);
+ bptr += sizeof(u_int32_t);
+
+ /* now read remaining record bytes */
+ bytestoread = recsize - (sizeof(u_int32_t) + sizeof(u_char));
+
+ if (fread(bptr, 1, bytestoread, fp) < bytestoread) {
+ free(*buf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
+
+ case AUT_OTHER_FILE32:
+ /*
+ * The file token is variable-length, as it includes a
+ * pathname. As a result, we have to read incrementally
+ * until we know the total length, then allocate space and
+ * read the rest.
+ */
+ if (fread(&sec, 1, sizeof(sec), fp) < sizeof(sec)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (fread(&msec, 1, sizeof(msec), fp) < sizeof(msec)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (fread(&filenamelen, 1, sizeof(filenamelen), fp) <
+ sizeof(filenamelen)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ recsize = sizeof(type) + sizeof(sec) + sizeof(msec) +
+ sizeof(filenamelen) + ntohs(filenamelen);
+ *buf = malloc(recsize);
+ if (*buf == NULL)
+ return (-1);
+ bptr = *buf;
+
+ bcopy(&type, bptr, sizeof(type));
+ bptr += sizeof(type);
+ bcopy(&sec, bptr, sizeof(sec));
+ bptr += sizeof(sec);
+ bcopy(&msec, bptr, sizeof(msec));
+ bptr += sizeof(msec);
+ bcopy(&filenamelen, bptr, sizeof(filenamelen));
+ bptr += sizeof(filenamelen);
+
+ if (fread(bptr, 1, ntohs(filenamelen), fp) <
+ ntohs(filenamelen)) {
+ free(buf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (recsize);
+}
diff --git a/contrib/openbsm/libbsm/bsm_mask.c b/contrib/openbsm/libbsm/bsm_mask.c
new file mode 100644
index 0000000..42e4e71
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_mask.c
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * Copyright (c) 2005 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.
+ * 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>
+#ifdef HAVE_FULL_QUEUE_H
+#include <sys/queue.h>
+#else /* !HAVE_FULL_QUEUE_H */
+#include <compat/queue.h>
+#endif /* !HAVE_FULL_QUEUE_H */
+
+#include <bsm/libbsm.h>
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+/* MT-Safe */
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+static int firsttime = 1;
+
+/*
+ * XXX ev_cache, once created, sticks around until the calling program exits.
+ * This may or may not be a problem as far as absolute memory usage goes, but
+ * at least there don't appear to be any leaks in using the cache.
+ *
+ * XXXRW: Note that despite (mutex), load_event_table() could race with
+ * other consumers of the getauevents() API.
+ */
+struct audit_event_map {
+ char ev_name[AU_EVENT_NAME_MAX];
+ char ev_desc[AU_EVENT_DESC_MAX];
+ struct au_event_ent ev;
+ LIST_ENTRY(audit_event_map) ev_list;
+};
+static LIST_HEAD(, audit_event_map) ev_cache;
+
+static struct audit_event_map *
+audit_event_map_alloc(void)
+{
+ struct audit_event_map *aemp;
+
+ aemp = malloc(sizeof(*aemp));
+ if (aemp == NULL)
+ return (aemp);
+ bzero(aemp, sizeof(*aemp));
+ aemp->ev.ae_name = aemp->ev_name;
+ aemp->ev.ae_desc = aemp->ev_desc;
+ return (aemp);
+}
+
+static void
+audit_event_map_free(struct audit_event_map *aemp)
+{
+
+ free(aemp);
+}
+
+/*
+ * When reading into the cache fails, we need to flush the entire cache to
+ * prevent it from containing some but not all records.
+ */
+static void
+flush_cache(void)
+{
+ struct audit_event_map *aemp;
+
+ /* XXX: Would assert 'mutex'. */
+
+ while ((aemp = LIST_FIRST(&ev_cache)) != NULL) {
+ LIST_REMOVE(aemp, ev_list);
+ audit_event_map_free(aemp);
+ }
+}
+
+static int
+load_event_table(void)
+{
+ struct audit_event_map *aemp;
+ struct au_event_ent *ep;
+
+ /*
+ * XXX: Would assert 'mutex'.
+ * Loading of the cache happens only once; dont check if cache is
+ * already loaded.
+ */
+ LIST_INIT(&ev_cache);
+ setauevent(); /* Rewind to beginning of entries. */
+ do {
+ aemp = audit_event_map_alloc();
+ if (aemp == NULL) {
+ flush_cache();
+ return (-1);
+ }
+ ep = getauevent_r(&aemp->ev);
+ if (ep != NULL)
+ LIST_INSERT_HEAD(&ev_cache, aemp, ev_list);
+ else
+ audit_event_map_free(aemp);
+ } while (ep != NULL);
+ return (1);
+}
+
+/*
+ * Read the event with the matching event number from the cache.
+ */
+static struct au_event_ent *
+read_from_cache(au_event_t event)
+{
+ struct audit_event_map *elem;
+
+ /* XXX: Would assert 'mutex'. */
+
+ LIST_FOREACH(elem, &ev_cache, ev_list) {
+ if (elem->ev.ae_number == event)
+ return (&elem->ev);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Check if the audit event is preselected against the preselection mask.
+ */
+int
+au_preselect(au_event_t event, au_mask_t *mask_p, int sorf, int flag)
+{
+ struct au_event_ent *ev;
+ au_class_t effmask = 0;
+
+ if (mask_p == NULL)
+ return (-1);
+
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ if (firsttime) {
+ firsttime = 0;
+ if ( -1 == load_event_table()) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ }
+ switch (flag) {
+ case AU_PRS_REREAD:
+ flush_cache();
+ if (load_event_table() == -1) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ ev = read_from_cache(event);
+ break;
+ case AU_PRS_USECACHE:
+ ev = read_from_cache(event);
+ break;
+ default:
+ ev = NULL;
+ }
+ if (ev == NULL) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (-1);
+ }
+ if (sorf & AU_PRS_SUCCESS)
+ effmask |= (mask_p->am_success & ev->ae_class);
+ if (sorf & AU_PRS_FAILURE)
+ effmask |= (mask_p->am_failure & ev->ae_class);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ if (effmask != 0)
+ return (1);
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_notify.c b/contrib/openbsm/libbsm/bsm_notify.c
new file mode 100644
index 0000000..a2dda74
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_notify.c
@@ -0,0 +1,179 @@
+/*-
+ * 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.
+ */
+
+/*
+ * Based on sample code from Marc Majka.
+ */
+#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 <bsm/audit_internal.h>
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <string.h>
+#include <syslog.h>
+
+
+#ifdef __APPLE__
+#include <notify.h>
+/* If 1, assumes a kernel that sends the right notification. */
+#define AUDIT_NOTIFICATION_ENABLED 1
+
+#if AUDIT_NOTIFICATION_ENABLED
+static int token = 0;
+#endif /* AUDIT_NOTIFICATION_ENABLED */
+
+static int au_cond = AUC_UNSET; /* <bsm/audit.h> */
+
+uint32_t
+au_notify_initialize(void)
+{
+#if AUDIT_NOTIFICATION_ENABLED
+ uint32_t status;
+ int ignore_first;
+
+ status = notify_register_check(__BSM_INTERNAL_NOTIFY_KEY, &token);
+ if (status != NOTIFY_STATUS_OK)
+ return (status);
+ status = notify_check(token, &ignore_first);
+ if (status != NOTIFY_STATUS_OK)
+ return (status);
+#endif
+
+ if (audit_get_cond(&au_cond) != 0) {
+ syslog(LOG_ERR, "Initial audit status check failed (%s)",
+ strerror(errno));
+ if (errno == ENOSYS) /* auditon() unimplemented. */
+ return (AU_UNIMPL);
+ return (NOTIFY_STATUS_FAILED); /* Is there a better code? */
+ }
+ return (NOTIFY_STATUS_OK);
+}
+
+int
+au_notify_terminate(void)
+{
+
+#if AUDIT_NOTIFICATION_ENABLED
+ return ((notify_cancel(token) == NOTIFY_STATUS_OK) ? 0 : -1);
+#else
+ return (0);
+#endif
+}
+
+/*
+ * On error of any notify(3) call, reset 'au_cond' to ensure we re-run
+ * au_notify_initialize() next time 'round--but assume auditing is on. This
+ * is a slight performance hit if auditing is off, but at least the system
+ * will behave correctly. The notification calls are unlikely to fail,
+ * anyway.
+ */
+int
+au_get_state(void)
+{
+#if AUDIT_NOTIFICATION_ENABLED
+ int did_notify;
+#endif
+ int status;
+
+ /*
+ * Don't make the client initialize this set of routines, but take the
+ * slight performance hit by checking ourselves every time.
+ */
+ if (au_cond == AUC_UNSET) {
+ status = au_notify_initialize();
+ if (status != NOTIFY_STATUS_OK) {
+ if (status == AU_UNIMPL)
+ return (AU_UNIMPL);
+ return (AUC_AUDITING);
+ } else
+ return (au_cond);
+ }
+#if AUDIT_NOTIFICATION_ENABLED
+ status = notify_check(token, &did_notify);
+ if (status != NOTIFY_STATUS_OK) {
+ au_cond = AUC_UNSET;
+ return (AUC_AUDITING);
+ }
+
+ if (did_notify == 0)
+ return (au_cond);
+#endif
+
+ if (audit_get_cond(&au_cond) != 0) {
+ /* XXX Reset au_cond to AUC_UNSET? */
+ syslog(LOG_ERR, "Audit status check failed (%s)",
+ strerror(errno));
+ if (errno == ENOSYS) /* Function unimplemented. */
+ return (AU_UNIMPL);
+ return (errno);
+ }
+
+ switch (au_cond) {
+ case AUC_NOAUDIT: /* Auditing suspended. */
+ case AUC_DISABLED: /* Auditing shut off. */
+ return (AUC_NOAUDIT);
+
+ case AUC_UNSET: /* Uninitialized; shouldn't get here. */
+ case AUC_AUDITING: /* Audit on. */
+ default:
+ return (AUC_AUDITING);
+ }
+}
+#endif /* !__APPLE__ */
+
+int
+cannot_audit(int val __unused)
+{
+#ifdef __APPLE__
+ return (!(au_get_state() == AUC_AUDITING));
+#else
+ int cond;
+
+ if (audit_get_cond(&cond) != 0) {
+ if (errno != ENOSYS) {
+ syslog(LOG_ERR, "Audit status check failed (%s)",
+ strerror(errno));
+ }
+ return (1);
+ }
+ if (cond == AUC_NOAUDIT || cond == AUC_DISABLED)
+ return (1);
+ return (0);
+#endif /* !__APPLE__ */
+}
diff --git a/contrib/openbsm/libbsm/bsm_socket_type.c b/contrib/openbsm/libbsm/bsm_socket_type.c
new file mode 100644
index 0000000..ffbe39e
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_socket_type.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <config/config.h>
+
+#include <bsm/audit_socket_type.h>
+#include <bsm/libbsm.h>
+
+struct bsm_socket_type {
+ u_short bst_bsm_socket_type;
+ int bst_local_socket_type;
+};
+
+#define ST_NO_LOCAL_MAPPING -600
+
+static const struct bsm_socket_type bsm_socket_types[] = {
+ { BSM_SOCK_DGRAM, SOCK_DGRAM },
+ { BSM_SOCK_STREAM, SOCK_STREAM },
+ { BSM_SOCK_RAW, SOCK_RAW },
+ { BSM_SOCK_RDM, SOCK_RDM },
+ { BSM_SOCK_SEQPACKET, SOCK_SEQPACKET },
+};
+static const int bsm_socket_types_count = sizeof(bsm_socket_types) /
+ sizeof(bsm_socket_types[0]);
+
+static const struct bsm_socket_type *
+bsm_lookup_local_socket_type(int local_socket_type)
+{
+ int i;
+
+ for (i = 0; i < bsm_socket_types_count; i++) {
+ if (bsm_socket_types[i].bst_local_socket_type ==
+ local_socket_type)
+ return (&bsm_socket_types[i]);
+ }
+ return (NULL);
+}
+
+u_short
+au_socket_type_to_bsm(int local_socket_type)
+{
+ const struct bsm_socket_type *bstp;
+
+ bstp = bsm_lookup_local_socket_type(local_socket_type);
+ if (bstp == NULL)
+ return (BSM_SOCK_UNKNOWN);
+ return (bstp->bst_bsm_socket_type);
+}
+
+static const struct bsm_socket_type *
+bsm_lookup_bsm_socket_type(u_short bsm_socket_type)
+{
+ int i;
+
+ for (i = 0; i < bsm_socket_types_count; i++) {
+ if (bsm_socket_types[i].bst_bsm_socket_type ==
+ bsm_socket_type)
+ return (&bsm_socket_types[i]);
+ }
+ return (NULL);
+}
+
+int
+au_bsm_to_socket_type(u_short bsm_socket_type, int *local_socket_typep)
+{
+ const struct bsm_socket_type *bstp;
+
+ bstp = bsm_lookup_bsm_socket_type(bsm_socket_type);
+ if (bstp == NULL || bstp->bst_local_socket_type)
+ return (-1);
+ *local_socket_typep = bstp->bst_local_socket_type;
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_token.c b/contrib/openbsm/libbsm/bsm_token.c
new file mode 100644
index 0000000..682836f
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_token.c
@@ -0,0 +1,1645 @@
+/*-
+ * Copyright (c) 2004-2009 Apple Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * 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>
+
+#ifdef USE_ENDIAN_H
+#include <endian.h>
+#endif
+#ifdef USE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+#ifdef USE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#ifdef USE_COMPAT_ENDIAN_H
+#include <compat/endian.h>
+#endif
+#ifdef USE_COMPAT_ENDIAN_ENC_H
+#include <compat/endian_enc.h>
+#endif
+
+#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/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#include <sys/ipc.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <bsm/audit_internal.h>
+#include <bsm/libbsm.h>
+
+#define GET_TOKEN_AREA(t, dptr, length) do { \
+ (t) = malloc(sizeof(token_t)); \
+ if ((t) != NULL) { \
+ (t)->len = (length); \
+ (dptr) = (t->t_data) = calloc((length), sizeof(u_char)); \
+ if ((dptr) == NULL) { \
+ free(t); \
+ (t) = NULL; \
+ } \
+ } else \
+ (dptr) = NULL; \
+ assert((t) == NULL || (dptr) != NULL); \
+} while (0)
+
+/*
+ * token ID 1 byte
+ * success/failure 1 byte
+ * privstrlen 2 bytes
+ * privstr N bytes + 1 (\0 byte)
+ */
+token_t *
+au_to_upriv(char sorf, char *priv)
+{
+ u_int16_t textlen;
+ u_char *dptr;
+ token_t *t;
+
+ textlen = strlen(priv) + 1;
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_char) +
+ sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+ ADD_U_CHAR(dptr, AUT_UPRIV);
+ ADD_U_CHAR(dptr, sorf);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, priv, textlen);
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * privtstrlen 2 bytes
+ * privtstr N bytes + 1
+ * privstrlen 2 bytes
+ * privstr N bytes + 1
+ */
+token_t *
+au_to_privset(char *privtypestr, char *privstr)
+{
+ u_int16_t type_len, priv_len;
+ u_char *dptr;
+ token_t *t;
+
+ type_len = strlen(privtypestr) + 1;
+ priv_len = strlen(privstr) + 1;
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
+ sizeof(u_int16_t) + type_len + priv_len);
+ if (t == NULL)
+ return (NULL);
+ ADD_U_CHAR(dptr, AUT_PRIV);
+ ADD_U_INT16(dptr, type_len);
+ ADD_STRING(dptr, privtypestr, type_len);
+ ADD_U_INT16(dptr, priv_len);
+ ADD_STRING(dptr, privstr, priv_len);
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * argument # 1 byte
+ * argument value 4 bytes/8 bytes (32-bit/64-bit value)
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_arg32(char n, const char *text, u_int32_t v)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ARG32);
+ ADD_U_CHAR(dptr, n);
+ ADD_U_INT32(dptr, v);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+token_t *
+au_to_arg64(char n, const char *text, u_int64_t v)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) +
+ sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ARG64);
+ ADD_U_CHAR(dptr, n);
+ ADD_U_INT64(dptr, v);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+token_t *
+au_to_arg(char n, const char *text, u_int32_t v)
+{
+
+ return (au_to_arg32(n, text, v));
+}
+
+#if defined(_KERNEL) || defined(KERNEL)
+/*
+ * token ID 1 byte
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+token_t *
+au_to_attr32(struct vnode_au_info *vni)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t pad0_16 = 0;
+ u_int32_t pad0_32 = 0;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
+ 3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ATTR32);
+
+ /*
+ * BSD defines the size for the file mode as 2 bytes; BSM defines 4
+ * so pad with 0.
+ *
+ * XXXRW: Possibly should be conditionally compiled.
+ *
+ * XXXRW: Should any conversions take place on the mode?
+ */
+ ADD_U_INT16(dptr, pad0_16);
+ ADD_U_INT16(dptr, vni->vn_mode);
+
+ ADD_U_INT32(dptr, vni->vn_uid);
+ ADD_U_INT32(dptr, vni->vn_gid);
+ ADD_U_INT32(dptr, vni->vn_fsid);
+
+ /*
+ * Some systems use 32-bit file ID's, others use 64-bit file IDs.
+ * Attempt to handle both, and let the compiler sort it out. If we
+ * could pick this out at compile-time, it would be better, so as to
+ * avoid the else case below.
+ */
+ if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
+ ADD_U_INT32(dptr, pad0_32);
+ ADD_U_INT32(dptr, vni->vn_fileid);
+ } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
+ ADD_U_INT64(dptr, vni->vn_fileid);
+ else
+ ADD_U_INT64(dptr, 0LL);
+
+ ADD_U_INT32(dptr, vni->vn_dev);
+
+ return (t);
+}
+
+token_t *
+au_to_attr64(struct vnode_au_info *vni)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t pad0_16 = 0;
+ u_int32_t pad0_32 = 0;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
+ 3 * sizeof(u_int32_t) + sizeof(u_int64_t) * 2);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ATTR64);
+
+ /*
+ * BSD defines the size for the file mode as 2 bytes; BSM defines 4
+ * so pad with 0.
+ *
+ * XXXRW: Possibly should be conditionally compiled.
+ *
+ * XXXRW: Should any conversions take place on the mode?
+ */
+ ADD_U_INT16(dptr, pad0_16);
+ ADD_U_INT16(dptr, vni->vn_mode);
+
+ ADD_U_INT32(dptr, vni->vn_uid);
+ ADD_U_INT32(dptr, vni->vn_gid);
+ ADD_U_INT32(dptr, vni->vn_fsid);
+
+ /*
+ * Some systems use 32-bit file ID's, other's use 64-bit file IDs.
+ * Attempt to handle both, and let the compiler sort it out. If we
+ * could pick this out at compile-time, it would be better, so as to
+ * avoid the else case below.
+ */
+ if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
+ ADD_U_INT32(dptr, pad0_32);
+ ADD_U_INT32(dptr, vni->vn_fileid);
+ } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
+ ADD_U_INT64(dptr, vni->vn_fileid);
+ else
+ ADD_U_INT64(dptr, 0LL);
+
+ ADD_U_INT64(dptr, vni->vn_dev);
+
+ return (t);
+}
+
+token_t *
+au_to_attr(struct vnode_au_info *vni)
+{
+
+ return (au_to_attr32(vni));
+}
+#endif /* !(defined(_KERNEL) || defined(KERNEL) */
+
+/*
+ * token ID 1 byte
+ * how to print 1 byte
+ * basic unit 1 byte
+ * unit count 1 byte
+ * data items (depends on basic unit)
+ */
+token_t *
+au_to_data(char unit_print, char unit_type, char unit_count, const char *p)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ size_t datasize, totdata;
+
+ /* Determine the size of the basic unit. */
+ switch (unit_type) {
+ case AUR_BYTE:
+ /* case AUR_CHAR: */
+ datasize = AUR_BYTE_SIZE;
+ break;
+
+ case AUR_SHORT:
+ datasize = AUR_SHORT_SIZE;
+ break;
+
+ case AUR_INT32:
+ /* case AUR_INT: */
+ datasize = AUR_INT32_SIZE;
+ break;
+
+ case AUR_INT64:
+ datasize = AUR_INT64_SIZE;
+ break;
+
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ totdata = datasize * unit_count;
+
+ GET_TOKEN_AREA(t, dptr, 4 * sizeof(u_char) + totdata);
+ if (t == NULL)
+ return (NULL);
+
+ /*
+ * XXXRW: We should be byte-swapping each data item for multi-byte
+ * types.
+ */
+ ADD_U_CHAR(dptr, AUT_DATA);
+ ADD_U_CHAR(dptr, unit_print);
+ ADD_U_CHAR(dptr, unit_type);
+ ADD_U_CHAR(dptr, unit_count);
+ ADD_MEM(dptr, p, totdata);
+
+ return (t);
+}
+
+
+/*
+ * token ID 1 byte
+ * status 4 bytes
+ * return value 4 bytes
+ */
+token_t *
+au_to_exit(int retval, int err)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXIT);
+ ADD_U_INT32(dptr, err);
+ ADD_U_INT32(dptr, retval);
+
+ return (t);
+}
+
+/*
+ */
+token_t *
+au_to_groups(int *groups)
+{
+
+ return (au_to_newgroups(AUDIT_MAX_GROUPS, (gid_t *)groups));
+}
+
+/*
+ * token ID 1 byte
+ * number groups 2 bytes
+ * group list count * 4 bytes
+ */
+token_t *
+au_to_newgroups(u_int16_t n, gid_t *groups)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ int i;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
+ n * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_NEWGROUPS);
+ ADD_U_INT16(dptr, n);
+ for (i = 0; i < n; i++)
+ ADD_U_INT32(dptr, groups[i]);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * internet address 4 bytes
+ */
+token_t *
+au_to_in_addr(struct in_addr *internet_addr)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(uint32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IN_ADDR);
+ ADD_MEM(dptr, &internet_addr->s_addr, sizeof(uint32_t));
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * address type/length 4 bytes
+ * address 16 bytes
+ */
+token_t *
+au_to_in_addr_ex(struct in6_addr *internet_addr)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t type = AU_IPv6;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(uint32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
+ ADD_U_INT32(dptr, type);
+ ADD_MEM(dptr, internet_addr, 4 * sizeof(uint32_t));
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * ip header 20 bytes
+ *
+ * The IP header should be submitted in network byte order.
+ */
+token_t *
+au_to_ip(struct ip *ip)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IP);
+ ADD_MEM(dptr, ip, sizeof(struct ip));
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * object ID type 1 byte
+ * object ID 4 bytes
+ */
+token_t *
+au_to_ipc(char type, int id)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPC);
+ ADD_U_CHAR(dptr, type);
+ ADD_U_INT32(dptr, id);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * creator user ID 4 bytes
+ * creator group ID 4 bytes
+ * access mode 4 bytes
+ * slot sequence # 4 bytes
+ * key 4 bytes
+ */
+token_t *
+au_to_ipc_perm(struct ipc_perm *perm)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t pad0 = 0;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 12 * sizeof(u_int16_t) +
+ sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPC_PERM);
+
+ /*
+ * Systems vary significantly in what types they use in struct
+ * ipc_perm; at least a few still use 16-bit uid's and gid's, so
+ * allow for that, as BSM define 32-bit values here.
+ * Some systems define the sizes for ipc_perm members as 2 bytes;
+ * BSM defines 4 so pad with 0.
+ *
+ * XXXRW: Possibly shoulid be conditionally compiled, and more cases
+ * need to be handled.
+ */
+ if (sizeof(perm->uid) != sizeof(u_int32_t)) {
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->uid);
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->gid);
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->cuid);
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->cgid);
+ } else {
+ ADD_U_INT32(dptr, perm->uid);
+ ADD_U_INT32(dptr, perm->gid);
+ ADD_U_INT32(dptr, perm->cuid);
+ ADD_U_INT32(dptr, perm->cgid);
+ }
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->mode);
+
+ ADD_U_INT16(dptr, pad0);
+
+#ifdef HAVE_IPC_PERM___SEQ
+ ADD_U_INT16(dptr, perm->__seq);
+#else /* HAVE_IPC_PERM___SEQ */
+#ifdef HAVE_IPC_PERM__SEQ
+ ADD_U_INT16(dptr, perm->_seq);
+#else /* HAVE_IPC_PERM__SEQ */
+ ADD_U_INT16(dptr, perm->seq);
+#endif /* HAVE_IPC_PERM__SEQ */
+#endif /* HAVE_IPC_PERM___SEQ */
+
+#ifdef HAVE_IPC_PERM___KEY
+ ADD_U_INT32(dptr, perm->__key);
+#else /* HAVE_IPC_PERM___KEY */
+#ifdef HAVE_IPC_PERM__KEY
+ ADD_U_INT32(dptr, perm->_key);
+#else /* HAVE_IPC_PERM__KEY */
+ ADD_U_INT32(dptr, perm->key);
+#endif /* HAVE_IPC_PERM__KEY */
+#endif /* HAVE_IPC_PERM___KEY */
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * port IP address 2 bytes
+ */
+token_t *
+au_to_iport(u_int16_t iport)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPORT);
+ ADD_U_INT16(dptr, iport);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * size 2 bytes
+ * data size bytes
+ */
+token_t *
+au_to_opaque(const char *data, u_int16_t bytes)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_OPAQUE);
+ ADD_U_INT16(dptr, bytes);
+ ADD_MEM(dptr, data, bytes);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * seconds of time 4 bytes
+ * milliseconds of time 4 bytes
+ * file name len 2 bytes
+ * file pathname N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_file(const char *file, struct timeval tm)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t filelen;
+ u_int32_t timems;
+
+ filelen = strlen(file);
+ filelen += 1;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
+ sizeof(u_int16_t) + filelen);
+ if (t == NULL)
+ return (NULL);
+
+ timems = tm.tv_usec/1000;
+
+ ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+ ADD_U_INT16(dptr, filelen);
+ ADD_STRING(dptr, file, filelen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_text(const char *text)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ /* XXXRW: Should validate length against token size limit. */
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_TEXT);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * path length 2 bytes
+ * path N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_path(const char *text)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PATH);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine address 4 bytes
+ */
+token_t *
+au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS32);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->port);
+
+ /*
+ * Note: Solaris will write out IPv6 addresses here as a 32-bit
+ * address type and 16 bytes of address, but for IPv4 addresses it
+ * simply writes the 4-byte address directly. We support only IPv4
+ * addresses for process32 tokens.
+ */
+ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_process64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 8 * sizeof(u_int32_t) +
+ sizeof(u_int64_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS64);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT64(dptr, tid->port);
+
+ /*
+ * Note: Solaris will write out IPv6 addresses here as a 32-bit
+ * address type and 16 bytes of address, but for IPv4 addresses it
+ * simply writes the 4-byte address directly. We support only IPv4
+ * addresses for process64 tokens.
+ */
+ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_process(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+
+ return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * address type-len 4 bytes
+ * machine address 16 bytes
+ */
+token_t *
+au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ if (tid->at_type == AU_IPv4)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 10 * sizeof(u_int32_t));
+ else if (tid->at_type == AU_IPv6)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 13 * sizeof(u_int32_t));
+ else {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+ if (tid->at_type == AU_IPv6) {
+ ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
+ ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
+ ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
+ }
+
+ return (t);
+}
+
+token_t *
+au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ if (tid->at_type == AU_IPv4)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
+ 2 * sizeof(u_int32_t));
+ else if (tid->at_type == AU_IPv6)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
+ 5 * sizeof(u_int32_t));
+ else {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS64_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT64(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+ if (tid->at_type == AU_IPv6) {
+ ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t));
+ ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t));
+ ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t));
+ }
+
+ return (t);
+}
+
+token_t *
+au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * error status 1 byte
+ * return value 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+token_t *
+au_to_return32(char status, u_int32_t ret)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_RETURN32);
+ ADD_U_CHAR(dptr, status);
+ ADD_U_INT32(dptr, ret);
+
+ return (t);
+}
+
+token_t *
+au_to_return64(char status, u_int64_t ret)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_RETURN64);
+ ADD_U_CHAR(dptr, status);
+ ADD_U_INT64(dptr, ret);
+
+ return (t);
+}
+
+token_t *
+au_to_return(char status, u_int32_t ret)
+{
+
+ return (au_to_return32(status, ret));
+}
+
+/*
+ * token ID 1 byte
+ * sequence number 4 bytes
+ */
+token_t *
+au_to_seq(long audit_count)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SEQ);
+ ADD_U_INT32(dptr, audit_count);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * socket domain 2 bytes
+ * socket type 2 bytes
+ * address type 2 byte
+ * local port 2 bytes
+ * local address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * remote port 2 bytes
+ * remote address 4 bytes/16 bytes (IPv4/IPv6 address)
+ *
+ * Domain and type arguments to this routine are assumed to already have been
+ * converted to the BSM constant space, so we don't do that here.
+ */
+token_t *
+au_to_socket_ex(u_short so_domain, u_short so_type,
+ struct sockaddr *sa_local, struct sockaddr *sa_remote)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ if (so_domain == AF_INET)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 5 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
+ else if (so_domain == AF_INET6)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 5 * sizeof(u_int16_t) + 8 * sizeof(u_int32_t));
+ else {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKET_EX);
+ ADD_U_INT16(dptr, au_domain_to_bsm(so_domain));
+ ADD_U_INT16(dptr, au_socket_type_to_bsm(so_type));
+ if (so_domain == AF_INET) {
+ ADD_U_INT16(dptr, AU_IPv4);
+ sin = (struct sockaddr_in *)sa_local;
+ ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
+ ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
+ sin = (struct sockaddr_in *)sa_remote;
+ ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t));
+ ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t));
+ } else {
+ ADD_U_INT16(dptr, AU_IPv6);
+ sin6 = (struct sockaddr_in6 *)sa_local;
+ ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
+ ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
+ sin6 = (struct sockaddr_in6 *)sa_remote;
+ ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t));
+ ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t));
+ }
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * socket family 2 bytes
+ * path (up to) 104 bytes + NULL (NULL terminated string)
+ */
+token_t *
+au_to_sock_unix(struct sockaddr_un *so)
+{
+ token_t *t;
+ u_char *dptr;
+
+ GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKUNIX);
+ /* BSM token has two bytes for family */
+ ADD_U_CHAR(dptr, 0);
+ ADD_U_CHAR(dptr, so->sun_family);
+ ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * socket family 2 bytes
+ * local port 2 bytes
+ * socket address 4 bytes
+ */
+token_t *
+au_to_sock_inet32(struct sockaddr_in *so)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ uint16_t family;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(uint16_t) +
+ sizeof(uint32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKINET32);
+ /*
+ * BSM defines the family field as 16 bits, but many operating
+ * systems have an 8-bit sin_family field. Extend to 16 bits before
+ * writing into the token. Assume that both the port and the address
+ * in the sockaddr_in are already in network byte order, but family
+ * is in local byte order.
+ *
+ * XXXRW: Should a name space conversion be taking place on the value
+ * of sin_family?
+ */
+ family = so->sin_family;
+ ADD_U_INT16(dptr, family);
+ ADD_MEM(dptr, &so->sin_port, sizeof(uint16_t));
+ ADD_MEM(dptr, &so->sin_addr.s_addr, sizeof(uint32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_sock_inet128(struct sockaddr_in6 *so)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
+ 4 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKINET128);
+ /*
+ * In BSD, sin6_family is one octet, but BSM defines the token to
+ * store two. So we copy in a 0 first. XXXRW: Possibly should be
+ * conditionally compiled.
+ */
+ ADD_U_CHAR(dptr, 0);
+ ADD_U_CHAR(dptr, so->sin6_family);
+
+ ADD_U_INT16(dptr, so->sin6_port);
+ ADD_MEM(dptr, &so->sin6_addr, 4 * sizeof(uint32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_sock_inet(struct sockaddr_in *so)
+{
+
+ return (au_to_sock_inet32(so));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine address 4 bytes
+ */
+token_t *
+au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT32);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->port);
+ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) +
+ sizeof(u_int64_t) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT64);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT64(dptr, tid->port);
+ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+
+ return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * address type/length 4 bytes
+ * machine address 16 bytes
+ */
+token_t *
+au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ if (tid->at_type == AU_IPv4)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 *
+ sizeof(u_int32_t));
+ else if (tid->at_type == AU_IPv6)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 *
+ sizeof(u_int32_t));
+ else {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ if (tid->at_type == AU_IPv6)
+ ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
+ else
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ if (tid->at_type == AU_IPv4)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
+ 2 * sizeof(u_int32_t));
+ else if (tid->at_type == AU_IPv6)
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) +
+ 7 * sizeof(u_int32_t) + sizeof(u_int64_t) +
+ 5 * sizeof(u_int32_t));
+ else {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT64_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT64(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ if (tid->at_type == AU_IPv6)
+ ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
+ else
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+
+ return (t);
+}
+
+token_t *
+au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+#if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS)
+/*
+ * Collects audit information for the current process and creates a subject
+ * token from it.
+ */
+token_t *
+au_to_me(void)
+{
+ auditinfo_t auinfo;
+ auditinfo_addr_t aia;
+
+ /*
+ * Try to use getaudit_addr(2) first. If this kernel does not support
+ * it, then fall back on to getaudit(2).
+ */
+ if (getaudit_addr(&aia, sizeof(aia)) != 0) {
+ if (errno == ENOSYS) {
+ if (getaudit(&auinfo) != 0)
+ return (NULL);
+ return (au_to_subject32(auinfo.ai_auid, geteuid(),
+ getegid(), getuid(), getgid(), getpid(),
+ auinfo.ai_asid, &auinfo.ai_termid));
+ } else {
+ /* getaudit_addr(2) failed for some other reason. */
+ return (NULL);
+ }
+ }
+
+ return (au_to_subject32_ex(aia.ai_auid, geteuid(), getegid(), getuid(),
+ getgid(), getpid(), aia.ai_asid, &aia.ai_termid));
+}
+#endif
+
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_args(char **argv)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ const char *nextarg;
+ int i, count = 0;
+ size_t totlen = 0;
+
+ nextarg = *argv;
+
+ while (nextarg != NULL) {
+ int nextlen;
+
+ nextlen = strlen(nextarg);
+ totlen += nextlen + 1;
+ count++;
+ nextarg = *(argv + count);
+ }
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
+ ADD_U_INT32(dptr, count);
+
+ for (i = 0; i < count; i++) {
+ nextarg = *(argv + i);
+ ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
+ }
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_env(char **envp)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ int i, count = 0;
+ size_t totlen = 0;
+ const char *nextenv;
+
+ nextenv = *envp;
+
+ while (nextenv != NULL) {
+ int nextlen;
+
+ nextlen = strlen(nextenv);
+ totlen += nextlen + 1;
+ count++;
+ nextenv = *(envp + count);
+ }
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXEC_ENV);
+ ADD_U_INT32(dptr, count);
+
+ for (i = 0; i < count; i++) {
+ nextenv = *(envp + i);
+ ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
+ }
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * zonename length 2 bytes
+ * zonename N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_zonename(const char *zonename)
+{
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+ token_t *t;
+
+ textlen = strlen(zonename) + 1;
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ZONENAME);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, zonename, textlen);
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+token_t *
+au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t timems;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_HEADER32);
+ ADD_U_INT32(dptr, rec_size);
+ ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
+ ADD_U_INT16(dptr, e_type);
+ ADD_U_INT16(dptr, e_mod);
+
+ timems = tm.tv_usec/1000;
+ /* Add the timestamp */
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+token_t *
+au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm, struct auditinfo_addr *aia)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t timems;
+ au_tid_addr_t *tid;
+
+ tid = &aia->ai_termid;
+ if (tid->at_type != AU_IPv4 && tid->at_type != AU_IPv6)
+ return (NULL);
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 *
+ sizeof(u_int32_t) + tid->at_type);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_HEADER32_EX);
+ ADD_U_INT32(dptr, rec_size);
+ ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
+ ADD_U_INT16(dptr, e_type);
+ ADD_U_INT16(dptr, e_mod);
+
+ ADD_U_INT32(dptr, tid->at_type);
+ if (tid->at_type == AU_IPv6)
+ ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
+ else
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+ timems = tm.tv_usec/1000;
+ /* Add the timestamp */
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+
+ return (t);
+}
+
+token_t *
+au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t timems;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int64_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_HEADER64);
+ ADD_U_INT32(dptr, rec_size);
+ ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
+ ADD_U_INT16(dptr, e_type);
+ ADD_U_INT16(dptr, e_mod);
+
+ timems = tm.tv_usec/1000;
+ /* Add the timestamp */
+ ADD_U_INT64(dptr, tm.tv_sec);
+ ADD_U_INT64(dptr, timems); /* We need time in ms. */
+
+ return (t);
+}
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+#ifdef HAVE_AUDIT_SYSCALLS
+token_t *
+au_to_header32_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
+{
+ struct timeval tm;
+ struct auditinfo_addr aia;
+
+ if (gettimeofday(&tm, NULL) == -1)
+ return (NULL);
+ if (audit_get_kaudit(&aia, sizeof(aia)) != 0) {
+ if (errno != ENOSYS)
+ return (NULL);
+ return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
+ }
+ return (au_to_header32_ex_tm(rec_size, e_type, e_mod, tm, &aia));
+}
+#endif /* HAVE_AUDIT_SYSCALLS */
+
+token_t *
+au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod)
+{
+ struct timeval tm;
+
+ if (gettimeofday(&tm, NULL) == -1)
+ return (NULL);
+ return (au_to_header32_tm(rec_size, e_type, e_mod, tm));
+}
+
+token_t *
+au_to_header64(__unused int rec_size, __unused au_event_t e_type,
+ __unused au_emod_t e_mod)
+{
+ struct timeval tm;
+
+ if (gettimeofday(&tm, NULL) == -1)
+ return (NULL);
+ return (au_to_header64_tm(rec_size, e_type, e_mod, tm));
+}
+
+token_t *
+au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod)
+{
+
+ return (au_to_header32(rec_size, e_type, e_mod));
+}
+
+#ifdef HAVE_AUDIT_SYSCALLS
+token_t *
+au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod)
+{
+
+ return (au_to_header32_ex(rec_size, e_type, e_mod));
+}
+#endif /* HAVE_AUDIT_SYSCALLS */
+#endif /* !defined(KERNEL) && !defined(_KERNEL) */
+
+/*
+ * token ID 1 byte
+ * trailer magic number 2 bytes
+ * record byte count 4 bytes
+ */
+token_t *
+au_to_trailer(int rec_size)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t magic = AUT_TRAILER_MAGIC;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
+ sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_TRAILER);
+ ADD_U_INT16(dptr, magic);
+ ADD_U_INT32(dptr, rec_size);
+
+ return (t);
+}
diff --git a/contrib/openbsm/libbsm/bsm_user.c b/contrib/openbsm/libbsm/bsm_user.c
new file mode 100644
index 0000000..5b48070
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_user.c
@@ -0,0 +1,294 @@
+/*-
+ * Copyright (c) 2004 Apple Inc.
+ * 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.
+ * 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 <config/config.h>
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+/*
+ * Parse the contents of the audit_user file into au_user_ent structures.
+ */
+
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *user_delim = ":";
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*
+ * Parse one line from the audit_user file into the au_user_ent structure.
+ */
+static struct au_user_ent *
+userfromstr(char *str, struct au_user_ent *u)
+{
+ char *username, *always, *never;
+ char *last;
+
+ username = strtok_r(str, user_delim, &last);
+ always = strtok_r(NULL, user_delim, &last);
+ never = strtok_r(NULL, user_delim, &last);
+
+ if ((username == NULL) || (always == NULL) || (never == NULL))
+ return (NULL);
+
+ if (strlen(username) >= AU_USER_NAME_MAX)
+ return (NULL);
+
+ strlcpy(u->au_name, username, AU_USER_NAME_MAX);
+ if (getauditflagsbin(always, &(u->au_always)) == -1)
+ return (NULL);
+
+ if (getauditflagsbin(never, &(u->au_never)) == -1)
+ return (NULL);
+
+ return (u);
+}
+
+/*
+ * Rewind to beginning of the file
+ */
+static void
+setauuser_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauuser(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ setauuser_locked();
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Close the file descriptor
+ */
+void
+endauuser(void)
+{
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+/*
+ * Enumerate the au_user_ent structures from the file
+ */
+static struct au_user_ent *
+getauuserent_r_locked(struct au_user_ent *u)
+{
+ char *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Get the next structure. */
+ if (userfromstr(linestr, u) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (u);
+}
+
+struct au_user_ent *
+getauuserent_r(struct au_user_ent *u)
+{
+ struct au_user_ent *up;
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+ up = getauuserent_r_locked(u);
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (up);
+}
+
+struct au_user_ent *
+getauuserent(void)
+{
+ static char user_ent_name[AU_USER_NAME_MAX];
+ static struct au_user_ent u;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ return (getauuserent_r(&u));
+}
+
+/*
+ * Find a au_user_ent structure matching the given user name.
+ */
+struct au_user_ent *
+getauusernam_r(struct au_user_ent *u, const char *name)
+{
+ struct au_user_ent *up;
+
+ if (name == NULL)
+ return (NULL);
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_lock(&mutex);
+#endif
+
+ setauuser_locked();
+ while ((up = getauuserent_r_locked(u)) != NULL) {
+ if (strcmp(name, u->au_name) == 0) {
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (up);
+ }
+ }
+
+#ifdef HAVE_PTHREAD_MUTEX_LOCK
+ pthread_mutex_unlock(&mutex);
+#endif
+ return (NULL);
+
+}
+
+struct au_user_ent *
+getauusernam(const char *name)
+{
+ static char user_ent_name[AU_USER_NAME_MAX];
+ static struct au_user_ent u;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ return (getauusernam_r(&u, name));
+}
+
+/*
+ * Read the default system wide audit classes from audit_control, combine with
+ * the per-user audit class and update the binary preselection mask.
+ */
+int
+au_user_mask(char *username, au_mask_t *mask_p)
+{
+ char auditstring[MAX_AUDITSTRING_LEN + 1];
+ char user_ent_name[AU_USER_NAME_MAX];
+ struct au_user_ent u, *up;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ /* Get user mask. */
+ if ((up = getauusernam_r(&u, username)) != NULL) {
+ if (-1 == getfauditflags(&up->au_always, &up->au_never,
+ mask_p))
+ return (-1);
+ return (0);
+ }
+
+ /* Read the default system mask. */
+ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
+ if (-1 == getauditflagsbin(auditstring, mask_p))
+ return (-1);
+ return (0);
+ }
+
+ /* No masks defined. */
+ return (-1);
+}
+
+/*
+ * Generate the process audit state by combining the audit masks passed as
+ * parameters with the system audit masks.
+ */
+int
+getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
+{
+ char auditstring[MAX_AUDITSTRING_LEN + 1];
+
+ if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
+ return (-1);
+
+ lastmask->am_success = 0;
+ lastmask->am_failure = 0;
+
+ /* Get the system mask. */
+ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
+ if (getauditflagsbin(auditstring, lastmask) != 0)
+ return (-1);
+ }
+
+ ADDMASK(lastmask, usremask);
+ SUBMASK(lastmask, usrdmask);
+
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_wrappers.c b/contrib/openbsm/libbsm/bsm_wrappers.c
new file mode 100644
index 0000000..01daaf1
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_wrappers.c
@@ -0,0 +1,821 @@
+/*-
+ * 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.
+ */
+
+#ifdef __APPLE__
+#define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */
+#endif
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#ifdef __APPLE__
+#include <sys/queue.h> /* Our bsm/audit.h doesn't include queue.h. */
+#endif
+
+#include <sys/sysctl.h>
+
+#include <bsm/libbsm.h>
+
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+/* These are not advertised in libbsm.h */
+int audit_set_terminal_port(dev_t *p);
+int audit_set_terminal_host(uint32_t *m);
+
+/*
+ * General purpose audit submission mechanism for userspace.
+ */
+int
+audit_submit(short au_event, au_id_t auid, char status,
+ int reterr, const char *fmt, ...)
+{
+ char text[MAX_AUDITSTRING_LEN];
+ token_t *token;
+ int acond;
+ va_list ap;
+ pid_t pid;
+ int error, afd, subj_ex;
+ struct auditinfo ai;
+ struct auditinfo_addr aia;
+ au_tid_t atid;
+
+ if (audit_get_cond(&acond) != 0) {
+ /*
+ * If auditon(2) returns ENOSYS, then audit has not been
+ * compiled into the kernel, so just return.
+ */
+ if (errno == ENOSYS)
+ return (0);
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR, "audit: auditon failed: %s",
+ strerror(errno));
+ errno = error;
+ return (-1);
+ }
+ if (acond == AUC_NOAUDIT)
+ return (0);
+ afd = au_open();
+ if (afd < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR, "audit: au_open failed: %s",
+ strerror(errno));
+ errno = error;
+ return (-1);
+ }
+ /*
+ * Try to use getaudit_addr(2) first. If this kernel does not support
+ * it, then fall back on to getaudit(2).
+ */
+ subj_ex = 0;
+ error = getaudit_addr(&aia, sizeof(aia));
+ if (error < 0 && errno == ENOSYS) {
+ error = getaudit(&ai);
+ if (error < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR, "audit: getaudit failed: %s",
+ strerror(errno));
+ errno = error;
+ return (-1);
+ }
+ /*
+ * Convert this auditinfo_t to an auditinfo_addr_t to make the
+ * following code less complicated wrt to preselection and
+ * subject token generation.
+ */
+ aia.ai_auid = ai.ai_auid;
+ aia.ai_mask = ai.ai_mask;
+ aia.ai_asid = ai.ai_asid;
+ aia.ai_termid.at_type = AU_IPv4;
+ aia.ai_termid.at_addr[0] = ai.ai_termid.machine;
+ aia.ai_termid.at_port = ai.ai_termid.port;
+ } else if (error < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR, "audit: getaudit_addr failed: %s",
+ strerror(errno));
+ errno = error;
+ return (-1);
+ }
+ /*
+ * NB: We should be performing pre-selection here now that we have the
+ * masks for this process.
+ */
+ if (aia.ai_termid.at_type == AU_IPv6)
+ subj_ex = 1;
+ pid = getpid();
+ if (subj_ex == 0) {
+ atid.port = aia.ai_termid.at_port;
+ atid.machine = aia.ai_termid.at_addr[0];
+ token = au_to_subject32(auid, geteuid(), getegid(),
+ getuid(), getgid(), pid, pid, &atid);
+ } else
+ token = au_to_subject_ex(auid, geteuid(), getegid(),
+ getuid(), getgid(), pid, pid, &aia.ai_termid);
+ if (token == NULL) {
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: unable to build subject token");
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = EPERM;
+ return (-1);
+ }
+ if (au_write(afd, token) < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: au_write failed: %s", strerror(errno));
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = error;
+ return (-1);
+ }
+ if (fmt != NULL) {
+ va_start(ap, fmt);
+ (void) vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap);
+ va_end(ap);
+ token = au_to_text(text);
+ if (token == NULL) {
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: failed to generate text token");
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = EPERM;
+ return (-1);
+ }
+ if (au_write(afd, token) < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: au_write failed: %s", strerror(errno));
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = error;
+ return (-1);
+ }
+ }
+ token = au_to_return32(au_errno_to_bsm(status), reterr);
+ if (token == NULL) {
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: unable to build return token");
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = EPERM;
+ return (-1);
+ }
+ if (au_write(afd, token) < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR,
+ "audit: au_write failed: %s", strerror(errno));
+ (void) au_close(afd, AU_TO_NO_WRITE, au_event);
+ errno = error;
+ return (-1);
+ }
+ if (au_close(afd, AU_TO_WRITE, au_event) < 0) {
+ error = errno;
+ syslog(LOG_AUTH | LOG_ERR, "audit: record not committed");
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+audit_set_terminal_port(dev_t *p)
+{
+ struct stat st;
+
+ if (p == NULL)
+ return (kAUBadParamErr);
+
+#ifdef NODEV
+ *p = NODEV;
+#else
+ *p = -1;
+#endif
+
+ /* for /usr/bin/login, try fstat() first */
+ if (fstat(STDIN_FILENO, &st) != 0) {
+ if (errno != EBADF) {
+ syslog(LOG_ERR, "fstat() failed (%s)",
+ strerror(errno));
+ return (kAUStatErr);
+ }
+ if (stat("/dev/console", &st) != 0) {
+ syslog(LOG_ERR, "stat() failed (%s)",
+ strerror(errno));
+ return (kAUStatErr);
+ }
+ }
+ *p = st.st_rdev;
+ return (kAUNoErr);
+}
+
+int
+audit_set_terminal_host(uint32_t *m)
+{
+
+#ifdef KERN_HOSTID
+ int name[2] = { CTL_KERN, KERN_HOSTID };
+ size_t len;
+
+ if (m == NULL)
+ return (kAUBadParamErr);
+ *m = 0;
+ len = sizeof(*m);
+ if (sysctl(name, 2, m, &len, NULL, 0) != 0) {
+ syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno));
+ return (kAUSysctlErr);
+ }
+ return (kAUNoErr);
+#else
+ *m = -1;
+ return (kAUNoErr);
+#endif
+}
+
+int
+audit_set_terminal_id(au_tid_t *tid)
+{
+ int ret;
+
+ if (tid == NULL)
+ return (kAUBadParamErr);
+ if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr)
+ return (ret);
+ return (audit_set_terminal_host(&tid->machine));
+}
+
+/*
+ * This is OK for those callers who have only one token to write. If you have
+ * multiple tokens that logically form part of the same audit record, you need
+ * to use the existing au_open()/au_write()/au_close() API:
+ *
+ * aufd = au_open();
+ * tok = au_to_random_token_1(...);
+ * au_write(aufd, tok);
+ * tok = au_to_random_token_2(...);
+ * au_write(aufd, tok);
+ * ...
+ * au_close(aufd, AU_TO_WRITE, AUE_your_event_type);
+ *
+ * Assumes, like all wrapper calls, that the caller has previously checked
+ * that auditing is enabled via the audit_get_state() call.
+ *
+ * XXX: Should be more robust against bad arguments.
+ */
+int
+audit_write(short event_code, token_t *subject, token_t *misctok, char retval,
+ int errcode)
+{
+ int aufd;
+ char *func = "audit_write()";
+ token_t *rettok;
+
+ if ((aufd = au_open()) == -1) {
+ au_free_token(subject);
+ au_free_token(misctok);
+ syslog(LOG_ERR, "%s: au_open() failed", func);
+ return (kAUOpenErr);
+ }
+
+ /* Save subject. */
+ if (subject && au_write(aufd, subject) == -1) {
+ au_free_token(subject);
+ au_free_token(misctok);
+ (void)au_close(aufd, AU_TO_NO_WRITE, event_code);
+ syslog(LOG_ERR, "%s: write of subject failed", func);
+ return (kAUWriteSubjectTokErr);
+ }
+
+ /* Save the event-specific token. */
+ if (misctok && au_write(aufd, misctok) == -1) {
+ au_free_token(misctok);
+ (void)au_close(aufd, AU_TO_NO_WRITE, event_code);
+ syslog(LOG_ERR, "%s: write of caller token failed", func);
+ return (kAUWriteCallerTokErr);
+ }
+
+ /* Tokenize and save the return value. */
+ if ((rettok = au_to_return32(retval, errcode)) == NULL) {
+ (void)au_close(aufd, AU_TO_NO_WRITE, event_code);
+ syslog(LOG_ERR, "%s: au_to_return32() failed", func);
+ return (kAUMakeReturnTokErr);
+ }
+
+ if (au_write(aufd, rettok) == -1) {
+ au_free_token(rettok);
+ (void)au_close(aufd, AU_TO_NO_WRITE, event_code);
+ syslog(LOG_ERR, "%s: write of return code failed", func);
+ return (kAUWriteReturnTokErr);
+ }
+
+ /*
+ * We assume the caller wouldn't have bothered with this
+ * function if it hadn't already decided to keep the record.
+ */
+ if (au_close(aufd, AU_TO_WRITE, event_code) < 0) {
+ syslog(LOG_ERR, "%s: au_close() failed", func);
+ return (kAUCloseErr);
+ }
+
+ return (kAUNoErr);
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes success; use audit_write_failure() on error.
+ */
+int
+audit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid,
+ gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
+ au_tid_t *tid)
+{
+ char *func = "audit_write_success()";
+ token_t *subject = NULL;
+
+ /* Tokenize and save subject. */
+ subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid);
+ if (subject == NULL) {
+ syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
+ return kAUMakeSubjectTokErr;
+ }
+
+ return (audit_write(event_code, subject, tok, 0, 0));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes success; use audit_write_failure_self() on error.
+ */
+int
+audit_write_success_self(short event_code, token_t *tok)
+{
+ token_t *subject;
+ char *func = "audit_write_success_self()";
+
+ if ((subject = au_to_me()) == NULL) {
+ syslog(LOG_ERR, "%s: au_to_me() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+
+ return (audit_write(event_code, subject, tok, 0, 0));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes failure; use audit_write_success() otherwise.
+ *
+ * XXX This should let the caller pass an error return value rather than
+ * hard-coding -1.
+ */
+int
+audit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid,
+ uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
+ au_tid_t *tid)
+{
+ char *func = "audit_write_failure()";
+ token_t *subject, *errtok;
+
+ subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid);
+ if (subject == NULL) {
+ syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+
+ /* tokenize and save the error message */
+ if ((errtok = au_to_text(errmsg)) == NULL) {
+ au_free_token(subject);
+ syslog(LOG_ERR, "%s: au_to_text() failed", func);
+ return (kAUMakeTextTokErr);
+ }
+
+ return (audit_write(event_code, subject, errtok, -1, errcode));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes failure; use audit_write_success_self() otherwise.
+ *
+ * XXX This should let the caller pass an error return value rather than
+ * hard-coding -1.
+ */
+int
+audit_write_failure_self(short event_code, char *errmsg, int errret)
+{
+ char *func = "audit_write_failure_self()";
+ token_t *subject, *errtok;
+
+ if ((subject = au_to_me()) == NULL) {
+ syslog(LOG_ERR, "%s: au_to_me() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+ /* tokenize and save the error message */
+ if ((errtok = au_to_text(errmsg)) == NULL) {
+ au_free_token(subject);
+ syslog(LOG_ERR, "%s: au_to_text() failed", func);
+ return (kAUMakeTextTokErr);
+ }
+ return (audit_write(event_code, subject, errtok, -1, errret));
+}
+
+/*
+ * For auditing errors during login. Such errors are implicitly
+ * non-attributable (i.e., not ascribable to any user).
+ *
+ * Assumes, like all wrapper calls, that the caller has previously checked
+ * that auditing is enabled via the audit_get_state() call.
+ */
+int
+audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid,
+ uid_t egid, pid_t pid, au_tid_t *tid)
+{
+
+ return (audit_write_failure(event_code, errmsg, errret, -1, euid,
+ egid, -1, -1, pid, -1, tid));
+}
+
+/* END OF au_write() WRAPPERS */
+
+#ifdef __APPLE__
+void
+audit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp,
+ gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp,
+ au_tid_t *tidp)
+{
+
+ if (auidp != NULL)
+ *auidp = (uid_t)atoken.val[0];
+ if (euidp != NULL)
+ *euidp = (uid_t)atoken.val[1];
+ if (egidp != NULL)
+ *egidp = (gid_t)atoken.val[2];
+ if (ruidp != NULL)
+ *ruidp = (uid_t)atoken.val[3];
+ if (rgidp != NULL)
+ *rgidp = (gid_t)atoken.val[4];
+ if (pidp != NULL)
+ *pidp = (pid_t)atoken.val[5];
+ if (asidp != NULL)
+ *asidp = (au_asid_t)atoken.val[6];
+ if (tidp != NULL) {
+ audit_set_terminal_host(&tidp->machine);
+ tidp->port = (dev_t)atoken.val[7];
+ }
+}
+#endif /* !__APPLE__ */
+
+int
+audit_get_cond(int *cond)
+{
+ int ret;
+
+ ret = auditon(A_GETCOND, cond, sizeof(*cond));
+#ifdef A_OLDGETCOND
+ if ((0 != ret) && EINVAL == errno) {
+ long lcond = *cond;
+
+ ret = auditon(A_OLDGETCOND, &lcond, sizeof(lcond));
+ *cond = (int)lcond;
+ }
+#endif
+ return (ret);
+}
+
+int
+audit_set_cond(int *cond)
+{
+ int ret;
+
+ ret = auditon(A_SETCOND, cond, sizeof(*cond));
+#ifdef A_OLDSETCOND
+ if ((0 != ret) && (EINVAL == errno)) {
+ long lcond = (long)*cond;
+
+ ret = auditon(A_OLDSETCOND, &lcond, sizeof(lcond));
+ *cond = (int)lcond;
+ }
+#endif
+ return (ret);
+}
+
+int
+audit_get_policy(int *policy)
+{
+ int ret;
+
+ ret = auditon(A_GETPOLICY, policy, sizeof(*policy));
+#ifdef A_OLDGETPOLICY
+ if ((0 != ret) && (EINVAL == errno)){
+ long lpolicy = (long)*policy;
+
+ ret = auditon(A_OLDGETPOLICY, &lpolicy, sizeof(lpolicy));
+ *policy = (int)lpolicy;
+ }
+#endif
+ return (ret);
+}
+
+int
+audit_set_policy(int *policy)
+{
+ int ret;
+
+ ret = auditon(A_SETPOLICY, policy, sizeof(*policy));
+#ifdef A_OLDSETPOLICY
+ if ((0 != ret) && (EINVAL == errno)){
+ long lpolicy = (long)*policy;
+
+ ret = auditon(A_OLDSETPOLICY, &lpolicy, sizeof(lpolicy));
+ *policy = (int)lpolicy;
+ }
+#endif
+ return (ret);
+}
+
+int
+audit_get_qctrl(au_qctrl_t *qctrl, size_t sz)
+{
+ int ret;
+
+ if (sizeof(*qctrl) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = auditon(A_GETQCTRL, qctrl, sizeof(*qctrl));
+#ifdef A_OLDGETQCTRL
+ if ((0 != ret) && (EINVAL == errno)){
+ struct old_qctrl {
+ size_t oq_hiwater;
+ size_t oq_lowater;
+ size_t oq_bufsz;
+ clock_t oq_delay;
+ int oq_minfree;
+ } oq;
+
+ oq.oq_hiwater = (size_t)qctrl->aq_hiwater;
+ oq.oq_lowater = (size_t)qctrl->aq_lowater;
+ oq.oq_bufsz = (size_t)qctrl->aq_bufsz;
+ oq.oq_delay = (clock_t)qctrl->aq_delay;
+ oq.oq_minfree = qctrl->aq_minfree;
+
+ ret = auditon(A_OLDGETQCTRL, &oq, sizeof(oq));
+
+ qctrl->aq_hiwater = (int)oq.oq_hiwater;
+ qctrl->aq_lowater = (int)oq.oq_lowater;
+ qctrl->aq_bufsz = (int)oq.oq_bufsz;
+ qctrl->aq_delay = (int)oq.oq_delay;
+ qctrl->aq_minfree = oq.oq_minfree;
+ }
+#endif /* A_OLDGETQCTRL */
+ return (ret);
+}
+
+int
+audit_set_qctrl(au_qctrl_t *qctrl, size_t sz)
+{
+ int ret;
+
+ if (sizeof(*qctrl) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = auditon(A_SETQCTRL, qctrl, sz);
+#ifdef A_OLDSETQCTRL
+ if ((0 != ret) && (EINVAL == errno)) {
+ struct old_qctrl {
+ size_t oq_hiwater;
+ size_t oq_lowater;
+ size_t oq_bufsz;
+ clock_t oq_delay;
+ int oq_minfree;
+ } oq;
+
+ oq.oq_hiwater = (size_t)qctrl->aq_hiwater;
+ oq.oq_lowater = (size_t)qctrl->aq_lowater;
+ oq.oq_bufsz = (size_t)qctrl->aq_bufsz;
+ oq.oq_delay = (clock_t)qctrl->aq_delay;
+ oq.oq_minfree = qctrl->aq_minfree;
+
+ ret = auditon(A_OLDSETQCTRL, &oq, sizeof(oq));
+
+ qctrl->aq_hiwater = (int)oq.oq_hiwater;
+ qctrl->aq_lowater = (int)oq.oq_lowater;
+ qctrl->aq_bufsz = (int)oq.oq_bufsz;
+ qctrl->aq_delay = (int)oq.oq_delay;
+ qctrl->aq_minfree = oq.oq_minfree;
+ }
+#endif /* A_OLDSETQCTRL */
+ return (ret);
+}
+
+int
+audit_send_trigger(int *trigger)
+{
+
+ return (auditon(A_SENDTRIGGER, trigger, sizeof(*trigger)));
+}
+
+int
+audit_get_kaudit(auditinfo_addr_t *aia, size_t sz)
+{
+
+ if (sizeof(*aia) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETKAUDIT, aia, sz));
+}
+
+int
+audit_set_kaudit(auditinfo_addr_t *aia, size_t sz)
+{
+
+ if (sizeof(*aia) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_SETKAUDIT, aia, sz));
+}
+
+int
+audit_get_class(au_evclass_map_t *evc_map, size_t sz)
+{
+
+ if (sizeof(*evc_map) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETCLASS, evc_map, sz));
+}
+
+int
+audit_set_class(au_evclass_map_t *evc_map, size_t sz)
+{
+
+ if (sizeof(*evc_map) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_SETCLASS, evc_map, sz));
+}
+
+int
+audit_get_kmask(au_mask_t *kmask, size_t sz)
+{
+ if (sizeof(*kmask) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETKMASK, kmask, sz));
+}
+
+int
+audit_set_kmask(au_mask_t *kmask, size_t sz)
+{
+ if (sizeof(*kmask) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_SETKMASK, kmask, sz));
+}
+
+int
+audit_get_fsize(au_fstat_t *fstat, size_t sz)
+{
+
+ if (sizeof(*fstat) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETFSIZE, fstat, sz));
+}
+
+int
+audit_set_fsize(au_fstat_t *fstat, size_t sz)
+{
+
+ if (sizeof(*fstat) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_SETFSIZE, fstat, sz));
+}
+
+int
+audit_set_pmask(auditpinfo_t *api, size_t sz)
+{
+
+ if (sizeof(*api) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_SETPMASK, api, sz));
+}
+
+int
+audit_get_pinfo(auditpinfo_t *api, size_t sz)
+{
+
+ if (sizeof(*api) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETPINFO, api, sz));
+}
+
+int
+audit_get_pinfo_addr(auditpinfo_addr_t *apia, size_t sz)
+{
+
+ if (sizeof(*apia) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETPINFO_ADDR, apia, sz));
+}
+
+int
+audit_get_sinfo_addr(auditinfo_addr_t *aia, size_t sz)
+{
+
+ if (sizeof(*aia) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETSINFO_ADDR, aia, sz));
+}
+
+int
+audit_get_stat(au_stat_t *stats, size_t sz)
+{
+
+ if (sizeof(*stats) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETSTAT, stats, sz));
+}
+
+int
+audit_set_stat(au_stat_t *stats, size_t sz)
+{
+
+ if (sizeof(*stats) != sz) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (auditon(A_GETSTAT, stats, sz));
+}
+
+int
+audit_get_cwd(char *path, size_t sz)
+{
+
+ return (auditon(A_GETCWD, path, sz));
+}
+
+int
+audit_get_car(char *path, size_t sz)
+{
+
+ return (auditon(A_GETCAR, path, sz));
+}
diff --git a/contrib/openbsm/libbsm/libbsm.3 b/contrib/openbsm/libbsm/libbsm.3
new file mode 100644
index 0000000..d84e774
--- /dev/null
+++ b/contrib/openbsm/libbsm/libbsm.3
@@ -0,0 +1,248 @@
+.\"-
+.\" Copyright (c) 2005-2007 Robert N. M. Watson
+.\" Copyright (c) 2008-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.
+.\"
+.\" 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.
+.\"
+.Dd March 5, 2009
+.Dt LIBBSM 3
+.Os
+.Sh NAME
+.Nm libbsm
+.Nd "Basic Security Module (BSM) Audit API"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In bsm/libbsm.h
+.Sh DESCRIPTION
+The
+.Nm
+library routines provide an interface to BSM audit record streams, allowing
+both the parsing of existing audit streams, as well as the creation of new
+audit records and streams.
+.Sh INTERFACES
+The
+.Nm
+library
+provides a large number of Audit programming interfaces in several classes:
+event stream interfaces, class interfaces, control interfaces, event
+interfaces, I/O interfaces, mask interfaces, notification interfaces, token
+interfaces, and user interfaces.
+These are described respectively in the
+.Xr au_class 3 ,
+.Xr au_control 3 ,
+.Xr au_event 3 ,
+.Xr au_mask 3 ,
+.Xr au_notify 3 ,
+.Xr au_stream 3 ,
+.Xr au_token 3 ,
+and
+.Xr au_user 3
+manual pages.
+.Ss Audit Event Stream Interfaces
+Audit event stream interfaces support interaction with file-backed audit
+event streams:
+.Xr au_close 3 ,
+.Xr au_close_buffer 3 ,
+.Xr au_free_token 3 ,
+.Xr au_open 3 ,
+.Xr au_write 3 ,
+.Xr audit_submit 3 .
+.Ss Audit Class Interfaces
+Audit class interfaces support the look up of information from the
+.Xr audit_class 5
+database:
+.Xr endauclass 3 ,
+.Xr getauclassent 3 ,
+.Xr getauclassent_r 3 ,
+.Xr getauclassnam 3 ,
+.Xr getauclassnam_r 3 ,
+.Xr setauclass 3 .
+.Ss Audit Control Interfaces
+Audit control interfaces support the look up of information from the
+.Xr audit_control 5
+database:
+.Xr endac 3 ,
+.Xr setac 3 ,
+.Xr getacdir 3 ,
+.Xr getacfilesz 3 ,
+.Xr getacflg 3 ,
+.Xr getacmin 3 ,
+.Xr getacna 3 ,
+.Xr getacpol 3 ,
+.Xr au_poltostr 3 ,
+.Xr au_strtopol 3 .
+.Ss Audit Event Interfaces
+Audit event interfaces support the look up of information from the
+.Xr audit_event 5
+database:
+.Xr endauevent 3 ,
+.Xr setauevent 3 ,
+.Xr getauevent 3 ,
+.Xr getauevent_r 3 ,
+.Xr getauevnam 3 ,
+.Xr getauevnam_r 3 ,
+.Xr getauevnonam 3 ,
+.Xr getauevnonam_r 3 ,
+.Xr getauevnum 3 ,
+.Xr getauevnum_r 3 .
+.Ss Audit I/O Interfaces
+Audit I/O interfaces support the processing and printing of tokens, as well
+as the reading of audit records:
+.Xr au_fetch_tok 3 ,
+.Xr au_print_tok 3 ,
+.Xr au_read_rec 3 .
+.Ss Audit Mask Interfaces
+Audit mask interfaces convert support the conversion between strings and
+.Vt au_mask_t
+values.
+They may also be used to determine if a particular audit event is matched
+by a mask:
+.Xr au_preselect 3 ,
+.Xr getauditflagsbin 3 ,
+.Xr getauditflagschar 3 .
+.Ss Audit Notification Interfaces
+Audit notification routines track audit state in a form permitting efficient
+update, avoiding frequent system calls to check the kernel audit state:
+.Xr au_get_state 3 ,
+.Xr au_notify_initialize 3 ,
+.Xr au_notify_terminate 3 .
+These interfaces are implemented only for Darwin/Mac OS X.
+.Ss Audit Token Interface
+Audit token interfaces permit the creation of tokens for use in creating
+audit records for submission to event streams.
+Each interface converts a C type to its
+.Vt token_t
+representation:
+.Xr au_to_arg 3 ,
+.Xr au_to_arg32 3 ,
+.Xr au_to_arg64 3 ,
+.Xr au_to_attr64 3 ,
+.Xr au_to_data 3 ,
+.Xr au_to_exec_args 3 ,
+.Xr au_to_exec_env 3 ,
+.Xr au_to_exit 3 ,
+.Xr au_to_file 3 ,
+.Xr au_to_groups 3 ,
+.Xr au_to_header32 3 ,
+.Xr au_to_header64 3 ,
+.Xr au_to_in_addr 3 ,
+.Xr au_to_in_addr_ex 3 ,
+.Xr au_to_ip 3 ,
+.Xr au_to_ipc 3 ,
+.Xr au_to_ipc_perm 3 ,
+.Xr au_to_iport 3 ,
+.Xr au_to_me 3 ,
+.Xr au_to_newgroups 3 ,
+.Xr au_to_opaque 3 ,
+.Xr au_to_path 3 ,
+.Xr au_to_process 3 ,
+.Xr au_to_process32 3 ,
+.Xr au_to_process64 3 ,
+.Xr au_to_process_ex 3 ,
+.Xr au_to_process32_ex 3 ,
+.Xr au_to_process64_ex 3 ,
+.Xr au_to_return 3 ,
+.Xr au_to_return32 3 ,
+.Xr au_to_return64 3 ,
+.Xr au_to_seq 3 ,
+.Xr au_to_sock_inet 3 ,
+.Xr au_to_sock_inet32 3 ,
+.Xr au_to_sock_inet128 3 ,
+.Xr au_to_socket_ex 3 ,
+.Xr au_to_subject 3 ,
+.Xr au_to_subject32 3 ,
+.Xr au_to_subject64 3 ,
+.Xr au_to_subject_ex 3 ,
+.Xr au_to_subject32_ex 3 ,
+.Xr au_to_subject64_ex 3 ,
+.Xr au_to_text 3 ,
+.Xr au_to_trailer 3 ,
+.Xr au_to_zonename 3 .
+.Ss Audit User Interfaces
+Audit user interfaces support the look up of information from the
+.Xr audit_user 5
+database:
+.Xr au_user_mask 3 ,
+.Xr endauuser 3 ,
+.Xr setauuser 3 ,
+.Xr getauuserent 3 ,
+.Xr getauuserent_r 3 ,
+.Xr getauusernam 3 ,
+.Xr getauusernam_r 3 ,
+.Xr getfauditflags 3 .
+.Ss Audit Constant Conversion Interfaces
+These functions convert between BSM and local constants, including the
+.Xr errno 2
+number, socket type, and protocol famil spaces, and must be used to generate
+and interpret BSM return and extended socket tokens:
+.Xr au_bsm_to_domain 3 ,
+.Xr au_bsm_to_errno 3 ,
+.Xr au_bsm_to_fcntl_cmd 3 ,
+.Xr au_bsm_to_socket_type 3 ,
+.Xr au_domain_to_bsm 3 ,
+.Xr au_errno_to_bsm 3 ,
+.Xr au_fcntl_cmd_to_bsm 3 ,
+.Xr au_socket_type_to_bsm 3 .
+.Sh SEE ALSO
+.Xr au_class 3 ,
+.Xr au_domain 3 ,
+.Xr au_errno 3 ,
+.Xr au_mask 3 ,
+.Xr au_notify 3 ,
+.Xr au_socket_type 3 ,
+.Xr au_stream 3 ,
+.Xr au_token 3 ,
+.Xr au_user 3 ,
+.Xr audit_submit 3 ,
+.Xr audit_class 5 ,
+.Xr audit_control 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
+.An Robert Watson ,
+.An Wayne Salamon ,
+and
+.An Suresh Krishnaswamy
+for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh BUGS
+Bugs would not be unlikely.
+.Pp
+The
+.Nm
+library implementations are generally thread-safe, but not reentrant.
+.Pp
+The assignment of routines to classes could use some work, as it is
+decidely ad hoc.
+For example,
+.Fn au_read_rec
+should probably be considered a stream routine.
OpenPOWER on IntegriCloud