diff options
Diffstat (limited to 'contrib/openbsm/bin')
65 files changed, 19601 insertions, 0 deletions
diff --git a/contrib/openbsm/bin/Makefile.am b/contrib/openbsm/bin/Makefile.am new file mode 100644 index 0000000..15a3dbc --- /dev/null +++ b/contrib/openbsm/bin/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS = \ + auditdistd \ + auditfilterd \ + auditreduce \ + praudit + +if HAVE_AUDIT_SYSCALLS +SUBDIRS += \ + audit \ + auditd +endif diff --git a/contrib/openbsm/bin/Makefile.in b/contrib/openbsm/bin/Makefile.in new file mode 100644 index 0000000..e2b3754 --- /dev/null +++ b/contrib/openbsm/bin/Makefile.in @@ -0,0 +1,579 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_AUDIT_SYSCALLS_TRUE@am__append_1 = \ +@HAVE_AUDIT_SYSCALLS_TRUE@ audit \ +@HAVE_AUDIT_SYSCALLS_TRUE@ auditd + +subdir = bin +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = auditdistd auditfilterd auditreduce praudit audit \ + auditd +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = auditdistd auditfilterd auditreduce praudit $(am__append_1) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/audit/Makefile.am b/contrib/openbsm/bin/audit/Makefile.am new file mode 100644 index 0000000..d0af56c --- /dev/null +++ b/contrib/openbsm/bin/audit/Makefile.am @@ -0,0 +1,19 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = audit +audit_LDADD = $(top_builddir)/libbsm/libbsm.la +man8_MANS = audit.8 + +if USE_MACH_IPC +audit_SOURCES = auditd_controlUser.c audit.c +CLEANFILES = auditd_controlUser.c auditd_control.h + +auditd_controlUser.c auditd_control.h: $(top_srcdir)/bin/auditd/auditd_control.defs + $(MIG) -user auditd_controlUser.c -header auditd_control.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs +else +audit_SOURCES = audit.c +endif diff --git a/contrib/openbsm/bin/audit/Makefile.in b/contrib/openbsm/bin/audit/Makefile.in new file mode 100644 index 0000000..b7b8361 --- /dev/null +++ b/contrib/openbsm/bin/audit/Makefile.in @@ -0,0 +1,657 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = audit$(EXEEXT) +subdir = bin/audit +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" +PROGRAMS = $(sbin_PROGRAMS) +am__audit_SOURCES_DIST = audit.c auditd_controlUser.c +@USE_MACH_IPC_FALSE@am_audit_OBJECTS = audit.$(OBJEXT) +@USE_MACH_IPC_TRUE@am_audit_OBJECTS = auditd_controlUser.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ audit.$(OBJEXT) +audit_OBJECTS = $(am_audit_OBJECTS) +audit_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(audit_SOURCES) +DIST_SOURCES = $(am__audit_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man8_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +audit_LDADD = $(top_builddir)/libbsm/libbsm.la +man8_MANS = audit.8 +@USE_MACH_IPC_FALSE@audit_SOURCES = audit.c +@USE_MACH_IPC_TRUE@audit_SOURCES = auditd_controlUser.c audit.c +@USE_MACH_IPC_TRUE@CLEANFILES = auditd_controlUser.c auditd_control.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/audit/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/audit/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +audit$(EXEEXT): $(audit_OBJECTS) $(audit_DEPENDENCIES) $(EXTRA_audit_DEPENDENCIES) + @rm -f audit$(EXEEXT) + $(LINK) $(audit_OBJECTS) $(audit_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_controlUser.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man8 install-pdf install-pdf-am install-ps \ + install-ps-am install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man8 \ + uninstall-sbinPROGRAMS + + +@USE_MACH_IPC_TRUE@auditd_controlUser.c auditd_control.h: $(top_srcdir)/bin/auditd/auditd_control.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user auditd_controlUser.c -header auditd_control.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/audit/audit.8 b/contrib/openbsm/bin/audit/audit.8 new file mode 100644 index 0000000..b9f98b3 --- /dev/null +++ b/contrib/openbsm/bin/audit/audit.8 @@ -0,0 +1,105 @@ +.\" Copyright (c) 2004-2009 Apple Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Apple Inc. ("Apple") nor the names of +.\" its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd July 25, 2015 +.Dt AUDIT 8 +.Os +.Sh NAME +.Nm audit +.Nd audit management utility +.Sh SYNOPSIS +.Nm +.Fl e | i | n | s | t +.Sh DESCRIPTION +The +.Nm +utility controls the state of the audit system. +One of the following flags is required as an argument to +.Nm : +.Bl -tag -width indent +.It Fl e +Forces the audit system to immediately remove audit log files that +meet the expiration criteria specified in the audit control file without +doing a log rotation. +.It Fl i +Initializes and starts auditing. +This option is currently for Mac OS X only +and requires +.Xr auditd 8 +to be configured to run under +.Xr launchd 8 . +.It Fl n +Forces the audit system to close the existing audit log file and rotate to +a new log file in a location specified in the audit control file. +Also, audit log files that meet the expiration criteria specified in the +audit control file will be removed. +.It Fl s +Specifies that the audit system should [re]synchronize its +configuration from the audit control file. +A new log file will be created. +.It Fl t +Specifies that the audit system should terminate. +Log files are closed +and renamed to indicate the time of the shutdown. +.El +.Sh NOTES +The +.Xr auditd 8 +daemon must already be running. +Optionally, it can be configured to be started +on-demand by +.Xr launchd 8 +(Mac OS X only). +The +.Nm +utility requires audit administrator privileges for successful operation. +.Sh FILES +.Bl -tag -width ".Pa /etc/security/audit_control" -compact +.It Pa /etc/security/audit_control +Audit policy file used to configure the auditing system. +.El +.Sh SEE ALSO +.Xr audit 4 , +.Xr audit_control 5 , +.Xr auditd 8 , +.Xr launchd 8 (Mac OS X) +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +.An -nosplit +This software was created by McAfee Research, the security research division +of McAfee, Inc., under contract to Apple Computer Inc. +Additional authors include +.An Wayne Salamon , +.An Robert Watson , +and SPARTA Inc. +.Pp +The Basic Security Module (BSM) interface to audit records and audit event +stream format were defined by Sun Microsystems. diff --git a/contrib/openbsm/bin/audit/audit.c b/contrib/openbsm/bin/audit/audit.c new file mode 100644 index 0000000..dfe956f --- /dev/null +++ b/contrib/openbsm/bin/audit/audit.c @@ -0,0 +1,179 @@ +/*- + * Copyright (c) 2005-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Program to trigger the audit daemon with a message that is either: + * - Open a new audit log file + * - Read the audit control file and take action on it + * - Close the audit log file and exit + * + */ + +#include <sys/types.h> +#include <config/config.h> +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else /* !HAVE_FULL_QUEUE_H */ +#include <compat/queue.h> +#endif /* !HAVE_FULL_QUEUE_H */ +#include <sys/uio.h> + +#include <bsm/libbsm.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +static int send_trigger(int); + +#ifdef USE_MACH_IPC +#include <mach/mach.h> +#include <servers/netname.h> +#include <mach/message.h> +#include <mach/port.h> +#include <mach/mach_error.h> +#include <mach/host_special_ports.h> +#include <servers/bootstrap.h> + +#include "auditd_control.h" + +/* + * XXX The following are temporary until these can be added to the kernel + * audit.h header. + */ +#ifndef AUDIT_TRIGGER_INITIALIZE +#define AUDIT_TRIGGER_INITIALIZE 7 +#endif +#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS +#define AUDIT_TRIGGER_EXPIRE_TRAILS 8 +#endif + +static int +send_trigger(int trigger) +{ + mach_port_t serverPort; + kern_return_t error; + + error = host_get_audit_control_port(mach_host_self(), &serverPort); + if (error != KERN_SUCCESS) { + if (geteuid() != 0) { + errno = EPERM; + perror("audit requires root privileges"); + } else + mach_error("Cannot get auditd_control Mach port:", + error); + return (-1); + } + + error = auditd_control(serverPort, trigger); + if (error != KERN_SUCCESS) { + mach_error("Error sending trigger: ", error); + return (-1); + } + + return (0); +} + +#else /* ! USE_MACH_IPC */ + +static int +send_trigger(int trigger) +{ + int error; + + error = audit_send_trigger(&trigger); + if (error != 0) { + if (error == EPERM) + perror("audit requires root privileges"); + else + perror("Error sending trigger"); + return (-1); + } + + return (0); +} +#endif /* ! USE_MACH_IPC */ + +static void +usage(void) +{ + + (void)fprintf(stderr, "Usage: audit -e | -i | -n | -s | -t \n"); + exit(-1); +} + +/* + * Main routine to process command line options. + */ +int +main(int argc, char **argv) +{ + int ch; + unsigned int trigger = 0; + + if (argc != 2) + usage(); + + while ((ch = getopt(argc, argv, "einst")) != -1) { + switch(ch) { + + case 'e': + trigger = AUDIT_TRIGGER_EXPIRE_TRAILS; + break; + + case 'i': + trigger = AUDIT_TRIGGER_INITIALIZE; + break; + + case 'n': + trigger = AUDIT_TRIGGER_ROTATE_USER; + break; + + case 's': + trigger = AUDIT_TRIGGER_READ_FILE; + break; + + case 't': + trigger = AUDIT_TRIGGER_CLOSE_AND_DIE; + break; + + case '?': + default: + usage(); + break; + } + } + if (send_trigger(trigger) < 0) + exit(-1); + + printf("Trigger sent.\n"); + exit (0); +} diff --git a/contrib/openbsm/bin/auditd/Makefile.am b/contrib/openbsm/bin/auditd/Makefile.am new file mode 100644 index 0000000..8a2a9df --- /dev/null +++ b/contrib/openbsm/bin/auditd/Makefile.am @@ -0,0 +1,22 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = auditd +auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la +man8_MANS = auditd.8 + +if USE_MACH_IPC +auditd_SOURCES = auditd_controlServer.c audit_triggersServer.c audit_warn.c auditd.c auditd_darwin.c +CLEANFILES = auditd_control_server.c auditd_controlServer.h audit_triggersServer.c audit_triggersServer.h + +auditd_controlServer.c auditd_controlServer.h: auditd_control.defs + $(MIG) -user /dev/null -header /dev/null -server auditd_controlServer.c -sheader auditd_controlServer.h $(top_srcdir)/bin/auditd/auditd_control.defs + +audit_triggersServer.c audit_triggersServer.h: audit_triggers.defs + $(MIG) -user /dev/null -header /dev/null -server audit_triggersServer.c -sheader audit_triggersServer.h $(top_srcdir)/bin/auditd/audit_triggers.defs +else +auditd_SOURCES = audit_warn.c auditd.c auditd_fbsd.c +endif diff --git a/contrib/openbsm/bin/auditd/Makefile.in b/contrib/openbsm/bin/auditd/Makefile.in new file mode 100644 index 0000000..3fa44f1 --- /dev/null +++ b/contrib/openbsm/bin/auditd/Makefile.in @@ -0,0 +1,669 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = auditd$(EXEEXT) +subdir = bin/auditd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" +PROGRAMS = $(sbin_PROGRAMS) +am__auditd_SOURCES_DIST = audit_warn.c auditd.c auditd_fbsd.c \ + auditd_controlServer.c audit_triggersServer.c auditd_darwin.c +@USE_MACH_IPC_FALSE@am_auditd_OBJECTS = audit_warn.$(OBJEXT) \ +@USE_MACH_IPC_FALSE@ auditd.$(OBJEXT) auditd_fbsd.$(OBJEXT) +@USE_MACH_IPC_TRUE@am_auditd_OBJECTS = auditd_controlServer.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ audit_triggersServer.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ audit_warn.$(OBJEXT) auditd.$(OBJEXT) \ +@USE_MACH_IPC_TRUE@ auditd_darwin.$(OBJEXT) +auditd_OBJECTS = $(am_auditd_OBJECTS) +auditd_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la \ + $(top_builddir)/libauditd/libauditd.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(auditd_SOURCES) +DIST_SOURCES = $(am__auditd_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man8_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la +man8_MANS = auditd.8 +@USE_MACH_IPC_FALSE@auditd_SOURCES = audit_warn.c auditd.c auditd_fbsd.c +@USE_MACH_IPC_TRUE@auditd_SOURCES = auditd_controlServer.c audit_triggersServer.c audit_warn.c auditd.c auditd_darwin.c +@USE_MACH_IPC_TRUE@CLEANFILES = auditd_control_server.c auditd_controlServer.h audit_triggersServer.c audit_triggersServer.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/auditd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +auditd$(EXEEXT): $(auditd_OBJECTS) $(auditd_DEPENDENCIES) $(EXTRA_auditd_DEPENDENCIES) + @rm -f auditd$(EXEEXT) + $(LINK) $(auditd_OBJECTS) $(auditd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_triggersServer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_warn.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_controlServer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_darwin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_fbsd.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man8 install-pdf install-pdf-am install-ps \ + install-ps-am install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man8 \ + uninstall-sbinPROGRAMS + + +@USE_MACH_IPC_TRUE@auditd_controlServer.c auditd_controlServer.h: auditd_control.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server auditd_controlServer.c -sheader auditd_controlServer.h $(top_srcdir)/bin/auditd/auditd_control.defs + +@USE_MACH_IPC_TRUE@audit_triggersServer.c audit_triggersServer.h: audit_triggers.defs +@USE_MACH_IPC_TRUE@ $(MIG) -user /dev/null -header /dev/null -server audit_triggersServer.c -sheader audit_triggersServer.h $(top_srcdir)/bin/auditd/audit_triggers.defs + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/auditd/audit_triggers.defs b/contrib/openbsm/bin/auditd/audit_triggers.defs new file mode 100644 index 0000000..9fe2c35 --- /dev/null +++ b/contrib/openbsm/bin/auditd/audit_triggers.defs @@ -0,0 +1 @@ +#include <mach/audit_triggers.defs> diff --git a/contrib/openbsm/bin/auditd/audit_warn.c b/contrib/openbsm/bin/auditd/audit_warn.c new file mode 100644 index 0000000..6bd2b84 --- /dev/null +++ b/contrib/openbsm/bin/auditd/audit_warn.c @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2005-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "auditd.h" + +/* + * Write an audit-related error to the system log via syslog(3). + */ +static int +auditwarnlog(char *args[]) +{ + char *loc_args[9]; + pid_t pid; + int i; + + loc_args[0] = AUDITWARN_SCRIPT; + for (i = 0; args[i] != NULL && i < 8; i++) + loc_args[i+1] = args[i]; + loc_args[i+1] = NULL; + + pid = fork(); + if (pid == -1) + return (-1); + if (pid == 0) { + /* + * Child. + */ + execv(AUDITWARN_SCRIPT, loc_args); + syslog(LOG_ERR, "Could not exec %s (%m)\n", + AUDITWARN_SCRIPT); + exit(1); + } + /* + * Parent. + */ + return (0); +} + +/* + * Indicates that the hard limit for all filesystems has been exceeded. + */ +int +audit_warn_allhard(void) +{ + char *args[2]; + + args[0] = HARDLIM_ALL_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that the soft limit for all filesystems has been exceeded. + */ +int +audit_warn_allsoft(void) +{ + char *args[2]; + + args[0] = SOFTLIM_ALL_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that someone other than the audit daemon turned off auditing. + * XXX Its not clear at this point how this function will be invoked. + * + * XXXRW: This function is not used. + */ +int +audit_warn_auditoff(void) +{ + char *args[2]; + + args[0] = AUDITOFF_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicate that a trail file has been closed, so can now be post-processed. + */ +int +audit_warn_closefile(char *filename) +{ + char *args[3]; + + args[0] = CLOSEFILE_WARN; + args[1] = filename; + args[2] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that the audit deammn is already running + */ +int +audit_warn_ebusy(void) +{ + char *args[2]; + + args[0] = EBUSY_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that there is a problem getting the directory from + * audit_control. + * + * XXX Note that we take the filename instead of a count as the argument here + * (different from BSM). + */ +int +audit_warn_getacdir(char *filename) +{ + char *args[3]; + + args[0] = GETACDIR_WARN; + args[1] = filename; + args[2] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that the hard limit for this file has been exceeded. + */ +int +audit_warn_hard(char *filename) +{ + char *args[3]; + + args[0] = HARDLIM_WARN; + args[1] = filename; + args[2] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that auditing could not be started. + */ +int +audit_warn_nostart(void) +{ + char *args[2]; + + args[0] = NOSTART_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicaes that an error occrred during the orderly shutdown of the audit + * daemon. + */ +int +audit_warn_postsigterm(void) +{ + char *args[2]; + + args[0] = POSTSIGTERM_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that the soft limit for this file has been exceeded. + */ +int +audit_warn_soft(char *filename) +{ + char *args[3]; + + args[0] = SOFTLIM_WARN; + args[1] = filename; + args[2] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that the temporary audit file already exists indicating a fatal + * error. + */ +int +audit_warn_tmpfile(void) +{ + char *args[2]; + + args[0] = TMPFILE_WARN; + args[1] = NULL; + + return (auditwarnlog(args)); +} + +/* + * Indicates that this trail file has expired and was removed. + */ +int +audit_warn_expired(char *filename) +{ + char *args[3]; + + args[0] = EXPIRED_WARN; + args[1] = filename; + args[2] = NULL; + + return (auditwarnlog(args)); +} diff --git a/contrib/openbsm/bin/auditd/auditd.8 b/contrib/openbsm/bin/auditd/auditd.8 new file mode 100644 index 0000000..c76dfca --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd.8 @@ -0,0 +1,140 @@ +.\" Copyright (c) 2004 Apple Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Apple Inc. ("Apple") nor the names of +.\" its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd July 25, 2015 +.Dt AUDITD 8 +.Os +.Sh NAME +.Nm auditd +.Nd audit log management daemon +.Sh SYNOPSIS +.Nm +.Op Fl d | l +.Sh DESCRIPTION +The +.Nm +daemon responds to requests from the +.Xr audit 8 +utility and notifications +from the kernel. +It manages the resulting audit log files and specified +log file locations. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d +Starts the daemon in debug mode \[em] it will not daemonize. +.It Fl l +This option is for when +.Nm +is configured to start on-demand using +.Xr launchd 8 . +.El +.Pp +Optionally, the audit review group "audit" may be created. +Non-privileged +users that are members of this group may read the audit trail log files. +.Sh NOTE +To assure uninterrupted audit support, the +.Nm +daemon should not be started and stopped manually. +Instead, the +.Xr audit 8 +command +should be used to inform the daemon to change state/configuration after altering +the +.Pa audit_control +file. +.Pp +If +.Nm +is started on-demand by +.Xr launchd 8 +then auditing should only be started and stopped with +.Xr audit 8 . +.Pp +On Mac OS X, +.Nm +uses the +.Xr asl 3 +API for writing system log messages. +Therefore, only the audit administrator +and members of the audit review group will be able to read the +system log entries. +.Sh FILES +.Bl -tag -width ".Pa /etc/security" -compact +.It Pa /var/audit +Default directory for storing audit log files. +.Pp +.It Pa /etc/security +The directory containing the auditing configuration files +.Xr audit_class 5 , +.Xr audit_control 5 , +.Xr audit_event 5 , +and +.Xr audit_warn 5 . +.El +.Sh COMPATIBILITY +The historical +.Fl h +and +.Fl s +flags are now configured using +.Xr audit_control 5 +policy flags +.Cm ahlt +and +.Cm cnt , +and are no longer available as arguments to +.Nm . +.Sh SEE ALSO +.Xr asl 3 , +.Xr libauditd 3 , +.Xr audit 4 , +.Xr audit_class 5 , +.Xr audit_control 5 , +.Xr audit_event 5 , +.Xr audit_warn 5 , +.Xr audit 8 , +.Xr auditdistd 8 , +.Xr launchd 8 (Mac OS X) +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +.An -nosplit +This software was created by McAfee Research, the security research division +of McAfee, Inc., under contract to Apple Computer Inc. +Additional authors include +.An Wayne Salamon , +.An Robert Watson , +and SPARTA Inc. +.Pp +The Basic Security Module (BSM) interface to audit records and audit event +stream format were defined by Sun Microsystems. diff --git a/contrib/openbsm/bin/auditd/auditd.c b/contrib/openbsm/bin/auditd/auditd.c new file mode 100644 index 0000000..a4357bd --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd.c @@ -0,0 +1,850 @@ +/*- + * Copyright (c) 2004-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <config/config.h> + +#include <sys/dirent.h> +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else /* !HAVE_FULL_QUEUE_H */ +#include <compat/queue.h> +#endif /* !HAVE_FULL_QUEUE_H */ +#include <sys/mman.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <bsm/audit.h> +#include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> +#include <bsm/libbsm.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> + +#include "auditd.h" + +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +/* + * XXX The following are temporary until these can be added to the kernel + * audit.h header. + */ +#ifndef AUDIT_TRIGGER_INITIALIZE +#define AUDIT_TRIGGER_INITIALIZE 7 +#endif +#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS +#define AUDIT_TRIGGER_EXPIRE_TRAILS 8 +#endif + + +/* + * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and + * http://wiki.freebsd.org/launchd for more information. + * + * In order for auditd to work "on demand" with launchd(8) it can't: + * call daemon(3) + * call fork and having the parent process exit + * change uids or gids. + * set up the current working directory or chroot. + * set the session id + * change stdio to /dev/null. + * call setrusage(2) + * call setpriority(2) + * Ignore SIGTERM. + * auditd (in 'launchd mode') is launched on demand so it must catch + * SIGTERM to exit cleanly. + */ +static int launchd_flag = 0; + +/* + * The GID of the audit review group (if used). The audit trail files and + * system logs (Mac OS X only) can only be reviewed by members of this group + * or the audit administrator (aka. "root"). + */ +static gid_t audit_review_gid = -1; + +/* + * The path and file name of the last audit trail file. + */ +static char *lastfile = NULL; + +/* + * Error starting auditd. Run warn script and exit. + */ +static void +fail_exit(void) +{ + + audit_warn_nostart(); + exit(1); +} + +/* + * Follow the 'current' symlink to get the active trail file name. + */ +static char * +get_curfile(void) +{ + char *cf; + int len; + + cf = malloc(MAXPATHLEN); + if (cf == NULL) { + auditd_log_err("malloc failed: %m"); + return (NULL); + } + + len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); + if (len < 0) { + free(cf); + return (NULL); + } + + /* readlink() doesn't terminate string. */ + cf[len] = '\0'; + + return (cf); +} + +/* + * Close the previous audit trail file. + */ +static int +close_lastfile(char *TS) +{ + char *ptr; + char *oldname; + + /* If lastfile is NULL try to get it from the 'current' link. */ + if (lastfile == NULL) + lastfile = get_curfile(); + + if (lastfile != NULL) { + oldname = strdup(lastfile); + if (oldname == NULL) + return (-1); + + /* Rename the last file -- append timestamp. */ + if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { + memcpy(ptr, TS, POSTFIX_LEN); + if (auditd_rename(oldname, lastfile) != 0) + auditd_log_err( + "Could not rename %s to %s: %m", oldname, + lastfile); + else { + /* + * Remove the 'current' symlink since the link + * is now invalid. + */ + (void) unlink(AUDIT_CURRENT_LINK); + auditd_log_notice("renamed %s to %s", + oldname, lastfile); + audit_warn_closefile(lastfile); + } + } else + auditd_log_err("Could not rename %s to %s", oldname, + lastfile); + free(lastfile); + free(oldname); + lastfile = NULL; + } + return (0); +} + +/* + * Create the new file name, swap with existing audit file. + */ +static int +swap_audit_file(void) +{ + int err; + char *newfile, *name; + char TS[TIMESTAMP_LEN + 1]; + time_t tt; + + if (getTSstr(tt, TS, sizeof(TS)) != 0) + return (-1); + /* + * If prefix and suffix are the same, it means that records are + * being produced too fast. We don't want to rename now, because + * next trail file can get the same name and once that one is + * terminated also within one second it will overwrite the current + * one. Just keep writing to the same trail and wait for the next + * trigger from the kernel. + * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT + * NOT BE THE CASE FOR OTHER OSES. + * If the kernel will not keep sending triggers, trail file will not + * be terminated. + */ + if (lastfile == NULL) { + name = NULL; + } else { + name = strrchr(lastfile, '/'); + if (name != NULL) + name++; + } + if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) { + auditd_log_debug("Not ready to terminate trail file yet."); + return (0); + } + err = auditd_swap_trail(TS, &newfile, audit_review_gid, + audit_warn_getacdir); + if (err != ADE_NOERR) { + auditd_log_err("%s: %m", auditd_strerror(err)); + if (err != ADE_ACTL) + return (-1); + } + + /* + * Only close the last file if were in an auditing state before + * calling swap_audit_file(). We may need to recover from a crash. + */ + if (auditd_get_state() == AUD_STATE_ENABLED) + close_lastfile(TS); + + + /* + * auditd_swap_trail() potentially enables auditing (if not already + * enabled) so updated the cached state as well. + */ + auditd_set_state(AUD_STATE_ENABLED); + + /* + * Create 'current' symlink. Recover from crash, if needed. + */ + if (auditd_new_curlink(newfile) != 0) + auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", + newfile, auditd_strerror(err)); + + lastfile = newfile; + auditd_log_notice("New audit file is %s", newfile); + + return (0); +} + +/* + * Create a new audit log trail file and swap with the current one, if any. + */ +static int +do_trail_file(void) +{ + int err; + + /* + * First, refresh the list of audit log directories. + */ + err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); + if (err) { + auditd_log_err("auditd_read_dirs(): %s", + auditd_strerror(err)); + if (err == ADE_HARDLIM) + audit_warn_allhard(); + if (err != ADE_SOFTLIM) + return (-1); + else + audit_warn_allsoft(); + /* continue on with soft limit error */ + } + + /* + * Create a new file and swap with the one being used in kernel. + */ + if (swap_audit_file() == -1) { + /* + * XXX Faulty directory listing? - user should be given + * XXX an opportunity to change the audit_control file + * XXX switch to a reduced mode of auditing? + */ + return (-1); + } + + /* + * Finally, see if there are any trail files to expire. + */ + err = auditd_expire_trails(audit_warn_expired); + if (err) + auditd_log_err("auditd_expire_trails(): %s", + auditd_strerror(err)); + + return (0); +} + +/* + * Start up auditing. + */ +static void +audit_setup(void) +{ + int err; + + /* Configure trail files distribution. */ + err = auditd_set_dist(); + if (err) { + auditd_log_err("auditd_set_dist() %s: %m", + auditd_strerror(err)); + } else + auditd_log_debug("Configured trail files distribution."); + + if (do_trail_file() == -1) { + auditd_log_err("Error creating audit trail file"); + fail_exit(); + } + + /* Generate an audit record. */ + err = auditd_gen_record(AUE_audit_startup, NULL); + if (err) + auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", + auditd_strerror(err)); + + if (auditd_config_controls() == 0) + auditd_log_info("Audit controls init successful"); + else + auditd_log_err("Audit controls init failed"); +} + + +/* + * Close auditd pid file and trigger mechanism. + */ +static int +close_misc(void) +{ + + auditd_close_dirs(); + if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { + auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); + return (1); + } + endac(); + + if (auditd_close_trigger() != 0) { + auditd_log_err("Error closing trigger messaging mechanism"); + return (1); + } + return (0); +} + +/* + * Close all log files, control files, and tell the audit system. + */ +static int +close_all(void) +{ + int err_ret = 0; + char TS[TIMESTAMP_LEN + 1]; + int err; + int cond; + time_t tt; + + err = auditd_gen_record(AUE_audit_shutdown, NULL); + if (err) + auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", + auditd_strerror(err)); + + /* Flush contents. */ + cond = AUC_DISABLED; + err_ret = audit_set_cond(&cond); + if (err_ret != 0) { + auditd_log_err("Disabling audit failed! : %s", strerror(errno)); + err_ret = 1; + } + + /* + * Updated the cached state that auditing has been disabled. + */ + auditd_set_state(AUD_STATE_DISABLED); + + if (getTSstr(tt, TS, sizeof(TS)) == 0) + close_lastfile(TS); + if (lastfile != NULL) + free(lastfile); + + err_ret += close_misc(); + + if (err_ret) { + auditd_log_err("Could not unregister"); + audit_warn_postsigterm(); + } + + auditd_log_info("Finished"); + return (err_ret); +} + +/* + * Register the daemon with the signal handler and the auditd pid file. + */ +static int +register_daemon(void) +{ + FILE * pidfile; + int fd; + pid_t pid; + + /* Set up the signal hander. */ + if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( + "Could not set signal handler for SIGTERM"); + fail_exit(); + } + if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( + "Could not set signal handler for SIGCHLD"); + fail_exit(); + } + if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( + "Could not set signal handler for SIGHUP"); + fail_exit(); + } + if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { + auditd_log_err( + "Could not set signal handler for SIGALRM"); + fail_exit(); + } + + if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { + auditd_log_err("Could not open PID file"); + audit_warn_tmpfile(); + return (-1); + } + + /* Attempt to lock the pid file; if a lock is present, exit. */ + fd = fileno(pidfile); + if (flock(fd, LOCK_EX | LOCK_NB) < 0) { + auditd_log_err( + "PID file is locked (is another auditd running?)."); + audit_warn_ebusy(); + return (-1); + } + + pid = getpid(); + ftruncate(fd, 0); + if (fprintf(pidfile, "%u\n", pid) < 0) { + /* Should not start the daemon. */ + fail_exit(); + } + + fflush(pidfile); + return (0); +} + +/* + * Handle the audit trigger event. + * + * We suppress (ignore) duplicated triggers in close succession in order to + * try to avoid thrashing-like behavior. However, not all triggers can be + * ignored, as triggers generally represent edge triggers, not level + * triggers, and won't be retransmitted if the condition persists. Of + * specific concern is the rotate trigger -- if one is dropped, then it will + * not be retransmitted, and the log file will grow in an unbounded fashion. + */ +#define DUPLICATE_INTERVAL 30 +void +auditd_handle_trigger(int trigger) +{ + static int last_trigger, last_warning; + static time_t last_time; + struct timeval ts; + struct timezone tzp; + time_t tt; + int au_state; + int err = 0; + + /* + * Suppress duplicate messages from the kernel within the specified + * interval. + */ + if (gettimeofday(&ts, &tzp) == 0) { + tt = (time_t)ts.tv_sec; + switch (trigger) { + case AUDIT_TRIGGER_LOW_SPACE: + case AUDIT_TRIGGER_NO_SPACE: + /* + * Triggers we can suppress. Of course, we also need + * to rate limit the warnings, so apply the same + * interval limit on syslog messages. + */ + if ((trigger == last_trigger) && + (tt < (last_time + DUPLICATE_INTERVAL))) { + if (tt >= (last_warning + DUPLICATE_INTERVAL)) + auditd_log_info( + "Suppressing duplicate trigger %d", + trigger); + return; + } + last_warning = tt; + break; + + case AUDIT_TRIGGER_ROTATE_KERNEL: + case AUDIT_TRIGGER_ROTATE_USER: + case AUDIT_TRIGGER_READ_FILE: + case AUDIT_TRIGGER_CLOSE_AND_DIE: + case AUDIT_TRIGGER_INITIALIZE: + /* + * Triggers that we cannot suppress. + */ + break; + } + + /* + * Only update last_trigger after aborting due to a duplicate + * trigger, not before, or we will never allow that trigger + * again. + */ + last_trigger = trigger; + last_time = tt; + } + + au_state = auditd_get_state(); + + /* + * Message processing is done here. + */ + switch(trigger) { + case AUDIT_TRIGGER_LOW_SPACE: + auditd_log_notice("Got low space trigger"); + if (do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); + break; + + case AUDIT_TRIGGER_NO_SPACE: + auditd_log_notice("Got no space trigger"); + if (do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); + break; + + case AUDIT_TRIGGER_ROTATE_KERNEL: + case AUDIT_TRIGGER_ROTATE_USER: + auditd_log_info("Got open new trigger from %s", trigger == + AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); + if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); + break; + + case AUDIT_TRIGGER_READ_FILE: + auditd_log_info("Got read file trigger"); + if (au_state == AUD_STATE_ENABLED) { + if (auditd_config_controls() == -1) + auditd_log_err("Error setting audit controls"); + else if (do_trail_file() == -1) + auditd_log_err("Error swapping audit file"); + } + break; + + case AUDIT_TRIGGER_CLOSE_AND_DIE: + auditd_log_info("Got close and die trigger"); + if (au_state == AUD_STATE_ENABLED) + err = close_all(); + /* + * Running under launchd don't exit. Wait for launchd to + * send SIGTERM. + */ + if (!launchd_flag) { + auditd_log_info("auditd exiting."); + exit (err); + } + break; + + case AUDIT_TRIGGER_INITIALIZE: + auditd_log_info("Got audit initialize trigger"); + if (au_state == AUD_STATE_DISABLED) + audit_setup(); + break; + + case AUDIT_TRIGGER_EXPIRE_TRAILS: + auditd_log_info("Got audit expire trails trigger"); + err = auditd_expire_trails(audit_warn_expired); + if (err) + auditd_log_err("auditd_expire_trails(): %s", + auditd_strerror(err)); + break; + + default: + auditd_log_err("Got unknown trigger %d", trigger); + break; + } +} + +/* + * Reap our children. + */ +void +auditd_reap_children(void) +{ + pid_t child; + int wstatus; + + while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { + if (!wstatus) + continue; + auditd_log_info("warn process [pid=%d] %s %d.", child, + ((WIFEXITED(wstatus)) ? "exited with non-zero status" : + "exited as a result of signal"), + ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : + WTERMSIG(wstatus))); + } +} + +/* + * Reap any children and terminate. If under launchd don't shutdown auditing + * but just the other stuff. + */ +void +auditd_terminate(void) +{ + int ret; + + auditd_reap_children(); + + if (launchd_flag) + ret = close_misc(); + else + ret = close_all(); + + exit(ret); +} + +/* + * Configure the audit controls in the kernel: the event to class mapping, + * kernel preselection mask, etc. + */ +int +auditd_config_controls(void) +{ + int cnt, err; + int ret = 0; + + /* + * Configure event to class mappings in kernel. + */ + cnt = auditd_set_evcmap(); + if (cnt < 0) { + auditd_log_err("auditd_set_evcmap() failed: %m"); + ret = -1; + } else if (cnt == 0) { + auditd_log_err("No events to class mappings registered."); + ret = -1; + } else + auditd_log_debug("Registered %d event to class mappings.", cnt); + + /* + * Configure non-attributable event mask in kernel. + */ + err = auditd_set_namask(); + if (err) { + auditd_log_err("auditd_set_namask() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug("Registered non-attributable event mask."); + + /* + * Configure audit policy in kernel. + */ + err = auditd_set_policy(); + if (err) { + auditd_log_err("auditd_set_policy() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug("Set audit policy in kernel."); + + /* + * Configure audit trail log size in kernel. + */ + err = auditd_set_fsize(); + if (err) { + auditd_log_err("audit_set_fsize() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug("Set audit trail size in kernel."); + + /* + * Configure audit trail volume minimum free percentage of blocks in + * kernel. + */ + err = auditd_set_minfree(); + if (err) { + auditd_log_err("auditd_set_minfree() %s: %m", + auditd_strerror(err)); + ret = -1; + } else + auditd_log_debug( + "Set audit trail min free percent in kernel."); + + /* + * Configure host address in the audit kernel information. + */ + err = auditd_set_host(); + if (err) { + if (err == ADE_PARSE) { + auditd_log_notice( + "audit_control(5) may be missing 'host:' field"); + } else { + auditd_log_err("auditd_set_host() %s: %m", + auditd_strerror(err)); + ret = -1; + } + } else + auditd_log_debug( + "Set audit host address information in kernel."); + + return (ret); +} + +/* + * Setup and initialize auditd. + */ +static void +setup(void) +{ + int err; + + if (auditd_open_trigger(launchd_flag) < 0) { + auditd_log_err("Error opening trigger messaging mechanism"); + fail_exit(); + } + + /* + * To prevent event feedback cycles and avoid auditd becoming + * stalled if auditing is suspended, auditd and its children run + * without their events being audited. We allow the uid, tid, and + * mask fields to be implicitly set to zero, but do set the pid. We + * run this after opening the trigger device to avoid configuring + * audit state without audit present in the system. + */ + err = auditd_prevent_audit(); + if (err) { + auditd_log_err("auditd_prevent_audit() %s: %m", + auditd_strerror(err)); + fail_exit(); + } + + /* + * Make sure auditd auditing state is correct. + */ + auditd_set_state(AUD_STATE_INIT); + + /* + * If under launchd, don't start auditing. Wait for a trigger to + * do so. + */ + if (!launchd_flag) + audit_setup(); +} + +int +main(int argc, char **argv) +{ + int ch; + int debug = 0; +#ifdef AUDIT_REVIEW_GROUP + struct group *grp; +#endif + + while ((ch = getopt(argc, argv, "dl")) != -1) { + switch(ch) { + case 'd': + /* Debug option. */ + debug = 1; + break; + + case 'l': + /* Be launchd friendly. */ + launchd_flag = 1; + break; + + case '?': + default: + (void)fprintf(stderr, + "usage: auditd [-d] [-l]\n"); + exit(1); + } + } + + audit_review_gid = getgid(); + +#ifdef AUDIT_REVIEW_GROUP + /* + * XXXRW: Currently, this code falls back to the daemon gid, which is + * likely the wheel group. Is there a better way to deal with this? + */ + grp = getgrnam(AUDIT_REVIEW_GROUP); + if (grp != NULL) + audit_review_gid = grp->gr_gid; +#endif + + auditd_openlog(debug, audit_review_gid); + + if (launchd_flag) + auditd_log_info("started by launchd..."); + else + auditd_log_info("starting..."); + +#ifdef AUDIT_REVIEW_GROUP + if (grp == NULL) + auditd_log_info( + "Audit review group '%s' not available, using daemon gid (%d)", + AUDIT_REVIEW_GROUP, audit_review_gid); +#endif + if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { + auditd_log_err("Failed to daemonize"); + exit(1); + } + + if (register_daemon() == -1) { + auditd_log_err("Could not register as daemon"); + exit(1); + } + + setup(); + + /* + * auditd_wait_for_events() shouldn't return unless something is wrong. + */ + auditd_wait_for_events(); + + auditd_log_err("abnormal exit."); + close_all(); + exit(-1); +} diff --git a/contrib/openbsm/bin/auditd/auditd.h b/contrib/openbsm/bin/auditd/auditd.h new file mode 100644 index 0000000..20afd75 --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2005-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AUDITD_H_ +#define _AUDITD_H_ + +#include <sys/types.h> +#include <sys/queue.h> +#include <syslog.h> + +#define MAX_DIR_SIZE 255 +#define AUDITD_NAME "auditd" + +/* + * If defined, then the audit daemon will attempt to chown newly created logs + * to this group. Otherwise, they will be the default for the user running + * auditd, likely the audit group. + */ +#define AUDIT_REVIEW_GROUP "audit" + +#define HARDLIM_ALL_WARN "allhard" +#define SOFTLIM_ALL_WARN "allsoft" +#define AUDITOFF_WARN "auditoff" +#define CLOSEFILE_WARN "closefile" +#define EBUSY_WARN "ebusy" +#define GETACDIR_WARN "getacdir" +#define HARDLIM_WARN "hard" +#define NOSTART_WARN "nostart" +#define POSTSIGTERM_WARN "postsigterm" +#define SOFTLIM_WARN "soft" +#define TMPFILE_WARN "tmpfile" +#define EXPIRED_WARN "expired" + +#define AUDITWARN_SCRIPT "/etc/security/audit_warn" +#define AUDITD_PIDFILE "/var/run/auditd.pid" + +#define AUD_STATE_INIT -1 +#define AUD_STATE_DISABLED 0 +#define AUD_STATE_ENABLED 1 + +int audit_warn_allhard(void); +int audit_warn_allsoft(void); +int audit_warn_auditoff(void); +int audit_warn_closefile(char *filename); +int audit_warn_ebusy(void); +int audit_warn_getacdir(char *filename); +int audit_warn_hard(char *filename); +int audit_warn_nostart(void); +int audit_warn_postsigterm(void); +int audit_warn_soft(char *filename); +int audit_warn_tmpfile(void); +int audit_warn_expired(char *filename); + +void auditd_openlog(int debug, gid_t gid); +void auditd_log_err(const char *fmt, ...); +void auditd_log_debug(const char *fmt, ...); +void auditd_log_info(const char *fmt, ...); +void auditd_log_notice(const char *fmt, ...); + +void auditd_set_state(int state); +int auditd_get_state(void); + +int auditd_open_trigger(int launchd_flag); +int auditd_close_trigger(void); +void auditd_handle_trigger(int trigger); + +void auditd_wait_for_events(void); +void auditd_relay_signal(int signal); +void auditd_terminate(void); +int auditd_config_controls(void); +void auditd_reap_children(void); + + +#endif /* !_AUDITD_H_ */ diff --git a/contrib/openbsm/bin/auditd/auditd_control.defs b/contrib/openbsm/bin/auditd/auditd_control.defs new file mode 100644 index 0000000..84f37df --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd_control.defs @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 1999-2007 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Exported client calls to the auditd facility. + */ + +Subsystem + KernelUser + auditd_control 456; + +#ifndef __MigTypeCheck +#define __MigTypeCheck 1 +#endif + +#include <mach/std_types.defs> +#include <mach/mach_types.defs> + +simpleroutine auditd_control( + auditd_port : mach_port_t; + in trigger : int); diff --git a/contrib/openbsm/bin/auditd/auditd_darwin.c b/contrib/openbsm/bin/auditd/auditd_darwin.c new file mode 100644 index 0000000..702eb94 --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd_darwin.c @@ -0,0 +1,482 @@ +/*- + * Copyright (c) 2004-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <config/config.h> + +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> + +#include <bsm/audit.h> +#include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> +#include <bsm/libbsm.h> + +#include <asl.h> +#include <launch.h> +#include <notify.h> +#include <mach/port.h> +#include <mach/mach_error.h> +#include <mach/mach_traps.h> +#include <mach/mach.h> +#include <mach/host_special_ports.h> + +#include "auditd.h" + +#include "auditd_controlServer.h" +#include "audit_triggersServer.h" + +/* + * Apple System Logger Handles. + */ +static aslmsg au_aslmsg = NULL; +static aslclient au_aslclient = NULL; + +static mach_port_t control_port = MACH_PORT_NULL; +static mach_port_t signal_port = MACH_PORT_NULL; +static mach_port_t port_set = MACH_PORT_NULL; + +/* + * Current auditing state (cache). + */ +static int auditing_state = AUD_STATE_INIT; + +/* + * Maximum idle time before auditd terminates under launchd. + * If it is zero then auditd does not timeout while idle. + */ +static int max_idletime = 0; + +#ifndef __BSM_INTERNAL_NOTIFY_KEY +#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" +#endif /* __BSM_INTERNAL_NOTIFY_KEY */ + +#ifndef __AUDIT_LAUNCHD_LABEL +#define __AUDIT_LAUNCHD_LABEL "com.apple.auditd" +#endif /* __AUDIT_LAUNCHD_LABEL */ + +#define MAX_MSG_SIZE 4096 + +/* + * Open and set up system logging. + */ +void +auditd_openlog(int debug, gid_t gid) +{ + uint32_t opt = 0; + char *cp = NULL; + + if (debug) + opt = ASL_OPT_STDERR; + + au_aslclient = asl_open("auditd", "com.apple.auditd", opt); + au_aslmsg = asl_new(ASL_TYPE_MSG); + +#ifdef ASL_KEY_READ_UID + /* + * Make it only so the audit administrator and members of the audit + * review group (if used) have access to the auditd system log messages. + */ + asl_set(au_aslmsg, ASL_KEY_READ_UID, "0"); + asprintf(&cp, "%u", gid); + if (cp != NULL) { +#ifdef ASL_KEY_READ_GID + asl_set(au_aslmsg, ASL_KEY_READ_GID, cp); +#endif + free(cp); + } +#endif + + /* + * Set the client-side system log filtering. + */ + if (debug) + asl_set_filter(au_aslclient, + ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); + else + asl_set_filter(au_aslclient, + ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO)); +} + +/* + * Log messages at different priority levels. + */ +void +auditd_log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_ERR, fmt, ap); + va_end(ap); +} + +void +auditd_log_notice(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_NOTICE, fmt, ap); + va_end(ap); +} + +void +auditd_log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_INFO, fmt, ap); + va_end(ap); +} + +void +auditd_log_debug(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_DEBUG, fmt, ap); + va_end(ap); +} + +/* + * Get the auditing state from the kernel and cache it. + */ +static void +init_audit_state(void) +{ + int au_cond; + + if (audit_get_cond(&au_cond) < 0) { + if (errno != ENOSYS) { + auditd_log_err("Audit status check failed (%s)", + strerror(errno)); + } + auditing_state = AUD_STATE_DISABLED; + } else + if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) + auditing_state = AUD_STATE_DISABLED; + else + auditing_state = AUD_STATE_ENABLED; +} + +/* + * Update the cached auditing state. Let other tasks that may be caching it + * as well to update their state via notify(3). + */ +void +auditd_set_state(int state) +{ + int old_auditing_state = auditing_state; + + if (state == AUD_STATE_INIT) + init_audit_state(); + else + auditing_state = state; + + if (auditing_state != old_auditing_state) { + notify_post(__BSM_INTERNAL_NOTIFY_KEY); + + if (auditing_state == AUD_STATE_ENABLED) + auditd_log_notice("Auditing enabled"); + if (auditing_state == AUD_STATE_DISABLED) + auditd_log_notice("Auditing disabled"); + } +} + +/* + * Get the cached auditing state. + */ +int +auditd_get_state(void) +{ + + if (auditing_state == AUD_STATE_INIT) { + init_audit_state(); + notify_post(__BSM_INTERNAL_NOTIFY_KEY); + } + + return (auditing_state); +} + +/* + * Lookup the audit mach port in the launchd dictionary. + */ +static mach_port_t +lookup_machport(const char *label) +{ + launch_data_t msg, msd, ld, cdict, to; + mach_port_t mp = MACH_PORT_NULL; + + msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); + + cdict = launch_msg(msg); + if (cdict == NULL) { + auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN + "\") IPC failure: %m"); + return (MACH_PORT_NULL); + } + + if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { + errno = launch_data_get_errno(cdict); + auditd_log_err("launch_data_get_type() can't get dict: %m"); + return (MACH_PORT_NULL); + } + + to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); + if (to) { + max_idletime = launch_data_get_integer(to); + auditd_log_debug("launchd timeout set to %d", max_idletime); + } else { + auditd_log_debug("launchd timeout not set, setting to 60"); + max_idletime = 60; + } + + msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); + if (msd == NULL) { + auditd_log_err( + "launch_data_dict_lookup() can't get mach services"); + return (MACH_PORT_NULL); + } + + ld = launch_data_dict_lookup(msd, label); + if (ld == NULL) { + auditd_log_err("launch_data_dict_lookup can't find %s", label); + return (MACH_PORT_NULL); + } + + mp = launch_data_get_machport(ld); + + return (mp); +} + +static int +mach_setup(int launchd_flag) +{ + mach_msg_type_name_t poly; + + /* + * Allocate a port set. + */ + if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, + &port_set) != KERN_SUCCESS) { + auditd_log_err("Allocation of port set failed"); + return (-1); + } + + + /* + * Allocate a signal reflection port. + */ + if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, + &signal_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), signal_port, port_set) != + KERN_SUCCESS) { + auditd_log_err("Allocation of signal port failed"); + return (-1); + } + + /* + * Allocate a trigger port. + */ + if (launchd_flag) { + /* + * If started under launchd, lookup port in launchd dictionary. + */ + if ((control_port = lookup_machport(__AUDIT_LAUNCHD_LABEL)) == + MACH_PORT_NULL || mach_port_move_member(mach_task_self(), + control_port, port_set) != KERN_SUCCESS) { + auditd_log_err("Cannot get Mach control port" + " via launchd"); + return (-1); + } else + auditd_log_debug("Mach control port registered" + " via launchd"); + } else { + /* + * If not started under launchd, allocate port and register. + */ + if (mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, &control_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), control_port, + port_set) != KERN_SUCCESS) + auditd_log_err("Allocation of trigger port failed"); + + /* + * Create a send right on our trigger port. + */ + mach_port_extract_right(mach_task_self(), control_port, + MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); + + /* + * Register the trigger port with the kernel. + */ + if (host_set_audit_control_port(mach_host_self(), + control_port) != KERN_SUCCESS) { + auditd_log_err("Cannot set Mach control port"); + return (-1); + } else + auditd_log_debug("Mach control port registered"); + } + + return (0); +} + +/* + * Open the trigger messaging mechanism. + */ +int +auditd_open_trigger(int launchd_flag) +{ + + return (mach_setup(launchd_flag)); +} + +/* + * Close the trigger messaging mechanism. + */ +int +auditd_close_trigger(void) +{ + + return (0); +} + +/* + * Combined server handler. Called by the mach message loop when there is + * a trigger or signal message. + */ +static boolean_t +auditd_combined_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + mach_port_t local_port = InHeadP->msgh_local_port; + + /* Reset the idle time alarm, if used. */ + if (max_idletime) + alarm(max_idletime); + + if (local_port == signal_port) { + int signo = InHeadP->msgh_id; + + switch(signo) { + case SIGTERM: + case SIGALRM: + auditd_terminate(); + /* Not reached. */ + + case SIGCHLD: + auditd_reap_children(); + return (TRUE); + + case SIGHUP: + auditd_config_controls(); + return (TRUE); + + default: + auditd_log_info("Received signal %d", signo); + return (TRUE); + } + } else if (local_port == control_port) { + boolean_t result; + + result = audit_triggers_server(InHeadP, OutHeadP); + if (!result) + result = auditd_control_server(InHeadP, OutHeadP); + return (result); + } + auditd_log_info("Recevied msg on bad port 0x%x.", local_port); + return (FALSE); +} + +/* + * The main event loop. Wait for trigger messages or signals and handle them. + * It should not return unless there is a problem. + */ +void +auditd_wait_for_events(void) +{ + kern_return_t result; + + /* + * Call the mach messaging server loop. + */ + result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, + port_set, MACH_MSG_OPTION_NONE); +} + +/* + * Implementation of the audit_triggers() MIG simpleroutine. Simply a + * wrapper function. This handles input from the kernel on the host + * special mach port. + */ +kern_return_t +audit_triggers(mach_port_t __unused audit_port, int trigger) +{ + + auditd_handle_trigger(trigger); + + return (KERN_SUCCESS); +} + +/* + * Implementation of the auditd_control() MIG simpleroutine. Simply a + * wrapper function. This handles input from the audit(1) tool. + */ +kern_return_t +auditd_control(mach_port_t __unused auditd_port, int trigger) +{ + + auditd_handle_trigger(trigger); + + return (KERN_SUCCESS); +} + +/* + * When we get a signal, we are often not at a clean point. So, little can + * be done in the signal handler itself. Instead, we send a message to the + * main servicing loop to do proper handling from a non-signal-handler + * context. + */ +void +auditd_relay_signal(int signal) +{ + mach_msg_empty_send_t msg; + + msg.header.msgh_id = signal; + msg.header.msgh_remote_port = signal_port; + msg.header.msgh_local_port = MACH_PORT_NULL; + msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); + mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), + 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); +} diff --git a/contrib/openbsm/bin/auditd/auditd_fbsd.c b/contrib/openbsm/bin/auditd/auditd_fbsd.c new file mode 100644 index 0000000..d8f040f --- /dev/null +++ b/contrib/openbsm/bin/auditd/auditd_fbsd.c @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2004-2009 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <config/config.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <signal.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#include <bsm/audit.h> +#include <bsm/audit_uevents.h> +#include <bsm/auditd_lib.h> +#include <bsm/libbsm.h> + +#include "auditd.h" + +/* + * Current auditing state (cache). + */ +static int auditing_state = AUD_STATE_INIT; + +/* + * Maximum idle time before auditd terminates under launchd. + * If it is zero then auditd does not timeout while idle. + */ +static int max_idletime = 0; + +static int sigchlds, sigchlds_handled; +static int sighups, sighups_handled; +static int sigterms, sigterms_handled; +static int sigalrms, sigalrms_handled; + +static int triggerfd = 0; + +/* + * Open and set up system logging. + */ +void +auditd_openlog(int debug, gid_t __unused gid) +{ + int logopts = LOG_CONS | LOG_PID; + + if (debug) + logopts |= LOG_PERROR; + +#ifdef LOG_SECURITY + openlog("auditd", logopts, LOG_SECURITY); +#else + openlog("auditd", logopts, LOG_AUTH); +#endif +} + +/* + * Log messages at different priority levels. + */ +void +auditd_log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); +} + +void +auditd_log_notice(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_NOTICE, fmt, ap); + va_end(ap); +} + +void +auditd_log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_INFO, fmt, ap); + va_end(ap); +} + +void +auditd_log_debug(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_DEBUG, fmt, ap); + va_end(ap); +} + +/* + * Get the auditing state from the kernel and cache it. + */ +static void +init_audit_state(void) +{ + int au_cond; + + if (audit_get_cond(&au_cond) < 0) { + if (errno != ENOSYS) { + auditd_log_err("Audit status check failed (%s)", + strerror(errno)); + } + auditing_state = AUD_STATE_DISABLED; + } else + if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) + auditing_state = AUD_STATE_DISABLED; + else + auditing_state = AUD_STATE_ENABLED; +} + +/* + * Update the cached auditing state. + */ +void +auditd_set_state(int state) +{ + int old_auditing_state = auditing_state; + + if (state == AUD_STATE_INIT) + init_audit_state(); + else + auditing_state = state; + + if (auditing_state != old_auditing_state) { + if (auditing_state == AUD_STATE_ENABLED) + auditd_log_notice("Auditing enabled"); + if (auditing_state == AUD_STATE_DISABLED) + auditd_log_notice("Auditing disabled"); + } +} + +/* + * Get the cached auditing state. + */ +int +auditd_get_state(void) +{ + + if (auditing_state == AUD_STATE_INIT) + init_audit_state(); + + return (auditing_state); +} + +/* + * Open the trigger messaging mechanism. + */ +int +auditd_open_trigger(int __unused launchd_flag) +{ + + return ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0))); +} + +/* + * Close the trigger messaging mechanism. + */ +int +auditd_close_trigger(void) +{ + + return (close(triggerfd)); +} + +/* + * The main event loop. Wait for trigger messages or signals and handle them. + * It should not return unless there is a problem. + */ +void +auditd_wait_for_events(void) +{ + int num; + unsigned int trigger; + + for (;;) { + num = read(triggerfd, &trigger, sizeof(trigger)); + if ((num == -1) && (errno != EINTR)) { + auditd_log_err("%s: error %d", __FUNCTION__, errno); + return; + } + + /* Reset the idle time alarm, if used. */ + if (max_idletime) + alarm(max_idletime); + + if (sigterms != sigterms_handled) { + auditd_log_debug("%s: SIGTERM", __FUNCTION__); + auditd_terminate(); + /* not reached */ + } + if (sigalrms != sigalrms_handled) { + auditd_log_debug("%s: SIGALRM", __FUNCTION__); + auditd_terminate(); + /* not reached */ + } + if (sigchlds != sigchlds_handled) { + sigchlds_handled = sigchlds; + auditd_reap_children(); + } + if (sighups != sighups_handled) { + auditd_log_debug("%s: SIGHUP", __FUNCTION__); + sighups_handled = sighups; + auditd_config_controls(); + } + + if ((num == -1) && (errno == EINTR)) + continue; + if (num == 0) { + auditd_log_err("%s: read EOF", __FUNCTION__); + return; + } + auditd_handle_trigger(trigger); + } +} + +/* + * When we get a signal, we are often not at a clean point. So, little can + * be done in the signal handler itself. Instead, we send a message to the + * main servicing loop to do proper handling from a non-signal-handler + * context. + */ +void +auditd_relay_signal(int signal) +{ + if (signal == SIGHUP) + sighups++; + if (signal == SIGTERM) + sigterms++; + if (signal == SIGCHLD) + sigchlds++; + if (signal == SIGALRM) + sigalrms++; +} + diff --git a/contrib/openbsm/bin/auditdistd/Makefile.am b/contrib/openbsm/bin/auditdistd/Makefile.am new file mode 100644 index 0000000..263cb2d --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/Makefile.am @@ -0,0 +1,29 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = auditdistd +man5_MANS = auditdistd.conf.5 +man8_MANS = auditdistd.8 +CFLAGS = -Wno-format +YFLAGS = -d +auditdistd_LDFLAGS = -lcrypto + +auditdistd_SOURCES = \ + auditdistd.c \ + parse.y \ + pjdlog.c \ + proto.c \ + proto_common.c \ + proto_socketpair.c \ + proto_tcp.c \ + proto_tls.c \ + proto_uds.c \ + receiver.c \ + sandbox.c \ + sender.c \ + subr.c \ + token.l \ + trail.c diff --git a/contrib/openbsm/bin/auditdistd/Makefile.in b/contrib/openbsm/bin/auditdistd/Makefile.in new file mode 100644 index 0000000..b6228fd --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/Makefile.in @@ -0,0 +1,753 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = auditdistd$(EXEEXT) +subdir = bin/auditdistd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp $(top_srcdir)/config/ylwrap \ + parse.c parse.h token.c +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \ + "$(DESTDIR)$(man8dir)" +PROGRAMS = $(sbin_PROGRAMS) +am_auditdistd_OBJECTS = auditdistd.$(OBJEXT) parse.$(OBJEXT) \ + pjdlog.$(OBJEXT) proto.$(OBJEXT) proto_common.$(OBJEXT) \ + proto_socketpair.$(OBJEXT) proto_tcp.$(OBJEXT) \ + proto_tls.$(OBJEXT) proto_uds.$(OBJEXT) receiver.$(OBJEXT) \ + sandbox.$(OBJEXT) sender.$(OBJEXT) subr.$(OBJEXT) \ + token.$(OBJEXT) trail.$(OBJEXT) +auditdistd_OBJECTS = $(am_auditdistd_OBJECTS) +auditdistd_LDADD = $(LDADD) +auditdistd_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(auditdistd_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ || +LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) +LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS) +YLWRAP = $(top_srcdir)/config/ylwrap +@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || +am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ + -e s/c++$$/h++/ -e s/c$$/h/ +YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) +LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS) +SOURCES = $(auditdistd_SOURCES) +DIST_SOURCES = $(auditdistd_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man5_MANS) $(man8_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = -Wno-format +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = -d +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +man5_MANS = auditdistd.conf.5 +man8_MANS = auditdistd.8 +auditdistd_LDFLAGS = -lcrypto +auditdistd_SOURCES = \ + auditdistd.c \ + parse.y \ + pjdlog.c \ + proto.c \ + proto_common.c \ + proto_socketpair.c \ + proto_tcp.c \ + proto_tls.c \ + proto_uds.c \ + receiver.c \ + sandbox.c \ + sender.c \ + subr.c \ + token.l \ + trail.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .l .lo .o .obj .y +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditdistd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/auditdistd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +parse.h: parse.c + @if test ! -f $@; then rm -f parse.c; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) parse.c; else :; fi +auditdistd$(EXEEXT): $(auditdistd_OBJECTS) $(auditdistd_DEPENDENCIES) $(EXTRA_auditdistd_DEPENDENCIES) + @rm -f auditdistd$(EXEEXT) + $(auditdistd_LINK) $(auditdistd_OBJECTS) $(auditdistd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditdistd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pjdlog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_socketpair.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_tcp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_tls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto_uds.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sandbox.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trail.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +.l.c: + $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) + +.y.c: + $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man5: $(man5_MANS) + @$(NORMAL_INSTALL) + @list1='$(man5_MANS)'; \ + list2=''; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -rm -f parse.c + -rm -f parse.h + -rm -f token.c +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man5 install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man5 uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man5 install-man8 install-pdf install-pdf-am \ + install-ps install-ps-am install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man5 \ + uninstall-man8 uninstall-sbinPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.8 b/contrib/openbsm/bin/auditdistd/auditdistd.8 new file mode 100644 index 0000000..71a6575 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/auditdistd.8 @@ -0,0 +1,106 @@ +.\" Copyright (c) 2012 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 5, 2012 +.Dt AUDITDISTD 8 +.Os +.Sh NAME +.Nm auditdistd +.Nd "Audit trail files distribution daemon" +.Sh SYNOPSIS +.Nm +.Op Fl dFhl +.Op Fl c Ar config +.Op Fl P Ar pidfile +.Sh DESCRIPTION +The +.Nm +daemon is responsible for distributing audit trail files over a TCP/IP network in +a secure and reliable way. +.Pp +The +.Nm +daemon can be started with the following command line arguments: +.Bl -tag -width ".Fl P Ar pidfile" +.It Fl c Ar config +Specify an alternative location of the configuration file. +The default location is +.Pa /etc/security/auditdistd.conf . +Note: the configuration file may contain passwords. +Care should be taken to configure proper permissions on this file +.Li ( eg. 0600 ) . +.It Fl d +Print or log debugging information. +This option can be specified multiple times to raise the verbosity +level. +.It Fl F +Start the +.Nm +daemon in the foreground. +By default +.Nm +starts in the background. +.It Fl h +Print the +.Nm +usage message. +.It Fl l +Start in a launchd-friendly mode, ie. do not use +.Xr daemon 3 . +.It Fl P Ar pidfile +Specify an alternative location of a file where main process PID will be +stored. +The default location is +.Pa /var/run/auditdistd.pid . +.El +.Sh FILES +.Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact +.It Pa /etc/security/auditdistd.conf +The configuration file for +.Nm . +.It Pa /var/run/auditdistd.pid +The default location of the +.Nm +PID file. +.El +.Sh EXIT STATUS +Exit status is 0 on success, or one of the values described in +.Xr sysexits 3 +on failure. +.Sh SEE ALSO +.Xr sysexits 3 , +.Xr audit 4 , +.Xr auditdistd.conf 5 , +.Xr auditd 8 +.Sh AUTHORS +The +.Nm +was developed by +.An Pawel Jakub Dawidek Aq pawel@dawidek.net +under sponsorship of the FreeBSD Foundation. diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.c b/contrib/openbsm/bin/auditdistd/auditdistd.c new file mode 100644 index 0000000..696f048 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/auditdistd.c @@ -0,0 +1,798 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> +#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) +#include <sys/endian.h> +#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#ifdef HAVE_MACHINE_ENDIAN_H +#include <machine/endian.h> +#else /* !HAVE_MACHINE_ENDIAN_H */ +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#else /* !HAVE_ENDIAN_H */ +#error "No supported endian.h" +#endif /* !HAVE_ENDIAN_H */ +#endif /* !HAVE_MACHINE_ENDIAN_H */ +#include <compat/endian.h> +#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#include <sys/queue.h> +#include <sys/wait.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> + +#include <openssl/hmac.h> + +#ifndef HAVE_PIDFILE_OPEN +#include <compat/pidfile.h> +#endif +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif +#ifndef HAVE_SIGTIMEDWAIT +#include "sigtimedwait.h" +#endif + +#include "auditdistd.h" +#include "pjdlog.h" +#include "proto.h" +#include "subr.h" +#include "synch.h" + +/* Path to configuration file. */ +const char *cfgpath = ADIST_CONFIG; +/* Auditdistd configuration. */ +static struct adist_config *adcfg; +/* Was SIGINT or SIGTERM signal received? */ +bool sigexit_received = false; +/* PID file handle. */ +struct pidfh *pfh; + +/* How often check for hooks running for too long. */ +#define SIGNALS_CHECK_INTERVAL 5 + +static void +usage(void) +{ + + errx(EX_USAGE, "[-dFhl] [-c config] [-P pidfile]"); +} + +void +descriptors_cleanup(struct adist_host *adhost) +{ + struct adist_host *adh; + struct adist_listen *lst; + + TAILQ_FOREACH(adh, &adcfg->adc_hosts, adh_next) { + if (adh == adhost) + continue; + if (adh->adh_remote != NULL) { + proto_close(adh->adh_remote); + adh->adh_remote = NULL; + } + } + TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { + if (lst->adl_conn != NULL) + proto_close(lst->adl_conn); + } + (void)pidfile_close(pfh); + pjdlog_fini(); +} + +static void +child_cleanup(struct adist_host *adhost) +{ + + if (adhost->adh_conn != NULL) { + PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); + proto_close(adhost->adh_conn); + adhost->adh_conn = NULL; + } + adhost->adh_worker_pid = 0; +} + +static void +child_exit_log(const char *type, unsigned int pid, int status) +{ + + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + pjdlog_debug(1, "%s process exited gracefully (pid=%u).", + type, pid); + } else if (WIFSIGNALED(status)) { + pjdlog_error("%s process killed (pid=%u, signal=%d).", + type, pid, WTERMSIG(status)); + } else { + pjdlog_error("%s process exited ungracefully (pid=%u, exitcode=%d).", + type, pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1); + } +} + +static void +child_exit(void) +{ + struct adist_host *adhost; + bool restart; + int status; + pid_t pid; + + restart = false; + while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { + /* Find host related to the process that just exited. */ + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (pid == adhost->adh_worker_pid) + break; + } + if (adhost == NULL) { + child_exit_log("Sandbox", pid, status); + } else { + if (adhost->adh_role == ADIST_ROLE_SENDER) + restart = true; + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); + child_exit_log("Worker", pid, status); + child_cleanup(adhost); + pjdlog_prefix_set("%s", ""); + } + } + if (!restart) + return; + /* We have some sender processes to restart. */ + sleep(1); + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role != ADIST_ROLE_SENDER) + continue; + if (adhost->adh_worker_pid != 0) + continue; + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); + pjdlog_info("Restarting sender process."); + adist_sender(adcfg, adhost); + pjdlog_prefix_set("%s", ""); + } +} + +/* TODO */ +static void +adist_reload(void) +{ + + pjdlog_info("Reloading configuration is not yet implemented."); +} + +static void +terminate_workers(void) +{ + struct adist_host *adhost; + + pjdlog_info("Termination signal received, exiting."); + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_worker_pid == 0) + continue; + pjdlog_info("Terminating worker process (adhost=%s, role=%s, pid=%u).", + adhost->adh_name, role2str(adhost->adh_role), + adhost->adh_worker_pid); + if (kill(adhost->adh_worker_pid, SIGTERM) == 0) + continue; + pjdlog_errno(LOG_WARNING, + "Unable to send signal to worker process (adhost=%s, role=%s, pid=%u).", + adhost->adh_name, role2str(adhost->adh_role), + adhost->adh_worker_pid); + } +} + +static void +listen_accept(struct adist_listen *lst) +{ + unsigned char rnd[32], hash[32], resp[32]; + struct adist_host *adhost; + struct proto_conn *conn; + char adname[ADIST_HOSTSIZE]; + char laddr[256], raddr[256]; + char welcome[8]; + int status, version; + pid_t pid; + + proto_local_address(lst->adl_conn, laddr, sizeof(laddr)); + pjdlog_debug(1, "Accepting connection to %s.", laddr); + + if (proto_accept(lst->adl_conn, &conn) == -1) { + pjdlog_errno(LOG_ERR, "Unable to accept connection to %s", + laddr); + return; + } + + proto_local_address(conn, laddr, sizeof(laddr)); + proto_remote_address(conn, raddr, sizeof(raddr)); + pjdlog_info("Connection from %s to %s.", raddr, laddr); + + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(conn, ADIST_TIMEOUT) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + + /* + * Before receiving any data see if remote host is known. + */ + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role != ADIST_ROLE_RECEIVER) + continue; + if (!proto_address_match(conn, adhost->adh_remoteaddr)) + continue; + break; + } + if (adhost == NULL) { + pjdlog_error("Client %s is not known.", raddr); + goto close; + } + /* Ok, remote host is known. */ + + /* Exchange welcome message, which include version number. */ + bzero(welcome, sizeof(welcome)); + if (proto_recv(conn, welcome, sizeof(welcome)) == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to receive welcome message from %s", + adhost->adh_remoteaddr); + goto close; + } + if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) || + !isdigit(welcome[6]) || welcome[7] != '\0') { + pjdlog_warning("Invalid welcome message from %s.", + adhost->adh_remoteaddr); + goto close; + } + + version = MIN(ADIST_VERSION, atoi(welcome + 5)); + + (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", version); + if (proto_send(conn, welcome, sizeof(welcome)) == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to send welcome message to %s", + adhost->adh_remoteaddr); + goto close; + } + + if (proto_recv(conn, adname, sizeof(adhost->adh_name)) < 0) { + pjdlog_errno(LOG_ERR, "Unable to receive hostname from %s", + raddr); + goto close; + } + + /* Find host now that we have hostname. */ + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role != ADIST_ROLE_RECEIVER) + continue; + if (!proto_address_match(conn, adhost->adh_remoteaddr)) + continue; + if (strcmp(adhost->adh_name, adname) != 0) + continue; + break; + } + if (adhost == NULL) { + pjdlog_error("No configuration for host %s from address %s.", + adname, raddr); + goto close; + } + + adhost->adh_version = version; + pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version, + adhost->adh_remoteaddr); + + /* Now that we know host name setup log prefix. */ + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); + + if (adist_random(rnd, sizeof(rnd)) == -1) { + pjdlog_error("Unable to generate challenge."); + goto close; + } + pjdlog_debug(1, "Challenge generated."); + + if (proto_send(conn, rnd, sizeof(rnd)) == -1) { + pjdlog_errno(LOG_ERR, "Unable to send challenge to %s", + adhost->adh_remoteaddr); + goto close; + } + pjdlog_debug(1, "Challenge sent."); + + if (proto_recv(conn, resp, sizeof(resp)) == -1) { + pjdlog_errno(LOG_ERR, "Unable to receive response from %s", + adhost->adh_remoteaddr); + goto close; + } + pjdlog_debug(1, "Response received."); + + if (HMAC(EVP_sha256(), adhost->adh_password, + (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, + NULL) == NULL) { + pjdlog_error("Unable to generate hash."); + goto close; + } + pjdlog_debug(1, "Hash generated."); + + if (memcmp(resp, hash, sizeof(hash)) != 0) { + pjdlog_error("Invalid response from %s (wrong password?).", + adhost->adh_remoteaddr); + goto close; + } + pjdlog_info("Sender authenticated."); + + if (proto_recv(conn, rnd, sizeof(rnd)) == -1) { + pjdlog_errno(LOG_ERR, "Unable to receive challenge from %s", + adhost->adh_remoteaddr); + goto close; + } + pjdlog_debug(1, "Challenge received."); + + if (HMAC(EVP_sha256(), adhost->adh_password, + (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, + NULL) == NULL) { + pjdlog_error("Unable to generate response."); + goto close; + } + pjdlog_debug(1, "Response generated."); + + if (proto_send(conn, hash, sizeof(hash)) == -1) { + pjdlog_errno(LOG_ERR, "Unable to send response to %s", + adhost->adh_remoteaddr); + goto close; + } + pjdlog_debug(1, "Response sent."); + + if (adhost->adh_worker_pid != 0) { + pjdlog_debug(1, + "Receiver process exists (pid=%u), stopping it.", + (unsigned int)adhost->adh_worker_pid); + /* Stop child process. */ + if (kill(adhost->adh_worker_pid, SIGINT) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to stop worker process (pid=%u)", + (unsigned int)adhost->adh_worker_pid); + /* + * Other than logging the problem we + * ignore it - nothing smart to do. + */ + } + /* Wait for it to exit. */ + else if ((pid = waitpid(adhost->adh_worker_pid, + &status, 0)) != adhost->adh_worker_pid) { + /* We can only log the problem. */ + pjdlog_errno(LOG_ERR, + "Waiting for worker process (pid=%u) failed", + (unsigned int)adhost->adh_worker_pid); + } else { + child_exit_log("Worker", adhost->adh_worker_pid, + status); + } + child_cleanup(adhost); + } + + adhost->adh_remote = conn; + adist_receiver(adcfg, adhost); + + pjdlog_prefix_set("%s", ""); + return; +close: + proto_close(conn); + pjdlog_prefix_set("%s", ""); +} + +static void +connection_migrate(struct adist_host *adhost) +{ + struct proto_conn *conn; + int16_t val = 0; + + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); + + PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); + + if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) { + pjdlog_errno(LOG_WARNING, + "Unable to receive connection command"); + return; + } + if (proto_set("tls:fingerprint", adhost->adh_fingerprint) == -1) { + val = errno; + pjdlog_errno(LOG_WARNING, "Unable to set fingerprint"); + goto out; + } + if (proto_connect(adhost->adh_localaddr[0] != '\0' ? + adhost->adh_localaddr : NULL, + adhost->adh_remoteaddr, -1, &conn) < 0) { + val = errno; + pjdlog_errno(LOG_WARNING, "Unable to connect to %s", + adhost->adh_remoteaddr); + goto out; + } + val = 0; +out: + if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) { + pjdlog_errno(LOG_WARNING, + "Unable to send reply to connection request"); + } + if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0) + pjdlog_errno(LOG_WARNING, "Unable to send connection"); + + pjdlog_prefix_set("%s", ""); +} + +static void +check_signals(void) +{ + struct timespec sigtimeout; + sigset_t mask; + int signo; + + sigtimeout.tv_sec = 0; + sigtimeout.tv_nsec = 0; + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); + + while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) { + switch (signo) { + case SIGINT: + case SIGTERM: + sigexit_received = true; + terminate_workers(); + exit(EX_OK); + break; + case SIGCHLD: + child_exit(); + break; + case SIGHUP: + adist_reload(); + break; + default: + PJDLOG_ABORT("Unexpected signal (%d).", signo); + } + } +} + +static void +main_loop(void) +{ + struct adist_host *adhost; + struct adist_listen *lst; + struct timeval seltimeout; + int fd, maxfd, ret; + fd_set rfds; + + seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL; + seltimeout.tv_usec = 0; + + pjdlog_info("Started successfully."); + + for (;;) { + check_signals(); + + /* Setup descriptors for select(2). */ + FD_ZERO(&rfds); + maxfd = -1; + TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { + if (lst->adl_conn == NULL) + continue; + fd = proto_descriptor(lst->adl_conn); + PJDLOG_ASSERT(fd >= 0); + FD_SET(fd, &rfds); + maxfd = fd > maxfd ? fd : maxfd; + } + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role == ADIST_ROLE_SENDER) { + /* Only sender workers asks for connections. */ + PJDLOG_ASSERT(adhost->adh_conn != NULL); + fd = proto_descriptor(adhost->adh_conn); + PJDLOG_ASSERT(fd >= 0); + FD_SET(fd, &rfds); + maxfd = fd > maxfd ? fd : maxfd; + } else { + PJDLOG_ASSERT(adhost->adh_conn == NULL); + } + } + + PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); + ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout); + if (ret == 0) { + /* + * select(2) timed out, so there should be no + * descriptors to check. + */ + continue; + } else if (ret == -1) { + if (errno == EINTR) + continue; + KEEP_ERRNO((void)pidfile_remove(pfh)); + pjdlog_exit(EX_OSERR, "select() failed"); + } + PJDLOG_ASSERT(ret > 0); + + /* + * Check for signals before we do anything to update our + * info about terminated workers in the meantime. + */ + check_signals(); + + TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { + if (lst->adl_conn == NULL) + continue; + if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds)) + listen_accept(lst); + } + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role == ADIST_ROLE_SENDER) { + PJDLOG_ASSERT(adhost->adh_conn != NULL); + if (FD_ISSET(proto_descriptor(adhost->adh_conn), + &rfds)) { + connection_migrate(adhost); + } + } else { + PJDLOG_ASSERT(adhost->adh_conn == NULL); + } + } + } +} + +static void +adist_config_dump(struct adist_config *cfg) +{ + struct adist_host *adhost; + struct adist_listen *lst; + + pjdlog_debug(2, "Configuration:"); + pjdlog_debug(2, " Global:"); + pjdlog_debug(2, " pidfile: %s", cfg->adc_pidfile); + pjdlog_debug(2, " timeout: %d", cfg->adc_timeout); + if (TAILQ_EMPTY(&cfg->adc_listen)) { + pjdlog_debug(2, " Sender only, not listening."); + } else { + pjdlog_debug(2, " Listening on:"); + TAILQ_FOREACH(lst, &cfg->adc_listen, adl_next) { + pjdlog_debug(2, " listen: %s", lst->adl_addr); + pjdlog_debug(2, " conn: %p", lst->adl_conn); + } + } + pjdlog_debug(2, " Hosts:"); + TAILQ_FOREACH(adhost, &cfg->adc_hosts, adh_next) { + pjdlog_debug(2, " name: %s", adhost->adh_name); + pjdlog_debug(2, " role: %s", role2str(adhost->adh_role)); + pjdlog_debug(2, " version: %d", adhost->adh_version); + pjdlog_debug(2, " localaddr: %s", adhost->adh_localaddr); + pjdlog_debug(2, " remoteaddr: %s", adhost->adh_remoteaddr); + pjdlog_debug(2, " remote: %p", adhost->adh_remote); + pjdlog_debug(2, " directory: %s", adhost->adh_directory); + pjdlog_debug(2, " compression: %d", adhost->adh_compression); + pjdlog_debug(2, " checksum: %d", adhost->adh_checksum); + pjdlog_debug(2, " pid: %ld", (long)adhost->adh_worker_pid); + pjdlog_debug(2, " conn: %p", adhost->adh_conn); + } +} + +static void +dummy_sighandler(int sig __unused) +{ + /* Nothing to do. */ +} + +int +main(int argc, char *argv[]) +{ + struct adist_host *adhost; + struct adist_listen *lst; + const char *execpath, *pidfile; + bool foreground, launchd; + pid_t otherpid; + int debuglevel; + sigset_t mask; + + execpath = argv[0]; + if (execpath[0] != '/') { + errx(EX_USAGE, + "auditdistd requires execution with an absolute path."); + } + + /* + * We are executed from proto to create sandbox. + */ + if (argc > 1 && strcmp(argv[1], "proto") == 0) { + argc -= 2; + argv += 2; + if (proto_exec(argc, argv) == -1) + err(EX_USAGE, "Unable to execute proto"); + } + + foreground = false; + debuglevel = 0; + launchd = false; + pidfile = NULL; + + for (;;) { + int ch; + + ch = getopt(argc, argv, "c:dFhlP:"); + if (ch == -1) + break; + switch (ch) { + case 'c': + cfgpath = optarg; + break; + case 'd': + debuglevel++; + break; + case 'F': + foreground = true; + break; + case 'l': + launchd = true; + break; + case 'P': + pidfile = optarg; + break; + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + pjdlog_init(PJDLOG_MODE_STD); + pjdlog_debug_set(debuglevel); + + if (proto_set("execpath", execpath) == -1) + pjdlog_exit(EX_TEMPFAIL, "Unable to set executable name"); + if (proto_set("user", ADIST_USER) == -1) + pjdlog_exit(EX_TEMPFAIL, "Unable to set proto user"); + if (proto_set("tcp:port", ADIST_TCP_PORT) == -1) + pjdlog_exit(EX_TEMPFAIL, "Unable to set default TCP port"); + + /* + * When path to the configuration file is relative, obtain full path, + * so we can always find the file, even after daemonizing and changing + * working directory to /. + */ + if (cfgpath[0] != '/') { + const char *newcfgpath; + + newcfgpath = realpath(cfgpath, NULL); + if (newcfgpath == NULL) { + pjdlog_exit(EX_CONFIG, + "Unable to obtain full path of %s", cfgpath); + } + cfgpath = newcfgpath; + } + + adcfg = yy_config_parse(cfgpath, true); + PJDLOG_ASSERT(adcfg != NULL); + adist_config_dump(adcfg); + + if (proto_set("tls:certfile", adcfg->adc_certfile) == -1) + pjdlog_exit(EX_TEMPFAIL, "Unable to set certfile path"); + if (proto_set("tls:keyfile", adcfg->adc_keyfile) == -1) + pjdlog_exit(EX_TEMPFAIL, "Unable to set keyfile path"); + + if (pidfile != NULL) { + if (strlcpy(adcfg->adc_pidfile, pidfile, + sizeof(adcfg->adc_pidfile)) >= + sizeof(adcfg->adc_pidfile)) { + pjdlog_exitx(EX_CONFIG, "Pidfile path is too long."); + } + } + if (foreground && pidfile == NULL) { + pfh = NULL; + } else { + pfh = pidfile_open(adcfg->adc_pidfile, 0600, &otherpid); + if (pfh == NULL) { + if (errno == EEXIST) { + pjdlog_exitx(EX_TEMPFAIL, + "Another auditdistd is already running, pid: %jd.", + (intmax_t)otherpid); + } + /* + * If we cannot create pidfile from other reasons, + * only warn. + */ + pjdlog_errno(LOG_WARNING, + "Unable to open or create pidfile %s", + adcfg->adc_pidfile); + } + } + + /* + * Restore default actions for interesting signals in case parent + * process (like init(8)) decided to ignore some of them (like SIGHUP). + */ + PJDLOG_VERIFY(signal(SIGHUP, SIG_DFL) != SIG_ERR); + PJDLOG_VERIFY(signal(SIGINT, SIG_DFL) != SIG_ERR); + PJDLOG_VERIFY(signal(SIGTERM, SIG_DFL) != SIG_ERR); + /* + * Because SIGCHLD is ignored by default, setup dummy handler for it, + * so we can mask it. + */ + PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR); + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); + + /* Listen for remote connections. */ + TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { + if (proto_server(lst->adl_addr, &lst->adl_conn) == -1) { + KEEP_ERRNO((void)pidfile_remove(pfh)); + pjdlog_exit(EX_OSERR, "Unable to listen on address %s", + lst->adl_addr); + } + } + + if (!foreground) { + if (!launchd && daemon(0, 0) == -1) { + KEEP_ERRNO((void)pidfile_remove(pfh)); + pjdlog_exit(EX_OSERR, "Unable to daemonize"); + } + + /* Start logging to syslog. */ + pjdlog_mode_set(PJDLOG_MODE_SYSLOG); + } + if (pfh != NULL) { + /* Write PID to a file. */ + if (pidfile_write(pfh) < 0) { + pjdlog_errno(LOG_WARNING, + "Unable to write PID to a file"); + } + } + + TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { + if (adhost->adh_role == ADIST_ROLE_SENDER) + adist_sender(adcfg, adhost); + } + + main_loop(); + + exit(0); +} diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 b/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 new file mode 100644 index 0000000..c6ed2b5 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 @@ -0,0 +1,364 @@ +.\" Copyright (c) 2012 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 1, 2015 +.Dt AUDITDISTD.CONF 5 +.Os +.Sh NAME +.Nm auditdistd.conf +.Nd configuration file for the +.Xr auditdistd 8 +daemon. +.Sh DESCRIPTION +Note: the configuration file may contain passwords. +Care should be taken to configure proper permissions for this file +.Li ( e.g., 0600 ) . +.Pp +Every line starting with +.Li # +gets treated as a comment and is ignored. +.Sh CONFIGURATION FILE SYNTAX +The general syntax of the +.Nm +file is as follows: +.Bd -literal +## Global section. + +# Our name. +# The default is the first part of the hostname. +name "<name>" + +# Connection timeout. +# The default is 5. +timeout <seconds> + +# Path to pidfile. +# The default is "/var/run/auditdistd.pid". +pidfile "<path>" + +sender { + ## Sender section. + + # Source address for connections. + # Optional. + source "<addr>" + + # Directory with audit trail files managed by auditdistd. + # The default is /var/audit/dist. + directory "<dir>" +.\" +.\" # Checksum algorithm for data sent over the wire. +.\" # The default is none. +.\" checksum "<algorithm>" +.\" +.\" # Compression algorithm for data sent over the wire. +.\" # The default is none. +.\" compression "<algorithm>" + + # Configuration for the target system we want to send audit trail + # files to. + host "<name>" { + # Source address for connections. + # Optional. + source "<addr>" + + # Address of the auditdistd receiver. + # No default. Obligatory. + remote "<addr>" + + # Directory with audit trail files managed by auditdistd. + # The default is /var/audit/dist. + directory "<dir>" + + # Fingerprint of the receiver's public key when using TLS + # for connections. + # Example fingerprint: + # SHA256=8F:0A:FC:8A:3D:09:80:AF:D9:AA:38:CC:8A:86:53:E6:8F:B6:1C:55:30:14:D7:F9:AA:8B:3E:73:CD:F5:76:2B + fingerprint "<algorithm=hash>" + + # Password used to authenticate in front of the receiver. + password "<password>" +.\" +.\" # Checksum algorithm for data sent over the wire. +.\" # The default is none. +.\" checksum "<algorithm>" +.\" +.\" # Compression algorithm for data sent over the wire. +.\" # The default is none. +.\" compression "<algorithm>" + } + + # Currently local audit trail files can be sent only to one remote + # auditdistd receiver, but this can change in the future. +} + +receiver { + ## Receiver section. + + # Address to listen on. Multiple listen addresses may be specified. + # The defaults are "tcp4://0.0.0.0:7878" and "tcp6://[::]:7878". + listen "<addr>" + + # Base directory. + # If the directory in the host section is not absolute, it will be + # concatenated with this base directory. + # The default is "/var/audit/remote". + directory "<basedir>" + + # Path to the receiver's certificate file. + # The default is "/etc/security/auditdistd.cert.pem". + certfile "<path>" + + # Path to the receiver's private key file. + # The default is "/etc/security/auditdistd.key.pem". + keyfile "<path>" + + # Configuration for a source system we want to receive audit trail + # files from. + host "<name>" { + # Sender address. + # No default. Obligatory. + remote "<addr>" + + # Directory where to store audit trail files received + # from system <name>. + # The default is "<basedir>/<name>". + directory "<dir>" + + # Password used by the sender to authenticate. + password "<password>" + } + + # Multiple hosts to receive from can be configured. +} +.Ed +.Pp +Most of the various available configuration parameters are optional. +If a parameter is not defined in the particular section, it will be +inherited from the parent section if possible. +For example, if the +.Ic source +parameter is not defined in the +.Ic host +section, it will be inherited from the +.Ic sender +section. +In case the +.Ic global +section does not define the +.Ic source +parameter at all, the default value will be used. +.Sh CONFIGURATION OPTION DESCRIPTION +The following statements are available: +.Bl -tag -width ".Ic xxxx" +.It Ic name Aq name +.Pp +This host's name. +It is sent to the receiver, so it can properly recognize us if there are +multiple senders coming from the same IP address. +.It Ic timeout Aq seconds +.Pp +Connection timeout in seconds. +The default value is +.Va 5 . +.It Ic pidfile Aq path +.Pp +File in which to store the process ID of the main +.Xr auditdistd 8 +process. +.Pp +The default value is +.Pa /var/run/auditdistd.pid . +.It Ic source Aq addr +.Pp +Local address to bind to before connecting to the remote +.Nm auditdistd +daemon. +The format is the same as for the +.Ic listen +statement. +.It Ic directory Aq path +.Pp +The directory where to look for audit trail files in case of sender mode, or +the directory where to store received audit trail files. +The provided path has to be an absolute path. +The only exception is when the directory is provided in the +.Ic receiver +section; then the path provided in the +.Ic host +subsections can be relative to the directory in the +.Ic receiver +section. +The default value is +.Pa /var/audit/dist +for the entire +.Ic sender +section, +.Pa /var/audit/remote +for the non-host +.Ic receiver +section and +.Pa /var/audit/remote/<name> +for the +.Ic host +subsections in the +.Ic receiver +section where +.Aq name +is the host's name. +.\".It Ic checksum Aq algorithm +.\".Pp +.\"Checksum algorithm should be one of the following: +.\".Bl -tag -width ".Ic sha256" +.\".It Ic none +.\"No checksum will be calculated for the data being sent over the network. +.\"This is the default setting. +.\".It Ic crc32 +.\"CRC32 checksum will be calculated. +.\".It Ic sha256 +.\"SHA256 checksum will be calculated. +.\".El +.\".It Ic compression Aq algorithm +.\".Pp +.\"Compression algorithm should be one of the following: +.\".Bl -tag -width ".Ic none" +.\".It Ic none +.\"Data sent over the network will not be compressed. +.\"This is the default setting. +.\".It Ic lzf +.\"The +.\".Nm LZF +.\"algorithm by +.\".An Marc Alexander Lehmann +.\"will be used to compress the data sent over the network. +.\".Nm LZF +.\"is a very fast, general purpose compression algorithm. +.\".El +.It Ic remote Aq addr +.Pp +Address of the remote +.Nm auditdistd +daemon. +The format is the same as for the +.Ic listen +statement. +When operating in +.Ic sender +mode this address will be used to connect to the +.Ic receiver . +When operating in +.Ic receiver +mode only connections from this address will be accepted. +.It Ic listen Aq addr +.Pp +Address to listen on in form of: +.Bd -literal -offset indent +protocol://protocol-specific-address +.Ed +.Pp +Each of the following examples defines the same listen address: +.Bd -literal -offset indent +0.0.0.0 +0.0.0.0:7878 +tcp://0.0.0.0 +tcp://0.0.0.0:7878 +tcp4://0.0.0.0 +tcp4://0.0.0.0:7878 +.Ed +.Pp +Multiple listen addresses can be specified. +By default +.Nm auditdistd +listens on +.Pa tcp4://0.0.0.0:7878 +and +.Pa tcp6://[::]:7878 , +if the kernel supports IPv4 and IPv6 respectively. +.It Ic keyfile Aq path +.Pp +Path to a file that contains the private key for TLS communication. +.It Ic certfile Aq path +.Pp +Path to a file that contains the certificate for TLS communication. +.It Ic fingerprint Aq algo=hash +.Pp +Fingerprint of the receiver's public key. +Currently only the SHA256 algorithm is supported. +The certificate public key's fingerprint ready to be pasted into the +.Nm auditdistd +configuration file can be obtained by running: +.Bd -literal +# openssl x509 -in /etc/security/auditdistd.cert.pem -noout -fingerprint -sha256 | awk -F '[ =]' '{printf("%s=%s\\n", $1, $3)}' +.Ed +.It Ic password Aq password +.Pp +Password used to authenticate the sender in front of the receiver. +.El +.Sh FILES +.Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact +.It Pa /etc/security/auditdistd.conf +The default +.Nm auditdistd +configuration file. +.El +.Sh EXAMPLES +The example configuration files can look as follows. +.Pp +Web server: +.Bd -literal -offset indent +sender { + host backup { + remote 10.0.0.4 + } +} +.Ed +.Pp +Audit backup server: +.Bd -literal -offset indent +receiver { + host webserv { + remote 10.0.0.1 + } + host mailserv { + remote 10.0.0.2 + } + host dnsserv { + remote 10.0.0.3 + } +} +.Ed +.Sh SEE ALSO +.Xr audit 4 , +.Xr auditdistd 8 +.Sh AUTHORS +The +.Nm auditdistd +daemon was developed by +.An Pawel Jakub Dawidek Aq pawel@dawidek.net +under sponsorship of the FreeBSD Foundation. diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.h b/contrib/openbsm/bin/auditdistd/auditdistd.h new file mode 100644 index 0000000..d0594f2 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/auditdistd.h @@ -0,0 +1,274 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _AUDITDISTD_H_ +#define _AUDITDISTD_H_ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#include <arpa/inet.h> + +#include <netinet/in.h> + +#include <dirent.h> +#include <limits.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdint.h> + +#include <compat/compat.h> + +#include "proto.h" + +/* + * Version history: + * 0 - initial version + */ +#define ADIST_VERSION 0 + +#define ADIST_ROLE_UNDEF 0 +#define ADIST_ROLE_SENDER 1 +#define ADIST_ROLE_RECEIVER 2 + +#define ADIST_USER "auditdistd" +#define ADIST_TIMEOUT 20 +#define ADIST_CONFIG "/etc/security/auditdistd.conf" +#define ADIST_TCP_PORT "7878" +#define ADIST_LISTEN_TLS_TCP4 "tls://0.0.0.0:" ADIST_TCP_PORT +#define ADIST_LISTEN_TLS_TCP6 "tls://[::]:" ADIST_TCP_PORT +#define ADIST_PIDFILE "/var/run/auditdistd.pid" +#define ADIST_DIRECTORY_SENDER "/var/audit/dist" +#define ADIST_DIRECTORY_RECEIVER "/var/audit/remote" +#define ADIST_CERTFILE "/etc/security/auditdistd.cert.pem" +#define ADIST_KEYFILE "/etc/security/auditdistd.key.pem" + +#define ADIST_ERROR_WRONG_ORDER 1 +#define ADIST_ERROR_INVALID_NAME 2 +#define ADIST_ERROR_OPEN_OLD 3 +#define ADIST_ERROR_CREATE 4 +#define ADIST_ERROR_OPEN 5 +#define ADIST_ERROR_READ 6 +#define ADIST_ERROR_WRITE 7 +#define ADIST_ERROR_RENAME 8 + +#define ADIST_ADDRSIZE 1024 +#define ADIST_HOSTSIZE 256 +#define ADIST_PATHSIZE 256 +#define ADIST_PASSWORDSIZE 128 +#define ADIST_FINGERPRINTSIZE 256 + +/* Number of seconds to sleep between reconnect retries or keepalive packets. */ +#define ADIST_KEEPALIVE 10 + +struct adist_listen { + /* Address to listen on. */ + char adl_addr[ADIST_ADDRSIZE]; + /* Protocol-specific data. */ + struct proto_conn *adl_conn; + TAILQ_ENTRY(adist_listen) adl_next; +}; + +struct adist_config { + /* Our name. */ + char adc_name[ADIST_HOSTSIZE]; + /* PID file path. */ + char adc_pidfile[PATH_MAX]; + /* Connection timeout. */ + int adc_timeout; + /* Path to receiver's certificate file. */ + char adc_certfile[PATH_MAX]; + /* Path to receiver's private key file. */ + char adc_keyfile[PATH_MAX]; + /* List of addresses to listen on. */ + TAILQ_HEAD(, adist_listen) adc_listen; + /* List of hosts. */ + TAILQ_HEAD(, adist_host) adc_hosts; +}; + +#define ADIST_COMPRESSION_NONE 0 +#define ADIST_COMPRESSION_LZF 1 + +#define ADIST_CHECKSUM_NONE 0 +#define ADIST_CHECKSUM_CRC32 1 +#define ADIST_CHECKSUM_SHA256 2 + +/* + * Structure that describes single host (either sender or receiver). + */ +struct adist_host { + /* Host name. */ + char adh_name[ADIST_HOSTSIZE]; + /* Host role: ADIST_ROLE_{SENDER,RECEIVER}. */ + int adh_role; + /* Protocol version negotiated. */ + int adh_version; + + /* Local address to bind to. */ + char adh_localaddr[ADIST_ADDRSIZE]; + /* Address of the remote component. */ + char adh_remoteaddr[ADIST_ADDRSIZE]; + /* Connection with remote host. */ + struct proto_conn *adh_remote; + /* Connection was reestablished, reset the state. */ + bool adh_reset; + + /* + * Directory from which audit trail files should be send in + * ADIST_ROLE_SENDER case or stored into in ADIST_ROLE_RECEIVER case. + */ + char adh_directory[PATH_MAX]; + /* Compression algorithm. Currently unused. */ + int adh_compression; + /* Checksum algorithm. Currently unused. */ + int adh_checksum; + + /* Sender's password. */ + char adh_password[ADIST_PASSWORDSIZE]; + /* Fingerprint of receiver's public key. */ + char adh_fingerprint[ADIST_FINGERPRINTSIZE]; + + /* PID of child worker process. 0 - no child. */ + pid_t adh_worker_pid; + /* Connection requests from sender to main. */ + struct proto_conn *adh_conn; + + /* Receiver-specific fields. */ + char adh_trail_name[ADIST_PATHSIZE]; + int adh_trail_fd; + int adh_trail_dirfd; + DIR *adh_trail_dirfp; + /* Sender-specific fields. */ + uint64_t adh_trail_offset; + + /* Next resource. */ + TAILQ_ENTRY(adist_host) adh_next; +}; + +#define ADIST_BYTEORDER_UNDEFINED 0 +#define ADIST_BYTEORDER_LITTLE_ENDIAN 1 +#define ADIST_BYTEORDER_BIG_ENDIAN 2 + +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define ADIST_BYTEORDER ADIST_BYTEORDER_LITTLE_ENDIAN +#elif _BYTE_ORDER == _BIG_ENDIAN +#define ADIST_BYTEORDER ADIST_BYTEORDER_BIG_ENDIAN +#else +#error Unknown byte order. +#endif + +struct adpkt { + uint8_t adp_byteorder; +#define ADIST_CMD_UNDEFINED 0 +#define ADIST_CMD_OPEN 1 +#define ADIST_CMD_APPEND 2 +#define ADIST_CMD_CLOSE 3 +#define ADIST_CMD_KEEPALIVE 4 +#define ADIST_CMD_ERROR 5 + uint8_t adp_cmd; + uint64_t adp_seq; + uint32_t adp_datasize; + unsigned char adp_data[0]; +} __packed; + +struct adreq { + int adr_error; + TAILQ_ENTRY(adreq) adr_next; + struct adpkt adr_packet; +}; + +#define adr_byteorder adr_packet.adp_byteorder +#define adr_cmd adr_packet.adp_cmd +#define adr_seq adr_packet.adp_seq +#define adr_datasize adr_packet.adp_datasize +#define adr_data adr_packet.adp_data + +#define ADPKT_SIZE(adreq) (sizeof((adreq)->adr_packet) + (adreq)->adr_datasize) + +struct adrep { + uint8_t adrp_byteorder; + uint64_t adrp_seq; + uint16_t adrp_error; +} __packed; + +#define ADIST_QUEUE_SIZE 16 +#define ADIST_BUF_SIZE 65536 + +#define QUEUE_TAKE(adreq, list, timeout) do { \ + mtx_lock(list##_lock); \ + if ((timeout) == 0) { \ + while (((adreq) = TAILQ_FIRST(list)) == NULL) \ + cv_wait(list##_cond, list##_lock); \ + } else { \ + (adreq) = TAILQ_FIRST(list); \ + if ((adreq) == NULL) { \ + cv_timedwait(list##_cond, list##_lock, \ + (timeout)); \ + (adreq) = TAILQ_FIRST(list); \ + } \ + } \ + if ((adreq) != NULL) \ + TAILQ_REMOVE((list), (adreq), adr_next); \ + mtx_unlock(list##_lock); \ +} while (0) +#define QUEUE_INSERT(adreq, list) do { \ + bool _wakeup; \ + \ + mtx_lock(list##_lock); \ + _wakeup = TAILQ_EMPTY(list); \ + TAILQ_INSERT_TAIL((list), (adreq), adr_next); \ + mtx_unlock(list##_lock); \ + if (_wakeup) \ + cv_signal(list##_cond); \ +} while (0) +#define QUEUE_WAIT(list) do { \ + mtx_lock(list##_lock); \ + while (TAILQ_EMPTY(list)) \ + cv_wait(list##_cond, list##_lock); \ + mtx_unlock(list##_lock); \ +} while (0) + +extern const char *cfgpath; +extern bool sigexit_received; +extern struct pidfh *pfh; + +void descriptors_cleanup(struct adist_host *adhost); +void descriptors_assert(const struct adist_host *adhost, int pjdlogmode); + +void adist_sender(struct adist_config *config, struct adist_host *adhost); +void adist_receiver(struct adist_config *config, struct adist_host *adhost); + +struct adist_config *yy_config_parse(const char *config, bool exitonerror); +void yy_config_free(struct adist_config *config); + +void yyerror(const char *); +int yylex(void); + +#endif /* !_AUDITDISTD_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/faccessat.h b/contrib/openbsm/bin/auditdistd/faccessat.h new file mode 100644 index 0000000..568a6b7 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/faccessat.h @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FACCESSAT_H_ +#define _FACCESSAT_H_ + +#include <unistd.h> + +#define AT_EACCESS 0x01 + +static int +faccessat(int fd, const char *path, int mode, int flag) +{ + int cfd, error, ret; + + if (flag == AT_EACCESS) { + errno = EINVAL; + return (-1); + } + + cfd = open(".", O_RDONLY | O_DIRECTORY); + if (cfd == -1) + return (-1); + + if (fchdir(fd) == -1) { + error = errno; + (void)close(cfd); + errno = error; + return (-1); + } + + ret = access(path, mode); + + error = errno; + (void)fchdir(cfd); + (void)close(cfd); + errno = error; + return (ret); +} + +#endif /* !_FACCESSAT_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/fstatat.h b/contrib/openbsm/bin/auditdistd/fstatat.h new file mode 100644 index 0000000..5327a7c --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/fstatat.h @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FSTATAT_H_ +#define _FSTATAT_H_ + +#include <sys/stat.h> + +#include <unistd.h> + +#define AT_SYMLINK_NOFOLLOW 0x01 + +static int +fstatat(int fd, const char *path, struct stat *buf, int flag) +{ + int cfd, error, ret; + + cfd = open(".", O_RDONLY | O_DIRECTORY); + if (cfd == -1) + return (-1); + + if (fchdir(fd) == -1) { + error = errno; + (void)close(cfd); + errno = error; + return (-1); + } + + if (flag == AT_SYMLINK_NOFOLLOW) + ret = lstat(path, buf); + else + ret = stat(path, buf); + + error = errno; + (void)fchdir(cfd); + (void)close(cfd); + errno = error; + return (ret); +} + +#endif /* !_FSTATAT_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/openat.h b/contrib/openbsm/bin/auditdistd/openat.h new file mode 100644 index 0000000..1d98014 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/openat.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _OPENAT_H_ +#define _OPENAT_H_ + +#include <fcntl.h> +#include <stdarg.h> +#include <unistd.h> + +static int +openat(int fd, const char *path, int flags, ...) +{ + int cfd, ffd, error; + + cfd = open(".", O_RDONLY | O_DIRECTORY); + if (cfd == -1) + return (-1); + + if (fchdir(fd) == -1) { + error = errno; + (void)close(cfd); + errno = error; + return (-1); + } + + if ((flags & O_CREAT) != 0) { + va_list ap; + int mode; + + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + + ffd = open(path, flags, mode); + } else { + ffd = open(path, flags); + } + + error = errno; + (void)fchdir(cfd); + (void)close(cfd); + errno = error; + return (ffd); +} + +#endif /* !_OPENAT_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/parse.y b/contrib/openbsm/bin/auditdistd/parse.y new file mode 100644 index 0000000..1f80d50 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/parse.y @@ -0,0 +1,854 @@ +%{ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/sysctl.h> + +#include <arpa/inet.h> + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +#include "auditdistd.h" +#include "pjdlog.h" + +extern int depth; +extern int lineno; + +extern FILE *yyin; +extern char *yytext; + +static struct adist_config *lconfig; +static struct adist_host *curhost; +#define SECTION_GLOBAL 0 +#define SECTION_SENDER 1 +#define SECTION_RECEIVER 2 +static int cursection; + +/* Sender section. */ +static char depth1_source[ADIST_ADDRSIZE]; +static int depth1_checksum; +static int depth1_compression; +/* Sender and receiver sections. */ +static char depth1_directory[PATH_MAX]; + +static bool adjust_directory(char *path); +static bool family_supported(int family); + +extern void yyrestart(FILE *); +%} + +%token CB +%token CERTFILE +%token DIRECTORY +%token FINGERPRINT +%token HOST +%token KEYFILE +%token LISTEN +%token NAME +%token OB +%token PASSWORD +%token PIDFILE +%token RECEIVER REMOTE +%token SENDER SOURCE +%token TIMEOUT + +/* +%type <num> checksum_type +%type <num> compression_type +*/ + +%union +{ + int num; + char *str; +} + +%token <num> NUM +%token <str> STR + +%% + +statements: + | + statements statement + ; + +statement: + name_statement + | + pidfile_statement + | + timeout_statement + | + sender_statement + | + receiver_statement + ; + +name_statement: NAME STR + { + PJDLOG_RASSERT(depth == 0, + "The name variable can only be specificed in the global section."); + + if (lconfig->adc_name[0] != '\0') { + pjdlog_error("The name variable is specified twice."); + free($2); + return (1); + } + if (strlcpy(lconfig->adc_name, $2, + sizeof(lconfig->adc_name)) >= + sizeof(lconfig->adc_name)) { + pjdlog_error("The name value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +pidfile_statement: PIDFILE STR + { + PJDLOG_RASSERT(depth == 0, + "The pidfile variable can only be specificed in the global section."); + + if (lconfig->adc_pidfile[0] != '\0') { + pjdlog_error("The pidfile variable is specified twice."); + free($2); + return (1); + } + if (strcmp($2, "none") != 0 && $2[0] != '/') { + pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\"."); + free($2); + return (1); + } + if (strlcpy(lconfig->adc_pidfile, $2, + sizeof(lconfig->adc_pidfile)) >= + sizeof(lconfig->adc_pidfile)) { + pjdlog_error("The pidfile value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +timeout_statement: TIMEOUT NUM + { + PJDLOG_ASSERT(depth == 0); + + lconfig->adc_timeout = $2; + } + ; + +sender_statement: SENDER sender_start sender_entries CB + { + PJDLOG_ASSERT(depth == 0); + PJDLOG_ASSERT(cursection == SECTION_SENDER); + + /* Configure defaults. */ + if (depth1_checksum == -1) + depth1_checksum = ADIST_CHECKSUM_NONE; + if (depth1_compression == -1) + depth1_compression = ADIST_COMPRESSION_NONE; + if (depth1_directory[0] == '\0') { + (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER, + sizeof(depth1_directory)); + } + /* Empty depth1_source is ok. */ + TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { + if (curhost->adh_role != ADIST_ROLE_SENDER) + continue; + if (curhost->adh_checksum == -1) + curhost->adh_checksum = depth1_checksum; + if (curhost->adh_compression == -1) + curhost->adh_compression = depth1_compression; + if (curhost->adh_directory[0] == '\0') { + (void)strlcpy(curhost->adh_directory, + depth1_directory, + sizeof(curhost->adh_directory)); + } + if (curhost->adh_localaddr[0] == '\0') { + (void)strlcpy(curhost->adh_localaddr, + depth1_source, + sizeof(curhost->adh_localaddr)); + } + } + cursection = SECTION_GLOBAL; + } + ; + +sender_start: OB + { + PJDLOG_ASSERT(depth == 1); + PJDLOG_ASSERT(cursection == SECTION_GLOBAL); + + cursection = SECTION_SENDER; + depth1_checksum = -1; + depth1_compression = -1; + depth1_source[0] = '\0'; + depth1_directory[0] = '\0'; + +#ifndef HAVE_AUDIT_SYSCALLS + pjdlog_error("Sender functionality is not available."); + return (1); +#endif + } + ; + +sender_entries: + | + sender_entries sender_entry + ; + +sender_entry: + source_statement + | + directory_statement +/* + | + checksum_statement + | + compression_statement +*/ + | + sender_host_statement + ; + +receiver_statement: RECEIVER receiver_start receiver_entries CB + { + PJDLOG_ASSERT(depth == 0); + PJDLOG_ASSERT(cursection == SECTION_RECEIVER); + + /* + * If not listen addresses were specified, + * configure default ones. + */ + if (TAILQ_EMPTY(&lconfig->adc_listen)) { + struct adist_listen *lst; + + if (family_supported(AF_INET)) { + lst = calloc(1, sizeof(*lst)); + if (lst == NULL) { + pjdlog_error("Unable to allocate memory for listen address."); + return (1); + } + (void)strlcpy(lst->adl_addr, + ADIST_LISTEN_TLS_TCP4, + sizeof(lst->adl_addr)); + TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); + } else { + pjdlog_debug(1, + "No IPv4 support in the kernel, not listening on IPv4 address."); + } + if (family_supported(AF_INET6)) { + lst = calloc(1, sizeof(*lst)); + if (lst == NULL) { + pjdlog_error("Unable to allocate memory for listen address."); + return (1); + } + (void)strlcpy(lst->adl_addr, + ADIST_LISTEN_TLS_TCP6, + sizeof(lst->adl_addr)); + TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); + } else { + pjdlog_debug(1, + "No IPv6 support in the kernel, not listening on IPv6 address."); + } + if (TAILQ_EMPTY(&lconfig->adc_listen)) { + pjdlog_error("No address to listen on."); + return (1); + } + } + /* Configure defaults. */ + if (depth1_directory[0] == '\0') { + (void)strlcpy(depth1_directory, + ADIST_DIRECTORY_RECEIVER, + sizeof(depth1_directory)); + } + TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { + if (curhost->adh_role != ADIST_ROLE_RECEIVER) + continue; + if (curhost->adh_directory[0] == '\0') { + if (snprintf(curhost->adh_directory, + sizeof(curhost->adh_directory), "%s/%s", + depth1_directory, curhost->adh_name) >= + (ssize_t)sizeof(curhost->adh_directory)) { + pjdlog_error("Directory value is too long."); + return (1); + } + } + } + cursection = SECTION_GLOBAL; + } + ; + +receiver_start: OB + { + PJDLOG_ASSERT(depth == 1); + PJDLOG_ASSERT(cursection == SECTION_GLOBAL); + + cursection = SECTION_RECEIVER; + depth1_directory[0] = '\0'; + } + ; + +receiver_entries: + | + receiver_entries receiver_entry + ; + +receiver_entry: + listen_statement + | + directory_statement + | + certfile_statement + | + keyfile_statement + | + receiver_host_statement + ; + +/* +checksum_statement: CHECKSUM checksum_type + { + PJDLOG_ASSERT(cursection == SECTION_SENDER); + + switch (depth) { + case 1: + depth1_checksum = $2; + break; + case 2: + PJDLOG_ASSERT(curhost != NULL); + curhost->adh_checksum = $2; + break; + default: + PJDLOG_ABORT("checksum at wrong depth level"); + } + } + ; + +checksum_type: + NONE { $$ = ADIST_CHECKSUM_NONE; } + | + CRC32 { $$ = ADIST_CHECKSUM_CRC32; } + | + SHA256 { $$ = ADIST_CHECKSUM_SHA256; } + ; + +compression_statement: COMPRESSION compression_type + { + PJDLOG_ASSERT(cursection == SECTION_SENDER); + + switch (depth) { + case 1: + depth1_compression = $2; + break; + case 2: + PJDLOG_ASSERT(curhost != NULL); + curhost->adh_compression = $2; + break; + default: + PJDLOG_ABORT("compression at wrong depth level"); + } + } + ; + +compression_type: + NONE { $$ = ADIST_COMPRESSION_NONE; } + | + LZF { $$ = ADIST_COMPRESSION_LZF; } + ; +*/ + +directory_statement: DIRECTORY STR + { + PJDLOG_ASSERT(cursection == SECTION_SENDER || + cursection == SECTION_RECEIVER); + + switch (depth) { + case 1: + if (strlcpy(depth1_directory, $2, + sizeof(depth1_directory)) >= + sizeof(depth1_directory)) { + pjdlog_error("Directory value is too long."); + free($2); + return (1); + } + if (!adjust_directory(depth1_directory)) + return (1); + break; + case 2: + if (cursection == SECTION_SENDER || $2[0] == '/') { + if (strlcpy(curhost->adh_directory, $2, + sizeof(curhost->adh_directory)) >= + sizeof(curhost->adh_directory)) { + pjdlog_error("Directory value is too long."); + free($2); + return (1); + } + } else /* if (cursection == SECTION_RECEIVER) */ { + if (depth1_directory[0] == '\0') { + pjdlog_error("Directory path must be absolute."); + free($2); + return (1); + } + if (snprintf(curhost->adh_directory, + sizeof(curhost->adh_directory), "%s/%s", + depth1_directory, $2) >= + (ssize_t)sizeof(curhost->adh_directory)) { + pjdlog_error("Directory value is too long."); + free($2); + return (1); + } + } + break; + default: + PJDLOG_ABORT("directory at wrong depth level"); + } + free($2); + } + ; + +source_statement: SOURCE STR + { + PJDLOG_RASSERT(cursection == SECTION_SENDER, + "The source variable must be in sender section."); + + switch (depth) { + case 1: + if (strlcpy(depth1_source, $2, + sizeof(depth1_source)) >= + sizeof(depth1_source)) { + pjdlog_error("Source value is too long."); + free($2); + return (1); + } + break; + case 2: + if (strlcpy(curhost->adh_localaddr, $2, + sizeof(curhost->adh_localaddr)) >= + sizeof(curhost->adh_localaddr)) { + pjdlog_error("Source value is too long."); + free($2); + return (1); + } + break; + } + free($2); + } + ; + +fingerprint_statement: FINGERPRINT STR + { + PJDLOG_ASSERT(cursection == SECTION_SENDER); + PJDLOG_ASSERT(depth == 2); + + if (strncasecmp($2, "SHA256=", 7) != 0) { + pjdlog_error("Invalid fingerprint value."); + free($2); + return (1); + } + if (strlcpy(curhost->adh_fingerprint, $2, + sizeof(curhost->adh_fingerprint)) >= + sizeof(curhost->adh_fingerprint)) { + pjdlog_error("Fingerprint value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +password_statement: PASSWORD STR + { + PJDLOG_ASSERT(cursection == SECTION_SENDER || + cursection == SECTION_RECEIVER); + PJDLOG_ASSERT(depth == 2); + + if (strlcpy(curhost->adh_password, $2, + sizeof(curhost->adh_password)) >= + sizeof(curhost->adh_password)) { + pjdlog_error("Password value is too long."); + bzero($2, strlen($2)); + free($2); + return (1); + } + bzero($2, strlen($2)); + free($2); + } + ; + +certfile_statement: CERTFILE STR + { + PJDLOG_ASSERT(cursection == SECTION_RECEIVER); + PJDLOG_ASSERT(depth == 1); + + if (strlcpy(lconfig->adc_certfile, $2, + sizeof(lconfig->adc_certfile)) >= + sizeof(lconfig->adc_certfile)) { + pjdlog_error("Certfile value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +keyfile_statement: KEYFILE STR + { + PJDLOG_ASSERT(cursection == SECTION_RECEIVER); + PJDLOG_ASSERT(depth == 1); + + if (strlcpy(lconfig->adc_keyfile, $2, + sizeof(lconfig->adc_keyfile)) >= + sizeof(lconfig->adc_keyfile)) { + pjdlog_error("Keyfile value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +listen_statement: LISTEN STR + { + struct adist_listen *lst; + + PJDLOG_ASSERT(depth == 1); + PJDLOG_ASSERT(cursection == SECTION_RECEIVER); + + lst = calloc(1, sizeof(*lst)); + if (lst == NULL) { + pjdlog_error("Unable to allocate memory for listen address."); + free($2); + return (1); + } + if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >= + sizeof(lst->adl_addr)) { + pjdlog_error("listen argument is too long."); + free($2); + free(lst); + return (1); + } + TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); + free($2); + } + ; + +sender_host_statement: HOST host_start OB sender_host_entries CB + { + /* Put it onto host list. */ + TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); + curhost = NULL; + } + ; + +receiver_host_statement: HOST host_start OB receiver_host_entries CB + { + /* Put it onto host list. */ + TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); + curhost = NULL; + } + ; + +host_start: STR + { + /* Check if there is no duplicate entry. */ + TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { + if (strcmp(curhost->adh_name, $1) != 0) + continue; + if (curhost->adh_role == ADIST_ROLE_SENDER && + cursection == SECTION_RECEIVER) { + continue; + } + if (curhost->adh_role == ADIST_ROLE_RECEIVER && + cursection == SECTION_SENDER) { + continue; + } + pjdlog_error("%s host %s is configured more than once.", + curhost->adh_role == ADIST_ROLE_SENDER ? + "Sender" : "Receiver", curhost->adh_name); + free($1); + return (1); + } + + curhost = calloc(1, sizeof(*curhost)); + if (curhost == NULL) { + pjdlog_error("Unable to allocate memory for host configuration."); + free($1); + return (1); + } + if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >= + sizeof(curhost->adh_name)) { + pjdlog_error("Host name is too long."); + free($1); + return (1); + } + free($1); + curhost->adh_role = cursection == SECTION_SENDER ? + ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER; + curhost->adh_version = ADIST_VERSION; + curhost->adh_localaddr[0] = '\0'; + curhost->adh_remoteaddr[0] = '\0'; + curhost->adh_remote = NULL; + curhost->adh_directory[0] = '\0'; + curhost->adh_password[0] = '\0'; + curhost->adh_fingerprint[0] = '\0'; + curhost->adh_worker_pid = 0; + curhost->adh_conn = NULL; + } + ; + +sender_host_entries: + | + sender_host_entries sender_host_entry + ; + +sender_host_entry: + source_statement + | + remote_statement + | + directory_statement + | + fingerprint_statement + | + password_statement +/* + | + checksum_statement + | + compression_statement +*/ + ; + +receiver_host_entries: + | + receiver_host_entries receiver_host_entry + ; + +receiver_host_entry: + remote_statement + | + directory_statement + | + password_statement + ; + +remote_statement: REMOTE STR + { + PJDLOG_ASSERT(depth == 2); + PJDLOG_ASSERT(cursection == SECTION_SENDER || + cursection == SECTION_RECEIVER); + + if (strlcpy(curhost->adh_remoteaddr, $2, + sizeof(curhost->adh_remoteaddr)) >= + sizeof(curhost->adh_remoteaddr)) { + pjdlog_error("Remote value is too long."); + free($2); + return (1); + } + free($2); + } + ; + +%% + +static bool +family_supported(int family) +{ + int sock; + + sock = socket(family, SOCK_STREAM, 0); + if (sock == -1 && errno == EPROTONOSUPPORT) + return (false); + if (sock >= 0) + (void)close(sock); + return (true); +} + +static bool +adjust_directory(char *path) +{ + size_t len; + + len = strlen(path); + for (;;) { + if (len == 0) { + pjdlog_error("Directory path is empty."); + return (false); + } + if (path[len - 1] != '/') + break; + len--; + path[len] = '\0'; + } + if (path[0] != '/') { + pjdlog_error("Directory path must be absolute."); + return (false); + } + return (true); +} + +static int +my_name(char *name, size_t size) +{ + char buf[MAXHOSTNAMELEN]; + char *pos; + + if (gethostname(buf, sizeof(buf)) < 0) { + pjdlog_errno(LOG_ERR, "gethostname() failed"); + return (-1); + } + + /* First component of the host name. */ + pos = strchr(buf, '.'); + if (pos == NULL) + (void)strlcpy(name, buf, size); + else + (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size)); + + if (name[0] == '\0') { + pjdlog_error("Empty host name."); + return (-1); + } + + return (0); +} + +void +yyerror(const char *str) +{ + + pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", + lineno, yytext, str); +} + +struct adist_config * +yy_config_parse(const char *config, bool exitonerror) +{ + int ret; + + curhost = NULL; + cursection = SECTION_GLOBAL; + depth = 0; + lineno = 0; + + lconfig = calloc(1, sizeof(*lconfig)); + if (lconfig == NULL) { + pjdlog_error("Unable to allocate memory for configuration."); + if (exitonerror) + exit(EX_TEMPFAIL); + return (NULL); + } + TAILQ_INIT(&lconfig->adc_hosts); + TAILQ_INIT(&lconfig->adc_listen); + lconfig->adc_name[0] = '\0'; + lconfig->adc_timeout = -1; + lconfig->adc_pidfile[0] = '\0'; + lconfig->adc_certfile[0] = '\0'; + lconfig->adc_keyfile[0] = '\0'; + + yyin = fopen(config, "r"); + if (yyin == NULL) { + pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", + config); + yy_config_free(lconfig); + if (exitonerror) + exit(EX_OSFILE); + return (NULL); + } + yyrestart(yyin); + ret = yyparse(); + fclose(yyin); + if (ret != 0) { + yy_config_free(lconfig); + if (exitonerror) + exit(EX_CONFIG); + return (NULL); + } + + /* + * Let's see if everything is set up. + */ + if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name, + sizeof(lconfig->adc_name)) == -1) { + yy_config_free(lconfig); + if (exitonerror) + exit(EX_CONFIG); + return (NULL); + } + if (lconfig->adc_timeout == -1) + lconfig->adc_timeout = ADIST_TIMEOUT; + if (lconfig->adc_pidfile[0] == '\0') { + (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE, + sizeof(lconfig->adc_pidfile)); + } + if (lconfig->adc_certfile[0] == '\0') { + (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE, + sizeof(lconfig->adc_certfile)); + } + if (lconfig->adc_keyfile[0] == '\0') { + (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE, + sizeof(lconfig->adc_keyfile)); + } + + return (lconfig); +} + +void +yy_config_free(struct adist_config *config) +{ + struct adist_host *adhost; + struct adist_listen *lst; + + while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) { + TAILQ_REMOVE(&config->adc_listen, lst, adl_next); + free(lst); + } + while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) { + TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next); + bzero(adhost, sizeof(*adhost)); + free(adhost); + } + free(config); +} diff --git a/contrib/openbsm/bin/auditdistd/pjdlog.c b/contrib/openbsm/bin/auditdistd/pjdlog.c new file mode 100644 index 0000000..16f176e --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/pjdlog.c @@ -0,0 +1,619 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <errno.h> +#ifdef __FreeBSD__ +#include <libutil.h> +#include <printf.h> +#endif +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#include "pjdlog.h" + +#define PJDLOG_NEVER_INITIALIZED 0 +#define PJDLOG_NOT_INITIALIZED 1 +#define PJDLOG_INITIALIZED 2 + +static int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; +static int pjdlog_mode, pjdlog_debug_level; +static char pjdlog_prefix[128]; + +#ifdef __FreeBSD__ +static int +pjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, + size_t n, int *argt) +{ + + assert(n >= 1); + argt[0] = PA_INT | PA_FLAG_INTMAX; + return (1); +} + +static int +pjdlog_printf_render_humanized_number(struct __printf_io *io, + const struct printf_info *pi, const void * const *arg) +{ + char buf[5]; + intmax_t num; + int ret; + + num = *(const intmax_t *)arg[0]; + humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + ret = __printf_out(io, pi, buf, strlen(buf)); + __printf_flush(io); + return (ret); +} + +static int +pjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, + size_t n, int *argt) +{ + + assert(n >= 1); + argt[0] = PA_POINTER; + return (1); +} + +static int +pjdlog_printf_render_sockaddr(struct __printf_io *io, + const struct printf_info *pi, const void * const *arg) +{ + const struct sockaddr_storage *ss; + char buf[64]; + int ret; + + ss = *(const struct sockaddr_storage * const *)arg[0]; + switch (ss->ss_family) { + case AF_INET: + { + char addr[INET_ADDRSTRLEN]; + const struct sockaddr_in *sin; + unsigned int port; + + sin = (const struct sockaddr_in *)ss; + port = ntohs(sin->sin_port); + if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, + sizeof(addr)) == NULL) { + PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", + strerror(errno)); + } + snprintf(buf, sizeof(buf), "%s:%u", addr, port); + break; + } + case AF_INET6: + { + char addr[INET6_ADDRSTRLEN]; + const struct sockaddr_in6 *sin; + unsigned int port; + + sin = (const struct sockaddr_in6 *)ss; + port = ntohs(sin->sin6_port); + if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, + sizeof(addr)) == NULL) { + PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", + strerror(errno)); + } + snprintf(buf, sizeof(buf), "[%s]:%u", addr, port); + break; + } + default: + snprintf(buf, sizeof(buf), "[unsupported family %hhu]", + ss->ss_family); + break; + } + ret = __printf_out(io, pi, buf, strlen(buf)); + __printf_flush(io); + return (ret); +} +#endif /* __FreeBSD__ */ + +void +pjdlog_init(int mode) +{ + int saved_errno; + + assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || + pjdlog_initialized == PJDLOG_NOT_INITIALIZED); + assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); + + saved_errno = errno; + + if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { +#ifdef __FreeBSD__ + __use_xprintf = 1; + register_printf_render_std("T"); + register_printf_render('N', + pjdlog_printf_render_humanized_number, + pjdlog_printf_arginfo_humanized_number); + register_printf_render('S', + pjdlog_printf_render_sockaddr, + pjdlog_printf_arginfo_sockaddr); +#endif + } + + if (mode == PJDLOG_MODE_SYSLOG) + openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); + pjdlog_mode = mode; + pjdlog_debug_level = 0; + bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); + + pjdlog_initialized = PJDLOG_INITIALIZED; + + errno = saved_errno; +} + +void +pjdlog_fini(void) +{ + int saved_errno; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + saved_errno = errno; + + if (pjdlog_mode == PJDLOG_MODE_SYSLOG) + closelog(); + + pjdlog_initialized = PJDLOG_NOT_INITIALIZED; + + errno = saved_errno; +} + +/* + * Configure where the logs should go. + * By default they are send to stdout/stderr, but after going into background + * (eg. by calling daemon(3)) application is responsible for changing mode to + * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. + */ +void +pjdlog_mode_set(int mode) +{ + int saved_errno; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); + + if (pjdlog_mode == mode) + return; + + saved_errno = errno; + + if (mode == PJDLOG_MODE_SYSLOG) + openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); + else /* if (mode == PJDLOG_MODE_STD) */ + closelog(); + + pjdlog_mode = mode; + + errno = saved_errno; +} + +/* + * Return current mode. + */ +int +pjdlog_mode_get(void) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + return (pjdlog_mode); +} + +/* + * Set debug level. All the logs above the level specified here will be + * ignored. + */ +void +pjdlog_debug_set(int level) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(level >= 0); + + pjdlog_debug_level = level; +} + +/* + * Return current debug level. + */ +int +pjdlog_debug_get(void) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + return (pjdlog_debug_level); +} + +/* + * Set prefix that will be used before each log. + * Setting prefix to NULL will remove it. + */ +void +pjdlog_prefix_set(const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_prefix_set(fmt, ap); + va_end(ap); +} + +/* + * Set prefix that will be used before each log. + * Setting prefix to NULL will remove it. + */ +void +pjdlogv_prefix_set(const char *fmt, va_list ap) +{ + int saved_errno; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(fmt != NULL); + + saved_errno = errno; + + vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); + + errno = saved_errno; +} + +/* + * Convert log level into string. + */ +static const char * +pjdlog_level_string(int loglevel) +{ + + switch (loglevel) { + case LOG_EMERG: + return ("EMERG"); + case LOG_ALERT: + return ("ALERT"); + case LOG_CRIT: + return ("CRIT"); + case LOG_ERR: + return ("ERROR"); + case LOG_WARNING: + return ("WARNING"); + case LOG_NOTICE: + return ("NOTICE"); + case LOG_INFO: + return ("INFO"); + case LOG_DEBUG: + return ("DEBUG"); + } + assert(!"Invalid log level."); + abort(); /* XXX: gcc */ +} + +/* + * Common log routine. + */ +void +pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_common(loglevel, debuglevel, error, fmt, ap); + va_end(ap); +} + +/* + * Common log routine, which can handle regular log level as well as debug + * level. We decide here where to send the logs (stdout/stderr or syslog). + */ +void +pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, + va_list ap) +{ + int saved_errno; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || + loglevel == LOG_CRIT || loglevel == LOG_ERR || + loglevel == LOG_WARNING || loglevel == LOG_NOTICE || + loglevel == LOG_INFO || loglevel == LOG_DEBUG); + assert(loglevel != LOG_DEBUG || debuglevel > 0); + assert(error >= -1); + + /* Ignore debug above configured level. */ + if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) + return; + + saved_errno = errno; + + switch (pjdlog_mode) { + case PJDLOG_MODE_STD: + { + FILE *out; + + /* + * We send errors and warning to stderr and the rest to stdout. + */ + switch (loglevel) { + case LOG_EMERG: + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + case LOG_WARNING: + out = stderr; + break; + case LOG_NOTICE: + case LOG_INFO: + case LOG_DEBUG: + out = stdout; + break; + default: + assert(!"Invalid loglevel."); + abort(); /* XXX: gcc */ + } + + fprintf(out, "(%d) ", getpid()); + fprintf(out, "[%s]", pjdlog_level_string(loglevel)); + /* Attach debuglevel if this is debug log. */ + if (loglevel == LOG_DEBUG) + fprintf(out, "[%d]", debuglevel); + fprintf(out, " %s", pjdlog_prefix); + vfprintf(out, fmt, ap); + if (error != -1) + fprintf(out, ": %s.", strerror(error)); + fprintf(out, "\n"); + fflush(out); + break; + } + case PJDLOG_MODE_SYSLOG: + { + char log[1024]; + int len; + + len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); + if ((size_t)len < sizeof(log)) + len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); + if (error != -1 && (size_t)len < sizeof(log)) { + (void)snprintf(log + len, sizeof(log) - len, ": %s.", + strerror(error)); + } + syslog(loglevel, "%s", log); + break; + } + default: + assert(!"Invalid mode."); + } + + errno = saved_errno; +} + +/* + * Regular logs. + */ +void +pjdlogv(int loglevel, const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ + assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || + loglevel == LOG_CRIT || loglevel == LOG_ERR || + loglevel == LOG_WARNING || loglevel == LOG_NOTICE || + loglevel == LOG_INFO); + + pjdlogv_common(loglevel, 0, -1, fmt, ap); +} + +/* + * Regular logs. + */ +void +pjdlog(int loglevel, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv(loglevel, fmt, ap); + va_end(ap); +} + +/* + * Debug logs. + */ +void +pjdlogv_debug(int debuglevel, const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); +} + +/* + * Debug logs. + */ +void +pjdlog_debug(int debuglevel, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_debug(debuglevel, fmt, ap); + va_end(ap); +} + +/* + * Error logs with errno logging. + */ +void +pjdlogv_errno(int loglevel, const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + pjdlogv_common(loglevel, 0, errno, fmt, ap); +} + +/* + * Error logs with errno logging. + */ +void +pjdlog_errno(int loglevel, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_errno(loglevel, fmt, ap); + va_end(ap); +} + +/* + * Log error, errno and exit. + */ +void +pjdlogv_exit(int exitcode, const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + pjdlogv_errno(LOG_ERR, fmt, ap); + exit(exitcode); + /* NOTREACHED */ +} + +/* + * Log error, errno and exit. + */ +void +pjdlog_exit(int exitcode, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_exit(exitcode, fmt, ap); + /* NOTREACHED */ + va_end(ap); +} + +/* + * Log error and exit. + */ +void +pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + pjdlogv(LOG_ERR, fmt, ap); + exit(exitcode); + /* NOTREACHED */ +} + +/* + * Log error and exit. + */ +void +pjdlog_exitx(int exitcode, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_exitx(exitcode, fmt, ap); + /* NOTREACHED */ + va_end(ap); +} + +/* + * Log failure message and exit. + */ +void +pjdlog_abort(const char *func, const char *file, int line, + const char *failedexpr, const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + /* + * When there is no message we pass __func__ as 'fmt'. + * It would be cleaner to pass NULL or "", but gcc generates a warning + * for both of those. + */ + if (fmt != func) { + va_start(ap, fmt); + pjdlogv_critical(fmt, ap); + va_end(ap); + } + if (failedexpr == NULL) { + if (func == NULL) { + pjdlog_critical("Aborted at file %s, line %d.", file, + line); + } else { + pjdlog_critical("Aborted at function %s, file %s, line %d.", + func, file, line); + } + } else { + if (func == NULL) { + pjdlog_critical("Assertion failed: (%s), file %s, line %d.", + failedexpr, file, line); + } else { + pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", + failedexpr, func, file, line); + } + } + abort(); +} diff --git a/contrib/openbsm/bin/auditdistd/pjdlog.h b/contrib/openbsm/bin/auditdistd/pjdlog.h new file mode 100644 index 0000000..d6f217f --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/pjdlog.h @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PJDLOG_H_ +#define _PJDLOG_H_ + +#include <sys/cdefs.h> + +#include <stdarg.h> +#include <sysexits.h> +#include <syslog.h> + +#include <compat/compat.h> + +#define PJDLOG_MODE_STD 0 +#define PJDLOG_MODE_SYSLOG 1 + +void pjdlog_init(int mode); +void pjdlog_fini(void); + +void pjdlog_mode_set(int mode); +int pjdlog_mode_get(void); + +void pjdlog_debug_set(int level); +int pjdlog_debug_get(void); + +void pjdlog_prefix_set(const char *fmt, ...) __printflike(1, 2); +void pjdlogv_prefix_set(const char *fmt, va_list ap) __printflike(1, 0); + +void pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, + ...) __printflike(4, 5); +void pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, + va_list ap) __printflike(4, 0); + +void pjdlog(int loglevel, const char *fmt, ...) __printflike(2, 3); +void pjdlogv(int loglevel, const char *fmt, va_list ap) __printflike(2, 0); + +#define pjdlogv_emergency(fmt, ap) pjdlogv(LOG_EMERG, (fmt), (ap)) +#define pjdlog_emergency(...) pjdlog(LOG_EMERG, __VA_ARGS__) +#define pjdlogv_alert(fmt, ap) pjdlogv(LOG_ALERT, (fmt), (ap)) +#define pjdlog_alert(...) pjdlog(LOG_ALERT, __VA_ARGS__) +#define pjdlogv_critical(fmt, ap) pjdlogv(LOG_CRIT, (fmt), (ap)) +#define pjdlog_critical(...) pjdlog(LOG_CRIT, __VA_ARGS__) +#define pjdlogv_error(fmt, ap) pjdlogv(LOG_ERR, (fmt), (ap)) +#define pjdlog_error(...) pjdlog(LOG_ERR, __VA_ARGS__) +#define pjdlogv_warning(fmt, ap) pjdlogv(LOG_WARNING, (fmt), (ap)) +#define pjdlog_warning(...) pjdlog(LOG_WARNING, __VA_ARGS__) +#define pjdlogv_notice(fmt, ap) pjdlogv(LOG_NOTICE, (fmt), (ap)) +#define pjdlog_notice(...) pjdlog(LOG_NOTICE, __VA_ARGS__) +#define pjdlogv_info(fmt, ap) pjdlogv(LOG_INFO, (fmt), (ap)) +#define pjdlog_info(...) pjdlog(LOG_INFO, __VA_ARGS__) + +void pjdlog_debug(int debuglevel, const char *fmt, ...) __printflike(2, 3); +void pjdlogv_debug(int debuglevel, const char *fmt, va_list ap) __printflike(2, 0); + +void pjdlog_errno(int loglevel, const char *fmt, ...) __printflike(2, 3); +void pjdlogv_errno(int loglevel, const char *fmt, va_list ap) __printflike(2, 0); + +void pjdlog_exit(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2; +void pjdlogv_exit(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2; + +void pjdlog_exitx(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2; +void pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2; + +void pjdlog_abort(const char *func, const char *file, int line, + const char *failedexpr, const char *fmt, ...) __printflike(5, 6) __dead2; + +#define PJDLOG_VERIFY(expr) do { \ + if (!(expr)) { \ + pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \ + "%s", __func__); \ + } \ +} while (0) +#define PJDLOG_RVERIFY(expr, ...) do { \ + if (!(expr)) { \ + pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \ + __VA_ARGS__); \ + } \ +} while (0) +#define PJDLOG_ABORT(...) pjdlog_abort(__func__, __FILE__, \ + __LINE__, NULL, __VA_ARGS__) +#ifdef NDEBUG +#define PJDLOG_ASSERT(expr) do { } while (0) +#define PJDLOG_RASSERT(...) do { } while (0) +#else +#define PJDLOG_ASSERT(expr) PJDLOG_VERIFY(expr) +#define PJDLOG_RASSERT(...) PJDLOG_RVERIFY(__VA_ARGS__) +#endif + +#endif /* !_PJDLOG_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/proto.c b/contrib/openbsm/bin/auditdistd/proto.c new file mode 100644 index 0000000..4e9bea0 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto.c @@ -0,0 +1,527 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> + +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> + +#include "pjdlog.h" +#include "proto.h" +#include "proto_impl.h" + +#define PROTO_CONN_MAGIC 0x907041c +struct proto_conn { + int pc_magic; + struct proto *pc_proto; + void *pc_ctx; + int pc_side; +#define PROTO_SIDE_CLIENT 0 +#define PROTO_SIDE_SERVER_LISTEN 1 +#define PROTO_SIDE_SERVER_WORK 2 +}; + +static TAILQ_HEAD(, proto) protos = TAILQ_HEAD_INITIALIZER(protos); + +void +proto_register(struct proto *proto, bool isdefault) +{ + static bool seen_default = false; + + if (!isdefault) + TAILQ_INSERT_HEAD(&protos, proto, prt_next); + else { + PJDLOG_ASSERT(!seen_default); + seen_default = true; + TAILQ_INSERT_TAIL(&protos, proto, prt_next); + } +} + +static struct proto_conn * +proto_alloc(struct proto *proto, int side) +{ + struct proto_conn *conn; + + PJDLOG_ASSERT(proto != NULL); + PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || + side == PROTO_SIDE_SERVER_LISTEN || + side == PROTO_SIDE_SERVER_WORK); + + conn = malloc(sizeof(*conn)); + if (conn != NULL) { + conn->pc_proto = proto; + conn->pc_side = side; + conn->pc_magic = PROTO_CONN_MAGIC; + } + return (conn); +} + +static void +proto_free(struct proto_conn *conn) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT || + conn->pc_side == PROTO_SIDE_SERVER_LISTEN || + conn->pc_side == PROTO_SIDE_SERVER_WORK); + PJDLOG_ASSERT(conn->pc_proto != NULL); + + bzero(conn, sizeof(*conn)); + free(conn); +} + +static int +proto_common_setup(const char *srcaddr, const char *dstaddr, int timeout, + int side, struct proto_conn **connp) +{ + struct proto *proto; + struct proto_conn *conn; + void *ctx; + int ret; + + PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || + side == PROTO_SIDE_SERVER_LISTEN); + + TAILQ_FOREACH(proto, &protos, prt_next) { + if (side == PROTO_SIDE_CLIENT) { + if (proto->prt_connect == NULL) { + ret = -1; + } else { + ret = proto->prt_connect(srcaddr, dstaddr, + timeout, &ctx); + } + } else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ { + if (proto->prt_server == NULL) + ret = -1; + else + ret = proto->prt_server(dstaddr, &ctx); + } + /* + * ret == 0 - success + * ret == -1 - dstaddr is not for this protocol + * ret > 0 - right protocol, but an error occured + */ + if (ret >= 0) + break; + } + if (proto == NULL) { + /* Unrecognized address. */ + errno = EINVAL; + return (-1); + } + if (ret > 0) { + /* An error occured. */ + errno = ret; + return (-1); + } + conn = proto_alloc(proto, side); + if (conn == NULL) { + if (proto->prt_close != NULL) + proto->prt_close(ctx); + errno = ENOMEM; + return (-1); + } + conn->pc_ctx = ctx; + *connp = conn; + + return (0); +} + +int +proto_connect(const char *srcaddr, const char *dstaddr, int timeout, + struct proto_conn **connp) +{ + + PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); + PJDLOG_ASSERT(dstaddr != NULL); + PJDLOG_ASSERT(timeout >= -1); + + return (proto_common_setup(srcaddr, dstaddr, timeout, + PROTO_SIDE_CLIENT, connp)); +} + +int +proto_connect_wait(struct proto_conn *conn, int timeout) +{ + int error; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_connect_wait != NULL); + PJDLOG_ASSERT(timeout >= 0); + + error = conn->pc_proto->prt_connect_wait(conn->pc_ctx, timeout); + if (error != 0) { + errno = error; + return (-1); + } + + return (0); +} + +int +proto_server(const char *addr, struct proto_conn **connp) +{ + + PJDLOG_ASSERT(addr != NULL); + + return (proto_common_setup(NULL, addr, -1, PROTO_SIDE_SERVER_LISTEN, + connp)); +} + +int +proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) +{ + struct proto_conn *newconn; + int error; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_accept != NULL); + + newconn = proto_alloc(conn->pc_proto, PROTO_SIDE_SERVER_WORK); + if (newconn == NULL) + return (-1); + + error = conn->pc_proto->prt_accept(conn->pc_ctx, &newconn->pc_ctx); + if (error != 0) { + proto_free(newconn); + errno = error; + return (-1); + } + + *newconnp = newconn; + + return (0); +} + +int +proto_send(const struct proto_conn *conn, const void *data, size_t size) +{ + int error; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); + + error = conn->pc_proto->prt_send(conn->pc_ctx, data, size, -1); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +int +proto_recv(const struct proto_conn *conn, void *data, size_t size) +{ + int error; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); + + error = conn->pc_proto->prt_recv(conn->pc_ctx, data, size, NULL); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +int +proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn) +{ + const char *protoname; + int error, fd; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); + PJDLOG_ASSERT(mconn != NULL); + PJDLOG_ASSERT(mconn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(mconn->pc_proto != NULL); + fd = proto_descriptor(mconn); + PJDLOG_ASSERT(fd >= 0); + protoname = mconn->pc_proto->prt_name; + PJDLOG_ASSERT(protoname != NULL); + + error = conn->pc_proto->prt_send(conn->pc_ctx, + (const unsigned char *)protoname, strlen(protoname) + 1, fd); + proto_close(mconn); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +int +proto_wrap(const char *protoname, bool client, int fd, + struct proto_conn **newconnp) +{ + struct proto *proto; + struct proto_conn *newconn; + int error; + + TAILQ_FOREACH(proto, &protos, prt_next) { + if (strcmp(proto->prt_name, protoname) == 0) + break; + } + if (proto == NULL) { + errno = EINVAL; + return (-1); + } + + newconn = proto_alloc(proto, + client ? PROTO_SIDE_CLIENT : PROTO_SIDE_SERVER_WORK); + if (newconn == NULL) + return (-1); + PJDLOG_ASSERT(newconn->pc_proto->prt_wrap != NULL); + error = newconn->pc_proto->prt_wrap(fd, client, &newconn->pc_ctx); + if (error != 0) { + proto_free(newconn); + errno = error; + return (-1); + } + + *newconnp = newconn; + + return (0); +} + +int +proto_connection_recv(const struct proto_conn *conn, bool client, + struct proto_conn **newconnp) +{ + char protoname[128]; + int error, fd; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); + PJDLOG_ASSERT(newconnp != NULL); + + bzero(protoname, sizeof(protoname)); + + error = conn->pc_proto->prt_recv(conn->pc_ctx, + (unsigned char *)protoname, sizeof(protoname) - 1, &fd); + if (error != 0) { + errno = error; + return (-1); + } + + PJDLOG_ASSERT(fd >= 0); + + return (proto_wrap(protoname, client, fd, newconnp)); +} + +int +proto_descriptor(const struct proto_conn *conn) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_descriptor != NULL); + + return (conn->pc_proto->prt_descriptor(conn->pc_ctx)); +} + +bool +proto_address_match(const struct proto_conn *conn, const char *addr) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_address_match != NULL); + + return (conn->pc_proto->prt_address_match(conn->pc_ctx, addr)); +} + +void +proto_local_address(const struct proto_conn *conn, char *addr, size_t size) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_local_address != NULL); + + conn->pc_proto->prt_local_address(conn->pc_ctx, addr, size); +} + +void +proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_remote_address != NULL); + + conn->pc_proto->prt_remote_address(conn->pc_ctx, addr, size); +} + +int +proto_timeout(const struct proto_conn *conn, int timeout) +{ + struct timeval tv; + int fd; + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + + fd = proto_descriptor(conn); + if (fd < 0) + return (-1); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) + return (-1); + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) + return (-1); + + return (0); +} + +void +proto_close(struct proto_conn *conn) +{ + + PJDLOG_ASSERT(conn != NULL); + PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); + PJDLOG_ASSERT(conn->pc_proto != NULL); + PJDLOG_ASSERT(conn->pc_proto->prt_close != NULL); + + conn->pc_proto->prt_close(conn->pc_ctx); + proto_free(conn); +} + +int +proto_exec(int argc, char *argv[]) +{ + struct proto *proto; + int error; + + if (argc == 0) { + errno = EINVAL; + return (-1); + } + TAILQ_FOREACH(proto, &protos, prt_next) { + if (strcmp(proto->prt_name, argv[0]) == 0) + break; + } + if (proto == NULL) { + errno = EINVAL; + return (-1); + } + if (proto->prt_exec == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + error = proto->prt_exec(argc, argv); + if (error != 0) { + errno = error; + return (-1); + } + /* NOTREACHED */ + return (0); +} + +struct proto_nvpair { + char *pnv_name; + char *pnv_value; + TAILQ_ENTRY(proto_nvpair) pnv_next; +}; + +static TAILQ_HEAD(, proto_nvpair) proto_nvpairs = + TAILQ_HEAD_INITIALIZER(proto_nvpairs); + +int +proto_set(const char *name, const char *value) +{ + struct proto_nvpair *pnv; + + TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { + if (strcmp(pnv->pnv_name, name) == 0) + break; + } + if (pnv != NULL) { + TAILQ_REMOVE(&proto_nvpairs, pnv, pnv_next); + free(pnv->pnv_value); + } else { + pnv = malloc(sizeof(*pnv)); + if (pnv == NULL) + return (-1); + pnv->pnv_name = strdup(name); + if (pnv->pnv_name == NULL) { + free(pnv); + return (-1); + } + } + pnv->pnv_value = strdup(value); + if (pnv->pnv_value == NULL) { + free(pnv->pnv_name); + free(pnv); + return (-1); + } + TAILQ_INSERT_TAIL(&proto_nvpairs, pnv, pnv_next); + return (0); +} + +const char * +proto_get(const char *name) +{ + struct proto_nvpair *pnv; + + TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { + if (strcmp(pnv->pnv_name, name) == 0) + break; + } + if (pnv != NULL) + return (pnv->pnv_value); + return (NULL); +} diff --git a/contrib/openbsm/bin/auditdistd/proto.h b/contrib/openbsm/bin/auditdistd/proto.h new file mode 100644 index 0000000..f26c0ad --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PROTO_H_ +#define _PROTO_H_ + +#include <stdbool.h> /* bool */ +#include <stdlib.h> /* size_t */ + +struct proto_conn; + +int proto_connect(const char *srcaddr, const char *dstaddr, int timeout, + struct proto_conn **connp); +int proto_connect_wait(struct proto_conn *conn, int timeout); +int proto_server(const char *addr, struct proto_conn **connp); +int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp); +int proto_send(const struct proto_conn *conn, const void *data, size_t size); +int proto_recv(const struct proto_conn *conn, void *data, size_t size); +int proto_connection_send(const struct proto_conn *conn, + struct proto_conn *mconn); +int proto_connection_recv(const struct proto_conn *conn, bool client, + struct proto_conn **newconnp); +int proto_descriptor(const struct proto_conn *conn); +bool proto_address_match(const struct proto_conn *conn, const char *addr); +void proto_local_address(const struct proto_conn *conn, char *addr, + size_t size); +void proto_remote_address(const struct proto_conn *conn, char *addr, + size_t size); +int proto_timeout(const struct proto_conn *conn, int timeout); +void proto_close(struct proto_conn *conn); +int proto_exec(int argc, char *argv[]); +int proto_set(const char *name, const char *value); +const char *proto_get(const char *name); + +#endif /* !_PROTO_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/proto_common.c b/contrib/openbsm/bin/auditdistd/proto_common.c new file mode 100644 index 0000000..acd2294 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_common.c @@ -0,0 +1,231 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> + +#include <compat/compat.h> + +#include "pjdlog.h" +#include "proto_impl.h" + +/* Maximum size of packet we want to use when sending data. */ +#ifndef MAX_SEND_SIZE +#define MAX_SEND_SIZE 32768 +#endif + +static bool +blocking_socket(int sock) +{ + int flags; + + flags = fcntl(sock, F_GETFL); + PJDLOG_ASSERT(flags >= 0); + return ((flags & O_NONBLOCK) == 0); +} + +static int +proto_descriptor_send(int sock, int fd) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(fd))]; + struct msghdr msg; + struct cmsghdr *cmsg; + + PJDLOG_ASSERT(sock >= 0); + PJDLOG_ASSERT(fd >= 0); + + bzero(&msg, sizeof(msg)); + bzero(&ctrl, sizeof(ctrl)); + + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + msg.msg_control = ctrl; + msg.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + + if (sendmsg(sock, &msg, 0) == -1) + return (errno); + + return (0); +} + +int +proto_common_send(int sock, const unsigned char *data, size_t size, int fd) +{ + ssize_t done; + size_t sendsize; + int errcount = 0; + + PJDLOG_ASSERT(sock >= 0); + + if (data == NULL) { + /* The caller is just trying to decide about direction. */ + + PJDLOG_ASSERT(size == 0); + + if (shutdown(sock, SHUT_RD) == -1) + return (errno); + return (0); + } + + PJDLOG_ASSERT(data != NULL); + PJDLOG_ASSERT(size > 0); + + do { + sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE; + done = send(sock, data, sendsize, MSG_NOSIGNAL); + if (done == 0) { + return (ENOTCONN); + } else if (done < 0) { + if (errno == EINTR) + continue; + if (errno == ENOBUFS) { + /* + * If there are no buffers we retry. + * After each try we increase delay before the + * next one and we give up after fifteen times. + * This gives 11s of total wait time. + */ + if (errcount == 15) { + pjdlog_warning("Getting ENOBUFS errors for 11s on send(), giving up."); + } else { + if (errcount == 0) + pjdlog_warning("Got ENOBUFS error on send(), retrying for a bit."); + errcount++; + usleep(100000 * errcount); + continue; + } + } + /* + * If this is blocking socket and we got EAGAIN, this + * means the request timed out. Translate errno to + * ETIMEDOUT, to give administrator a hint to + * eventually increase timeout. + */ + if (errno == EAGAIN && blocking_socket(sock)) + errno = ETIMEDOUT; + return (errno); + } + data += done; + size -= done; + } while (size > 0); + if (errcount > 0) { + pjdlog_info("Data sent successfully after %d ENOBUFS error%s.", + errcount, errcount == 1 ? "" : "s"); + } + + if (fd == -1) + return (0); + return (proto_descriptor_send(sock, fd)); +} + +static int +proto_descriptor_recv(int sock, int *fdp) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))]; + struct msghdr msg; + struct cmsghdr *cmsg; + + PJDLOG_ASSERT(sock >= 0); + PJDLOG_ASSERT(fdp != NULL); + + bzero(&msg, sizeof(msg)); + bzero(&ctrl, sizeof(ctrl)); + + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + msg.msg_control = ctrl; + msg.msg_controllen = sizeof(ctrl); + + if (recvmsg(sock, &msg, 0) == -1) + return (errno); + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + return (EINVAL); + } + bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp)); + + return (0); +} + +int +proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp) +{ + ssize_t done; + + PJDLOG_ASSERT(sock >= 0); + + if (data == NULL) { + /* The caller is just trying to decide about direction. */ + + PJDLOG_ASSERT(size == 0); + + if (shutdown(sock, SHUT_WR) == -1) + return (errno); + return (0); + } + + PJDLOG_ASSERT(data != NULL); + PJDLOG_ASSERT(size > 0); + + do { + done = recv(sock, data, size, MSG_WAITALL); + } while (done == -1 && errno == EINTR); + if (done == 0) { + return (ENOTCONN); + } else if (done < 0) { + /* + * If this is blocking socket and we got EAGAIN, this + * means the request timed out. Translate errno to + * ETIMEDOUT, to give administrator a hint to + * eventually increase timeout. + */ + if (errno == EAGAIN && blocking_socket(sock)) + errno = ETIMEDOUT; + return (errno); + } + if (fdp == NULL) + return (0); + return (proto_descriptor_recv(sock, fdp)); +} diff --git a/contrib/openbsm/bin/auditdistd/proto_impl.h b/contrib/openbsm/bin/auditdistd/proto_impl.h new file mode 100644 index 0000000..7915ee9 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_impl.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PROTO_IMPL_H_ +#define _PROTO_IMPL_H_ + +#include <sys/queue.h> + +#include <stdbool.h> /* bool */ +#include <stdlib.h> /* size_t */ + +#define __constructor __attribute__((constructor)) + +struct proto_conn; + +typedef int prt_connect_t(const char *, const char *, int, void **); +typedef int prt_connect_wait_t(void *, int); +typedef int prt_server_t(const char *, void **); +typedef int prt_accept_t(void *, void **); +typedef int prt_wrap_t(int, bool, void **); +typedef int prt_send_t(void *, const unsigned char *, size_t, int); +typedef int prt_recv_t(void *, unsigned char *, size_t, int *); +typedef int prt_descriptor_t(const void *); +typedef bool prt_address_match_t(const void *, const char *); +typedef void prt_local_address_t(const void *, char *, size_t); +typedef void prt_remote_address_t(const void *, char *, size_t); +typedef void prt_close_t(void *); +typedef int prt_exec_t(int, char *[]); + +struct proto { + const char *prt_name; + prt_connect_t *prt_connect; + prt_connect_wait_t *prt_connect_wait; + prt_server_t *prt_server; + prt_accept_t *prt_accept; + prt_wrap_t *prt_wrap; + prt_send_t *prt_send; + prt_recv_t *prt_recv; + prt_descriptor_t *prt_descriptor; + prt_address_match_t *prt_address_match; + prt_local_address_t *prt_local_address; + prt_remote_address_t *prt_remote_address; + prt_close_t *prt_close; + prt_exec_t *prt_exec; + TAILQ_ENTRY(proto) prt_next; +}; + +void proto_register(struct proto *proto, bool isdefault); + +int proto_wrap(const char *protoname, bool client, int fd, + struct proto_conn **newconnp); + +int proto_common_send(int sock, const unsigned char *data, size_t size, int fd); +int proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp); + +#endif /* !_PROTO_IMPL_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/proto_socketpair.c b/contrib/openbsm/bin/auditdistd/proto_socketpair.c new file mode 100644 index 0000000..fc65c76 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_socketpair.c @@ -0,0 +1,264 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "pjdlog.h" +#include "proto_impl.h" + +#define SP_CTX_MAGIC 0x50c3741 +struct sp_ctx { + int sp_magic; + int sp_fd[2]; + int sp_side; +#define SP_SIDE_UNDEF 0 +#define SP_SIDE_CLIENT 1 +#define SP_SIDE_SERVER 2 +}; + +static void sp_close(void *ctx); + +static int +sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) +{ + struct sp_ctx *spctx; + int error; + + PJDLOG_ASSERT(dstaddr != NULL); + PJDLOG_ASSERT(timeout >= -1); + + if (strcmp(dstaddr, "socketpair://") != 0) + return (-1); + + PJDLOG_ASSERT(srcaddr == NULL); + + spctx = malloc(sizeof(*spctx)); + if (spctx == NULL) + return (errno); + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) { + error = errno; + free(spctx); + return (error); + } + + spctx->sp_side = SP_SIDE_UNDEF; + spctx->sp_magic = SP_CTX_MAGIC; + *ctxp = spctx; + + return (0); +} + +static int +sp_wrap(int fd, bool client, void **ctxp) +{ + struct sp_ctx *spctx; + + PJDLOG_ASSERT(fd >= 0); + + spctx = malloc(sizeof(*spctx)); + if (spctx == NULL) + return (errno); + + if (client) { + spctx->sp_side = SP_SIDE_CLIENT; + spctx->sp_fd[0] = fd; + spctx->sp_fd[1] = -1; + } else { + spctx->sp_side = SP_SIDE_SERVER; + spctx->sp_fd[0] = -1; + spctx->sp_fd[1] = fd; + } + spctx->sp_magic = SP_CTX_MAGIC; + *ctxp = spctx; + + return (0); +} + +static int +sp_send(void *ctx, const unsigned char *data, size_t size, int fd) +{ + struct sp_ctx *spctx = ctx; + int sock; + + PJDLOG_ASSERT(spctx != NULL); + PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); + + switch (spctx->sp_side) { + case SP_SIDE_UNDEF: + /* + * If the first operation done by the caller is proto_send(), + * we assume this is the client. + */ + /* FALLTHROUGH */ + spctx->sp_side = SP_SIDE_CLIENT; + /* Close other end. */ + close(spctx->sp_fd[1]); + spctx->sp_fd[1] = -1; + case SP_SIDE_CLIENT: + PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); + sock = spctx->sp_fd[0]; + break; + case SP_SIDE_SERVER: + PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); + sock = spctx->sp_fd[1]; + break; + default: + PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); + } + + /* Someone is just trying to decide about side. */ + if (data == NULL) + return (0); + + return (proto_common_send(sock, data, size, fd)); +} + +static int +sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) +{ + struct sp_ctx *spctx = ctx; + int sock; + + PJDLOG_ASSERT(spctx != NULL); + PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); + + switch (spctx->sp_side) { + case SP_SIDE_UNDEF: + /* + * If the first operation done by the caller is proto_recv(), + * we assume this is the server. + */ + /* FALLTHROUGH */ + spctx->sp_side = SP_SIDE_SERVER; + /* Close other end. */ + close(spctx->sp_fd[0]); + spctx->sp_fd[0] = -1; + case SP_SIDE_SERVER: + PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); + sock = spctx->sp_fd[1]; + break; + case SP_SIDE_CLIENT: + PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); + sock = spctx->sp_fd[0]; + break; + default: + PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); + } + + /* Someone is just trying to decide about side. */ + if (data == NULL) + return (0); + + return (proto_common_recv(sock, data, size, fdp)); +} + +static int +sp_descriptor(const void *ctx) +{ + const struct sp_ctx *spctx = ctx; + + PJDLOG_ASSERT(spctx != NULL); + PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); + PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || + spctx->sp_side == SP_SIDE_SERVER); + + switch (spctx->sp_side) { + case SP_SIDE_CLIENT: + PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); + return (spctx->sp_fd[0]); + case SP_SIDE_SERVER: + PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); + return (spctx->sp_fd[1]); + } + + PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); +} + +static void +sp_close(void *ctx) +{ + struct sp_ctx *spctx = ctx; + + PJDLOG_ASSERT(spctx != NULL); + PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); + + switch (spctx->sp_side) { + case SP_SIDE_UNDEF: + PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); + close(spctx->sp_fd[0]); + spctx->sp_fd[0] = -1; + PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); + close(spctx->sp_fd[1]); + spctx->sp_fd[1] = -1; + break; + case SP_SIDE_CLIENT: + PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); + close(spctx->sp_fd[0]); + spctx->sp_fd[0] = -1; + PJDLOG_ASSERT(spctx->sp_fd[1] == -1); + break; + case SP_SIDE_SERVER: + PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); + close(spctx->sp_fd[1]); + spctx->sp_fd[1] = -1; + PJDLOG_ASSERT(spctx->sp_fd[0] == -1); + break; + default: + PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); + } + + spctx->sp_magic = 0; + free(spctx); +} + +static struct proto sp_proto = { + .prt_name = "socketpair", + .prt_connect = sp_connect, + .prt_wrap = sp_wrap, + .prt_send = sp_send, + .prt_recv = sp_recv, + .prt_descriptor = sp_descriptor, + .prt_close = sp_close +}; + +static __constructor void +sp_ctor(void) +{ + + proto_register(&sp_proto, false); +} diff --git a/contrib/openbsm/bin/auditdistd/proto_tcp.c b/contrib/openbsm/bin/auditdistd/proto_tcp.c new file mode 100644 index 0000000..465221d --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_tcp.c @@ -0,0 +1,721 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#include <sys/socket.h> + +#include <arpa/inet.h> + +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +#include "pjdlog.h" +#include "proto_impl.h" +#include "subr.h" + +#define TCP_CTX_MAGIC 0x7c41c +struct tcp_ctx { + int tc_magic; + struct sockaddr_storage tc_sa; + int tc_fd; + int tc_side; +#define TCP_SIDE_CLIENT 0 +#define TCP_SIDE_SERVER_LISTEN 1 +#define TCP_SIDE_SERVER_WORK 2 + bool tc_wait_called; +}; + +static int tcp_connect_wait(void *ctx, int timeout); +static void tcp_close(void *ctx); + +/* + * Function converts the given string to unsigned number. + */ +static int +numfromstr(const char *str, intmax_t minnum, intmax_t maxnum, intmax_t *nump) +{ + intmax_t digit, num; + + if (str[0] == '\0') + goto invalid; /* Empty string. */ + num = 0; + for (; *str != '\0'; str++) { + if (*str < '0' || *str > '9') + goto invalid; /* Non-digit character. */ + digit = *str - '0'; + if (num > num * 10 + digit) + goto invalid; /* Overflow. */ + num = num * 10 + digit; + if (num > maxnum) + goto invalid; /* Too big. */ + } + if (num < minnum) + goto invalid; /* Too small. */ + *nump = num; + return (0); +invalid: + errno = EINVAL; + return (-1); +} + +static int +tcp_addr(const char *addr, int defport, struct sockaddr_storage *sap) +{ + char iporhost[MAXHOSTNAMELEN], portstr[6]; + struct addrinfo hints; + struct addrinfo *res; + const char *pp; + intmax_t port; + size_t size; + int error; + + if (addr == NULL) + return (-1); + + bzero(&hints, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (strncasecmp(addr, "tcp4://", 7) == 0) { + addr += 7; + hints.ai_family = PF_INET; + } else if (strncasecmp(addr, "tcp6://", 7) == 0) { + addr += 7; + hints.ai_family = PF_INET6; + } else if (strncasecmp(addr, "tcp://", 6) == 0) { + addr += 6; + } else { + /* + * Because TCP is the default assume IP or host is given without + * prefix. + */ + } + + /* + * Extract optional port. + * There are three cases to consider. + * 1. hostname with port, eg. freefall.freebsd.org:8457 + * 2. IPv4 address with port, eg. 192.168.0.101:8457 + * 3. IPv6 address with port, eg. [fe80::1]:8457 + * We discover IPv6 address by checking for two colons and if port is + * given, the address has to start with [. + */ + pp = NULL; + if (strchr(addr, ':') != strrchr(addr, ':')) { + if (addr[0] == '[') + pp = strrchr(addr, ':'); + } else { + pp = strrchr(addr, ':'); + } + if (pp == NULL) { + /* Port not given, use the default. */ + port = defport; + } else { + if (numfromstr(pp + 1, 1, 65535, &port) < 0) + return (errno); + } + (void)snprintf(portstr, sizeof(portstr), "%jd", (intmax_t)port); + /* Extract host name or IP address. */ + if (pp == NULL) { + size = sizeof(iporhost); + if (strlcpy(iporhost, addr, size) >= size) + return (ENAMETOOLONG); + } else if (addr[0] == '[' && pp[-1] == ']') { + size = (size_t)(pp - addr - 2 + 1); + if (size > sizeof(iporhost)) + return (ENAMETOOLONG); + (void)strlcpy(iporhost, addr + 1, size); + } else { + size = (size_t)(pp - addr + 1); + if (size > sizeof(iporhost)) + return (ENAMETOOLONG); + (void)strlcpy(iporhost, addr, size); + } + + error = getaddrinfo(iporhost, portstr, &hints, &res); + if (error != 0) { + pjdlog_debug(1, "getaddrinfo(%s, %s) failed: %s.", iporhost, + portstr, gai_strerror(error)); + return (EINVAL); + } + if (res == NULL) + return (ENOENT); + + memcpy(sap, res->ai_addr, res->ai_addrlen); + + freeaddrinfo(res); + + return (0); +} + +static int +tcp_setup_new(const char *addr, int side, struct tcp_ctx **tctxp) +{ + struct tcp_ctx *tctx; + int error, nodelay; + + PJDLOG_ASSERT(addr != NULL); + PJDLOG_ASSERT(side == TCP_SIDE_CLIENT || + side == TCP_SIDE_SERVER_LISTEN); + PJDLOG_ASSERT(tctxp != NULL); + + tctx = malloc(sizeof(*tctx)); + if (tctx == NULL) + return (errno); + + /* Parse given address. */ + error = tcp_addr(addr, atoi(proto_get("tcp:port")), &tctx->tc_sa); + if (error != 0) { + free(tctx); + return (error); + } + + PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); + + tctx->tc_fd = socket(tctx->tc_sa.ss_family, SOCK_STREAM, 0); + if (tctx->tc_fd == -1) { + error = errno; + free(tctx); + return (error); + } + + PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); + + /* Socket settings. */ + nodelay = 1; + if (setsockopt(tctx->tc_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, + sizeof(nodelay)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to set TCP_NOELAY"); + } + + tctx->tc_wait_called = (side == TCP_SIDE_CLIENT ? false : true); + tctx->tc_side = side; + tctx->tc_magic = TCP_CTX_MAGIC; + *tctxp = tctx; + + return (0); +} + +static socklen_t +sockaddr_len(const struct sockaddr_storage *ss) +{ + +#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN + return (ss->ss_len); +#else + switch (ss->ss_family) { + case AF_INET: + return (sizeof(struct sockaddr_in)); + case AF_INET6: + return (sizeof(struct sockaddr_in6)); + default: + PJDLOG_ABORT("Unexpected family %hhu.", ss->ss_family); + } +#endif +} + +static int +tcp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) +{ + struct tcp_ctx *tctx; + struct sockaddr_storage sa; + int error, flags, ret; + + PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); + PJDLOG_ASSERT(dstaddr != NULL); + PJDLOG_ASSERT(timeout >= -1); + + error = tcp_setup_new(dstaddr, TCP_SIDE_CLIENT, &tctx); + if (error != 0) + return (error); + if (srcaddr != NULL) { + error = tcp_addr(srcaddr, 0, &sa); + if (error != 0) + goto fail; + if (bind(tctx->tc_fd, (struct sockaddr *)&sa, + sockaddr_len(&sa)) == -1) { + error = errno; + goto fail; + } + } + + flags = fcntl(tctx->tc_fd, F_GETFL); + if (flags == -1) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed"); + goto fail; + } + /* + * We make socket non-blocking so we can handle connection timeout + * manually. + */ + flags |= O_NONBLOCK; + if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_SETFL, O_NONBLOCK) failed"); + goto fail; + } + + ret = connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, + sockaddr_len(&tctx->tc_sa)); + if (ret == -1 && errno != EINPROGRESS) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "connect() failed"); + goto fail; + } + + if (timeout >= 0) { + if (ret == -1) { + /* Connection still in progress. Wait for it. */ + error = tcp_connect_wait(tctx, timeout); + if (error != 0) + goto fail; + } else { + /* Connection already complete. */ + flags &= ~O_NONBLOCK; + if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_SETFL, ~O_NONBLOCK) failed"); + goto fail; + } + } + } + + *ctxp = tctx; + return (0); +fail: + tcp_close(tctx); + return (error); +} + +static int +tcp_connect_wait(void *ctx, int timeout) +{ + struct tcp_ctx *tctx = ctx; + struct timeval tv; + fd_set fdset; + socklen_t esize; + int error, flags, ret; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT); + PJDLOG_ASSERT(!tctx->tc_wait_called); + PJDLOG_ASSERT(tctx->tc_fd >= 0); + PJDLOG_ASSERT(timeout >= 0); + + tv.tv_sec = timeout; + tv.tv_usec = 0; +again: + FD_ZERO(&fdset); + FD_SET(tctx->tc_fd, &fdset); + ret = select(tctx->tc_fd + 1, NULL, &fdset, NULL, &tv); + if (ret == 0) { + error = ETIMEDOUT; + goto done; + } else if (ret == -1) { + if (errno == EINTR) + goto again; + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "select() failed"); + goto done; + } + PJDLOG_ASSERT(ret > 0); + PJDLOG_ASSERT(FD_ISSET(tctx->tc_fd, &fdset)); + esize = sizeof(error); + if (getsockopt(tctx->tc_fd, SOL_SOCKET, SO_ERROR, &error, + &esize) == -1) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "getsockopt(SO_ERROR) failed"); + goto done; + } + if (error != 0) { + pjdlog_common(LOG_DEBUG, 1, error, + "getsockopt(SO_ERROR) returned error"); + goto done; + } + error = 0; + tctx->tc_wait_called = true; +done: + flags = fcntl(tctx->tc_fd, F_GETFL); + if (flags == -1) { + if (error == 0) + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed"); + return (error); + } + flags &= ~O_NONBLOCK; + if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { + if (error == 0) + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_SETFL, ~O_NONBLOCK) failed"); + } + return (error); +} + +static int +tcp_server(const char *addr, void **ctxp) +{ + struct tcp_ctx *tctx; + int error, val; + + error = tcp_setup_new(addr, TCP_SIDE_SERVER_LISTEN, &tctx); + if (error != 0) + return (error); + + val = 1; + /* Ignore failure. */ + (void)setsockopt(tctx->tc_fd, SOL_SOCKET, SO_REUSEADDR, &val, + sizeof(val)); + + PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); + + if (bind(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, + sockaddr_len(&tctx->tc_sa)) == -1) { + error = errno; + tcp_close(tctx); + return (error); + } + if (listen(tctx->tc_fd, 8) == -1) { + error = errno; + tcp_close(tctx); + return (error); + } + + *ctxp = tctx; + + return (0); +} + +static int +tcp_accept(void *ctx, void **newctxp) +{ + struct tcp_ctx *tctx = ctx; + struct tcp_ctx *newtctx; + socklen_t fromlen; + int ret; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_SERVER_LISTEN); + PJDLOG_ASSERT(tctx->tc_fd >= 0); + PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); + + newtctx = malloc(sizeof(*newtctx)); + if (newtctx == NULL) + return (errno); + + fromlen = sockaddr_len(&tctx->tc_sa); + newtctx->tc_fd = accept(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, + &fromlen); + if (newtctx->tc_fd < 0) { + ret = errno; + free(newtctx); + return (ret); + } + + newtctx->tc_wait_called = true; + newtctx->tc_side = TCP_SIDE_SERVER_WORK; + newtctx->tc_magic = TCP_CTX_MAGIC; + *newctxp = newtctx; + + return (0); +} + +static int +tcp_wrap(int fd, bool client, void **ctxp) +{ + struct tcp_ctx *tctx; + + PJDLOG_ASSERT(fd >= 0); + PJDLOG_ASSERT(ctxp != NULL); + + tctx = malloc(sizeof(*tctx)); + if (tctx == NULL) + return (errno); + + tctx->tc_fd = fd; + tctx->tc_sa.ss_family = AF_UNSPEC; + tctx->tc_wait_called = (client ? false : true); + tctx->tc_side = (client ? TCP_SIDE_CLIENT : TCP_SIDE_SERVER_WORK); + tctx->tc_magic = TCP_CTX_MAGIC; + *ctxp = tctx; + + return (0); +} + +static int +tcp_send(void *ctx, const unsigned char *data, size_t size, int fd) +{ + struct tcp_ctx *tctx = ctx; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT || + tctx->tc_side == TCP_SIDE_SERVER_WORK); + PJDLOG_ASSERT(tctx->tc_wait_called); + PJDLOG_ASSERT(tctx->tc_fd >= 0); + PJDLOG_ASSERT(fd == -1); + + return (proto_common_send(tctx->tc_fd, data, size, -1)); +} + +static int +tcp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) +{ + struct tcp_ctx *tctx = ctx; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT || + tctx->tc_side == TCP_SIDE_SERVER_WORK); + PJDLOG_ASSERT(tctx->tc_wait_called); + PJDLOG_ASSERT(tctx->tc_fd >= 0); + PJDLOG_ASSERT(fdp == NULL); + + return (proto_common_recv(tctx->tc_fd, data, size, NULL)); +} + +static int +tcp_descriptor(const void *ctx) +{ + const struct tcp_ctx *tctx = ctx; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + + return (tctx->tc_fd); +} + +static bool +tcp_address_match(const void *ctx, const char *addr) +{ + const struct tcp_ctx *tctx = ctx; + struct sockaddr_storage sa1, sa2; + socklen_t salen; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + + if (tcp_addr(addr, atoi(proto_get("tcp:port")), &sa1) != 0) + return (false); + + salen = sizeof(sa2); + if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa2, &salen) < 0) + return (false); + + if (sa1.ss_family != sa2.ss_family) + return (false); + +#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN + if (sa1.ss_len != sa2.ss_len) + return (false); +#endif + + switch (sa1.ss_family) { + case AF_INET: + { + struct sockaddr_in *sin1, *sin2; + + sin1 = (struct sockaddr_in *)&sa1; + sin2 = (struct sockaddr_in *)&sa2; + + return (memcmp(&sin1->sin_addr, &sin2->sin_addr, + sizeof(sin1->sin_addr)) == 0); + } + case AF_INET6: + { + struct sockaddr_in6 *sin1, *sin2; + + sin1 = (struct sockaddr_in6 *)&sa1; + sin2 = (struct sockaddr_in6 *)&sa2; + + return (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, + sizeof(sin1->sin6_addr)) == 0); + } + default: + return (false); + } +} + +#ifndef __FreeBSD__ +static void +sockaddr_to_string(const void *sa, char *buf, size_t size) +{ + const struct sockaddr_storage *ss; + + ss = (const struct sockaddr_storage * const *)sa; + switch (ss->ss_family) { + case AF_INET: + { + char addr[INET_ADDRSTRLEN]; + const struct sockaddr_in *sin; + unsigned int port; + + sin = (const struct sockaddr_in *)ss; + port = ntohs(sin->sin_port); + if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, + sizeof(addr)) == NULL) { + PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", + strerror(errno)); + } + snprintf(buf, size, "%s:%u", addr, port); + break; + } + case AF_INET6: + { + char addr[INET6_ADDRSTRLEN]; + const struct sockaddr_in6 *sin; + unsigned int port; + + sin = (const struct sockaddr_in6 *)ss; + port = ntohs(sin->sin6_port); + if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, + sizeof(addr)) == NULL) { + PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", + strerror(errno)); + } + snprintf(buf, size, "[%s]:%u", addr, port); + break; + } + default: + snprintf(buf, size, "[unsupported family %hhu]", + ss->ss_family); + break; + } +} +#endif /* !__FreeBSD__ */ + +static void +tcp_local_address(const void *ctx, char *addr, size_t size) +{ + const struct tcp_ctx *tctx = ctx; + struct sockaddr_storage sa; + socklen_t salen; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + + salen = sizeof(sa); + if (getsockname(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } +#ifdef __FreeBSD__ + PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size); +#else + strlcpy(addr, "tcp://", size); + if (size > 6) + sockaddr_to_string(&sa, addr + 6, size - 6); +#endif +} + +static void +tcp_remote_address(const void *ctx, char *addr, size_t size) +{ + const struct tcp_ctx *tctx = ctx; + struct sockaddr_storage sa; + socklen_t salen; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + + salen = sizeof(sa); + if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } +#ifdef __FreeBSD__ + PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size); +#else + strlcpy(addr, "tcp://", size); + if (size > 6) + sockaddr_to_string(&sa, addr + 6, size - 6); +#endif +} + +static void +tcp_close(void *ctx) +{ + struct tcp_ctx *tctx = ctx; + + PJDLOG_ASSERT(tctx != NULL); + PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); + + if (tctx->tc_fd >= 0) + close(tctx->tc_fd); + tctx->tc_magic = 0; + free(tctx); +} + +static struct proto tcp_proto = { + .prt_name = "tcp", + .prt_connect = tcp_connect, + .prt_connect_wait = tcp_connect_wait, + .prt_server = tcp_server, + .prt_accept = tcp_accept, + .prt_wrap = tcp_wrap, + .prt_send = tcp_send, + .prt_recv = tcp_recv, + .prt_descriptor = tcp_descriptor, + .prt_address_match = tcp_address_match, + .prt_local_address = tcp_local_address, + .prt_remote_address = tcp_remote_address, + .prt_close = tcp_close +}; + +static __constructor void +tcp_ctor(void) +{ + + proto_register(&tcp_proto, true); +} diff --git a/contrib/openbsm/bin/auditdistd/proto_tls.c b/contrib/openbsm/bin/auditdistd/proto_tls.c new file mode 100644 index 0000000..de89147 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_tls.c @@ -0,0 +1,1074 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#include <sys/socket.h> + +#include <arpa/inet.h> + +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <signal.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <openssl/err.h> +#include <openssl/ssl.h> + +#include <compat/compat.h> +#ifndef HAVE_CLOSEFROM +#include <compat/closefrom.h> +#endif +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +#include "pjdlog.h" +#include "proto_impl.h" +#include "sandbox.h" +#include "subr.h" + +#define TLS_CTX_MAGIC 0x715c7 +struct tls_ctx { + int tls_magic; + struct proto_conn *tls_sock; + struct proto_conn *tls_tcp; + char tls_laddr[256]; + char tls_raddr[256]; + int tls_side; +#define TLS_SIDE_CLIENT 0 +#define TLS_SIDE_SERVER_LISTEN 1 +#define TLS_SIDE_SERVER_WORK 2 + bool tls_wait_called; +}; + +#define TLS_DEFAULT_TIMEOUT 30 + +static int tls_connect_wait(void *ctx, int timeout); +static void tls_close(void *ctx); + +static void +block(int fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed"); + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed"); +} + +static void +nonblock(int fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed"); + flags |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed"); +} + +static int +wait_for_fd(int fd, int timeout) +{ + struct timeval tv; + fd_set fdset; + int error, ret; + + error = 0; + + for (;;) { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + ret = select(fd + 1, NULL, &fdset, NULL, + timeout == -1 ? NULL : &tv); + if (ret == 0) { + error = ETIMEDOUT; + break; + } else if (ret == -1) { + if (errno == EINTR) + continue; + error = errno; + break; + } + PJDLOG_ASSERT(ret > 0); + PJDLOG_ASSERT(FD_ISSET(fd, &fdset)); + break; + } + + return (error); +} + +static void +ssl_log_errors(void) +{ + unsigned long error; + + while ((error = ERR_get_error()) != 0) + pjdlog_error("SSL error: %s", ERR_error_string(error, NULL)); +} + +static int +ssl_check_error(SSL *ssl, int ret) +{ + int error; + + error = SSL_get_error(ssl, ret); + + switch (error) { + case SSL_ERROR_NONE: + return (0); + case SSL_ERROR_WANT_READ: + pjdlog_debug(2, "SSL_ERROR_WANT_READ"); + return (-1); + case SSL_ERROR_WANT_WRITE: + pjdlog_debug(2, "SSL_ERROR_WANT_WRITE"); + return (-1); + case SSL_ERROR_ZERO_RETURN: + pjdlog_exitx(EX_OK, "Connection closed."); + case SSL_ERROR_SYSCALL: + ssl_log_errors(); + pjdlog_exitx(EX_TEMPFAIL, "SSL I/O error."); + case SSL_ERROR_SSL: + ssl_log_errors(); + pjdlog_exitx(EX_TEMPFAIL, "SSL protocol error."); + default: + ssl_log_errors(); + pjdlog_exitx(EX_TEMPFAIL, "Unknown SSL error (%d).", error); + } +} + +static void +tcp_recv_ssl_send(int recvfd, SSL *sendssl) +{ + static unsigned char buf[65536]; + ssize_t tcpdone; + int sendfd, ssldone; + + sendfd = SSL_get_fd(sendssl); + PJDLOG_ASSERT(sendfd >= 0); + pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd); + for (;;) { + tcpdone = recv(recvfd, buf, sizeof(buf), 0); + pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone); + if (tcpdone == 0) { + pjdlog_debug(1, "Connection terminated."); + exit(0); + } else if (tcpdone == -1) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN) + break; + pjdlog_exit(EX_TEMPFAIL, "recv() failed"); + } + for (;;) { + ssldone = SSL_write(sendssl, buf, (int)tcpdone); + pjdlog_debug(2, "%s: send() returned %d", __func__, + ssldone); + if (ssl_check_error(sendssl, ssldone) == -1) { + (void)wait_for_fd(sendfd, -1); + continue; + } + PJDLOG_ASSERT(ssldone == tcpdone); + break; + } + } + pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd); +} + +static void +ssl_recv_tcp_send(SSL *recvssl, int sendfd) +{ + static unsigned char buf[65536]; + unsigned char *ptr; + ssize_t tcpdone; + size_t todo; + int recvfd, ssldone; + + recvfd = SSL_get_fd(recvssl); + PJDLOG_ASSERT(recvfd >= 0); + pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd); + for (;;) { + ssldone = SSL_read(recvssl, buf, sizeof(buf)); + pjdlog_debug(2, "%s: SSL_read() returned %d", __func__, + ssldone); + if (ssl_check_error(recvssl, ssldone) == -1) + break; + todo = (size_t)ssldone; + ptr = buf; + do { + tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL); + pjdlog_debug(2, "%s: send() returned %zd", __func__, + tcpdone); + if (tcpdone == 0) { + pjdlog_debug(1, "Connection terminated."); + exit(0); + } else if (tcpdone == -1) { + if (errno == EINTR || errno == ENOBUFS) + continue; + if (errno == EAGAIN) { + (void)wait_for_fd(sendfd, -1); + continue; + } + pjdlog_exit(EX_TEMPFAIL, "send() failed"); + } + todo -= tcpdone; + ptr += tcpdone; + } while (todo > 0); + } + pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd); +} + +static void +tls_loop(int sockfd, SSL *tcpssl) +{ + fd_set fds; + int maxfd, tcpfd; + + tcpfd = SSL_get_fd(tcpssl); + PJDLOG_ASSERT(tcpfd >= 0); + + for (;;) { + FD_ZERO(&fds); + FD_SET(sockfd, &fds); + FD_SET(tcpfd, &fds); + maxfd = MAX(sockfd, tcpfd); + + PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); + if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) { + if (errno == EINTR) + continue; + pjdlog_exit(EX_TEMPFAIL, "select() failed"); + } + if (FD_ISSET(sockfd, &fds)) + tcp_recv_ssl_send(sockfd, tcpssl); + if (FD_ISSET(tcpfd, &fds)) + ssl_recv_tcp_send(tcpssl, sockfd); + } +} + +static void +tls_certificate_verify(SSL *ssl, const char *fingerprint) +{ + unsigned char md[EVP_MAX_MD_SIZE]; + char mdstr[sizeof("SHA256=") - 1 + EVP_MAX_MD_SIZE * 3]; + char *mdstrp; + unsigned int i, mdsize; + X509 *cert; + + if (fingerprint[0] == '\0') { + pjdlog_debug(1, "No fingerprint verification requested."); + return; + } + + cert = SSL_get_peer_certificate(ssl); + if (cert == NULL) + pjdlog_exitx(EX_TEMPFAIL, "No peer certificate received."); + + if (X509_digest(cert, EVP_sha256(), md, &mdsize) != 1) + pjdlog_exitx(EX_TEMPFAIL, "X509_digest() failed."); + PJDLOG_ASSERT(mdsize <= EVP_MAX_MD_SIZE); + + X509_free(cert); + + (void)strlcpy(mdstr, "SHA256=", sizeof(mdstr)); + mdstrp = mdstr + strlen(mdstr); + for (i = 0; i < mdsize; i++) { + PJDLOG_VERIFY(mdstrp + 3 <= mdstr + sizeof(mdstr)); + (void)sprintf(mdstrp, "%02hhX:", md[i]); + mdstrp += 3; + } + /* Clear last colon. */ + mdstrp[-1] = '\0'; + if (strcasecmp(mdstr, fingerprint) != 0) { + pjdlog_exitx(EX_NOPERM, + "Finger print doesn't match. Received \"%s\", expected \"%s\"", + mdstr, fingerprint); + } +} + +static void +tls_exec_client(const char *user, int startfd, const char *srcaddr, + const char *dstaddr, const char *fingerprint, const char *defport, + int timeout, int debuglevel) +{ + struct proto_conn *tcp; + char *saddr, *daddr; + SSL_CTX *sslctx; + SSL *ssl; + long ret; + int sockfd, tcpfd; + uint8_t connected; + + pjdlog_debug_set(debuglevel); + pjdlog_prefix_set("[TLS sandbox] (client) "); +#ifdef HAVE_SETPROCTITLE + setproctitle("[TLS sandbox] (client) "); +#endif + proto_set("tcp:port", defport); + + sockfd = startfd; + + /* Change tls:// to tcp://. */ + if (srcaddr == NULL) { + saddr = NULL; + } else { + saddr = strdup(srcaddr); + if (saddr == NULL) + pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); + bcopy("tcp://", saddr, 6); + } + daddr = strdup(dstaddr); + if (daddr == NULL) + pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); + bcopy("tcp://", daddr, 6); + + /* Establish TCP connection. */ + if (proto_connect(saddr, daddr, timeout, &tcp) == -1) + exit(EX_TEMPFAIL); + + SSL_load_error_strings(); + SSL_library_init(); + + /* + * TODO: On FreeBSD we could move this below sandbox() once libc and + * libcrypto use sysctl kern.arandom to obtain random data + * instead of /dev/urandom and friends. + */ + sslctx = SSL_CTX_new(TLSv1_client_method()); + if (sslctx == NULL) + pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); + + if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0) + pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client."); + pjdlog_debug(1, "Privileges successfully dropped."); + + SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + /* Load CA certs. */ + /* TODO */ + //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL); + + ssl = SSL_new(sslctx); + if (ssl == NULL) + pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); + + tcpfd = proto_descriptor(tcp); + + block(tcpfd); + + if (SSL_set_fd(ssl, tcpfd) != 1) + pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); + + ret = SSL_connect(ssl); + ssl_check_error(ssl, (int)ret); + + nonblock(sockfd); + nonblock(tcpfd); + + tls_certificate_verify(ssl, fingerprint); + + /* + * The following byte is send to make proto_connect_wait() to work. + */ + connected = 1; + for (;;) { + switch (send(sockfd, &connected, sizeof(connected), 0)) { + case -1: + if (errno == EINTR || errno == ENOBUFS) + continue; + if (errno == EAGAIN) { + (void)wait_for_fd(sockfd, -1); + continue; + } + pjdlog_exit(EX_TEMPFAIL, "send() failed"); + case 0: + pjdlog_debug(1, "Connection terminated."); + exit(0); + case 1: + break; + } + break; + } + + tls_loop(sockfd, ssl); +} + +static void +tls_call_exec_client(struct proto_conn *sock, const char *srcaddr, + const char *dstaddr, int timeout) +{ + char *timeoutstr, *startfdstr, *debugstr; + int startfd; + + /* Declare that we are receiver. */ + proto_recv(sock, NULL, 0); + + if (pjdlog_mode_get() == PJDLOG_MODE_STD) + startfd = 3; + else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */ + startfd = 0; + + if (proto_descriptor(sock) != startfd) { + /* Move socketpair descriptor to descriptor number startfd. */ + if (dup2(proto_descriptor(sock), startfd) == -1) + pjdlog_exit(EX_OSERR, "dup2() failed"); + proto_close(sock); + } else { + /* + * The FD_CLOEXEC is cleared by dup2(2), so when we not + * call it, we have to clear it by hand in case it is set. + */ + if (fcntl(startfd, F_SETFD, 0) == -1) + pjdlog_exit(EX_OSERR, "fcntl() failed"); + } + + closefrom(startfd + 1); + + if (asprintf(&startfdstr, "%d", startfd) == -1) + pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); + if (timeout == -1) + timeout = TLS_DEFAULT_TIMEOUT; + if (asprintf(&timeoutstr, "%d", timeout) == -1) + pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); + if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1) + pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); + + execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls", + proto_get("user"), "client", startfdstr, + srcaddr == NULL ? "" : srcaddr, dstaddr, + proto_get("tls:fingerprint"), proto_get("tcp:port"), timeoutstr, + debugstr, NULL); + pjdlog_exit(EX_SOFTWARE, "execl() failed"); +} + +static int +tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) +{ + struct tls_ctx *tlsctx; + struct proto_conn *sock; + pid_t pid; + int error; + + PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); + PJDLOG_ASSERT(dstaddr != NULL); + PJDLOG_ASSERT(timeout >= -1); + PJDLOG_ASSERT(ctxp != NULL); + + if (strncmp(dstaddr, "tls://", 6) != 0) + return (-1); + if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0) + return (-1); + + if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) + return (errno); + +#if 0 + /* + * We use rfork() with the following flags to disable SIGCHLD + * delivery upon the sandbox process exit. + */ + pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0)); +#else + /* + * We don't use rfork() to be able to log information about sandbox + * process exiting. + */ + pid = fork(); +#endif + switch (pid) { + case -1: + /* Failure. */ + error = errno; + proto_close(sock); + return (error); + case 0: + /* Child. */ + pjdlog_prefix_set("[TLS sandbox] (client) "); +#ifdef HAVE_SETPROCTITLE + setproctitle("[TLS sandbox] (client) "); +#endif + tls_call_exec_client(sock, srcaddr, dstaddr, timeout); + /* NOTREACHED */ + default: + /* Parent. */ + tlsctx = calloc(1, sizeof(*tlsctx)); + if (tlsctx == NULL) { + error = errno; + proto_close(sock); + (void)kill(pid, SIGKILL); + return (error); + } + proto_send(sock, NULL, 0); + tlsctx->tls_sock = sock; + tlsctx->tls_tcp = NULL; + tlsctx->tls_side = TLS_SIDE_CLIENT; + tlsctx->tls_wait_called = false; + tlsctx->tls_magic = TLS_CTX_MAGIC; + if (timeout >= 0) { + error = tls_connect_wait(tlsctx, timeout); + if (error != 0) { + (void)kill(pid, SIGKILL); + tls_close(tlsctx); + return (error); + } + } + *ctxp = tlsctx; + return (0); + } +} + +static int +tls_connect_wait(void *ctx, int timeout) +{ + struct tls_ctx *tlsctx = ctx; + int error, sockfd; + uint8_t connected; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT); + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + PJDLOG_ASSERT(!tlsctx->tls_wait_called); + PJDLOG_ASSERT(timeout >= 0); + + sockfd = proto_descriptor(tlsctx->tls_sock); + error = wait_for_fd(sockfd, timeout); + if (error != 0) + return (error); + + for (;;) { + switch (recv(sockfd, &connected, sizeof(connected), + MSG_WAITALL)) { + case -1: + if (errno == EINTR || errno == ENOBUFS) + continue; + error = errno; + break; + case 0: + pjdlog_debug(1, "Connection terminated."); + error = ENOTCONN; + break; + case 1: + tlsctx->tls_wait_called = true; + break; + } + break; + } + + return (error); +} + +static int +tls_server(const char *lstaddr, void **ctxp) +{ + struct proto_conn *tcp; + struct tls_ctx *tlsctx; + char *laddr; + int error; + + if (strncmp(lstaddr, "tls://", 6) != 0) + return (-1); + + tlsctx = malloc(sizeof(*tlsctx)); + if (tlsctx == NULL) { + pjdlog_warning("Unable to allocate memory."); + return (ENOMEM); + } + + laddr = strdup(lstaddr); + if (laddr == NULL) { + free(tlsctx); + pjdlog_warning("Unable to allocate memory."); + return (ENOMEM); + } + bcopy("tcp://", laddr, 6); + + if (proto_server(laddr, &tcp) == -1) { + error = errno; + free(tlsctx); + free(laddr); + return (error); + } + free(laddr); + + tlsctx->tls_sock = NULL; + tlsctx->tls_tcp = tcp; + tlsctx->tls_side = TLS_SIDE_SERVER_LISTEN; + tlsctx->tls_wait_called = true; + tlsctx->tls_magic = TLS_CTX_MAGIC; + *ctxp = tlsctx; + + return (0); +} + +static void +tls_exec_server(const char *user, int startfd, const char *privkey, + const char *cert, int debuglevel) +{ + SSL_CTX *sslctx; + SSL *ssl; + int sockfd, tcpfd, ret; + + pjdlog_debug_set(debuglevel); + pjdlog_prefix_set("[TLS sandbox] (server) "); +#ifdef HAVE_SETPROCTITLE + setproctitle("[TLS sandbox] (server) "); +#endif + + sockfd = startfd; + tcpfd = startfd + 1; + + SSL_load_error_strings(); + SSL_library_init(); + + sslctx = SSL_CTX_new(TLSv1_server_method()); + if (sslctx == NULL) + pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); + + SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + ssl = SSL_new(sslctx); + if (ssl == NULL) + pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); + + if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) { + ssl_log_errors(); + pjdlog_exitx(EX_CONFIG, + "SSL_use_RSAPrivateKey_file(%s) failed.", privkey); + } + + if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) { + ssl_log_errors(); + pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.", + cert); + } + + if (sandbox(user, true, "proto_tls server") != 0) + pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server."); + pjdlog_debug(1, "Privileges successfully dropped."); + + nonblock(sockfd); + nonblock(tcpfd); + + if (SSL_set_fd(ssl, tcpfd) != 1) + pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); + + ret = SSL_accept(ssl); + ssl_check_error(ssl, ret); + + tls_loop(sockfd, ssl); +} + +static void +tls_call_exec_server(struct proto_conn *sock, struct proto_conn *tcp) +{ + int startfd, sockfd, tcpfd, safefd; + char *startfdstr, *debugstr; + + if (pjdlog_mode_get() == PJDLOG_MODE_STD) + startfd = 3; + else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */ + startfd = 0; + + /* Declare that we are receiver. */ + proto_send(sock, NULL, 0); + + sockfd = proto_descriptor(sock); + tcpfd = proto_descriptor(tcp); + + safefd = MAX(sockfd, tcpfd); + safefd = MAX(safefd, startfd); + safefd++; + + /* Move sockfd and tcpfd to safe numbers first. */ + if (dup2(sockfd, safefd) == -1) + pjdlog_exit(EX_OSERR, "dup2() failed"); + proto_close(sock); + sockfd = safefd; + if (dup2(tcpfd, safefd + 1) == -1) + pjdlog_exit(EX_OSERR, "dup2() failed"); + proto_close(tcp); + tcpfd = safefd + 1; + + /* Move socketpair descriptor to descriptor number startfd. */ + if (dup2(sockfd, startfd) == -1) + pjdlog_exit(EX_OSERR, "dup2() failed"); + (void)close(sockfd); + /* Move tcp descriptor to descriptor number startfd + 1. */ + if (dup2(tcpfd, startfd + 1) == -1) + pjdlog_exit(EX_OSERR, "dup2() failed"); + (void)close(tcpfd); + + closefrom(startfd + 2); + + /* + * Even if FD_CLOEXEC was set on descriptors before dup2(), it should + * have been cleared on dup2(), but better be safe than sorry. + */ + if (fcntl(startfd, F_SETFD, 0) == -1) + pjdlog_exit(EX_OSERR, "fcntl() failed"); + if (fcntl(startfd + 1, F_SETFD, 0) == -1) + pjdlog_exit(EX_OSERR, "fcntl() failed"); + + if (asprintf(&startfdstr, "%d", startfd) == -1) + pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); + if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1) + pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); + + execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls", + proto_get("user"), "server", startfdstr, proto_get("tls:keyfile"), + proto_get("tls:certfile"), debugstr, NULL); + pjdlog_exit(EX_SOFTWARE, "execl() failed"); +} + +static int +tls_accept(void *ctx, void **newctxp) +{ + struct tls_ctx *tlsctx = ctx; + struct tls_ctx *newtlsctx; + struct proto_conn *sock, *tcp; + pid_t pid; + int error; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN); + + if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) + return (errno); + + /* Accept TCP connection. */ + if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) { + error = errno; + proto_close(sock); + return (error); + } + + pid = fork(); + switch (pid) { + case -1: + /* Failure. */ + error = errno; + proto_close(sock); + return (error); + case 0: + /* Child. */ + pjdlog_prefix_set("[TLS sandbox] (server) "); +#ifdef HAVE_SETPROCTITLE + setproctitle("[TLS sandbox] (server) "); +#endif + /* Close listen socket. */ + proto_close(tlsctx->tls_tcp); + tls_call_exec_server(sock, tcp); + /* NOTREACHED */ + PJDLOG_ABORT("Unreachable."); + default: + /* Parent. */ + newtlsctx = calloc(1, sizeof(*tlsctx)); + if (newtlsctx == NULL) { + error = errno; + proto_close(sock); + proto_close(tcp); + (void)kill(pid, SIGKILL); + return (error); + } + proto_local_address(tcp, newtlsctx->tls_laddr, + sizeof(newtlsctx->tls_laddr)); + PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0); + bcopy("tls://", newtlsctx->tls_laddr, 6); + *strrchr(newtlsctx->tls_laddr, ':') = '\0'; + proto_remote_address(tcp, newtlsctx->tls_raddr, + sizeof(newtlsctx->tls_raddr)); + PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0); + bcopy("tls://", newtlsctx->tls_raddr, 6); + *strrchr(newtlsctx->tls_raddr, ':') = '\0'; + proto_close(tcp); + proto_recv(sock, NULL, 0); + newtlsctx->tls_sock = sock; + newtlsctx->tls_tcp = NULL; + newtlsctx->tls_wait_called = true; + newtlsctx->tls_side = TLS_SIDE_SERVER_WORK; + newtlsctx->tls_magic = TLS_CTX_MAGIC; + *newctxp = newtlsctx; + return (0); + } +} + +static int +tls_wrap(int fd, bool client, void **ctxp) +{ + struct tls_ctx *tlsctx; + struct proto_conn *sock; + int error; + + tlsctx = calloc(1, sizeof(*tlsctx)); + if (tlsctx == NULL) + return (errno); + + if (proto_wrap("socketpair", client, fd, &sock) == -1) { + error = errno; + free(tlsctx); + return (error); + } + + tlsctx->tls_sock = sock; + tlsctx->tls_tcp = NULL; + tlsctx->tls_wait_called = (client ? false : true); + tlsctx->tls_side = (client ? TLS_SIDE_CLIENT : TLS_SIDE_SERVER_WORK); + tlsctx->tls_magic = TLS_CTX_MAGIC; + *ctxp = tlsctx; + + return (0); +} + +static int +tls_send(void *ctx, const unsigned char *data, size_t size, int fd) +{ + struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT || + tlsctx->tls_side == TLS_SIDE_SERVER_WORK); + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + PJDLOG_ASSERT(tlsctx->tls_wait_called); + PJDLOG_ASSERT(fd == -1); + + if (proto_send(tlsctx->tls_sock, data, size) == -1) + return (errno); + + return (0); +} + +static int +tls_recv(void *ctx, unsigned char *data, size_t size, int *fdp) +{ + struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT || + tlsctx->tls_side == TLS_SIDE_SERVER_WORK); + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + PJDLOG_ASSERT(tlsctx->tls_wait_called); + PJDLOG_ASSERT(fdp == NULL); + + if (proto_recv(tlsctx->tls_sock, data, size) == -1) + return (errno); + + return (0); +} + +static int +tls_descriptor(const void *ctx) +{ + const struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + + switch (tlsctx->tls_side) { + case TLS_SIDE_CLIENT: + case TLS_SIDE_SERVER_WORK: + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + + return (proto_descriptor(tlsctx->tls_sock)); + case TLS_SIDE_SERVER_LISTEN: + PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); + + return (proto_descriptor(tlsctx->tls_tcp)); + default: + PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); + } +} + +static bool +tcp_address_match(const void *ctx, const char *addr) +{ + const struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + + return (strcmp(tlsctx->tls_raddr, addr) == 0); +} + +static void +tls_local_address(const void *ctx, char *addr, size_t size) +{ + const struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_wait_called); + + switch (tlsctx->tls_side) { + case TLS_SIDE_CLIENT: + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + + PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size); + break; + case TLS_SIDE_SERVER_WORK: + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + + PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_laddr, size) < size); + break; + case TLS_SIDE_SERVER_LISTEN: + PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); + + proto_local_address(tlsctx->tls_tcp, addr, size); + PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0); + /* Replace tcp:// prefix with tls:// */ + bcopy("tls://", addr, 6); + break; + default: + PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); + } +} + +static void +tls_remote_address(const void *ctx, char *addr, size_t size) +{ + const struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + PJDLOG_ASSERT(tlsctx->tls_wait_called); + + switch (tlsctx->tls_side) { + case TLS_SIDE_CLIENT: + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + + PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size); + break; + case TLS_SIDE_SERVER_WORK: + PJDLOG_ASSERT(tlsctx->tls_sock != NULL); + + PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size); + break; + case TLS_SIDE_SERVER_LISTEN: + PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); + + proto_remote_address(tlsctx->tls_tcp, addr, size); + PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0); + /* Replace tcp:// prefix with tls:// */ + bcopy("tls://", addr, 6); + break; + default: + PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); + } +} + +static void +tls_close(void *ctx) +{ + struct tls_ctx *tlsctx = ctx; + + PJDLOG_ASSERT(tlsctx != NULL); + PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); + + if (tlsctx->tls_sock != NULL) { + proto_close(tlsctx->tls_sock); + tlsctx->tls_sock = NULL; + } + if (tlsctx->tls_tcp != NULL) { + proto_close(tlsctx->tls_tcp); + tlsctx->tls_tcp = NULL; + } + tlsctx->tls_side = 0; + tlsctx->tls_magic = 0; + free(tlsctx); +} + +static int +tls_exec(int argc, char *argv[]) +{ + + PJDLOG_ASSERT(argc > 3); + PJDLOG_ASSERT(strcmp(argv[0], "tls") == 0); + + pjdlog_init(atoi(argv[3]) == 0 ? PJDLOG_MODE_SYSLOG : PJDLOG_MODE_STD); + + if (strcmp(argv[2], "client") == 0) { + if (argc != 10) + return (EINVAL); + tls_exec_client(argv[1], atoi(argv[3]), + argv[4][0] == '\0' ? NULL : argv[4], argv[5], argv[6], + argv[7], atoi(argv[8]), atoi(argv[9])); + } else if (strcmp(argv[2], "server") == 0) { + if (argc != 7) + return (EINVAL); + tls_exec_server(argv[1], atoi(argv[3]), argv[4], argv[5], + atoi(argv[6])); + } + return (EINVAL); +} + +static struct proto tls_proto = { + .prt_name = "tls", + .prt_connect = tls_connect, + .prt_connect_wait = tls_connect_wait, + .prt_server = tls_server, + .prt_accept = tls_accept, + .prt_wrap = tls_wrap, + .prt_send = tls_send, + .prt_recv = tls_recv, + .prt_descriptor = tls_descriptor, + .prt_address_match = tcp_address_match, + .prt_local_address = tls_local_address, + .prt_remote_address = tls_remote_address, + .prt_close = tls_close, + .prt_exec = tls_exec +}; + +static __constructor void +tls_ctor(void) +{ + + proto_register(&tls_proto, false); +} diff --git a/contrib/openbsm/bin/auditdistd/proto_uds.c b/contrib/openbsm/bin/auditdistd/proto_uds.c new file mode 100644 index 0000000..3168bbf --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/proto_uds.c @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* UDS - UNIX Domain Socket */ + +#include <config/config.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +#include "pjdlog.h" +#include "proto_impl.h" + +#define UDS_CTX_MAGIC 0xd541c +struct uds_ctx { + int uc_magic; + struct sockaddr_un uc_sun; + int uc_fd; + int uc_side; +#define UDS_SIDE_CLIENT 0 +#define UDS_SIDE_SERVER_LISTEN 1 +#define UDS_SIDE_SERVER_WORK 2 + pid_t uc_owner; +}; + +static void uds_close(void *ctx); + +static int +uds_addr(const char *addr, struct sockaddr_un *sunp) +{ + + if (addr == NULL) + return (-1); + + if (strncasecmp(addr, "uds://", 6) == 0) + addr += 6; + else if (strncasecmp(addr, "unix://", 7) == 0) + addr += 7; + else if (addr[0] == '/' && /* If it starts from /... */ + strstr(addr, "://") == NULL)/* ...and there is no prefix... */ + ; /* ...we assume its us. */ + else + return (-1); + + sunp->sun_family = AF_UNIX; + if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >= + sizeof(sunp->sun_path)) { + return (ENAMETOOLONG); + } +#ifdef HAVE_SOCKADDR_STORAGE_SS_LEN + sunp->sun_len = SUN_LEN(sunp); +#endif + + return (0); +} + +static int +uds_common_setup(const char *addr, int side, struct uds_ctx **uctxp) +{ + struct uds_ctx *uctx; + int error; + + uctx = malloc(sizeof(*uctx)); + if (uctx == NULL) + return (errno); + + /* Parse given address. */ + error = uds_addr(addr, &uctx->uc_sun); + if (error != 0) { + free(uctx); + return (error); + } + + uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (uctx->uc_fd == -1) { + error = errno; + free(uctx); + return (error); + } + + uctx->uc_side = side; + uctx->uc_owner = 0; + uctx->uc_magic = UDS_CTX_MAGIC; + *uctxp = uctx; + + return (0); +} + +static int +uds_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) +{ + struct uds_ctx *uctx; + int error; + + PJDLOG_ASSERT(dstaddr != NULL); + PJDLOG_ASSERT(timeout >= -1); + + error = uds_common_setup(dstaddr, UDS_SIDE_CLIENT, &uctx); + if (error != 0) + return (error); + + PJDLOG_ASSERT(srcaddr == NULL); + + if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun, + sizeof(uctx->uc_sun)) == -1) { + error = errno; + uds_close(uctx); + return (error); + } + + *ctxp = uctx; + + return (0); +} + +static int +uds_connect_wait(void *ctx, int timeout) +{ + struct uds_ctx *uctx = ctx; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT); + PJDLOG_ASSERT(uctx->uc_fd >= 0); + PJDLOG_ASSERT(timeout >= 0); + + return (0); +} + +static int +uds_server(const char *addr, void **ctxp) +{ + struct uds_ctx *uctx; + int error; + + error = uds_common_setup(addr, UDS_SIDE_SERVER_LISTEN, &uctx); + if (error != 0) + return (error); + + (void)unlink(uctx->uc_sun.sun_path); + if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun, + sizeof(uctx->uc_sun)) == -1) { + error = errno; + uds_close(uctx); + return (error); + } + uctx->uc_owner = getpid(); + if (listen(uctx->uc_fd, 8) == -1) { + error = errno; + uds_close(uctx); + return (error); + } + + *ctxp = uctx; + + return (0); +} + +static int +uds_accept(void *ctx, void **newctxp) +{ + struct uds_ctx *uctx = ctx; + struct uds_ctx *newuctx; + socklen_t fromlen; + int error; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN); + PJDLOG_ASSERT(uctx->uc_fd >= 0); + + newuctx = malloc(sizeof(*newuctx)); + if (newuctx == NULL) + return (errno); + + fromlen = sizeof(newuctx->uc_sun); + newuctx->uc_fd = accept(uctx->uc_fd, + (struct sockaddr *)&newuctx->uc_sun, &fromlen); + if (newuctx->uc_fd < 0) { + error = errno; + free(newuctx); + return (error); + } + + newuctx->uc_side = UDS_SIDE_SERVER_WORK; + newuctx->uc_magic = UDS_CTX_MAGIC; + *newctxp = newuctx; + + return (0); +} + +static int +uds_send(void *ctx, const unsigned char *data, size_t size, int fd) +{ + struct uds_ctx *uctx = ctx; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(uctx->uc_fd >= 0); + + return (proto_common_send(uctx->uc_fd, data, size, fd)); +} + +static int +uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp) +{ + struct uds_ctx *uctx = ctx; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(uctx->uc_fd >= 0); + + return (proto_common_recv(uctx->uc_fd, data, size, fdp)); +} + +static int +uds_descriptor(const void *ctx) +{ + const struct uds_ctx *uctx = ctx; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + + return (uctx->uc_fd); +} + +static void +uds_local_address(const void *ctx, char *addr, size_t size) +{ + const struct uds_ctx *uctx = ctx; + struct sockaddr_un sun; + socklen_t sunlen; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(addr != NULL); + + sunlen = sizeof(sun); + if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } + PJDLOG_ASSERT(sun.sun_family == AF_UNIX); + if (sun.sun_path[0] == '\0') { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } + PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size); +} + +static void +uds_remote_address(const void *ctx, char *addr, size_t size) +{ + const struct uds_ctx *uctx = ctx; + struct sockaddr_un sun; + socklen_t sunlen; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + PJDLOG_ASSERT(addr != NULL); + + sunlen = sizeof(sun); + if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } + PJDLOG_ASSERT(sun.sun_family == AF_UNIX); + if (sun.sun_path[0] == '\0') { + PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); + return; + } + snprintf(addr, size, "uds://%s", sun.sun_path); +} + +static void +uds_close(void *ctx) +{ + struct uds_ctx *uctx = ctx; + + PJDLOG_ASSERT(uctx != NULL); + PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); + + if (uctx->uc_fd >= 0) + close(uctx->uc_fd); + /* + * Unlink the socket only if we are the owner and this is descriptor + * we listen on. + */ + if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN && + uctx->uc_owner == getpid()) { + PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0'); + if (unlink(uctx->uc_sun.sun_path) == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to unlink socket file %s", + uctx->uc_sun.sun_path); + } + } + uctx->uc_owner = 0; + uctx->uc_magic = 0; + free(uctx); +} + +static struct proto uds_proto = { + .prt_name = "uds", + .prt_connect = uds_connect, + .prt_connect_wait = uds_connect_wait, + .prt_server = uds_server, + .prt_accept = uds_accept, + .prt_send = uds_send, + .prt_recv = uds_recv, + .prt_descriptor = uds_descriptor, + .prt_local_address = uds_local_address, + .prt_remote_address = uds_remote_address, + .prt_close = uds_close +}; + +static __constructor void +uds_ctor(void) +{ + + proto_register(&uds_proto, false); +} diff --git a/contrib/openbsm/bin/auditdistd/receiver.c b/contrib/openbsm/bin/auditdistd/receiver.c new file mode 100644 index 0000000..9dc3b018 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/receiver.c @@ -0,0 +1,712 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> +#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) +#include <sys/endian.h> +#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#ifdef HAVE_MACHINE_ENDIAN_H +#include <machine/endian.h> +#else /* !HAVE_MACHINE_ENDIAN_H */ +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#else /* !HAVE_ENDIAN_H */ +#error "No supported endian.h" +#endif /* !HAVE_ENDIAN_H */ +#endif /* !HAVE_MACHINE_ENDIAN_H */ +#include <compat/endian.h> +#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#include <sys/queue.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> + +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif +#ifndef HAVE_FSTATAT +#include "fstatat.h" +#endif +#ifndef HAVE_OPENAT +#include "openat.h" +#endif +#ifndef HAVE_RENAMEAT +#include "renameat.h" +#endif + +#include "auditdistd.h" +#include "pjdlog.h" +#include "proto.h" +#include "sandbox.h" +#include "subr.h" +#include "synch.h" +#include "trail.h" + +static struct adist_config *adcfg; +static struct adist_host *adhost; + +static TAILQ_HEAD(, adreq) adist_free_list; +static pthread_mutex_t adist_free_list_lock; +static pthread_cond_t adist_free_list_cond; +static TAILQ_HEAD(, adreq) adist_disk_list; +static pthread_mutex_t adist_disk_list_lock; +static pthread_cond_t adist_disk_list_cond; +static TAILQ_HEAD(, adreq) adist_send_list; +static pthread_mutex_t adist_send_list_lock; +static pthread_cond_t adist_send_list_cond; + +static void +adreq_clear(struct adreq *adreq) +{ + + adreq->adr_error = -1; + adreq->adr_byteorder = ADIST_BYTEORDER_UNDEFINED; + adreq->adr_cmd = ADIST_CMD_UNDEFINED; + adreq->adr_seq = 0; + adreq->adr_datasize = 0; +} + +static void +init_environment(void) +{ + struct adreq *adreq; + unsigned int ii; + + TAILQ_INIT(&adist_free_list); + mtx_init(&adist_free_list_lock); + cv_init(&adist_free_list_cond); + TAILQ_INIT(&adist_disk_list); + mtx_init(&adist_disk_list_lock); + cv_init(&adist_disk_list_cond); + TAILQ_INIT(&adist_send_list); + mtx_init(&adist_send_list_lock); + cv_init(&adist_send_list_cond); + + for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) { + adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE); + if (adreq == NULL) { + pjdlog_exitx(EX_TEMPFAIL, + "Unable to allocate %zu bytes of memory for adreq object.", + sizeof(*adreq) + ADIST_BUF_SIZE); + } + adreq_clear(adreq); + TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); + } +} + +static void +adreq_decode_and_validate_header(struct adreq *adreq) +{ + + /* Byte-swap only is the sender is using different byte order. */ + if (adreq->adr_byteorder != ADIST_BYTEORDER) { + adreq->adr_byteorder = ADIST_BYTEORDER; + adreq->adr_seq = bswap64(adreq->adr_seq); + adreq->adr_datasize = bswap32(adreq->adr_datasize); + } + + /* Validate packet header. */ + + if (adreq->adr_datasize > ADIST_BUF_SIZE) { + pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).", + (uintmax_t)adreq->adr_datasize); + } + + switch (adreq->adr_cmd) { + case ADIST_CMD_OPEN: + case ADIST_CMD_APPEND: + case ADIST_CMD_CLOSE: + if (adreq->adr_datasize == 0) { + pjdlog_exitx(EX_PROTOCOL, + "Invalid datasize received (%ju).", + (uintmax_t)adreq->adr_datasize); + } + break; + case ADIST_CMD_KEEPALIVE: + case ADIST_CMD_ERROR: + if (adreq->adr_datasize > 0) { + pjdlog_exitx(EX_PROTOCOL, + "Invalid datasize received (%ju).", + (uintmax_t)adreq->adr_datasize); + } + break; + default: + pjdlog_exitx(EX_PROTOCOL, "Invalid command received (%hhu).", + adreq->adr_cmd); + } +} + +static void +adreq_validate_data(const struct adreq *adreq) +{ + + /* Validate packet data. */ + + switch (adreq->adr_cmd) { + case ADIST_CMD_OPEN: + case ADIST_CMD_CLOSE: + /* + * File name must end up with '\0' and there must be no '\0' + * in the middle. + */ + if (adreq->adr_data[adreq->adr_datasize - 1] != '\0' || + strchr(adreq->adr_data, '\0') != + (const char *)adreq->adr_data + adreq->adr_datasize - 1) { + pjdlog_exitx(EX_PROTOCOL, + "Invalid file name received."); + } + break; + } +} + +/* + * Thread receives requests from the sender. + */ +static void * +recv_thread(void *arg __unused) +{ + struct adreq *adreq; + + for (;;) { + pjdlog_debug(3, "recv: Taking free request."); + QUEUE_TAKE(adreq, &adist_free_list, 0); + pjdlog_debug(3, "recv: (%p) Got request.", adreq); + + if (proto_recv(adhost->adh_remote, &adreq->adr_packet, + sizeof(adreq->adr_packet)) == -1) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to receive request header"); + } + adreq_decode_and_validate_header(adreq); + + switch (adreq->adr_cmd) { + case ADIST_CMD_KEEPALIVE: + adreq->adr_error = 0; + adreq_log(LOG_DEBUG, 2, -1, adreq, + "recv: (%p) Got request header: ", adreq); + pjdlog_debug(3, + "recv: (%p) Moving request to the send queue.", + adreq); + QUEUE_INSERT(adreq, &adist_send_list); + continue; + case ADIST_CMD_ERROR: + pjdlog_error("An error occured on the sender while reading \"%s/%s\".", + adhost->adh_directory, adhost->adh_trail_name); + adreq_log(LOG_DEBUG, 2, ADIST_ERROR_READ, adreq, + "recv: (%p) Got request header: ", adreq); + pjdlog_debug(3, + "recv: (%p) Moving request to the send queue.", + adreq); + QUEUE_INSERT(adreq, &adist_disk_list); + continue; + case ADIST_CMD_OPEN: + case ADIST_CMD_APPEND: + case ADIST_CMD_CLOSE: + if (proto_recv(adhost->adh_remote, adreq->adr_data, + adreq->adr_datasize) == -1) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to receive request data"); + } + adreq_validate_data(adreq); + adreq_log(LOG_DEBUG, 2, -1, adreq, + "recv: (%p) Got request header: ", adreq); + pjdlog_debug(3, + "recv: (%p) Moving request to the disk queue.", + adreq); + QUEUE_INSERT(adreq, &adist_disk_list); + break; + default: + PJDLOG_ABORT("Invalid condition."); + } + } + /* NOTREACHED */ + return (NULL); +} + +/* + * Function that opens trail file requested by the sender. + * If the file already exist, it has to be the most recent file and it can + * only be open for append. + * If the file doesn't already exist, it has to be "older" than all existing + * files. + */ +static int +receiver_open(const char *filename) +{ + int fd; + + /* + * Previous file should be closed by now. Sending OPEN request without + * sending CLOSE for the previous file is a sender bug. + */ + if (adhost->adh_trail_fd != -1) { + pjdlog_error("Sender requested opening file \"%s\" without first closing \"%s\".", + filename, adhost->adh_trail_name); + return (ADIST_ERROR_WRONG_ORDER); + } + + if (!trail_validate_name(filename, NULL)) { + pjdlog_error("Sender wants to open file \"%s\", which has invalid name.", + filename); + return (ADIST_ERROR_INVALID_NAME); + } + + switch (trail_name_compare(filename, adhost->adh_trail_name)) { + case TRAIL_RENAMED: + if (!trail_is_not_terminated(adhost->adh_trail_name)) { + pjdlog_error("Terminated trail \"%s/%s\" was unterminated on the sender as \"%s/%s\"?", + adhost->adh_directory, adhost->adh_trail_name, + adhost->adh_directory, filename); + return (ADIST_ERROR_INVALID_NAME); + } + if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, + adhost->adh_trail_dirfd, filename) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to rename file \"%s/%s\" to \"%s/%s\"", + adhost->adh_directory, adhost->adh_trail_name, + adhost->adh_directory, filename); + PJDLOG_ASSERT(errno > 0); + return (ADIST_ERROR_RENAME); + } + pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", + adhost->adh_directory, adhost->adh_trail_name, + adhost->adh_directory, filename); + /* FALLTHROUGH */ + case TRAIL_IDENTICAL: + /* Opening existing file. */ + fd = openat(adhost->adh_trail_dirfd, filename, + O_WRONLY | O_APPEND | O_NOFOLLOW); + if (fd == -1) { + pjdlog_errno(LOG_ERR, + "Unable to open file \"%s/%s\" for append", + adhost->adh_directory, filename); + PJDLOG_ASSERT(errno > 0); + return (ADIST_ERROR_OPEN); + } + pjdlog_debug(1, "Opened file \"%s/%s\".", + adhost->adh_directory, filename); + break; + case TRAIL_NEWER: + /* Opening new file. */ + fd = openat(adhost->adh_trail_dirfd, filename, + O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); + if (fd == -1) { + pjdlog_errno(LOG_ERR, + "Unable to create file \"%s/%s\"", + adhost->adh_directory, filename); + PJDLOG_ASSERT(errno > 0); + return (ADIST_ERROR_CREATE); + } + pjdlog_debug(1, "Created file \"%s/%s\".", + adhost->adh_directory, filename); + break; + case TRAIL_OLDER: + /* Trying to open old file. */ + pjdlog_error("Sender wants to open an old file \"%s\".", filename); + return (ADIST_ERROR_OPEN_OLD); + default: + PJDLOG_ABORT("Unknown return value from trail_name_compare()."); + } + PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, + sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); + adhost->adh_trail_fd = fd; + return (0); +} + +/* + * Function appends data to the trail file that is currently open. + */ +static int +receiver_append(const unsigned char *data, size_t size) +{ + ssize_t done; + size_t osize; + + /* We should have opened trail file. */ + if (adhost->adh_trail_fd == -1) { + pjdlog_error("Sender requested append without first opening file."); + return (ADIST_ERROR_WRONG_ORDER); + } + + osize = size; + while (size > 0) { + done = write(adhost->adh_trail_fd, data, size); + if (done == -1) { + if (errno == EINTR) + continue; + pjdlog_errno(LOG_ERR, "Write to \"%s/%s\" failed", + adhost->adh_directory, adhost->adh_trail_name); + PJDLOG_ASSERT(errno > 0); + return (ADIST_ERROR_WRITE); + } + pjdlog_debug(3, "Wrote %zd bytes into \"%s/%s\".", done, + adhost->adh_directory, adhost->adh_trail_name); + size -= done; + } + pjdlog_debug(2, "Appended %zu bytes to file \"%s/%s\".", + osize, adhost->adh_directory, adhost->adh_trail_name); + return (0); +} + +static int +receiver_close(const char *filename) +{ + + /* We should have opened trail file. */ + if (adhost->adh_trail_fd == -1) { + pjdlog_error("Sender requested closing file without first opening it."); + return (ADIST_ERROR_WRONG_ORDER); + } + + /* Validate if we can do the rename. */ + if (!trail_validate_name(adhost->adh_trail_name, filename)) { + pjdlog_error("Sender wants to close file \"%s\" using name \"%s\".", + adhost->adh_trail_name, filename); + return (ADIST_ERROR_INVALID_NAME); + } + + PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); + adhost->adh_trail_fd = -1; + + pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, + adhost->adh_trail_name); + + if (strcmp(adhost->adh_trail_name, filename) == 0) { + /* File name didn't change, we are done here. */ + return (0); + } + + if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, + adhost->adh_trail_dirfd, filename) == -1) { + pjdlog_errno(LOG_ERR, "Unable to rename \"%s\" to \"%s\"", + adhost->adh_trail_name, filename); + PJDLOG_ASSERT(errno > 0); + return (ADIST_ERROR_RENAME); + } + pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", + adhost->adh_directory, adhost->adh_trail_name, + adhost->adh_directory, filename); + PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, + sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); + + return (0); +} + +static int +receiver_error(void) +{ + + /* We should have opened trail file. */ + if (adhost->adh_trail_fd == -1) { + pjdlog_error("Sender send read error, but file is not open."); + return (ADIST_ERROR_WRONG_ORDER); + } + + PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); + adhost->adh_trail_fd = -1; + + pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, + adhost->adh_trail_name); + + return (0); +} + +static void * +disk_thread(void *arg __unused) +{ + struct adreq *adreq; + + for (;;) { + pjdlog_debug(3, "disk: Taking request."); + QUEUE_TAKE(adreq, &adist_disk_list, 0); + adreq_log(LOG_DEBUG, 3, -1, adreq, "disk: (%p) Got request: ", + adreq); + /* Handle the actual request. */ + switch (adreq->adr_cmd) { + case ADIST_CMD_OPEN: + adreq->adr_error = receiver_open(adreq->adr_data); + break; + case ADIST_CMD_APPEND: + adreq->adr_error = receiver_append(adreq->adr_data, + adreq->adr_datasize); + break; + case ADIST_CMD_CLOSE: + adreq->adr_error = receiver_close(adreq->adr_data); + break; + case ADIST_CMD_ERROR: + adreq->adr_error = receiver_error(); + break; + default: + PJDLOG_ABORT("Unexpected command (cmd=%hhu).", + adreq->adr_cmd); + } + if (adreq->adr_error != 0) { + adreq_log(LOG_ERR, 0, adreq->adr_error, adreq, + "Request failed: "); + } + pjdlog_debug(3, "disk: (%p) Moving request to the send queue.", + adreq); + QUEUE_INSERT(adreq, &adist_send_list); + } + /* NOTREACHED */ + return (NULL); +} + +/* + * Thread sends requests back to primary node. + */ +static void * +send_thread(void *arg __unused) +{ + struct adreq *adreq; + struct adrep adrep; + + for (;;) { + pjdlog_debug(3, "send: Taking request."); + QUEUE_TAKE(adreq, &adist_send_list, 0); + adreq_log(LOG_DEBUG, 3, -1, adreq, "send: (%p) Got request: ", + adreq); + adrep.adrp_byteorder = ADIST_BYTEORDER; + adrep.adrp_seq = adreq->adr_seq; + adrep.adrp_error = adreq->adr_error; + if (proto_send(adhost->adh_remote, &adrep, + sizeof(adrep)) == -1) { + pjdlog_exit(EX_TEMPFAIL, "Unable to send reply"); + } + pjdlog_debug(3, "send: (%p) Moving request to the free queue.", + adreq); + adreq_clear(adreq); + QUEUE_INSERT(adreq, &adist_free_list); + } + /* NOTREACHED */ + return (NULL); +} + +static void +receiver_directory_create(void) +{ + struct passwd *pw; + + /* + * According to getpwnam(3) we have to clear errno before calling the + * function to be able to distinguish between an error and missing + * entry (with is not treated as error by getpwnam(3)). + */ + errno = 0; + pw = getpwnam(ADIST_USER); + if (pw == NULL) { + if (errno != 0) { + pjdlog_exit(EX_NOUSER, + "Unable to find info about '%s' user", ADIST_USER); + } else { + pjdlog_exitx(EX_NOUSER, "User '%s' doesn't exist.", + ADIST_USER); + } + } + + if (mkdir(adhost->adh_directory, 0700) == -1) { + pjdlog_exit(EX_OSFILE, "Unable to create directory \"%s\"", + adhost->adh_directory); + } + if (chown(adhost->adh_directory, pw->pw_uid, pw->pw_gid) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to change owner of the directory \"%s\"", + adhost->adh_directory); + (void)rmdir(adhost->adh_directory); + exit(EX_OSFILE); + } +} + +static void +receiver_directory_open(void) +{ + +#ifdef HAVE_FDOPENDIR + adhost->adh_trail_dirfd = open(adhost->adh_directory, + O_RDONLY | O_DIRECTORY); + if (adhost->adh_trail_dirfd == -1) { + if (errno == ENOENT) { + receiver_directory_create(); + adhost->adh_trail_dirfd = open(adhost->adh_directory, + O_RDONLY | O_DIRECTORY); + } + if (adhost->adh_trail_dirfd == -1) { + pjdlog_exit(EX_CONFIG, + "Unable to open directory \"%s\"", + adhost->adh_directory); + } + } + adhost->adh_trail_dirfp = fdopendir(adhost->adh_trail_dirfd); + if (adhost->adh_trail_dirfp == NULL) { + pjdlog_exit(EX_CONFIG, "Unable to fdopen directory \"%s\"", + adhost->adh_directory); + } +#else + struct stat sb; + + if (stat(adhost->adh_directory, &sb) == -1) { + if (errno == ENOENT) { + receiver_directory_create(); + } else { + pjdlog_exit(EX_CONFIG, + "Unable to stat directory \"%s\"", + adhost->adh_directory); + } + } + adhost->adh_trail_dirfp = opendir(adhost->adh_directory); + if (adhost->adh_trail_dirfp == NULL) { + pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"", + adhost->adh_directory); + } + adhost->adh_trail_dirfd = dirfd(adhost->adh_trail_dirfp); +#endif +} + +static void +receiver_connect(void) +{ + uint64_t trail_size; + struct stat sb; + + PJDLOG_ASSERT(adhost->adh_trail_dirfp != NULL); + + trail_last(adhost->adh_trail_dirfp, adhost->adh_trail_name, + sizeof(adhost->adh_trail_name)); + + if (adhost->adh_trail_name[0] == '\0') { + trail_size = 0; + } else { + if (fstatat(adhost->adh_trail_dirfd, adhost->adh_trail_name, + &sb, AT_SYMLINK_NOFOLLOW) == -1) { + pjdlog_exit(EX_CONFIG, "Unable to stat \"%s/%s\"", + adhost->adh_directory, adhost->adh_trail_name); + } + if (!S_ISREG(sb.st_mode)) { + pjdlog_exitx(EX_CONFIG, + "File \"%s/%s\" is not a regular file.", + adhost->adh_directory, adhost->adh_trail_name); + } + trail_size = sb.st_size; + } + trail_size = htole64(trail_size); + if (proto_send(adhost->adh_remote, &trail_size, + sizeof(trail_size)) == -1) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to send size of the most recent trail file"); + } + if (proto_send(adhost->adh_remote, adhost->adh_trail_name, + sizeof(adhost->adh_trail_name)) == -1) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to send name of the most recent trail file"); + } +} + +void +adist_receiver(struct adist_config *config, struct adist_host *adh) +{ + sigset_t mask; + pthread_t td; + pid_t pid; + int error, mode, debuglevel; + + pid = fork(); + if (pid == -1) { + pjdlog_errno(LOG_ERR, "Unable to fork"); + proto_close(adh->adh_remote); + adh->adh_remote = NULL; + return; + } + + if (pid > 0) { + /* This is parent. */ + proto_close(adh->adh_remote); + adh->adh_remote = NULL; + adh->adh_worker_pid = pid; + return; + } + + adcfg = config; + adhost = adh; + mode = pjdlog_mode_get(); + debuglevel = pjdlog_debug_get(); + + descriptors_cleanup(adhost); + +// descriptors_assert(adhost, mode); + + pjdlog_init(mode); + pjdlog_debug_set(debuglevel); + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); +#ifdef HAVE_SETPROCTITLE + setproctitle("%s (%s)", adhost->adh_name, role2str(adhost->adh_role)); +#endif + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); + + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(adhost->adh_remote, adcfg->adc_timeout) == -1) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + + init_environment(); + + adhost->adh_trail_fd = -1; + receiver_directory_open(); + + if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", + role2str(adhost->adh_role), adhost->adh_name) != 0) { + exit(EX_CONFIG); + } + pjdlog_info("Privileges successfully dropped."); + + receiver_connect(); + + error = pthread_create(&td, NULL, recv_thread, adhost); + PJDLOG_ASSERT(error == 0); + error = pthread_create(&td, NULL, disk_thread, adhost); + PJDLOG_ASSERT(error == 0); + (void)send_thread(adhost); +} diff --git a/contrib/openbsm/bin/auditdistd/renameat.h b/contrib/openbsm/bin/auditdistd/renameat.h new file mode 100644 index 0000000..0becb8a --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/renameat.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RENAMEAT_H_ +#define _RENAMEAT_H_ + +#include <stdio.h> +#include <unistd.h> + +static int +renameat(int fromfd, const char *from, int tofd, const char *to) +{ + int cfd, error, ret; + + if (fromfd != tofd) { + errno = EINVAL; + return (-1); + } + + cfd = open(".", O_RDONLY | O_DIRECTORY); + if (cfd == -1) + return (-1); + + if (fchdir(fromfd) == -1) { + error = errno; + (void)close(cfd); + errno = error; + return (-1); + } + + ret = rename(from, to); + + error = errno; + (void)fchdir(cfd); + (void)close(cfd); + errno = error; + return (ret); +} + +#endif /* !_RENAMEAT_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/sandbox.c b/contrib/openbsm/bin/auditdistd/sandbox.c new file mode 100644 index 0000000..53cd6b3 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/sandbox.c @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> +#ifdef HAVE_JAIL +#include <sys/jail.h> +#endif +#ifdef HAVE_CAP_ENTER +#include <sys/capability.h> +#endif + +#include <errno.h> +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> + +#include "pjdlog.h" +#include "sandbox.h" + +static int +groups_compare(const void *grp0, const void *grp1) +{ + gid_t gr0 = *(const gid_t *)grp0; + gid_t gr1 = *(const gid_t *)grp1; + + return (gr0 <= gr1 ? (gr0 < gr1 ? -1 : 0) : 1); + +} + +int +sandbox(const char *user, bool capsicum, const char *fmt, ...) +{ +#ifdef HAVE_JAIL + struct jail jailst; + char *jailhost; + va_list ap; +#endif + struct passwd *pw; + uid_t ruid, euid; + gid_t rgid, egid; +#ifdef HAVE_GETRESUID + uid_t suid; +#endif +#ifdef HAVE_GETRESGID + gid_t sgid; +#endif + gid_t *groups, *ggroups; + bool jailed; + int ngroups, ret; + + PJDLOG_ASSERT(user != NULL); + PJDLOG_ASSERT(fmt != NULL); + + ret = -1; + groups = NULL; + ggroups = NULL; + + /* + * According to getpwnam(3) we have to clear errno before calling the + * function to be able to distinguish between an error and missing + * entry (with is not treated as error by getpwnam(3)). + */ + errno = 0; + pw = getpwnam(user); + if (pw == NULL) { + if (errno != 0) { + pjdlog_errno(LOG_ERR, + "Unable to find info about '%s' user", user); + goto out; + } else { + pjdlog_error("'%s' user doesn't exist.", user); + errno = ENOENT; + goto out; + } + } + + ngroups = sysconf(_SC_NGROUPS_MAX); + if (ngroups == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to obtain maximum number of groups"); + ngroups = NGROUPS_MAX; + } + ngroups++; /* For base gid. */ + groups = malloc(sizeof(groups[0]) * ngroups); + if (groups == NULL) { + pjdlog_error("Unable to allocate memory for %d groups.", + ngroups); + goto out; + } + if (getgrouplist(user, pw->pw_gid, groups, &ngroups) == -1) { + pjdlog_error("Unable to obtain groups of user %s.", user); + goto out; + } + +#ifdef HAVE_JAIL + va_start(ap, fmt); + (void)vasprintf(&jailhost, fmt, ap); + va_end(ap); + if (jailhost == NULL) { + pjdlog_error("Unable to allocate memory for jail host name."); + goto out; + } + bzero(&jailst, sizeof(jailst)); + jailst.version = JAIL_API_VERSION; + jailst.path = pw->pw_dir; + jailst.hostname = jailhost; + if (jail(&jailst) >= 0) { + jailed = true; + } else { + jailed = false; + pjdlog_errno(LOG_WARNING, + "Unable to jail to directory %s", pw->pw_dir); + } + free(jailhost); +#else /* !HAVE_JAIL */ + jailed = false; +#endif /* !HAVE_JAIL */ + + if (!jailed) { + if (chroot(pw->pw_dir) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to change root directory to %s", + pw->pw_dir); + goto out; + } + } + PJDLOG_VERIFY(chdir("/") == 0); + + if (setgroups(ngroups, groups) == -1) { + pjdlog_errno(LOG_ERR, "Unable to set groups"); + goto out; + } + if (setgid(pw->pw_gid) == -1) { + pjdlog_errno(LOG_ERR, "Unable to set gid to %u", + (unsigned int)pw->pw_gid); + goto out; + } + if (setuid(pw->pw_uid) == -1) { + pjdlog_errno(LOG_ERR, "Unable to set uid to %u", + (unsigned int)pw->pw_uid); + goto out; + } + +#ifdef HAVE_CAP_ENTER + if (capsicum) { + capsicum = (cap_enter() == 0); + if (!capsicum) { + pjdlog_common(LOG_DEBUG, 1, errno, + "Unable to sandbox using capsicum"); + } + } +#else /* !HAVE_CAP_ENTER */ + capsicum = false; +#endif /* !HAVE_CAP_ENTER */ + + /* + * Better be sure that everything succeeded. + */ +#ifdef HAVE_GETRESUID + PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0); + PJDLOG_VERIFY(suid == pw->pw_uid); +#else + ruid = getuid(); + euid = geteuid(); +#endif + PJDLOG_VERIFY(ruid == pw->pw_uid); + PJDLOG_VERIFY(euid == pw->pw_uid); +#ifdef HAVE_GETRESGID + PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0); + PJDLOG_VERIFY(sgid == pw->pw_gid); +#else + rgid = getgid(); + egid = getegid(); +#endif + PJDLOG_VERIFY(rgid == pw->pw_gid); + PJDLOG_VERIFY(egid == pw->pw_gid); + PJDLOG_VERIFY(getgroups(0, NULL) == ngroups); + ggroups = malloc(sizeof(ggroups[0]) * ngroups); + if (ggroups == NULL) { + pjdlog_error("Unable to allocate memory for %d groups.", + ngroups); + goto out; + } + PJDLOG_VERIFY(getgroups(ngroups, ggroups) == ngroups); + qsort(groups, (size_t)ngroups, sizeof(groups[0]), groups_compare); + qsort(ggroups, (size_t)ngroups, sizeof(ggroups[0]), groups_compare); + PJDLOG_VERIFY(bcmp(groups, ggroups, sizeof(groups[0]) * ngroups) == 0); + + pjdlog_debug(1, + "Privileges successfully dropped using %s%s+setgid+setuid.", + capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot"); + + ret = 0; +out: + if (groups != NULL) + free(groups); + if (ggroups != NULL) + free(ggroups); + return (ret); +} diff --git a/contrib/openbsm/bin/auditdistd/sandbox.h b/contrib/openbsm/bin/auditdistd/sandbox.h new file mode 100644 index 0000000..7bcde25 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/sandbox.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SANDBOX_H_ +#define _SANDBOX_H_ + +#include <stdbool.h> + +int sandbox(const char *user, bool capsicum, const char *fmt, ...); + +#endif /* !_SANDBOX_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/sender.c b/contrib/openbsm/bin/auditdistd/sender.c new file mode 100644 index 0000000..4349b0f --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/sender.c @@ -0,0 +1,845 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> +#if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) +#include <sys/endian.h> +#else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#ifdef HAVE_MACHINE_ENDIAN_H +#include <machine/endian.h> +#else /* !HAVE_MACHINE_ENDIAN_H */ +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#else /* !HAVE_ENDIAN_H */ +#error "No supported endian.h" +#endif /* !HAVE_ENDIAN_H */ +#endif /* !HAVE_MACHINE_ENDIAN_H */ +#include <compat/endian.h> +#endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ +#include <sys/queue.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <ctype.h> +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#include <signal.h> +#include <string.h> +#include <strings.h> + +#include <openssl/hmac.h> + +#ifndef HAVE_SIGTIMEDWAIT +#include "sigtimedwait.h" +#endif + +#include "auditdistd.h" +#include "pjdlog.h" +#include "proto.h" +#include "sandbox.h" +#include "subr.h" +#include "synch.h" +#include "trail.h" + +static struct adist_config *adcfg; +static struct adist_host *adhost; + +static pthread_rwlock_t adist_remote_lock; +static pthread_mutex_t adist_remote_mtx; +static pthread_cond_t adist_remote_cond; +static struct trail *adist_trail; + +static TAILQ_HEAD(, adreq) adist_free_list; +static pthread_mutex_t adist_free_list_lock; +static pthread_cond_t adist_free_list_cond; +static TAILQ_HEAD(, adreq) adist_send_list; +static pthread_mutex_t adist_send_list_lock; +static pthread_cond_t adist_send_list_cond; +static TAILQ_HEAD(, adreq) adist_recv_list; +static pthread_mutex_t adist_recv_list_lock; +static pthread_cond_t adist_recv_list_cond; + +static void +init_environment(void) +{ + struct adreq *adreq; + unsigned int ii; + + rw_init(&adist_remote_lock); + mtx_init(&adist_remote_mtx); + cv_init(&adist_remote_cond); + TAILQ_INIT(&adist_free_list); + mtx_init(&adist_free_list_lock); + cv_init(&adist_free_list_cond); + TAILQ_INIT(&adist_send_list); + mtx_init(&adist_send_list_lock); + cv_init(&adist_send_list_cond); + TAILQ_INIT(&adist_recv_list); + mtx_init(&adist_recv_list_lock); + cv_init(&adist_recv_list_cond); + + for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) { + adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE); + if (adreq == NULL) { + pjdlog_exitx(EX_TEMPFAIL, + "Unable to allocate %zu bytes of memory for adreq object.", + sizeof(*adreq) + ADIST_BUF_SIZE); + } + adreq->adr_byteorder = ADIST_BYTEORDER; + adreq->adr_cmd = ADIST_CMD_UNDEFINED; + adreq->adr_seq = 0; + adreq->adr_datasize = 0; + TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); + } +} + +static int +sender_connect(void) +{ + unsigned char rnd[32], hash[32], resp[32]; + struct proto_conn *conn; + char welcome[8]; + int16_t val; + + val = 1; + if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to send connection request to parent"); + } + if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to receive reply to connection request from parent"); + } + if (val != 0) { + errno = val; + pjdlog_errno(LOG_WARNING, "Unable to connect to %s", + adhost->adh_remoteaddr); + return (-1); + } + if (proto_connection_recv(adhost->adh_conn, true, &conn) < 0) { + pjdlog_exit(EX_TEMPFAIL, + "Unable to receive connection from parent"); + } + if (proto_connect_wait(conn, adcfg->adc_timeout) < 0) { + pjdlog_errno(LOG_WARNING, "Unable to connect to %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Connected to %s.", adhost->adh_remoteaddr); + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(conn, adcfg->adc_timeout) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + else + pjdlog_debug(1, "Timeout set to %d.", adcfg->adc_timeout); + + /* Exchange welcome message, which includes version number. */ + (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", ADIST_VERSION); + if (proto_send(conn, welcome, sizeof(welcome)) < 0) { + pjdlog_errno(LOG_WARNING, + "Unable to send welcome message to %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Welcome message sent (%s).", welcome); + bzero(welcome, sizeof(welcome)); + if (proto_recv(conn, welcome, sizeof(welcome)) < 0) { + pjdlog_errno(LOG_WARNING, + "Unable to receive welcome message from %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) || + !isdigit(welcome[6]) || welcome[7] != '\0') { + pjdlog_warning("Invalid welcome message from %s.", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Welcome message received (%s).", welcome); + /* + * Receiver can only reply with version number lower or equal to + * the one we sent. + */ + adhost->adh_version = atoi(welcome + 5); + if (adhost->adh_version > ADIST_VERSION) { + pjdlog_warning("Invalid version number from %s (%d received, up to %d supported).", + adhost->adh_remoteaddr, adhost->adh_version, ADIST_VERSION); + proto_close(conn); + return (-1); + } + + pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version, + adhost->adh_remoteaddr); + + if (proto_send(conn, adcfg->adc_name, sizeof(adcfg->adc_name)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to send name to %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Name (%s) sent.", adcfg->adc_name); + + if (proto_recv(conn, rnd, sizeof(rnd)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to receive challenge from %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Challenge received."); + + if (HMAC(EVP_sha256(), adhost->adh_password, + (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, + NULL) == NULL) { + pjdlog_warning("Unable to generate response."); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Response generated."); + + if (proto_send(conn, hash, sizeof(hash)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to send response to %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Response sent."); + + if (adist_random(rnd, sizeof(rnd)) == -1) { + pjdlog_warning("Unable to generate challenge."); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Challenge generated."); + + if (proto_send(conn, rnd, sizeof(rnd)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to send challenge to %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Challenge sent."); + + if (proto_recv(conn, resp, sizeof(resp)) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to receive response from %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Response received."); + + if (HMAC(EVP_sha256(), adhost->adh_password, + (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, + NULL) == NULL) { + pjdlog_warning("Unable to generate hash."); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Hash generated."); + + if (memcmp(resp, hash, sizeof(hash)) != 0) { + pjdlog_warning("Invalid response from %s (wrong password?).", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_info("Receiver authenticated."); + + if (proto_recv(conn, &adhost->adh_trail_offset, + sizeof(adhost->adh_trail_offset)) == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to receive size of the most recent trail file from %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + adhost->adh_trail_offset = le64toh(adhost->adh_trail_offset); + if (proto_recv(conn, &adhost->adh_trail_name, + sizeof(adhost->adh_trail_name)) == -1) { + pjdlog_errno(LOG_WARNING, + "Unable to receive name of the most recent trail file from %s", + adhost->adh_remoteaddr); + proto_close(conn); + return (-1); + } + pjdlog_debug(1, "Trail name (%s) and offset (%ju) received.", + adhost->adh_trail_name, (uintmax_t)adhost->adh_trail_offset); + + rw_wlock(&adist_remote_lock); + mtx_lock(&adist_remote_mtx); + PJDLOG_ASSERT(adhost->adh_remote == NULL); + PJDLOG_ASSERT(conn != NULL); + adhost->adh_remote = conn; + mtx_unlock(&adist_remote_mtx); + rw_unlock(&adist_remote_lock); + cv_signal(&adist_remote_cond); + + return (0); +} + +static void +sender_disconnect(void) +{ + + rw_wlock(&adist_remote_lock); + /* + * Check for a race between dropping rlock and acquiring wlock - + * another thread can close connection in-between. + */ + if (adhost->adh_remote == NULL) { + rw_unlock(&adist_remote_lock); + return; + } + pjdlog_debug(2, "Closing connection to %s.", adhost->adh_remoteaddr); + proto_close(adhost->adh_remote); + mtx_lock(&adist_remote_mtx); + adhost->adh_remote = NULL; + adhost->adh_reset = true; + adhost->adh_trail_name[0] = '\0'; + adhost->adh_trail_offset = 0; + mtx_unlock(&adist_remote_mtx); + rw_unlock(&adist_remote_lock); + + pjdlog_warning("Disconnected from %s.", adhost->adh_remoteaddr); + + /* Move all in-flight requests back onto free list. */ + mtx_lock(&adist_free_list_lock); + mtx_lock(&adist_send_list_lock); + TAILQ_CONCAT(&adist_free_list, &adist_send_list, adr_next); + mtx_unlock(&adist_send_list_lock); + mtx_lock(&adist_recv_list_lock); + TAILQ_CONCAT(&adist_free_list, &adist_recv_list, adr_next); + mtx_unlock(&adist_recv_list_lock); + mtx_unlock(&adist_free_list_lock); +} + +static void +adreq_fill(struct adreq *adreq, uint8_t cmd, const unsigned char *data, + size_t size) +{ + static uint64_t seq = 1; + + PJDLOG_ASSERT(size <= ADIST_BUF_SIZE); + + switch (cmd) { + case ADIST_CMD_OPEN: + case ADIST_CMD_CLOSE: + PJDLOG_ASSERT(data != NULL && size == 0); + size = strlen(data) + 1; + break; + case ADIST_CMD_APPEND: + PJDLOG_ASSERT(data != NULL && size > 0); + break; + case ADIST_CMD_KEEPALIVE: + case ADIST_CMD_ERROR: + PJDLOG_ASSERT(data == NULL && size == 0); + break; + default: + PJDLOG_ABORT("Invalid command (%hhu).", cmd); + } + + adreq->adr_cmd = cmd; + adreq->adr_seq = seq++; + adreq->adr_datasize = size; + /* Don't copy if data is already in out buffer. */ + if (data != NULL && data != adreq->adr_data) + bcopy(data, adreq->adr_data, size); +} + +static bool +read_thread_wait(void) +{ + bool newfile = false; + + mtx_lock(&adist_remote_mtx); + if (adhost->adh_reset) { +reset: + adhost->adh_reset = false; + if (trail_filefd(adist_trail) != -1) + trail_close(adist_trail); + trail_reset(adist_trail); + while (adhost->adh_remote == NULL) + cv_wait(&adist_remote_cond, &adist_remote_mtx); + trail_start(adist_trail, adhost->adh_trail_name, + adhost->adh_trail_offset); + newfile = true; + } + mtx_unlock(&adist_remote_mtx); + while (trail_filefd(adist_trail) == -1) { + newfile = true; + wait_for_dir(); + /* + * We may have been disconnected and reconnected in the + * meantime, check if reset is set. + */ + mtx_lock(&adist_remote_mtx); + if (adhost->adh_reset) + goto reset; + mtx_unlock(&adist_remote_mtx); + if (trail_filefd(adist_trail) == -1) + trail_next(adist_trail); + } + if (newfile) { + pjdlog_debug(1, "Trail file \"%s/%s\" opened.", + adhost->adh_directory, + trail_filename(adist_trail)); + (void)wait_for_file_init(trail_filefd(adist_trail)); + } + return (newfile); +} + +static void * +read_thread(void *arg __unused) +{ + struct adreq *adreq; + ssize_t done; + bool newfile; + + pjdlog_debug(1, "%s started.", __func__); + + for (;;) { + newfile = read_thread_wait(); + QUEUE_TAKE(adreq, &adist_free_list, 0); + if (newfile) { + adreq_fill(adreq, ADIST_CMD_OPEN, + trail_filename(adist_trail), 0); + newfile = false; + goto move; + } + + done = read(trail_filefd(adist_trail), adreq->adr_data, + ADIST_BUF_SIZE); + if (done == -1) { + off_t offset; + int error; + + error = errno; + offset = lseek(trail_filefd(adist_trail), 0, SEEK_CUR); + errno = error; + pjdlog_errno(LOG_ERR, + "Error while reading \"%s/%s\" at offset %jd", + adhost->adh_directory, trail_filename(adist_trail), + offset); + trail_close(adist_trail); + adreq_fill(adreq, ADIST_CMD_ERROR, NULL, 0); + goto move; + } else if (done == 0) { + /* End of file. */ + pjdlog_debug(3, "End of \"%s/%s\".", + adhost->adh_directory, trail_filename(adist_trail)); + if (!trail_switch(adist_trail)) { + /* More audit records can arrive. */ + mtx_lock(&adist_free_list_lock); + TAILQ_INSERT_TAIL(&adist_free_list, adreq, + adr_next); + mtx_unlock(&adist_free_list_lock); + wait_for_file(); + continue; + } + adreq_fill(adreq, ADIST_CMD_CLOSE, + trail_filename(adist_trail), 0); + trail_close(adist_trail); + goto move; + } + + adreq_fill(adreq, ADIST_CMD_APPEND, adreq->adr_data, done); +move: + pjdlog_debug(3, + "read thread: Moving request %p to the send queue (%hhu).", + adreq, adreq->adr_cmd); + QUEUE_INSERT(adreq, &adist_send_list); + } + /* NOTREACHED */ + return (NULL); +} + +static void +keepalive_send(void) +{ + struct adreq *adreq; + + rw_rlock(&adist_remote_lock); + if (adhost->adh_remote == NULL) { + rw_unlock(&adist_remote_lock); + return; + } + rw_unlock(&adist_remote_lock); + + mtx_lock(&adist_free_list_lock); + adreq = TAILQ_FIRST(&adist_free_list); + if (adreq != NULL) + TAILQ_REMOVE(&adist_free_list, adreq, adr_next); + mtx_unlock(&adist_free_list_lock); + if (adreq == NULL) + return; + + adreq_fill(adreq, ADIST_CMD_KEEPALIVE, NULL, 0); + + QUEUE_INSERT(adreq, &adist_send_list); + + pjdlog_debug(3, "keepalive_send: Request sent."); +} + +/* + * Thread sends request to secondary node. + */ +static void * +send_thread(void *arg __unused) +{ + time_t lastcheck, now; + struct adreq *adreq; + + pjdlog_debug(1, "%s started.", __func__); + + lastcheck = time(NULL); + + for (;;) { + pjdlog_debug(3, "send thread: Taking request."); + for (;;) { + QUEUE_TAKE(adreq, &adist_send_list, ADIST_KEEPALIVE); + if (adreq != NULL) + break; + now = time(NULL); + if (lastcheck + ADIST_KEEPALIVE <= now) { + keepalive_send(); + lastcheck = now; + } + } + PJDLOG_ASSERT(adreq != NULL); + pjdlog_debug(3, "send thread: (%p) Got request %hhu.", adreq, + adreq->adr_cmd); + /* + * Protect connection from disappearing. + */ + rw_rlock(&adist_remote_lock); + /* + * Move the request to the recv queue first to avoid race + * where the recv thread receives the reply before we move + * the request to the recv queue. + */ + QUEUE_INSERT(adreq, &adist_recv_list); + if (adhost->adh_remote == NULL || + proto_send(adhost->adh_remote, &adreq->adr_packet, + ADPKT_SIZE(adreq)) == -1) { + rw_unlock(&adist_remote_lock); + pjdlog_debug(1, + "send thread: (%p) Unable to send request.", adreq); + if (adhost->adh_remote != NULL) + sender_disconnect(); + continue; + } else { + pjdlog_debug(3, "Request %p sent successfully.", adreq); + adreq_log(LOG_DEBUG, 2, -1, adreq, + "send: (%p) Request sent: ", adreq); + rw_unlock(&adist_remote_lock); + } + } + /* NOTREACHED */ + return (NULL); +} + +static void +adrep_decode_header(struct adrep *adrep) +{ + + /* Byte-swap only is the receiver is using different byte order. */ + if (adrep->adrp_byteorder != ADIST_BYTEORDER) { + adrep->adrp_byteorder = ADIST_BYTEORDER; + adrep->adrp_seq = bswap64(adrep->adrp_seq); + adrep->adrp_error = bswap16(adrep->adrp_error); + } +} + +/* + * Thread receives answer from secondary node and passes it to ggate_send + * thread. + */ +static void * +recv_thread(void *arg __unused) +{ + struct adrep adrep; + struct adreq *adreq; + + pjdlog_debug(1, "%s started.", __func__); + + for (;;) { + /* Wait until there is anything to receive. */ + QUEUE_WAIT(&adist_recv_list); + pjdlog_debug(3, "recv thread: Got something."); + rw_rlock(&adist_remote_lock); + if (adhost->adh_remote == NULL) { + /* + * Connection is dead. + * XXX: We shouldn't be here. + */ + rw_unlock(&adist_remote_lock); + continue; + } + if (proto_recv(adhost->adh_remote, &adrep, + sizeof(adrep)) == -1) { + rw_unlock(&adist_remote_lock); + pjdlog_errno(LOG_ERR, "Unable to receive reply"); + sender_disconnect(); + continue; + } + rw_unlock(&adist_remote_lock); + adrep_decode_header(&adrep); + /* + * Find the request that was just confirmed. + */ + mtx_lock(&adist_recv_list_lock); + TAILQ_FOREACH(adreq, &adist_recv_list, adr_next) { + if (adreq->adr_seq == adrep.adrp_seq) { + TAILQ_REMOVE(&adist_recv_list, adreq, + adr_next); + break; + } + } + if (adreq == NULL) { + /* + * If we disconnected in the meantime, just continue. + * On disconnect sender_disconnect() clears the queue, + * we can use that. + */ + if (TAILQ_EMPTY(&adist_recv_list)) { + mtx_unlock(&adist_recv_list_lock); + continue; + } + mtx_unlock(&adist_recv_list_lock); + pjdlog_error("Found no request matching received 'seq' field (%ju).", + (uintmax_t)adrep.adrp_seq); + sender_disconnect(); + continue; + } + mtx_unlock(&adist_recv_list_lock); + adreq_log(LOG_DEBUG, 2, -1, adreq, + "recv thread: (%p) Request confirmed: ", adreq); + pjdlog_debug(3, "recv thread: (%p) Got request %hhu.", adreq, + adreq->adr_cmd); + if (adrep.adrp_error != 0) { + pjdlog_error("Receiver returned error (%s), disconnecting.", + adist_errstr((int)adrep.adrp_error)); + sender_disconnect(); + continue; + } + if (adreq->adr_cmd == ADIST_CMD_CLOSE) + trail_unlink(adist_trail, adreq->adr_data); + pjdlog_debug(3, "Request received successfully."); + QUEUE_INSERT(adreq, &adist_free_list); + } + /* NOTREACHED */ + return (NULL); +} + +static void +guard_check_connection(void) +{ + + PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); + + rw_rlock(&adist_remote_lock); + if (adhost->adh_remote != NULL) { + rw_unlock(&adist_remote_lock); + pjdlog_debug(3, "remote_guard: Connection to %s is ok.", + adhost->adh_remoteaddr); + return; + } + + /* + * Upgrade the lock. It doesn't have to be atomic as no other thread + * can change connection status from disconnected to connected. + */ + rw_unlock(&adist_remote_lock); + pjdlog_debug(1, "remote_guard: Reconnecting to %s.", + adhost->adh_remoteaddr); + if (sender_connect() == 0) { + pjdlog_info("Successfully reconnected to %s.", + adhost->adh_remoteaddr); + } else { + pjdlog_debug(1, "remote_guard: Reconnect to %s failed.", + adhost->adh_remoteaddr); + } +} + +/* + * Thread guards remote connections and reconnects when needed, handles + * signals, etc. + */ +static void * +guard_thread(void *arg __unused) +{ + struct timespec timeout; + time_t lastcheck, now; + sigset_t mask; + int signo; + + lastcheck = time(NULL); + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); + + timeout.tv_sec = ADIST_KEEPALIVE; + timeout.tv_nsec = 0; + signo = -1; + + for (;;) { + switch (signo) { + case SIGINT: + case SIGTERM: + sigexit_received = true; + pjdlog_exitx(EX_OK, + "Termination signal received, exiting."); + break; + default: + break; + } + + pjdlog_debug(3, "remote_guard: Checking connections."); + now = time(NULL); + if (lastcheck + ADIST_KEEPALIVE <= now) { + guard_check_connection(); + lastcheck = now; + } + signo = sigtimedwait(&mask, NULL, &timeout); + } + /* NOTREACHED */ + return (NULL); +} + +void +adist_sender(struct adist_config *config, struct adist_host *adh) +{ + pthread_t td; + pid_t pid; + int error, mode, debuglevel; + + /* + * Create communication channel for sending connection requests from + * child to parent. + */ + if (proto_connect(NULL, "socketpair://", -1, &adh->adh_conn) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to create connection sockets between child and parent"); + return; + } + + pid = fork(); + if (pid == -1) { + pjdlog_errno(LOG_ERR, "Unable to fork"); + proto_close(adh->adh_conn); + adh->adh_conn = NULL; + return; + } + + if (pid > 0) { + /* This is parent. */ + adh->adh_worker_pid = pid; + /* Declare that we are receiver. */ + proto_recv(adh->adh_conn, NULL, 0); + return; + } + + adcfg = config; + adhost = adh; + + mode = pjdlog_mode_get(); + debuglevel = pjdlog_debug_get(); + + /* Declare that we are sender. */ + proto_send(adhost->adh_conn, NULL, 0); + + descriptors_cleanup(adhost); + +#ifdef TODO + descriptors_assert(adhost, mode); +#endif + + pjdlog_init(mode); + pjdlog_debug_set(debuglevel); + pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); +#ifdef HAVE_SETPROCTITLE + setproctitle("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); +#endif + + /* + * The sender process should be able to remove entries from its + * trail directory, but it should not be able to write to the + * trail files, only read from them. + */ + adist_trail = trail_new(adhost->adh_directory, false); + if (adist_trail == NULL) + exit(EX_OSFILE); + + if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", + role2str(adhost->adh_role), adhost->adh_name) != 0) { + exit(EX_CONFIG); + } + pjdlog_info("Privileges successfully dropped."); + + /* + * We can ignore wait_for_dir_init() failures. It will fall back to + * using sleep(3). + */ + (void)wait_for_dir_init(trail_dirfd(adist_trail)); + + init_environment(); + if (sender_connect() == 0) { + pjdlog_info("Successfully connected to %s.", + adhost->adh_remoteaddr); + } + adhost->adh_reset = true; + + /* + * Create the guard thread first, so we can handle signals from the + * very begining. + */ + error = pthread_create(&td, NULL, guard_thread, NULL); + PJDLOG_ASSERT(error == 0); + error = pthread_create(&td, NULL, send_thread, NULL); + PJDLOG_ASSERT(error == 0); + error = pthread_create(&td, NULL, recv_thread, NULL); + PJDLOG_ASSERT(error == 0); + (void)read_thread(NULL); +} diff --git a/contrib/openbsm/bin/auditdistd/sigtimedwait.h b/contrib/openbsm/bin/auditdistd/sigtimedwait.h new file mode 100644 index 0000000..06a4d13 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/sigtimedwait.h @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SIGTIMEDWAIT_H_ +#define _SIGTIMEDWAIT_H_ + +#include <sys/types.h> +#include <sys/time.h> + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "pjdlog.h" + +static int +sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + struct itimerval it; + sigset_t mask; + int error, signo; + + PJDLOG_ASSERT(info == NULL); + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); + + timerclear(&it.it_interval); + it.it_value.tv_sec = timeout->tv_sec; + it.it_value.tv_usec = timeout->tv_nsec / 1000; + if (it.it_value.tv_sec == 0 && it.it_value.tv_usec == 0) + it.it_value.tv_usec = 1; + PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0); + + bcopy(set, &mask, sizeof(mask)); + PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); + + PJDLOG_VERIFY(sigwait(&mask, &signo) == 0); + error = errno; + + timerclear(&it.it_interval); + timerclear(&it.it_value); + PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0); + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0); + + if (signo == SIGALRM) { + errno = EAGAIN; + signo = -1; + } else { + errno = error; + } + + return (signo); +} + +#endif /* !_SIGTIMEDWAIT_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/strndup.h b/contrib/openbsm/bin/auditdistd/strndup.h new file mode 100644 index 0000000..c36a950 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/strndup.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _STRNDUP_H_ +#define _STRNDUP_H_ + +#include <stdlib.h> +#include <string.h> + +static char * +strndup(const char *str, size_t len) +{ + size_t outlen; + char *outstr; + + outlen = strlen(str); + if (outlen > len) + outlen = len; + outstr = malloc(outlen + 1); + if (outstr != NULL) { + memcpy(outstr, str, outlen); + outstr[outlen] = '\0'; + } + return (outstr); +} + +#endif /* !_STRNDUP_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/subr.c b/contrib/openbsm/bin/auditdistd/subr.c new file mode 100644 index 0000000..ecc626c --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/subr.c @@ -0,0 +1,304 @@ +/*- + * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#ifdef HAVE_KQUEUE +#include <sys/types.h> +#include <sys/event.h> +#include <sys/time.h> +#endif + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#ifndef HAVE_ARC4RANDOM +#include <openssl/rand.h> +#endif + +#ifndef HAVE_STRLCAT +#include <compat/strlcat.h> +#endif + +#include "auditdistd.h" +#include "pjdlog.h" +#include "subr.h" + +int +vsnprlcat(char *str, size_t size, const char *fmt, va_list ap) +{ + size_t len; + + len = strlen(str); + return (vsnprintf(str + len, size - len, fmt, ap)); +} + +int +snprlcat(char *str, size_t size, const char *fmt, ...) +{ + va_list ap; + int result; + + va_start(ap, fmt); + result = vsnprlcat(str, size, fmt, ap); + va_end(ap); + return (result); +} + +const char * +role2str(int role) +{ + + switch (role) { + case ADIST_ROLE_SENDER: + return ("sender"); + case ADIST_ROLE_RECEIVER: + return ("receiver"); + } + return ("unknown"); +} + +const char * +adist_errstr(int error) +{ + + switch (error) { + case ADIST_ERROR_WRONG_ORDER: + return ("wrong operations order"); + case ADIST_ERROR_INVALID_NAME: + return ("invalid trail file name"); + case ADIST_ERROR_OPEN_OLD: + return ("attempt to open an old trail file"); + case ADIST_ERROR_CREATE: + return ("creation of new trail file failed"); + case ADIST_ERROR_OPEN: + return ("open of existing trail file failed"); + case ADIST_ERROR_READ: + return ("read failed"); + case ADIST_ERROR_WRITE: + return ("write failed"); + case ADIST_ERROR_RENAME: + return ("rename of a trail file failed"); + default: + return ("unknown error"); + } +} + +void +adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, + const char *fmt, ...) +{ + char msg[1024]; + va_list ap; + + va_start(ap, fmt); + (void)vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ", + (uintmax_t)adreq->adr_seq); + switch (adreq->adr_cmd) { + case ADIST_CMD_OPEN: + (void)snprlcat(msg, sizeof(msg), "OPEN(%s)", + adreq->adr_data); + break; + case ADIST_CMD_APPEND: + (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)", + (uintmax_t)adreq->adr_datasize); + break; + case ADIST_CMD_CLOSE: + (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)", + adreq->adr_data); + break; + case ADIST_CMD_KEEPALIVE: + (void)snprlcat(msg, sizeof(msg), "KEEPALIVE"); + break; + case ADIST_CMD_ERROR: + (void)snprlcat(msg, sizeof(msg), "ERROR"); + break; + default: + (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)", + adreq->adr_cmd); + break; + } + if (error != -1) + (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error)); + (void)strlcat(msg, ".", sizeof(msg)); + pjdlog_common(loglevel, debuglevel, -1, "%s", msg); +} + +int +adist_random(unsigned char *buf, size_t size) +{ +#ifdef HAVE_ARC4RANDOM_BUF + arc4random_buf(buf, size); + return (0); +#elif defined(HAVE_ARC4RANDOM) + uint32_t val; + + PJDLOG_ASSERT(size > 0); + PJDLOG_ASSERT((size % sizeof(val)) == 0); + + do { + val = arc4random(); + bcopy(&val, buf, sizeof(val)); + buf += sizeof(val); + size -= sizeof(val); + } while (size > 0); + + return (0); +#else + if (RAND_bytes(buf, (int)size) == 0) + return (-1); + return (0); +#endif +} + +static int wait_for_dir_kq = -1; +static int wait_for_file_kq = -1; + +int +wait_for_dir_init(int fd) +{ +#ifdef HAVE_KQUEUE + struct kevent ev; + int error, kq; + + PJDLOG_ASSERT(wait_for_dir_kq == -1); +#endif + + PJDLOG_ASSERT(fd != -1); + +#ifdef HAVE_KQUEUE + kq = kqueue(); + if (kq == -1) { + pjdlog_errno(LOG_WARNING, "kqueue() failed"); + return (-1); + } + EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_WRITE, 0, 0); + if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { + error = errno; + pjdlog_errno(LOG_WARNING, "kevent() failed"); + (void)close(kq); + errno = error; + return (-1); + } + wait_for_dir_kq = kq; +#endif + + return (0); +} + +int +wait_for_file_init(int fd) +{ +#ifdef HAVE_KQUEUE + struct kevent ev[2]; + int error, kq; +#endif + + PJDLOG_ASSERT(fd != -1); + +#ifdef HAVE_KQUEUE + if (wait_for_file_kq != -1) { + close(wait_for_file_kq); + wait_for_file_kq = -1; + } + + kq = kqueue(); + if (kq == -1) { + pjdlog_errno(LOG_WARNING, "kqueue() failed"); + return (-1); + } + EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_RENAME, 0, 0); + EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, + 0, 0, 0); + if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) { + error = errno; + pjdlog_errno(LOG_WARNING, "kevent() failed"); + (void)close(kq); + errno = error; + return (-1); + } + wait_for_file_kq = kq; +#endif + + return (0); +} + +/* + * Wait for new file to appear in directory. + */ +void +wait_for_dir(void) +{ +#ifdef HAVE_KQUEUE + struct kevent ev; +#endif + + if (wait_for_dir_kq == -1) { + sleep(1); + return; + } + +#ifdef HAVE_KQUEUE + PJDLOG_ASSERT(wait_for_dir_kq != -1); + + if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) { + pjdlog_errno(LOG_WARNING, "kevent() failed"); + sleep(1); + } +#endif +} + +/* + * Wait for file growth or rename. + */ +void +wait_for_file(void) +{ +#ifdef HAVE_KQUEUE + struct kevent ev[2]; +#endif + + if (wait_for_file_kq == -1) { + sleep(1); + return; + } + +#ifdef HAVE_KQUEUE + PJDLOG_ASSERT(wait_for_file_kq != -1); + + if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) { + pjdlog_errno(LOG_WARNING, "kevent() failed"); + sleep(1); + } +#endif +} diff --git a/contrib/openbsm/bin/auditdistd/subr.h b/contrib/openbsm/bin/auditdistd/subr.h new file mode 100644 index 0000000..7e2ddeb --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/subr.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _AUDITDISTD_SUBR_H_ +#define _AUDITDISTD_SUBR_H_ + +#include <sys/types.h> + +#include "auditdistd.h" + +#define KEEP_ERRNO(work) do { \ + int _rerrno; \ + \ + _rerrno = errno; \ + work; \ + errno = _rerrno; \ +} while (0) + +int vsnprlcat(char *str, size_t size, const char *fmt, va_list ap); +int snprlcat(char *str, size_t size, const char *fmt, ...); + +const char *role2str(int role); +const char *adist_errstr(int error); + +void adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, + const char *fmt, ...); + +int adist_random(unsigned char *buf, size_t size); + +int wait_for_dir_init(int fd); +int wait_for_file_init(int fd); +void wait_for_dir(void); +void wait_for_file(void); + +#endif /* !_AUDITDISTD_SUBR_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/synch.h b/contrib/openbsm/bin/auditdistd/synch.h new file mode 100644 index 0000000..6d83a9b --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/synch.h @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYNCH_H_ +#define _SYNCH_H_ + +#include <errno.h> +#include <pthread.h> +#ifdef HAVE_PTHREAD_NP_H +#include <pthread_np.h> +#endif +#include <stdbool.h> +#include <time.h> + +#include "pjdlog.h" + +#ifndef PJDLOG_ASSERT +#include <assert.h> +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#endif + +static __inline void +mtx_init(pthread_mutex_t *lock) +{ + int error; + + error = pthread_mutex_init(lock, NULL); + PJDLOG_ASSERT(error == 0); +} +static __inline void +mtx_destroy(pthread_mutex_t *lock) +{ + int error; + + error = pthread_mutex_destroy(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline void +mtx_lock(pthread_mutex_t *lock) +{ + int error; + + error = pthread_mutex_lock(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline bool +mtx_trylock(pthread_mutex_t *lock) +{ + int error; + + error = pthread_mutex_trylock(lock); + PJDLOG_ASSERT(error == 0 || error == EBUSY); + return (error == 0); +} +static __inline void +mtx_unlock(pthread_mutex_t *lock) +{ + int error; + + error = pthread_mutex_unlock(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline bool +mtx_owned(pthread_mutex_t *lock) +{ + + return (pthread_mutex_isowned_np(lock) != 0); +} + +static __inline void +rw_init(pthread_rwlock_t *lock) +{ + int error; + + error = pthread_rwlock_init(lock, NULL); + PJDLOG_ASSERT(error == 0); +} +static __inline void +rw_destroy(pthread_rwlock_t *lock) +{ + int error; + + error = pthread_rwlock_destroy(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline void +rw_rlock(pthread_rwlock_t *lock) +{ + int error; + + error = pthread_rwlock_rdlock(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline void +rw_wlock(pthread_rwlock_t *lock) +{ + int error; + + error = pthread_rwlock_wrlock(lock); + PJDLOG_ASSERT(error == 0); +} +static __inline void +rw_unlock(pthread_rwlock_t *lock) +{ + int error; + + error = pthread_rwlock_unlock(lock); + PJDLOG_ASSERT(error == 0); +} + +static __inline void +cv_init(pthread_cond_t *cv) +{ + pthread_condattr_t attr; + int error; + + error = pthread_condattr_init(&attr); + PJDLOG_ASSERT(error == 0); +#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK + error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + PJDLOG_ASSERT(error == 0); +#endif + error = pthread_cond_init(cv, &attr); + PJDLOG_ASSERT(error == 0); + error = pthread_condattr_destroy(&attr); + PJDLOG_ASSERT(error == 0); +} +static __inline void +cv_wait(pthread_cond_t *cv, pthread_mutex_t *lock) +{ + int error; + + error = pthread_cond_wait(cv, lock); + PJDLOG_ASSERT(error == 0); +} +static __inline bool +cv_timedwait(pthread_cond_t *cv, pthread_mutex_t *lock, int timeout) +{ + struct timespec ts; + int error; + + if (timeout == 0) { + cv_wait(cv, lock); + return (false); + } + +#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK + error = clock_gettime(CLOCK_MONOTONIC, &ts); + PJDLOG_ASSERT(error == 0); + ts.tv_sec += timeout; + error = pthread_cond_timedwait(cv, lock, &ts); +#elif HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + ts.tv_sec = timeout; + ts.tv_nsec = 0; + error = pthread_cond_timedwait_relative_np(cv, lock, &ts); +#else +#error Neither pthread_condattr_setclock nor pthread_cond_timedwait_relative_np is available. +#endif + PJDLOG_ASSERT(error == 0 || error == ETIMEDOUT); + return (error == ETIMEDOUT); +} +static __inline void +cv_signal(pthread_cond_t *cv) +{ + int error; + + error = pthread_cond_signal(cv); + PJDLOG_ASSERT(error == 0); +} +static __inline void +cv_broadcast(pthread_cond_t *cv) +{ + int error; + + error = pthread_cond_broadcast(cv); + PJDLOG_ASSERT(error == 0); +} +#endif /* !_SYNCH_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/token.l b/contrib/openbsm/bin/auditdistd/token.l new file mode 100644 index 0000000..e3c4624 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/token.l @@ -0,0 +1,82 @@ +%{ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <stdio.h> +#include <string.h> + +#ifndef HAVE_STRNDUP +#include "strndup.h" +#endif + +#include "auditdistd.h" + +#include "parse.h" + +#define SECTION_GLOBAL 0 +#define SECTION_SENDER 1 +#define SECTION_RECEIVER 2 + +int cursection; +int depth; +int lineno; + +#define DP do { } while (0) +#define YY_DECL int yylex(void) +%} + +%option noinput +%option nounput +%option noyywrap + +%% +certfile { DP; return CERTFILE; } +directory { DP; return DIRECTORY; } +fingerprint { DP; return FINGERPRINT; } +host { DP; return HOST; } +keyfile { DP; return KEYFILE; } +listen { DP; return LISTEN; } +name { DP; return NAME; } +password { DP; return PASSWORD; } +pidfile { DP; return PIDFILE; } +receiver { DP; return RECEIVER; } +remote { DP; return REMOTE; } +sender { DP; return SENDER; } +source { DP; return SOURCE; } +timeout { DP; return TIMEOUT; } +[0-9]+ { DP; yylval.num = atoi(yytext); return NUM; } +\"[a-zA-Z0-9_/ !@#\$%\^\&\*\(\)\+\=\|\;\?\,\.\[\]\-\:]*\" { DP; yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; } +\{ { DP; depth++; return OB; } +\} { DP; depth--; return CB; } +#.*$ /* ignore comments */; +\n { lineno++; } +[ \t]+ /* ignore whitespace */; +%% diff --git a/contrib/openbsm/bin/auditdistd/trail.c b/contrib/openbsm/bin/auditdistd/trail.c new file mode 100644 index 0000000..b8a9881 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/trail.c @@ -0,0 +1,609 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config/config.h> + +#include <sys/param.h> +#include <sys/stat.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <compat/compat.h> +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif +#ifndef HAVE_FACCESSAT +#include "faccessat.h" +#endif +#ifndef HAVE_FSTATAT +#include "fstatat.h" +#endif +#ifndef HAVE_OPENAT +#include "openat.h" +#endif +#ifndef HAVE_UNLINKAT +#include "unlinkat.h" +#endif + +#include "pjdlog.h" +#include "trail.h" + +#define TRAIL_MAGIC 0x79a11 +struct trail { + int tr_magic; + /* Path usually to /var/audit/dist/ directory. */ + char tr_dirname[PATH_MAX]; + /* Descriptor to td_dirname directory. */ + DIR *tr_dirfp; + /* Path to audit trail file. */ + char tr_filename[PATH_MAX]; + /* Descriptor to audit trail file. */ + int tr_filefd; +}; + +#define HALF_LEN 14 + +bool +trail_is_not_terminated(const char *filename) +{ + + return (strcmp(filename + HALF_LEN, ".not_terminated") == 0); +} + +bool +trail_is_crash_recovery(const char *filename) +{ + + return (strcmp(filename + HALF_LEN, ".crash_recovery") == 0); +} + +struct trail * +trail_new(const char *dirname, bool create) +{ + struct trail *trail; + + trail = calloc(1, sizeof(*trail)); + + if (strlcpy(trail->tr_dirname, dirname, sizeof(trail->tr_dirname)) >= + sizeof(trail->tr_dirname)) { + free(trail); + pjdlog_error("Directory name too long (\"%s\").", dirname); + errno = ENAMETOOLONG; + return (NULL); + } + trail->tr_dirfp = opendir(dirname); + if (trail->tr_dirfp == NULL) { + if (create && errno == ENOENT) { + if (mkdir(dirname, 0700) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to create directory \"%s\"", + dirname); + free(trail); + return (NULL); + } + /* TODO: Set directory ownership. */ + } else { + pjdlog_errno(LOG_ERR, + "Unable to open directory \"%s\"", + dirname); + free(trail); + return (NULL); + } + trail->tr_dirfp = opendir(dirname); + if (trail->tr_dirfp == NULL) { + pjdlog_errno(LOG_ERR, + "Unable to open directory \"%s\"", + dirname); + free(trail); + return (NULL); + } + } + trail->tr_filefd = -1; + trail->tr_magic = TRAIL_MAGIC; + return (trail); +} + +void +trail_free(struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + + if (trail->tr_filefd != -1) + trail_close(trail); + closedir(trail->tr_dirfp); + bzero(trail, sizeof(*trail)); + trail->tr_magic = 0; + trail->tr_filefd = -1; + free(trail); +} + +static uint8_t +trail_type(DIR *dirfp, const char *filename) +{ + struct stat sb; + int dfd; + + PJDLOG_ASSERT(dirfp != NULL); + + dfd = dirfd(dirfp); + PJDLOG_ASSERT(dfd >= 0); + if (fstatat(dfd, filename, &sb, AT_SYMLINK_NOFOLLOW) == -1) { + pjdlog_errno(LOG_ERR, "Unable to stat \"%s\"", filename); + return (DT_UNKNOWN); + } + return (IFTODT(sb.st_mode)); +} + +/* + * Find trail file by first part of the name in case it was renamed. + * First part of the trail file name never changes, but trail file + * can be renamed when hosts are disconnected from .not_terminated + * to .[0-9]{14} or to .crash_recovery. + */ +static bool +trail_find(struct trail *trail) +{ + struct dirent *dp; + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(trail_is_not_terminated(trail->tr_filename)); + + rewinddir(trail->tr_dirfp); + while ((dp = readdir(trail->tr_dirfp)) != NULL) { + if (strncmp(dp->d_name, trail->tr_filename, HALF_LEN + 1) == 0) + break; + } + if (dp == NULL) + return (false); + PJDLOG_VERIFY(strlcpy(trail->tr_filename, dp->d_name, + sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); + return (true); +} + +/* + * Open the given trail file and move pointer at the given offset, as this is + * where receiver finished the last time. + * If the file doesn't exist or the given offset is equal to the file size, + * move to the next trail file. + */ +void +trail_start(struct trail *trail, const char *filename, off_t offset) +{ + struct stat sb; + int dfd, fd; + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + + PJDLOG_VERIFY(strlcpy(trail->tr_filename, filename, + sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); + trail->tr_filefd = -1; + + if (trail->tr_filename[0] == '\0') { + PJDLOG_ASSERT(offset == 0); + trail_next(trail); + return; + } + + dfd = dirfd(trail->tr_dirfp); + PJDLOG_ASSERT(dfd >= 0); +again: + fd = openat(dfd, trail->tr_filename, O_RDONLY); + if (fd == -1) { + if (errno == ENOENT && + trail_is_not_terminated(trail->tr_filename) && + trail_find(trail)) { + /* File was renamed. Retry with new name. */ + pjdlog_debug(1, + "Trail file was renamed since last connection to \"%s/%s\".", + trail->tr_dirname, trail->tr_filename); + goto again; + } else if (errno == ENOENT) { + /* File disappeared. */ + pjdlog_debug(1, "File \"%s/%s\" doesn't exist.", + trail->tr_dirname, trail->tr_filename); + } else { + pjdlog_errno(LOG_ERR, + "Unable to open file \"%s/%s\", skipping", + trail->tr_dirname, trail->tr_filename); + } + trail_next(trail); + return; + } + if (fstat(fd, &sb) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to stat file \"%s/%s\", skipping", + trail->tr_dirname, trail->tr_filename); + close(fd); + trail_next(trail); + return; + } + if (!S_ISREG(sb.st_mode)) { + pjdlog_warning("File \"%s/%s\" is not a regular file, skipping.", + trail->tr_dirname, trail->tr_filename); + close(fd); + trail_next(trail); + return; + } + /* + * We continue sending requested file if: + * 1. It is not fully sent yet, or + * 2. It is fully sent, but is not terminated, so new data can be + * appended still, or + * 3. It is fully sent but file name has changed. + * + * Note that we are fine if our .not_terminated or .crash_recovery file + * is smaller than the one on the receiver side, as it is possible that + * more data was send to the receiver than was safely stored on disk. + * We accept .not_terminated only because auditdistd can start before + * auditd manage to rename it to .crash_recovery. + */ + if (offset < sb.st_size || + (offset >= sb.st_size && + trail_is_not_terminated(trail->tr_filename)) || + (offset >= sb.st_size && trail_is_not_terminated(filename) && + trail_is_crash_recovery(trail->tr_filename))) { + /* File was not fully send. Let's finish it. */ + if (lseek(fd, offset, SEEK_SET) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to move to offset %jd within file \"%s/%s\", skipping", + (intmax_t)offset, trail->tr_dirname, + trail->tr_filename); + close(fd); + trail_next(trail); + return; + } + if (!trail_is_crash_recovery(trail->tr_filename)) { + pjdlog_debug(1, + "Restarting file \"%s/%s\" at offset %jd.", + trail->tr_dirname, trail->tr_filename, + (intmax_t)offset); + } + trail->tr_filefd = fd; + return; + } + close(fd); + if (offset > sb.st_size) { + pjdlog_warning("File \"%s/%s\" shrinked, removing it.", + trail->tr_dirname, trail->tr_filename); + } else { + pjdlog_debug(1, "File \"%s/%s\" is already sent, removing it.", + trail->tr_dirname, trail->tr_filename); + } + /* Entire file is already sent or it shirnked, we can remove it. */ + if (unlinkat(dfd, trail->tr_filename, 0) == -1) { + pjdlog_errno(LOG_WARNING, "Unable to remove file \"%s/%s\"", + trail->tr_dirname, trail->tr_filename); + } + trail_next(trail); +} + +/* + * Set next file in the trail->tr_dirname directory and open it for reading. + */ +void +trail_next(struct trail *trail) +{ + char curfile[PATH_MAX]; + struct dirent *dp; + int dfd; + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(trail->tr_filefd == -1); + +again: + curfile[0] = '\0'; + + rewinddir(trail->tr_dirfp); + while ((dp = readdir(trail->tr_dirfp)) != NULL) { + if (dp->d_name[0] < '0' || dp->d_name[0] > '9') + continue; + if (dp->d_type == DT_UNKNOWN) + dp->d_type = trail_type(trail->tr_dirfp, dp->d_name); + /* We are only interested in regular files, skip the rest. */ + if (dp->d_type != DT_REG) { + pjdlog_debug(1, + "File \"%s/%s\" is not a regular file, skipping.", + trail->tr_dirname, dp->d_name); + continue; + } + /* Skip all files "greater" than curfile. */ + if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) > 0) + continue; + /* Skip all files "smaller" than the current trail_filename. */ + if (trail->tr_filename[0] != '\0' && + strcmp(dp->d_name, trail->tr_filename) <= 0) { + continue; + } + PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) < + sizeof(curfile)); + } + if (curfile[0] == '\0') { + /* + * There are no new trail files, so we return. + * We don't clear trail_filename string, to know where to + * start when new file appears. + */ + PJDLOG_ASSERT(trail->tr_filefd == -1); + pjdlog_debug(1, "No new trail files."); + return; + } + PJDLOG_VERIFY(strlcpy(trail->tr_filename, curfile, + sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); + dfd = dirfd(trail->tr_dirfp); + PJDLOG_ASSERT(dfd >= 0); + trail->tr_filefd = openat(dfd, trail->tr_filename, O_RDONLY); + if (trail->tr_filefd == -1) { + pjdlog_errno(LOG_ERR, + "Unable to open file \"%s/%s\", skipping", + trail->tr_dirname, trail->tr_filename); + goto again; + } + pjdlog_debug(1, "Found next trail file: \"%s/%s\".", trail->tr_dirname, + trail->tr_filename); +} + +/* + * Close current trial file. + */ +void +trail_close(struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(trail->tr_filefd >= 0); + PJDLOG_ASSERT(trail->tr_filename[0] != '\0'); + + PJDLOG_VERIFY(close(trail->tr_filefd) == 0); + trail->tr_filefd = -1; +} + +/* + * Reset trail state. Used when connection is disconnected and we will + * need to start over after reconnect. Trail needs to be already closed. + */ +void +trail_reset(struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(trail->tr_filefd == -1); + + trail->tr_filename[0] = '\0'; +} + +/* + * Unlink current trial file. + */ +void +trail_unlink(struct trail *trail, const char *filename) +{ + int dfd; + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(filename != NULL); + PJDLOG_ASSERT(filename[0] != '\0'); + + dfd = dirfd(trail->tr_dirfp); + PJDLOG_ASSERT(dfd >= 0); + + if (unlinkat(dfd, filename, 0) == -1) { + pjdlog_errno(LOG_ERR, "Unable to remove \"%s/%s\"", + trail->tr_dirname, filename); + } else { + pjdlog_debug(1, "Trail file \"%s/%s\" removed.", + trail->tr_dirname, filename); + } +} + +/* + * Return true if we should switch to next trail file. + * We don't switch if our file name ends with ".not_terminated" and it + * exists (ie. wasn't renamed). + */ +bool +trail_switch(struct trail *trail) +{ + char filename[PATH_MAX]; + int fd; + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + PJDLOG_ASSERT(trail->tr_filefd >= 0); + + if (!trail_is_not_terminated(trail->tr_filename)) + return (true); + fd = dirfd(trail->tr_dirfp); + PJDLOG_ASSERT(fd >= 0); + if (faccessat(fd, trail->tr_filename, F_OK, 0) == 0) + return (false); + if (errno != ENOENT) { + pjdlog_errno(LOG_ERR, "Unable to access file \"%s/%s\"", + trail->tr_dirname, trail->tr_filename); + } + strlcpy(filename, trail->tr_filename, sizeof(filename)); + if (!trail_find(trail)) { + pjdlog_error("Trail file \"%s/%s\" disappeared.", + trail->tr_dirname, trail->tr_filename); + return (true); + } + pjdlog_debug(1, "Trail file \"%s/%s\" was renamed to \"%s/%s\".", + trail->tr_dirname, filename, trail->tr_dirname, + trail->tr_filename); + return (true); +} + +const char * +trail_filename(const struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + + return (trail->tr_filename); +} + +int +trail_filefd(const struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + + return (trail->tr_filefd); +} + +int +trail_dirfd(const struct trail *trail) +{ + + PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); + + return (dirfd(trail->tr_dirfp)); +} + +/* + * Find the last file in the directory opened under dirfp. + */ +void +trail_last(DIR *dirfp, char *filename, size_t filenamesize) +{ + char curfile[PATH_MAX]; + struct dirent *dp; + + PJDLOG_ASSERT(dirfp != NULL); + + curfile[0] = '\0'; + + rewinddir(dirfp); + while ((dp = readdir(dirfp)) != NULL) { + if (dp->d_name[0] < '0' || dp->d_name[0] > '9') + continue; + if (dp->d_type == DT_UNKNOWN) + dp->d_type = trail_type(dirfp, dp->d_name); + /* We are only interested in regular files, skip the rest. */ + if (dp->d_type != DT_REG) + continue; + /* Skip all files "greater" than curfile. */ + if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) < 0) + continue; + PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) < + sizeof(curfile)); + } + if (curfile[0] == '\0') { + /* + * There are no trail files, so we return. + */ + pjdlog_debug(1, "No trail files."); + bzero(filename, filenamesize); + return; + } + PJDLOG_VERIFY(strlcpy(filename, curfile, filenamesize) < filenamesize); + pjdlog_debug(1, "Found the most recent trail file: \"%s\".", filename); +} + +/* + * Check if the given file name is a valid audit trail file name. + * Possible names: + * 20120106132657.20120106132805 + * 20120106132657.not_terminated + * 20120106132657.crash_recovery + * If two names are given, check if the first name can be renamed + * to the second name. When renaming, first part of the name has + * to be identical and only the following renames are valid: + * 20120106132657.not_terminated -> 20120106132657.20120106132805 + * 20120106132657.not_terminated -> 20120106132657.crash_recovery + */ +bool +trail_validate_name(const char *srcname, const char *dstname) +{ + int i; + + PJDLOG_ASSERT(srcname != NULL); + + if (strlen(srcname) != 2 * HALF_LEN + 1) + return (false); + if (srcname[HALF_LEN] != '.') + return (false); + for (i = 0; i < HALF_LEN; i++) { + if (srcname[i] < '0' || srcname[i] > '9') + return (false); + } + for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) { + if (srcname[i] < '0' || srcname[i] > '9') + break; + } + if (i < 2 * HALF_LEN - 1 && + strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0 && + strcmp(srcname + HALF_LEN + 1, "crash_recovery") != 0) { + return (false); + } + + if (dstname == NULL) + return (true); + + /* We tolarate if both names are identical. */ + if (strcmp(srcname, dstname) == 0) + return (true); + + /* We can only rename not_terminated files. */ + if (strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0) + return (false); + if (strlen(dstname) != 2 * HALF_LEN + 1) + return (false); + if (strncmp(srcname, dstname, HALF_LEN + 1) != 0) + return (false); + for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) { + if (dstname[i] < '0' || dstname[i] > '9') + break; + } + if (i < 2 * HALF_LEN - 1 && + strcmp(dstname + HALF_LEN + 1, "crash_recovery") != 0) { + return (false); + } + + return (true); +} + +int +trail_name_compare(const char *name0, const char *name1) +{ + int ret; + + ret = strcmp(name0, name1); + if (ret == 0) + return (TRAIL_IDENTICAL); + if (strncmp(name0, name1, HALF_LEN + 1) == 0) + return (TRAIL_RENAMED); + return (ret < 0 ? TRAIL_OLDER : TRAIL_NEWER); +} diff --git a/contrib/openbsm/bin/auditdistd/trail.h b/contrib/openbsm/bin/auditdistd/trail.h new file mode 100644 index 0000000..204ea2b --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/trail.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _AUDITDISTD_TRAIL_H_ +#define _AUDITDISTD_TRAIL_H_ + +#include <stdbool.h> +#include <unistd.h> /* off_t */ + +#define TRAIL_IDENTICAL 0 +#define TRAIL_RENAMED 1 +#define TRAIL_OLDER 2 +#define TRAIL_NEWER 3 + +struct trail; + +struct trail *trail_new(const char *dirname, bool create); +void trail_free(struct trail *trail); +bool trail_is_not_terminated(const char *filename); +bool trail_is_crash_recovery(const char *filename); +void trail_start(struct trail *trail, const char *filename, off_t offset); +void trail_next(struct trail *trail); +void trail_close(struct trail *trail); +void trail_reset(struct trail *trail); +void trail_unlink(struct trail *trail, const char *filename); +bool trail_switch(struct trail *trail); +const char *trail_filename(const struct trail *trail); +int trail_filefd(const struct trail *trail); +int trail_dirfd(const struct trail *trail); +void trail_last(DIR *dirfp, char *filename, size_t filenamesize); +bool trail_validate_name(const char *srcname, const char *dstname); +int trail_name_compare(const char *name0, const char *name1); + +#endif /* !_AUDITDISTD_TRAIL_H_ */ diff --git a/contrib/openbsm/bin/auditdistd/unlinkat.h b/contrib/openbsm/bin/auditdistd/unlinkat.h new file mode 100644 index 0000000..6364208 --- /dev/null +++ b/contrib/openbsm/bin/auditdistd/unlinkat.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _UNLINKAT_H_ +#define _UNLINKAT_H_ + +#include <fcntl.h> +#include <unistd.h> + +#define AT_REMOVEDIR 0x01 + +static int +unlinkat(int fd, const char *path, int flag) +{ + int cfd, error, ret; + + cfd = open(".", O_RDONLY | O_DIRECTORY); + if (cfd == -1) + return (-1); + + if (fchdir(fd) == -1) { + error = errno; + (void)close(cfd); + errno = error; + return (-1); + } + + if (flag == AT_REMOVEDIR) + ret = rmdir(path); + else + ret = unlink(path); + + error = errno; + (void)fchdir(cfd); + (void)close(cfd); + errno = error; + return (ret); +} + +#endif /* !_UNLINKAT_H_ */ diff --git a/contrib/openbsm/bin/auditfilterd/Makefile.am b/contrib/openbsm/bin/auditfilterd/Makefile.am new file mode 100644 index 0000000..400a1d9 --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/Makefile.am @@ -0,0 +1,10 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = auditfilterd +auditfilterd_SOURCES = auditfilterd_conf.c auditfilterd.c +auditfilterd_LDADD = $(top_builddir)/libbsm/libbsm.la +man8_MANS = auditfilterd.8 diff --git a/contrib/openbsm/bin/auditfilterd/Makefile.in b/contrib/openbsm/bin/auditfilterd/Makefile.in new file mode 100644 index 0000000..e90f7d7 --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/Makefile.in @@ -0,0 +1,649 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = auditfilterd$(EXEEXT) +subdir = bin/auditfilterd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" +PROGRAMS = $(sbin_PROGRAMS) +am_auditfilterd_OBJECTS = auditfilterd_conf.$(OBJEXT) \ + auditfilterd.$(OBJEXT) +auditfilterd_OBJECTS = $(am_auditfilterd_OBJECTS) +auditfilterd_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(auditfilterd_SOURCES) +DIST_SOURCES = $(auditfilterd_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man8_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +auditfilterd_SOURCES = auditfilterd_conf.c auditfilterd.c +auditfilterd_LDADD = $(top_builddir)/libbsm/libbsm.la +man8_MANS = auditfilterd.8 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditfilterd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/auditfilterd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +auditfilterd$(EXEEXT): $(auditfilterd_OBJECTS) $(auditfilterd_DEPENDENCIES) $(EXTRA_auditfilterd_DEPENDENCIES) + @rm -f auditfilterd$(EXEEXT) + $(LINK) $(auditfilterd_OBJECTS) $(auditfilterd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditfilterd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditfilterd_conf.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man8 install-pdf install-pdf-am install-ps \ + install-ps-am install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man8 \ + uninstall-sbinPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd.8 b/contrib/openbsm/bin/auditfilterd/auditfilterd.8 new file mode 100644 index 0000000..f78c664 --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.8 @@ -0,0 +1,84 @@ +.\"- +.\" Copyright (c) 2006 Robert N. M. Watson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd October 3, 2006 +.Dt AUDITFILTERD 8 +.Os +.Sh NAME +.Nm auditfilterd +.Nd audit filter daemon +.Sh SYNOPSIS +.Nm +.Op Fl d +.Op Fl c Ar conffile +.Op Fl p Ar pipefile +.Op Fl t Ar trailfile +.Sh DESCRIPTION +The +.Nm +daemon is an extensible audit event monitoring daemon, allowing pluggable +modules to track audit events from a live audit source. +It is configured using the audit_filter configuration file. +The source can either be a pipe or a file. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl c Ar conffile +Specify an alternative configuration file. +.It Fl d +Starts the daemon in debug mode \[em] it will not daemonize. +.It Fl p Ar pipefile +Specify a pipe as an alternative source of audit event records. +Default is +.Pa /dev/auditpipe . +.It Fl t Ar trailfile +Specify a file as an alternative source of audit event records. +.El +.Sh FILES +.Bl -tag -width ".Pa /etc/security/audit_filterd" -compact +.It Pa /etc/security/audit_filterd +Default configuration file for +.Nm . +.It Pa /dev/auditpipe +Default audit record source for +.Nm . +.El +.Sh SEE ALSO +.Xr audit 8 , +.Xr auditd 8 +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +The +.Nm +daemon and audit filter APIs were created by +.An Robert Watson . +.Sh BUGS +.Nm +is experimental, and should not be relied on in production. +APIs and services it offers can and will change in future OpenBSM releases. diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd.c b/contrib/openbsm/bin/auditfilterd/auditfilterd.c new file mode 100644 index 0000000..46c86b2 --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.c @@ -0,0 +1,352 @@ +/*- + * Copyright (c) 2006 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by Robert Watson for the TrustedBSD Project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Main file for the audit filter daemon, which presents audit records to a + * set of run-time registered loadable modules. This is the main event loop + * of the daemon, which handles starting up, waiting for records, and + * presenting records to configured modules. auditfilterd_conf.c handles the + * reading and management of the configuration, module list and module state, + * etc. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <config/config.h> +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else +#include <compat/queue.h> +#endif + +#ifndef HAVE_CLOCK_GETTIME +#include <compat/clock_gettime.h> +#endif + +#include <bsm/libbsm.h> +#include <bsm/audit_filter.h> +#include <bsm/audit_internal.h> + +#include <err.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "auditfilterd.h" + +/* + * Global list of registered filters. + */ +struct auditfilter_module_list filter_list; + +/* + * Configuration and signal->main flags. + */ +int debug; /* Debugging mode requested, don't detach. */ +int reread_config; /* SIGHUP has been received. */ +int quit; /* SIGQUIT/TERM/INT has been received. */ + +static void +usage(void) +{ + + fprintf(stderr, "auditfilterd [-d] [-c conffile] [-p pipefile]" + " [-t trailfile]\n"); + fprintf(stderr, " -c Specify configuration file (default: %s)\n", + AUDITFILTERD_CONFFILE); + fprintf(stderr, " -d Debugging mode, don't daemonize\n"); + fprintf(stderr, " -p Specify pipe file (default: %s)\n", + AUDITFILTERD_PIPEFILE); + fprintf(stderr, " -t Specify audit trail file (default: none)\n"); + exit(-1); +} + +static void +auditfilterd_init(void) +{ + + TAILQ_INIT(&filter_list); +} + +static void +signal_handler(int signum) +{ + + switch (signum) { + case SIGHUP: + reread_config++; + break; + + case SIGINT: + case SIGTERM: + case SIGQUIT: + quit++; + break; + } +} + +/* + * Present raw BSM to a set of registered and interested filters. + */ +static void +present_rawrecord(struct timespec *ts, u_char *data, u_int len) +{ + struct auditfilter_module *am; + + TAILQ_FOREACH(am, &filter_list, am_list) { + if (am->am_rawrecord != NULL) + (am->am_rawrecord)(am, ts, data, len); + } +} + +/* + * Parse the BSM into a set of tokens, which will be passed to registered + * and interested filters. + */ +#define MAX_TOKENS 128 /* Maximum tokens we handle per record. */ +static void +present_tokens(struct timespec *ts, u_char *data, u_int len) +{ + struct auditfilter_module *am; + tokenstr_t tokens[MAX_TOKENS]; + u_int bytesread; + int tokencount; + + tokencount = 0; + while (bytesread < len) { + if (au_fetch_tok(&tokens[tokencount], data + bytesread, + len - bytesread) == -1) + break; + bytesread += tokens[tokencount].len; + tokencount++; + } + + TAILQ_FOREACH(am, &filter_list, am_list) { + if (am->am_record != NULL) + (am->am_record)(am, ts, tokencount, tokens); + } +} + +/* + * The main loop spins pulling records out of the record source and passing + * them to modules for processing. + */ +static void +mainloop_file(const char *conffile, const char *trailfile, FILE *trail_fp) +{ + struct timespec ts; + FILE *conf_fp; + u_char *buf; + int reclen; + + while (1) { + /* + * On SIGHUP, we reread the configuration file and reopen + * the trail file. + */ + if (reread_config) { + reread_config = 0; + warnx("rereading configuration"); + conf_fp = fopen(conffile, "r"); + if (conf_fp == NULL) + err(-1, "%s", conffile); + auditfilterd_conf(conffile, conf_fp); + fclose(conf_fp); + + fclose(trail_fp); + trail_fp = fopen(trailfile, "r"); + if (trail_fp == NULL) + err(-1, "%s", trailfile); + } + if (quit) { + warnx("quitting"); + break; + } + + /* + * For now, be relatively unrobust about incomplete records, + * but in the future will want to do better. Need to look + * more at the right blocking and signal behavior here. + */ + reclen = au_read_rec(trail_fp, &buf); + if (reclen == -1) + continue; + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + err(-1, "clock_gettime"); + present_rawrecord(&ts, buf, reclen); + present_tokens(&ts, buf, reclen); + free(buf); + } +} + +/* + * The main loop spins pulling records out of the record source and passing + * them to modules for processing. This version of the function accepts + * discrete record input from a file descriptor, as opposed to buffered input + * from a file stream. + */ +static void +mainloop_pipe(const char *conffile, const char *pipefile __unused, int pipe_fd) +{ + u_char record[MAX_AUDIT_RECORD_SIZE]; + struct timespec ts; + FILE *conf_fp; + int reclen; + + while (1) { + /* + * On SIGHUP, we reread the configuration file. Unlike with + * a trail file, we don't reopen the pipe, as we don't want + * to miss records which will be flushed if we do. + */ + if (reread_config) { + reread_config = 0; + warnx("rereading configuration"); + conf_fp = fopen(conffile, "r"); + if (conf_fp == NULL) + err(-1, "%s", conffile); + auditfilterd_conf(conffile, conf_fp); + fclose(conf_fp); + } + if (quit) { + warnx("quitting"); + break; + } + + /* + * For now, be relatively unrobust about incomplete records, + * but in the future will want to do better. Need to look + * more at the right blocking and signal behavior here. + */ + reclen = read(pipe_fd, record, MAX_AUDIT_RECORD_SIZE); + if (reclen < 0) + continue; + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + err(-1, "clock_gettime"); + present_rawrecord(&ts, record, reclen); + present_tokens(&ts, record, reclen); + } +} + +int +main(int argc, char *argv[]) +{ + const char *pipefile, *trailfile, *conffile; + FILE *trail_fp, *conf_fp; + struct stat sb; + int pipe_fd; + int ch; + + conffile = AUDITFILTERD_CONFFILE; + trailfile = NULL; + pipefile = NULL; + while ((ch = getopt(argc, argv, "c:dp:t:")) != -1) { + switch (ch) { + case 'c': + conffile = optarg; + break; + + case 'd': + debug++; + break; + + case 't': + if (trailfile != NULL || pipefile != NULL) + usage(); + trailfile = optarg; + break; + + case 'p': + if (pipefile != NULL || trailfile != NULL) + usage(); + pipefile = optarg; + break; + + default: + usage(); + } + } + + argc -= optind; + argv += optind; + + if (argc != 0) + usage(); + + /* + * We allow only one of a pipe or a trail to be used. If none is + * specified, we provide a default pipe path. + */ + if (pipefile == NULL && trailfile == NULL) + pipefile = AUDITFILTERD_PIPEFILE; + + if (pipefile != NULL) { + pipe_fd = open(pipefile, O_RDONLY); + if (pipe_fd < 0) + err(-1, "open:%s", pipefile); + if (fstat(pipe_fd, &sb) < 0) + err(-1, "stat: %s", pipefile); + if (!S_ISCHR(sb.st_mode)) + errx(-1, "fstat: %s not device", pipefile); + } else { + trail_fp = fopen(trailfile, "r"); + if (trail_fp == NULL) + err(-1, "%s", trailfile); + } + + conf_fp = fopen(conffile, "r"); + if (conf_fp == NULL) + err(-1, "%s", conffile); + + auditfilterd_init(); + if (auditfilterd_conf(conffile, conf_fp) < 0) + exit(-1); + fclose(conf_fp); + + if (!debug) { + if (daemon(0, 0) < 0) + err(-1, "daemon"); + } + + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGQUIT, signal_handler); + signal(SIGTERM, signal_handler); + + if (pipefile != NULL) + mainloop_pipe(conffile, pipefile, pipe_fd); + else + mainloop_file(conffile, trailfile, trail_fp); + + auditfilterd_conf_shutdown(); + return (0); +} diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd.h b/contrib/openbsm/bin/auditfilterd/auditfilterd.h new file mode 100644 index 0000000..c178b82 --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/auditfilterd.h @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2006 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by Robert Watson for the TrustedBSD Project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define AUDITFILTERD_CONFFILE "/etc/security/audit_filter" +#define AUDITFILTERD_PIPEFILE "/dev/auditpipe" + +/* + * Limit on the number of arguments that can appear in an audit_filterd + * configuration line. + */ +#define AUDITFILTERD_CONF_MAXARGS 256 + +/* + * Data structure description each instantiated module. + */ +struct auditfilter_module { + /* + * Fields from configuration file and dynamic linker. + */ + char *am_modulename; + char *am_arg_buffer; + int am_argc; + char **am_argv; + void *am_dlhandle; + + /* + * Fields provided by or extracted from the module. + */ + void *am_cookie; + audit_filter_attach_t am_attach; + audit_filter_reinit_t am_reinit; + audit_filter_record_t am_record; + audit_filter_rawrecord_t am_rawrecord; + audit_filter_detach_t am_detach; + + /* + * Fields for maintaining the list of modules. + */ + TAILQ_ENTRY(auditfilter_module) am_list; +}; +TAILQ_HEAD(auditfilter_module_list, auditfilter_module); + +/* + * List of currently registered modules. + */ +extern struct auditfilter_module_list filter_list; + +/* + * Function definitions. + */ +int auditfilterd_conf(const char *filename, FILE *fp); +void auditfilterd_conf_shutdown(void); diff --git a/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c b/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c new file mode 100644 index 0000000..bf3b3bb --- /dev/null +++ b/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c @@ -0,0 +1,511 @@ +/*- + * Copyright (c) 2006 Robert N. M. Watson + * All rights reserved. + * + * This software was developed by Robert Watson for the TrustedBSD Project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file parser for auditfilterd. The configuration file is a + * very simple format, similar to other BSM configuration files, consisting + * of configuration entries of one line each. The configuration function is + * aware of previous runs, and will update the current configuration as + * needed. + * + * Modules are in one of two states: attached, or detached. If attach fails, + * detach is not called because it was not attached. If a module is attached + * and a call to its reinit method fails, we will detach it. + * + * Modules are passed a (void *) reference to their configuration state so + * that they may pass this into any common APIs we provide which may rely on + * that state. Currently, the only such API is the cookie API, which allows + * per-instance state to be maintained by a module. In the future, this will + * also be used to support per-instance preselection state. + */ + +#include <sys/types.h> + +#include <config/config.h> +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else +#include <compat/queue.h> +#endif + +#include <bsm/libbsm.h> +#include <bsm/audit_filter.h> + +#include <dlfcn.h> +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "auditfilterd.h" + +/* + * Free an individual auditfilter_module structure. Will not shut down the + * module, just frees the memory. Does so conditional on pointers being + * non-NULL so that it can be used on partially allocated structures. + */ +static void +auditfilter_module_free(struct auditfilter_module *am) +{ + + if (am->am_modulename != NULL) + free(am->am_modulename); + if (am->am_arg_buffer != NULL) + free(am->am_arg_buffer); + if (am->am_argv != NULL) + free(am->am_argv); +} + +/* + * Free all memory associated with an auditfilter_module list. Does not + * dlclose() or shut down the modules, just free the memory. Use + * auditfilter_module_list_detach() for that, if required. + */ +static void +auditfilter_module_list_free(struct auditfilter_module_list *list) +{ + struct auditfilter_module *am; + + while (!(TAILQ_EMPTY(list))) { + am = TAILQ_FIRST(list); + TAILQ_REMOVE(list, am, am_list); + auditfilter_module_free(am); + } +} + +/* + * Detach an attached module from an auditfilter_module structure. Does not + * free the data structure itself. + */ +static void +auditfilter_module_detach(struct auditfilter_module *am) +{ + + if (am->am_detach != NULL) + am->am_detach(am); + am->am_cookie = NULL; + (void)dlclose(am->am_dlhandle); + am->am_dlhandle = NULL; +} + +/* + * Walk an auditfilter_module list, detaching each module. Intended to be + * combined with auditfilter_module_list_free(). + */ +static void +auditfilter_module_list_detach(struct auditfilter_module_list *list) +{ + struct auditfilter_module *am; + + TAILQ_FOREACH(am, list, am_list) + auditfilter_module_detach(am); +} + +/* + * Given a filled out auditfilter_module, use dlopen() and dlsym() to attach + * the module. If we fail, leave fields in the state we found them. + * + * XXXRW: Need a better way to report errors. + */ +static int +auditfilter_module_attach(struct auditfilter_module *am) +{ + + am->am_dlhandle = dlopen(am->am_modulename, RTLD_NOW); + if (am->am_dlhandle == NULL) { + warnx("auditfilter_module_attach: %s: %s", am->am_modulename, + dlerror()); + return (-1); + } + + /* + * Not implementing these is not considered a failure condition, + * although we might want to consider warning if obvious stuff is + * not implemented, such as am_record. + */ + am->am_attach = dlsym(am->am_dlhandle, AUDIT_FILTER_ATTACH_STRING); + am->am_reinit = dlsym(am->am_dlhandle, AUDIT_FILTER_REINIT_STRING); + am->am_record = dlsym(am->am_dlhandle, AUDIT_FILTER_RECORD_STRING); + am->am_rawrecord = dlsym(am->am_dlhandle, + AUDIT_FILTER_RAWRECORD_STRING); + am->am_detach = dlsym(am->am_dlhandle, AUDIT_FILTER_DETACH_STRING); + + if (am->am_attach != NULL) { + if (am->am_attach(am, am->am_argc, am->am_argv) + != AUDIT_FILTER_SUCCESS) { + warnx("auditfilter_module_attach: %s: failed", + am->am_modulename); + dlclose(am->am_dlhandle); + am->am_dlhandle = NULL; + am->am_cookie = NULL; + am->am_attach = NULL; + am->am_reinit = NULL; + am->am_record = NULL; + am->am_rawrecord = NULL; + am->am_detach = NULL; + return (-1); + } + } + + return (0); +} + +/* + * When the arguments for a module are changed, we notify the module through + * a call to its reinit method, if any. Return 0 on success, or -1 on + * failure. + */ +static int +auditfilter_module_reinit(struct auditfilter_module *am) +{ + + if (am->am_reinit == NULL) + return (0); + + if (am->am_reinit(am, am->am_argc, am->am_argv) != + AUDIT_FILTER_SUCCESS) { + warnx("auditfilter_module_reinit: %s: failed", + am->am_modulename); + return (-1); + } + + return (0); +} + +/* + * Given a configuration line, generate an auditfilter_module structure that + * describes it; caller will not pass comments in, so they are not looked + * for. Do not attempt to instantiate it. Will destroy the contents of + * 'buffer'. + * + * Configuration lines consist of two parts: the module name and arguments + * separated by a ':', and then a ','-delimited list of arguments. + * + * XXXRW: Need to decide where to send the warning output -- stderr for now. + */ +struct auditfilter_module * +auditfilter_module_parse(const char *filename, int linenumber, char *buffer) +{ + char *arguments, *module, **ap; + struct auditfilter_module *am; + + am = malloc(sizeof(*am)); + if (am == NULL) { + warn("auditfilter_module_parse: %s:%d", filename, linenumber); + return (NULL); + } + bzero(am, sizeof(*am)); + + /* + * First, break out the module and arguments strings. We look for + * one extra argument to make sure there are no more :'s in the line. + * That way, we prevent modules from using argument strings that, in + * the future, may cause problems for adding additional columns. + */ + arguments = buffer; + module = strsep(&arguments, ":"); + if (module == NULL || arguments == NULL) { + warnx("auditfilter_module_parse: %s:%d: parse error", + filename, linenumber); + return (NULL); + } + + am->am_modulename = strdup(module); + if (am->am_modulename == NULL) { + warn("auditfilter_module_parse: %s:%d", filename, linenumber); + auditfilter_module_free(am); + return (NULL); + } + + am->am_arg_buffer = strdup(buffer); + if (am->am_arg_buffer == NULL) { + warn("auditfilter_module_parse: %s:%d", filename, linenumber); + auditfilter_module_free(am); + return (NULL); + } + + /* + * Now, break out the arguments string into a series of arguments. + * This is a bit more complicated, and requires cleanup if things go + * wrong. + */ + am->am_argv = malloc(sizeof(char *) * AUDITFILTERD_CONF_MAXARGS); + if (am->am_argv == NULL) { + warn("auditfilter_module_parse: %s:%d", filename, linenumber); + auditfilter_module_free(am); + return (NULL); + } + bzero(am->am_argv, sizeof(char *) * AUDITFILTERD_CONF_MAXARGS); + am->am_argc = 0; + for (ap = am->am_argv; (*ap = strsep(&arguments, " \t")) != NULL;) { + if (**ap != '\0') { + am->am_argc++; + if (++ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS]) + break; + } + } + if (ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS]) { + warnx("auditfilter_module_parse: %s:%d: too many arguments", + filename, linenumber); + auditfilter_module_free(am); + return (NULL); + } + + return (am); +} + +/* + * Read a configuration file, and populate 'list' with the configuration + * lines. Does not attempt to instantiate the configuration, just read it + * into a useful set of data structures. + */ +static int +auditfilterd_conf_read(const char *filename, FILE *fp, + struct auditfilter_module_list *list) +{ + int error, linenumber, syntaxerror; + struct auditfilter_module *am; + char buffer[LINE_MAX]; + + syntaxerror = 0; + linenumber = 0; + while (!feof(fp) && !ferror(fp)) { + if (fgets(buffer, LINE_MAX, fp) == NULL) + break; + linenumber++; + if (buffer[0] == '#' || strlen(buffer) < 1) + continue; + buffer[strlen(buffer)-1] = '\0'; + am = auditfilter_module_parse(filename, linenumber, buffer); + if (am == NULL) { + syntaxerror = 1; + break; + } + TAILQ_INSERT_HEAD(list, am, am_list); + } + + /* + * File I/O error. + */ + if (ferror(fp)) { + error = errno; + auditfilter_module_list_free(list); + errno = error; + return (-1); + } + + /* + * Syntax error. + */ + if (syntaxerror) { + auditfilter_module_list_free(list); + errno = EINVAL; + return (-1); + } + return (0); +} + +/* + * Apply changes necessary to bring a new configuration into force. The new + * configuration data is passed in, and the current configuration is updated + * to match it. The contents of 'list' are freed or otherwise disposed of + * before return. + * + * The algorithms here are not very efficient, but this is an infrequent + * operation on very short lists. + */ +static void +auditfilterd_conf_apply(struct auditfilter_module_list *list) +{ + struct auditfilter_module *am1, *am2, *am_tmp; + int argc_tmp, found; + char **argv_tmp; + + /* + * First, remove remove and detach any entries that appear in the + * current configuration, but not the new configuration. + */ + TAILQ_FOREACH_SAFE(am1, &filter_list, am_list, am_tmp) { + found = 0; + TAILQ_FOREACH(am2, list, am_list) { + if (strcmp(am1->am_modulename, am2->am_modulename) + == 0) { + found = 1; + break; + } + } + if (found) + continue; + + /* + * am1 appears in filter_list, but not the new list, detach + * and free the module. + */ + warnx("detaching module %s", am1->am_modulename); + TAILQ_REMOVE(&filter_list, am1, am_list); + auditfilter_module_detach(am1); + auditfilter_module_free(am1); + } + + /* + * Next, update the configuration of any modules that appear in both + * lists. We do this by swapping the two argc and argv values and + * freeing the new one, rather than detaching the old one and + * attaching the new one. That way module state is preserved. + */ + TAILQ_FOREACH(am1, &filter_list, am_list) { + found = 0; + TAILQ_FOREACH(am2, list, am_list) { + if (strcmp(am1->am_modulename, am2->am_modulename) + == 0) { + found = 1; + break; + } + } + if (!found) + continue; + + /* + * Swap the arguments. + */ + argc_tmp = am1->am_argc; + argv_tmp = am1->am_argv; + am1->am_argc = am2->am_argc; + am1->am_argv = am2->am_argv; + am2->am_argc = argc_tmp; + am2->am_argv = argv_tmp; + + /* + * The reinit is a bit tricky: if reinit fails, we actually + * remove the old entry and detach that, as we don't allow + * running modules to be out of sync with the configuration + * file. + */ + warnx("reiniting module %s", am1->am_modulename); + if (auditfilter_module_reinit(am1) != 0) { + warnx("reinit failed for module %s, detaching", + am1->am_modulename); + TAILQ_REMOVE(&filter_list, am1, am_list); + auditfilter_module_detach(am1); + auditfilter_module_free(am1); + } + + /* + * Free the entry from the new list, which will discard the + * old arguments. No need to detach, as it was never + * attached in the first place. + */ + TAILQ_REMOVE(list, am2, am_list); + auditfilter_module_free(am2); + } + + /* + * Finally, attach any new entries that don't appear in the old + * configuration, and if they attach successfully, move them to the + * real configuration list. + */ + TAILQ_FOREACH(am1, list, am_list) { + found = 0; + TAILQ_FOREACH(am2, &filter_list, am_list) { + if (strcmp(am1->am_modulename, am2->am_modulename) + == 0) { + found = 1; + break; + } + } + if (found) + continue; + /* + * Attach the entry. If it succeeds, add to filter_list, + * otherwise, free. No need to detach if attach failed. + */ + warnx("attaching module %s", am1->am_modulename); + TAILQ_REMOVE(list, am1, am_list); + if (auditfilter_module_attach(am1) != 0) { + warnx("attaching module %s failed", + am1->am_modulename); + auditfilter_module_free(am1); + } else + TAILQ_INSERT_HEAD(&filter_list, am1, am_list); + } + + if (TAILQ_FIRST(list) != NULL) + warnx("auditfilterd_conf_apply: new list not empty\n"); +} + +/* + * Read the new configuration file into a local list. If the configuration + * file is parsed OK, then apply the changes. + */ +int +auditfilterd_conf(const char *filename, FILE *fp) +{ + struct auditfilter_module_list list; + + TAILQ_INIT(&list); + if (auditfilterd_conf_read(filename, fp, &list) < 0) + return (-1); + + auditfilterd_conf_apply(&list); + + return (0); +} + +/* + * Detach and free all active filter modules for daemon shutdown. + */ +void +auditfilterd_conf_shutdown(void) +{ + + auditfilter_module_list_detach(&filter_list); + auditfilter_module_list_free(&filter_list); +} + +/* + * APIs to allow modules to query and set their per-instance cookie. + */ +void +audit_filter_getcookie(void *instance, void **cookie) +{ + struct auditfilter_module *am; + + am = (struct auditfilter_module *)instance; + *cookie = am->am_cookie; +} + +void +audit_filter_setcookie(void *instance, void *cookie) +{ + struct auditfilter_module *am; + + am = (struct auditfilter_module *)instance; + am->am_cookie = cookie; +} diff --git a/contrib/openbsm/bin/auditreduce/Makefile.am b/contrib/openbsm/bin/auditreduce/Makefile.am new file mode 100644 index 0000000..b5e2433 --- /dev/null +++ b/contrib/openbsm/bin/auditreduce/Makefile.am @@ -0,0 +1,10 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = auditreduce +auditreduce_SOURCES = auditreduce.c +auditreduce_LDADD = $(top_builddir)/libbsm/libbsm.la +man1_MANS = auditreduce.1 diff --git a/contrib/openbsm/bin/auditreduce/Makefile.in b/contrib/openbsm/bin/auditreduce/Makefile.in new file mode 100644 index 0000000..53090e2 --- /dev/null +++ b/contrib/openbsm/bin/auditreduce/Makefile.in @@ -0,0 +1,647 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = auditreduce$(EXEEXT) +subdir = bin/auditreduce +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)" +PROGRAMS = $(sbin_PROGRAMS) +am_auditreduce_OBJECTS = auditreduce.$(OBJEXT) +auditreduce_OBJECTS = $(am_auditreduce_OBJECTS) +auditreduce_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(auditreduce_SOURCES) +DIST_SOURCES = $(auditreduce_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man1_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +auditreduce_SOURCES = auditreduce.c +auditreduce_LDADD = $(top_builddir)/libbsm/libbsm.la +man1_MANS = auditreduce.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/auditreduce/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/auditreduce/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +auditreduce$(EXEEXT): $(auditreduce_OBJECTS) $(auditreduce_DEPENDENCIES) $(EXTRA_auditreduce_DEPENDENCIES) + @rm -f auditreduce$(EXEEXT) + $(LINK) $(auditreduce_OBJECTS) $(auditreduce_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditreduce.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man1_MANS) + @$(NORMAL_INSTALL) + @list1='$(man1_MANS)'; \ + list2=''; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man1 \ + uninstall-sbinPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.1 b/contrib/openbsm/bin/auditreduce/auditreduce.1 new file mode 100644 index 0000000..3266ad9 --- /dev/null +++ b/contrib/openbsm/bin/auditreduce/auditreduce.1 @@ -0,0 +1,195 @@ +.\" Copyright (c) 2004 Apple Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Apple Inc. ("Apple") nor the names of +.\" its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR +.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 24, 2004 +.Dt AUDITREDUCE 1 +.Os +.Sh NAME +.Nm auditreduce +.Nd "select records from audit trail files" +.Sh SYNOPSIS +.Nm +.Op Fl A +.Op Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS +.Op Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS +.Op Fl c Ar flags +.Op Fl d Ar YYYYMMDD +.Op Fl e Ar euid +.Op Fl f Ar egid +.Op Fl g Ar rgid +.Op Fl j Ar id +.Op Fl m Ar event +.Op Fl o Ar object Ns = Ns Ar value +.Op Fl r Ar ruid +.Op Fl u Ar auid +.Op Fl v +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility selects records from the audit trail files based on the specified +criteria. +Matching audit records are printed to the standard output in +their raw binary form. +If no +.Ar file +argument is specified, the standard input is used +by default. +Use the +.Xr praudit 1 +utility to print the selected audit records in human-readable form. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl A +Select all records. +.It Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS +Select records that occurred after or on the given datetime. +.It Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS +Select records that occurred before the given datetime. +.It Fl c Ar flags +Select records matching the given audit classes specified as a comma +separated list of audit flags. +See +.Xr audit_control 5 +for a description of audit flags. +.It Fl d Ar YYYYMMDD +Select records that occurred on a given date. +This option cannot be used with +.Fl a +or +.Fl b . +.It Fl e Ar euid +Select records with the given effective user ID or name. +.It Fl f Ar egid +Select records with the given effective group ID or name. +.It Fl g Ar rgid +Select records with the given real group ID or name. +.It Fl j Ar id +Select records having a subject token with matching ID, where ID is a process ID. +.It Fl m Ar event +Select records with the given event name or number. This option can +be used more then once to select records of multiple event types. +See +.Xr audit_event 5 +for a description of audit event names and numbers. +.It Fl o Ar object Ns = Ns Ar value +.Bl -tag -width ".Cm msgqid" +.It Cm file +Select records containing path tokens, where the pathname matches +one of the comma delimited extended regular expression contained in +given specification. +Regular expressions which are prefixed with a tilde +.Pq Ql ~ +are excluded +from the search results. +These extended regular expressions are processed from left to right, +and a path will either be selected or deslected based on the first match. +.Pp +Since commas are used to delimit the regular expressions, a backslash +.Pq Ql \e +character should be used to escape the comma if it is a part of the search +pattern. +.It Cm msgqid +Select records containing the given message queue ID. +.It Cm pid +Select records containing the given process ID. +.It Cm semid +Select records containing the given semaphore ID. +.It Cm shmid +Select records containing the given shared memory ID. +.El +.It Fl r Ar ruid +Select records with the given real user ID or name. +.It Fl u Ar auid +Select records with the given audit ID. +.It Fl v +Invert sense of matching, to select records that do not match. +.El +.Sh EXAMPLES +To select all records associated with effective user ID root from the audit +log +.Pa /var/audit/20031016184719.20031017122634 : +.Bd -literal -offset indent +auditreduce -e root \e + /var/audit/20031016184719.20031017122634 +.Ed +.Pp +To select all +.Xr setlogin 2 +events from that log: +.Bd -literal -offset indent +auditreduce -m AUE_SETLOGIN \e + /var/audit/20031016184719.20031017122634 +.Ed +.Pp +Output from the above command lines will typically be piped to a new trail +file, or via standard output to the +.Xr praudit 1 +command. +.Pp +Select all records containing a path token where the pathname contains +.Pa /etc/master.passwd : +.Bd -literal -offset indent +auditreduce -o file="/etc/master.passwd" \e + /var/audit/20031016184719.20031017122634 +.Ed +.Pp +Select all records containing path tokens, where the pathname is a TTY +device: +.Bd -literal -offset indent +auditreduce -o file="/dev/tty[a-zA-Z][0-9]+" \e + /var/audit/20031016184719.20031017122634 +.Ed +.Pp +Select all records containing path tokens, where the pathname is a TTY +except for +.Pa /dev/ttyp2 : +.Bd -literal -offset indent +auditreduce -o file="~/dev/ttyp2,/dev/tty[a-zA-Z][0-9]+" \e + /var/audit/20031016184719.20031017122634 +.Ed +.Sh SEE ALSO +.Xr praudit 1 , +.Xr audit_control 5 , +.Xr audit_event 5 +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +.An -nosplit +This software was created by McAfee Research, the security research division +of McAfee, Inc., under contract to Apple Computer Inc. +Additional authors include +.An Wayne Salamon , +.An Robert Watson , +and SPARTA Inc. +.Pp +The Basic Security Module (BSM) interface to audit records and audit event +stream format were defined by Sun Microsystems. diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.c b/contrib/openbsm/bin/auditreduce/auditreduce.c new file mode 100644 index 0000000..f73d341 --- /dev/null +++ b/contrib/openbsm/bin/auditreduce/auditreduce.c @@ -0,0 +1,801 @@ +/*- + * Copyright (c) 2004-2008 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Tool used to merge and select audit records from audit trail files + */ + +/* + * XXX Currently we do not support merging of records from multiple + * XXX audit trail files + * XXX We assume that records are sorted chronologically - both wrt to + * XXX the records present within the file and between the files themselves + */ + +#include <config/config.h> + +#define _GNU_SOURCE /* Required for strptime() on glibc2. */ + +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else +#include <compat/queue.h> +#endif + +#include <bsm/libbsm.h> + +#include <err.h> +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sysexits.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <regex.h> +#include <errno.h> + +#ifndef HAVE_STRLCPY +#include <compat/strlcpy.h> +#endif + +#include "auditreduce.h" + +static TAILQ_HEAD(tailhead, re_entry) re_head = + TAILQ_HEAD_INITIALIZER(re_head); + +extern char *optarg; +extern int optind, optopt, opterr,optreset; + +static au_mask_t maskp; /* Class. */ +static time_t p_atime; /* Created after this time. */ +static time_t p_btime; /* Created before this time. */ +static int p_auid; /* Audit id. */ +static int p_euid; /* Effective user id. */ +static int p_egid; /* Effective group id. */ +static int p_rgid; /* Real group id. */ +static int p_ruid; /* Real user id. */ +static int p_subid; /* Subject id. */ + +/* + * Maintain a dynamically sized array of events for -m + */ +static uint16_t *p_evec; /* Event type list */ +static int p_evec_used; /* Number of events used */ +static int p_evec_alloc; /* Number of events allocated */ + +/* + * Following are the objects (-o option) that we can select upon. + */ +static char *p_fileobj = NULL; +static char *p_msgqobj = NULL; +static char *p_pidobj = NULL; +static char *p_semobj = NULL; +static char *p_shmobj = NULL; +static char *p_sockobj = NULL; + +static uint32_t opttochk = 0; + +static void +parse_regexp(char *re_string) +{ + char *orig, *copy, re_error[64]; + struct re_entry *rep; + int error, nstrs, i, len; + + copy = strdup(re_string); + orig = copy; + len = strlen(copy); + for (nstrs = 0, i = 0; i < len; i++) { + if (copy[i] == ',' && i > 0) { + if (copy[i - 1] == '\\') + strlcpy(©[i - 1], ©[i], len); + else { + nstrs++; + copy[i] = '\0'; + } + } + } + TAILQ_INIT(&re_head); + for (i = 0; i < nstrs + 1; i++) { + rep = calloc(1, sizeof(*rep)); + if (rep == NULL) { + (void) fprintf(stderr, "calloc: %s\n", + strerror(errno)); + exit(1); + } + if (*copy == '~') { + copy++; + rep->re_negate = 1; + } + rep->re_pattern = strdup(copy); + error = regcomp(&rep->re_regexp, rep->re_pattern, + REG_EXTENDED | REG_NOSUB); + if (error != 0) { + regerror(error, &rep->re_regexp, re_error, 64); + (void) fprintf(stderr, "regcomp: %s\n", re_error); + exit(1); + } + TAILQ_INSERT_TAIL(&re_head, rep, re_glue); + len = strlen(copy); + copy += len + 1; + } + free(orig); +} + +static void +usage(const char *msg) +{ + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "Usage: auditreduce [options] [file ...]\n"); + fprintf(stderr, "\tOptions are : \n"); + fprintf(stderr, "\t-A : all records\n"); + fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n"); + fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n"); + fprintf(stderr, "\t-c <flags> : matching class\n"); + fprintf(stderr, "\t-d YYYYMMDD : on date\n"); + fprintf(stderr, "\t-e <uid|name> : effective user\n"); + fprintf(stderr, "\t-f <gid|group> : effective group\n"); + fprintf(stderr, "\t-g <gid|group> : real group\n"); + fprintf(stderr, "\t-j <pid> : subject id \n"); + fprintf(stderr, "\t-m <evno|evname> : matching event\n"); + fprintf(stderr, "\t-o objecttype=objectvalue\n"); + fprintf(stderr, "\t\t file=<pathname>\n"); + fprintf(stderr, "\t\t msgqid=<ID>\n"); + fprintf(stderr, "\t\t pid=<ID>\n"); + fprintf(stderr, "\t\t semid=<ID>\n"); + fprintf(stderr, "\t\t shmid=<ID>\n"); + fprintf(stderr, "\t-r <uid|name> : real user\n"); + fprintf(stderr, "\t-u <uid|name> : audit user\n"); + fprintf(stderr, "\t-v : select non-matching records\n"); + exit(EX_USAGE); +} + +/* + * Check if the given auid matches the selection criteria. + */ +static int +select_auid(int au) +{ + + /* Check if we want to select on auid. */ + if (ISOPTSET(opttochk, OPT_u)) { + if (au != p_auid) + return (0); + } + return (1); +} + +/* + * Check if the given euid matches the selection criteria. + */ +static int +select_euid(int euser) +{ + + /* Check if we want to select on euid. */ + if (ISOPTSET(opttochk, OPT_e)) { + if (euser != p_euid) + return (0); + } + return (1); +} + +/* + * Check if the given egid matches the selection criteria. + */ +static int +select_egid(int egrp) +{ + + /* Check if we want to select on egid. */ + if (ISOPTSET(opttochk, OPT_f)) { + if (egrp != p_egid) + return (0); + } + return (1); +} + +/* + * Check if the given rgid matches the selection criteria. + */ +static int +select_rgid(int grp) +{ + + /* Check if we want to select on rgid. */ + if (ISOPTSET(opttochk, OPT_g)) { + if (grp != p_rgid) + return (0); + } + return (1); +} + +/* + * Check if the given ruid matches the selection criteria. + */ +static int +select_ruid(int user) +{ + + /* Check if we want to select on rgid. */ + if (ISOPTSET(opttochk, OPT_r)) { + if (user != p_ruid) + return (0); + } + return (1); +} + +/* + * Check if the given subject id (pid) matches the selection criteria. + */ +static int +select_subid(int subid) +{ + + /* Check if we want to select on subject uid. */ + if (ISOPTSET(opttochk, OPT_j)) { + if (subid != p_subid) + return (0); + } + return (1); +} + + +/* + * Check if object's pid maches the given pid. + */ +static int +select_pidobj(uint32_t pid) +{ + + if (ISOPTSET(opttochk, OPT_op)) { + if (pid != (uint32_t)strtol(p_pidobj, (char **)NULL, 10)) + return (0); + } + return (1); +} + +/* + * Check if the given ipc object with the given type matches the selection + * criteria. + */ +static int +select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd) +{ + + if (type == AT_IPC_MSG) { + SETOPT((*optchkd), OPT_om); + if (ISOPTSET(opttochk, OPT_om)) { + if (id != (uint32_t)strtol(p_msgqobj, (char **)NULL, + 10)) + return (0); + } + return (1); + } else if (type == AT_IPC_SEM) { + SETOPT((*optchkd), OPT_ose); + if (ISOPTSET(opttochk, OPT_ose)) { + if (id != (uint32_t)strtol(p_semobj, (char **)NULL, 10)) + return (0); + } + return (1); + } else if (type == AT_IPC_SHM) { + SETOPT((*optchkd), OPT_osh); + if (ISOPTSET(opttochk, OPT_osh)) { + if (id != (uint32_t)strtol(p_shmobj, (char **)NULL, 10)) + return (0); + } + return (1); + } + + /* Unknown type -- filter if *any* ipc filtering is required. */ + if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose) + || ISOPTSET(opttochk, OPT_osh)) + return (0); + + return (1); +} + + +/* + * Check if the file name matches selection criteria. + */ +static int +select_filepath(char *path, uint32_t *optchkd) +{ + struct re_entry *rep; + int match; + + SETOPT((*optchkd), OPT_of); + match = 1; + if (ISOPTSET(opttochk, OPT_of)) { + match = 0; + TAILQ_FOREACH(rep, &re_head, re_glue) { + if (regexec(&rep->re_regexp, path, 0, NULL, + 0) != REG_NOMATCH) + return (!rep->re_negate); + } + } + return (match); +} + +/* + * Returns 1 if the following pass the selection rules: + * + * before-time, + * after time, + * date, + * class, + * event + */ +static int +select_hdr32(tokenstr_t tok, uint32_t *optchkd) +{ + uint16_t *ev; + int match; + + SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m | OPT_v)); + + /* The A option overrides a, b and d. */ + if (!ISOPTSET(opttochk, OPT_A)) { + if (ISOPTSET(opttochk, OPT_a)) { + if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) { + /* Record was created before p_atime. */ + return (0); + } + } + + if (ISOPTSET(opttochk, OPT_b)) { + if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) { + /* Record was created after p_btime. */ + return (0); + } + } + } + + if (ISOPTSET(opttochk, OPT_c)) { + /* + * Check if the classes represented by the event matches + * given class. + */ + if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH, + AU_PRS_USECACHE) != 1) + return (0); + } + + /* Check if event matches. */ + if (ISOPTSET(opttochk, OPT_m)) { + match = 0; + for (ev = p_evec; ev < &p_evec[p_evec_used]; ev++) + if (tok.tt.hdr32.e_type == *ev) + match = 1; + if (match == 0) + return (0); + } + + return (1); +} + +static int +select_return32(tokenstr_t tok_ret32, tokenstr_t tok_hdr32, uint32_t *optchkd) +{ + int sorf; + + SETOPT((*optchkd), (OPT_c)); + if (tok_ret32.tt.ret32.status == 0) + sorf = AU_PRS_SUCCESS; + else + sorf = AU_PRS_FAILURE; + if (ISOPTSET(opttochk, OPT_c)) { + if (au_preselect(tok_hdr32.tt.hdr32.e_type, &maskp, sorf, + AU_PRS_USECACHE) != 1) + return (0); + } + return (1); +} + +/* + * Return 1 if checks for the the following succeed + * auid, + * euid, + * egid, + * rgid, + * ruid, + * process id + */ +static int +select_proc32(tokenstr_t tok, uint32_t *optchkd) +{ + + SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op)); + + if (!select_auid(tok.tt.proc32.auid)) + return (0); + if (!select_euid(tok.tt.proc32.euid)) + return (0); + if (!select_egid(tok.tt.proc32.egid)) + return (0); + if (!select_rgid(tok.tt.proc32.rgid)) + return (0); + if (!select_ruid(tok.tt.proc32.ruid)) + return (0); + if (!select_pidobj(tok.tt.proc32.pid)) + return (0); + return (1); +} + +/* + * Return 1 if checks for the the following succeed + * auid, + * euid, + * egid, + * rgid, + * ruid, + * subject id + */ +static int +select_subj32(tokenstr_t tok, uint32_t *optchkd) +{ + + SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j)); + + if (!select_auid(tok.tt.subj32.auid)) + return (0); + if (!select_euid(tok.tt.subj32.euid)) + return (0); + if (!select_egid(tok.tt.subj32.egid)) + return (0); + if (!select_rgid(tok.tt.subj32.rgid)) + return (0); + if (!select_ruid(tok.tt.subj32.ruid)) + return (0); + if (!select_subid(tok.tt.subj32.pid)) + return (0); + return (1); +} + +/* + * Read each record from the audit trail. Check if it is selected after + * passing through each of the options + */ +static int +select_records(FILE *fp) +{ + tokenstr_t tok_hdr32_copy; + u_char *buf; + tokenstr_t tok; + int reclen; + int bytesread; + int selected; + uint32_t optchkd; + int print; + + int err = 0; + while ((reclen = au_read_rec(fp, &buf)) != -1) { + optchkd = 0; + bytesread = 0; + selected = 1; + while ((selected == 1) && (bytesread < reclen)) { + if (-1 == au_fetch_tok(&tok, buf + bytesread, + reclen - bytesread)) { + /* Is this an incomplete record? */ + err = 1; + break; + } + + /* + * For each token type we have have different + * selection criteria. + */ + switch(tok.id) { + case AUT_HEADER32: + selected = select_hdr32(tok, + &optchkd); + bcopy(&tok, &tok_hdr32_copy, + sizeof(tok)); + break; + + case AUT_PROCESS32: + selected = select_proc32(tok, + &optchkd); + break; + + case AUT_SUBJECT32: + selected = select_subj32(tok, + &optchkd); + break; + + case AUT_IPC: + selected = select_ipcobj( + tok.tt.ipc.type, tok.tt.ipc.id, + &optchkd); + break; + + case AUT_PATH: + selected = select_filepath( + tok.tt.path.path, &optchkd); + break; + + case AUT_RETURN32: + selected = select_return32(tok, + tok_hdr32_copy, &optchkd); + break; + + default: + break; + } + bytesread += tok.len; + } + /* Check if all the options were matched. */ + print = ((selected == 1) && (!err) && (!(opttochk & ~optchkd))); + if (ISOPTSET(opttochk, OPT_v)) + print = !print; + if (print) + (void) fwrite(buf, 1, reclen, stdout); + free(buf); + } + return (0); +} + +/* + * The -o option has the form object_type=object_value. Identify the object + * components. + */ +static void +parse_object_type(char *name, char *val) +{ + if (val == NULL) + return; + + if (!strcmp(name, FILEOBJ)) { + p_fileobj = val; + parse_regexp(val); + SETOPT(opttochk, OPT_of); + } else if (!strcmp(name, MSGQIDOBJ)) { + p_msgqobj = val; + SETOPT(opttochk, OPT_om); + } else if (!strcmp(name, PIDOBJ)) { + p_pidobj = val; + SETOPT(opttochk, OPT_op); + } else if (!strcmp(name, SEMIDOBJ)) { + p_semobj = val; + SETOPT(opttochk, OPT_ose); + } else if (!strcmp(name, SHMIDOBJ)) { + p_shmobj = val; + SETOPT(opttochk, OPT_osh); + } else if (!strcmp(name, SOCKOBJ)) { + p_sockobj = val; + SETOPT(opttochk, OPT_oso); + } else + usage("unknown value for -o"); +} + +int +main(int argc, char **argv) +{ + struct group *grp; + struct passwd *pw; + struct tm tm; + au_event_t *n; + FILE *fp; + int i; + char *objval, *converr; + int ch; + char timestr[128]; + char *fname; + uint16_t *etp; + + converr = NULL; + + while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:v")) != -1) { + switch(ch) { + case 'A': + SETOPT(opttochk, OPT_A); + break; + + case 'a': + if (ISOPTSET(opttochk, OPT_a)) { + usage("d is exclusive with a and b"); + } + SETOPT(opttochk, OPT_a); + bzero(&tm, sizeof(tm)); + strptime(optarg, "%Y%m%d%H%M%S", &tm); + strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", + &tm); + /* fprintf(stderr, "Time converted = %s\n", timestr); */ + p_atime = mktime(&tm); + break; + + case 'b': + if (ISOPTSET(opttochk, OPT_b)) { + usage("d is exclusive with a and b"); + } + SETOPT(opttochk, OPT_b); + bzero(&tm, sizeof(tm)); + strptime(optarg, "%Y%m%d%H%M%S", &tm); + strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", + &tm); + /* fprintf(stderr, "Time converted = %s\n", timestr); */ + p_btime = mktime(&tm); + break; + + case 'c': + if (0 != getauditflagsbin(optarg, &maskp)) { + /* Incorrect class */ + usage("Incorrect class"); + } + SETOPT(opttochk, OPT_c); + break; + + case 'd': + if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk, + OPT_a)) + usage("'d' is exclusive with 'a' and 'b'"); + SETOPT(opttochk, OPT_d); + bzero(&tm, sizeof(tm)); + strptime(optarg, "%Y%m%d", &tm); + strftime(timestr, sizeof(timestr), "%Y%m%d", &tm); + /* fprintf(stderr, "Time converted = %s\n", timestr); */ + p_atime = mktime(&tm); + tm.tm_hour = 23; + tm.tm_min = 59; + tm.tm_sec = 59; + strftime(timestr, sizeof(timestr), "%Y%m%d", &tm); + /* fprintf(stderr, "Time converted = %s\n", timestr); */ + p_btime = mktime(&tm); + break; + + case 'e': + p_euid = strtol(optarg, &converr, 10); + if (*converr != '\0') { + /* Try the actual name */ + if ((pw = getpwnam(optarg)) == NULL) + break; + p_euid = pw->pw_uid; + } + SETOPT(opttochk, OPT_e); + break; + + case 'f': + p_egid = strtol(optarg, &converr, 10); + if (*converr != '\0') { + /* Try actual group name. */ + if ((grp = getgrnam(optarg)) == NULL) + break; + p_egid = grp->gr_gid; + } + SETOPT(opttochk, OPT_f); + break; + + case 'g': + p_rgid = strtol(optarg, &converr, 10); + if (*converr != '\0') { + /* Try actual group name. */ + if ((grp = getgrnam(optarg)) == NULL) + break; + p_rgid = grp->gr_gid; + } + SETOPT(opttochk, OPT_g); + break; + + case 'j': + p_subid = strtol(optarg, (char **)NULL, 10); + SETOPT(opttochk, OPT_j); + break; + + case 'm': + if (p_evec == NULL) { + p_evec_alloc = 32; + p_evec = malloc(sizeof(*etp) * p_evec_alloc); + if (p_evec == NULL) + err(1, "malloc"); + } else if (p_evec_alloc == p_evec_used) { + p_evec_alloc <<= 1; + p_evec = realloc(p_evec, + sizeof(*p_evec) * p_evec_alloc); + if (p_evec == NULL) + err(1, "realloc"); + } + etp = &p_evec[p_evec_used++]; + *etp = strtol(optarg, (char **)NULL, 10); + if (*etp == 0) { + /* Could be the string representation. */ + n = getauevnonam(optarg); + if (n == NULL) + usage("Incorrect event name"); + *etp = *n; + } + SETOPT(opttochk, OPT_m); + break; + + case 'o': + objval = strchr(optarg, '='); + if (objval != NULL) { + *objval = '\0'; + objval += 1; + parse_object_type(optarg, objval); + } + break; + + case 'r': + p_ruid = strtol(optarg, &converr, 10); + if (*converr != '\0') { + if ((pw = getpwnam(optarg)) == NULL) + break; + p_ruid = pw->pw_uid; + } + SETOPT(opttochk, OPT_r); + break; + + case 'u': + p_auid = strtol(optarg, &converr, 10); + if (*converr != '\0') { + if ((pw = getpwnam(optarg)) == NULL) + break; + p_auid = pw->pw_uid; + } + SETOPT(opttochk, OPT_u); + break; + + case 'v': + SETOPT(opttochk, OPT_v); + break; + + case '?': + default: + usage("Unknown option"); + } + } + argv += optind; + argc -= optind; + + if (argc == 0) { + if (select_records(stdin) == -1) + errx(EXIT_FAILURE, + "Couldn't select records from stdin"); + exit(EXIT_SUCCESS); + } + + /* + * XXX: We should actually be merging records here. + */ + for (i = 0; i < argc; i++) { + fname = argv[i]; + fp = fopen(fname, "r"); + if (fp == NULL) + errx(EXIT_FAILURE, "Couldn't open %s", fname); + if (select_records(fp) == -1) { + errx(EXIT_FAILURE, "Couldn't select records %s", + fname); + } + fclose(fp); + } + exit(EXIT_SUCCESS); +} diff --git a/contrib/openbsm/bin/auditreduce/auditreduce.h b/contrib/openbsm/bin/auditreduce/auditreduce.h new file mode 100644 index 0000000..655b45d --- /dev/null +++ b/contrib/openbsm/bin/auditreduce/auditreduce.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2004 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AUDITREDUCE_H_ +#define _AUDITREDUCE_H_ + + +struct re_entry { + char *re_pattern; + int re_negate; + regex_t re_regexp; + TAILQ_ENTRY(re_entry) re_glue; +}; + +#define OPT_a 0x00000001 +#define OPT_b 0x00000002 +#define OPT_c 0x00000004 +#define OPT_d (OPT_a | OPT_b) +#define OPT_e 0x00000010 +#define OPT_f 0x00000020 +#define OPT_g 0x00000040 +#define OPT_j 0x00000080 +#define OPT_m 0x00000100 +#define OPT_of 0x00000200 +#define OPT_om 0x00000400 +#define OPT_op 0x00000800 +#define OPT_ose 0x00001000 +#define OPT_osh 0x00002000 +#define OPT_oso 0x00004000 +#define OPT_r 0x00008000 +#define OPT_u 0x00010000 +#define OPT_A 0x00020000 +#define OPT_v 0x00040000 + +#define FILEOBJ "file" +#define MSGQIDOBJ "msgqid" +#define PIDOBJ "pid" +#define SEMIDOBJ "semid" +#define SHMIDOBJ "shmid" +#define SOCKOBJ "sock" + + +#define SETOPT(optmask, bit) (optmask |= bit) +#define ISOPTSET(optmask, bit) (optmask & bit) + + +#endif /* !_AUDITREDUCE_H_ */ diff --git a/contrib/openbsm/bin/praudit/Makefile.am b/contrib/openbsm/bin/praudit/Makefile.am new file mode 100644 index 0000000..4643b7c --- /dev/null +++ b/contrib/openbsm/bin/praudit/Makefile.am @@ -0,0 +1,10 @@ +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +sbin_PROGRAMS = praudit +praudit_SOURCES = praudit.c +praudit_LDADD = $(top_builddir)/libbsm/libbsm.la +man1_MANS = praudit.1 diff --git a/contrib/openbsm/bin/praudit/Makefile.in b/contrib/openbsm/bin/praudit/Makefile.in new file mode 100644 index 0000000..d8469bb --- /dev/null +++ b/contrib/openbsm/bin/praudit/Makefile.in @@ -0,0 +1,647 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = praudit$(EXEEXT) +subdir = bin/praudit +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)" +PROGRAMS = $(sbin_PROGRAMS) +am_praudit_OBJECTS = praudit.$(OBJEXT) +praudit_OBJECTS = $(am_praudit_OBJECTS) +praudit_DEPENDENCIES = $(top_builddir)/libbsm/libbsm.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(praudit_SOURCES) +DIST_SOURCES = $(praudit_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man1_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +praudit_SOURCES = praudit.c +praudit_LDADD = $(top_builddir)/libbsm/libbsm.la +man1_MANS = praudit.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/praudit/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/praudit/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +praudit$(EXEEXT): $(praudit_OBJECTS) $(praudit_DEPENDENCIES) $(EXTRA_praudit_DEPENDENCIES) + @rm -f praudit$(EXEEXT) + $(LINK) $(praudit_OBJECTS) $(praudit_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/praudit.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man1_MANS) + @$(NORMAL_INSTALL) + @list1='$(man1_MANS)'; \ + list2=''; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-man uninstall-man1 \ + uninstall-sbinPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/openbsm/bin/praudit/praudit.1 b/contrib/openbsm/bin/praudit/praudit.1 new file mode 100644 index 0000000..2954ba3 --- /dev/null +++ b/contrib/openbsm/bin/praudit/praudit.1 @@ -0,0 +1,119 @@ +.\" Copyright (c) 2004-2009 Apple Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Apple Inc. ("Apple") nor the names of +.\" its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR +.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 4, 2009 +.Dt PRAUDIT 1 +.Os +.Sh NAME +.Nm praudit +.Nd "print the contents of audit trail files" +.Sh SYNOPSIS +.Nm +.Op Fl lnpx +.Op Fl r | s +.Op Fl d Ar del +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility prints the contents of the audit trail files to the standard output in +human-readable form. +If no +.Ar file +argument is specified, the standard input is used +by default. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar del +Specifies the delimiter. +The default delimiter is the comma. +.It Fl l +Prints the entire record on the same line. +If this option is not specified, +every token is displayed on a different line. +.It Fl n +Do not convert user and group IDs to their names but leave in their +numeric forms. +.It Fl p +Specify this option if input to +.Nm +is piped from the +.Xr tail 1 +utility. +This causes +.Nm +to sync to the start of the next record. +.It Fl r +Prints the records in their raw, numeric form. +This option is exclusive from +.Fl s . +.It Fl s +Prints the tokens in their short form. +Short text representations for +record and event type are displayed. +This option is exclusive from +.Fl r . +.It Fl x +Print audit records in the XML output format. +.El +.Pp +If the raw or short forms are not specified, the default is to print the tokens +in their long form. +Events are displayed as per their descriptions given in +.Pa /etc/security/audit_event ; +UIDs and GIDs are expanded to their names; +dates and times are displayed in human-readable format. +.Sh FILES +.Bl -tag -width ".Pa /etc/security/audit_control" -compact +.It Pa /etc/security/audit_class +Descriptions of audit event classes. +.It Pa /etc/security/audit_event +Descriptions of audit events. +.El +.Sh SEE ALSO +.Xr auditreduce 1 , +.Xr audit 4 , +.Xr auditpipe 4 , +.Xr audit_class 5 , +.Xr audit_event 5 +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +.An -nosplit +This software was created by McAfee Research, the security research division +of McAfee, Inc., under contract to Apple Computer Inc. +Additional authors include +.An Wayne Salamon , +.An Robert Watson , +and SPARTA Inc. +.Pp +The Basic Security Module (BSM) interface to audit records and audit event +stream format were defined by Sun Microsystems. diff --git a/contrib/openbsm/bin/praudit/praudit.c b/contrib/openbsm/bin/praudit/praudit.c new file mode 100644 index 0000000..f795434 --- /dev/null +++ b/contrib/openbsm/bin/praudit/praudit.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2004-2009 Apple Inc. + * Copyright (c) 2006 Martin Voros + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Tool used to parse audit records conforming to the BSM structure. + */ + +/* + * praudit [-lnpx] [-r | -s] [-d del] [file ...] + */ + +#include <bsm/libbsm.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +extern char *optarg; +extern int optind, optopt, opterr,optreset; + +static char *del = ","; /* Default delimiter. */ +static int oneline = 0; +static int partial = 0; +static int oflags = AU_OFLAG_NONE; + +static void +usage(void) +{ + + fprintf(stderr, "usage: praudit [-lnpx] [-r | -s] [-d del] " + "[file ...]\n"); + exit(1); +} + +/* + * Token printing for each token type . + */ +static int +print_tokens(FILE *fp) +{ + u_char *buf; + tokenstr_t tok; + int reclen; + int bytesread; + + /* Allow tail -f | praudit to work. */ + if (partial) { + u_char type = 0; + /* Record must begin with a header token. */ + do { + type = fgetc(fp); + } while(type != AUT_HEADER32); + ungetc(type, fp); + } + + while ((reclen = au_read_rec(fp, &buf)) != -1) { + bytesread = 0; + while (bytesread < reclen) { + /* Is this an incomplete record? */ + if (-1 == au_fetch_tok(&tok, buf + bytesread, + reclen - bytesread)) + break; + au_print_flags_tok(stdout, &tok, del, oflags); + bytesread += tok.len; + if (oneline) { + if (!(oflags & AU_OFLAG_XML)) + printf("%s", del); + } else + printf("\n"); + } + free(buf); + if (oneline) + printf("\n"); + fflush(stdout); + } + return (0); +} + +int +main(int argc, char **argv) +{ + int ch; + int i; + FILE *fp; + + while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) { + switch(ch) { + case 'd': + del = optarg; + break; + + case 'l': + oneline = 1; + break; + + case 'n': + oflags |= AU_OFLAG_NORESOLVE; + break; + + case 'p': + partial = 1; + break; + + case 'r': + if (oflags & AU_OFLAG_SHORT) + usage(); /* Exclusive from shortfrm. */ + oflags |= AU_OFLAG_RAW; + break; + + case 's': + if (oflags & AU_OFLAG_RAW) + usage(); /* Exclusive from raw. */ + oflags |= AU_OFLAG_SHORT; + break; + + case 'x': + oflags |= AU_OFLAG_XML; + break; + + case '?': + default: + usage(); + } + } + + if (oflags & AU_OFLAG_XML) + au_print_xml_header(stdout); + + /* For each of the files passed as arguments dump the contents. */ + if (optind == argc) { + print_tokens(stdin); + return (1); + } + for (i = optind; i < argc; i++) { + fp = fopen(argv[i], "r"); + if ((fp == NULL) || (print_tokens(fp) == -1)) + perror(argv[i]); + if (fp != NULL) + fclose(fp); + } + + if (oflags & AU_OFLAG_XML) + au_print_xml_footer(stdout); + + return (1); +} |