196N/A/*
943N/A * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
919N/A *
919N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
919N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
919N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
196N/A */
196N/A
196N/A
196N/A/*
196N/A * auditwrite() - Construct and write user level records to the audit trail.
196N/A */
196N/A
196N/A/* Include common system files first */
196N/A#include <stdlib.h>
196N/A#include <unistd.h>
196N/A#include <errno.h>
196N/A#include <strings.h>
196N/A#include <stdarg.h>
196N/A#include <syslog.h>
196N/A#include <sys/types.h>
196N/A#include <sys/stat.h>
196N/A#include <sys/fcntl.h>
196N/A#include <stdio.h>
196N/A#include <thread.h>
196N/A#include <synch.h>
196N/A#include <bsm/audit.h>
196N/A#include <bsm/audit_record.h>
196N/A#include <bsm/libbsm.h>
196N/A#include "auditwrite.h"
196N/A#include <bsm/audit_uevents.h>
196N/A#include <priv.h>
196N/A#include <tsol/label.h>
196N/A
196N/A/*
196N/A * invocation flags
196N/A */
196N/A
196N/A#define AW_NO_FLAGS ((uint_t)0x00000000) /* No flags. */
196N/A
196N/A#define AW_ABORT_FLAG ((uint_t)0x0000010) /* Abort gracefully */
196N/A#define AW_APPEND_FLAG ((uint_t)0x0000020) /* Append to save rec */
196N/A#define AW_ATTRIB_FLAG ((uint_t)0x0000040) /* Got some attribs */
196N/A#define AW_DEFAULTRD_FLAG ((uint_t)0x0000080) /* Use default rd */
196N/A#define AW_DISCARDRD_FLAG ((uint_t)0x0000100) /* Get rid of one rec */
196N/A#define AW_DISCARD_FLAG ((uint_t)0x0000200) /* Get rid of all recs */
196N/A#define AW_EVENT_FLAG ((uint_t)0x0000400) /* Event type */
196N/A#define AW_FLUSH_FLAG ((uint_t)0x0000800) /* Flush queued recs */
196N/A#define AW_GETRD_FLAG ((uint_t)0x0001000) /* Get a descriptor */
196N/A#define AW_INVOKED_BEFORE_FLAG ((uint_t)0x0002000) /* Been here before */
196N/A#define AW_NOPRESELECT_FLAG ((uint_t)0x0004000) /* Don't preselect recs */
196N/A#define AW_NOQUEUE_FLAG ((uint_t)0x0008000) /* Stop queueing. Flush */
196N/A#define AW_NOSAVE_FLAG ((uint_t)0x0010000) /* Don't attach save buf */
196N/A#define AW_NOSERVER_FLAG ((uint_t)0x0020000) /* Not a trusted srvr */
196N/A#define AW_PRESELECT_FLAG ((uint_t)0x0040000) /* Preselect recs here */
196N/A#define AW_QUEUE_FLAG ((uint_t)0x0080000) /* Buffer all records */
196N/A#define AW_SAVERD_FLAG ((uint_t)0x0100000) /* Attach save buffer */
196N/A#define AW_SERVER_FLAG ((uint_t)0x0200000) /* A trusted server */
196N/A#define AW_USERD_FLAG ((uint_t)0x0400000) /* Use rec. descriptor */
196N/A#define AW_WRITE_FLAG ((uint_t)0x0800000) /* Write to trail */
196N/A#define AW_SAVEDONE ((uint_t)0x1000000) /* Context is saved, */
196N/A /* needs to be restored */
196N/A
196N/A/*
196N/A * required attribute flags
196N/A * if these attributes are not included in the record, they are added
196N/A */
196N/A#define AW_REC_RETURN_FLAG ((char)0x0000001) /* return attribute */
196N/A#define AW_REC_SUBJECT_FLAG ((char)0x0000002) /* subject attribute */
196N/A
196N/A#define AW_CTRLCMD_FLAGS \
196N/A (AW_ABORT_FLAG | AW_APPEND_FLAG | AW_DISCARD_FLAG | \
196N/A AW_DISCARDRD_FLAG | AW_FLUSH_FLAG | AW_GETRD_FLAG | \
196N/A AW_NOQUEUE_FLAG | AW_NOSAVE_FLAG | AW_NOSERVER_FLAG | \
196N/A AW_PRESELECT_FLAG | AW_NOPRESELECT_FLAG | AW_QUEUE_FLAG | \
196N/A AW_SAVERD_FLAG | AW_SERVER_FLAG | AW_USERD_FLAG | \
196N/A AW_WRITE_FLAG | AW_DEFAULTRD_FLAG)
196N/A
196N/A#define AW_NORMALCMD_FLAGS (AW_CTRLCMD_FLAGS & ~AW_USERD_FLAG)
196N/A
196N/A/*
196N/A * AW_NOUSERDCMD - these cmds may not be used with AW_USERD on auditwrite call.
196N/A */
196N/A#define AW_NOUSERDCMD_FLAGS \
196N/A (AW_DISCARD_FLAG | AW_DISCARDRD_FLAG | AW_FLUSH_FLAG | \
196N/A AW_GETRD_FLAG | AW_DEFAULTRD_FLAG | AW_USERD_FLAG)
196N/A
196N/A#define AW_SUCCESS_RTN (0)
196N/A#define AW_ERR_RTN (-1)
196N/A
196N/A#define AW_PARSE_ERR(flags, error) \
196N/A{ \
196N/A if (aw_iflags & flags) { \
196N/A aw_set_err(error); \
196N/A aw_restore(); \
196N/A return (AW_ERR_RTN); \
196N/A } \
196N/A}
196N/A
196N/A#define AW_GEN_ERR(error) \
196N/A{ \
196N/A aw_set_err(error); \
196N/A aw_restore(); \
196N/A return (AW_ERR_RTN); \
196N/A}
196N/A
196N/A#define AW_CMD_MIN AW_END
303N/A#define AW_CMD_MAX AW_SUBJECT_EX
196N/A
196N/A/*
196N/A * Where control commands end and attribute commands begin.
196N/A */
196N/A#define AW_CMD_CUTOFF AW_ACL
196N/A
196N/A#define AW_IS_CONTROL_CMD(cmd_num) \
196N/A ((cmd_num) < AW_CMD_CUTOFF)
196N/A
196N/A#define AW_IS_DATA_CMD(cmd_num) \
196N/A ((cmd_num) >= AW_CMD_CUTOFF)
196N/A
196N/A/*
196N/A * Currently, AW_MAX_REC_SIZE applies to both audit(2). This
196N/A * will need to be changed as the limits associated w/audit(2) and
196N/A * auditctl(2) change. It's defined here because the kernel imposed maximum
196N/A * record size is not program visible.
196N/A */
196N/A#define AW_MAX_REC_SIZE (0x8000)
196N/A
196N/A/*
196N/A * Number of record pointers to initially allocate
196N/A */
196N/A#define AW_NUM_RECP (20)
196N/A
196N/A/*
196N/A * A record descriptor that is not allocated.
196N/A */
196N/A#define AW_NO_RD (-1)
196N/A
196N/A/*
196N/A * This is a fakeout for auditwrite. We don't have a
196N/A * auditctl(A_AUDIT), so we'll emulate this with existing
196N/A * functionality.
196N/A */
196N/A#define A_AUDIT (10)
196N/A
196N/Astruct aw_context {
196N/A uint_t static_flags; /* static flags */
196N/A au_mask_t pmask; /* preselection mask */
196N/A int save_rd; /* associated save rd */
196N/A int aw_errno; /* errno for this rec */
196N/A};
196N/Atypedef struct aw_context aw_context_t;
196N/A
196N/Aaw_context_t old_context; /* For saving previous state */
196N/Aint old_cur_rd;
196N/A
196N/A/* Data structures used to account for and queue audit record buffers */
196N/A
196N/Astruct aw_rec {
196N/A aw_context_t context; /* saved state for this rec */
196N/A char aflags; /* for required attribs */
196N/A int len; /* number of bytes in buffer */
196N/A au_event_t event_id; /* audit event identifier */
196N/A au_emod_t event_mod; /* audit event modifier */
196N/A uint_t class; /* audit event classes associated with event */
196N/A caddr_t buf; /* audit record buffer */
196N/A};
196N/Atypedef struct aw_rec aw_rec_t;
196N/A
196N/Astatic aw_rec_t **aw_recs; /* dynam arr of aud rec ptrs */
196N/Astatic int aw_num_recs; /* # token pointers */
196N/Astatic caddr_t aw_queue; /* a rec queue in user addr space */
196N/Astatic int aw_queue_hiwater; /* max number of bytes on queue */
196N/Astatic int aw_queue_bytes; /* current # of bytes on queue */
196N/A
196N/Astatic mutex_t mutex_auditwrite = DEFAULTMUTEX; /* Global audiwrite mutex */
196N/A
196N/A/*
196N/A * Command table. Contains the command and the number of args that follow
196N/A * the command.
196N/A *
196N/A * If you add to the list, be aware that this is an array, and
196N/A * in indexed accordingly. I don't know why the cmd_number field
196N/A * was ever used.
196N/A */
196N/Astatic struct {
196N/A int cmd_number;
196N/A int cmd_numargs;
196N/A} aw_cmd_table[] = {
196N/A {AW_END, 0},
196N/A/*
196N/A * Control commands. These control the behavior of auditwrite.
196N/A */
196N/A {AW_ABORT, 0},
196N/A {AW_APPEND, 0},
196N/A {AW_DEFAULTRD, 0},
196N/A {AW_DISCARD, 0},
196N/A {AW_DISCARDRD, 1},
196N/A {AW_FLUSH, 0},
196N/A {AW_GETRD, 1},
196N/A {AW_NOPRESELECT, 0},
196N/A {AW_NOQUEUE, 0},
196N/A {AW_NOSAVE, 0},
196N/A {AW_NOSERVER, 0},
196N/A {AW_PRESELECT, 1},
196N/A {AW_QUEUE, 1},
196N/A {AW_SAVERD, 1},
196N/A {AW_SERVER, 0},
196N/A {AW_USERD, 1},
196N/A {AW_WRITE, 0},
196N/A {AW_END, 0}, /* Reserved for future use */
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A/*
196N/A * Attribute commands. These tell audiwrite how many attributes
196N/A * of data to expect.
196N/A */
196N/A {AW_ACL, 0}, /* Don't support ACL's yet */
196N/A {AW_ARG, 3},
196N/A {AW_ATTR, 6},
196N/A {AW_DATA, 4},
196N/A {AW_EVENT, 1},
196N/A {AW_EVENTNUM, 1},
196N/A {AW_EXEC_ARGS, 1},
196N/A {AW_EXEC_ENV, 1},
196N/A {AW_EXIT, 2},
196N/A {AW_GROUPS, 2},
196N/A {AW_IN_ADDR, 1},
196N/A {AW_IPC, 2},
303N/A {AW_END, 0}, /* obsolete AW_IPC_PERM */
196N/A {AW_IPORT, 1},
196N/A {AW_OPAQUE, 2},
196N/A {AW_PATH, 1},
196N/A {AW_PROCESS, 8},
196N/A {AW_RETURN, 2},
196N/A {AW_SOCKET, 1},
196N/A {AW_SUBJECT, 8},
196N/A {AW_TEXT, 1},
196N/A {AW_UAUTH, 1},
196N/A {AW_CMD, 3},
196N/A {AW_END, 0}, /* Reserved for future use */
196N/A {AW_END, 0},
196N/A
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A {AW_LEVEL, 1},
196N/A {AW_LIAISON, 1},
196N/A {AW_PRIVILEGE, 2},
196N/A {AW_SLABEL, 1},
196N/A {AW_USEOFPRIV, 2},
196N/A {AW_END, 0}, /* Reserved for future use */
196N/A {AW_END, 0},
196N/A {AW_END, 0},
196N/A
196N/A {AW_XATOM, 1},
196N/A {AW_XCOLORMAP, 2},
196N/A {AW_XCURSOR, 2},
196N/A {AW_XFONT, 2},
196N/A {AW_XGC, 2},
196N/A {AW_END, /* OBS */ 0},
196N/A {AW_XPIXMAP, 2},
196N/A {AW_XPROPERTY, 3},
196N/A {AW_END, /* OBS */ 0},
196N/A {AW_XSELECT, 3},
196N/A {AW_XWINDOW, 2},
196N/A {AW_XCLIENT, 1},
196N/A
196N/A {AW_PROCESS_EX, 8},
303N/A {AW_SUBJECT_EX, 8}
196N/A};
196N/A
196N/A/* externally accessible data */
196N/Aint aw_errno = AW_ERR_NO_ERROR; /* error number */
196N/A
196N/Astatic char *aw_errlist[] = {
196N/A "No error",
196N/A "Address invalid",
196N/A "Memory allocation failure",
196N/A "auditon(2) failed",
196N/A "audit(2) failed",
196N/A "Command incomplete",
196N/A "Command invalid",
196N/A "Command in effect",
196N/A "Command not in effect",
196N/A "More than one control command specified",
196N/A "Event ID invalid",
196N/A "Event ID not set",
196N/A "getaudit(2) or getaudit_addr(2) failed",
196N/A "Queue size invalid",
196N/A "Record descriptor invalid",
196N/A "Record too big",
196N/A "No process label",
196N/A};
196N/A
196N/Aint aw_nerr = sizeof (aw_errlist) / sizeof (char *);
196N/A
196N/A/* Data used by parsing routines and auditwrite */
196N/A
196N/Astatic int *get_rd_p; /* descriptor addr */
196N/Astatic int *save_rd_p; /* descriptor addr */
196N/A
196N/Astatic uint_t aw_iflags = AW_NO_FLAGS; /* invocation line flags */
196N/A
196N/Astatic uint_t aw_static_flags; /* flags saved between invocations */
196N/A
196N/Astatic int dflt_rd = AW_NO_RD; /* default audit record descriptor */
196N/A /* used if invoker doesn't specify one */
196N/A
196N/Astatic int save_rd = AW_NO_RD; /* audit record buffer attribs to prepend to */
196N/A /* every audit record */
196N/A
196N/Astatic int user_rd; /* descriptor passed by user */
196N/A
196N/Astatic int cur_rd = AW_NO_RD; /* the current rd */
196N/A
196N/Astatic au_mask_t pmask; /* for preselection */
196N/A
196N/Astatic int audit_policies; /* cache the audit policies for the sake */
196N/A /* of efficiency */
196N/A
196N/Astatic void aw_abort(void);
196N/Astatic int aw_buf_append(caddr_t *b1, int *l1, caddr_t b2, int l2);
196N/Astatic int aw_buf_prepend(caddr_t *b1, int *l1, caddr_t b2, int l2);
196N/Astatic int aw_chk_addr(caddr_t p);
196N/Astatic int aw_chk_event_id(int rd);
196N/Astatic int aw_chk_print(char arg);
196N/Astatic int aw_chk_type(char arg);
196N/Astatic int aw_chk_rd(int rd);
196N/Astatic void aw_cleanup(void);
196N/Astatic char aw_cvrt_path(char *path, char **pathp);
196N/Astatic char aw_cvrt_print(char arg);
196N/Astatic char aw_cvrt_type(char arg);
196N/Astatic int aw_do_subject(int rd);
196N/Astatic int aw_do_write(void);
196N/Astatic int aw_write_cleanup(void);
196N/Astatic void aw_free(caddr_t p);
196N/Astatic void aw_free_tok(token_t *tokp);
196N/Astatic int aw_gen_rec(int param, va_list arglist);
196N/Astatic int aw_head(int rd);
196N/Astatic int aw_parse(int param, va_list arglist);
196N/Astatic int aw_preselect(int rd, au_mask_t *pmaskp);
196N/Astatic void aw_queue_dealloc(void);
196N/Astatic int aw_queue_flush(void);
196N/Astatic int aw_queue_write(int rd);
196N/Astatic int aw_rec_alloc(int *rdp);
196N/A#ifdef NOTYET
196N/Astatic int aw_rec_append(int to_rd, int from_rd);
196N/A#endif /* NOTYET */
196N/Astatic void aw_rec_dealloc(int rd);
196N/Astatic int aw_rec_prepend(int to_rd, int from_rd);
196N/Astatic int aw_return_attrib(int rd);
196N/Astatic void aw_set_err(int error);
196N/Astatic void aw_set_event(int rd, au_event_t event_id, uint_t class);
196N/Astatic int aw_init(void);
196N/Astatic int aw_set_context(int param, va_list arglist);
196N/Astatic void aw_restore(void);
196N/Astatic int aw_audit_write(int rd);
196N/Astatic int aw_auditctl_write(int rd);
388N/Astatic int auditctl(uint32_t command, uint32_t value, caddr_t data);
196N/A#ifdef DEBUG
196N/Astatic void aw_debuglog(char *string, int rc, int param, va_list arglist);
196N/A#endif
196N/A
196N/Aextern int cannot_audit(int);
196N/A
196N/A/*
196N/A * a w _ g e t _ a r g s ( )
196N/A *
196N/A * Gets arguments off the stack;
196N/A *
196N/A */
196N/A#define aw_get_args(arglist, ad, numargs) \
196N/A{ \
196N/A int i; \
196N/A \
196N/A for (i = 0; i < (numargs); i++) \
196N/A (ad)[i] = (void *)va_arg((arglist), void *); \
196N/A}
196N/A
196N/A/*
196N/A * a w _ s k i p _ a r g ( )
196N/A *
196N/A * Skip args on the invocation line.
196N/A *
196N/A */
196N/A#define aw_skip_args(arglist, numskips) \
196N/A{ \
196N/A int i; \
196N/A \
196N/A for (i = 0; i < (numskips); i++) \
196N/A (void) va_arg((arglist), void *); \
196N/A}
196N/A
196N/A/*
196N/A * a u d i t w r i t e ( )
196N/A *
196N/A * Construct and write user level audit records to the audit trail.
196N/A *
196N/A */
196N/A/*VARARGS*/
196N/Aint
196N/Aauditwrite(int param, ...)
196N/A{
196N/A va_list arglist; /* var args arglist pointer */
196N/A int get_rd; /* rd to pass back */
196N/A register int i; /* counter */
196N/A int retval; /* return value */
196N/A
196N/A /* Is auditing even enabled? If not, just exit */
196N/A if (cannot_audit(0) == 1)
196N/A AW_GEN_ERR(AW_ERR_AUDITON_FAIL);
196N/A
196N/A /* Grab the lock */
196N/A (void) mutex_lock(&mutex_auditwrite);
196N/A
196N/A#ifdef DEBUG
196N/A va_start(arglist, param);
196N/A aw_debuglog("in ", 0, param, arglist);
196N/A va_end(arglist);
196N/A#endif /* DEBUG */
196N/A
196N/A /*
196N/A * first time initialization stuff.
196N/A * get the preselection mask and the audit policy.
196N/A * allocate a default record buffer.
196N/A */
196N/A if (aw_init() == AW_ERR_RTN) {
196N/A (void) mutex_unlock(&mutex_auditwrite);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A
196N/A /*
196N/A * set context, parse the invocation line and get the command.
196N/A */
196N/A va_start(arglist, param);
196N/A retval = aw_set_context(param, arglist);
196N/A if (retval != AW_ERR_RTN) {
196N/A /* need to rewind the command line first... */
196N/A va_start(arglist, param);
196N/A retval = aw_parse(param, arglist);
196N/A }
196N/A if (retval == AW_ERR_RTN) {
196N/A aw_abort();
196N/A aw_restore();
196N/A (void) mutex_unlock(&mutex_auditwrite);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A va_end(arglist);
196N/A
196N/A retval = AW_SUCCESS_RTN;
196N/A
196N/A#ifdef DEBUG
196N/A aw_debuglog("my in ", 0, param, arglist);
196N/A#endif /* DEBUG */
196N/A
196N/A switch (aw_iflags & AW_NORMALCMD_FLAGS) {
196N/A
196N/A case AW_WRITE_FLAG:
196N/A /*
196N/A * Preselect the record here.
196N/A * If we're not going to write it, no sense in constructing it.
196N/A */
196N/A if (!aw_preselect(cur_rd, &pmask)) {
196N/A retval = aw_write_cleanup();
196N/A break;
196N/A }
196N/A
196N/A if (aw_iflags & AW_ATTRIB_FLAG) {
196N/A va_start(arglist, param);
196N/A if ((retval = aw_gen_rec(param, arglist)) == AW_ERR_RTN)
196N/A break;
196N/A va_end(arglist);
196N/A }
196N/A
196N/A if ((retval = aw_do_write()) == AW_SUCCESS_RTN)
196N/A retval = aw_write_cleanup();
196N/A break;
196N/A
196N/A case AW_APPEND_FLAG:
196N/A va_start(arglist, param);
196N/A if ((retval = aw_gen_rec(param, arglist)) == AW_ERR_RTN)
196N/A break;
196N/A va_end(arglist);
196N/A break;
196N/A
196N/A case AW_ABORT_FLAG:
196N/A aw_abort();
196N/A break;
196N/A
196N/A case AW_DEFAULTRD_FLAG:
196N/A cur_rd = dflt_rd;
196N/A break;
196N/A
196N/A case AW_DISCARD_FLAG:
196N/A /*
196N/A * deallocate all records
196N/A */
196N/A for (i = 0; i < aw_num_recs; i++)
196N/A aw_rec_dealloc(i);
196N/A /*
196N/A * deallocate the queue
196N/A */
196N/A aw_queue_dealloc();
196N/A /*
196N/A * save buffer is gone
196N/A */
196N/A aw_static_flags &= ~AW_SAVERD_FLAG;
196N/A cur_rd = dflt_rd = save_rd = AW_NO_RD;
196N/A break;
196N/A
196N/A case AW_DISCARDRD_FLAG:
196N/A if ((retval = aw_chk_rd(user_rd)) == AW_ERR_RTN)
196N/A break;
196N/A else {
196N/A aw_rec_dealloc(user_rd);
196N/A if (user_rd == save_rd) {
196N/A aw_static_flags &= ~AW_SAVERD_FLAG;
196N/A save_rd = AW_NO_RD;
196N/A }
196N/A /*
196N/A * special case - reallocate the default rd
196N/A * if user blows it away.
196N/A */
196N/A if (user_rd == dflt_rd) {
196N/A if ((retval = aw_rec_alloc(&dflt_rd))
196N/A == AW_ERR_RTN)
196N/A break;
196N/A }
196N/A /*
196N/A * if user blows away the current rd, set it back
196N/A * to the default
196N/A */
196N/A if (user_rd == cur_rd)
196N/A cur_rd = dflt_rd;
196N/A }
196N/A break;
196N/A
196N/A case AW_FLUSH_FLAG:
196N/A retval = aw_queue_flush();
196N/A break;
196N/A
196N/A case AW_GETRD_FLAG:
196N/A if ((retval = aw_rec_alloc(&get_rd)) == AW_ERR_RTN)
196N/A break;
196N/A *get_rd_p = get_rd;
196N/A break;
196N/A
196N/A case AW_NOQUEUE_FLAG:
196N/A if ((retval = aw_queue_flush()) == AW_ERR_RTN) {
196N/A aw_queue_dealloc();
196N/A break;
196N/A }
196N/A aw_queue_dealloc();
196N/A aw_static_flags &= ~AW_QUEUE_FLAG;
196N/A break;
196N/A
196N/A case AW_NOPRESELECT_FLAG: {
196N/A auditinfo_addr_t auinfo; /* temporary holder */
196N/A
196N/A pmask.am_success = pmask.am_failure = 0;
196N/A
196N/A /* Get the info from the proc */
196N/A if (getaudit_addr(&auinfo, sizeof (auinfo)) == -1) {
196N/A aw_set_err(AW_ERR_GETAUDIT_FAIL);
196N/A retval = AW_ERR_RTN;
196N/A }
196N/A
196N/A /* Stuff the real values in */
196N/A pmask = auinfo.ai_mask;
196N/A
196N/A aw_static_flags &= ~AW_PRESELECT_FLAG;
196N/A break;
196N/A }
196N/A case AW_NOSAVE_FLAG:
196N/A aw_rec_dealloc(save_rd);
196N/A aw_static_flags &= ~AW_SAVERD_FLAG;
196N/A save_rd = AW_NO_RD;
196N/A break;
196N/A
196N/A case AW_NOSERVER_FLAG:
196N/A aw_static_flags &= ~AW_SERVER_FLAG;
196N/A break;
196N/A
196N/A case AW_PRESELECT_FLAG:
196N/A aw_static_flags |= AW_PRESELECT_FLAG;
196N/A break;
196N/A
196N/A case AW_QUEUE_FLAG:
196N/A aw_static_flags |= AW_QUEUE_FLAG;
196N/A break;
196N/A
196N/A case AW_SAVERD_FLAG:
196N/A if (aw_rec_alloc(&save_rd) == AW_ERR_RTN)
196N/A break;
196N/A *save_rd_p = save_rd;
196N/A /*
196N/A * SAVERD can be used by long-running processes
196N/A * (servers) to set-up context for a new "subject".
196N/A * Take the opportunity here to force a check of
196N/A * the event file on disk for any changes.
196N/A */
196N/A /* XXXX refreshauevcache(); */
196N/A aw_static_flags |= AW_SAVERD_FLAG;
196N/A break;
196N/A
196N/A case AW_SERVER_FLAG:
196N/A aw_static_flags |= AW_SERVER_FLAG;
196N/A break;
196N/A
196N/A default:
196N/A break;
196N/A }
196N/A
196N/A if (retval == AW_ERR_RTN)
196N/A aw_abort();
196N/A
196N/A /* Free up the lock */
196N/A (void) mutex_unlock(&mutex_auditwrite);
196N/A
196N/A#ifdef DEBUG
196N/A aw_debuglog("my out", retval, param, arglist);
196N/A#endif /* DEBUG */
196N/A aw_restore();
196N/A#ifdef DEBUG
196N/A aw_debuglog("out ", retval, param, arglist);
196N/A#endif /* DEBUG */
196N/A return (retval);
196N/A}
196N/A
196N/A/*
196N/A * a w _ a b o r t ( )
196N/A *
196N/A * Called when an an error occurs. Write any incomplete or buffered records.
196N/A */
196N/Astatic void
196N/Aaw_abort(void)
196N/A{
196N/A uint_t i;
196N/A
196N/A char *err_mesg; /* Mesg returned by strerror */
196N/A char *aw_err_mesg; /* Mesg returned by aw_strerror */
196N/A
196N/A /* Write queued or partial records */
196N/A
196N/A if (aw_static_flags & AW_QUEUE_FLAG)
196N/A (void) aw_queue_flush();
196N/A else
196N/A for (i = 0; i < aw_num_recs; i++) {
196N/A if (aw_recs[i] != (aw_rec_t *)0 &&
196N/A aw_recs[i]->buf != (caddr_t)0 &&
196N/A aw_recs[i]->len != 0) {
196N/A (void) aw_audit_write(i);
196N/A }
196N/A }
196N/A
196N/A aw_cleanup();
196N/A
196N/A (void) openlog("auditwrite(3)", LOG_PID|LOG_CONS, LOG_USER);
196N/A (void) syslog(LOG_ALERT,
196N/A "aborted: aw_errno = %d = %s, errno = %d = %s",
196N/A aw_errno,
196N/A (aw_err_mesg = aw_strerror(aw_errno)) ? aw_err_mesg : "unknown error",
196N/A errno,
196N/A (err_mesg = strerror(errno)) ? err_mesg : "unknown error");
196N/A (void) closelog();
196N/A
196N/A}
196N/A
196N/A/*
196N/A * Several programs, most noticably init(1M), have their own local
196N/A * copies of bcopy(3C), which take precedence over lib C's
196N/A * bcopy(3C) that we previously used here. memmove(3C) does the same
196N/A * thing, and doesn't have any name collisions...so far.
196N/A */
196N/A
196N/A/*
196N/A * a w _ b u f _ a p p e n d ( )
196N/A *
196N/A * Append some data from one buffer to another
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_buf_append(caddr_t *b1, int *l1, caddr_t b2, int l2)
196N/A{
196N/A if (l2 == 0)
196N/A return (AW_SUCCESS_RTN);
196N/A
196N/A if (*b1 == (caddr_t)0) {
196N/A if ((*b1 = (caddr_t)calloc(1, (size_t)l2)) == (caddr_t)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A (void) memmove(*b1, b2, l2);
196N/A
196N/A *l1 = l2;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A
196N/A if ((*b1 = (caddr_t)realloc((void *)*b1, (size_t)(*l1 + l2)))
196N/A == (caddr_t)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A (void) memmove(*b1+*l1, b2, l2);
196N/A
196N/A *l1 += l2;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ b u f _ p r e p e n d ( )
196N/A *
196N/A * Prepend the contents of one buffer to another
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_buf_prepend(caddr_t *b1, int *l1, caddr_t b2, int l2)
196N/A{
196N/A if (l2 == 0)
196N/A return (AW_SUCCESS_RTN);
196N/A
196N/A if (*b1 == (caddr_t)0) {
196N/A if ((*b1 = (caddr_t)calloc(1, (size_t)l2)) == (caddr_t)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A (void) memmove(*b1, b2, l2);
196N/A
196N/A *l1 = l2;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A
196N/A if ((*b1 = (caddr_t)realloc((void *)*b1, (size_t)(*l1 + l2)))
196N/A == (caddr_t)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A (void) memmove(*b1+l2, *b1, *l1);
196N/A
196N/A (void) memmove(*b1, b2, l2);
196N/A
196N/A *l1 += l2;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c h k _ a d d r ( )
196N/A *
196N/A * Make sure address is within allowable boundaries. This is done to minimize
196N/A * core dumps (mostly SIGSEGV and SIGBUS) that can occur when a bad
196N/A * invocation line is passed.
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_chk_addr(caddr_t p)
196N/A{
196N/A /*
196N/A * if pointer is null, it's bogus
196N/A */
196N/A
196N/A if (p == (caddr_t)0)
196N/A return (AW_ERR_RTN);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c h k _ e v e n t _ i d ( )
196N/A *
196N/A * Make sure event id is set.
196N/A */
196N/Astatic int
196N/Aaw_chk_event_id(int rd)
196N/A{
196N/A if (aw_recs[rd]->event_id == (au_event_t)NULL)
196N/A return (AW_ERR_RTN);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c h k _ p r i n t ( )
196N/A *
196N/A * Indicate validity of arbitrary data print arg.
196N/A */
196N/Astatic int
196N/Aaw_chk_print(char arg)
196N/A{
196N/A switch (arg) {
196N/A case AWD_BINARY:
196N/A case AWD_OCTAL:
196N/A case AWD_DECIMAL:
196N/A case AWD_HEX:
196N/A case AWD_STRING:
196N/A return (AW_SUCCESS_RTN);
196N/A default:
196N/A return (AW_ERR_RTN);
196N/A }
196N/A /*NOTREACHED*/
196N/A}
196N/A
196N/A/*
196N/A * a w _ c h k _ t y p e ( )
196N/A *
196N/A * Indicate validity of arbitrary data type arg.
196N/A */
196N/Astatic int
196N/Aaw_chk_type(char arg)
196N/A{
196N/A switch (arg) {
196N/A case AWD_BYTE:
196N/A case AWD_CHAR:
196N/A case AWD_SHORT:
196N/A case AWD_INT:
196N/A case AWD_LONG:
196N/A case AWD_INT32:
196N/A case AWD_INT64:
196N/A return (AW_SUCCESS_RTN);
196N/A default:
196N/A return (AW_ERR_RTN);
196N/A }
196N/A /*NOTREACHED*/
196N/A}
196N/A
196N/A/*
196N/A * a w _ c h k _ r d ( )
196N/A *
196N/A * Make sure record descriptor is valid
196N/A */
196N/Astatic int
196N/Aaw_chk_rd(int rd)
196N/A{
196N/A if ((rd > aw_num_recs) || (aw_recs[rd] == (aw_rec_t *)0))
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c l e a n u p ( )
196N/A *
196N/A * Free all buffer space. Reset all static flags.
196N/A *
196N/A */
196N/Astatic void
196N/Aaw_cleanup(void)
196N/A{
196N/A int i;
196N/A
196N/A /* Deallocate all audit records and record pointer array */
196N/A
196N/A for (i = 0; i < aw_num_recs; i++) {
196N/A aw_rec_dealloc(i);
196N/A }
196N/A
196N/A cur_rd = dflt_rd = save_rd = AW_NO_RD;
196N/A
196N/A aw_free((caddr_t)aw_recs);
196N/A aw_recs = (aw_rec_t **)0;
196N/A
196N/A /* Deallocate audit record queue */
196N/A
196N/A aw_queue_dealloc();
196N/A
196N/A /* Reset flags */
196N/A
196N/A aw_iflags = aw_static_flags = AW_NO_FLAGS;
196N/A}
196N/A
196N/A/*
196N/A * a w _ c v r t _ p a t h ( )
196N/A *
196N/A * Get path ready for the audit trail by prepending the absolute root.
196N/A */
196N/Astatic char
196N/Aaw_cvrt_path(char *path, /* orig path */
196N/A char **pathp) /* converted path */
196N/A{
196N/A#define AW_PATH_LEN (MAXPATHLEN)
196N/A
196N/A int cmd;
196N/A char absroot[AW_PATH_LEN+1];
196N/A static char cvrt_path[AW_PATH_LEN+AW_PATH_LEN+2];
196N/A
196N/A if (path[0] == '/')
196N/A cmd = A_GETCAR;
196N/A else
196N/A cmd = A_GETCWD;
196N/A
196N/A if (auditon(cmd, absroot, AW_PATH_LEN+1) != 0)
196N/A AW_GEN_ERR(AW_ERR_AUDITON_FAIL);
196N/A
196N/A (void) strncpy(cvrt_path, absroot, AW_PATH_LEN);
196N/A (void) strcat(cvrt_path, "/");
196N/A (void) strcat(cvrt_path, path);
196N/A
196N/A *pathp = cvrt_path;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c v r t _ t y p e ( )
196N/A *
196N/A * Convert arbitrary data print suggestions to token print suggestions.
196N/A */
196N/Astatic char
196N/Aaw_cvrt_print(char arg)
196N/A{
196N/A switch (arg) {
196N/A case AWD_BINARY:
196N/A return (AUP_BINARY);
196N/A case AWD_OCTAL:
196N/A return (AUP_OCTAL);
196N/A case AWD_DECIMAL:
196N/A return (AUP_DECIMAL);
196N/A case AWD_HEX:
196N/A return (AUP_HEX);
196N/A case AWD_STRING:
196N/A return (AUP_STRING);
196N/A }
196N/A return ((char)~0);
196N/A}
196N/A
196N/A/*
196N/A * a w _ c v r t _ t y p e ( )
196N/A *
196N/A * Convert arbitrary data type to token data type.
196N/A */
196N/Astatic char
196N/Aaw_cvrt_type(char arg)
196N/A{
196N/A switch (arg) {
196N/A case AWD_BYTE:
196N/A return (AUR_BYTE);
196N/A case AWD_CHAR:
196N/A return (AUR_CHAR);
196N/A case AWD_SHORT:
196N/A return (AUR_SHORT);
196N/A case AWD_INT:
196N/A return (AUR_INT);
196N/A case AWD_LONG:
196N/A return (AUR_INT32);
196N/A case AWD_INT32:
196N/A return (AUR_INT32);
196N/A case AWD_INT64:
196N/A return (AUR_INT64);
196N/A }
196N/A return ((char)~0);
196N/A}
196N/A
196N/A/*
196N/A * a w _ d o _ s u b j e c t ( )
196N/A *
196N/A * Add subject/groups/SL/IL attribs if they haven't already been added.
196N/A * Check the audit policy and add any necessary attribs.
196N/A * The remaining policies such as seq and trailers are done by audit(2).
196N/A */
196N/Astatic int
196N/Aaw_do_subject(int rd)
196N/A{
196N/A token_t *tokp;
196N/A gid_t gidset[NGROUPS_MAX];
196N/A auditinfo_addr_t auinfo;
196N/A bslabel_t label_p;
196N/A
196N/A /*
196N/A * if the record does not contain a subject attribute
196N/A * prepend one now
196N/A */
196N/A if (AW_REC_SUBJECT_FLAG & aw_recs[rd]->aflags)
196N/A return (AW_SUCCESS_RTN);
196N/A
196N/A if (getaudit_addr(&auinfo, sizeof (auinfo)) != 0)
196N/A AW_GEN_ERR(AW_ERR_GETAUDIT_FAIL);
196N/A
196N/A /*
196N/A * Add the subject token using the values we have.
196N/A * Append them to the record under construction
196N/A */
196N/A
196N/A if ((tokp = au_to_subject_ex(auinfo.ai_auid, geteuid(),
196N/A getegid(), getuid(), getgid(), getpid(),
196N/A auinfo.ai_asid, &auinfo.ai_termid))
196N/A == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[rd]->buf), &(aw_recs[rd]->len),
196N/A tokp->tt_data, (int)tokp->tt_size) ==
196N/A AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A
196N/A /* Go grab the sensitivity label for this process */
196N/A if (getplabel(&label_p) != 0)
196N/A AW_GEN_ERR(AW_ERR_NO_PLABEL);
196N/A
196N/A /* Now output the SL */
196N/A if ((tokp = au_to_label(&label_p)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[rd]->buf), &(aw_recs[rd]->len),
196N/A tokp->tt_data, (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A
196N/A /* Now add the groups */
196N/A if (audit_policies & AUDIT_GROUP) {
196N/A (void) getgroups(NGROUPS_MAX, gidset);
196N/A if ((tokp = au_to_groups((int *)gidset)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A if (aw_buf_append(&(aw_recs[rd]->buf), &(aw_recs[rd]->len),
196N/A tokp->tt_data, (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A }
196N/A
196N/A /*
196N/A * The sequence token is no longer required to be added by
196N/A * auditwrite(), it's added by BSM.
196N/A */
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ d o _ w r i t e ( )
196N/A *
196N/A * Write an audit record.
196N/A */
196N/Astatic int
196N/Aaw_do_write(void)
196N/A{
196N/A /*
196N/A * an attempt to write an audit record without an event id
196N/A * set is a serious error
196N/A */
196N/A if (aw_static_flags & AW_SAVERD_FLAG) {
196N/A if (aw_chk_event_id(cur_rd) == AW_ERR_RTN &&
196N/A aw_chk_event_id(save_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_NOT_SET);
196N/A } else {
196N/A if (aw_chk_event_id(cur_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_NOT_SET);
196N/A }
196N/A
196N/A if (aw_static_flags & AW_SAVERD_FLAG)
196N/A if (aw_rec_prepend(cur_rd, save_rd) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A
196N/A /*
196N/A * if we are a server, we don't need to add subject and return
196N/A * attributes.
196N/A */
196N/A if ((aw_static_flags & AW_SERVER_FLAG) == 0) {
196N/A if (aw_do_subject(cur_rd) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A }
196N/A
196N/A /*
196N/A * Must add a return attribute in all cases if one
196N/A * has not already been added. this attribute denotes
196N/A * the success/failure of the event.
196N/A */
196N/A if (!(aw_recs[cur_rd]->aflags & AW_REC_RETURN_FLAG))
196N/A if (aw_return_attrib(cur_rd) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A
196N/A /* Now finish up by writing the header attribute */
196N/A if (aw_head(cur_rd) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A
196N/A /*
196N/A * if queueing is on write to the queue
196N/A */
196N/A if (aw_static_flags & AW_QUEUE_FLAG)
196N/A return (aw_queue_write(cur_rd));
196N/A
196N/A /*
196N/A * if we are a server, we need to use auditctl(2)
196N/A */
196N/A if (aw_static_flags & AW_SERVER_FLAG)
196N/A return (aw_auditctl_write(cur_rd));
196N/A
196N/A /*
196N/A * default case. we are not a server and we are not queueing.
196N/A */
196N/A return (aw_audit_write(cur_rd));
196N/A}
196N/A
196N/A
196N/Astatic int
196N/Aaw_write_cleanup(void)
196N/A{
196N/A aw_rec_dealloc(cur_rd);
196N/A
196N/A if (cur_rd == dflt_rd)
196N/A dflt_rd = AW_NO_RD;
196N/A
196N/A if (cur_rd == save_rd) {
196N/A save_rd = AW_NO_RD;
196N/A aw_static_flags &= ~AW_SAVERD_FLAG;
196N/A }
196N/A
196N/A if ((aw_iflags & AW_SAVEDONE) && (save_rd != AW_NO_RD)) {
196N/A /*
196N/A * If we are in context for a descriptor, now that the
196N/A * descriptor is gone we must clean up its save rd if any.
196N/A */
196N/A aw_rec_dealloc(save_rd);
196N/A save_rd = AW_NO_RD;
196N/A aw_static_flags &= ~AW_SAVERD_FLAG;
196N/A }
196N/A
196N/A cur_rd = AW_NO_RD;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ f r e e ( )
196N/A *
196N/A * Only free good addrs.
196N/A */
196N/Astatic void
196N/Aaw_free(caddr_t p)
196N/A{
196N/A if (p != (caddr_t)0)
196N/A free((void *)p);
196N/A}
196N/A
196N/A/*
196N/A * a w _ f r e e _ t o k ( )
196N/A *
196N/A * Free tokens.
196N/A */
196N/Astatic void
196N/Aaw_free_tok(token_t *tokp)
196N/A{
196N/A aw_free((caddr_t)tokp->tt_data);
196N/A aw_free((caddr_t)tokp);
196N/A}
196N/A
196N/A/*
196N/A * a w _ g e n _ r e c ( )
196N/A *
196N/A * Traverse the invocation line again. This time grab all the record attributes,
196N/A * convert them to ADR format and append them to the current record buffer.
196N/A */
196N/Astatic int
196N/Aaw_gen_rec(int param, va_list arglist)
196N/A{
196N/A void *ad[8]; /* attribute data */
196N/A token_t *tokp; /* token for converted data */
196N/A int a; /* invocation line argument */
196N/A au_event_ent_t *auevent; /* event for this call */
196N/A char *apath; /* anchored path */
196N/A
196N/A a = param;
196N/A
196N/A while (a != AW_END) {
196N/A
196N/A if (AW_IS_CONTROL_CMD(a)) {
196N/A aw_skip_args(arglist, aw_cmd_table[a].cmd_numargs);
196N/A a = va_arg(arglist, int);
196N/A continue;
196N/A }
196N/A
196N/A aw_get_args(arglist, ad, aw_cmd_table[a].cmd_numargs);
196N/A
196N/A switch (a) {
196N/A
196N/A case AW_ARG:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_arg32((char)(uintptr_t)ad[0],
196N/A (char *)ad[1],
196N/A (uint32_t)(uintptr_t)ad[2])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len), tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_ATTR: {
196N/A /*
196N/A * This is a bit of a hack. Rather than
196N/A * write a new au_to_attr() routine, we
196N/A * simply allocate a new vattr and stuff
196N/A * values in.
196N/A */
196N/A vattr_t attr;
196N/A
196N/A if (aw_chk_addr((caddr_t)ad[6]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A
196N/A attr.va_mode = (int)(uintptr_t)ad[0];
196N/A attr.va_uid = (int)(uintptr_t)ad[1];
196N/A attr.va_gid = (int)(uintptr_t)ad[2];
196N/A attr.va_fsid = (int)(uintptr_t)ad[3];
196N/A attr.va_nodeid = (int)(uintptr_t)ad[4];
196N/A attr.va_rdev = (int)(uintptr_t)ad[5];
196N/A
196N/A if ((tokp = au_to_attr(&attr)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len), tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A }
196N/A
196N/A case AW_DATA:
196N/A if (aw_chk_print((char)(uintptr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_CMD_INVALID);
196N/A ad[0] = (void *)(uintptr_t)aw_cvrt_print(
196N/A (char)(uintptr_t)ad[0]);
196N/A if (aw_chk_type((char)(uintptr_t)ad[1]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_CMD_INVALID);
196N/A ad[1] = (void *)(uintptr_t)aw_cvrt_type(
196N/A (char)(uintptr_t)ad[1]);
196N/A if (aw_chk_addr((caddr_t)ad[3]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_data((char)(uintptr_t)ad[0],
196N/A (char)(uintptr_t)ad[1],
196N/A (char)(uintptr_t)ad[2], (char *)ad[3])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_EVENT:
196N/A aw_iflags |= AW_EVENT_FLAG;
196N/A if ((auevent = getauevnam((char *)ad[0]))
196N/A == (au_event_ent_t *)NULL)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_INVALID)
196N/A else
196N/A aw_set_event(cur_rd, auevent->ae_number,
196N/A auevent->ae_class);
196N/A break;
196N/A
196N/A case AW_EVENTNUM:
196N/A aw_iflags |= AW_EVENT_FLAG;
196N/A if ((cacheauevent(&auevent,
196N/A (au_event_t)(uintptr_t)ad[0])) != 1)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_INVALID)
196N/A else
196N/A aw_set_event(cur_rd, auevent->ae_number,
196N/A auevent->ae_class);
196N/A break;
196N/A
196N/A case AW_EXEC_ARGS:
196N/A if (!(audit_policies & AUDIT_ARGV))
196N/A break;
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_exec_args((char **)ad[0]))
196N/A == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_EXEC_ENV:
196N/A if (!(audit_policies & AUDIT_ARGE))
196N/A break;
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_exec_env((char **)ad[0]))
196N/A == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_EXIT:
196N/A if ((tokp = au_to_exit((int)(uintptr_t)ad[0],
196N/A (int)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_GROUPS:
196N/A if (!(audit_policies & AUDIT_GROUP))
196N/A break;
196N/A if (aw_chk_addr((caddr_t)ad[1]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_newgroups((int)(uintptr_t)ad[0],
196N/A (gid_t *)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_IN_ADDR:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_in_addr((struct in_addr *)
196N/A ad[0])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_IPC:
196N/A if ((tokp = au_to_ipc((char)(uintptr_t)ad[0],
196N/A (int)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_IPORT:
196N/A if ((tokp = au_to_iport((ushort_t)(uintptr_t)ad[0])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_OPAQUE:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_opaque((char *)ad[0],
196N/A (short)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_PATH:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A if (aw_cvrt_path((char *)ad[0], &apath) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A if ((tokp = au_to_path(apath)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_PRIVILEGE:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_privset("",
196N/A (priv_set_t *)ad[0])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_LEVEL:
196N/A case AW_SLABEL:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_label((bslabel_t *)ad[0])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_PROCESS:
196N/A if (aw_chk_addr((caddr_t)ad[7]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_process((uint32_t)(uintptr_t)ad[0],
196N/A (uint32_t)(uintptr_t)ad[1],
196N/A (uint32_t)(uintptr_t)ad[2],
196N/A (uint32_t)(uintptr_t)ad[3],
196N/A (uint32_t)(uintptr_t)ad[4],
196N/A (uint32_t)(uintptr_t)ad[5],
196N/A (uint32_t)(uintptr_t)ad[6],
196N/A (au_tid_t *)ad[7])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_PROCESS_EX:
196N/A if (aw_chk_addr((caddr_t)ad[7]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_process_ex((uint32_t)(uintptr_t)ad[0],
196N/A (uint32_t)(uintptr_t)ad[1],
196N/A (uint32_t)(uintptr_t)ad[2],
196N/A (uint32_t)(uintptr_t)ad[3],
196N/A (uint32_t)(uintptr_t)ad[4],
196N/A (uint32_t)(uintptr_t)ad[5],
196N/A (uint32_t)(uintptr_t)ad[6],
196N/A (au_tid_addr_t *)ad[7])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_RETURN:
196N/A aw_recs[cur_rd]->aflags |= AW_REC_RETURN_FLAG;
196N/A if ((tokp = au_to_return32((char)(uintptr_t)ad[0],
196N/A (uint_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A /*
196N/A * Set up event for success/failure preselection
196N/A */
196N/A if ((char)(uintptr_t)ad[0] != 0)
196N/A aw_recs[cur_rd]->event_mod |= PAD_FAILURE;
196N/A break;
196N/A
196N/A#if 0
196N/A case AW_SOCKET:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_socket((struct socket *)ad[0])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A#endif
196N/A
196N/A case AW_SUBJECT:
196N/A aw_recs[cur_rd]->aflags |= AW_REC_SUBJECT_FLAG;
196N/A if (aw_chk_addr((caddr_t)ad[7]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_subject((uint32_t)(uintptr_t)ad[0],
196N/A (uint32_t)(uintptr_t)ad[1],
196N/A (uint32_t)(uintptr_t)ad[2],
196N/A (uint32_t)(uintptr_t)ad[3],
196N/A (uint32_t)(uintptr_t)ad[4],
196N/A (uint32_t)(uintptr_t)ad[5],
196N/A (uint32_t)(uintptr_t)ad[6],
196N/A (au_tid_t *)ad[7])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_SUBJECT_EX:
196N/A aw_recs[cur_rd]->aflags |= AW_REC_SUBJECT_FLAG;
196N/A if (aw_chk_addr((caddr_t)ad[7]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_subject_ex((uint32_t)(uintptr_t)ad[0],
196N/A (uint32_t)(uintptr_t)ad[1],
196N/A (uint32_t)(uintptr_t)ad[2],
196N/A (uint32_t)(uintptr_t)ad[3],
196N/A (uint32_t)(uintptr_t)ad[4],
196N/A (uint32_t)(uintptr_t)ad[5],
196N/A (uint32_t)(uintptr_t)ad[6],
196N/A (au_tid_addr_t *)ad[7])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_USEOFPRIV:
196N/A if ((tokp = au_to_upriv((char)(uintptr_t)ad[0],
196N/A (char *)ad[1])) == (token_t *)0) {
196N/A aw_free_tok(tokp);
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL)
196N/A }
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_TEXT:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_text((char *)
196N/A ad[0])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_UAUTH:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if ((tokp = au_to_uauth((char *)
196N/A ad[0])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_CMD: {
196N/A char **env = NULL;
196N/A
196N/A if (aw_chk_addr((caddr_t)ad[1]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if (aw_chk_addr((caddr_t)ad[2]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A
196N/A if (audit_policies & AUDIT_ARGE)
196N/A env = (char **)ad[2];
196N/A
196N/A if ((tokp = au_to_cmd((int)(uintptr_t)ad[0],
196N/A (char **)ad[1], env)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len), tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A }
196N/A
196N/A case AW_XATOM:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
303N/A if ((tokp = au_to_xatom((char *)ad[0]))
196N/A == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XCLIENT:
303N/A if ((tokp = au_to_xclient(
196N/A (uint32_t)(uintptr_t)ad[0])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XCURSOR:
303N/A if ((tokp = au_to_xcursor(
196N/A (int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XCOLORMAP:
303N/A if ((tokp = au_to_xcolormap(
196N/A (int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XFONT:
303N/A if ((tokp = au_to_xfont((int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XGC:
303N/A if ((tokp = au_to_xgc((int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XPIXMAP:
303N/A if ((tokp = au_to_xpixmap(
196N/A (int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XPROPERTY:
196N/A if (aw_chk_addr((caddr_t)ad[2]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
303N/A if ((tokp = au_to_xproperty(
196N/A (int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1], (char *)ad[2])) ==
196N/A (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XSELECT:
196N/A if (aw_chk_addr((caddr_t)ad[0]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if (aw_chk_addr((caddr_t)ad[1]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A if (aw_chk_addr((caddr_t)ad[2]) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
303N/A if ((tokp = au_to_xselect((char *)ad[0],
196N/A (char *)ad[1], (char *)ad[2])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A case AW_XWINDOW:
303N/A if ((tokp = au_to_xwindow(
196N/A (int32_t)(uintptr_t)ad[0],
196N/A (uid_t)(uintptr_t)ad[1])) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[cur_rd]->buf),
196N/A &(aw_recs[cur_rd]->len),
196N/A tokp->tt_data,
196N/A (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A aw_free_tok(tokp);
196N/A break;
196N/A
196N/A default:
196N/A AW_GEN_ERR(AW_ERR_CMD_INVALID)
196N/A
196N/A } /* switch */
196N/A
196N/A a = va_arg(arglist, int);
196N/A
196N/A } /* while */
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ h e a d ( )
196N/A *
196N/A * Add a header to an audit record.
196N/A *
196N/A * Note that we no longer need to add a trailer in Solaris 2.x, as this
196N/A * is handled by the audit(2) system call.
196N/A */
196N/Astatic int
196N/Aaw_head(int rd)
196N/A{
196N/A
196N/A token_t *tokp;
196N/A adr_t adr; /* tmp pointer */
196N/A char id; /* tmp variable to hold value */
196N/A int32_t len; /* Value to fix */
196N/A
196N/A if ((tokp = au_to_header_ex(aw_recs[rd]->event_id,
196N/A aw_recs[rd]->event_mod)) == (token_t *)NULL)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A /*
196N/A * Need to fix up the size correctly.
196N/A */
196N/A len = aw_recs[rd]->len + tokp->tt_size;
196N/A adrm_start(&adr, tokp->tt_data); /* beginning of pointer */
196N/A adrm_char(&adr, &id, 1); /* move past attr id */
196N/A adr_int32(&adr, &len, 1); /* fix the length */
196N/A
196N/A if (aw_buf_prepend(&(aw_recs[rd]->buf), &(aw_recs[rd]->len),
196N/A tokp->tt_data, (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A
196N/A aw_free_tok(tokp);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ p a r s e ( )
196N/A *
196N/A * Parse the invocation line looking for invalid commands and invalid data
196N/A * (bad pointers).
196N/A *
196N/A * Returns AW_ERR_RTN when:
196N/A * more than one control command has been specified.
196N/A * AW_APPEND is specified w/out any attribute commands.
196N/A *
196N/A * Returns AW_SUCCESS_RTN upon success.
196N/A */
196N/Astatic int
196N/Aaw_parse(int param, va_list arglist)
196N/A{
196N/A int a;
196N/A au_event_ent_t *auevent;
196N/A void *ad[8]; /* argument data */
196N/A
196N/A /*
196N/A * During the port from TS 2, we had to slightly reorg code, thus
196N/A * I'm simply going to continue to use the "a" variable.
196N/A */
196N/A a = param;
196N/A
196N/A while (a != AW_END) {
196N/A
196N/A if (a < AW_CMD_MIN || a > AW_CMD_MAX)
196N/A AW_GEN_ERR(AW_ERR_CMD_INVALID);
196N/A
196N/A /*
196N/A * EVENT attribute and RETURN attribute have preselection
196N/A * info. Need to gobble up that info here so that we can
196N/A * preselect without the overhead of record construction.
196N/A */
196N/A if (AW_IS_DATA_CMD(a) &&
196N/A ((a != AW_EVENT) && (a != AW_EVENTNUM)) &&
196N/A (a != AW_RETURN)) {
196N/A aw_iflags |= AW_ATTRIB_FLAG;
196N/A aw_skip_args(arglist, aw_cmd_table[a].cmd_numargs);
196N/A /* Reload with next value of "a" */
196N/A a = va_arg(arglist, int);
196N/A continue;
196N/A }
196N/A
196N/A aw_get_args(arglist, ad, aw_cmd_table[a].cmd_numargs);
196N/A
196N/A switch (a) {
196N/A
196N/A /* AW_ABORT is not documented. It is used for debugging */
196N/A
196N/A case AW_ABORT:
196N/A aw_iflags |= AW_ABORT_FLAG;
196N/A break;
196N/A
196N/A case AW_APPEND:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_APPEND_FLAG;
196N/A break;
196N/A
196N/A case AW_EVENT:
196N/A aw_iflags |= AW_EVENT_FLAG;
196N/A aw_iflags |= AW_ATTRIB_FLAG;
196N/A if ((auevent = getauevnam((char *)ad[0]))
196N/A == (au_event_ent_t *)0)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_INVALID)
196N/A else
196N/A aw_set_event(cur_rd, auevent->ae_number,
196N/A auevent->ae_class);
196N/A break;
196N/A
196N/A case AW_EVENTNUM:
196N/A aw_iflags |= AW_EVENT_FLAG;
196N/A aw_iflags |= AW_ATTRIB_FLAG;
196N/A if ((cacheauevent(&auevent,
196N/A (au_event_t)(uintptr_t)ad[0])) != 1)
196N/A AW_GEN_ERR(AW_ERR_EVENT_ID_INVALID)
196N/A else
196N/A aw_set_event(cur_rd, auevent->ae_number,
196N/A auevent->ae_class);
196N/A break;
196N/A
196N/A case AW_QUEUE:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (aw_static_flags & AW_QUEUE_FLAG)
196N/A AW_GEN_ERR(AW_ERR_CMD_IN_EFFECT);
196N/A aw_queue_hiwater = (int)(uintptr_t)ad[0];
196N/A if (aw_queue_hiwater > AW_MAX_REC_SIZE ||
196N/A aw_queue_hiwater == 0)
196N/A AW_GEN_ERR(AW_ERR_QUEUE_SIZE_INVALID);
196N/A aw_iflags |= AW_QUEUE_FLAG;
196N/A break;
196N/A
196N/A case AW_DEFAULTRD:
196N/A AW_PARSE_ERR(AW_CTRLCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_DEFAULTRD_FLAG;
196N/A break;
196N/A
196N/A case AW_DISCARD:
196N/A AW_PARSE_ERR(AW_CTRLCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_DISCARD_FLAG;
196N/A break;
196N/A
196N/A case AW_DISCARDRD:
196N/A AW_PARSE_ERR(AW_CTRLCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A user_rd = (int)(uintptr_t)ad[0];
196N/A /*
196N/A * A specified rd of -1 here means that the
196N/A * default rd should be discarded.
196N/A */
196N/A if (user_rd == -1)
196N/A user_rd = dflt_rd;
196N/A aw_iflags |= AW_DISCARDRD_FLAG;
196N/A break;
196N/A
196N/A case AW_FLUSH:
196N/A AW_PARSE_ERR(AW_CTRLCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (!(aw_static_flags & AW_QUEUE_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_NOT_IN_EFFECT);
196N/A aw_iflags |= AW_FLUSH_FLAG;
196N/A break;
196N/A
196N/A case AW_GETRD:
196N/A AW_PARSE_ERR(AW_CTRLCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A get_rd_p = (int *)ad[0];
196N/A if (aw_chk_addr((caddr_t)get_rd_p) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A aw_iflags |= AW_GETRD_FLAG;
196N/A break;
196N/A
196N/A case AW_NOPRESELECT:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (!(aw_static_flags & AW_PRESELECT_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_NOT_IN_EFFECT);
196N/A aw_iflags |= AW_NOPRESELECT_FLAG;
196N/A break;
196N/A
196N/A case AW_NOQUEUE:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (!(aw_static_flags & AW_QUEUE_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_NOT_IN_EFFECT);
196N/A aw_queue_hiwater = 0;
196N/A aw_iflags |= AW_NOQUEUE_FLAG;
196N/A break;
196N/A
196N/A case AW_NOSAVE:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (!(aw_static_flags & AW_SAVERD_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_NOT_IN_EFFECT);
196N/A aw_iflags |= AW_NOSAVE_FLAG;
196N/A break;
196N/A
196N/A case AW_NOSERVER:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if (!(aw_static_flags & AW_SERVER_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_NOT_IN_EFFECT);
196N/A aw_iflags |= AW_NOSERVER_FLAG;
196N/A break;
196N/A
196N/A case AW_PRESELECT:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A if ((au_mask_t *)ad[0] != (au_mask_t *)0) {
196N/A (void) memcpy((char *)&pmask,
196N/A (char *)((au_mask_t *)ad[0]),
196N/A sizeof (au_mask_t));
196N/A }
196N/A aw_iflags |= AW_PRESELECT_FLAG;
196N/A break;
196N/A
196N/A case AW_RETURN:
196N/A /*
196N/A * Set up event for success/failure preselection
196N/A */
196N/A aw_iflags |= AW_ATTRIB_FLAG;
196N/A if ((char)(uintptr_t)ad[0] != 0)
196N/A aw_recs[cur_rd]->event_mod |= PAD_FAILURE;
196N/A break;
196N/A
196N/A case AW_SAVERD:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A save_rd_p = (int *)ad[0];
196N/A if (aw_chk_addr((caddr_t)save_rd_p) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ADDR_INVALID);
196N/A aw_iflags |= AW_SAVERD_FLAG;
196N/A break;
196N/A
196N/A case AW_SERVER:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_SERVER_FLAG;
196N/A break;
196N/A
196N/A case AW_USERD:
196N/A /*
196N/A * Already handled a valid one in aw_set_context().
196N/A */
196N/A AW_PARSE_ERR(AW_NOUSERDCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_USERD_FLAG;
196N/A break;
196N/A
196N/A case AW_WRITE:
196N/A AW_PARSE_ERR(AW_NORMALCMD_FLAGS, AW_ERR_CMD_TOO_MANY);
196N/A aw_iflags |= AW_WRITE_FLAG;
196N/A break;
196N/A
196N/A default:
196N/A AW_GEN_ERR(AW_ERR_CMD_INVALID)
196N/A
196N/A } /* switch */
196N/A
196N/A /* Reload with the next value of "a" */
196N/A a = va_arg(arglist, int);
196N/A
196N/A } /* while */
196N/A
196N/A /* Must have a control command */
196N/A if (!(aw_iflags & AW_CTRLCMD_FLAGS))
196N/A AW_GEN_ERR(AW_ERR_CMD_INCOMPLETE);
196N/A
196N/A /* Must be an attribute command with AW_APPEND control command */
196N/A if ((aw_iflags & AW_APPEND_FLAG) &&
196N/A !(aw_iflags & AW_ATTRIB_FLAG))
196N/A AW_GEN_ERR(AW_ERR_CMD_INCOMPLETE);
196N/A
196N/A /*
196N/A * If there was an attribute command, need a control command to that
196N/A * tells what to do with the attributes.
196N/A */
196N/A if ((aw_iflags & AW_ATTRIB_FLAG) &&
196N/A !((aw_iflags & AW_APPEND_FLAG) ||
196N/A (aw_iflags & AW_WRITE_FLAG)))
196N/A AW_GEN_ERR(AW_ERR_CMD_INCOMPLETE);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ p r e s e l e c t ( )
196N/A *
196N/A * Do user level audit preselection
196N/A *
196N/A * Returns:
196N/A * 1 - audit event is preselected
196N/A * 0 - audit event is not preselected
196N/A */
196N/Astatic int
196N/Aaw_preselect(int rd, au_mask_t *pmaskp)
196N/A{
196N/A if (aw_recs[rd]->event_mod & PAD_FAILURE)
196N/A return (aw_recs[rd]->class & pmaskp->am_failure);
196N/A
196N/A return (aw_recs[rd]->class & pmaskp->am_success);
196N/A}
196N/A
196N/A/*
196N/A * a w _ q u e u e _ d e a l l o c ( )
196N/A *
196N/A * Deallocate audit record queue.
196N/A */
196N/Astatic void
196N/Aaw_queue_dealloc(void)
196N/A{
196N/A aw_queue_bytes = 0;
196N/A aw_free(aw_queue);
196N/A aw_queue = (caddr_t)0;
196N/A}
196N/A
196N/A/*
196N/A * a w _ q u e u e _ f l u s h ( )
196N/A *
196N/A * Flush audit record queue.
196N/A */
196N/Astatic int
196N/Aaw_queue_flush(void)
196N/A{
196N/A /* write all records on queue to trail */
196N/A
196N/A if (aw_queue_bytes) {
196N/A if (auditctl(A_AUDIT, (uint32_t)aw_queue_bytes,
388N/A aw_queue) == -1)
196N/A AW_GEN_ERR(AW_ERR_AUDIT_FAIL);
196N/A
196N/A aw_queue_bytes = 0;
196N/A }
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ q u e u e _ w r i t e ( )
196N/A *
196N/A * "Queue" an audit record. Actually, each record passed is appended to a
196N/A * buffer. This buffer eventually gets written with auditctl(2). Auditctl(2)
196N/A * will process the records in the order in which it receives them. This
196N/A * creates a "queueing" effect.
196N/A */
196N/Astatic int
196N/Aaw_queue_write(int rd)
196N/A{
196N/A if (aw_queue_bytes + aw_recs[rd]->len > AW_MAX_REC_SIZE) {
196N/A
196N/A (void) aw_queue_flush();
196N/A
196N/A if ((auditctl(A_AUDIT, (uint32_t)aw_recs[rd]->len,
388N/A aw_recs[rd]->buf)) == -1)
196N/A AW_GEN_ERR(AW_ERR_AUDIT_FAIL);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A
196N/A /* no queue? allocate it now. */
196N/A
196N/A if (aw_buf_append(&aw_queue, &aw_queue_bytes,
196N/A aw_recs[rd]->buf, aw_recs[rd]->len) == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A
196N/A /* did we reach the hi-water mark? */
196N/A
196N/A if (aw_queue_bytes >= aw_queue_hiwater)
196N/A if (aw_queue_flush() == AW_ERR_RTN)
196N/A return (AW_ERR_RTN);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ r e c _ i n i t ( )
196N/A *
196N/A * Init a rec area.
196N/A *
196N/A */
196N/Astatic void
196N/Aaw_rec_init(aw_rec_t *rec)
196N/A{
196N/A rec->event_id = 0;
196N/A rec->event_mod = 0;
196N/A
196N/A rec->context.static_flags = AW_NO_FLAGS;
196N/A rec->context.save_rd = AW_NO_RD;
196N/A rec->context.aw_errno = AW_ERR_NO_ERROR;
196N/A rec->context.pmask.am_success = 0;
196N/A rec->context.pmask.am_failure = 0;
196N/A}
196N/A/*
196N/A * a w _ r e c _ a l l o c ( )
196N/A *
196N/A * Allocate a buffer to store an audit record.
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_rec_alloc(int *rdp)
196N/A{
196N/A int slot;
196N/A
196N/A /* allocate the audit record buffer pointers */
196N/A
196N/A if (aw_recs == (aw_rec_t **)0) {
196N/A if ((aw_recs = (aw_rec_t **)calloc(AW_NUM_RECP,
196N/A (size_t)sizeof (aw_rec_t *))) == (aw_rec_t **)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A aw_num_recs = AW_NUM_RECP;
196N/A
196N/A /* allocate the record */
196N/A
196N/A if ((aw_recs[0] = (aw_rec_t *)calloc(1,
196N/A (size_t)sizeof (aw_rec_t))) == (aw_rec_t *)0)
196N/A return (AW_ERR_RTN);
196N/A
196N/A aw_rec_init(aw_recs[0]);
196N/A *rdp = 0;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A /* linear search to find the next open slot */
196N/A
196N/A for (slot = 0; slot < aw_num_recs; slot++)
196N/A if (aw_recs[slot] == (aw_rec_t *)0) {
196N/A
196N/A /* allocate the record */
196N/A
196N/A if ((aw_recs[slot] = (aw_rec_t *)calloc(1,
196N/A (size_t)sizeof (aw_rec_t))) == (aw_rec_t *)0)
196N/A return (AW_ERR_RTN);
196N/A
196N/A aw_rec_init(aw_recs[slot]);
196N/A *rdp = slot;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A /* no open slots, allocate for another */
196N/A if ((aw_recs = (aw_rec_t **)realloc((void *)aw_recs,
196N/A ((size_t)(aw_num_recs + 1) * sizeof (aw_rec_t *)))) ==
196N/A (aw_rec_t **)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A
196N/A /* allocate the record */
196N/A
196N/A slot = aw_num_recs;
196N/A
196N/A if ((aw_recs[slot] = (aw_rec_t *)calloc(1, (size_t)sizeof (aw_rec_t)))
196N/A == (aw_rec_t *)0)
196N/A return (AW_ERR_RTN);
196N/A
196N/A aw_rec_init(aw_recs[aw_num_recs]);
196N/A *rdp = aw_num_recs++;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A#ifdef NOTYET
196N/A/*
196N/A * a w _ r e c _ a p p e n d ( )
196N/A *
196N/A * Concatentate two previously allocated records.
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_rec_append(int to_rd, int from_rd)
196N/A{
196N/A if (aw_chk_rd(to_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A if (aw_chk_rd(from_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A if (aw_recs[from_rd]->event_id) {
196N/A aw_recs[to_rd]->event_id = aw_recs[from_rd]->event_id;
196N/A aw_recs[to_rd]->class = aw_recs[from_rd]->class;
196N/A }
196N/A
196N/A aw_recs[to_rd]->aflags |= aw_recs[from_rd]->aflags;
196N/A
196N/A if ((aw_recs[to_rd]->len +
196N/A aw_recs[from_rd]->len) > AW_MAX_REC_SIZE)
196N/A AW_GEN_ERR(AW_ERR_REC_TOO_BIG);
196N/A
196N/A return (aw_buf_append(&(aw_recs[to_rd]->buf),
196N/A &(aw_recs[to_rd]->len),
196N/A aw_recs[from_rd]->buf,
196N/A aw_recs[from_rd]->len));
196N/A}
196N/A#endif /* NOTYET */
196N/A
196N/A/*
196N/A * a w _ r e c _ d e a l l o c ( )
196N/A *
196N/A * Deallocate a previously allocated audit record buffer.
196N/A *
196N/A */
196N/Astatic void
196N/Aaw_rec_dealloc(int rd)
196N/A{
196N/A /* free the audit record buffer */
196N/A
196N/A if (aw_recs[rd] == (aw_rec_t *)0)
196N/A return;
196N/A
196N/A aw_free(aw_recs[rd]->buf);
196N/A aw_recs[rd]->buf = (caddr_t)0;
196N/A
196N/A /* free the record */
196N/A
196N/A aw_free((caddr_t)aw_recs[rd]);
196N/A aw_recs[rd] = (aw_rec_t *)0;
196N/A}
196N/A
196N/A/*
196N/A * a w _ r e c _ p r e p e n d ( )
196N/A *
196N/A * Prepend a record buffer with the contents of another record buffer.
196N/A *
196N/A */
196N/Astatic int
196N/Aaw_rec_prepend(int to_rd, int from_rd)
196N/A{
196N/A if (aw_chk_rd(to_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A if (aw_chk_rd(from_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A if (aw_recs[from_rd]->event_id)
196N/A aw_recs[to_rd]->event_id = aw_recs[from_rd]->event_id;
196N/A
196N/A if ((aw_recs[to_rd]->len +
196N/A aw_recs[from_rd]->len) > AW_MAX_REC_SIZE)
196N/A AW_GEN_ERR(AW_ERR_REC_TOO_BIG);
196N/A
196N/A return (aw_buf_prepend(&(aw_recs[to_rd]->buf),
196N/A &(aw_recs[to_rd]->len),
196N/A aw_recs[from_rd]->buf,
196N/A aw_recs[from_rd]->len));
196N/A}
196N/A
196N/Astatic int
196N/Aaw_return_attrib(int rd)
196N/A{
196N/A token_t *tokp;
196N/A
196N/A /*
196N/A * append a return token indicating a success event
196N/A */
196N/A if ((tokp = au_to_return32(0, 0)) == (token_t *)0)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A if (aw_buf_append(&(aw_recs[rd]->buf), &(aw_recs[rd]->len),
196N/A tokp->tt_data, (int)tokp->tt_size) == AW_ERR_RTN) {
196N/A aw_free_tok(tokp);
196N/A return (AW_ERR_RTN);
196N/A }
196N/A
196N/A aw_free_tok(tokp);
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ s e t _ e r r ( )
196N/A *
196N/A * This routine sets aw_errno. It insures aw_errno is set
196N/A * once per invocation.
196N/A */
196N/Astatic void
196N/Aaw_set_err(int error)
196N/A{
196N/A if (error == AW_ERR_NO_ERROR || aw_errno == AW_ERR_NO_ERROR)
196N/A aw_errno = error;
196N/A}
196N/A
196N/A/*
196N/A * a w _ s e t _ e v e n t ( )
196N/A *
196N/A * Set event id and class.
196N/A */
196N/Astatic void
196N/Aaw_set_event(int rd, au_event_t event_id, uint_t class)
196N/A{
196N/A aw_recs[rd]->event_id = event_id;
196N/A aw_recs[rd]->class = class;
196N/A}
196N/A
196N/A/*
196N/A * a w _ i n i t ( )
196N/A *
196N/A * if this is the first invocation of auditwrite(3), do some setup
196N/A */
196N/Astatic int
196N/Aaw_init(void)
196N/A{
196N/A auditinfo_addr_t auinfo; /* tmp holder for masks */
196N/A
196N/A aw_errno = AW_ERR_NO_ERROR; /* No error so far */
196N/A
196N/A /*
196N/A * allocate a default audit record buf if we don't have one.
196N/A */
196N/A if (dflt_rd == AW_NO_RD) {
196N/A if (aw_rec_alloc(&dflt_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_ALLOC_FAIL);
196N/A }
196N/A
196N/A /*
196N/A * current record buf was recently deallocated
196N/A * set it back to the default
196N/A */
196N/A if (cur_rd == AW_NO_RD)
196N/A cur_rd = dflt_rd;
196N/A
196N/A if (aw_static_flags & AW_INVOKED_BEFORE_FLAG) {
196N/A aw_iflags = AW_NO_FLAGS;
196N/A return (AW_SUCCESS_RTN);
196N/A }
196N/A
196N/A /*
196N/A * First call setup
196N/A *
196N/A * Cache the preselection mask and the audit policies in order
196N/A * to reduce system call overhead. If they change, we will be
196N/A * auditing with stale values.
196N/A */
196N/A if (getaudit_addr(&auinfo, sizeof (auinfo)) == -1)
196N/A AW_GEN_ERR(AW_ERR_GETAUDIT_FAIL);
196N/A
196N/A /* Stuff the real values in */
196N/A pmask = auinfo.ai_mask;
196N/A
196N/A if (auditon(A_GETPOLICY, (caddr_t)&audit_policies, 0) == -1)
196N/A AW_GEN_ERR(AW_ERR_AUDIT_FAIL);
196N/A
196N/A aw_static_flags |= AW_INVOKED_BEFORE_FLAG;
196N/A
196N/A cur_rd = dflt_rd;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ s e t _ c o n t e x t ( )
196N/A *
196N/A * set context as needed.
196N/A */
196N/Astatic int
196N/Aaw_set_context(int param, va_list arglist)
196N/A{
196N/A int a;
196N/A void *ad[8]; /* argument data */
196N/A
196N/A a = param;
196N/A
196N/A /*
196N/A * If the input params start with USERD and after this there's
196N/A * anything besides AW_END, then we need to switch to the context
196N/A * for that record descriptor.
196N/A */
196N/A if (a != AW_USERD)
196N/A return (AW_SUCCESS_RTN);
196N/A
196N/A aw_get_args(arglist, ad, aw_cmd_table[a].cmd_numargs);
196N/A user_rd = (int)(uintptr_t)ad[0];
196N/A if (aw_chk_rd(user_rd) == AW_ERR_RTN)
196N/A AW_GEN_ERR(AW_ERR_RD_INVALID);
196N/A
196N/A a = va_arg(arglist, int);
196N/A if (a != AW_END) {
196N/A /*
196N/A * USERD is used with another command.
196N/A * Save context first, then load context for the
196N/A * given rd.
196N/A */
196N/A old_context.static_flags = aw_static_flags;
196N/A old_context.save_rd = save_rd;
196N/A old_context.aw_errno = aw_errno;
196N/A old_context.pmask = pmask;
196N/A
196N/A old_cur_rd = cur_rd;
196N/A
196N/A /*
196N/A * Now load up our values.
196N/A */
196N/A aw_static_flags =
196N/A aw_recs[user_rd]->context.static_flags;
196N/A save_rd = aw_recs[user_rd]->context.save_rd;
196N/A aw_errno = aw_recs[user_rd]->context.aw_errno;
196N/A pmask = aw_recs[user_rd]->context.pmask;
196N/A
196N/A /* initialize as needed... */
196N/A if (aw_init() == AW_ERR_RTN) {
196N/A return (AW_ERR_RTN);
196N/A }
196N/A
196N/A aw_iflags |= AW_SAVEDONE;
196N/A }
196N/A
196N/A /*
196N/A * Finish basic USERD processing here.
196N/A */
196N/A cur_rd = user_rd;
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ r e s t o r e ( )
196N/A *
196N/A * restore context if needed.
196N/A */
196N/Astatic void
196N/Aaw_restore(void)
196N/A{
196N/A if (aw_iflags & AW_SAVEDONE) {
196N/A /*
196N/A * Save context for our rd first... If our rd is gone
196N/A * by now, we can't and won't need to do this part.
196N/A */
196N/A if ((user_rd <= aw_num_recs) &&
196N/A (aw_recs[user_rd] != (aw_rec_t *)0)) {
196N/A aw_recs[user_rd]->context.static_flags =
196N/A aw_static_flags;
196N/A aw_recs[user_rd]->context.save_rd = save_rd;
196N/A aw_recs[user_rd]->context.aw_errno = aw_errno;
196N/A aw_recs[user_rd]->context.pmask = pmask;
196N/A }
196N/A
196N/A /*
196N/A * Now restore the old values.
196N/A */
196N/A aw_static_flags = old_context.static_flags;
196N/A save_rd = old_context.save_rd;
196N/A pmask = old_context.pmask;
196N/A
196N/A cur_rd = old_cur_rd;
196N/A
196N/A aw_iflags &= ~AW_SAVEDONE;
196N/A }
196N/A}
196N/A
196N/A/*
196N/A * a w _ a u d i t _ w r i t e ( )
196N/A *
196N/A * Write an audit record to the audit trail using the audit(2) system call.
196N/A */
196N/Astatic int
196N/Aaw_audit_write(int rd)
196N/A{
196N/A if (audit(aw_recs[rd]->buf, aw_recs[rd]->len) == -1)
196N/A AW_GEN_ERR(AW_ERR_AUDIT_FAIL);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A/*
196N/A * a w _ a u d i t c t l _ w r i t e ( )
196N/A *
196N/A * Write an audit record to the audit trail using the auditctl(2) system call.
196N/A */
196N/Astatic int
196N/Aaw_auditctl_write(int rd)
196N/A{
196N/A if (auditctl(A_AUDIT, (uint32_t)aw_recs[rd]->len,
388N/A aw_recs[rd]->buf) == -1)
196N/A AW_GEN_ERR(AW_ERR_AUDIT_FAIL);
196N/A
196N/A return (AW_SUCCESS_RTN);
196N/A}
196N/A
196N/A#ifdef DEBUG
196N/A/*
196N/A * aw_debuglog: dump auditwrite parameters and current state
196N/A * to the debug file.
196N/A *
196N/A * General format of such an entry:
196N/A *
196N/A * xxx e pid= nnn stat-flags= xxxxxx aw_errno= n cur_rd= n
196N/A * dflt_rd= n save_rd= n arg1 arg2 ... arg11
196N/A *
196N/A * ...where:
196N/A * xxx = text, generally either "in" (auditwrite begin) or "out" (exit)
196N/A * e = auditwrite return value (significant only with "out")
196N/A * arg1, = auditwrite arguments (1st 11 only, whether used or not)
196N/A * arg2
196N/A * ...
196N/A *
196N/A */
196N/Astatic int cntr = 0;
196N/A
196N/Astatic void
196N/Aaw_debuglog(char *s, int rc, int param, va_list arglist)
196N/A{
196N/A void *a;
196N/A int i;
196N/A FILE *f;
196N/A
196N/A f = fopen("/var/audit/awlog", "a");
196N/A if (f == NULL) {
196N/A return;
196N/A }
196N/A
196N/A if (strcmp(s, "in ") == 0) {
196N/A cntr++;
196N/A (void) fprintf(f, "\n%4d \n", cntr);
196N/A }
196N/A
196N/A (void) fprintf(f, "%9s ", s);
196N/A (void) fprintf(f, "%8d ", rc);
196N/A (void) fprintf(f, "pid= %7ld ", (long)getpid());
196N/A
196N/A (void) fprintf(f, "stat-flags= %8x ", aw_static_flags);
196N/A (void) fprintf(f, "aw_errno= %8d ", aw_errno);
196N/A
196N/A (void) fprintf(f, "cur_rd= %8x ", cur_rd);
196N/A (void) fprintf(f, "dflt_rd= %8x ", dflt_rd);
196N/A (void) fprintf(f, "save_rd= %8x\n\t\t", save_rd);
196N/A
196N/A if ((arglist == 0) && (param == 0))
196N/A goto done;
196N/A
196N/A /*
196N/A * Now dump in the arguments auditwrite was called with... Since
196N/A * the number of args is variable, just dump the first 10 or so
196N/A * (some of which may not actually have been passed).
196N/A */
196N/A a = (void *)param;
196N/A for (i = 1; i <= 10; i++) {
196N/A (void) fprintf(f, "%d ", a);
196N/A a = va_arg(arglist, void *);
196N/A }
196N/A
196N/Adone:
196N/A (void) fprintf(f, "\n");
196N/A (void) fclose(f);
196N/A}
196N/A#endif
196N/A
196N/A/*
196N/A * aw_strerror: return the error string
196N/A */
196N/Achar *
196N/Aaw_strerror(const int aw_errnum)
196N/A{
196N/A if ((aw_errnum < aw_nerr) && (aw_errnum >= 0))
196N/A return (aw_errlist[aw_errnum]);
196N/A else
196N/A return (NULL);
196N/A}
196N/A
196N/A/*
196N/A * aw_geterrno: return the aw_errno for the given descriptor.
196N/A */
196N/Aint
196N/Aaw_geterrno(const int rd)
196N/A{
196N/A int err;
196N/A
196N/A (void) mutex_lock(&mutex_auditwrite);
196N/A
196N/A if (aw_chk_rd(rd) == AW_ERR_RTN) {
196N/A (void) mutex_unlock(&mutex_auditwrite);
196N/A return (AW_ERR_RD_INVALID);
196N/A }
196N/A
196N/A err = aw_recs[rd]->context.aw_errno;
196N/A
196N/A (void) mutex_unlock(&mutex_auditwrite);
196N/A return (err);
196N/A}
196N/A
196N/A/*
196N/A * aw_perror_c: common internal routine to return the error string
196N/A */
196N/Astatic void
196N/Aaw_perror_c(const int err, const char *s)
196N/A{
196N/A char *c;
196N/A
196N/A if ((err < aw_nerr) && (err >= 0))
196N/A c = aw_errlist[err];
196N/A else
196N/A c = "Unknown error";
196N/A
196N/A if (s && *s) {
196N/A (void) write(2, s, strlen(s));
196N/A (void) write(2, ": ", 2);
196N/A }
196N/A
196N/A (void) write(2, c, strlen(c));
196N/A (void) write(2, "\n", 1);
196N/A}
196N/A
196N/A/*
196N/A * aw_perror: return the error string
196N/A */
196N/Avoid
196N/Aaw_perror(const char *s)
196N/A{
196N/A aw_perror_c(aw_errno, s);
196N/A}
196N/A
196N/A/*
196N/A * aw_perror_r: return the error string
196N/A */
196N/Avoid
196N/Aaw_perror_r(const int rd, const char *s)
196N/A{
196N/A int err;
196N/A
196N/A err = aw_geterrno(rd);
196N/A aw_perror_c(err, s);
196N/A}
196N/A
196N/A/*
196N/A * Currently we are using Solaris 2.x BSM's audit mechanism,
196N/A * which doesn't have the large queue buffer mechanism. Rather
196N/A * than rewrite the system call, we'll simply emulate the large
196N/A * buffer write. If this gets to be problem in performance,
196N/A * we can readd the system call.
196N/A */
196N/Astatic int
388N/Aauditctl(uint32_t command, uint32_t value, caddr_t data)
196N/A{
196N/A uint32_t bytes_left = value; /* number of bytes to write */
388N/A caddr_t mover = data; /* moving pointer */
196N/A adr_t adr; /* byte independent addressing */
196N/A char id; /* check for proper audit record */
196N/A int32_t bytes; /* number of bytes for this record */
196N/A
196N/A /* The only remaining option to auditctl is be A_AUDIT */
196N/A if (command != A_AUDIT)
196N/A return (-1);
196N/A
196N/A while (bytes_left > (uint32_t)0) {
196N/A
196N/A /* Where to start parsing */
196N/A adrm_start(&adr, mover);
196N/A adrm_char(&adr, &id, 1);
196N/A adrm_int32(&adr, &bytes, 1);
196N/A
196N/A /* Make sure we have a header and output the record */
196N/A
196N/A if (!((id == AUT_HEADER32) || (id == AUT_HEADER64) ||
196N/A (id == AUT_HEADER32_EX) || (id == AUT_HEADER64_EX)) ||
196N/A (bytes > bytes_left)) {
196N/A errno = EINVAL;
196N/A return (-1);
196N/A }
196N/A
196N/A if (audit((caddr_t)mover, bytes) != 0) {
196N/A /* Use the audit(2) errno */
196N/A return (-1);
196N/A }
196N/A
196N/A mover += bytes;
196N/A bytes_left -= bytes;
196N/A }
196N/A
196N/A /* Last minute check to make sure we wrote out the exact number */
196N/A if (bytes_left != 0) {
196N/A errno = E2BIG;
196N/A return (-1);
196N/A }
196N/A
196N/A return (0);
196N/A}