diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-11-12 23:48:20 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-11-12 23:48:20 +0000 |
commit | 2bd138f9edd4a43ef97291f03523af35e1ae18f8 (patch) | |
tree | e103f4f6bb4ebb161c9702d64560b216d1990d94 /libbsm | |
parent | 280c17909566cfd4eff091c2747edb9d747f7343 (diff) | |
download | FreeBSD-src-2bd138f9edd4a43ef97291f03523af35e1ae18f8.zip FreeBSD-src-2bd138f9edd4a43ef97291f03523af35e1ae18f8.tar.gz |
Flatten OpenBSM vendor tree in preparation for new OpenBSM vendor
import.
Diffstat (limited to 'libbsm')
-rw-r--r-- | libbsm/Makefile | 125 | ||||
-rw-r--r-- | libbsm/Makefile.am | 37 | ||||
-rw-r--r-- | libbsm/Makefile.in | 553 | ||||
-rw-r--r-- | libbsm/au_class.3 | 120 | ||||
-rw-r--r-- | libbsm/au_control.3 | 211 | ||||
-rw-r--r-- | libbsm/au_event.3 | 171 | ||||
-rw-r--r-- | libbsm/au_free_token.3 | 97 | ||||
-rw-r--r-- | libbsm/au_io.3 | 136 | ||||
-rw-r--r-- | libbsm/au_mask.3 | 156 | ||||
-rw-r--r-- | libbsm/au_open.3 | 158 | ||||
-rw-r--r-- | libbsm/au_token.3 | 235 | ||||
-rw-r--r-- | libbsm/au_user.3 | 156 | ||||
-rw-r--r-- | libbsm/audit_submit.3 | 132 | ||||
-rw-r--r-- | libbsm/bsm_audit.c | 383 | ||||
-rw-r--r-- | libbsm/bsm_class.c | 267 | ||||
-rw-r--r-- | libbsm/bsm_control.c | 516 | ||||
-rw-r--r-- | libbsm/bsm_event.c | 332 | ||||
-rw-r--r-- | libbsm/bsm_flags.c | 176 | ||||
-rw-r--r-- | libbsm/bsm_io.c | 4513 | ||||
-rw-r--r-- | libbsm/bsm_mask.c | 200 | ||||
-rw-r--r-- | libbsm/bsm_notify.c | 181 | ||||
-rw-r--r-- | libbsm/bsm_token.c | 1399 | ||||
-rw-r--r-- | libbsm/bsm_user.c | 268 | ||||
-rw-r--r-- | libbsm/bsm_wrappers.c | 469 | ||||
-rw-r--r-- | libbsm/libbsm.3 | 232 |
25 files changed, 11223 insertions, 0 deletions
diff --git a/libbsm/Makefile b/libbsm/Makefile new file mode 100644 index 0000000..00534aa --- /dev/null +++ b/libbsm/Makefile @@ -0,0 +1,125 @@ +# +# OpenBSM libbsm +# +# $P4: //depot/projects/trustedbsd/openbsm/libbsm/Makefile#13 $ +# + +LIB= bsm +SHLIB_MAJOR= 1 + +CFLAGS+=-I- \ + -I .. \ + -Wall + +SRCS= bsm_audit.c \ + bsm_class.c \ + bsm_control.c \ + bsm_event.c \ + bsm_flags.c \ + bsm_io.c \ + bsm_mask.c \ + bsm_notify.c \ + bsm_token.c \ + bsm_user.c \ + bsm_wrappers.c + +MAN= libbsm.3 \ + au_class.3 \ + au_control.3 \ + au_event.3 \ + au_free_token.3 \ + au_io.3 \ + au_mask.3 \ + au_token.3 \ + au_user.3 + +MLINKS= libbsm.3 bsm.3 \ + au_class.3 getauclassent.3 \ + au_class.3 getauclassent_r.3 \ + au_class.3 getauclassnam.3 \ + au_class.3 getauclassnam_r.3 \ + au_class.3 setauclass.3 \ + au_class.3 endauclass.3 \ + au_control.3 setac.3 \ + au_control.3 endac.3 \ + au_control.3 getacdir.3 \ + au_control.3 getacmin.3 \ + au_control.3 getacflg.3 \ + au_control.3 getacna.3 \ + au_event.3 setauevent.3 \ + au_event.3 endauevent.3 \ + au_event.3 getauevent.3 \ + au_event.3 getauevent_r.3 \ + au_event.3 getauevnam.3 \ + au_event.3 getauevnam_r.3 \ + au_event.3 getauevnum.3 \ + au_event.3 getauevnum_r.3 \ + au_event.3 getauevnonam.3 \ + au_event.3 getauevnonam_r.3 \ + au_io.3 au_fetch_tok.3 \ + au_io.3 au_print_tok.3 \ + au_io.3 au_read_rec.3 \ + au_mask.3 au_preselect.3 \ + au_mask.3 getauditflagsbin.3 \ + au_mask.3 getauditflagschar.3 \ + au_user.3 setauuser.3 \ + au_user.3 endauuser.3 \ + au_user.3 getauuserent.3 \ + au_user.3 getauusernam.3 \ + au_user.3 au_user_mask.3 \ + au_user.3 getfauditflags.3 \ + au_token.3 au_to_arg32.3 \ + au_token.3 au_to_arg64.3 \ + au_token.3 au_to_arg.3 \ + au_token.3 au_to_attr64.3 \ + au_token.3 au_to_data.3 \ + au_token.3 au_to_exit.3 \ + au_token.3 au_to_groups.3 \ + au_token.3 au_to_newgroups.3 \ + au_token.3 au_to_in_addr.3 \ + au_token.3 au_to_in_addr_ex.3 \ + au_token.3 au_to_ip.3 \ + au_token.3 au_to_ipc.3 \ + au_token.3 au_to_ipc_perm.3 \ + au_token.3 au_to_iport.3 \ + au_token.3 au_to_opaque.3 \ + au_token.3 au_to_file.3 \ + au_token.3 au_to_text.3 \ + au_token.3 au_to_path.3 \ + au_token.3 au_to_process32.3 \ + au_token.3 au_to_process64.3 \ + au_token.3 au_to_process.3 \ + au_token.3 au_to_process32_ex.3 \ + au_token.3 au_to_process64_ex.3 \ + au_token.3 au_to_process_ex.3 \ + au_token.3 au_to_return32.3 \ + au_token.3 au_to_return64.3 \ + au_token.3 au_to_return.3 \ + au_token.3 au_to_seq.3 \ + au_token.3 au_to_socket.3 \ + au_token.3 au_to_socket_ex_32.3 \ + au_token.3 au_to_socket_ex_128.3 \ + au_token.3 au_to_sock_inet32.3 \ + au_token.3 au_to_sock_inet128.3 \ + au_token.3 au_to_sock_inet.3 \ + au_token.3 au_to_subject32.3 \ + au_token.3 au_to_subject64.3 \ + au_token.3 au_to_subject.3 \ + au_token.3 au_to_subject32_ex.3 \ + au_token.3 au_to_subject64_ex.3 \ + au_token.3 au_to_subject_ex.3 \ + au_token.3 au_to_me.3 \ + au_token.3 au_to_exec_args.3 \ + au_token.3 au_to_exec_env.3 \ + au_token.3 au_to_header.3 \ + au_token.3 au_to_header32.3 \ + au_token.3 au_to_header64.3 \ + au_token.3 au_to_trailer.3 + +beforeinstall: + if test -d ${INCSDIR}; then \ + else \ + mkdir ${INCSDIR}; \ + fi; + +.include <bsd.lib.mk> diff --git a/libbsm/Makefile.am b/libbsm/Makefile.am new file mode 100644 index 0000000..5e4a317 --- /dev/null +++ b/libbsm/Makefile.am @@ -0,0 +1,37 @@ +# +# $P4: //depot/projects/trustedbsd/openbsm/libbsm/Makefile.am#3 $ +# + +INCLUDES = -I$(top_srcdir) + +lib_LTLIBRARIES = libbsm.la + +libbsm_la_SOURCES = \ + bsm_audit.c \ + bsm_class.c \ + bsm_control.c \ + bsm_event.c \ + bsm_flags.c \ + bsm_io.c \ + bsm_mask.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_event.3 \ + au_free_token.3 \ + au_io.3 \ + au_mask.3 \ + au_open.3 \ + au_token.3 \ + au_user.3 \ + libbsm.3 + diff --git a/libbsm/Makefile.in b/libbsm/Makefile.in new file mode 100644 index 0000000..d9da623 --- /dev/null +++ b/libbsm/Makefile.in @@ -0,0 +1,553 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 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@ + +# +# $P4: //depot/projects/trustedbsd/openbsm/libbsm/Makefile.in#5 $ +# + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@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 +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 = +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 = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libbsm_la_LIBADD = +am__libbsm_la_SOURCES_DIST = bsm_audit.c bsm_class.c bsm_control.c \ + bsm_event.c bsm_flags.c bsm_io.c bsm_mask.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_event.lo bsm_flags.lo bsm_io.lo bsm_mask.lo bsm_token.lo \ + bsm_user.lo $(am__objects_1) +libbsm_la_OBJECTS = $(am_libbsm_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(top_builddir)/config@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +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) +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@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +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_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_srcdir) +lib_LTLIBRARIES = libbsm.la +libbsm_la_SOURCES = bsm_audit.c bsm_class.c bsm_control.c bsm_event.c \ + bsm_flags.c bsm_io.c bsm_mask.c bsm_token.c bsm_user.c \ + $(am__append_1) +man3_MANS = \ + au_class.3 \ + au_control.3 \ + au_event.3 \ + au_free_token.3 \ + au_io.3 \ + au_mask.3 \ + au_open.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 \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libbsm/Makefile'; \ + 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 +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libbsm.la: $(libbsm_la_OBJECTS) $(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_event.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_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@ mv -f $(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@ mv -f $(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@ mv -f $(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) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" + @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 3*) ;; \ + *) ext='3' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \ + done +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 3*) ;; \ + *) ext='3' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man3dir)/$$inst"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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 + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: install-man3 + +install-pdf: install-pdf-am + +install-ps: 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-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-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 + +# 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/libbsm/au_class.3 b/libbsm/au_class.3 new file mode 100644 index 0000000..d270b52 --- /dev/null +++ b/libbsm/au_class.3 @@ -0,0 +1,120 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_class.3#6 $ +.\" +.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/libbsm/au_control.3 b/libbsm/au_control.3 new file mode 100644 index 0000000..e17ae16 --- /dev/null +++ b/libbsm/au_control.3 @@ -0,0 +1,211 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_control.3#9 $ +.\" +.Dd April 19, 2005 +.Dt AU_CONTROL 3 +.Os +.Sh NAME +.Nm setac , +.Nm endac , +.Nm getacdir , +.Nm getacmin , +.Nm getacfilesz , +.Nm getacflg , +.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 getacmin "int *min_val" +.Ft int +.Fn getacfilesz "size_t *size_val" +.Ft int +.Fn getacflg "char *auditstr" "int len" +.Ft int +.Fn getacna "char *auditstr" "int len" +.Ft int +.Fn getacpol "char *auditstr" "size_t len" +.Ft ssize_t +.Fn au_poltostr "long policy" "size_t maxsize" "char *buf" +.Ft int +.Fn au_strtopol "const char *polstr" "long *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 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 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 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 getacdir , +.Fn getacmin , +.Fn getacflg , +.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 +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. +.Sh BUGS +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/libbsm/au_event.3 b/libbsm/au_event.3 new file mode 100644 index 0000000..8fe25b4 --- /dev/null +++ b/libbsm/au_event.3 @@ -0,0 +1,171 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_event.3#8 $ +.\" +.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/libbsm/au_free_token.3 b/libbsm/au_free_token.3 new file mode 100644 index 0000000..7ce109a --- /dev/null +++ b/libbsm/au_free_token.3 @@ -0,0 +1,97 @@ +.\"- +.\" Copyright (c) 2004 Apple Computer, 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 Computer, 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_free_token.3#6 $ +.\" +.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 audit_write 3 , +.Xr au_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/libbsm/au_io.3 b/libbsm/au_io.3 new file mode 100644 index 0000000..5e9045f --- /dev/null +++ b/libbsm/au_io.3 @@ -0,0 +1,136 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_io.3#5 $ +.\" +.Dd April 19, 2005 +.Dt AU_IO 3 +.Os +.Sh NAME +.Nm au_fetch_tok , +.Nm au_print_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 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. +.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_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. +.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/libbsm/au_mask.3 b/libbsm/au_mask.3 new file mode 100644 index 0000000..2845279 --- /dev/null +++ b/libbsm/au_mask.3 @@ -0,0 +1,156 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_mask.3#6 $ +.\" +.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/libbsm/au_open.3 b/libbsm/au_open.3 new file mode 100644 index 0000000..bbb0eca --- /dev/null +++ b/libbsm/au_open.3 @@ -0,0 +1,158 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_open.3#8 $ +.\" +.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/libbsm/au_token.3 b/libbsm/au_token.3 new file mode 100644 index 0000000..e4ea65f --- /dev/null +++ b/libbsm/au_token.3 @@ -0,0 +1,235 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_token.3#13 $ +.\" +.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_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_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" "char *text" "u_int32_t v" +.Ft "token_t *" +.Fn au_to_arg64 "char n" "char *text" "u_int64_t v" +.Ft "token_t *" +.Fn au_to_arg "char n" "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" "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 "char *data" "u_int16_t bytes" +.Ft "token_t *" +.Fn au_to_file "char *file" "struct timeval tm" +.Ft "token_t *" +.Fn au_to_text "char *text" +.Ft "token_t *" +.Fn au_to_path "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 *" +.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_trailer "int rec_size" +.Ft "token_t *" +.Fn au_to_zonename "char *zonename" +.Sh DESCRIPTION +These interfaces support the allocation of BSM audit tokens, represented by +.Vt token_t , +for various data types. +.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 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/libbsm/au_user.3 b/libbsm/au_user.3 new file mode 100644 index 0000000..3016f65 --- /dev/null +++ b/libbsm/au_user.3 @@ -0,0 +1,156 @@ +.\"- +.\" 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_user.3#10 $ +.\" +.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/libbsm/audit_submit.3 b/libbsm/audit_submit.3 new file mode 100644 index 0000000..609468c --- /dev/null +++ b/libbsm/audit_submit.3 @@ -0,0 +1,132 @@ +.\" +.\" 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. +.\" 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of +.\" its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR +.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/audit_submit.3#12 $ +.\" +.Dd May 29, 2006 +.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 au_ctx . +The return token is dependent on the +.Fa status +and +.Fa reterr +arguments. +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 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> + +int +audit_bad_su(char *from_login, char *to_login) +{ + int error; + + error = audit_submit(AUE_su, getuid(), 1, EPERM, + "bad su from %s to %s", from_login, to_login); + return (error); +} +.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/libbsm/bsm_audit.c b/libbsm/bsm_audit.c new file mode 100644 index 0000000..2f6df41 --- /dev/null +++ b/libbsm/bsm_audit.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_audit.c#28 $ + */ + +#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 <errno.h> +#include <pthread.h> +#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; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * 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; + + pthread_mutex_lock(&mutex); + + 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); + } + + pthread_mutex_unlock(&mutex); + + 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); + } + + pthread_mutex_lock(&mutex); + + if (audit_rec_count == MAX_AUDIT_RECORDS) { + pthread_mutex_unlock(&mutex); + 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++; + + pthread_mutex_unlock(&mutex); + + } + + 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) +{ + token_t *header, *tok, *trailer; + size_t tot_rec_size; + u_char *dptr; + int error; + + tot_rec_size = rec->len + AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE; + header = au_to_header32(tot_rec_size, event, 0); + 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; + + pthread_mutex_lock(&mutex); + + /* Add the record to the freelist tail */ + LIST_INSERT_HEAD(&audit_free_q, rec, au_rec_q); + + pthread_mutex_unlock(&mutex); +} + +#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 + 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 + 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/libbsm/bsm_class.c b/libbsm/bsm_class.c new file mode 100644 index 0000000..5982d7e --- /dev/null +++ b/libbsm/bsm_class.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#11 $ + */ + +#include <bsm/libbsm.h> + +#include <string.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * 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 = ":"; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * 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); + + strcpy(c->ac_name, classname); + + /* + * Check for very large class description. + */ + if (strlen(classdesc) >= AU_CLASS_DESC_MAX) + return (NULL); + strcpy(c->ac_desc, classdesc); + 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; + + pthread_mutex_lock(&mutex); + cp = getauclassent_r_locked(c); + pthread_mutex_unlock(&mutex); + 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; + + pthread_mutex_lock(&mutex); + cp = getauclassent_r_locked(&c); + pthread_mutex_unlock(&mutex); + 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) +{ + + pthread_mutex_lock(&mutex); + setauclass_locked(); + pthread_mutex_unlock(&mutex); +} + +/* + * 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); + + pthread_mutex_lock(&mutex); + setauclass_locked(); + while ((cp = getauclassent_r_locked(c)) != NULL) { + if (strcmp(name, cp->ac_name) == 0) { + pthread_mutex_unlock(&mutex); + return (cp); + } + } + pthread_mutex_unlock(&mutex); + 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; + + pthread_mutex_lock(&mutex); + setauclass_locked(); + while ((cp = getauclassent_r_locked(c)) != NULL) { + if (class_number == cp->ac_class) + return (cp); + } + pthread_mutex_unlock(&mutex); + 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) +{ + + pthread_mutex_lock(&mutex); + if (fp != NULL) { + fclose(fp); + fp = NULL; + } + pthread_mutex_unlock(&mutex); +} diff --git a/libbsm/bsm_control.c b/libbsm/bsm_control.c new file mode 100644 index 0000000..dd901b7 --- /dev/null +++ b/libbsm/bsm_control.c @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#16 $ + */ + +#include <bsm/libbsm.h> + +#include <errno.h> +#include <string.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +#include <config/config.h> +#ifndef HAVE_STRLCAT +#include <compat/strlcat.h> +#endif + +/* + * 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; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * Returns the string value corresponding to the given label from the + * configuration file. + * + * Must be called with mutex held. + */ +static int +getstrfromtype_locked(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. */ + if ((nl = strrchr(linestr, '\n')) != NULL) + *nl = '\0'; + + 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 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(long policy, size_t maxsize, char *buf) +{ + int first; + + if (maxsize < 1) + return (-1); + first = 1; + buf[0] = '\0'; + + if (policy & AUDIT_CNT) { + if (strlcat(buf, "cnt", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_AHLT) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "ahlt", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_ARGV) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "argv", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_ARGE) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "arge", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_SEQ) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "seq", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_WINDATA) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "windata", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_USER) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "user", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_GROUP) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "group", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_TRAIL) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "trail", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_PATH) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "path", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_SCNT) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "scnt", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_PUBLIC) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "public", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_ZONENAME) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "zonename", maxsize) >= maxsize) + return (-1); + first = 0; + } + if (policy & AUDIT_PERZONE) { + if (!first) { + if (strlcat(buf, ",", maxsize) >= maxsize) + return (-1); + } + if (strlcat(buf, "perzone", maxsize) >= maxsize) + return (-1); + first = 0; + } + 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, long *policy) +{ + char *bufp, *string; + char *buffer; + + *policy = 0; + buffer = strdup(polstr); + if (buffer == NULL) + return (-1); + + bufp = buffer; + while ((string = strsep(&bufp, ",")) != NULL) { + if (strcmp(string, "cnt") == 0) + *policy |= AUDIT_CNT; + else if (strcmp(string, "ahlt") == 0) + *policy |= AUDIT_AHLT; + else if (strcmp(string, "argv") == 0) + *policy |= AUDIT_ARGV; + else if (strcmp(string, "arge") == 0) + *policy |= AUDIT_ARGE; + else if (strcmp(string, "seq") == 0) + *policy |= AUDIT_SEQ; + else if (strcmp(string, "winau_fstat") == 0) + *policy |= AUDIT_WINDATA; + else if (strcmp(string, "user") == 0) + *policy |= AUDIT_USER; + else if (strcmp(string, "group") == 0) + *policy |= AUDIT_GROUP; + else if (strcmp(string, "trail") == 0) + *policy |= AUDIT_TRAIL; + else if (strcmp(string, "path") == 0) + *policy |= AUDIT_PATH; + else if (strcmp(string, "scnt") == 0) + *policy |= AUDIT_SCNT; + else if (strcmp(string, "public") == 0) + *policy |= AUDIT_PUBLIC; + else if (strcmp(string, "zonename") == 0) + *policy |= AUDIT_ZONENAME; + else if (strcmp(string, "perzone") == 0) + *policy |= AUDIT_PERZONE; + else { + free(buffer); + errno = EINVAL; + return (-1); + } + } + free(buffer); + return (0); +} + +/* + * Rewind the file pointer to beginning. + */ +static void +setac_locked(void) +{ + + ptrmoved = 1; + if (fp != NULL) + fseek(fp, 0, SEEK_SET); +} + +void +setac(void) +{ + + pthread_mutex_lock(&mutex); + setac_locked(); + pthread_mutex_unlock(&mutex); +} + +/* + * Close the audit_control file. + */ +void +endac(void) +{ + + pthread_mutex_lock(&mutex); + ptrmoved = 1; + if (fp != NULL) { + fclose(fp); + fp = NULL; + } + pthread_mutex_unlock(&mutex); +} + +/* + * 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. + */ + pthread_mutex_lock(&mutex); + if (inacdir && ptrmoved) { + ptrmoved = 0; + if (fp != NULL) + fseek(fp, 0, SEEK_SET); + ret = 2; + } + if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (dir == NULL) { + pthread_mutex_unlock(&mutex); + return (-1); + } + if (strlen(dir) >= len) { + pthread_mutex_unlock(&mutex); + return (-3); + } + strcpy(name, dir); + pthread_mutex_unlock(&mutex); + return (ret); +} + +/* + * Return the minimum free diskspace value from the audit control file. + */ +int +getacmin(int *min_val) +{ + char *min; + + pthread_mutex_lock(&mutex); + setac_locked(); + if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (min == NULL) { + pthread_mutex_unlock(&mutex); + return (1); + } + *min_val = atoi(min); + pthread_mutex_unlock(&mutex); + return (0); +} + +/* + * Return the desired trail rotation size from the audit control file. + */ +int +getacfilesz(size_t *filesz_val) +{ + char *filesz, *dummy; + long long ll; + + pthread_mutex_lock(&mutex); + setac_locked(); + if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &filesz) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (filesz == NULL) { + pthread_mutex_unlock(&mutex); + errno = EINVAL; + return (1); + } + ll = strtoll(filesz, &dummy, 10); + if (*dummy != '\0') { + pthread_mutex_unlock(&mutex); + errno = EINVAL; + return (-1); + } + /* + * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 + * indicates no rotation size. + */ + if (ll < 0 || (ll > 0 && ll < MIN_AUDIT_FILE_SIZE)) { + pthread_mutex_unlock(&mutex); + errno = EINVAL; + return (-1); + } + *filesz_val = ll; + pthread_mutex_unlock(&mutex); + return (0); +} + +/* + * Return the system audit value from the audit contol file. + */ +int +getacflg(char *auditstr, int len) +{ + char *str; + + pthread_mutex_lock(&mutex); + setac_locked(); + if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (str == NULL) { + pthread_mutex_unlock(&mutex); + return (1); + } + if (strlen(str) >= len) { + pthread_mutex_unlock(&mutex); + return (-3); + } + strcpy(auditstr, str); + pthread_mutex_unlock(&mutex); + return (0); +} + +/* + * Return the non attributable flags from the audit contol file. + */ +int +getacna(char *auditstr, int len) +{ + char *str; + + pthread_mutex_lock(&mutex); + setac_locked(); + if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (str == NULL) { + pthread_mutex_unlock(&mutex); + return (1); + } + if (strlen(str) >= len) { + pthread_mutex_unlock(&mutex); + return (-3); + } + strcpy(auditstr, str); + return (0); +} + +/* + * Return the policy field from the audit control file. + */ +int +getacpol(char *auditstr, size_t len) +{ + char *str; + + pthread_mutex_lock(&mutex); + setac_locked(); + if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) { + pthread_mutex_unlock(&mutex); + return (-2); + } + if (str == NULL) { + pthread_mutex_unlock(&mutex); + return (-1); + } + if (strlen(str) >= len) { + pthread_mutex_unlock(&mutex); + return (-3); + } + strcpy(auditstr, str); + pthread_mutex_unlock(&mutex); + return (0); +} diff --git a/libbsm/bsm_event.c b/libbsm/bsm_event.c new file mode 100644 index 0000000..092d176 --- /dev/null +++ b/libbsm/bsm_event.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_event.c#13 $ + */ + +#include <bsm/libbsm.h> + +#include <string.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * 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 = ":"; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * 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); + + strcpy(e->ae_name, evname); + if (evdesc != NULL) { + if (strlen(evdesc) >= AU_EVENT_DESC_MAX) + return (NULL); + strcpy(e->ae_desc, evdesc); + } else + strcpy(e->ae_desc, ""); + + 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) +{ + + pthread_mutex_lock(&mutex); + setauevent_locked(); + pthread_mutex_unlock(&mutex); +} + +/* + * Close the open file pointers. + */ +void +endauevent(void) +{ + + pthread_mutex_lock(&mutex); + if (fp != NULL) { + fclose(fp); + fp = NULL; + } + pthread_mutex_unlock(&mutex); +} + +/* + * 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; + + pthread_mutex_lock(&mutex); + ep = getauevent_r_locked(e); + pthread_mutex_unlock(&mutex); + 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; + + pthread_mutex_lock(&mutex); + ep = getauevnam_r_locked(e, name); + pthread_mutex_unlock(&mutex); + 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; + + pthread_mutex_lock(&mutex); + ep = getauevnum_r_locked(e, event_number); + pthread_mutex_unlock(&mutex); + 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/libbsm/bsm_flags.c b/libbsm/bsm_flags.c new file mode 100644 index 0000000..e514c86 --- /dev/null +++ b/libbsm/bsm_flags.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#13 $ + */ + +#include <bsm/libbsm.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +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) { + strcpy(strptr, c.ac_desc); + strptr += strlen(c.ac_desc); + } else { + strcpy(strptr, c.ac_name); + 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/libbsm/bsm_io.c b/libbsm/bsm_io.c new file mode 100644 index 0000000..29fdc87 --- /dev/null +++ b/libbsm/bsm_io.c @@ -0,0 +1,4513 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_io.c#50 $ + */ + +#include <sys/types.h> + +#include <config/config.h> +#ifdef HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#else /* !HAVE_SYS_ENDIAN_H */ +#ifdef HAVE_MACHINE_ENDIAN_H +#include <machine/endian.h> +#else /* !HAVE_MACHINE_ENDIAN_H */ +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#else /* !HAVE_ENDIAN_H */ +#error "No supported endian.h" +#endif /* !HAVE_ENDIAN_H */ +#endif /* !HAVE_MACHINE_ENDIAN_H */ +#include <compat/endian.h> +#endif /* !HAVE_SYS_ENDIAN_H */ +#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> + +#include <bsm/audit_internal.h> + +#define READ_TOKEN_BYTES(buf, len, dest, size, bytesread, err) do { \ + if (bytesread + size > 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) <= 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) <= 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) <= 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) <= 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) > (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) +{ + int i; + + if (len > 0) { + fprintf(fp, "0x"); + for (i = 0; i < len; i++) + fprintf(fp, "%x", data[i]); + } +} + +/* + * Prints the given data bytes as a string. + */ +static void +print_string(FILE *fp, const char *str, size_t len) +{ + int i; + + if (len > 0) { + for (i = 0; i < len; i++) { + if (str[i] != '\0') + fprintf(fp, "%c", str[i]); + } + } +} + +/* + * Prints the beggining of attribute. + */ +static void +open_attr(FILE *fp, const char *str) +{ + + fprintf(fp,"%s=\"", str); +} + +/* + * Prints the end of attribute. + */ +static void +close_attr(FILE *fp) +{ + + fprintf(fp,"\" "); +} + +/* + * Prints the end of 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_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, char raw, int xml) +{ + + if (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, "<old_socket"); + break; + + case AUT_SOCKUNIX: + fprintf(fp, "<old_socket"); + 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 (raw) + fprintf(fp, "%u", type); + else + fprintf(fp, "%s", tokname); + } +} + +/* + * Prints a user value. + */ +static void +print_user(FILE *fp, u_int32_t usr, char raw) +{ + struct passwd *pwent; + + if (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, char raw) +{ + struct group *grpent; + + if (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, char raw, char sfrm) +{ + 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 (raw) + fprintf(fp, "%u", ev); + else if (sfrm) + 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, char raw) +{ + if (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, char raw) +{ + time_t timestamp; + char timestr[26]; + + if (raw) + fprintf(fp, "%u", sec); + else { + timestamp = (time_t)sec; + ctime_r(×tamp, 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, char raw) +{ + time_t timestamp; + char timestr[26]; + + if (raw) + fprintf(fp, "%u", (u_int32_t)sec); + else { + timestamp = (time_t)sec; + ctime_r(×tamp, 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, char raw) +{ + if (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, char raw) +{ + + msec &= 0xffffffff; + if (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, char raw) +{ + if (raw) + fprintf(fp, "%u", status); + else { + if (status == 0) + fprintf(fp, "success"); + else + fprintf(fp, "failure : %s", strerror(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, char raw) +{ + if (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, char raw, char sfrm, + int xml) +{ + + print_tok_type(fp, tok->id, "header", raw, xml); + if (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, raw, sfrm); + close_attr(fp); + open_attr(fp, "modifier"); + print_evmod(fp, tok->tt.hdr32.e_mod, raw); + close_attr(fp); + open_attr(fp, "time"); + print_sec32(fp, tok->tt.hdr32.s, raw); + close_attr(fp); + open_attr(fp, "msec"); + print_msec32(fp, tok->tt.hdr32.ms, 1); + 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, raw, sfrm); + print_delim(fp, del); + print_evmod(fp, tok->tt.hdr32.e_mod, raw); + print_delim(fp, del); + print_sec32(fp, tok->tt.hdr32.s, raw); + print_delim(fp, del); + print_msec32(fp, tok->tt.hdr32.ms, raw); + } +} + +/* + * 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, char raw, + char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "header_ex", raw, xml); + if (xml) { + 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, raw, sfrm); + close_attr(fp); + open_attr(fp, "modifier"); + print_evmod(fp, tok->tt.hdr32_ex.e_mod, raw); + close_attr(fp); + /* + * No attribute for additional types. + * + print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type, + tok->tt.hdr32_ex.addr); + */ + open_attr(fp, "time"); + print_sec32(fp, tok->tt.hdr32_ex.s, raw); + close_attr(fp); + open_attr(fp, "msec"); + print_msec32(fp, tok->tt.hdr32_ex.ms, raw); + 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, raw, sfrm); + print_delim(fp, del); + print_evmod(fp, tok->tt.hdr32_ex.e_mod, raw); + 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, raw); + print_delim(fp, del); + print_msec32(fp, tok->tt.hdr32_ex.ms, raw); + } +} + +/* + * 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, char raw, char sfrm, + int xml) +{ + + print_tok_type(fp, tok->id, "header", raw, xml); + if (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, raw, sfrm); + close_attr(fp); + open_attr(fp, "modifier"); + print_evmod(fp, tok->tt.hdr64.e_mod, raw); + close_attr(fp); + open_attr(fp, "time"); + print_sec64(fp, tok->tt.hdr64.s, raw); + close_attr(fp); + open_attr(fp, "msec"); + print_msec64(fp, tok->tt.hdr64.ms, raw); + 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, raw, sfrm); + print_delim(fp, del); + print_evmod(fp, tok->tt.hdr64.e_mod, raw); + print_delim(fp, del); + print_sec64(fp, tok->tt.hdr64.s, raw); + print_delim(fp, del); + print_msec64(fp, tok->tt.hdr64.ms, raw); + } +} + +/* + * 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, char raw, + char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "header_ex", raw, xml); + if (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, raw, sfrm); + close_attr(fp); + open_attr(fp, "modifier"); + print_evmod(fp, tok->tt.hdr64_ex.e_mod, raw); + close_attr(fp); + /* + * No attribute for additional types. + * + print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type, + tok->tt.hdr64_ex.addr); + */ + open_attr(fp, "time"); + print_sec64(fp, tok->tt.hdr64_ex.s, raw); + close_attr(fp); + open_attr(fp, "msec"); + print_msec64(fp, tok->tt.hdr64_ex.ms, raw); + 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, raw, sfrm); + print_delim(fp, del); + print_evmod(fp, tok->tt.hdr64_ex.e_mod, raw); + 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, raw); + print_delim(fp, del); + print_msec64(fp, tok->tt.hdr64_ex.ms, raw); + } +} + +/* + * 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "trailer", raw, xml); + if (!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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "argument", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "argument", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + char *str; + char *format; + size_t size; + int i; + + print_tok_type(fp, tok->id, "arbitrary", raw, xml); + if (!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 (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 (xml) { + open_attr(fp, "type"); + fprintf(fp, "%u", 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 (xml) { + open_attr(fp, "type"); + fprintf(fp, "%u", 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 (xml) { + open_attr(fp, "type"); + fprintf(fp, "%u", 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 (xml) { + open_attr(fp, "type"); + fprintf(fp, "%u", 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "attribute", raw, xml); + if (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, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.attr32.gid, raw); + 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, raw); + print_delim(fp, del); + print_group(fp, tok->tt.attr32.gid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "attribute", raw, xml); + if (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, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.attr64.gid, raw); + 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, raw); + print_delim(fp, del); + print_group(fp, tok->tt.attr64.gid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "exit", raw, xml); + if (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; + int 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 >=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, char raw, + __unused char sfrm, int xml) +{ + int i; + + print_tok_type(fp, tok->id, "exec arg", raw, xml); + for (i = 0; i < tok->tt.execarg.count; i++) { + if (xml) { + fprintf(fp, "<arg>"); + print_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 (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; + int 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 >=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, char raw, + __unused char sfrm, int xml) +{ + int i; + + print_tok_type(fp, tok->id, "exec env", raw, xml); + for (i = 0; i< tok->tt.execenv.count; i++) { + if (xml) { + fprintf(fp, "<env>"); + print_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 (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "file", raw, xml); + if (xml) { + open_attr(fp, "time"); + print_sec32(fp, tok->tt.file.s, raw); + close_attr(fp); + open_attr(fp, "msec"); + print_msec32(fp, tok->tt.file.ms, raw); + 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, raw); + print_delim(fp, del); + print_msec32(fp, tok->tt.file.ms, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + int i; + + print_tok_type(fp, tok->id, "group", raw, xml); + for (i = 0; i < tok->tt.grps.no; i++) { + if (xml) { + fprintf(fp, "<gid>"); + print_group(fp, tok->tt.grps.list[i], raw); + fprintf(fp, "</gid>"); + close_tag(fp, tok->id); + } else { + print_delim(fp, del); + print_group(fp, tok->tt.grps.list[i], raw); + } + } +} + +/* + * 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "ip addr", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "ip addr ex", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "ip", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "IPC", raw, xml); + if (xml) { + open_attr(fp, "ipc-type"); + print_ipctype(fp, tok->tt.ipc.type, raw); + 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, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "IPC perm", raw, xml); + if (xml) { + open_attr(fp, "uid"); + print_user(fp, tok->tt.ipcperm.uid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.ipcperm.gid, raw); + close_attr(fp); + open_attr(fp, "creator-uid"); + print_user(fp, tok->tt.ipcperm.puid, raw); + close_attr(fp); + open_attr(fp, "creator-gid"); + print_group(fp, tok->tt.ipcperm.pgid, raw); + 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, raw); + print_delim(fp, del); + print_group(fp, tok->tt.ipcperm.gid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.ipcperm.puid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.ipcperm.pgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "ip port", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "opaque", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "path", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "process", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.proc32.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.proc32.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.proc32.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.proc32.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.proc32.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc32.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc32.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc32.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc32.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + print_tok_type(fp, tok->id, "process", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.proc64.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.proc64.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.proc64.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.proc64.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.proc64.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc64.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc64.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc64.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc64.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "process_ex", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.proc32_ex.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.proc32_ex.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.proc32_ex.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.proc32_ex.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.proc32_ex.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc32_ex.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc32_ex.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc32_ex.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc32_ex.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + print_tok_type(fp, tok->id, "process_ex", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.proc64_ex.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.proc64_ex.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.proc64_ex.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.proc64_ex.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.proc64_ex.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc64_ex.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc64_ex.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.proc64_ex.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.proc64_ex.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "return", raw, xml); + if (xml) { + open_attr(fp ,"errval"); + print_retval(fp, tok->tt.ret32.status, raw); + 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, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "return", raw, xml); + if (xml) { + open_attr(fp, "errval"); + print_retval(fp, tok->tt.ret64.err, raw); + 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, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "sequence", raw, xml); + if (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.sockinet32.family, tok->len, + err); + if (err) + return (-1); + + READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet32.port, + sizeof(uint16_t), tok->len, err); + if (err) + return (-1); + + READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet32.addr, + sizeof(tok->tt.sockinet32.addr), tok->len, err); + if (err) + return (-1); + + return (0); +} + +static void +print_sock_inet32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "socket-inet", raw, xml); + if (xml) { + open_attr(fp, "type"); + print_2_bytes(fp, tok->tt.sockinet32.family, "%u"); + close_attr(fp); + open_attr(fp, "port"); + print_2_bytes(fp, ntohs(tok->tt.sockinet32.port), "%u"); + close_attr(fp); + open_attr(fp, "addr"); + print_ip_address(fp, tok->tt.sockinet32.addr); + close_attr(fp); + close_tag(fp, tok->id); + } else { + print_delim(fp, del); + print_2_bytes(fp, tok->tt.sockinet32.family, "%u"); + print_delim(fp, del); + print_2_bytes(fp, ntohs(tok->tt.sockinet32.port), "%u"); + print_delim(fp, del); + print_ip_address(fp, tok->tt.sockinet32.addr); + } +} + +/* + * socket family 2 bytes + * path 104 bytes + */ +static int +fetch_sock_unix_tok(tokenstr_t *tok, u_char *buf, int len) +{ + int err = 0; + + READ_TOKEN_U_INT16(buf, len, tok->tt.sockunix.family, tok->len, err); + if (err) + return (-1); + + READ_TOKEN_BYTES(buf, len, tok->tt.sockunix.path, 104, tok->len, + err); + if (err) + return (-1); + + return (0); +} + +static void +print_sock_unix_tok(FILE *fp, tokenstr_t *tok, char *del, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "socket-unix", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "socket", raw, xml); + if (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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "subject", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.subj32.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.subj32.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.subj32.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.subj32.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.subj32.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj32.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj32.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj32.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj32.rgid, raw); + 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); + } +} + +/* + * 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "subject", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.subj64.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.subj64.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.subj64.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.subj64.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.subj64.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj64.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj64.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj64.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj64.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "subject_ex", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.subj32_ex.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.subj32_ex.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.subj32_ex.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.subj32_ex.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.subj32_ex.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj32_ex.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj32_ex.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj32_ex.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj32_ex.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + print_tok_type(fp, tok->id, "subject_ex", raw, xml); + if (xml) { + open_attr(fp, "audit-uid"); + print_user(fp, tok->tt.subj64_ex.auid, raw); + close_attr(fp); + open_attr(fp, "uid"); + print_user(fp, tok->tt.subj64_ex.euid, raw); + close_attr(fp); + open_attr(fp, "gid"); + print_group(fp, tok->tt.subj64_ex.egid, raw); + close_attr(fp); + open_attr(fp, "ruid"); + print_user(fp, tok->tt.subj64_ex.ruid, raw); + close_attr(fp); + open_attr(fp, "rgid"); + print_group(fp, tok->tt.subj64_ex.rgid, raw); + 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, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj64_ex.euid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj64_ex.egid, raw); + print_delim(fp, del); + print_user(fp, tok->tt.subj64_ex.ruid, raw); + print_delim(fp, del); + print_group(fp, tok->tt.subj64_ex.rgid, raw); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "text", raw, xml); + if (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 type 2 bytes + * local port 2 bytes + * address type/length 4 bytes + * local Internet address 4 bytes + * remote port 4 bytes + * address type/length 4 bytes + * remote Internet address 4 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.type, tok->len, + err); + if (err) + return (-1); + + READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_port, + sizeof(uint16_t), tok->len, err); + if (err) + return (-1); + + READ_TOKEN_U_INT32(buf, len, tok->tt.socket_ex32.l_ad_type, tok->len, + err); + if (err) + return (-1); + + 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); + + READ_TOKEN_U_INT32(buf, len, tok->tt.socket_ex32.r_ad_type, tok->len, + err); + if (err) + return (-1); + + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "socket", raw, xml); + if (xml) { + 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_address(fp, tok->tt.socket_ex32.l_addr); + close_attr(fp); + open_attr(fp, "faddr"); + print_ip_address(fp, tok->tt.socket_ex32.r_addr); + close_attr(fp); + open_attr(fp, "fport"); + print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x"); + close_attr(fp); + close_tag(fp, tok->id); + } else { + 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_address(fp, 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_address(fp, 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, char raw, + __unused char sfrm, int xml) +{ + + if (!xml) { + print_tok_type(fp, tok->id, "unknown", raw, 0); + 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, char raw, + __unused char sfrm, int xml) +{ + + print_tok_type(fp, tok->id, "zone", raw, xml); + if (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_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)); + + default: + return (fetch_invalid_tok(tok, buf, len)); + } +} + +/* + * 'prints' the token out to outfp. + */ +void +au_print_tok(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm) +{ + + switch(tok->id) { + case AUT_HEADER32: + print_header32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_HEADER32_EX: + print_header32_ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_HEADER64: + print_header64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_HEADER64_EX: + print_header64_ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_TRAILER: + print_trailer_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_ARG32: + print_arg32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_ARG64: + print_arg64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_DATA: + print_arb_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_ATTR32: + print_attr32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_ATTR64: + print_attr64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_EXIT: + print_exit_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_EXEC_ARGS: + print_execarg_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_EXEC_ENV: + print_execenv_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_OTHER_FILE32: + print_file_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_NEWGROUPS: + print_newgroups_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IN_ADDR: + print_inaddr_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IN_ADDR_EX: + print_inaddr_ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IP: + print_ip_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IPC: + print_ipc_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IPC_PERM: + print_ipcperm_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_IPORT: + print_iport_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_OPAQUE: + print_opaque_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_PATH: + print_path_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_PROCESS32: + print_process32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_PROCESS32_EX: + print_process32ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_PROCESS64: + print_process64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_PROCESS64_EX: + print_process64ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_RETURN32: + print_return32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_RETURN64: + print_return64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SEQ: + print_seq_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SOCKET: + print_socket_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SOCKINET32: + print_sock_inet32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SOCKUNIX: + print_sock_unix_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SUBJECT32: + print_subject32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SUBJECT64: + print_subject64_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SUBJECT32_EX: + print_subject32ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SUBJECT64_EX: + print_subject64ex_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_TEXT: + print_text_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_SOCKET_EX: + print_socketex32_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + case AUT_ZONENAME: + print_zonename_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + return; + + default: + print_invalid_tok(outfp, tok, del, raw, sfrm, AU_PLAIN); + } +} + +/* + * '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) +{ + + switch(tok->id) { + case AUT_HEADER32: + print_header32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_HEADER32_EX: + print_header32_ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_HEADER64: + print_header64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_HEADER64_EX: + print_header64_ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_TRAILER: + print_trailer_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_ARG32: + print_arg32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_ARG64: + print_arg64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_DATA: + print_arb_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_ATTR32: + print_attr32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_ATTR64: + print_attr64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_EXIT: + print_exit_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_EXEC_ARGS: + print_execarg_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_EXEC_ENV: + print_execenv_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_OTHER_FILE32: + print_file_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_NEWGROUPS: + print_newgroups_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IN_ADDR: + print_inaddr_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IN_ADDR_EX: + print_inaddr_ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IP: + print_ip_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IPC: + print_ipc_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IPC_PERM: + print_ipcperm_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_IPORT: + print_iport_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_OPAQUE: + print_opaque_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_PATH: + print_path_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_PROCESS32: + print_process32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_PROCESS32_EX: + print_process32ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_PROCESS64: + print_process64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_PROCESS64_EX: + print_process64ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_RETURN32: + print_return32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_RETURN64: + print_return64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SEQ: + print_seq_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SOCKET: + print_socket_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SOCKINET32: + print_sock_inet32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SOCKUNIX: + print_sock_unix_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SUBJECT32: + print_subject32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SUBJECT64: + print_subject64_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SUBJECT32_EX: + print_subject32ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SUBJECT64_EX: + print_subject64ex_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_TEXT: + print_text_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_SOCKET_EX: + print_socketex32_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + case AUT_ZONENAME: + print_zonename_tok(outfp, tok, del, raw, sfrm, AU_XML); + return; + + default: + print_invalid_tok(outfp, tok, del, raw, sfrm, AU_XML); + } +} + +/* + * 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 = malloc(recsize * sizeof(u_char)); + if (*buf == NULL) + return (-1); + bptr = *buf; + memset(bptr, 0, recsize); + + /* 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/libbsm/bsm_mask.c b/libbsm/bsm_mask.c new file mode 100644 index 0000000..4914dd3 --- /dev/null +++ b/libbsm/bsm_mask.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_mask.c#13 $ + */ + +#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> + +#include <pthread.h> +#include <stdlib.h> +#include <string.h> + +/* MT-Safe */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +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); + + + pthread_mutex_lock(&mutex); + if (firsttime) { + firsttime = 0; + if ( -1 == load_event_table()) { + pthread_mutex_unlock(&mutex); + return (-1); + } + } + switch (flag) { + case AU_PRS_REREAD: + flush_cache(); + if (load_event_table() == -1) { + pthread_mutex_unlock(&mutex); + return (-1); + } + ev = read_from_cache(event); + break; + case AU_PRS_USECACHE: + ev = read_from_cache(event); + break; + default: + ev = NULL; + } + if (ev == NULL) { + pthread_mutex_unlock(&mutex); + 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); + pthread_mutex_unlock(&mutex); + if (effmask != 0) + return (1); + return (0); +} diff --git a/libbsm/bsm_notify.c b/libbsm/bsm_notify.c new file mode 100644 index 0000000..e7d3ea2 --- /dev/null +++ b/libbsm/bsm_notify.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_notify.c#13 $ + */ + +/* + * 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 long 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 (auditon(A_GETCOND, &au_cond, sizeof(long)) < 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 (auditon(A_GETCOND, &au_cond, sizeof(long)) < 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 + unsigned long au_cond; + + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno != ENOSYS) { + syslog(LOG_ERR, "Audit status check failed (%s)", + strerror(errno)); + } + return (1); + } + if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) + return (1); + return (0); +#endif /* !__APPLE__ */ +} diff --git a/libbsm/bsm_token.c b/libbsm/bsm_token.c new file mode 100644 index 0000000..c660895 --- /dev/null +++ b/libbsm/bsm_token.c @@ -0,0 +1,1399 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_token.c#63 $ + */ + +#include <sys/types.h> + +#include <config/config.h> +#ifdef HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#else /* !HAVE_SYS_ENDIAN_H */ +#ifdef HAVE_MACHINE_ENDIAN_H +#include <machine/endian.h> +#else /* !HAVE_MACHINE_ENDIAN_H */ +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#else /* !HAVE_ENDIAN_H */ +#error "No supported endian.h" +#endif /* !HAVE_ENDIAN_H */ +#endif /* !HAVE_MACHINE_ENDIAN_H */ +#include <compat/endian.h> +#endif /* !HAVE_SYS_ENDIAN_H */ +#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) = malloc((length) * sizeof(u_char)); \ + if ((dptr) == NULL) { \ + free(t); \ + (t) = NULL; \ + } else \ + memset((dptr), 0, (length)); \ + } else \ + (dptr) = NULL; \ + assert(t == NULL || dptr != NULL); \ +} while (0) + +/* + * 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, 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, 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, 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_int16_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); + + /* + * Darwin defines the size for the file mode + * as 2 bytes; BSM defines 4 so pad with 0 + */ + 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_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_int16_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); + + /* + * Darwin defines the size for the file mode + * as 2 bytes; BSM defines 4 so pad with 0 + */ + 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, 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); + + 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 = AF_INET6; + + 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, 12 * sizeof(u_int16_t) + sizeof(u_int32_t)); + if (t == NULL) + return (NULL); + + ADD_U_CHAR(dptr, AUT_IPC_PERM); + + /* + * Darwin defines the sizes for ipc_perm members + * as 2 bytes; BSM defines 4 so pad with 0 + */ + 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); + + 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 + ADD_U_INT16(dptr, perm->seq); +#endif + +#ifdef HAVE_IPC_PERM___KEY + ADD_U_INT32(dptr, perm->__key); +#else + ADD_U_INT32(dptr, perm->key); +#endif + + 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(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(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(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_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(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); + 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); + 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 family 2 bytes + * path 104 bytes + */ +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, AU_SOCK_UNIX_TOKEN); + /* 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 Darwin, sin6_family is one octet, but BSM defines the token + * to store two. So we copy in a 0 first. + */ + 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; + + if (getaudit(&auinfo) != 0) + return (NULL); + + return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(), + getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.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); + } + + totlen += count * sizeof(char); /* nul terminations. */ + 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 + * zonename length 2 bytes + * zonename N bytes + 1 terminating NULL byte + */ +token_t * +au_to_zonename(char *zonename) +{ + u_char *dptr = NULL; + u_int16_t textlen; + token_t *t; + + textlen = strlen(zonename); + textlen += 1; + GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen); + ADD_U_CHAR(dptr, AUT_ZONENAME); + ADD_U_INT16(dptr, textlen); + ADD_STRING(dptr, zonename, textlen); + 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); + } + + totlen += sizeof(char) * 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 + * 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_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) +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)); +} +#endif + +/* + * 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 = TRAILER_PAD_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/libbsm/bsm_user.c b/libbsm/bsm_user.c new file mode 100644 index 0000000..c00d139 --- /dev/null +++ b/libbsm/bsm_user.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#15 $ + */ + +#include <bsm/libbsm.h> + +#include <string.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * 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 = ":"; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * 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); + + strcpy(u->au_name, username); + 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) +{ + + pthread_mutex_lock(&mutex); + setauuser_locked(); + pthread_mutex_unlock(&mutex); +} + +/* + * Close the file descriptor + */ +void +endauuser(void) +{ + + pthread_mutex_lock(&mutex); + if (fp != NULL) { + fclose(fp); + fp = NULL; + } + pthread_mutex_unlock(&mutex); +} + +/* + * 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; + + pthread_mutex_lock(&mutex); + up = getauuserent_r_locked(u); + pthread_mutex_unlock(&mutex); + 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); + + pthread_mutex_lock(&mutex); + + setauuser_locked(); + while ((up = getauuserent_r_locked(u)) != NULL) { + if (strcmp(name, u->au_name) == 0) { + pthread_mutex_unlock(&mutex); + return (u); + } + } + + pthread_mutex_unlock(&mutex); + 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/libbsm/bsm_wrappers.c b/libbsm/bsm_wrappers.c new file mode 100644 index 0000000..f001e5f --- /dev/null +++ b/libbsm/bsm_wrappers.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2004 Apple Computer, 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 Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#24 $ + */ + +#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; + long acond; + va_list ap; + pid_t pid; + int error, afd, subj_ex; + struct auditinfo ai; + struct auditinfo_addr aia; + + if (auditon(A_GETCOND, &acond, sizeof(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); + /* XXXCSJP we should be doing a pre-select here */ + afd = au_open(); + if (afd < 0) { + error = errno; + syslog(LOG_AUTH | LOG_ERR, "audit: au_open failed: %s", + strerror(errno)); + errno = error; + return (-1); + } + /* + * Some operating systems do not have getaudit_addr(2) implemented + * yet. So we try to use getaudit(2) first, if the subject is + * using IPv6, then we will have to try getaudit_addr(2). Failing + * this, we return error. + */ + subj_ex = 0; + error = getaudit(&ai); + if (error < 0 && errno == E2BIG) { + error = getaudit_addr(&aia, sizeof(aia)); + if (error == 0) + subj_ex = 1; + } + if (error < 0) { + error = errno; + syslog(LOG_AUTH | LOG_ERR, "audit: getaudit failed: %s", + strerror(errno)); + errno = error; + return (-1); + } + pid = getpid(); + if (subj_ex == 0) + token = au_to_subject32(auid, geteuid(), getegid(), + getuid(), getgid(), pid, pid, &ai.ai_termid); + 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(status, reterr); + if (token == NULL) { + syslog(LOG_AUTH | LOG_ERR, + "audit: enable 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_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__ */ diff --git a/libbsm/libbsm.3 b/libbsm/libbsm.3 new file mode 100644 index 0000000..e84ea94 --- /dev/null +++ b/libbsm/libbsm.3 @@ -0,0 +1,232 @@ +.\"- +.\" 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 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. +.\" +.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/libbsm.3#13 $ +.\" +.Dd April 19, 2005 +.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_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 . +.Sh SEE ALSO +.Xr au_class 3 , +.Xr audit_submit 3 , +.Xr au_mask 3 , +.Xr au_notify 3 , +.Xr au_stream 3 , +.Xr au_token 3 , +.Xr au_user 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. |