summaryrefslogtreecommitdiffstats
path: root/contrib/openbsm/libbsm
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-01-31 19:40:12 +0000
committerrwatson <rwatson@FreeBSD.org>2006-01-31 19:40:12 +0000
commit3fdf6fa244dacc3457a4a9e0e97f27ef50422fe1 (patch)
treec4e450cb39e9c6a30103f365387470a9c9566bca /contrib/openbsm/libbsm
downloadFreeBSD-src-3fdf6fa244dacc3457a4a9e0e97f27ef50422fe1.zip
FreeBSD-src-3fdf6fa244dacc3457a4a9e0e97f27ef50422fe1.tar.gz
Initial vendor import of the TrustedBSD OpenBSM distribution, version
1.0 alpha 1, an implementation of the documented Sun Basic Security Module (BSM) Audit API and file format, as well as local extensions to support the Mac OS X and FreeBSD operating systems. Also included are command line tools for audit trail reduction and conversion to text, as well as documentation of the commands, file format, and APIs. This distribution is the foundation for the TrustedBSD Audit implementation, and is a pre-release. This is the first in a series of commits to introduce support for Common Criteria CAPP security event audit support. This software has been made possible through the generous contributions of Apple Computer, Inc., SPARTA, Inc., as well as members of the TrustedBSD Project, including Wayne Salamon <wsalamon> and Tom Rhodes <trhodes>. The original OpenBSM implementation was created by McAfee Research under contract to Apple Computer, Inc., as part of their CC CAPP security evaluation. Many thanks to: wsalamon, trhodes Obtained from: TrustedBSD Project
Diffstat (limited to 'contrib/openbsm/libbsm')
-rw-r--r--contrib/openbsm/libbsm/Makefile119
-rw-r--r--contrib/openbsm/libbsm/au_class.3108
-rw-r--r--contrib/openbsm/libbsm/au_control.3136
-rw-r--r--contrib/openbsm/libbsm/au_event.3153
-rw-r--r--contrib/openbsm/libbsm/au_free_token.391
-rw-r--r--contrib/openbsm/libbsm/au_io.3119
-rw-r--r--contrib/openbsm/libbsm/au_mask.3140
-rw-r--r--contrib/openbsm/libbsm/au_token.3209
-rw-r--r--contrib/openbsm/libbsm/au_user.3136
-rw-r--r--contrib/openbsm/libbsm/bsm_audit.c354
-rw-r--r--contrib/openbsm/libbsm/bsm_class.c267
-rw-r--r--contrib/openbsm/libbsm/bsm_control.c275
-rw-r--r--contrib/openbsm/libbsm/bsm_event.c327
-rw-r--r--contrib/openbsm/libbsm/bsm_flags.c176
-rw-r--r--contrib/openbsm/libbsm/bsm_io.c2831
-rw-r--r--contrib/openbsm/libbsm/bsm_mask.c194
-rw-r--r--contrib/openbsm/libbsm/bsm_notify.c149
-rw-r--r--contrib/openbsm/libbsm/bsm_token.c1219
-rw-r--r--contrib/openbsm/libbsm/bsm_user.c268
-rw-r--r--contrib/openbsm/libbsm/bsm_wrappers.c322
-rw-r--r--contrib/openbsm/libbsm/libbsm.3220
21 files changed, 7813 insertions, 0 deletions
diff --git a/contrib/openbsm/libbsm/Makefile b/contrib/openbsm/libbsm/Makefile
new file mode 100644
index 0000000..4137f4a
--- /dev/null
+++ b/contrib/openbsm/libbsm/Makefile
@@ -0,0 +1,119 @@
+#
+# OpenBSM libbsm
+#
+# $P4: //depot/projects/trustedbsd/openbsm/libbsm/Makefile#11 $
+#
+
+LIB= bsm
+SHLIB_MAJOR= 1
+
+CFLAGS+=-I- \
+ -I .. \
+ -Wall
+
+SRCS= bsm_audit.c \
+ bsm_class.c \
+ bsm_control.c \
+ bsm_event.c \
+ bsm_flags.c \
+ bsm_io.c \
+ bsm_mask.c \
+ bsm_notify.c \
+ bsm_token.c \
+ bsm_user.c \
+ bsm_wrappers.c
+
+MAN= libbsm.3 \
+ au_class.3 \
+ au_control.3 \
+ au_event.3 \
+ au_free_token.3 \
+ au_io.3 \
+ au_mask.3 \
+ au_token.3 \
+ au_user.3
+
+MLINKS= libbsm.3 bsm.3 \
+ au_class.3 getauclassent.3 \
+ au_class.3 getauclassnam.3 \
+ au_class.3 setauclass.3 \
+ au_class.3 endauclass.3 \
+ au_control.3 setac.3 \
+ au_control.3 endac.3 \
+ au_control.3 getacdir.3 \
+ au_control.3 getacmin.3 \
+ au_control.3 getacflg.3 \
+ au_control.3 getacna.3 \
+ au_event.3 setauevent.3 \
+ au_event.3 endauevent.3 \
+ au_event.3 getauevent.3 \
+ au_event.3 getauevnam.3 \
+ au_event.3 getauevnum.3 \
+ au_event.3 getauevnonam.3 \
+ au_io.3 au_fetch_tok.3 \
+ au_io.3 au_print_tok.3 \
+ au_io.3 au_read_rec.3 \
+ au_mask.3 au_preselect.3 \
+ au_mask.3 getauditflagsbin.3 \
+ au_mask.3 getauditflagschar.3 \
+ au_user.3 setauuser.3 \
+ au_user.3 endauuser.3 \
+ au_user.3 getauuserent.3 \
+ au_user.3 getauusernam.3 \
+ au_user.3 au_user_mask.3 \
+ au_user.3 getfauditflags.3 \
+ au_token.3 au_to_arg32.3 \
+ au_token.3 au_to_arg64.3 \
+ au_token.3 au_to_arg.3 \
+ au_token.3 au_to_attr64.3 \
+ au_token.3 au_to_data.3 \
+ au_token.3 au_to_exit.3 \
+ au_token.3 au_to_groups.3 \
+ au_token.3 au_to_newgroups.3 \
+ au_token.3 au_to_in_addr.3 \
+ au_token.3 au_to_in_addr_ex.3 \
+ au_token.3 au_to_ip.3 \
+ au_token.3 au_to_ipc.3 \
+ au_token.3 au_to_ipc_perm.3 \
+ au_token.3 au_to_iport.3 \
+ au_token.3 au_to_opaque.3 \
+ au_token.3 au_to_file.3 \
+ au_token.3 au_to_text.3 \
+ au_token.3 au_to_path.3 \
+ au_token.3 au_to_process32.3 \
+ au_token.3 au_to_process64.3 \
+ au_token.3 au_to_process.3 \
+ au_token.3 au_to_process32_ex.3 \
+ au_token.3 au_to_process64_ex.3 \
+ au_token.3 au_to_process_ex.3 \
+ au_token.3 au_to_return32.3 \
+ au_token.3 au_to_return64.3 \
+ au_token.3 au_to_return.3 \
+ au_token.3 au_to_seq.3 \
+ au_token.3 au_to_socket.3 \
+ au_token.3 au_to_socket_ex_32.3 \
+ au_token.3 au_to_socket_ex_128.3 \
+ au_token.3 au_to_sock_inet32.3 \
+ au_token.3 au_to_sock_inet128.3 \
+ au_token.3 au_to_sock_inet.3 \
+ au_token.3 au_to_subject32.3 \
+ au_token.3 au_to_subject64.3 \
+ au_token.3 au_to_subject.3 \
+ au_token.3 au_to_subject32_ex.3 \
+ au_token.3 au_to_subject64_ex.3 \
+ au_token.3 au_to_subject_ex.3 \
+ au_token.3 au_to_me.3 \
+ au_token.3 au_to_exec_args.3 \
+ au_token.3 au_to_exec_env.3 \
+ au_token.3 au_to_header.3 \
+ au_token.3 au_to_header32.3 \
+ au_token.3 au_to_header64.3 \
+ au_token.3 au_to_trailer.3
+
+beforeinstall:
+ if test -d ${INCSDIR}; then \
+ else \
+ mkdir ${INCSDIR}; \
+ fi;
+
+.include <bsd.lib.mk>
diff --git a/contrib/openbsm/libbsm/au_class.3 b/contrib/openbsm/libbsm/au_class.3
new file mode 100644
index 0000000..f1cd9e9
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_class.3
@@ -0,0 +1,108 @@
+.\"-
+.\" Copyright (c) 2005-2006 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_class.3#3 $
+.\"
+.Dd April 19, 2005
+.Dt AU_CLASS 3
+.Os
+.Sh NAME
+.Nm getauclassent ,
+.Nm getauclassent_r ,
+.Nm getauclassnam ,
+.Nm getauclassnam_r ,
+.Nm setauclass ,
+.Nm endauclass
+.Nd "Look up information from the audit_class database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft struct au_class_ent *
+.Fn getauclassent "void"
+.Ft struct au_class_ent *
+.Fn getauclassent_r "struct au_class_ent *e"
+.Ft struct au_class_ent *
+.Fn getauclassnam "const char *name"
+.Ft struct au_class_ent *
+.Fn getauclassnam_r "struct au_class_ent *e" "const char *name"
+.Ft void
+.Fn setauclass "void"
+.Ft void
+.Fn endauclass "void"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_class 5
+database, which describes audit event classes.
+Audit event classes are described by
+.Vt struct au_class_ent .
+.Pp
+.Pp
+.Fn getauclassent
+will return the next class found in the
+.Xr audit_class 5
+database, or the first if the function has not yet been called.
+.Dv NULL
+will be returned if no further records are available.
+.Pp
+.Fn getauclassnam
+looks up a class by name.
+.Dv NULL
+will be returned if no matching class can be found.
+.Pp
+.Fn setauclass
+resets the iterator through the
+.Xr audit_class 5
+database, causing the next call to
+.Fn getauclassent
+to start again from the beginning of the file.
+.Pp
+.Fn endauclass
+closes the
+.Xr audit_class 5
+database, if open.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_class 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
diff --git a/contrib/openbsm/libbsm/au_control.3 b/contrib/openbsm/libbsm/au_control.3
new file mode 100644
index 0000000..915c521
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_control.3
@@ -0,0 +1,136 @@
+.\"-
+.\" Copyright (c) 2005 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_control.3#2 $
+.\"
+.Dd April 19, 2005
+.Dt AU_CONTROL 3
+.Os
+.Sh NAME
+.Nm setac ,
+.Nm endac ,
+.Nm getacdir ,
+.Nm getacmin ,
+.Nm getacflg ,
+.Nm getacna
+.Nd "Look up information from the audit_control database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft void
+.Fn setac "void"
+.Ft void
+.Fn endac "void"
+.Ft int
+.Fn getacdir "char *name" "int len"
+.Ft int
+.Fn getacmin "int *min_val"
+.Ft int
+.Fn getacflg "char *auditstr" "int len"
+.Ft int
+.Fn getacna "char *auditstr" "int len"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_control 5
+database, which contains various audit-related administrative parameters.
+.Pp
+.Fn setac
+resets the database iterator to the beginning of the database; see the
+BUGS section for more information.
+.Pp
+.Fn sendac
+closes the
+.Xr audit_control 5
+database.
+.Pp
+.Fn getacdir
+Return the name of the directory where log data is stored via the passed
+character buffer
+.Va name
+of length
+.Va len .
+.Pp
+.Fn getacmin
+returns the minimum free disk space for the audit log target file system via
+the passed
+.Va min_val
+variable.
+.Pp
+.Fn getacflg
+returns the audit system flags via the the passed character buffer
+.Va auditstr
+of length
+.Va len .
+.Pp
+.Fn getacna
+returns the non-attributable flags via the passed character buffer
+.Va auditstr
+of length
+.Va len .
+.Sh RETURN VALULES
+.Fn getacdir ,
+.Fn getacmin ,
+.Fn getacflg ,
+and
+.Fn getacna
+return 0 on success, or a negative value on failure, along with error
+information in
+.Va errno .
+Functions that return a string value will return a failure if there is
+insufficient room in the passed character buffer for the full string.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_control 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
+.Sh BUGS
+There is no reason for the
+.Fn setac
+interface to be exposed as part of the public API, as it is called implicitly
+by other access functions and iteration is not supported.
+.Pp
+These interfaces inconsistently return various negative values depending on
+the failure mode, and do not always set
+.Va errno
+on failure.
diff --git a/contrib/openbsm/libbsm/au_event.3 b/contrib/openbsm/libbsm/au_event.3
new file mode 100644
index 0000000..bd021de
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_event.3
@@ -0,0 +1,153 @@
+.\"-
+.\" Copyright (c) 2005-2006 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_event.3#3 $
+.\"
+.Dd April 19, 2005
+.Dt AU_EVENT 3
+.Os
+.Sh NAME
+.Nm free_au_event_ent ,
+.Nm setauevent ,
+.Nm endauevent ,
+.Nm getauevent ,
+.Nm getauevent_r ,
+.Nm getauevnam ,
+.Nm getauevnam_r ,
+.Nm getauevnum ,
+.Nm getauevnum_r ,
+.Nm getauevnonam ,
+.Nm getauevnonam_r ,
+.Nd "Look up information from the audit_event database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft void
+.Fn setauevent "void"
+.Ft void
+.Fn endauevent "void"
+.Ft "struct au_event_ent *"
+.Fn getauevent "void"
+.Ft "struct au_event_ent *"
+.Fn getauevent_r "struct au_event_ent *e"
+.Ft "struct au_event_ent *"
+.Fn getauevnam "char *name"
+.Ft "struct au_event_ent *"
+.Fn getauevnam_r "struct au_event_ent *e" "char *name"
+.Ft "struct au_event_ent *"
+.Fn getauevnum "au_event_t event_number"
+.Ft "struct au_event_ent *"
+.Fn getauevnum_r "struct au_event_ent *e" "au_event_t event_number"
+.Ft "au_event_t *"
+.Fn getauevnonam "char *event_name"
+.Ft "au_event_t *"
+.Fn getauevnonam_r "au_event_t *ev" "char *event_name"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_event 5
+database, which describes audit events.
+Entries in the database are described by
+.Vt struct au_event_ent
+entries, which are returned by calls to
+.Fn getauevent ,
+.Fn getauevnam ,
+or
+.Fn getauevnum .
+It is also possible look up an event number via a call to
+.Nm getauevnonam .
+.Pp
+.Fn setauevent
+resets the database access session for
+.Xr audit_event 5 ,
+so that the next call to
+.Fn getauevent
+will start with the first entry in the database.
+.Pp
+.Fn endauevent
+closes the
+.Xr audit_event 5
+database session.
+.Pp
+.Fn getauevent
+returns a reference to the next entry in the
+.Xr audit_event 5
+database.
+.Pp
+.Fn getauevnam
+returns a reference to the entry in the
+.Xr audit_event 5
+database with a name of
+.Va name .
+.Pp
+.Fn getauevnum
+returns a reference to the entry in the
+.Xr audit_event 5
+database with an event number of
+.Va event_number .
+.Pp
+.Fn getauevnonam
+returns a reference to an audit event number using the
+.Xr audit_event 5
+database.
+.Sh RETURN VALUES
+Functions
+.Fn getauevent ,
+.Fn getauevent_r ,
+.Fn getauevnam ,
+.Fn getauevnam_r ,
+.Fn getauevnum ,
+.Fn getauevnum_r ,
+and
+.Fn getauevnuam
+will return a reference to a
+.Dt struct au_event_ent
+or
+.Dt au_event_t
+on success, or
+.Dv NULL on failure, with
+.Va errno
+set to provide further error information.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_event 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+.Va errno
+is not always properly set following a failure.
+.Pp
+These routines are thread-safe, but not re-entrant, so simultaneous or
+interleaved use of these functions will affect the iterator.
diff --git a/contrib/openbsm/libbsm/au_free_token.3 b/contrib/openbsm/libbsm/au_free_token.3
new file mode 100644
index 0000000..fc4ab0b
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_free_token.3
@@ -0,0 +1,91 @@
+.\"-
+.\" Copyright (c) 2004 Apple Computer, Inc.
+.\" Copyright (c) 2005 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+.\" its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRING LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_free_token.3#2 $
+.\"
+.Dd April 19, 2005
+.Dt AU_FREE_TOKEN 3
+.Os
+.Sh NAME
+.Nm au_free_token
+.Nd "Deallocate a token_t created by any of the au_to_*() BSM API functions"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft void
+.Fn au_free_tokenen "token_t *tok"
+.Sh DESCRIPTION
+The BSM API generally manages deallocation of
+.Vt token_t
+objects.
+However, if
+.Xr au_write 3
+is passed a bad audit descriptor, the
+.Vt token_t *
+parameter will be left untouched.
+In that case, the caller can deallocate the
+.Vt token_t
+using
+.Nm
+if desired.
+.Pp
+The
+.Va tok
+argument is a
+.Vt token_t *
+generated by one of the au_to_*() BSM API calls.
+For convenience,
+.Va tok
+may be
+.Dv NULL ,
+in which case
+.Nm
+returns immediately.
+.Sh IMPLEMENTATION NOTES
+This is, in fact, what
+.Xr audit_write 3
+does, in keeping with the existing memory management model of the BSM API.
+.Sh SEE ALSO
+.Xr au_write 3 ,
+.Xr audit_write 3 ,
+.Xr libbsm 3
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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.
+
diff --git a/contrib/openbsm/libbsm/au_io.3 b/contrib/openbsm/libbsm/au_io.3
new file mode 100644
index 0000000..0c520a1
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_io.3
@@ -0,0 +1,119 @@
+.\"-
+.\" Copyright (c) 2005 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_io.3#2 $
+.\"
+.Dd April 19, 2005
+.Dt AU_IO 3
+.Os
+.Sh NAME
+.Nm au_fetch_tok ,
+.Nm au_print_tok ,
+.Nm au_read_rec
+.Nd "Perform I/O involving an audit record"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft int
+.Fn au_fetch_tok "tokenstr_t *tok" "u_char *buf" "int len"
+.Ft void
+.Fn au_print_tok "FILE outfp" "tokenstr_t *tok" "char *del" "char raw" "char sfrm"
+.Ft int
+.Fn au_read_rec "FILE *fp" "u_char **buf"
+.Sh DESCRIPTION
+These interfaces support input and output (I/O) involving audit records,
+internalizing an audit record from a byte stream, converting a token to
+either a raw or default string, and reading a single record from a file.
+.Pp
+.Fn au_fetch_tok
+reads a token from the passed buffer
+.Va buf
+of length
+.Va len
+bytes, and returns a pointer to the token via
+.Va tok .
+.Pp
+.Fn au_print_tok
+prints a string form of the token
+.Va tok
+to the file output stream
+.Va outfp,
+either in default mode, or raw mode if
+.Va raw
+is set non-zero.
+The delimiter
+.Va del
+is used when printing.
+.Pp
+.Fn au_read_rec
+reads an audit record from the file stream
+.Va fp ,
+and returns an allocated memory buffer containing the record via
+.Va *buf ,
+which must be freed by the caller using
+.Xr free 3 .
+.Pp
+A typical use of these routines might open a file with
+.Xr fopen 3 ,
+then read records from the file sequentially by calling
+.Fn au_read_rec .
+Each record would be broken down into components tokens through sequential
+calls to
+.Fn au_fetch_tok
+on the buffer, and then invoking
+.Fn au_print_tok
+to print each token to an output stream such as
+.Dv stdout .
+On completion of the processing of each record, a call to
+.Xr free 3
+would be used to free the record buffer.
+Finally, the source stream would be closed by a call to
+.Xr fclose 3 .
+.Sh RETURN VALUES
+.Fn au_fetch_tok
+and
+.Fn au_read_rec
+return 0 on success, or -1 on failure along with additional error information
+returned via
+.Va errno .
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr libbsm 3
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+.Va errno
+may not always be properly set in the event of an error.
diff --git a/contrib/openbsm/libbsm/au_mask.3 b/contrib/openbsm/libbsm/au_mask.3
new file mode 100644
index 0000000..67bb187
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_mask.3
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2005 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_mask.3#2 $
+.\"
+.Dd April 19, 2005
+.Dt AU_MASK 3
+.Os
+.Sh NAME
+.Nm au_preselect ,
+.Nm getauditflagsbin ,
+.Nm getauditflagschar
+.Nd "Convert between string and numeric values of audit masks"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft int
+.Fn au_preselect "au_event_t event" "au_mask_t *mask_p" "int sorf" "int flag"
+.Ft int
+.Fn getauditflagsbin "char *auditstr" "au_mask_t *masks"
+.Ft int
+.Fn getauditflagschar "char *auditstr" "au_mask_t *masks" "int verbose"
+.Sh DESCRIPTION
+These interfaces support processing of an audit mask represented by type
+.Vt au_mask_t ,
+including conversion between numeric and text formats, and computing whether
+or not an event is matched by a mask.
+.Pp
+.Fn au_preselect
+calculates whether or not the audit event passed via
+.Va event
+is matched by the audit mask passed via
+.Va au_mask_t .
+The
+.Va sorf
+argument indicates whether or not to consider the event as a success,
+if the
+.Dv AU_PRS_SUCCESS
+flag is set, or failure, if the
+.Dv AU_PRS_FAILURE
+flag is set.
+The
+.Va flag
+argument accepts additional arguments influencing the behavior of
+.Fn au_preselect ,
+including
+.Dv AU_PRS_REREAD ,
+which causes the event to be re-looked up rather than read from the cache,
+or
+.Dv AU_PRS_USECACHE
+which forces use of the cache.
+.Pp
+.Fn getauditflagsbin
+converts a string representation of an audit mask passed via a character
+string pointed to by
+.Va auditstr ,
+returning the resulting mask, if valid, via
+.Va *masks .
+.Pp
+.Fn getauditflagschar
+converts the audit event mask passed via
+.Va *masks
+and converts it to a character string in a buffer pointed to by
+.Va auditstr .
+See the BUGS section for more information on how to provide a buffer of
+sufficient size.
+If the
+.Va verbose
+flag is set, the class description string retrieved from
+.Xr audit_class 5
+will be used; otherwise, the two-character class name.
+.Sh RETURN VALUES
+.Fn au_preselect
+returns 0 on success, or returns -1 if there is a failure looking up the
+event type or other database access, in which case
+.Va errno
+will be set to indicate the error.
+It returns 1 if the event is matched; 0 if not.
+.Pp
+.Fn getauditflagsbin
+and
+.Fn getauditflagschar
+returns 0 on success, or -1 if there is a failure, in which case
+.Va errno
+will be set to indicate the error.
+.Sh IMPLEMENTATION NOTES
+.Fn au_preselect
+makes implicit use of various audit database routines, and may influence
+the behavior of simultaenous or interleaved processing of those databases by
+other code.
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr audit_class 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+.Va errno
+may not always be properly set in the event of an error.
+.Pp
+.Fn getauditflagschar
+does not provide a way to indicate how long the character buffer is, in order
+to detect overflow.
+As a result, the caller must always provide a buffer of sufficient length for
+any possible mask, which may be calculated as three times the number of
+non-zero bits in the mask argument in the event non-verbose class names are
+used, and is not trivially predictable for verbose class names.
+This API should be replaced with a more robust one.
diff --git a/contrib/openbsm/libbsm/au_token.3 b/contrib/openbsm/libbsm/au_token.3
new file mode 100644
index 0000000..dd0ce27
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_token.3
@@ -0,0 +1,209 @@
+.\"-
+.\" Copyright (c) 2005 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_token.3#4 $
+.\"
+.Dd April 19, 2005
+.Dt AU_TOKEN 3
+.Os
+.Sh NAME
+.Nm au_to_arg32 ,
+.Nm au_to_arg64 ,
+.Nm au_to_arg ,
+.Nm au_to_attr64 ,
+.Nm au_to_data ,
+.Nm au_to_exit ,
+.Nm au_to_groups ,
+.Nm au_to_newgroups ,
+.Nm au_to_in_addr ,
+.Nm au_to_in_addr_ex ,
+.Nm au_to_ip ,
+.Nm au_to_ipc ,
+.Nm au_to_ipc_perm ,
+.Nm au_to_iport ,
+.Nm au_to_opaque ,
+.Nm au_to_file ,
+.Nm au_to_text ,
+.Nm au_to_path ,
+.Nm au_to_process32 ,
+.Nm au_to_process64 ,
+.Nm au_to_process ,
+.Nm au_to_process32_ex ,
+.Nm au_to_process64_ex ,
+.Nm au_to_process_ex ,
+.Nm au_to_return32 ,
+.Nm au_to_return64 ,
+.Nm au_to_return ,
+.Nm au_to_seq ,
+.Nm au_to_socket ,
+.Nm au_to_socket_ex_32 ,
+.Nm au_to_socket_ex_128 ,
+.Nm au_to_sock_inet32 ,
+.Nm au_to_sock_inet128 ,
+.Nm au_to_sock_inet ,
+.Nm au_to_subject32 ,
+.Nm au_to_subject64 ,
+.Nm au_to_subject ,
+.Nm au_to_subject32_ex ,
+.Nm au_to_subject64_ex ,
+.Nm au_to_subject_ex ,
+.Nm au_to_me ,
+.Nm au_to_exec_args ,
+.Nm au_to_exec_env ,
+.Nm au_to_header ,
+.Nm au_to_header32 ,
+.Nm au_to_header64 ,
+.Nm au_to_trailer .
+.Nd "Routines for generating BSM audit tokens"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft token_t *
+.Fn au_to_arg32 "char n" "char *text" "u_int32_t v"
+.Ft token_t *
+.Fn au_to_arg64 "char n" "char *text" "u_int64_t v"
+.Ft token_t *
+.Fn au_to_arg "char n" "char *text" "u_int32_t v"
+.Ft token_t *
+.Fn au_to_attr32 "struct vattr *attr"
+.Ft token_t *
+.Fn au_to_attr64 "struct vattr *attr"
+.Ft token_t *
+.Fn au_to_attr "struct vattr *attr"
+.Ft token_t *
+.Fn au_to_data "char unit_print" "char unit_type" "char unit_count" "char *p"
+.Ft token_t *
+.Fn au_to_exit "int retval" "int err"
+.Ft token_t *
+.Fn au_to_groups "int *groups"
+.Ft token_t *
+.Fn au_to_newgroups "u_int16_t n" "gid_t *groups"
+.Ft token_t *
+.Fn au_to_in_addr "struct in_addr *internet_addr"
+.Ft token_t *
+.Fn au_to_in_addr_ex "struct in6_addr *internet_addr"
+.Ft token_t *
+.Fn au_to_ip "struct ip *ip"
+.Ft token_t *
+.Fn au_to_ipc "char type" "int id"
+.Ft token_t *
+.Fn au_to_ipc_perm "struct ipc_perm *perm"
+.Ft token_t *
+.Fn au_to_iport "u_int16_t iport"
+.Ft token_t *
+.Fn au_to_opaque "char *data" "u_int64_t bytes"
+.Ft token_t *
+.Fn au_to_file "char *file"
+.Ft token_t *
+.Fn au_to_file "char *file"
+.Ft token_t *
+.Fn au_to_text "char *text"
+.Ft token_t *
+.Fn au_to_path "char *text"
+.Ft token_t *
+.Fn au_to_process32 "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_process64 "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_process32_ex "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Ft token_t *
+.Fn au_to_process64_ex "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Ft token_t *
+.Fn au_to_return32 "char status" "u_int32_t ret"
+.Ft token_t *
+.Fn au_to_return64 "char status" "u_int64_t ret"
+.Ft token_t *
+.Fn au_to_return "char status" "u_int32_t ret"
+.Ft token_t *
+.Fn au_to_seq "long audit_count"
+.Ft token_t *
+.Fn au_to_socket "struct socket *so"
+.Ft token_t *
+.Fn au_to_socket_ex_32 "struct socket *so"
+.Ft token_t *
+.Fn au_to_socket_ex_128 "struct socket *so"
+.Ft token_t *
+.Fn au_to_sock_inet32 "struct sockaddr_in *so"
+.Ft token_t *
+.Fn au_to_sock_inet128 "struct sockaddr_in6 *so"
+.Ft token_t *
+.Fn au_to_sock_int "struct sockaddr_in *so"
+.Ft token_t *
+.Fn au_to_subject32 "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_subject64 "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_subject "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_subject32_ex "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid"
+.Ft token_t *
+.Fn au_to_subject64_ex "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Ft token_t *
+.Fn au_to_subject_ex "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid"
+.Ft token_t *
+.Fn au_to_me "void"
+.Ft token_t *
+.Fn au_to_exec_args "const char **args"
+.Ft token_t *
+.Fn au_to_exec_env "const char **env"
+.Ft token_t *
+.Fn au_to_header "int rec_size" "au_event_t e_type" "au_emod_t emod"
+.Ft token_t *
+.Fn au_to_header32 "int rec_size" "au_event_t e_type" "au_emod_t emod"
+.Ft token_t *
+.Fn au_to_header64 "int rec_size" "au_event_t e_type" "au_emod_t e_mod"
+.Ft token_t *
+.Fn au_to_trailer "int rec_size"
+.Sh DESCRIPTION
+These interfaces support the allocation of BSM audit tokens, represented by
+.Dt token_t ,
+for various data types.
+.Sh RETURN VALUES
+On sucess, a pointer to a
+.Vt token_t
+will be returned; the allocated
+.Vt token_t
+can be freed via a call to
+.Xr au_free_token 3 .
+On failure,
+.Dv NULL
+will be returned, and an error condition returned via
+.Va errno .
+.Sh SEE ALSO
+.Xr libbsm 3
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
diff --git a/contrib/openbsm/libbsm/au_user.3 b/contrib/openbsm/libbsm/au_user.3
new file mode 100644
index 0000000..e71deae
--- /dev/null
+++ b/contrib/openbsm/libbsm/au_user.3
@@ -0,0 +1,136 @@
+.\"-
+.\" Copyright (c) 2005-2006 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_user.3#3 $
+.\"
+.Dd April 19, 2005
+.Dt AU_USER 3
+.Os
+.Sh NAME
+.Nm setauuser ,
+.Nm endauuser ,
+.Nm getauuserent ,
+.Nm getauuserent_r ,
+.Nm getauusernam ,
+.Nm getauusernam_r ,
+.Nm au_user_mask ,
+.Nm getfauditflags
+.Nd "Look up information from the audit_user database"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Ft void
+.Fn setauuser "void"
+.Ft void
+.Fn endauuser "void"
+.Ft struct au_user_ent *
+.Fn getauuserent "void"
+.Ft struct au_user_ent *
+.Fn getauuserent_r "struct au_user_ent *u" "void"
+.Ft struct au_user_ent *
+.Fn getauusernam "const char *name"
+.Ft struct au_user_ent *
+.Fn getauusernam_r "struct au_user_ent *u" "const char *name"
+.Ft int
+.Fn au_user_mask "char *username" "au_mask_t *mask_p"
+.Ft int
+.Fn getfauditflags "au_mask_t *usremask" "au_mask_t *usrdmask" "au_mask_t *lastmask"
+.Sh DESCRIPTION
+These interfaces may be used to look up information from the
+.Xr audit_user 5
+database, which describes per-user audit configuration.
+Audit user entries are described by a
+.Vt au_user_ent ,
+which stores the user's name in
+.Dv au_name ,
+events to always audit in
+.Dv au_always ,
+and events never to audit
+.Dv au_never .
+.Pp
+.Fn getauuserent
+return the next user found in the
+.Xr audit_user 5
+database, or the first if the function has not yet been called.
+.Dv NULL
+will be returned if no further records are available.
+.Pp
+.Fn getauusernam
+looks up a user by name.
+.Dv NULL
+will be returned if no matching class can be found.
+.Pp
+.Fn setauuser
+resets the iterator through the
+.Xr audit_user 5
+database, causing the next call to
+.Fn getauuserent
+to start again from the beginning of the file.
+.Pp
+.Fn endauuser
+closes the
+.Xr audit_user 5
+database, if open.
+.Pp
+.Nm au_user_mask
+calculate a new session audit mask to be returned via
+.Dv mask_p
+for the user identified by
+.Dv username .
+If the user audit configuration is not found, the default system audit
+properties returned by
+.Xr getacflg 3 .
+The resulting mask may be set via a call to
+.Xr setaudit 3
+or related variants.
+.Pp
+.Nm getfauditflags
+XXXXXXXXXXXXXXXXX
+.Sh SEE ALSO
+.Xr libbsm 3 ,
+.Xr getacflg 3 ,
+.Xr setaudit 3 ,
+.Xr audit_user 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+These routines cannot currently distinguish between an entry not being found
+and an error accessing the database.
+The implementation should be changed to return an error via
+.Va errno
+when
+.Dv NULL
+is returned.
diff --git a/contrib/openbsm/libbsm/bsm_audit.c b/contrib/openbsm/libbsm/bsm_audit.c
new file mode 100644
index 0000000..c4374cd
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_audit.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_audit.c#18 $
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bsm/audit_internal.h>
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* array of used descriptors */
+static au_record_t *open_desc_table[MAX_AUDIT_RECORDS];
+
+/* The current number of active record descriptors */
+static int bsm_rec_count = 0;
+
+/*
+ * Records that can be recycled are maintained in the list given below. The
+ * maximum number of elements that can be present in this list is bounded by
+ * MAX_AUDIT_RECORDS. Memory allocated for these records are never freed.
+ */
+static LIST_HEAD(, au_record) bsm_free_q;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * This call frees a token_t and its internal data.
+ */
+void
+au_free_token(token_t *tok)
+{
+
+ if (tok != NULL) {
+ if (tok->t_data)
+ free(tok->t_data);
+ free(tok);
+ }
+}
+
+/*
+ * This call reserves memory for the audit record. Memory must be guaranteed
+ * before any auditable event can be generated. The au_record_t structure
+ * maintains a reference to the memory allocated above and also the list of
+ * tokens associated with this record. Descriptors are recyled once the
+ * records are added to the audit trail following au_close().
+ */
+int
+au_open(void)
+{
+ au_record_t *rec = NULL;
+
+ pthread_mutex_lock(&mutex);
+
+ if (bsm_rec_count == 0)
+ LIST_INIT(&bsm_free_q);
+
+ /*
+ * Find an unused descriptor, remove it from the free list, mark as
+ * used.
+ */
+ if (!LIST_EMPTY(&bsm_free_q)) {
+ rec = LIST_FIRST(&bsm_free_q);
+ rec->used = 1;
+ LIST_REMOVE(rec, au_rec_q);
+ }
+
+ pthread_mutex_unlock(&mutex);
+
+ if (rec == NULL) {
+ /*
+ * Create a new au_record_t if no descriptors are available.
+ */
+ rec = malloc (sizeof(au_record_t));
+ if (rec == NULL)
+ return (-1);
+
+ rec->data = malloc (MAX_AUDIT_RECORD_SIZE * sizeof(u_char));
+ if (rec->data == NULL) {
+ free(rec);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ if (bsm_rec_count == MAX_AUDIT_RECORDS) {
+ pthread_mutex_unlock(&mutex);
+ free(rec->data);
+ free(rec);
+
+ /* XXX We need to increase size of MAX_AUDIT_RECORDS */
+ errno = ENOMEM;
+ return (-1);
+ }
+ rec->desc = bsm_rec_count;
+ open_desc_table[bsm_rec_count] = rec;
+ bsm_rec_count++;
+
+ pthread_mutex_unlock(&mutex);
+
+ }
+
+ memset(rec->data, 0, MAX_AUDIT_RECORD_SIZE);
+
+ TAILQ_INIT(&rec->token_q);
+ rec->len = 0;
+ rec->used = 1;
+
+ return (rec->desc);
+}
+
+/*
+ * Store the token with the record descriptor.
+ *
+ * Don't permit writing more to the buffer than would let the trailer be
+ * appended later.
+ */
+int
+au_write(int d, token_t *tok)
+{
+ au_record_t *rec;
+
+ if (tok == NULL) {
+ errno = EINVAL;
+ return (-1); /* Invalid Token */
+ }
+
+ /* Write the token to the record descriptor */
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1); /* Invalid descriptor */
+ }
+
+ if (rec->len + tok->len + BSM_TRAILER_SIZE > MAX_AUDIT_RECORD_SIZE) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /* Add the token to the tail */
+ /*
+ * XXX Not locking here -- we should not be writing to
+ * XXX the same descriptor from different threads
+ */
+ TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens);
+
+ rec->len += tok->len; /* grow record length by token size bytes */
+
+ /* Token should not be available after this call */
+ tok = NULL;
+ return (0); /* Success */
+}
+
+/*
+ * Assemble an audit record out of its tokens, including allocating header and
+ * trailer tokens. Does not free the token chain, which must be done by the
+ * caller if desirable.
+ *
+ * XXX: Assumes there is sufficient space for the header and trailer.
+ */
+static int
+au_assemble(au_record_t *rec, short event)
+{
+ token_t *header, *tok, *trailer;
+ size_t tot_rec_size;
+ u_char *dptr;
+ int error;
+
+ tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
+ header = au_to_header32(tot_rec_size, event, 0);
+ if (header == NULL)
+ return (-1);
+
+ trailer = au_to_trailer(tot_rec_size);
+ if (trailer == NULL) {
+ error = errno;
+ au_free_token(header);
+ errno = error;
+ return (-1);
+ }
+
+ TAILQ_INSERT_HEAD(&rec->token_q, header, tokens);
+ TAILQ_INSERT_TAIL(&rec->token_q, trailer, tokens);
+
+ rec->len = tot_rec_size;
+ dptr = rec->data;
+
+ TAILQ_FOREACH(tok, &rec->token_q, tokens) {
+ memcpy(dptr, tok->t_data, tok->len);
+ dptr += tok->len;
+ }
+
+ return (0);
+}
+
+/*
+ * Given a record that is no longer of interest, tear it down and convert to a
+ * free record.
+ */
+static void
+au_teardown(au_record_t *rec)
+{
+ token_t *tok;
+
+ /* Free the token list */
+ while ((tok = TAILQ_FIRST(&rec->token_q)) != NULL) {
+ TAILQ_REMOVE(&rec->token_q, tok, tokens);
+ free(tok->t_data);
+ free(tok);
+ }
+
+ rec->used = 0;
+ rec->len = 0;
+
+ pthread_mutex_lock(&mutex);
+
+ /* Add the record to the freelist tail */
+ LIST_INSERT_HEAD(&bsm_free_q, rec, au_rec_q);
+
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Add the header token, identify any missing tokens. Write out the tokens to
+ * the record memory and finally, call audit.
+ */
+int au_close(int d, int keep, short event)
+{
+ au_record_t *rec;
+ size_t tot_rec_size;
+ int retval = 0;
+
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1); /* Invalid descriptor */
+ }
+
+ if (!keep) {
+ retval = 0;
+ goto cleanup;
+ }
+
+
+ tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
+
+ if (tot_rec_size > MAX_AUDIT_RECORD_SIZE) {
+ /*
+ * XXXRW: Since au_write() is supposed to prevent this, spew
+ * an error here.
+ */
+ fprintf(stderr, "au_close failed");
+ errno = ENOMEM;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (au_assemble(rec, event) < 0) {
+ /*
+ * XXXRW: This is also not supposed to happen, but might if we
+ * are unable to allocate header and trailer memory.
+ */
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Call the kernel interface to audit */
+ retval = audit(rec->data, rec->len);
+
+cleanup:
+ /* CLEANUP */
+ au_teardown(rec);
+ return (retval);
+}
+
+/*
+ * au_close(), except onto an in-memory buffer. Buffer size as an argument,
+ * record size returned via same argument on success.
+ */
+int
+au_close_buffer(int d, short event, u_char *buffer, size_t *buflen)
+{
+ size_t tot_rec_size;
+ au_record_t *rec;
+ int retval;
+
+ rec = open_desc_table[d];
+ if ((rec == NULL) || (rec->used == 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ retval = 0;
+ tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
+ if ((tot_rec_size > MAX_AUDIT_RECORD_SIZE) ||
+ (tot_rec_size > *buflen)) {
+ /*
+ * XXXRW: See au_close() comment.
+ */
+ fprintf(stderr, "au_close_buffer failed %zd", tot_rec_size);
+ errno = ENOMEM;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (au_assemble(rec, event) < 0) {
+ /* XXXRW: See au_close() comment. */
+ retval = -1;
+ goto cleanup;
+ }
+
+ memcpy(buffer, rec->data, rec->len);
+ *buflen = rec->len;
+
+cleanup:
+ au_teardown(rec);
+ return (retval);
+}
diff --git a/contrib/openbsm/libbsm/bsm_class.c b/contrib/openbsm/libbsm/bsm_class.c
new file mode 100644
index 0000000..5982d7e
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_class.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#11 $
+ */
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Parse the contents of the audit_class file to return struct au_class_ent
+ * entries.
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *classdelim = ":";
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Parse a single line from the audit_class file passed in str to the struct
+ * au_class_ent elements; store the result in c.
+ */
+static struct au_class_ent *
+classfromstr(char *str, struct au_class_ent *c)
+{
+ char *classname, *classdesc, *classflag;
+ char *last;
+
+ /* Each line contains flag:name:desc. */
+ classflag = strtok_r(str, classdelim, &last);
+ classname = strtok_r(NULL, classdelim, &last);
+ classdesc = strtok_r(NULL, classdelim, &last);
+
+ if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL))
+ return (NULL);
+
+ /*
+ * Check for very large classnames.
+ */
+ if (strlen(classname) >= AU_CLASS_NAME_MAX)
+ return (NULL);
+
+ strcpy(c->ac_name, classname);
+
+ /*
+ * Check for very large class description.
+ */
+ if (strlen(classdesc) >= AU_CLASS_DESC_MAX)
+ return (NULL);
+ strcpy(c->ac_desc, classdesc);
+ c->ac_class = strtoul(classflag, (char **) NULL, 0);
+
+ return (c);
+}
+
+/*
+ * Return the next au_class_ent structure from the file setauclass should be
+ * called before invoking this function for the first time.
+ *
+ * Must be called with mutex held.
+ */
+static struct au_class_ent *
+getauclassent_r_locked(struct au_class_ent *c)
+{
+ char *tokptr, *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL))
+ return (NULL);
+
+ /*
+ * Read until next non-comment line is found, or EOF.
+ */
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Remove trailing new line character. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Parse tokptr to au_class_ent components. */
+ tokptr = linestr;
+ if (classfromstr(tokptr, c) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (c);
+}
+
+struct au_class_ent *
+getauclassent_r(struct au_class_ent *c)
+{
+ struct au_class_ent *cp;
+
+ pthread_mutex_lock(&mutex);
+ cp = getauclassent_r_locked(c);
+ pthread_mutex_unlock(&mutex);
+ return (cp);
+}
+
+struct au_class_ent *
+getauclassent(void)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c, *cp;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ pthread_mutex_lock(&mutex);
+ cp = getauclassent_r_locked(&c);
+ pthread_mutex_unlock(&mutex);
+ return (cp);
+}
+
+/*
+ * Rewind to the beginning of the enumeration.
+ *
+ * Must be called with mutex held.
+ */
+static void
+setauclass_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauclass(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ setauclass_locked();
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Return the next au_class_entry having the given class name.
+ */
+struct au_class_ent *
+getauclassnam_r(struct au_class_ent *c, const char *name)
+{
+ struct au_class_ent *cp;
+
+ if (name == NULL)
+ return (NULL);
+
+ pthread_mutex_lock(&mutex);
+ setauclass_locked();
+ while ((cp = getauclassent_r_locked(c)) != NULL) {
+ if (strcmp(name, cp->ac_name) == 0) {
+ pthread_mutex_unlock(&mutex);
+ return (cp);
+ }
+ }
+ pthread_mutex_unlock(&mutex);
+ return (NULL);
+}
+
+struct au_class_ent *
+getauclassnam(const char *name)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ return (getauclassnam_r(&c, name));
+}
+
+
+/*
+ * Return the next au_class_entry having the given class number.
+ *
+ * OpenBSM extension.
+ */
+struct au_class_ent *
+getauclassnum_r(struct au_class_ent *c, au_class_t class_number)
+{
+ struct au_class_ent *cp;
+
+ pthread_mutex_lock(&mutex);
+ setauclass_locked();
+ while ((cp = getauclassent_r_locked(c)) != NULL) {
+ if (class_number == cp->ac_class)
+ return (cp);
+ }
+ pthread_mutex_unlock(&mutex);
+ return (NULL);
+}
+
+struct au_class_ent *
+getauclassnum(au_class_t class_number)
+{
+ static char class_ent_name[AU_CLASS_NAME_MAX];
+ static char class_ent_desc[AU_CLASS_DESC_MAX];
+ static struct au_class_ent c;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ return (getauclassnum_r(&c, class_number));
+}
+
+/*
+ * audit_class processing is complete; close any open files.
+ */
+void
+endauclass(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ pthread_mutex_unlock(&mutex);
+}
diff --git a/contrib/openbsm/libbsm/bsm_control.c b/contrib/openbsm/libbsm/bsm_control.c
new file mode 100644
index 0000000..438082b
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_control.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#13 $
+ */
+
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Parse the contents of the audit_control file to return the audit control
+ * parameters.
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static char *delim = ":";
+
+static char inacdir = 0;
+static char ptrmoved = 0;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Returns the string value corresponding to the given label from the
+ * configuration file.
+ *
+ * Must be called with mutex held.
+ */
+static int
+getstrfromtype_locked(char *name, char **str)
+{
+ char *type, *nl;
+ char *tokptr;
+ char *last;
+
+ *str = NULL;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
+ return (-1); /* Error */
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
+ if (ferror(fp))
+ return (-1);
+ return (0); /* EOF */
+ }
+
+ if (linestr[0] == '#')
+ continue;
+
+ /* Remove trailing new line character. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ tokptr = linestr;
+ if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
+ if (strcmp(name, type) == 0) {
+ /* Found matching name. */
+ *str = strtok_r(NULL, delim, &last);
+ if (*str == NULL) {
+ errno = EINVAL;
+ return (-1); /* Parse error in file */
+ }
+ return (0); /* Success */
+ }
+ }
+ }
+}
+
+/*
+ * Rewind the file pointer to beginning.
+ */
+void
+setac(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ ptrmoved = 1;
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Close the audit_control file
+ */
+void
+endac(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ ptrmoved = 1;
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Return audit directory information from the audit control file.
+ */
+int
+getacdir(char *name, int len)
+{
+ char *dir;
+ int ret = 0;
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return (-2);
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ /*
+ * Check if another function was called between
+ * successive calls to getacdir
+ */
+ if (inacdir && ptrmoved) {
+ ptrmoved = 0;
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+ ret = 2;
+ }
+
+
+ if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
+ pthread_mutex_unlock(&mutex);
+ return (-2);
+ }
+
+ pthread_mutex_unlock(&mutex);
+
+ if (dir == NULL)
+ return (-1);
+
+ if (strlen(dir) >= len)
+ return (-3);
+
+ strcpy(name, dir);
+
+ return (ret);
+}
+
+/*
+ * Return the minimum free diskspace value from the audit control file
+ */
+int
+getacmin(int *min_val)
+{
+ char *min;
+
+ setac();
+
+ if (min_val == NULL) {
+ errno = EINVAL;
+ return (-2);
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
+ pthread_mutex_unlock(&mutex);
+ return (-2);
+ }
+
+ pthread_mutex_unlock(&mutex);
+
+ if (min == NULL)
+ return (1);
+
+ *min_val = atoi(min);
+
+ return (0);
+}
+
+/*
+ * Return the system audit value from the audit contol file.
+ */
+int
+getacflg(char *auditstr, int len)
+{
+ char *str;
+
+ setac();
+
+ if (auditstr == NULL) {
+ errno = EINVAL;
+ return (-2);
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) {
+ pthread_mutex_unlock(&mutex);
+ return (-2);
+ }
+
+ pthread_mutex_unlock(&mutex);
+
+ if (str == NULL)
+ return (1);
+
+ if (strlen(str) >= len)
+ return (-3);
+
+ strcpy(auditstr, str);
+
+ return (0);
+}
+
+/*
+ * Return the non attributable flags from the audit contol file.
+ */
+int
+getacna(char *auditstr, int len)
+{
+ char *str;
+
+ setac();
+
+ if (auditstr == NULL) {
+ errno = EINVAL;
+ return (-2);
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) {
+ pthread_mutex_unlock(&mutex);
+ return (-2);
+ }
+ pthread_mutex_unlock(&mutex);
+
+ if (str == NULL)
+ return (1);
+
+ if (strlen(str) >= len)
+ return (-3);
+
+ strcpy(auditstr, str);
+
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_event.c b/contrib/openbsm/libbsm/bsm_event.c
new file mode 100644
index 0000000..6e22e4c
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_event.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_event.c#11 $
+ */
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Parse the contents of the audit_event file to return
+ * au_event_ent entries
+ */
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *eventdelim = ":";
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Parse one line from the audit_event file into the au_event_ent structure.
+ */
+static struct au_event_ent *
+eventfromstr(char *str, struct au_event_ent *e)
+{
+ char *evno, *evname, *evdesc, *evclass;
+ struct au_mask evmask;
+ char *last;
+
+ evno = strtok_r(str, eventdelim, &last);
+ evname = strtok_r(NULL, eventdelim, &last);
+ evdesc = strtok_r(NULL, eventdelim, &last);
+ evclass = strtok_r(NULL, eventdelim, &last);
+
+ if ((evno == NULL) || (evname == NULL) || (evdesc == NULL) ||
+ (evclass == NULL))
+ return (NULL);
+
+ if (strlen(evname) >= AU_EVENT_NAME_MAX)
+ return (NULL);
+
+ strcpy(e->ae_name, evname);
+ if (strlen(evdesc) >= AU_EVENT_DESC_MAX)
+ return (NULL);
+ strcpy(e->ae_desc, evdesc);
+
+ e->ae_number = atoi(evno);
+
+ /*
+ * Find out the mask that corresponds to the given list of classes.
+ */
+ if (getauditflagsbin(evclass, &evmask) != 0)
+ e->ae_class = AU_NULL;
+ else
+ e->ae_class = evmask.am_success;
+
+ return (e);
+}
+
+/*
+ * Rewind the audit_event file.
+ */
+static void
+setauevent_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauevent(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ setauevent_locked();
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Close the open file pointers.
+ */
+void
+endauevent(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Enumerate the au_event_ent entries.
+ */
+static struct au_event_ent *
+getauevent_r_locked(struct au_event_ent *e)
+{
+ char *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Get the next event structure. */
+ if (eventfromstr(linestr, e) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (e);
+}
+
+struct au_event_ent *
+getauevent_r(struct au_event_ent *e)
+{
+ struct au_event_ent *ep;
+
+ pthread_mutex_lock(&mutex);
+ ep = getauevent_r_locked(e);
+ pthread_mutex_unlock(&mutex);
+ return (ep);
+}
+
+struct au_event_ent *
+getauevent(void)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevent_r(&e));
+}
+
+/*
+ * Search for an audit event structure having the given event name.
+ *
+ * XXXRW: Why accept NULL name?
+ */
+static struct au_event_ent *
+getauevnam_r_locked(struct au_event_ent *e, const char *name)
+{
+ char *nl;
+
+ if (name == NULL)
+ return (NULL);
+
+ /* Rewind to beginning of the file. */
+ setauevent_locked();
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ if (eventfromstr(linestr, e) != NULL) {
+ if (strcmp(name, e->ae_name) == 0)
+ return (e);
+ }
+ }
+
+ return (NULL);
+}
+
+struct au_event_ent *
+getauevnam_r(struct au_event_ent *e, const char *name)
+{
+ struct au_event_ent *ep;
+
+ pthread_mutex_lock(&mutex);
+ ep = getauevnam_r_locked(e, name);
+ pthread_mutex_unlock(&mutex);
+ return (ep);
+}
+
+struct au_event_ent *
+getauevnam(const char *name)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevnam_r(&e, name));
+}
+
+/*
+ * Search for an audit event structure having the given event number.
+ */
+static struct au_event_ent *
+getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number)
+{
+ char *nl;
+
+ /* Rewind to beginning of the file. */
+ setauevent_locked();
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ if (eventfromstr(linestr, e) != NULL) {
+ if (event_number == e->ae_number)
+ return (e);
+ }
+ }
+
+ return (NULL);
+}
+
+struct au_event_ent *
+getauevnum_r(struct au_event_ent *e, au_event_t event_number)
+{
+ struct au_event_ent *ep;
+
+ pthread_mutex_lock(&mutex);
+ ep = getauevnum_r_locked(e, event_number);
+ pthread_mutex_unlock(&mutex);
+ return (ep);
+}
+
+struct au_event_ent *
+getauevnum(au_event_t event_number)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+ return (getauevnum_r(&e, event_number));
+}
+
+/*
+ * Search for an audit_event entry with a given event_name and returns the
+ * corresponding event number.
+ */
+au_event_t *
+getauevnonam_r(au_event_t *ev, const char *event_name)
+{
+ static char event_ent_name[AU_EVENT_NAME_MAX];
+ static char event_ent_desc[AU_EVENT_DESC_MAX];
+ static struct au_event_ent e, *ep;
+
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ bzero(&e, sizeof(e));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+
+ ep = getauevnam_r(&e, event_name);
+ if (ep == NULL)
+ return (NULL);
+
+ *ev = e.ae_number;
+ return (ev);
+}
+
+au_event_t *
+getauevnonam(const char *event_name)
+{
+ static au_event_t event;
+
+ return (getauevnonam_r(&event, event_name));
+}
diff --git a/contrib/openbsm/libbsm/bsm_flags.c b/contrib/openbsm/libbsm/bsm_flags.c
new file mode 100644
index 0000000..e514c86
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_flags.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#13 $
+ */
+
+#include <bsm/libbsm.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+static const char *flagdelim = ",";
+
+/*
+ * Convert the character representation of audit values into the au_mask_t
+ * field.
+ */
+int
+getauditflagsbin(char *auditstr, au_mask_t *masks)
+{
+ char class_ent_name[AU_CLASS_NAME_MAX];
+ char class_ent_desc[AU_CLASS_DESC_MAX];
+ struct au_class_ent c;
+ char *tok;
+ char sel, sub;
+ char *last;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ masks->am_success = 0;
+ masks->am_failure = 0;
+
+ tok = strtok_r(auditstr, flagdelim, &last);
+ while (tok != NULL) {
+ /* Check for the events that should not be audited. */
+ if (tok[0] == '^') {
+ sub = 1;
+ tok++;
+ } else
+ sub = 0;
+
+ /* Check for the events to be audited for success. */
+ if (tok[0] == '+') {
+ sel = AU_PRS_SUCCESS;
+ tok++;
+ } else if (tok[0] == '-') {
+ sel = AU_PRS_FAILURE;
+ tok++;
+ } else
+ sel = AU_PRS_BOTH;
+
+ if ((getauclassnam_r(&c, tok)) != NULL) {
+ if (sub)
+ SUB_FROM_MASK(masks, c.ac_class, sel);
+ else
+ ADD_TO_MASK(masks, c.ac_class, sel);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Get the next class. */
+ tok = strtok_r(NULL, flagdelim, &last);
+ }
+ return (0);
+}
+
+/*
+ * Convert the au_mask_t fields into a string value. If verbose is non-zero
+ * the long flag names are used else the short (2-character)flag names are
+ * used.
+ *
+ * XXXRW: If bits are specified that are not matched by any class, they are
+ * omitted rather than rejected with EINVAL.
+ *
+ * XXXRW: This is not thread-safe as it relies on atomicity between
+ * setauclass() and sequential calls to getauclassent(). This could be
+ * fixed by iterating through the bitmask fields rather than iterating
+ * through the classes.
+ */
+int
+getauditflagschar(char *auditstr, au_mask_t *masks, int verbose)
+{
+ char class_ent_name[AU_CLASS_NAME_MAX];
+ char class_ent_desc[AU_CLASS_DESC_MAX];
+ struct au_class_ent c;
+ char *strptr = auditstr;
+ u_char sel;
+
+ bzero(&c, sizeof(c));
+ bzero(class_ent_name, sizeof(class_ent_name));
+ bzero(class_ent_desc, sizeof(class_ent_desc));
+ c.ac_name = class_ent_name;
+ c.ac_desc = class_ent_desc;
+
+ /*
+ * Enumerate the class entries, check if each is selected in either
+ * the success or failure masks.
+ */
+ setauclass();
+ while ((getauclassent_r(&c)) != NULL) {
+ sel = 0;
+
+ /* Dont do anything for class = no. */
+ if (c.ac_class == 0)
+ continue;
+
+ sel |= ((c.ac_class & masks->am_success) == c.ac_class) ?
+ AU_PRS_SUCCESS : 0;
+ sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ?
+ AU_PRS_FAILURE : 0;
+
+ /*
+ * No prefix should be attached if both success and failure
+ * are selected.
+ */
+ if ((sel & AU_PRS_BOTH) == 0) {
+ if ((sel & AU_PRS_SUCCESS) != 0) {
+ *strptr = '+';
+ strptr = strptr + 1;
+ } else if ((sel & AU_PRS_FAILURE) != 0) {
+ *strptr = '-';
+ strptr = strptr + 1;
+ }
+ }
+
+ if (sel != 0) {
+ if (verbose) {
+ strcpy(strptr, c.ac_desc);
+ strptr += strlen(c.ac_desc);
+ } else {
+ strcpy(strptr, c.ac_name);
+ strptr += strlen(c.ac_name);
+ }
+ *strptr = ','; /* delimiter */
+ strptr = strptr + 1;
+ }
+ }
+
+ /* Overwrite the last delimiter with the string terminator. */
+ if (strptr != auditstr)
+ *(strptr-1) = '\0';
+
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_io.c b/contrib/openbsm/libbsm/bsm_io.c
new file mode 100644
index 0000000..bfdd366
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_io.c
@@ -0,0 +1,2831 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_io.c#29 $
+ */
+
+#include <sys/types.h>
+#ifdef __APPLE__
+#include <compat/endian.h>
+#else /* !__APPLE__ */
+#include <sys/endian.h>
+#endif /* __APPLE__*/
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <bsm/libbsm.h>
+
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <bsm/audit_internal.h>
+
+#define READ_TOKEN_BYTES(buf, len, dest, size, bytesread, err) do { \
+ if (bytesread + size > len) { \
+ err = 1; \
+ } else { \
+ memcpy(dest, buf + bytesread, size); \
+ bytesread += size; \
+ } \
+} while (0)
+
+#define READ_TOKEN_U_CHAR(buf, len, dest, bytesread, err) do { \
+ if (bytesread + sizeof(u_char) <= len) { \
+ dest = buf[bytesread]; \
+ bytesread += sizeof(u_char); \
+ } else \
+ err = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT16(buf, len, dest, bytesread, err) do { \
+ if (bytesread + sizeof(u_int16_t) <= len) { \
+ dest = be16dec(buf + bytesread); \
+ bytesread += sizeof(u_int16_t); \
+ } else \
+ err = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT32(buf, len, dest, bytesread, err) do { \
+ if (bytesread + sizeof(u_int32_t) <= len) { \
+ dest = be32dec(buf + bytesread); \
+ bytesread += sizeof(u_int32_t); \
+ } else \
+ err = 1; \
+} while (0)
+
+#define READ_TOKEN_U_INT64(buf, len, dest, bytesread, err) do { \
+ if (bytesread + sizeof(u_int64_t) <= len) { \
+ dest = be64dec(buf + bytesread); \
+ bytesread += sizeof(u_int64_t); \
+ } else \
+ err = 1; \
+} while (0)
+
+#define SET_PTR(buf, len, ptr, size, bytesread, err) do { \
+ if ((bytesread) + (size) > (len)) \
+ (err) = 1; \
+ else { \
+ (ptr) = (buf) + (bytesread); \
+ (bytesread) += (size); \
+ } \
+} while (0)
+
+/*
+ * Prints the delimiter string.
+ */
+static void
+print_delim(FILE *fp, const char *del)
+{
+
+ fprintf(fp, "%s", del);
+}
+
+/*
+ * Prints a single byte in the given format.
+ */
+static void
+print_1_byte(FILE *fp, u_char val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Print 2 bytes in the given format.
+ */
+static void
+print_2_bytes(FILE *fp, u_int16_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints 4 bytes in the given format.
+ */
+static void
+print_4_bytes(FILE *fp, u_int32_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints 8 bytes in the given format.
+ */
+static void
+print_8_bytes(FILE *fp, u_int64_t val, const char *format)
+{
+
+ fprintf(fp, format, val);
+}
+
+/*
+ * Prints the given size of data bytes in hex.
+ */
+static void
+print_mem(FILE *fp, u_char *data, size_t len)
+{
+ int i;
+
+ if (len > 0) {
+ fprintf(fp, "0x");
+ for (i = 0; i < len; i++)
+ fprintf(fp, "%x", data[i]);
+ }
+}
+
+/*
+ * Prints the given data bytes as a string.
+ */
+static void
+print_string(FILE *fp, u_char *str, size_t len)
+{
+ int i;
+
+ if (len > 0) {
+ for (i = 0; i < len; i++) {
+ if (str[i] != '\0')
+ fprintf(fp, "%c", str[i]);
+ }
+ }
+}
+
+/*
+ * Prints the token type in either the raw or the default form.
+ */
+static void
+print_tok_type(FILE *fp, u_char type, const char *tokname, char raw)
+{
+
+ if (raw)
+ fprintf(fp, "%u", type);
+ else
+ fprintf(fp, "%s", tokname);
+}
+
+/*
+ * Prints a user value.
+ */
+static void
+print_user(FILE *fp, u_int32_t usr, char raw)
+{
+ struct passwd *pwent;
+
+ if (raw)
+ fprintf(fp, "%d", usr);
+ else {
+ pwent = getpwuid(usr);
+ if (pwent != NULL)
+ fprintf(fp, "%s", pwent->pw_name);
+ else
+ fprintf(fp, "%d", usr);
+ }
+}
+
+/*
+ * Prints a group value.
+ */
+static void
+print_group(FILE *fp, u_int32_t grp, char raw)
+{
+ struct group *grpent;
+
+ if (raw)
+ fprintf(fp, "%d", grp);
+ else {
+ grpent = getgrgid(grp);
+ if (grpent != NULL)
+ fprintf(fp, "%s", grpent->gr_name);
+ else
+ fprintf(fp, "%d", grp);
+ }
+}
+
+/*
+ * Prints the event from the header token in either the short, default or raw
+ * form.
+ */
+static void
+print_event(FILE *fp, u_int16_t ev, char raw, char sfrm)
+{
+ char event_ent_name[AU_EVENT_NAME_MAX];
+ char event_ent_desc[AU_EVENT_DESC_MAX];
+ struct au_event_ent e, *ep;
+
+ bzero(&e, sizeof(e));
+ bzero(event_ent_name, sizeof(event_ent_name));
+ bzero(event_ent_desc, sizeof(event_ent_desc));
+ e.ae_name = event_ent_name;
+ e.ae_desc = event_ent_desc;
+
+ ep = getauevnum_r(&e, ev);
+ if (ep == NULL) {
+ fprintf(fp, "%u", ev);
+ return;
+ }
+
+ if (raw)
+ fprintf(fp, "%u", ev);
+ else if (sfrm)
+ fprintf(fp, "%s", e.ae_name);
+ else
+ fprintf(fp, "%s", e.ae_desc);
+}
+
+
+/*
+ * Prints the event modifier from the header token in either the default or
+ * raw form.
+ */
+static void
+print_evmod(FILE *fp, u_int16_t evmod, char raw)
+{
+ if (raw)
+ fprintf(fp, "%u", evmod);
+ else
+ fprintf(fp, "%u", evmod);
+}
+
+/*
+ * Prints seconds in the ctime format.
+ */
+static void
+print_sec32(FILE *fp, u_int32_t sec, char raw)
+{
+ time_t timestamp;
+ char timestr[26];
+
+ if (raw)
+ fprintf(fp, "%u", sec);
+ else {
+ timestamp = (time_t)sec;
+ ctime_r(&timestamp, timestr);
+ timestr[24] = '\0'; /* No new line */
+ fprintf(fp, "%s", timestr);
+ }
+}
+
+/*
+ * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we
+ * assume a 32-bit time_t, we simply truncate for now.
+ */
+static void
+print_sec64(FILE *fp, u_int64_t sec, char raw)
+{
+ time_t timestamp;
+ char timestr[26];
+
+ if (raw)
+ fprintf(fp, "%u", (u_int32_t)sec);
+ else {
+ timestamp = (time_t)sec;
+ ctime_r(&timestamp, timestr);
+ timestr[24] = '\0'; /* No new line */
+ fprintf(fp, "%s", timestr);
+ }
+}
+
+/*
+ * Prints the excess milliseconds.
+ */
+static void
+print_msec32(FILE *fp, u_int32_t msec, char raw)
+{
+ if (raw)
+ fprintf(fp, "%u", msec);
+ else
+ fprintf(fp, " + %u msec", msec);
+}
+
+/*
+ * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we assume
+ * a 32-bit msec, we simply truncate for now.
+ */
+static void
+print_msec64(FILE *fp, u_int64_t msec, char raw)
+{
+
+ msec &= 0xffffffff;
+ if (raw)
+ fprintf(fp, "%u", (u_int32_t)msec);
+ else
+ fprintf(fp, " + %u msec", (u_int32_t)msec);
+}
+
+/*
+ * Prints a dotted form for the IP address.
+ */
+static void
+print_ip_address(FILE *fp, u_int32_t ip)
+{
+ struct in_addr ipaddr;
+
+ ipaddr.s_addr = ip;
+ fprintf(fp, "%s", inet_ntoa(ipaddr));
+}
+
+/*
+ * Prints a string value for the given ip address.
+ */
+static void
+print_ip_ex_address(FILE *fp, u_int32_t type, u_int32_t *ipaddr)
+{
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ char dst[INET6_ADDRSTRLEN];
+
+ switch (type) {
+ case AU_IPv4:
+ ipv4.s_addr = (in_addr_t)(ipaddr[0]);
+ fprintf(fp, "%s", inet_ntop(AF_INET, &ipv4, dst,
+ INET6_ADDRSTRLEN));
+ break;
+
+ case AU_IPv6:
+ ipv6.__u6_addr.__u6_addr32[0] = ipaddr[0];
+ ipv6.__u6_addr.__u6_addr32[1] = ipaddr[1];
+ ipv6.__u6_addr.__u6_addr32[2] = ipaddr[2];
+ ipv6.__u6_addr.__u6_addr32[3] = ipaddr[3];
+ fprintf(fp, "%s", inet_ntop(AF_INET6, &ipv6, dst,
+ INET6_ADDRSTRLEN));
+ break;
+
+ default:
+ fprintf(fp, "invalid");
+ }
+}
+
+/*
+ * Prints return value as success or failure.
+ */
+static void
+print_retval(FILE *fp, u_char status, char raw)
+{
+ if (raw)
+ fprintf(fp, "%u", status);
+ else {
+ if (status == 0)
+ fprintf(fp, "success");
+ else
+ fprintf(fp, "failure : %s", strerror(status));
+ }
+}
+
+/*
+ * Prints the exit value.
+ */
+static void
+print_errval(FILE *fp, u_int32_t val)
+{
+
+ fprintf(fp, "Error %u", val);
+}
+
+/*
+ * Prints IPC type.
+ */
+static void
+print_ipctype(FILE *fp, u_char type, char raw)
+{
+ if (raw)
+ fprintf(fp, "%u", type);
+ else {
+ if (type == AT_IPC_MSG)
+ fprintf(fp, "Message IPC");
+ else if (type == AT_IPC_SEM)
+ fprintf(fp, "Semaphore IPC");
+ else if (type == AT_IPC_SHM)
+ fprintf(fp, "Shared Memory IPC");
+ else
+ fprintf(fp, "%u", type);
+ }
+}
+
+/*
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+static int
+fetch_header32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw, char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "header", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr32.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr32.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr32.e_type, raw, sfrm);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr32.e_mod, raw);
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.hdr32.s, raw);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.hdr32.ms, raw);
+}
+
+/*
+ * The Solaris specifications for AUE_HEADER32_EX seem to differ a bit
+ * depending on the bit of the specifications found. The OpenSolaris source
+ * code uses a 4-byte address length, followed by some number of bytes of
+ * address data. This contrasts with the Solaris audit.log.5 man page, which
+ * specifies a 1-byte length field. We use the Solaris 10 definition so that
+ * we can parse audit trails from that system.
+ *
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * [ Solaris man page: address type/length 1 byte]
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32/64-bits)
+ * nanoseconds of time 4 bytes/8 bytes (32/64-bits)
+ */
+static int
+fetch_header32_ex_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32_ex.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ad_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ bzero(tok->tt.hdr32_ex.addr, sizeof(tok->tt.hdr32_ex.addr));
+ switch (tok->tt.hdr32_ex.ad_type) {
+ case AU_IPv4:
+ READ_TOKEN_BYTES(buf, len, &tok->tt.hdr32_ex.addr[0],
+ sizeof(tok->tt.hdr32_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ break;
+
+ case AU_IPv6:
+ READ_TOKEN_BYTES(buf, len, tok->tt.hdr32_ex.addr,
+ sizeof(tok->tt.hdr32_ex.addr), tok->len, err);
+ break;
+ }
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header32_ex_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "header_ex", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr32_ex.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr32_ex.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr32_ex.e_type, raw, sfrm);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr32_ex.e_mod, raw);
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type,
+ tok->tt.hdr32_ex.addr);
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.hdr32_ex.s, raw);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.hdr32_ex.ms, raw);
+}
+
+/*
+ * record byte count 4 bytes
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * version #
+ */
+static int
+fetch_header64_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header64_tok(FILE *fp, tokenstr_t *tok, char *del, char raw, char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "header", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr64.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr64.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr64.e_type, raw, sfrm);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr64.e_mod, raw);
+ print_delim(fp, del);
+ print_sec64(fp, tok->tt.hdr64.s, raw);
+ print_delim(fp, del);
+ print_msec64(fp, tok->tt.hdr64.ms, raw);
+}
+/*
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * [ Solaris man page: address type/length 1 byte]
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32/64-bits)
+ * nanoseconds of time 4 bytes/8 bytes (32/64-bits)
+ *
+ * XXXAUDIT: See comment by fetch_header32_ex_tok() for details on the
+ * accuracy of the BSM spec.
+ */
+static int
+fetch_header64_ex_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64_ex.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_mod, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.ad_type, tok->len, err);
+ if (err)
+ return (-1);
+
+ bzero(tok->tt.hdr64_ex.addr, sizeof(tok->tt.hdr64_ex.addr));
+ switch (tok->tt.hdr64_ex.ad_type) {
+ case AU_IPv4:
+ READ_TOKEN_BYTES(buf, len, &tok->tt.hdr64_ex.addr[0],
+ sizeof(tok->tt.hdr64_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ break;
+
+ case AU_IPv6:
+ READ_TOKEN_BYTES(buf, len, tok->tt.hdr64_ex.addr,
+ sizeof(tok->tt.hdr64_ex.addr), tok->len, err);
+ break;
+ }
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_header64_ex_tok(FILE *fp, tokenstr_t *tok, char *del, char raw, char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "header_ex", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.hdr64_ex.size, "%u");
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.hdr64_ex.version, "%u");
+ print_delim(fp, del);
+ print_event(fp, tok->tt.hdr64_ex.e_type, raw, sfrm);
+ print_delim(fp, del);
+ print_evmod(fp, tok->tt.hdr64_ex.e_mod, raw);
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type,
+ tok->tt.hdr64_ex.addr);
+ print_delim(fp, del);
+ print_sec64(fp, tok->tt.hdr64_ex.s, raw);
+ print_delim(fp, del);
+ print_msec64(fp, tok->tt.hdr64_ex.ms, raw);
+}
+
+/*
+ * trailer magic 2 bytes
+ * record size 4 bytes
+ */
+static int
+fetch_trailer_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.trail.magic, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.trail.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_trailer_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "trailer", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.trail.count, "%u");
+}
+
+/*
+ * argument # 1 byte
+ * argument value 4 bytes/8 bytes (32-bit/64-bit value)
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+static int
+fetch_arg32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arg32.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.arg32.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.arg32.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.arg32.text, tok->tt.arg32.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arg32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "argument", raw);
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arg32.no, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.arg32.val, "%#x");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.arg32.text, tok->tt.arg32.len);
+}
+
+static int
+fetch_arg64_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arg64.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.arg64.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.arg64.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.arg64.text, tok->tt.arg64.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arg64_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "argument", raw);
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arg64.no, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.arg64.val, "%#llx");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.arg64.text, tok->tt.arg64.len);
+}
+
+/*
+ * how to print 1 byte
+ * basic unit 1 byte
+ * unit count 1 byte
+ * data items (depends on basic unit)
+ */
+static int
+fetch_arb_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+ int datasize;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.howtopr, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.bu, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.uc, tok->len, err);
+ if (err)
+ return (-1);
+
+ /*
+ * Determine the size of the basic unit.
+ */
+ switch(tok->tt.arb.bu) {
+ case AUR_BYTE:
+ datasize = AUR_BYTE_SIZE;
+ break;
+
+ case AUR_SHORT:
+ datasize = AUR_SHORT_SIZE;
+ break;
+
+ case AUR_LONG:
+ datasize = AUR_LONG_SIZE;
+ break;
+
+ default:
+ return (-1);
+ }
+
+ SET_PTR(buf, len, tok->tt.arb.data, datasize * tok->tt.arb.uc,
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_arb_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+ char *str;
+ char *format;
+ size_t size;
+ int i;
+
+ print_tok_type(fp, tok->id, "arbitrary", raw);
+ print_delim(fp, del);
+
+ switch(tok->tt.arb.howtopr) {
+ case AUP_BINARY:
+ str = "binary";
+ format = " %c";
+ break;
+
+ case AUP_OCTAL:
+ str = "octal";
+ format = " %o";
+ break;
+
+ case AUP_DECIMAL:
+ str = "decimal";
+ format = " %d";
+ break;
+
+ case AUP_HEX:
+ str = "hex";
+ format = " %x";
+ break;
+
+ case AUP_STRING:
+ str = "string";
+ format = "%c";
+ break;
+
+ default:
+ return;
+ }
+
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ switch(tok->tt.arb.bu) {
+ case AUR_BYTE:
+ str = "byte";
+ size = AUR_BYTE_SIZE;
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i<tok->tt.arb.uc; i++)
+ fprintf(fp, format, *(tok->tt.arb.data + (size * i)));
+ break;
+
+ case AUR_SHORT:
+ str = "short";
+ size = AUR_SHORT_SIZE;
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i<tok->tt.arb.uc; i++)
+ fprintf(fp, format, *((u_int16_t *)(tok->tt.arb.data +
+ (size * i))));
+ break;
+
+ case AUR_LONG:
+ str = "int";
+ size = AUR_LONG_SIZE;
+ print_string(fp, str, strlen(str));
+ print_delim(fp, del);
+ print_1_byte(fp, tok->tt.arb.uc, "%u");
+ print_delim(fp, del);
+ for (i = 0; i<tok->tt.arb.uc; i++)
+ fprintf(fp, format, *((u_int32_t *)(tok->tt.arb.data +
+ (size * i))));
+ break;
+
+ default:
+ return;
+ }
+}
+
+/*
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+static int
+fetch_attr32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.fsid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr32.nid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.dev, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_attr32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "attribute", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.mode, "%o");
+ print_delim(fp, del);
+ print_user(fp, tok->tt.attr32.uid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.attr32.gid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.fsid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr32.nid, "%lld");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr32.dev, "%u");
+}
+
+/*
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+static int
+fetch_attr64_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.fsid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.nid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.dev, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_attr64_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "attribute", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr64.mode, "%o");
+ print_delim(fp, del);
+ print_user(fp, tok->tt.attr64.uid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.attr64.gid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.attr64.fsid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr64.nid, "%lld");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.attr64.dev, "%llu");
+}
+
+/*
+ * status 4 bytes
+ * return value 4 bytes
+ */
+static int
+fetch_exit_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.exit.status, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.exit.ret, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_exit_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "exit", raw);
+ print_delim(fp, del);
+ print_errval(fp, tok->tt.exit.status);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.exit.ret, "%u");
+}
+
+/*
+ * count 4 bytes
+ * text count null-terminated string(s)
+ */
+static int
+fetch_execarg_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+ int i;
+ char *bptr;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.execarg.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i < tok->tt.execarg.count; i++) {
+ bptr = buf + tok->len;
+ tok->tt.execarg.text[i] = bptr;
+
+ /* Look for a null terminated string. */
+ while (bptr && (*bptr != '\0')) {
+ if (++tok->len >=len)
+ return (-1);
+ bptr = buf + tok->len;
+ }
+ if (!bptr)
+ return (-1);
+ tok->len++; /* \0 character */
+ }
+
+ return (0);
+}
+
+static void
+print_execarg_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+ int i;
+
+ print_tok_type(fp, tok->id, "exec arg", raw);
+ for (i = 0; i < tok->tt.execarg.count; i++) {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.execarg.text[i],
+ strlen(tok->tt.execarg.text[i]));
+ }
+}
+
+/*
+ * count 4 bytes
+ * text count null-terminated string(s)
+ */
+static int
+fetch_execenv_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+ int i;
+ char *bptr;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.execenv.count, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i< tok->tt.execenv.count; i++) {
+ bptr = buf + tok->len;
+ tok->tt.execenv.text[i] = bptr;
+
+ /* Look for a null terminated string. */
+ while (bptr && (*bptr != '\0')) {
+ if (++tok->len >=len)
+ return (-1);
+ bptr = buf + tok->len;
+ }
+ if (!bptr)
+ return (-1);
+ tok->len++; /* \0 character */
+ }
+
+ return (0);
+}
+
+static void
+print_execenv_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+ int i;
+
+ print_tok_type(fp, tok->id, "exec arg", raw);
+ for (i = 0; i< tok->tt.execenv.count; i++) {
+ print_delim(fp, del);
+ print_string(fp, tok->tt.execenv.text[i],
+ strlen(tok->tt.execenv.text[i]));
+ }
+}
+
+/*
+ * seconds of time 4 bytes
+ * milliseconds of time 4 bytes
+ * file name len 2 bytes
+ * file pathname N bytes + 1 terminating NULL byte
+ */
+static int
+fetch_file_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.file.s, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.file.ms, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.file.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.file.name, tok->tt.file.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_file_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "file", raw);
+ print_delim(fp, del);
+ print_sec32(fp, tok->tt.file.s, raw);
+ print_delim(fp, del);
+ print_msec32(fp, tok->tt.file.ms, raw);
+ print_delim(fp, del);
+ print_string(fp, tok->tt.file.name, tok->tt.file.len);
+}
+
+/*
+ * number groups 2 bytes
+ * group list count * 4 bytes
+ */
+static int
+fetch_newgroups_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int i;
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.grps.no, tok->len, err);
+ if (err)
+ return (-1);
+
+ for (i = 0; i<tok->tt.grps.no; i++) {
+ READ_TOKEN_U_INT32(buf, len, tok->tt.grps.list[i], tok->len,
+ err);
+ if (err)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+print_newgroups_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+ int i;
+
+ print_tok_type(fp, tok->id, "group", raw);
+ for (i = 0; i < tok->tt.grps.no; i++) {
+ print_delim(fp, del);
+ print_group(fp, tok->tt.grps.list[i], raw);
+ }
+}
+
+/*
+ * Internet addr 4 bytes
+ */
+static int
+fetch_inaddr_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.inaddr.addr, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+
+}
+
+static void
+print_inaddr_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "ip addr", raw);
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.inaddr.addr);
+}
+
+/*
+ * type 4 bytes
+ * address 16 bytes
+ */
+static int
+fetch_inaddr_ex_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.inaddr_ex.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.inaddr_ex.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.inaddr_ex.addr[0],
+ sizeof(tok->tt.inaddr_ex.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.inaddr_ex.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.inaddr_ex.addr,
+ sizeof(tok->tt.inaddr_ex.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_inaddr_ex_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "ip addr ex", raw);
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.inaddr_ex.type,
+ tok->tt.inaddr_ex.addr);
+}
+
+/*
+ * ip header 20 bytes
+ */
+static int
+fetch_ip_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.version, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.tos, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.ip.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.ip.id, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.ip.offset, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.ttl, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.prot, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.ip.chksm, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.src, sizeof(tok->tt.ip.src),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.ip.dest, sizeof(tok->tt.ip.dest),
+ tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ip_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "ip", raw);
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.version), sizeof(u_char));
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.tos), sizeof(u_char));
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.ip.len, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.ip.id, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.ip.offset, "%u");
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.ttl), sizeof(u_char));
+ print_delim(fp, del);
+ print_mem(fp, (u_char *)(&tok->tt.ip.prot), sizeof(u_char));
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.ip.chksm, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.ip.src);
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.ip.dest);
+}
+
+/*
+ * object ID type 1 byte
+ * Object ID 4 bytes
+ */
+static int
+fetch_ipc_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ipc.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipc.id, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ipc_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "IPC", raw);
+ print_delim(fp, del);
+ print_ipctype(fp, tok->tt.ipc.type, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipc.id, "%u");
+}
+
+/*
+ * owner user id 4 bytes
+ * owner group id 4 bytes
+ * creator user id 4 bytes
+ * creator group id 4 bytes
+ * access mode 4 bytes
+ * slot seq 4 bytes
+ * key 4 bytes
+ */
+static int
+fetch_ipcperm_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.uid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.gid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.puid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.pgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.mode, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.seq, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.key, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_ipcperm_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "IPC perm", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.ipcperm.uid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.ipcperm.gid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.ipcperm.puid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.ipcperm.pgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.mode, "%o");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.seq, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ipcperm.key, "%u");
+}
+
+/*
+ * port Ip address 2 bytes
+ */
+static int
+fetch_iport_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.iport.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_iport_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "ip port", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.iport.port, "%#x");
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_opaque_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.opaque.size, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.opaque.data, tok->tt.opaque.size, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_opaque_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "opaque", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.opaque.size, "%u");
+ print_delim(fp, del);
+ print_mem(fp, tok->tt.opaque.data, tok->tt.opaque.size);
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_path_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.path.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.path.path, tok->tt.path.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_path_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "path", raw);
+ print_delim(fp, del);
+ print_string(fp, tok->tt.path.path, tok->tt.path.len);
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes
+ * machine id 4 bytes
+ */
+static int
+fetch_process32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.tid.addr, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "process", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.auid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.euid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32.egid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32.ruid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32.rgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.proc32.tid.addr);
+}
+
+static int
+fetch_process32ex_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.proc32_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.proc32_ex.tid.addr[0],
+ sizeof(tok->tt.proc32_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.proc32_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.proc32_ex.tid.addr,
+ sizeof(tok->tt.proc32_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_process32ex_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "process_ex", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.auid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.euid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32_ex.egid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.proc32_ex.ruid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.proc32_ex.rgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.proc32_ex.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.proc32_ex.tid.type,
+ tok->tt.proc32_ex.tid.addr);
+}
+
+/*
+ * errno 1 byte
+ * return value 4 bytes
+ */
+static int
+fetch_return32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ret32.status, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.ret32.ret, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_return32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "return", raw);
+ print_delim(fp, del);
+ print_retval(fp, tok->tt.ret32.status, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.ret32.ret, "%u");
+}
+
+static int
+fetch_return64_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_CHAR(buf, len, tok->tt.ret64.err, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.ret64.val, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_return64_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "return", raw);
+ print_delim(fp, del);
+ print_retval(fp, tok->tt.ret64.err, raw);
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.ret64.val, "%lld");
+}
+
+/*
+ * seq 4 bytes
+ */
+static int
+fetch_seq_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.seq.seqno, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_seq_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "sequence", raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.seq.seqno, "%u");
+}
+
+/*
+ * socket family 2 bytes
+ * local port 2 bytes
+ * socket address 4 bytes
+ */
+static int
+fetch_sock_inet32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet32.family, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet32.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet32.addr,
+ sizeof(tok->tt.sockinet32.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_sock_inet32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "socket-inet", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockinet32.family, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockinet32.port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.sockinet32.addr);
+}
+
+/*
+ * socket family 2 bytes
+ * path 104 bytes
+ */
+static int fetch_sock_unix_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.sockunix.family, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, tok->tt.sockunix.path, 104, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_sock_unix_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "socket-unix", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.sockunix.family, "%u");
+ print_delim(fp, del);
+ print_string(fp, tok->tt.sockunix.path,
+ strlen(tok->tt.sockunix.path));
+}
+
+/*
+ * socket type 2 bytes
+ * local port 2 bytes
+ * local address 4 bytes
+ * remote port 2 bytes
+ * remote address 4 bytes
+ */
+static int fetch_socket_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket.type, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket.l_port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr,
+ sizeof(tok->tt.socket.l_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket.r_port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr,
+ sizeof(tok->tt.socket.r_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_socket_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "socket", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket.type, "%u");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket.l_port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket.l_addr);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket.r_port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket.r_addr);
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine id 4 bytes
+ */
+static int
+fetch_subject32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj32.tid.addr,
+ sizeof(tok->tt.subj32.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "subject", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.auid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.euid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32.egid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32.ruid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32.rgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.subj32.tid.addr);
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine id 4 bytes
+ */
+static int
+fetch_subject64_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT64(buf, len, tok->tt.subj64.tid.port, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj64.tid.addr,
+ sizeof(tok->tt.subj64.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject64_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "subject", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.auid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.euid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64.egid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj64.ruid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj64.rgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj64.sid, "%u");
+ print_delim(fp, del);
+ print_8_bytes(fp, tok->tt.subj64.tid.port, "%llu");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.subj64.tid.addr);
+}
+
+/*
+ * audit ID 4 bytes
+ * euid 4 bytes
+ * egid 4 bytes
+ * ruid 4 bytes
+ * rgid 4 bytes
+ * pid 4 bytes
+ * sessid 4 bytes
+ * terminal ID
+ * portid 4 bytes
+ * type 4 bytes
+ * machine id 16 bytes
+ */
+static int
+fetch_subject32ex_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.auid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.euid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.egid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.ruid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.rgid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.pid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.sid, tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ if (tok->tt.subj32_ex.tid.type == AU_IPv4) {
+ READ_TOKEN_BYTES(buf, len, &tok->tt.subj32_ex.tid.addr[0],
+ sizeof(tok->tt.subj32_ex.tid.addr[0]), tok->len, err);
+ if (err)
+ return (-1);
+ } else if (tok->tt.subj32_ex.tid.type == AU_IPv6) {
+ READ_TOKEN_BYTES(buf, len, tok->tt.subj32_ex.tid.addr,
+ sizeof(tok->tt.subj32_ex.tid.addr), tok->len, err);
+ if (err)
+ return (-1);
+ } else
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_subject32ex_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "subject_ex", raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.auid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.euid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32_ex.egid, raw);
+ print_delim(fp, del);
+ print_user(fp, tok->tt.subj32_ex.ruid, raw);
+ print_delim(fp, del);
+ print_group(fp, tok->tt.subj32_ex.rgid, raw);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.pid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.sid, "%u");
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.subj32_ex.tid.port, "%u");
+ print_delim(fp, del);
+ print_ip_ex_address(fp, tok->tt.subj32_ex.tid.type,
+ tok->tt.subj32_ex.tid.addr);
+}
+
+/*
+ * size 2 bytes
+ * data size bytes
+ */
+static int
+fetch_text_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.text.len, tok->len, err);
+ if (err)
+ return (-1);
+
+ SET_PTR(buf, len, tok->tt.text.text, tok->tt.text.len, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_text_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "text", raw);
+ print_delim(fp, del);
+ print_string(fp, tok->tt.text.text, tok->tt.text.len);
+}
+
+/*
+ * socket type 2 bytes
+ * local port 2 bytes
+ * address type/length 4 bytes
+ * local Internet address 4 bytes
+ * remote port 4 bytes
+ * address type/length 4 bytes
+ * remote Internet address 4 bytes
+ */
+static int
+fetch_socketex32_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.l_port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.socket_ex32.l_ad_type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_addr,
+ sizeof(tok->tt.socket_ex32.l_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.socket_ex32.r_port, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_U_INT32(buf, len, tok->tt.socket_ex32.r_ad_type, tok->len,
+ err);
+ if (err)
+ return (-1);
+
+ READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_addr,
+ sizeof(tok->tt.socket_ex32.r_addr), tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_socketex32_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "socket", raw);
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x");
+ print_delim(fp, del);
+ print_2_bytes(fp, tok->tt.socket_ex32.l_port, "%#x");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket_ex32.l_addr);
+ print_delim(fp, del);
+ print_4_bytes(fp, tok->tt.socket_ex32.r_port, "%#x");
+ print_delim(fp, del);
+ print_ip_address(fp, tok->tt.socket_ex32.r_addr);
+}
+
+static int
+fetch_invalid_tok(tokenstr_t *tok, char *buf, int len)
+{
+ int err = 0;
+ int recoversize;
+
+ recoversize = len - (tok->len + BSM_TRAILER_SIZE);
+ if (recoversize <= 0)
+ return (-1);
+
+ tok->tt.invalid.length = recoversize;
+
+ SET_PTR(buf, len, tok->tt.invalid.data, recoversize, tok->len, err);
+ if (err)
+ return (-1);
+
+ return (0);
+}
+
+static void
+print_invalid_tok(FILE *fp, tokenstr_t *tok, char *del, char raw,
+ __unused char sfrm)
+{
+
+ print_tok_type(fp, tok->id, "unknown", raw);
+ print_delim(fp, del);
+ print_mem(fp, tok->tt.invalid.data, tok->tt.invalid.length);
+}
+
+
+/*
+ * Reads the token beginning at buf into tok.
+ */
+int
+au_fetch_tok(tokenstr_t *tok, u_char *buf, int len)
+{
+
+ if (len <= 0)
+ return (-1);
+
+ tok->len = 1;
+ tok->data = buf;
+ tok->id = *buf;
+
+ switch(tok->id) {
+ case AUT_HEADER32:
+ return (fetch_header32_tok(tok, buf, len));
+
+ case AUT_HEADER32_EX:
+ return (fetch_header32_ex_tok(tok, buf, len));
+
+ case AUT_HEADER64:
+ return (fetch_header64_tok(tok, buf, len));
+
+ case AUT_HEADER64_EX:
+ return (fetch_header64_ex_tok(tok, buf, len));
+
+ case AUT_TRAILER:
+ return (fetch_trailer_tok(tok, buf, len));
+
+ case AUT_ARG32:
+ return (fetch_arg32_tok(tok, buf, len));
+
+ case AUT_ARG64:
+ return (fetch_arg64_tok(tok, buf, len));
+
+ case AUT_ATTR32:
+ return (fetch_attr32_tok(tok, buf, len));
+
+ case AUT_ATTR64:
+ return (fetch_attr64_tok(tok, buf, len));
+
+ case AUT_EXIT:
+ return (fetch_exit_tok(tok, buf, len));
+
+ case AUT_EXEC_ARGS:
+ return (fetch_execarg_tok(tok, buf, len));
+
+ case AUT_EXEC_ENV:
+ return (fetch_execenv_tok(tok, buf, len));
+
+ case AUT_OTHER_FILE32:
+ return (fetch_file_tok(tok, buf, len));
+
+ case AUT_NEWGROUPS:
+ return (fetch_newgroups_tok(tok, buf, len));
+
+ case AUT_IN_ADDR:
+ return (fetch_inaddr_tok(tok, buf, len));
+
+ case AUT_IN_ADDR_EX:
+ return (fetch_inaddr_ex_tok(tok, buf, len));
+
+ case AUT_IP:
+ return (fetch_ip_tok(tok, buf, len));
+
+ case AUT_IPC:
+ return (fetch_ipc_tok(tok, buf, len));
+
+ case AUT_IPC_PERM:
+ return (fetch_ipcperm_tok(tok, buf, len));
+
+ case AUT_IPORT:
+ return (fetch_iport_tok(tok, buf, len));
+
+ case AUT_OPAQUE:
+ return (fetch_opaque_tok(tok, buf, len));
+
+ case AUT_PATH:
+ return (fetch_path_tok(tok, buf, len));
+
+ case AUT_PROCESS32:
+ return (fetch_process32_tok(tok, buf, len));
+
+ case AUT_PROCESS32_EX:
+ return (fetch_process32ex_tok(tok, buf, len));
+
+ case AUT_RETURN32:
+ return (fetch_return32_tok(tok, buf, len));
+
+ case AUT_RETURN64:
+ return (fetch_return64_tok(tok, buf, len));
+
+ case AUT_SEQ:
+ return (fetch_seq_tok(tok, buf, len));
+
+ case AUT_SOCKET:
+ return (fetch_socket_tok(tok, buf, len));
+
+ case AUT_SOCKINET32:
+ return (fetch_sock_inet32_tok(tok, buf, len));
+
+ case AUT_SOCKUNIX:
+ return (fetch_sock_unix_tok(tok, buf, len));
+
+ case AUT_SUBJECT32:
+ return (fetch_subject32_tok(tok, buf, len));
+
+ case AUT_SUBJECT64:
+ return (fetch_subject64_tok(tok, buf, len));
+
+ case AUT_SUBJECT32_EX:
+ return (fetch_subject32ex_tok(tok, buf, len));
+
+ case AUT_TEXT:
+ return (fetch_text_tok(tok, buf, len));
+
+ case AUT_SOCKET_EX:
+ return (fetch_socketex32_tok(tok, buf, len));
+
+ case AUT_DATA:
+ return (fetch_arb_tok(tok, buf, len));
+
+ default:
+ return (fetch_invalid_tok(tok, buf, len));
+ }
+}
+
+/*
+ * 'prints' the token out to outfp
+ */
+void
+au_print_tok(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm)
+{
+
+ switch(tok->id) {
+ case AUT_HEADER32:
+ print_header32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_HEADER32_EX:
+ print_header32_ex_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_HEADER64:
+ print_header64_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_HEADER64_EX:
+ print_header64_ex_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_TRAILER:
+ print_trailer_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_ARG32:
+ print_arg32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_ARG64:
+ print_arg64_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_DATA:
+ print_arb_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_ATTR32:
+ print_attr32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_ATTR64:
+ print_attr64_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_EXIT:
+ print_exit_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_EXEC_ARGS:
+ print_execarg_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_EXEC_ENV:
+ print_execenv_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_OTHER_FILE32:
+ print_file_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_NEWGROUPS:
+ print_newgroups_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IN_ADDR:
+ print_inaddr_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IN_ADDR_EX:
+ print_inaddr_ex_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IP:
+ print_ip_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IPC:
+ print_ipc_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IPC_PERM:
+ print_ipcperm_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_IPORT:
+ print_iport_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_OPAQUE:
+ print_opaque_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_PATH:
+ print_path_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_PROCESS32:
+ print_process32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_PROCESS32_EX:
+ print_process32ex_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_RETURN32:
+ print_return32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_RETURN64:
+ print_return64_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SEQ:
+ print_seq_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SOCKET:
+ print_socket_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SOCKINET32:
+ print_sock_inet32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SOCKUNIX:
+ print_sock_unix_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SUBJECT32:
+ print_subject32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SUBJECT64:
+ print_subject64_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SUBJECT32_EX:
+ print_subject32ex_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_TEXT:
+ print_text_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ case AUT_SOCKET_EX:
+ print_socketex32_tok(outfp, tok, del, raw, sfrm);
+ return;
+
+ default:
+ print_invalid_tok(outfp, tok, del, raw, sfrm);
+ }
+}
+
+/*
+ * Read a record from the file pointer, store data in buf memory for buf is
+ * also allocated in this function and has to be free'd outside this call.
+ *
+ * au_read_rec() handles two possibilities: a stand-alone file token, or a
+ * complete audit record.
+ *
+ * XXXRW: Note that if we hit an error, we leave the stream in an unusable
+ * state, because it will be partly offset into a record. We should rewind
+ * or do something more intelligent. Particularly interesting is the case
+ * where we perform a partial read of a record from a non-blockable file
+ * descriptor. We should return the partial read and continue...?
+ */
+int
+au_read_rec(FILE *fp, u_char **buf)
+{
+ u_char *bptr;
+ u_int32_t recsize;
+ u_int32_t bytestoread;
+ u_char type;
+
+ u_int32_t sec, msec;
+ u_int16_t filenamelen;
+
+ type = fgetc(fp);
+
+ switch (type) {
+ case AUT_HEADER32:
+ case AUT_HEADER32_EX:
+ case AUT_HEADER64:
+ case AUT_HEADER64_EX:
+ /* read the record size from the token */
+ if (fread(&recsize, 1, sizeof(u_int32_t), fp) <
+ sizeof(u_int32_t)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ recsize = be32toh(recsize);
+
+ /* Check for recsize sanity */
+ if (recsize < (sizeof(u_int32_t) + sizeof(u_char))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *buf = malloc(recsize * sizeof(u_char));
+ if (*buf == NULL)
+ return (-1);
+ bptr = *buf;
+ memset(bptr, 0, recsize);
+
+ /* store the token contents already read, back to the buffer*/
+ *bptr = type;
+ bptr++;
+ be32enc(bptr, recsize);
+ bptr += sizeof(u_int32_t);
+
+ /* now read remaining record bytes */
+ bytestoread = recsize - (sizeof(u_int32_t) + sizeof(u_char));
+
+ if (fread(bptr, 1, bytestoread, fp) < bytestoread) {
+ free(*buf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
+
+ case AUT_OTHER_FILE32:
+ /*
+ * The file token is variable-length, as it includes a
+ * pathname. As a result, we have to read incrementally
+ * until we know the total length, then allocate space and
+ * read the rest.
+ */
+ if (fread(&sec, 1, sizeof(sec), fp) < sizeof(sec)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (fread(&msec, 1, sizeof(msec), fp) < sizeof(msec)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (fread(&filenamelen, 1, sizeof(filenamelen), fp) <
+ sizeof(filenamelen)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ recsize = sizeof(type) + sizeof(sec) + sizeof(msec) +
+ sizeof(filenamelen) + ntohs(filenamelen);
+ *buf = malloc(recsize);
+ if (*buf == NULL)
+ return (-1);
+ bptr = *buf;
+
+ bcopy(&type, bptr, sizeof(type));
+ bptr += sizeof(type);
+ bcopy(&sec, bptr, sizeof(sec));
+ bptr += sizeof(sec);
+ bcopy(&msec, bptr, sizeof(msec));
+ bptr += sizeof(msec);
+ bcopy(&filenamelen, bptr, sizeof(filenamelen));
+ bptr += sizeof(filenamelen);
+
+ if (fread(bptr, 1, ntohs(filenamelen), fp) <
+ ntohs(filenamelen)) {
+ free(buf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (recsize);
+}
diff --git a/contrib/openbsm/libbsm/bsm_mask.c b/contrib/openbsm/libbsm/bsm_mask.c
new file mode 100644
index 0000000..b575bbc
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_mask.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2005 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_mask.c#11 $
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bsm/libbsm.h>
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* MT-Safe */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static int firsttime = 1;
+
+/*
+ * XXX ev_cache, once created, sticks around until the calling program exits.
+ * This may or may not be a problem as far as absolute memory usage goes, but
+ * at least there don't appear to be any leaks in using the cache.
+ *
+ * XXXRW: Note that despite (mutex), load_event_table() could race with
+ * other consumers of the getauevents() API.
+ */
+struct audit_event_map {
+ char ev_name[AU_EVENT_NAME_MAX];
+ char ev_desc[AU_EVENT_DESC_MAX];
+ struct au_event_ent ev;
+ LIST_ENTRY(audit_event_map) ev_list;
+};
+static LIST_HEAD(, audit_event_map) ev_cache;
+
+static struct audit_event_map *
+audit_event_map_alloc(void)
+{
+ struct audit_event_map *aemp;
+
+ aemp = malloc(sizeof(*aemp));
+ if (aemp == NULL)
+ return (aemp);
+ bzero(aemp, sizeof(*aemp));
+ aemp->ev.ae_name = aemp->ev_name;
+ aemp->ev.ae_desc = aemp->ev_desc;
+ return (aemp);
+}
+
+static void
+audit_event_map_free(struct audit_event_map *aemp)
+{
+
+ free(aemp);
+}
+
+/*
+ * When reading into the cache fails, we need to flush the entire cache to
+ * prevent it from containing some but not all records.
+ */
+static void
+flush_cache(void)
+{
+ struct audit_event_map *aemp;
+
+ /* XXX: Would assert 'mutex'. */
+
+ while ((aemp = LIST_FIRST(&ev_cache)) != NULL) {
+ LIST_REMOVE(aemp, ev_list);
+ audit_event_map_free(aemp);
+ }
+}
+
+static int
+load_event_table(void)
+{
+ struct audit_event_map *aemp;
+ struct au_event_ent *ep;
+
+ /*
+ * XXX: Would assert 'mutex'.
+ * Loading of the cache happens only once; dont check if cache is
+ * already loaded.
+ */
+ LIST_INIT(&ev_cache);
+ setauevent(); /* Rewind to beginning of entries. */
+ do {
+ aemp = audit_event_map_alloc();
+ if (aemp == NULL) {
+ flush_cache();
+ return (-1);
+ }
+ ep = getauevent_r(&aemp->ev);
+ if (ep != NULL)
+ LIST_INSERT_HEAD(&ev_cache, aemp, ev_list);
+ else
+ audit_event_map_free(aemp);
+ } while (ep != NULL);
+ return (1);
+}
+
+/*
+ * Read the event with the matching event number from the cache.
+ */
+static struct au_event_ent *
+read_from_cache(au_event_t event)
+{
+ struct audit_event_map *elem;
+
+ /* XXX: Would assert 'mutex'. */
+
+ LIST_FOREACH(elem, &ev_cache, ev_list) {
+ if (elem->ev.ae_number == event)
+ return (&elem->ev);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Check if the audit event is preselected against the preselection mask.
+ */
+int
+au_preselect(au_event_t event, au_mask_t *mask_p, int sorf, int flag)
+{
+ struct au_event_ent *ev;
+ au_class_t effmask = 0;
+
+ if (mask_p == NULL)
+ return (-1);
+
+
+ pthread_mutex_lock(&mutex);
+ if (firsttime) {
+ firsttime = 0;
+ if ( -1 == load_event_table()) {
+ pthread_mutex_unlock(&mutex);
+ return (-1);
+ }
+ }
+ switch (flag) {
+ case AU_PRS_REREAD:
+ flush_cache();
+ if (load_event_table() == -1) {
+ pthread_mutex_unlock(&mutex);
+ return (-1);
+ }
+ ev = read_from_cache(event);
+ break;
+ case AU_PRS_USECACHE:
+ ev = read_from_cache(event);
+ break;
+ default:
+ ev = NULL;
+ }
+ if (ev == NULL) {
+ pthread_mutex_unlock(&mutex);
+ return (-1);
+ }
+ if (sorf & AU_PRS_SUCCESS)
+ effmask |= (mask_p->am_success & ev->ae_class);
+ if (sorf & AU_PRS_FAILURE)
+ effmask |= (mask_p->am_failure & ev->ae_class);
+ pthread_mutex_unlock(&mutex);
+ if (effmask != 0)
+ return (1);
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_notify.c b/contrib/openbsm/libbsm/bsm_notify.c
new file mode 100644
index 0000000..92f9b50
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_notify.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_notify.c#8 $
+ */
+
+#ifdef __APPLE__
+
+/*
+ * Based on sample code from Marc Majka.
+ */
+#include <notify.h>
+#include <string.h> /* strerror() */
+#include <sys/errno.h> /* errno */
+#include <bsm/libbsm.h>
+#include <stdint.h> /* uint32_t */
+#include <syslog.h> /* syslog() */
+#include <stdarg.h> /* syslog() */
+
+/* If 1, assumes a kernel that sends the right notification. */
+#define AUDIT_NOTIFICATION_ENABLED 1
+
+#if AUDIT_NOTIFICATION_ENABLED
+static int token = 0;
+#endif /* AUDIT_NOTIFICATION_ENABLED */
+
+static long au_cond = AUC_UNSET; /* <bsm/audit.h> */
+
+uint32_t
+au_notify_initialize(void)
+{
+#if AUDIT_NOTIFICATION_ENABLED
+ uint32_t status, ignore_first;
+
+ status = notify_register_check(__BSM_INTERNAL_NOTIFY_KEY, &token);
+ if (status != NOTIFY_STATUS_OK)
+ return (status);
+ status = notify_check(token, &ignore_first);
+ if (status != NOTIFY_STATUS_OK)
+ return (status);
+#endif
+
+ if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
+ syslog(LOG_ERR, "Initial audit status check failed (%s)",
+ strerror(errno));
+ if (errno == ENOSYS) /* auditon() unimplemented. */
+ return (AU_UNIMPL);
+ return (NOTIFY_STATUS_FAILED); /* Is there a better code? */
+ }
+ return (NOTIFY_STATUS_OK);
+}
+
+int
+au_notify_terminate(void)
+{
+
+#if AUDIT_NOTIFICATION_ENABLED
+ return ((notify_cancel(token) == NOTIFY_STATUS_OK) ? 0 : -1);
+#else
+ return (0);
+#endif
+}
+
+/*
+ * On error of any notify(3) call, reset 'au_cond' to ensure we re-run
+ * au_notify_initialize() next time 'round--but assume auditing is on. This
+ * is a slight performance hit if auditing is off, but at least the system
+ * will behave correctly. The notification calls are unlikely to fail,
+ * anyway.
+ */
+int
+au_get_state(void)
+{
+#if AUDIT_NOTIFICATION_ENABLED
+ uint32_t did_notify;
+#endif
+ int status;
+
+ /*
+ * Don't make the client initialize this set of routines, but take the
+ * slight performance hit by checking ourselves every time.
+ */
+ if (au_cond == AUC_UNSET) {
+ status = au_notify_initialize();
+ if (status != NOTIFY_STATUS_OK) {
+ if (status == AU_UNIMPL)
+ return (AU_UNIMPL);
+ return (AUC_AUDITING);
+ } else
+ return (au_cond);
+ }
+#if AUDIT_NOTIFICATION_ENABLED
+ status = notify_check(token, &did_notify);
+ if (status != NOTIFY_STATUS_OK) {
+ au_cond = AUC_UNSET;
+ return (AUC_AUDITING);
+ }
+
+ if (did_notify == 0)
+ return (au_cond);
+#endif
+
+ if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
+ /* XXX Reset au_cond to AUC_UNSET? */
+ syslog(LOG_ERR, "Audit status check failed (%s)",
+ strerror(errno));
+ if (errno == ENOSYS) /* Function unimplemented. */
+ return (AU_UNIMPL);
+ return (errno);
+ }
+
+ switch (au_cond) {
+ case AUC_NOAUDIT: /* Auditing suspended. */
+ case AUC_DISABLED: /* Auditing shut off. */
+ return (AUC_NOAUDIT);
+
+ case AUC_UNSET: /* Uninitialized; shouldn't get here. */
+ case AUC_AUDITING: /* Audit on. */
+ default:
+ return (AUC_AUDITING);
+ }
+}
+
+#endif /* !__APPLE__ */
diff --git a/contrib/openbsm/libbsm/bsm_token.c b/contrib/openbsm/libbsm/bsm_token.c
new file mode 100644
index 0000000..d7eadb2
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_token.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2005 SPARTA, Inc.
+ * All rights reserved.
+ *
+ * This code was developed in part by Robert N. M. Watson, Senior Principal
+ * Scientist, SPARTA, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_token.c#34 $
+ */
+
+#include <sys/types.h>
+#ifdef __APPLE__
+#include <compat/endian.h>
+#else /* !__APPLE__ */
+#include <sys/endian.h>
+#endif /* __APPLE__*/
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#include <sys/ipc.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socketvar.h>
+
+#include <bsm/audit_internal.h>
+#include <bsm/libbsm.h>
+
+#define GET_TOKEN_AREA(t, dptr, length) do { \
+ (t) = malloc(sizeof(token_t)); \
+ if ((t) != NULL) { \
+ (t)->len = (length); \
+ (dptr) = (t->t_data) = malloc((length) * sizeof(u_char)); \
+ if ((dptr) == NULL) { \
+ free(t); \
+ (t) = NULL; \
+ } else \
+ memset((dptr), 0, (length)); \
+ } else \
+ (dptr) = NULL; \
+ assert(t == NULL || dptr != NULL); \
+} while (0)
+
+/*
+ * token ID 1 byte
+ * argument # 1 byte
+ * argument value 4 bytes/8 bytes (32-bit/64-bit value)
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_arg32(char n, char *text, u_int32_t v)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ARG32);
+ ADD_U_CHAR(dptr, n);
+ ADD_U_INT32(dptr, v);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+
+}
+
+token_t *
+au_to_arg64(char n, char *text, u_int64_t v)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) +
+ sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ARG64);
+ ADD_U_CHAR(dptr, n);
+ ADD_U_INT64(dptr, v);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+
+}
+
+token_t *
+au_to_arg(char n, char *text, u_int32_t v)
+{
+
+ return (au_to_arg32(n, text, v));
+}
+
+#if defined(_KERNEL) || defined(KERNEL)
+/*
+ * token ID 1 byte
+ * file access mode 4 bytes
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * file system ID 4 bytes
+ * node ID 8 bytes
+ * device 4 bytes/8 bytes (32-bit/64-bit)
+ */
+token_t *
+au_to_attr32(struct vnode_au_info *vni)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t pad0_16 = 0;
+ u_int16_t pad0_32 = 0;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
+ 3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_ATTR32);
+
+ /*
+ * Darwin defines the size for the file mode
+ * as 2 bytes; BSM defines 4 so pad with 0
+ */
+ ADD_U_INT16(dptr, pad0_16);
+ ADD_U_INT16(dptr, vni->vn_mode);
+
+ ADD_U_INT32(dptr, vni->vn_uid);
+ ADD_U_INT32(dptr, vni->vn_gid);
+ ADD_U_INT32(dptr, vni->vn_fsid);
+
+ /*
+ * Some systems use 32-bit file ID's, other's use 64-bit file IDs.
+ * Attempt to handle both, and let the compiler sort it out. If we
+ * could pick this out at compile-time, it would be better, so as to
+ * avoid the else case below.
+ */
+ if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
+ ADD_U_INT32(dptr, pad0_32);
+ ADD_U_INT32(dptr, vni->vn_fileid);
+ } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
+ ADD_U_INT64(dptr, vni->vn_fileid);
+ else
+ ADD_U_INT64(dptr, 0LL);
+
+ ADD_U_INT32(dptr, vni->vn_dev);
+
+ return (t);
+}
+
+token_t *
+au_to_attr64(struct vnode_au_info *vni)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_attr(struct vnode_au_info *vni)
+{
+
+ return (au_to_attr32(vni));
+}
+#endif /* !(defined(_KERNEL) || defined(KERNEL) */
+
+/*
+ * token ID 1 byte
+ * how to print 1 byte
+ * basic unit 1 byte
+ * unit count 1 byte
+ * data items (depends on basic unit)
+ */
+token_t *
+au_to_data(char unit_print, char unit_type, char unit_count, char *p)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ size_t datasize, totdata;
+
+ /* Determine the size of the basic unit. */
+ switch (unit_type) {
+ case AUR_BYTE:
+ datasize = AUR_BYTE_SIZE;
+ break;
+
+ case AUR_SHORT:
+ datasize = AUR_SHORT_SIZE;
+ break;
+
+ case AUR_LONG:
+ datasize = AUR_LONG_SIZE;
+ break;
+
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ totdata = datasize * unit_count;
+
+ GET_TOKEN_AREA(t, dptr, totdata + 4 * sizeof(u_char));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_DATA);
+ ADD_U_CHAR(dptr, unit_print);
+ ADD_U_CHAR(dptr, unit_type);
+ ADD_U_CHAR(dptr, unit_count);
+ ADD_MEM(dptr, p, totdata);
+
+ return (t);
+}
+
+
+/*
+ * token ID 1 byte
+ * status 4 bytes
+ * return value 4 bytes
+ */
+token_t *
+au_to_exit(int retval, int err)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXIT);
+ ADD_U_INT32(dptr, err);
+ ADD_U_INT32(dptr, retval);
+
+ return (t);
+}
+
+/*
+ */
+token_t *
+au_to_groups(int *groups)
+{
+
+ return (au_to_newgroups(BSM_MAX_GROUPS, groups));
+}
+
+/*
+ * token ID 1 byte
+ * number groups 2 bytes
+ * group list count * 4 bytes
+ */
+token_t *
+au_to_newgroups(u_int16_t n, gid_t *groups)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ int i;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
+ n * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_NEWGROUPS);
+ ADD_U_INT16(dptr, n);
+ for (i = 0; i < n; i++)
+ ADD_U_INT32(dptr, groups[i]);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * internet address 4 bytes
+ */
+token_t *
+au_to_in_addr(struct in_addr *internet_addr)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IN_ADDR);
+ ADD_U_INT32(dptr, internet_addr->s_addr);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * address type/length 4 bytes
+ * Address 16 bytes
+ */
+token_t *
+au_to_in_addr_ex(struct in6_addr *internet_addr)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t type = AF_INET6;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
+ ADD_U_INT32(dptr, type);
+ ADD_U_INT32(dptr, internet_addr->__u6_addr.__u6_addr32[0]);
+ ADD_U_INT32(dptr, internet_addr->__u6_addr.__u6_addr32[1]);
+ ADD_U_INT32(dptr, internet_addr->__u6_addr.__u6_addr32[2]);
+ ADD_U_INT32(dptr, internet_addr->__u6_addr.__u6_addr32[3]);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * ip header 20 bytes
+ */
+token_t *
+au_to_ip(struct ip *ip)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IP);
+ /*
+ * XXXRW: Any byte order work needed on the IP header before writing?
+ */
+ ADD_MEM(dptr, ip, sizeof(struct ip));
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * object ID type 1 byte
+ * object ID 4 bytes
+ */
+token_t *
+au_to_ipc(char type, int id)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPC);
+ ADD_U_CHAR(dptr, type);
+ ADD_U_INT32(dptr, id);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * owner user ID 4 bytes
+ * owner group ID 4 bytes
+ * creator user ID 4 bytes
+ * creator group ID 4 bytes
+ * access mode 4 bytes
+ * slot sequence # 4 bytes
+ * key 4 bytes
+ */
+token_t *
+au_to_ipc_perm(struct ipc_perm *perm)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t pad0 = 0;
+
+ GET_TOKEN_AREA(t, dptr, 12 * sizeof(u_int16_t) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPC_PERM);
+
+ /*
+ * Darwin defines the sizes for ipc_perm members
+ * as 2 bytes; BSM defines 4 so pad with 0
+ */
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->uid);
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->gid);
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->cuid);
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->cgid);
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->mode);
+
+ ADD_U_INT16(dptr, pad0);
+ ADD_U_INT16(dptr, perm->seq);
+
+ ADD_U_INT32(dptr, perm->key);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * port IP address 2 bytes
+ */
+token_t *
+au_to_iport(u_int16_t iport)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_IPORT);
+ ADD_U_INT16(dptr, iport);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * size 2 bytes
+ * data size bytes
+ */
+token_t *
+au_to_opaque(char *data, u_int16_t bytes)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_OPAQUE);
+ ADD_U_INT16(dptr, bytes);
+ ADD_MEM(dptr, data, bytes);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * seconds of time 4 bytes
+ * milliseconds of time 4 bytes
+ * file name len 2 bytes
+ * file pathname N bytes + 1 terminating NULL byte
+ */
+token_t *
+#if defined(KERNEL) || defined(_KERNEL)
+au_to_file(char *file, struct timeval tm)
+#else
+au_to_file(char *file)
+#endif
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t filelen;
+ u_int32_t timems;
+#if !defined(KERNEL) && !defined(_KERNEL)
+ struct timeval tm;
+ struct timezone tzp;
+
+ if (gettimeofday(&tm, &tzp) == -1)
+ return (NULL);
+#endif
+
+ filelen = strlen(file);
+ filelen += 1;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
+ sizeof(u_int16_t) + filelen);
+ if (t == NULL)
+ return (NULL);
+
+ timems = tm.tv_usec/1000;
+
+ ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+ ADD_U_INT16(dptr, filelen);
+ ADD_STRING(dptr, file, filelen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * text length 2 bytes
+ * text N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_text(char *text)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_TEXT);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * path length 2 bytes
+ * path N bytes + 1 terminating NULL byte
+ */
+token_t *
+au_to_path(char *text)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t textlen;
+
+ textlen = strlen(text);
+ textlen += 1;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PATH);
+ ADD_U_INT16(dptr, textlen);
+ ADD_STRING(dptr, text, textlen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine address 4 bytes
+ */
+token_t *
+au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS32);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->port);
+ ADD_U_INT32(dptr, tid->machine);
+
+ return (t);
+}
+
+token_t *
+au_to_process64(__unused au_id_t auid, __unused uid_t euid,
+ __unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
+ __unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_process(__unused au_id_t auid, __unused uid_t euid,
+ __unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
+ __unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
+{
+
+ return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * address type-len 4 bytes
+ * machine address 16 bytes
+ */
+token_t *
+au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ ADD_U_INT32(dptr, tid->at_addr[0]);
+ ADD_U_INT32(dptr, tid->at_addr[1]);
+ ADD_U_INT32(dptr, tid->at_addr[2]);
+ ADD_U_INT32(dptr, tid->at_addr[3]);
+
+ return (t);
+}
+
+token_t *
+au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * error status 1 byte
+ * return value 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+token_t *
+au_to_return32(char status, u_int32_t ret)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_RETURN32);
+ ADD_U_CHAR(dptr, status);
+ ADD_U_INT32(dptr, ret);
+
+ return (t);
+}
+
+token_t *
+au_to_return64(char status, u_int64_t ret)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_RETURN64);
+ ADD_U_CHAR(dptr, status);
+ ADD_U_INT64(dptr, ret);
+
+ return (t);
+}
+
+token_t *
+au_to_return(char status, u_int32_t ret)
+{
+
+ return (au_to_return32(status, ret));
+}
+
+/*
+ * token ID 1 byte
+ * sequence number 4 bytes
+ */
+token_t *
+au_to_seq(long audit_count)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SEQ);
+ ADD_U_INT32(dptr, audit_count);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * socket type 2 bytes
+ * local port 2 bytes
+ * local Internet address 4 bytes
+ * remote port 2 bytes
+ * remote Internet address 4 bytes
+ */
+token_t *
+au_to_socket(struct socket *so)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+/*
+ * token ID 1 byte
+ * socket type 2 bytes
+ * local port 2 bytes
+ * address type/length 4 bytes
+ * local Internet address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * remote port 4 bytes
+ * address type/length 4 bytes
+ * remote Internet address 4 bytes/16 bytes (IPv4/IPv6 address)
+ */
+token_t *
+au_to_socket_ex_32(u_int16_t lp, u_int16_t rp, struct sockaddr *la,
+ struct sockaddr *ra)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_socket_ex_128(u_int16_t lp, u_int16_t rp, struct sockaddr *la,
+ struct sockaddr *ra)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+/*
+ * token ID 1 byte
+ * socket family 2 bytes
+ * path 104 bytes
+ */
+token_t *
+au_to_sock_unix(struct sockaddr_un *so)
+{
+ token_t *t;
+ u_char *dptr;
+
+ GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AU_SOCK_UNIX_TOKEN);
+ /* BSM token has two bytes for family */
+ ADD_U_CHAR(dptr, 0);
+ ADD_U_CHAR(dptr, so->sun_family);
+ ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * socket family 2 bytes
+ * local port 2 bytes
+ * socket address 4 bytes
+ */
+token_t *
+au_to_sock_inet32(struct sockaddr_in *so)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
+ sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKINET32);
+ /*
+ * In Darwin, sin_family is one octet, but BSM defines the token
+ * to store two. So we copy in a 0 first.
+ */
+ ADD_U_CHAR(dptr, 0);
+ ADD_U_CHAR(dptr, so->sin_family);
+ ADD_U_INT16(dptr, so->sin_port);
+ ADD_U_INT32(dptr, so->sin_addr.s_addr);
+
+ return (t);
+
+}
+
+token_t *
+au_to_sock_inet128(struct sockaddr_in6 *so)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
+ 4 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SOCKINET128);
+ /*
+ * In Darwin, sin6_family is one octet, but BSM defines the token
+ * to store two. So we copy in a 0 first.
+ */
+ ADD_U_CHAR(dptr, 0);
+ ADD_U_CHAR(dptr, so->sin6_family);
+
+ ADD_U_INT16(dptr, so->sin6_port);
+ ADD_U_INT32(dptr, so->sin6_addr.__u6_addr.__u6_addr32[0]);
+ ADD_U_INT32(dptr, so->sin6_addr.__u6_addr.__u6_addr32[1]);
+ ADD_U_INT32(dptr, so->sin6_addr.__u6_addr.__u6_addr32[2]);
+ ADD_U_INT32(dptr, so->sin6_addr.__u6_addr.__u6_addr32[3]);
+
+ return (t);
+
+}
+
+token_t *
+au_to_sock_inet(struct sockaddr_in *so)
+{
+
+ return (au_to_sock_inet32(so));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * machine address 4 bytes
+ */
+token_t *
+au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT32);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->port);
+ ADD_U_INT32(dptr, tid->machine);
+
+ return (t);
+}
+
+token_t *
+au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
+ pid_t pid, au_asid_t sid, au_tid_t *tid)
+{
+
+ return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+/*
+ * token ID 1 byte
+ * audit ID 4 bytes
+ * effective user ID 4 bytes
+ * effective group ID 4 bytes
+ * real user ID 4 bytes
+ * real group ID 4 bytes
+ * process ID 4 bytes
+ * session ID 4 bytes
+ * terminal ID
+ * port ID 4 bytes/8 bytes (32-bit/64-bit value)
+ * address type/length 4 bytes
+ * machine address 16 bytes
+ */
+token_t *
+au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
+ ADD_U_INT32(dptr, auid);
+ ADD_U_INT32(dptr, euid);
+ ADD_U_INT32(dptr, egid);
+ ADD_U_INT32(dptr, ruid);
+ ADD_U_INT32(dptr, rgid);
+ ADD_U_INT32(dptr, pid);
+ ADD_U_INT32(dptr, sid);
+ ADD_U_INT32(dptr, tid->at_port);
+ ADD_U_INT32(dptr, tid->at_type);
+ ADD_U_INT32(dptr, tid->at_addr[0]);
+ ADD_U_INT32(dptr, tid->at_addr[1]);
+ ADD_U_INT32(dptr, tid->at_addr[2]);
+ ADD_U_INT32(dptr, tid->at_addr[3]);
+
+ return (t);
+}
+
+token_t *
+au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
+ gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
+{
+
+ return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
+ tid));
+}
+
+#if !defined(_KERNEL) && !defined(KERNEL)
+/*
+ * Collects audit information for the current process
+ * and creates a subject token from it
+ */
+token_t *
+au_to_me(void)
+{
+ auditinfo_t auinfo;
+
+ if (getaudit(&auinfo) != 0)
+ return (NULL);
+
+ return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(),
+ getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid));
+}
+#endif
+
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_args(const char **args)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ const char *nextarg;
+ int i, count = 0;
+ size_t totlen = 0;
+
+ nextarg = *args;
+
+ while (nextarg != NULL) {
+ int nextlen;
+
+ nextlen = strlen(nextarg);
+ totlen += nextlen + 1;
+ count++;
+ nextarg = *(args + count);
+ }
+
+ totlen += count * sizeof(char); /* nul terminations. */
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
+ ADD_U_INT32(dptr, count);
+
+ for (i = 0; i < count; i++) {
+ nextarg = *(args + i);
+ ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
+ }
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_env(const char **env)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ int i, count = 0;
+ size_t totlen = 0;
+ const char *nextenv;
+
+ nextenv = *env;
+
+ while (nextenv != NULL) {
+ int nextlen;
+
+ nextlen = strlen(nextenv);
+ totlen += nextlen + 1;
+ count++;
+ nextenv = *(env + count);
+ }
+
+ totlen += sizeof(char) * count;
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_EXEC_ENV);
+ ADD_U_INT32(dptr, count);
+
+ for (i = 0; i < count; i++) {
+ nextenv = *(env + i);
+ ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
+ }
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * record byte count 4 bytes
+ * version # 1 byte [2]
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
+ */
+token_t *
+#if defined(KERNEL) || defined(_KERNEL)
+au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm)
+#else
+au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod)
+#endif
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t timems;
+#if !defined(KERNEL) && !defined(_KERNEL)
+ struct timeval tm;
+ struct timezone tzp;
+
+ if (gettimeofday(&tm, &tzp) == -1)
+ return (NULL);
+#endif
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_HEADER32);
+ ADD_U_INT32(dptr, rec_size);
+ ADD_U_CHAR(dptr, HEADER_VERSION);
+ ADD_U_INT16(dptr, e_type);
+ ADD_U_INT16(dptr, e_mod);
+
+ timems = tm.tv_usec/1000;
+ /* Add the timestamp */
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+
+ return (t);
+}
+
+token_t *
+au_to_header64(__unused int rec_size, __unused au_event_t e_type,
+ __unused au_emod_t e_mod)
+{
+
+ errno = ENOTSUP;
+ return (NULL);
+}
+
+token_t *
+au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod)
+{
+
+ return (au_to_header32(rec_size, e_type, e_mod));
+}
+
+/*
+ * token ID 1 byte
+ * trailer magic number 2 bytes
+ * record byte count 4 bytes
+ */
+token_t *
+au_to_trailer(int rec_size)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int16_t magic = TRAILER_PAD_MAGIC;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
+ sizeof(u_int32_t));
+ if (t == NULL)
+ return (NULL);
+
+ ADD_U_CHAR(dptr, AUT_TRAILER);
+ ADD_U_INT16(dptr, magic);
+ ADD_U_INT32(dptr, rec_size);
+
+ return (t);
+}
diff --git a/contrib/openbsm/libbsm/bsm_user.c b/contrib/openbsm/libbsm/bsm_user.c
new file mode 100644
index 0000000..3927423
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_user.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#14 $
+ */
+
+#include <bsm/libbsm.h>
+
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Parse the contents of the audit_user file into au_user_ent structures.
+ */
+
+static FILE *fp = NULL;
+static char linestr[AU_LINE_MAX];
+static const char *user_delim = ":";
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Parse one line from the audit_user file into the au_user_ent structure.
+ */
+static struct au_user_ent *
+userfromstr(char *str, struct au_user_ent *u)
+{
+ char *username, *always, *never;
+ char *last;
+
+ username = strtok_r(str, user_delim, &last);
+ always = strtok_r(NULL, user_delim, &last);
+ never = strtok_r(NULL, user_delim, &last);
+
+ if ((username == NULL) || (always == NULL) || (never == NULL))
+ return (NULL);
+
+ if (strlen(username) >= AU_USER_NAME_MAX)
+ return (NULL);
+
+ strcpy(u->au_name, username);
+ if (getauditflagsbin(always, &(u->au_always)) == -1)
+ return (NULL);
+
+ if (getauditflagsbin(never, &(u->au_never)) == -1)
+ return (NULL);
+
+ return (u);
+}
+
+/*
+ * Rewind to beginning of the file
+ */
+static void
+setauuser_locked(void)
+{
+
+ if (fp != NULL)
+ fseek(fp, 0, SEEK_SET);
+}
+
+void
+setauuser(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ setauuser_locked();
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Close the file descriptor
+ */
+void
+endauuser(void)
+{
+
+ pthread_mutex_lock(&mutex);
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ pthread_mutex_unlock(&mutex);
+}
+
+/*
+ * Enumerate the au_user_ent structures from the file
+ */
+static struct au_user_ent *
+getauuserent_r_locked(struct au_user_ent *u)
+{
+ char *nl;
+
+ if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL))
+ return (NULL);
+
+ while (1) {
+ if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
+ return (NULL);
+
+ /* Remove new lines. */
+ if ((nl = strrchr(linestr, '\n')) != NULL)
+ *nl = '\0';
+
+ /* Skip comments. */
+ if (linestr[0] == '#')
+ continue;
+
+ /* Get the next structure. */
+ if (userfromstr(linestr, u) == NULL)
+ return (NULL);
+ break;
+ }
+
+ return (u);
+}
+
+struct au_user_ent *
+getauuserent_r(struct au_user_ent *u)
+{
+ struct au_user_ent *up;
+
+ pthread_mutex_lock(&mutex);
+ up = getauuserent_r_locked(u);
+ pthread_mutex_unlock(&mutex);
+ return (up);
+}
+
+struct au_user_ent *
+getauuserent(void)
+{
+ static char user_ent_name[AU_USER_NAME_MAX];
+ static struct au_user_ent u;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ return (getauuserent_r(&u));
+}
+
+/*
+ * Find a au_user_ent structure matching the given user name.
+ */
+struct au_user_ent *
+getauusernam_r(struct au_user_ent *u, const char *name)
+{
+ struct au_user_ent *up;
+
+ if (name == NULL)
+ return (NULL);
+
+ pthread_mutex_lock(&mutex);
+
+ setauuser_locked();
+ while ((up = getauuserent_r_locked(u)) != NULL) {
+ if (strcmp(name, u->au_name) == 0) {
+ pthread_mutex_unlock(&mutex);
+ return (u);
+ }
+ }
+
+ pthread_mutex_unlock(&mutex);
+ return (NULL);
+
+}
+
+struct au_user_ent *
+getauusernam(const char *name)
+{
+ static char user_ent_name[AU_USER_NAME_MAX];
+ static struct au_user_ent u;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ return (getauusernam_r(&u, name));
+}
+
+/*
+ * Read the default system wide audit classes from audit_control, combine with
+ * the per-user audit class and update the binary preselection mask.
+ */
+int
+au_user_mask(char *username, au_mask_t *mask_p)
+{
+ char auditstring[MAX_AUDITSTRING_LEN + 1];
+ char user_ent_name[AU_USER_NAME_MAX];
+ struct au_user_ent u, *up;
+
+ bzero(&u, sizeof(u));
+ bzero(user_ent_name, sizeof(user_ent_name));
+ u.au_name = user_ent_name;
+
+ /* Get user mask. */
+ if ((up = getauusernam_r(&u, username)) != NULL) {
+ if (-1 == getfauditflags(&up->au_always, &up->au_never,
+ mask_p))
+ return (-1);
+ return (0);
+ }
+
+ /* Read the default system mask. */
+ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
+ if (-1 == getauditflagsbin(auditstring, mask_p))
+ return (-1);
+ return (0);
+ }
+
+ /* No masks defined. */
+ return (-1);
+}
+
+/*
+ * Generate the process audit state by combining the audit masks passed as
+ * parameters with the system audit masks.
+ */
+int
+getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask)
+{
+ char auditstring[MAX_AUDITSTRING_LEN + 1];
+
+ if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL))
+ return (-1);
+
+ lastmask->am_success = 0;
+ lastmask->am_failure = 0;
+
+ /* Get the system mask. */
+ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) {
+ if (getauditflagsbin(auditstring, lastmask) != 0)
+ return (-1);
+ }
+
+ ADDMASK(lastmask, usremask);
+ SUBMASK(lastmask, usrdmask);
+
+ return (0);
+}
diff --git a/contrib/openbsm/libbsm/bsm_wrappers.c b/contrib/openbsm/libbsm/bsm_wrappers.c
new file mode 100644
index 0000000..e7600e7
--- /dev/null
+++ b/contrib/openbsm/libbsm/bsm_wrappers.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#14 $
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <bsm/libbsm.h>
+
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+
+/* These are not advertised in libbsm.h */
+int audit_set_terminal_port(dev_t *p);
+int audit_set_terminal_host(uint32_t *m);
+
+int
+audit_set_terminal_port(dev_t *p)
+{
+ struct stat st;
+
+ if (p == NULL)
+ return (kAUBadParamErr);
+
+ *p = NODEV;
+
+ /* for /usr/bin/login, try fstat() first */
+ if (fstat(STDIN_FILENO, &st) != 0) {
+ if (errno != EBADF) {
+ syslog(LOG_ERR, "fstat() failed (%s)",
+ strerror(errno));
+ return (kAUStatErr);
+ }
+ if (stat("/dev/console", &st) != 0) {
+ syslog(LOG_ERR, "stat() failed (%s)",
+ strerror(errno));
+ return (kAUStatErr);
+ }
+ }
+ *p = st.st_rdev;
+ return (kAUNoErr);
+}
+
+int
+audit_set_terminal_host(uint32_t *m)
+{
+ int name[2] = { CTL_KERN, KERN_HOSTID };
+ size_t len;
+
+ if (m == NULL)
+ return (kAUBadParamErr);
+ *m = 0;
+ len = sizeof(*m);
+ if (sysctl(name, 2, m, &len, NULL, 0) != 0) {
+ syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno));
+ return (kAUSysctlErr);
+ }
+ return (kAUNoErr);
+}
+
+int
+audit_set_terminal_id(au_tid_t *tid)
+{
+ int ret;
+
+ if (tid == NULL)
+ return (kAUBadParamErr);
+ if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr)
+ return (ret);
+ return (audit_set_terminal_host(&tid->machine));
+}
+
+/*
+ * This is OK for those callers who have only one token to write. If you have
+ * multiple tokens that logically form part of the same audit record, you need
+ * to use the existing au_open()/au_write()/au_close() API:
+ *
+ * aufd = au_open();
+ * tok = au_to_random_token_1(...);
+ * au_write(aufd, tok);
+ * tok = au_to_random_token_2(...);
+ * au_write(aufd, tok);
+ * ...
+ * au_close(aufd, 1, AUE_your_event_type);
+ *
+ * Assumes, like all wrapper calls, that the caller has previously checked
+ * that auditing is enabled via the audit_get_state() call.
+ *
+ * XXX: Should be more robust against bad arguments.
+ */
+int
+audit_write(short event_code, token_t *subject, token_t *misctok, char retval,
+ int errcode)
+{
+ int aufd;
+ char *func = "audit_write()";
+ token_t *rettok;
+
+ if ((aufd = au_open()) == -1) {
+ au_free_token(subject);
+ au_free_token(misctok);
+ syslog(LOG_ERR, "%s: au_open() failed", func);
+ return (kAUOpenErr);
+ }
+
+ /* Save subject. */
+ if (subject && au_write(aufd, subject) == -1) {
+ au_free_token(subject);
+ au_free_token(misctok);
+ (void)au_close(aufd, 0, event_code);
+ syslog(LOG_ERR, "%s: write of subject failed", func);
+ return (kAUWriteSubjectTokErr);
+ }
+
+ /* Save the event-specific token. */
+ if (misctok && au_write(aufd, misctok) == -1) {
+ au_free_token(misctok);
+ (void)au_close(aufd, 0, event_code);
+ syslog(LOG_ERR, "%s: write of caller token failed", func);
+ return (kAUWriteCallerTokErr);
+ }
+
+ /* Tokenize and save the return value. */
+ if ((rettok = au_to_return32(retval, errcode)) == NULL) {
+ (void)au_close(aufd, 0, event_code);
+ syslog(LOG_ERR, "%s: au_to_return32() failed", func);
+ return (kAUMakeReturnTokErr);
+ }
+
+ if (au_write(aufd, rettok) == -1) {
+ au_free_token(rettok);
+ (void)au_close(aufd, 0, event_code);
+ syslog(LOG_ERR, "%s: write of return code failed", func);
+ return (kAUWriteReturnTokErr);
+ }
+
+ /*
+ * au_close()'s second argument is "keep": if keep == 0, the record is
+ * discarded. We assume the caller wouldn't have bothered with this
+ * function if it hadn't already decided to keep the record.
+ */
+ if (au_close(aufd, 1, event_code) < 0) {
+ syslog(LOG_ERR, "%s: au_close() failed", func);
+ return (kAUCloseErr);
+ }
+
+ return (kAUNoErr);
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes success; use audit_write_failure() on error.
+ */
+int
+audit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid,
+ gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
+ au_tid_t *tid)
+{
+ char *func = "audit_write_success()";
+ token_t *subject = NULL;
+
+ /* Tokenize and save subject. */
+ subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
+ tid);
+ if (subject == NULL) {
+ syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
+ return kAUMakeSubjectTokErr;
+ }
+
+ return (audit_write(event_code, subject, tok, 0, 0));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes success; use audit_write_failure_self() on error.
+ */
+int
+audit_write_success_self(short event_code, token_t *tok)
+{
+ token_t *subject;
+ char *func = "audit_write_success_self()";
+
+ if ((subject = au_to_me()) == NULL) {
+ syslog(LOG_ERR, "%s: au_to_me() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+
+ return (audit_write(event_code, subject, tok, 0, 0));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes failure; use audit_write_success() otherwise.
+ *
+ * XXX This should let the caller pass an error return value rather than
+ * hard-coding -1.
+ */
+int
+audit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid,
+ uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
+ au_tid_t *tid)
+{
+ char *func = "audit_write_failure()";
+ token_t *subject, *errtok;
+
+ subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid);
+ if (subject == NULL) {
+ syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+
+ /* tokenize and save the error message */
+ if ((errtok = au_to_text(errmsg)) == NULL) {
+ au_free_token(subject);
+ syslog(LOG_ERR, "%s: au_to_text() failed", func);
+ return (kAUMakeTextTokErr);
+ }
+
+ return (audit_write(event_code, subject, errtok, -1, errcode));
+}
+
+/*
+ * Same caveats as audit_write(). In addition, this function explicitly
+ * assumes failure; use audit_write_success_self() otherwise.
+ *
+ * XXX This should let the caller pass an error return value rather than
+ * hard-coding -1.
+ */
+int
+audit_write_failure_self(short event_code, char *errmsg, int errret)
+{
+ char *func = "audit_write_failure_self()";
+ token_t *subject, *errtok;
+
+ if ((subject = au_to_me()) == NULL) {
+ syslog(LOG_ERR, "%s: au_to_me() failed", func);
+ return (kAUMakeSubjectTokErr);
+ }
+ /* tokenize and save the error message */
+ if ((errtok = au_to_text(errmsg)) == NULL) {
+ au_free_token(subject);
+ syslog(LOG_ERR, "%s: au_to_text() failed", func);
+ return (kAUMakeTextTokErr);
+ }
+ return (audit_write(event_code, subject, errtok, -1, errret));
+}
+
+/*
+ * For auditing errors during login. Such errors are implicitly
+ * non-attributable (i.e., not ascribable to any user).
+ *
+ * Assumes, like all wrapper calls, that the caller has previously checked
+ * that auditing is enabled via the audit_get_state() call.
+ */
+int
+audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid,
+ uid_t egid, pid_t pid, au_tid_t *tid)
+{
+
+ return (audit_write_failure(event_code, errmsg, errret, -1, euid,
+ egid, -1, -1, pid, -1, tid));
+}
+
+/* END OF au_write() WRAPPERS */
+
+#ifdef __APPLE__
+void
+audit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp,
+ gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp,
+ au_tid_t *tidp)
+{
+
+ if (auidp != NULL)
+ *auidp = (uid_t)atoken.val[0];
+ if (euidp != NULL)
+ *euidp = (uid_t)atoken.val[1];
+ if (egidp != NULL)
+ *egidp = (gid_t)atoken.val[2];
+ if (ruidp != NULL)
+ *ruidp = (uid_t)atoken.val[3];
+ if (rgidp != NULL)
+ *rgidp = (gid_t)atoken.val[4];
+ if (pidp != NULL)
+ *pidp = (pid_t)atoken.val[5];
+ if (asidp != NULL)
+ *asidp = (au_asid_t)atoken.val[6];
+ if (tidp != NULL) {
+ audit_set_terminal_host(&tidp->machine);
+ tidp->port = (dev_t)atoken.val[7];
+ }
+}
+#endif /* !__APPLE__ */
diff --git a/contrib/openbsm/libbsm/libbsm.3 b/contrib/openbsm/libbsm/libbsm.3
new file mode 100644
index 0000000..3ec8168
--- /dev/null
+++ b/contrib/openbsm/libbsm/libbsm.3
@@ -0,0 +1,220 @@
+.\"-
+.\" Copyright (c) 2005-2006 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/libbsm.3#3 $
+.\"
+.Dd April 19, 2005
+.Dt LIBBSM 3
+.Os
+.Sh NAME
+.Nm libbsm
+.Nd "Basic Security Module (BSM) Audit API"
+.Sh LIBRARY
+.Lb libbsm
+.Sh SYNOPSIS
+.In libbsm.h
+.Sh DESCRIPTION
+The
+.Nm
+library routines provide an interface to BSM audit record streams, allowing
+both the parsing of existing audit streams, as well as the creation of new
+audit records and streams.
+.Sh INTERFACES
+.Nm
+provides a large number of Audit programming interfaces in several classes:
+event stream interfaces, class interfaces, control interfaces, event
+interfaces, I/O interfaces, mask interfaces, notification interfaces, token
+interfaces, and user interfaces.
+These are described respectively in the
+.Xr au_stream 3 ,
+.Xr au_class 3 ,
+.Xr au_control 3 ,
+.Xr au_event 3 ,
+.Xr au_mask 3 ,
+.Xr au_notify 3 ,
+.Xr au_token 3 ,
+.Xr au_user 3
+man pages.
+.Ss Audit Event Stream Interfaces
+Audit event stream interfaces support interaction with file-backed audit
+event streams:
+.Xr au_free_token 3 ,
+.Xr au_free_token 3 ,
+.Xr au_open 3 ,
+.Xr au_write 3 ,
+.Xr au_close 3 .
+.Ss Audit Class Interfaces
+Audit class interfaces support the look up of information from the
+.Xr audit_class 5
+database:
+.Xr getauclassent 3 ,
+.Xr getauclassent_r 3 ,
+.Xr getauclassnam 3 ,
+.Xr getauclassnam_r 3 ,
+.Xr setauclass 3 ,
+.Xr endauclass 3 .
+.Ss Audit Control Interfaces
+Audit control interfaces support the look up of information from the
+.Xr audit_control 5
+database:
+.Xr setac 3 ,
+.Xr endac 3 ,
+.Xr getacdir 3 ,
+.Xr getacmin 3 ,
+.Xr getacflg 3 ,
+.Xr getacna 3 .
+.Ss Audit Event Interfaces
+Audit event interfaces support the look up of information from the
+.Xr audit_event 5
+database:
+.Xr setauevent 3 ,
+.Xr endauevent 3 ,
+.Xr getauevent 3 ,
+.Xr getauevent_r 3 ,
+.Xr getauevnam 3 ,
+.Xr getauevnam_r 3 ,
+.Xr getauevnum 3 ,
+.Xr getauevnum_r 3 ,
+.Xr getauevnonam 3 ,
+.Xr getauevnonam_r 3 ,
+.Ss Audit I/O Interfaces
+Audit I/O interfaces support the processing and printing of tokens, as well
+as the reading of audit records:
+.Xr au_fetch_tok 3 ,
+.Xr au_print_tok 3 ,
+.Xr au_read_rec 3 .
+.Ss Audit Mask Interfaces
+Audit mask interfaces convert support the conversion between strings and
+.Vt au_mask_t
+values.
+They may also be used to determine if a particular audit event is matched
+by a mask:
+.Xr au_preselect 3 ,
+.Xr getauditflagsbin 3 ,
+.Xr getauditflagschar 3 .
+.Ss Audit Notification Interfaces
+Audit notification routines track audit state in a form permitting efficient
+update, avoiding frequent system calls to check the kernel audit state:
+.Xr au_notify_initialize 3 ,
+.Xr au_notify_terminate 3 ,
+.Xr au_get_state 3 .
+These interfaces are implemented only for Darwin/Mac OS X.
+.Ss Audit Token Interface
+Audit token interfaces permit the creation of tokens for use in creating
+audit records for submission to event streams.
+Each interface converts a C type to its
+.Vt token_t
+representation.
+.Xr au_to_arg32 3 ,
+.Xr au_to_arg64 3 ,
+.Xr au_to_arg 3 ,
+.Xr au_to_attr64 3 ,
+.Xr au_to_data 3 ,
+.Xr au_to_exit 3 ,
+.Xr au_to_groups 3 ,
+.Xr au_to_newgroups 3 ,
+.Xr au_to_in_addr 3 ,
+.Xr au_to_in_addr_ex 3 ,
+.Xr au_to_ip 3 ,
+.Xr au_to_ipc 3 ,
+.Xr au_to_ipc_perm 3 ,
+.Xr au_to_iport 3 ,
+.Xr au_to_opaque 3 ,
+.Xr au_to_file 3 ,
+.Xr au_to_text 3 ,
+.Xr au_to_path 3 ,
+.Xr au_to_process32 3 ,
+.Xr au_to_process64 3 ,
+.Xr au_to_process 3 ,
+.Xr au_to_process32_ex 3 ,
+.Xr au_to_process64_ex 3 ,
+.Xr au_to_process_ex 3 ,
+.Xr au_to_return32 3 ,
+.Xr au_to_return64 3 ,
+.Xr au_to_return 3 ,
+.Xr au_to_seq 3 ,
+.Xr au_to_socket 3 ,
+.Xr au_to_socket_ex_32 3 ,
+.Xr au_to_socket_ex_128 3 ,
+.Xr au_to_sock_inet32 3 ,
+.Xr au_to_sock_inet128 3 ,
+.Xr au_to_sock_inet 3 ,
+.Xr au_to_subject32 3 ,
+.Xr au_to_subject64 3 ,
+.Xr au_to_subject 3 ,
+.Xr au_to_subject32_ex 3 ,
+.Xr au_to_subject64_ex 3 ,
+.Xr au_to_subject_ex 3 ,
+.Xr au_to_me 3 ,
+.Xr au_to_exec_args 3 ,
+.Xr au_to_exec_env 3 ,
+.Xr au_to_header32 3 ,
+.Xr au_to_header64 3 ,
+.Xr au_to_trailer 3 .
+.Ss Audit User Interfaces
+Audit user interfaces support the look up of information from the
+.Xr audit_user 5
+database:
+.Xr setauuser 3 ,
+.Xr endauuser 3 ,
+.Xr getauuserent 3 ,
+.Xr getauuserent_r 3 ,
+.Xr getauusernam 3 ,
+.Xr getauusernam_r 3 ,
+.Xr au_user_mask 3 ,
+.Xr getfauditflags 3 .
+.Sh SEE ALSO
+.Xr au_class 3 ,
+.Xr au_mask 3 ,
+.Xr au_notify 3 ,
+.Xr au_stream 3 ,
+.Xr au_token 3 ,
+.Xr au_user 3 ,
+.Xr audit_class 5 ,
+.Xr audit_control 5
+.Sh AUTHORS
+This software was created by Robert Watson, Wayne Salamon, and Suresh
+Krishnaswamy for McAfee Research, the security research division of McAfee,
+Inc., under contract to Apple Computer, Inc.
+.Pp
+The Basic Security Module (BSM) interface to audit records and audit event
+stream format were defined by Sun Microsystems.
+.Sh 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 BUGS
+Bugs would not be unlikely.
+.Pp
+The
+.Nm
+library implementations are generally thread-safe, but not reentrant.
+.Pp
+The assignment of routines to classes could use some work, as it is
+decidely ad hoc.
+For example,
+.Fn au_read_rec
+should probably be considered a stream routine.
OpenPOWER on IntegriCloud