diff options
Diffstat (limited to 'libauditd')
-rw-r--r-- | libauditd/Makefile.am | 17 | ||||
-rw-r--r-- | libauditd/Makefile.in | 474 | ||||
-rw-r--r-- | libauditd/auditd_lib.c | 867 |
3 files changed, 1358 insertions, 0 deletions
diff --git a/libauditd/Makefile.am b/libauditd/Makefile.am new file mode 100644 index 0000000..6fab267 --- /dev/null +++ b/libauditd/Makefile.am @@ -0,0 +1,17 @@ +# +# $P4: //depot/projects/trustedbsd/openbsm/libauditd/Makefile.am#1 $ +# + +if USE_NATIVE_INCLUDES +INCLUDES = -I$(top_builddir) -I$(top_srcdir) +else +INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +endif + +lib_LTLIBRARIES = libauditd.la + +libauditd_la_SOURCES = \ + auditd_lib.c + +#man3_MANS = \ +# libauditd.3 diff --git a/libauditd/Makefile.in b/libauditd/Makefile.in new file mode 100644 index 0000000..561e78f --- /dev/null +++ b/libauditd/Makefile.in @@ -0,0 +1,474 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# $P4: //depot/projects/trustedbsd/openbsm/libauditd/Makefile.in#1 $ +# + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = libauditd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libauditd_la_LIBADD = +am_libauditd_la_OBJECTS = auditd_lib.lo +libauditd_la_OBJECTS = $(am_libauditd_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(top_builddir)/config@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libauditd_la_SOURCES) +DIST_SOURCES = $(libauditd_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MIG = @MIG@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys +@USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) +lib_LTLIBRARIES = libauditd.la +libauditd_la_SOURCES = \ + auditd_lib.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libauditd/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign libauditd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libauditd.la: $(libauditd_la_OBJECTS) $(libauditd_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libauditd_la_OBJECTS) $(libauditd_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auditd_lib.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +#man3_MANS = \ +# libauditd.3 +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libauditd/auditd_lib.c b/libauditd/auditd_lib.c new file mode 100644 index 0000000..d3bee65 --- /dev/null +++ b/libauditd/auditd_lib.c @@ -0,0 +1,867 @@ +/*- + * Copyright (c) 2008 Apple Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#1 $ + */ + +#include <sys/param.h> + +#include <config/config.h> + +#include <sys/dirent.h> +#include <sys/mount.h> +#include <sys/socket.h> +#ifdef HAVE_FULL_QUEUE_H +#include <sys/queue.h> +#else /* !HAVE_FULL_QUEUE_H */ +#include <compat/queue.h> +#endif /* !HAVE_FULL_QUEUE_H */ + +#include <sys/stat.h> +#include <sys/time.h> + +#include <netinet/in.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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <netdb.h> + +#ifdef __APPLE__ +#include <notify.h> +#ifndef __BSM_INTERNAL_NOTIFY_KEY +#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" +#endif /* __BSM_INTERNAL_NOTIFY_KEY */ +#endif /* __APPLE__ */ + +/* + * XXX This is temporary until this is moved to <bsm/audit.h> and shared with + * the kernel. + */ +#ifndef AUDIT_HARD_LIMIT_FREE_BLOCKS +#define AUDIT_HARD_LIMIT_FREE_BLOCKS 4 +#endif + +struct dir_ent { + char *dirname; + uint8_t softlim; + uint8_t hardlim; + TAILQ_ENTRY(dir_ent) dirs; +}; + +static TAILQ_HEAD(, dir_ent) dir_q; +static int minval = -1; + +static char *auditd_errmsg[] = { + "no error", /* ADE_NOERR ( 0) */ + "could not parse audit_control(5) file", /* ADE_PARSE ( 1) */ + "auditon(2) failed", /* ADE_AUDITON ( 2) */ + "malloc(3) failed", /* ADE_NOMEM ( 3) */ + "all audit log directories over soft limit", /* ADE_SOFTLIM ( 4) */ + "all audit log directories over hard limit", /* ADE_HARDLIM ( 5) */ + "could not create file name string", /* ADE_STRERR ( 6) */ + "could not open audit record", /* ADE_AU_OPEN ( 7) */ + "could not close audit record", /* ADE_AU_CLOSE ( 8) */ + "could not set active audit session state", /* ADE_SETAUDIT ( 9) */ + "auditctl(2) failed (trail still swapped)", /* ADE_ACTL (10) */ + "auditctl(2) failed (trail not swapped)", /* ADE_ACTLERR (11) */ + "could not swap audit trail file", /* ADE_SWAPERR (12) */ + "could not rename crash recovery file", /* ADE_RENAME (13) */ + "could not read 'current' link file", /* ADE_READLINK (14) */ + "could not create 'current' link file", /* ADE_SYMLINK (15) */ + "invalid argument", /* ADE_INVAL (16) */ + "could not resolve hostname to address", /* ADE_GETADDR (17) */ + "address family not supported", /* ADE_ADDRFAM (18) */ +}; + +#define MAXERRCODE (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0])) + +#define NA_EVENT_STR_SIZE 25 +#define POL_STR_SIZE 128 + + +/* + * Look up and return the error string for the given audit error code. + */ +const char * +auditd_strerror(int errcode) +{ + int idx = -errcode; + + if (idx < 0 || idx > (int)MAXERRCODE) + return ("Invalid auditd error code"); + + return (auditd_errmsg[idx]); +} + + +/* + * Free our local list of directory names and init list + */ +static void +free_dir_q(void) +{ + struct dir_ent *d1, *d2; + + d1 = TAILQ_FIRST(&dir_q); + while (d1 != NULL) { + d2 = TAILQ_NEXT(d1, dirs); + free(d1->dirname); + free(d1); + d1 = d2; + } + TAILQ_INIT(&dir_q); +} + +/* + * Concat the directory name to the given file name. + * XXX We should affix the hostname also + */ +static char * +affixdir(char *name, struct dir_ent *dirent) +{ + char *fn = NULL; + + /* + * Sanity check on file name. + */ + if (strlen(name) != (FILENAME_LEN - 1)) { + errno = EINVAL; + return (NULL); + } + + asprintf(&fn, "%s/%s", dirent->dirname, name); + return (fn); +} + +/* + * Insert the directory entry in the list by the way they are ordered in + * audit_control(5). Move the entries that are over the soft and hard limits + * toward the tail. + */ +static void +insert_orderly(struct dir_ent *denew) +{ + struct dir_ent *dep; + + TAILQ_FOREACH(dep, &dir_q, dirs) { + if (dep->softlim == 1 && denew->softlim == 0) { + TAILQ_INSERT_BEFORE(dep, denew, dirs); + return; + } + if (dep->hardlim == 1 && denew->hardlim == 0) { + TAILQ_INSERT_BEFORE(dep, denew, dirs); + return; + } + } + TAILQ_INSERT_TAIL(&dir_q, denew, dirs); +} + +/* + * Get the host from audit_control(5) and set it in the audit kernel + * information. Return: + * ADE_NOERR on success. + * ADE_PARSE error parsing audit_control(5). + * ADE_AUDITON error getting/setting auditon(2) value. + * ADE_GETADDR error getting address info for host. + * ADE_ADDRFAM un-supported address family. + */ +int +auditd_set_host(void) +{ + char hoststr[MAXHOSTNAMELEN]; + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + struct addrinfo *res; + struct auditinfo_addr aia; + int error, ret = ADE_NOERR; + + if (getachost(hoststr, MAXHOSTNAMELEN) != 0) { + + ret = ADE_PARSE; + + /* + * To maintain reverse compatability with older audit_control + * files, simply drop a warning if the host parameter has not + * been set. However, we will explicitly disable the + * generation of extended audit header by passing in a zeroed + * termid structure. + */ + bzero(&aia, sizeof(aia)); + aia.ai_termid.at_type = AU_IPv4; + error = auditon(A_SETKAUDIT, &aia, sizeof(aia)); + if (error < 0 && errno != ENOSYS) + ret = ADE_AUDITON; + return (ret); + } + error = getaddrinfo(hoststr, NULL, NULL, &res); + if (error) + return (ADE_GETADDR); + switch (res->ai_family) { + case PF_INET6: + sin6 = (struct sockaddr_in6 *) res->ai_addr; + bcopy(&sin6->sin6_addr.s6_addr, + &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); + aia.ai_termid.at_type = AU_IPv6; + break; + + case PF_INET: + sin = (struct sockaddr_in *) res->ai_addr; + bcopy(&sin->sin_addr.s_addr, + &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); + aia.ai_termid.at_type = AU_IPv4; + break; + + default: + /* Un-supported address family in host parameter. */ + errno = EAFNOSUPPORT; + return (ADE_ADDRFAM); + } + + if (auditon(A_SETKAUDIT, &aia, sizeof(aia)) < 0) + ret = ADE_AUDITON; + + return (ret); +} + +/* + * Get the min percentage of free blocks from audit_control(5) and that + * value in the kernel. Return: + * ADE_NOERR on success, + * ADE_PARSE error parsing audit_control(5), + * ADE_AUDITON error getting/setting auditon(2) value. + */ +int +auditd_set_minfree(void) +{ + au_qctrl_t qctrl; + + if (getacmin(&minval) != 0) + return (ADE_PARSE); + + if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) + return (ADE_AUDITON); + + if (qctrl.aq_minfree != minval) { + qctrl.aq_minfree = minval; + if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) + return (ADE_AUDITON); + } + + return (0); +} + +/* + * Parses the "dir" entry in audit_control(5) into an ordered list. Also, will + * set the minfree value if not already set. Arguments include function + * pointers to audit_warn functions for soft and hard limits. Returns: + * ADE_NOERR on success, + * ADE_PARSE error parsing audit_control(5), + * ADE_AUDITON error getting/setting auditon(2) value, + * ADE_NOMEM error allocating memory, + * ADE_SOFTLIM if all the directories are over the soft limit, + * ADE_HARDLIM if all the directories are over the hard limit, + */ +int +auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *)) +{ + char cur_dir[MAXNAMLEN]; + struct dir_ent *dirent; + struct statfs sfs; + int err; + char soft, hard; + int tcnt = 0; + int scnt = 0; + int hcnt = 0; + + if (minval == -1 && (err = auditd_set_minfree()) != 0) + return (err); + + /* + * Init directory q. Force a re-read of the file the next time. + */ + free_dir_q(); + endac(); + + /* + * Read the list of directories into an ordered linked list + * admin's preference, then those over soft limit and, finally, + * those over the hard limit. + * + * XXX We should use the reentrant interfaces once they are + * available. + */ + while (getacdir(cur_dir, MAXNAMLEN) >= 0) { + if (statfs(cur_dir, &sfs) < 0) + continue; /* XXX should warn */ + soft = (sfs.f_bfree < (sfs.f_blocks / (100 / minval))) ? 1 : 0; + hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0; + if (soft) { + if (warn_soft) + (*warn_soft)(cur_dir); + scnt++; + } + if (hard) { + if (warn_hard) + (*warn_hard)(cur_dir); + hcnt++; + } + dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); + if (dirent == NULL) + return (ADE_NOMEM); + dirent->softlim = soft; + dirent->hardlim = hard; + dirent->dirname = (char *) malloc(MAXNAMLEN); + if (dirent->dirname == NULL) { + free(dirent); + return (ADE_NOMEM); + } + strlcpy(dirent->dirname, cur_dir, MAXNAMLEN); + insert_orderly(dirent); + tcnt++; + } + + if (hcnt == tcnt) + return (ADE_HARDLIM); + if (scnt == tcnt) + return (ADE_SOFTLIM); + return (0); +} + +void +auditd_close_dirs(void) +{ + free_dir_q(); + minval = -1; +} + + +/* + * Process the audit event file, obtaining a class mapping for each event, and + * set that mapping into the kernel. Return: + * n number of event mappings that were successfully processed, + * ADE_NOMEM if there was an error allocating memory. + */ +int +auditd_set_evcmap(void) +{ + au_event_ent_t ev, *evp; + au_evclass_map_t evc_map; + int ctr = 0; + + + /* + * XXX There's a risk here that the BSM library will return NULL + * for an event when it can't properly map it to a class. In that + * case, we will not process any events beyond the one that failed, + * but should. We need a way to get a count of the events. + */ + ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); + ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); + if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) { + if (ev.ae_name != NULL) + free(ev.ae_name); + return (ADE_NOMEM); + } + + /* + * XXXRW: Currently we have no way to remove mappings from the kernel + * when they are removed from the file-based mappings. + */ + evp = &ev; + setauevent(); + while ((evp = getauevent_r(evp)) != NULL) { + evc_map.ec_number = evp->ae_number; + evc_map.ec_class = evp->ae_class; + if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) + == 0) + ctr++; + } + endauevent(); + free(ev.ae_name); + free(ev.ae_desc); + + return (ctr); +} + +/* + * Get the non-attributable event string and set the kernel mask. Return: + * ADE_NOERR on success, + * ADE_PARSE error parsing audit_control(5), + * ADE_AUDITON error setting the mask using auditon(2). + */ +int +auditd_set_namask(void) +{ + au_mask_t aumask; + char naeventstr[NA_EVENT_STR_SIZE]; + + if ((getacna(naeventstr, NA_EVENT_STR_SIZE) != 0) || + (getauditflagsbin(naeventstr, &aumask) != 0)) + return (ADE_PARSE); + + if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))) + return (ADE_AUDITON); + + return (ADE_NOERR); +} + +/* + * Set the audit control policy if a policy is configured in audit_control(5), + * implement the policy. However, if one isn't defined or if there is an error + * parsing the control file, set AUDIT_CNT to avoid leaving the system in a + * fragile state. Return: + * ADE_NOERR on success, + * ADE_PARSE error parsing audit_control(5), + * ADE_AUDITON error setting policy using auditon(2). + */ +int +auditd_set_policy(void) +{ + long policy; + char polstr[POL_STR_SIZE]; + + if ((getacpol(polstr, POL_STR_SIZE) != 0) || + (au_strtopol(polstr, &policy) != 0)) { + policy = AUDIT_CNT; + if (auditon(A_SETPOLICY, &policy, sizeof(policy))) + return (ADE_AUDITON); + return (ADE_PARSE); + } + + if (auditon(A_SETPOLICY, &policy, sizeof(policy))) + return (ADE_AUDITON); + + return (ADE_NOERR); +} + +/* + * Set trail rotation size. Return: + * ADE_NOERR on success, + * ADE_PARSE error parsing audit_control(5), + * ADE_AUDITON error setting file size using auditon(2). + */ +int +auditd_set_fsize(void) +{ + size_t filesz; + au_fstat_t au_fstat; + + /* + * Set trail rotation size. + */ + if (getacfilesz(&filesz) != 0) + return (ADE_PARSE); + + bzero(&au_fstat, sizeof(au_fstat)); + au_fstat.af_filesz = filesz; + if (auditon(A_SETFSIZE, &au_fstat, sizeof(au_fstat)) < 0) + return (ADE_AUDITON); + + return (ADE_NOERR); +} + +/* + * Create the new audit file with appropriate permissions and ownership. Try + * to clean up if something goes wrong. + */ +static int +open_trail(char *fname, gid_t gid) +{ + int error, fd; + + fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP); + if (fd < 0) + return (-1); + if (fchown(fd, -1, gid) < 0) { + error = errno; + close(fd); + (void)unlink(fname); + errno = error; + return (-1); + } + return (fd); +} + +/* + * Create the new audit trail file, swap with existing audit file. Arguments + * include timestamp for the filename, a pointer to a string for returning the + * new file name, GID for trail file, and audit_warn function pointer for + * 'getacdir()' errors. Returns: + * ADE_NOERR on success, + * ADE_STRERR if the file name string could not be created, + * ADE_SWAPERR if the audit trail file could not be swapped, + * ADE_ACTL if the auditctl(2) call failed but file swap still + * successful. + * ADE_ACTLERR if the auditctl(2) call failed and file swap failed. + * ADE_SYMLINK if symlink(2) failed updating the current link. + */ +int +auditd_swap_trail(char *TS, char **newfile, gid_t gid, + int (*warn_getacdir)(char *)) +{ + char timestr[FILENAME_LEN]; + char *fn; + struct dir_ent *dirent; + int fd; + int error; + int saverrno = 0; + + if (strlen(TS) != (TIMESTAMP_LEN - 1) || + snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED) < 0) { + errno = EINVAL; + return (ADE_STRERR); + } + + /* Try until we succeed. */ + while ((dirent = TAILQ_FIRST(&dir_q))) { + if (dirent->hardlim) + continue; + if ((fn = affixdir(timestr, dirent)) == NULL) + return (ADE_STRERR); + + /* + * Create and open the file; then close and pass to the + * kernel if all went well. + */ + fd = open_trail(fn, gid); + if (fd >= 0) { + error = auditctl(fn); + if (error) { + /* + * auditctl failed setting log file. + * Try again. + */ + saverrno = errno; + close(fd); + } else { + /* Success. */ + *newfile = fn; + close(fd); + if (error) + return (error); + if (saverrno) { + /* + * auditctl() failed but still + * successful. Return errno and "soft" + * error. + */ + errno = saverrno; + return (ADE_ACTL); + } + return (ADE_NOERR); + } + } + + /* + * Tell the administrator about lack of permissions for dir. + */ + if (warn_getacdir != NULL) + (*warn_getacdir)(dirent->dirname); + } + if (saverrno) { + errno = saverrno; + return (ADE_ACTLERR); + } else + return (ADE_SWAPERR); +} + +/* + * Mask calling process from being audited. Returns: + * ADE_NOERR on success, + * ADE_SETAUDIT if setaudit(2) fails. + */ +int +auditd_prevent_audit(void) +{ + auditinfo_t ai; + + /* + * To prevent event feedback cycles and avoid audit becoming stalled if + * auditing is suspended we mask this processes events from being + * audited. We allow the uid, tid, and mask fields to be implicitly + * set to zero, but do set the audit session ID to the PID. + * + * XXXRW: Is there more to it than this? + */ + bzero(&ai, sizeof(ai)); + ai.ai_asid = getpid(); + if (setaudit(&ai) != 0) + return (ADE_SETAUDIT); + return (ADE_NOERR); +} + +/* + * Generate and submit audit record for audit startup or shutdown. The event + * argument can be AUE_audit_recovery, AUE_audit_startup or + * AUE_audit_shutdown. The path argument will add a path token, if not NULL. + * Returns: + * AUE_NOERR on success, + * ADE_NOMEM if memory allocation fails, + * ADE_AU_OPEN if au_open(3) fails, + * ADE_AU_CLOSE if au_close(3) fails. + */ +int +auditd_gen_record(int event, char *path) +{ + int aufd; + uid_t uid; + pid_t pid; + char *autext = NULL; + token_t *tok; + struct auditinfo_addr aia; + + if (event == AUE_audit_startup) + asprintf(&autext, "%s::Audit startup", getprogname()); + else if (event == AUE_audit_shutdown) + asprintf(&autext, "%s::Audit shutdown", getprogname()); + else if (event == AUE_audit_recovery) + asprintf(&autext, "%s::Audit recovery", getprogname()); + else + return (ADE_INVAL); + if (autext == NULL) + return (ADE_NOMEM); + + if ((aufd = au_open()) == -1) { + free(autext); + return (ADE_AU_OPEN); + } + bzero(&aia, sizeof(aia)); + uid = getuid(); pid = getpid(); + if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(), + pid, pid, &aia.ai_termid)) != NULL) + au_write(aufd, tok); + if ((tok = au_to_text(autext)) != NULL) + au_write(aufd, tok); + free(autext); + if (path != NULL && (tok = au_to_path(path)) != NULL) + au_write(aufd, tok); + if ((tok = au_to_return32(0, 0)) != NULL) + au_write(aufd, tok); + if (au_close(aufd, 1, event) == -1) + return (ADE_AU_CLOSE); + + return (ADE_NOERR); +} + +/* + * Check for a 'current' symlink and do crash recovery, if needed. Create a new + * 'current' symlink. The argument 'curfile' is the file the 'current' symlink + * should point to. Returns: + * ADE_NOERR on success, + * ADE_AU_OPEN if au_open(3) fails, + * ADE_AU_CLOSE if au_close(3) fails. + * ADE_RENAME if error renaming audit trail file, + * ADE_READLINK if error reading the 'current' link, + * ADE_SYMLINK if error creating 'current' link. + */ +int +auditd_new_curlink(char *curfile) +{ + int len, err; + char *ptr; + char *path = NULL; + struct stat sb; + char recoveredname[MAXPATHLEN]; + char newname[MAXPATHLEN]; + + /* + * Check to see if audit was shutdown properly. If not, clean up, + * recover previous audit trail file, and generate audit record. + */ + len = readlink(AUDIT_CURRENT_LINK, recoveredname, MAXPATHLEN - 1); + if (len > 0) { + /* 'current' exist but is it pointing at a valid file? */ + recoveredname[len++] = '\0'; + if (stat(recoveredname, &sb) == 0) { + /* Yes, rename it to a crash recovery file. */ + strlcpy(newname, recoveredname, MAXPATHLEN); + + if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { + strlcpy(ptr, CRASH_RECOVERY, TIMESTAMP_LEN); + if (rename(recoveredname, newname) != 0) + return (ADE_RENAME); + } else + return (ADE_STRERR); + + path = newname; + } + + /* 'current' symlink is (now) invalid so remove it. */ + (void) unlink(AUDIT_CURRENT_LINK); + + /* Note the crash recovery in current audit trail */ + err = auditd_gen_record(AUE_audit_recovery, path); + if (err) + return (err); + } + + if (len < 0 && errno != ENOENT) + return (ADE_READLINK); + + if (symlink(curfile, AUDIT_CURRENT_LINK) != 0) + return (ADE_SYMLINK); + + return (0); +} + +/* + * Do just what we need to quickly start auditing. Assume no system logging or + * notify. Return: + * 0 on success, + * -1 on failure. + */ +int +audit_quick_start(void) +{ + int err; + char *newfile; + time_t tt; + char TS[TIMESTAMP_LEN]; + + /* + * Mask auditing of this process. + */ + if (auditd_prevent_audit() != 0) + return (-1); + + /* + * Read audit_control and get log directories. + */ + err = auditd_read_dirs(NULL, NULL); + if (err != ADE_NOERR && err != ADE_SOFTLIM) + return (-1); + + /* + * Create a new audit trail log. + */ + if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) + return (-1); + err = auditd_swap_trail(TS, &newfile, getgid(), NULL); + if (err != ADE_NOERR && err != ADE_ACTL) + return (-1); + + /* + * Add the current symlink and recover from crash, if needed. + */ + if (auditd_new_curlink(newfile) != 0) + return(-1); + + /* + * At this point auditing has started so generate audit start-up record. + */ + if (auditd_gen_record(AUE_audit_startup, NULL) != 0) + return (-1); + + /* + * Configure the audit controls. + */ + (void) auditd_set_evcmap(); + (void) auditd_set_namask(); + (void) auditd_set_policy(); + (void) auditd_set_fsize(); + (void) auditd_set_minfree(); + (void) auditd_set_host(); + + return (0); +} + +/* + * Shut down auditing quickly. Assumes that is only called on system shutdown. + * Returns: + * 0 on success, + * -1 on failure. + */ +int +audit_quick_stop(void) +{ + int len; + long cond; + char *ptr; + time_t tt; + char oldname[MAXPATHLEN]; + char newname[MAXPATHLEN]; + char TS[TIMESTAMP_LEN]; + + /* + * Auditing already disabled? + */ + if (auditon(A_GETCOND, &cond, sizeof(cond)) < 0) + return (-1); + if (cond == AUC_DISABLED) + return (0); + + /* + * Generate audit shutdown record. + */ + (void) auditd_gen_record(AUE_audit_shutdown, NULL); + + /* + * Shutdown auditing in the kernel. + */ + cond = AUC_DISABLED; + if (auditon(A_SETCOND, &cond, sizeof(cond)) != 0) + return (-1); +#ifdef __BSM_INTERNAL_NOTIFY_KEY + notify_post(__BSM_INTERNAL_NOTIFY_KEY); +#endif + + /* + * Rename last audit trail and remove 'current' link. + */ + len = readlink(AUDIT_CURRENT_LINK, oldname, MAXPATHLEN - 1); + if (len < 0) + return (-1); + oldname[len++] = '\0'; + + if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) + return (-1); + + strlcpy(newname, oldname, len); + + if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { + strlcpy(ptr, TS, TIMESTAMP_LEN); + if (rename(oldname, newname) != 0) + return (-1); + } else + return (-1); + + (void) unlink(AUDIT_CURRENT_LINK); + + return (0); +} |