2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A
2N/A/*
2N/A * Token processing for sysupd; each token function does one
2N/A * or more operations. All of them bump the buffer pointer
2N/A * to the next token; some of them extract one or more data
2N/A * from the token.
2N/A */
2N/A
2N/A#include <locale.h>
2N/A#include <stdlib.h>
2N/A#include <stdio.h>
2N/A#include <string.h>
2N/A#include <sys/types.h>
2N/A#include <bsm/libbsm.h>
2N/A#include <sys/tsol/label.h>
2N/A#include <toktable.h>
2N/A#include "sysplugin.h"
2N/A#include <audit_plugin.h>
2N/A
2N/Astatic void anchor_path(char *);
2N/Astatic size_t collapse_path(char *, size_t);
2N/Astatic void get_bytes_to_string(parse_context_t *, size_t *, char **,
2N/A size_t);
2N/Astatic void skip_bytes(parse_context_t *);
2N/Astatic void skip_string(parse_context_t *);
2N/Astatic int xgeneric(parse_context_t *);
2N/A
2N/A/*
2N/A * parse_token - process a token in a record to (1) extract data of interest
2N/A * if any and (2) point to the next token.
2N/A *
2N/A * returns 0 if ok. + or - values are of debug value:
2N/A *
2N/A * returns -1 if the parsing of the token failed.
2N/A *
2N/A * returns +<previous id> if the token is not found. This value
2N/A * is used to help determine where in the record the problem
2N/A * occurred. The common failure case is that the parsing of
2N/A * token M is incorrect and the buffer pointer ends up pointing
2N/A * to garbage. The positive error value of M *may* be the id of
2N/A * the incorrectly parsed token.
2N/A */
2N/Aint
2N/Aparse_token(parse_context_t *ctx)
2N/A{
2N/A char tokenid;
2N/A static char prev_tokenid = -1;
2N/A int rc;
2N/A
2N/A#if DEBUG
2N/A static boolean_t first = 1;
2N/A
2N/A if (first) {
2N/A dbfp = __auditd_debug_file_open();
2N/A first = 0;
2N/A }
2N/A#endif
2N/A
2N/A adrm_char(&(ctx->adr), &tokenid, 1);
2N/A
2N/A if ((tokenid > 0) && (tokentable[tokenid].func != NOFUNC)) {
2N/A rc = (*tokentable[tokenid].func)(ctx);
2N/A prev_tokenid = tokenid;
2N/A return (rc);
2N/A }
2N/A /* here if token id is not in table */
2N/A return (prev_tokenid);
2N/A}
2N/A
2N/A/* There should not be any file tokens in the middle of a record */
2N/A
2N/A/* ARGSUSED */
2N/Aint
2N/Afile_token(parse_context_t *ctx)
2N/A{
2N/A return (-1);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Aint
2N/Afile64_token(parse_context_t *ctx)
2N/A{
2N/A return (-1);
2N/A}
2N/A
2N/Astatic void
2N/Acommon_header(parse_context_t *ctx)
2N/A{
2N/A adrm_u_int32(&(ctx->adr), &(ctx->out.sf_reclen), 1);
2N/A ctx->adr.adr_now += sizeof (char); /* version number */
2N/A adrm_u_short(&(ctx->adr), &(ctx->out.sf_eventid), 1);
2N/A ctx->adr.adr_now += sizeof (short); /* modifier */
2N/A}
2N/A
2N/A/*
2N/A * 32bit header
2N/A */
2N/Aint
2N/Aheader_token(parse_context_t *ctx)
2N/A{
2N/A common_header(ctx);
2N/A ctx->adr.adr_now += 2 * sizeof (int32_t); /* time */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Aint
2N/Aheader32_ex_token(parse_context_t *ctx)
2N/A{
2N/A int32_t type;
2N/A
2N/A common_header(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &type, 1); /* tid type */
2N/A ctx->adr.adr_now += type * sizeof (char); /* ip address */
2N/A
2N/A ctx->adr.adr_now += 2 * sizeof (int32_t); /* time */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Aint
2N/Aheader64_ex_token(parse_context_t *ctx)
2N/A{
2N/A int32_t type;
2N/A
2N/A common_header(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &type, 1); /* tid type */
2N/A ctx->adr.adr_now += type * sizeof (char); /* ip address */
2N/A
2N/A ctx->adr.adr_now += 2 * sizeof (int64_t); /* time */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Aint
2N/Aheader64_token(parse_context_t *ctx)
2N/A{
2N/A common_header(ctx);
2N/A
2N/A ctx->adr.adr_now += 2 * sizeof (int64_t); /* time */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * ======================================================
2N/A * The following token processing routines return
2N/A * 0: if parsed ok
2N/A * -1: can't parse and can't determine location of next token
2N/A * ======================================================
2N/A */
2N/A
2N/Aint
2N/Atrailer_token(parse_context_t *ctx)
2N/A{
2N/A short magic_number;
2N/A uint32_t bytes;
2N/A
2N/A adrm_u_short(&(ctx->adr), (ushort_t *)&magic_number, 1);
2N/A if (magic_number != AUT_TRAILER_MAGIC)
2N/A return (-1);
2N/A
2N/A adrm_u_int32(&(ctx->adr), &bytes, 1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of arbitrary data token:
2N/A * arbitrary data token id &(ctx->adr) char
2N/A * how to print adr_char
2N/A * basic unit adr_char
2N/A * unit count adr_char, specifying number of units of
2N/A * data items depends on basic unit
2N/A *
2N/A */
2N/Aint
2N/Aarbitrary_data_token(parse_context_t *ctx)
2N/A{
2N/A char basic_unit, unit_count;
2N/A
2N/A ctx->adr.adr_now += sizeof (char); /* how to print */
2N/A
2N/A adrm_char(&(ctx->adr), &basic_unit, 1);
2N/A adrm_char(&(ctx->adr), &unit_count, 1);
2N/A
2N/A switch (basic_unit) {
2N/A case AUR_CHAR: /* same as AUR_BYTE */
2N/A ctx->adr.adr_now += unit_count * sizeof (char);
2N/A break;
2N/A case AUR_SHORT:
2N/A ctx->adr.adr_now += unit_count * sizeof (short);
2N/A break;
2N/A case AUR_INT32: /* same as AUR_INT */
2N/A ctx->adr.adr_now += unit_count * sizeof (int32_t);
2N/A break;
2N/A case AUR_INT64:
2N/A ctx->adr.adr_now += unit_count * sizeof (int64_t);
2N/A break;
2N/A default:
2N/A return (-1);
2N/A /* NOTREACHED */
2N/A break;
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of opaque token:
2N/A * opaque token id adr_char
2N/A * size adr_short
2N/A * data adr_char, size times
2N/A *
2N/A */
2N/Aint
2N/Aopaque_token(parse_context_t *ctx)
2N/A{
2N/A skip_bytes(ctx);
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of return32 value token:
2N/A * return value token id adr_char
2N/A * error number adr_char
2N/A * return value adr_u_int32
2N/A *
2N/A */
2N/Aint
2N/Areturn_value32_token(parse_context_t *ctx)
2N/A{
2N/A char errnum;
2N/A
2N/A adrm_char(&(ctx->adr), &errnum, 1); /* pass / fail */
2N/A ctx->adr.adr_now += sizeof (int32_t); /* error code */
2N/A
2N/A ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of return64 value token:
2N/A * return value token id adr_char
2N/A * error number adr_char
2N/A * return value adr_u_int64
2N/A *
2N/A */
2N/Aint
2N/Areturn_value64_token(parse_context_t *ctx)
2N/A{
2N/A char errnum;
2N/A
2N/A adrm_char(&(ctx->adr), &errnum, 1); /* pass / fail */
2N/A ctx->adr.adr_now += sizeof (int64_t); /* error code */
2N/A
2N/A ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of sequence token:
2N/A * sequence token id adr_char
2N/A * audit_count int32_t
2N/A *
2N/A */
2N/Aint
2N/Asequence_token(parse_context_t *ctx)
2N/A{
2N/A adrm_int32(&(ctx->adr), &(ctx->out.sf_sequence), 1);
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of text token:
2N/A * text token id adr_char
2N/A * text adr_string
2N/A */
2N/Aint
2N/Atext_token(parse_context_t *ctx)
2N/A{
2N/A ushort_t len;
2N/A size_t separator_sz = 0;
2N/A char *bp; /* pointer to output string */
2N/A
2N/A adrm_u_short(&(ctx->adr), &len, 1);
2N/A
2N/A if (ctx->out.sf_textlen > 0)
2N/A separator_sz = sizeof (AU_TEXT_NAME) - 1;
2N/A
2N/A DPRINT((dbfp, "text_token: start length=%d, add length=%d+%d\n",
2N/A ctx->out.sf_textlen, (size_t)len, separator_sz));
2N/A
2N/A ctx->out.sf_text = realloc(ctx->out.sf_text,
2N/A ctx->out.sf_textlen + (size_t)len + separator_sz);
2N/A
2N/A if (ctx->out.sf_text == NULL)
2N/A return (-1);
2N/A
2N/A bp = ctx->out.sf_text;
2N/A
2N/A if (ctx->out.sf_textlen != 0) { /* concatenation? */
2N/A bp += ctx->out.sf_textlen;
2N/A bp += strlcpy(bp, AU_TEXT_NAME, separator_sz + 1);
2N/A ctx->out.sf_textlen += separator_sz;
2N/A DPRINT((dbfp, "text_token: l is %d\n%s\n", ctx->out.sf_textlen,
2N/A ctx->out.sf_text));
2N/A }
2N/A adrm_char(&(ctx->adr), bp, len);
2N/A len--; /* includes EOS */
2N/A *(bp + len) = '\0';
2N/A
2N/A ctx->out.sf_textlen += len;
2N/A DPRINT((dbfp, "text_token: l=%d\n%s\n", ctx->out.sf_textlen,
2N/A ctx->out.sf_text));
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of tid token:
2N/A * ip token id adr_char
2N/A * terminal type adr_char
2N/A * terminal type = AU_IPADR:
2N/A * remote port: ushort
2N/A * local port: ushort
2N/A * IP type: int32 -- AU_IPv4 or AU_IPv6
2N/A * address: int32 if IPv4, else 4 * int32
2N/A */
2N/Aint
2N/Atid_token(parse_context_t *ctx)
2N/A{
2N/A uchar_t type;
2N/A int32_t ip_length;
2N/A
2N/A adrm_char(&(ctx->adr), (char *)&type, 1);
2N/A
2N/A switch (type) {
2N/A default:
2N/A return (-1); /* other than IP type is not implemented */
2N/A case AU_IPADR:
2N/A ctx->adr.adr_now += 2 * sizeof (ushort_t);
2N/A adrm_int32(&(ctx->adr), &ip_length, 1);
2N/A ctx->adr.adr_now += ip_length;
2N/A break;
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of ip_addr token:
2N/A * ip token id adr_char
2N/A * address adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aip_addr_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of ip_addr_ex token:
2N/A * ip token id adr_char
2N/A * ip type adr_int32
2N/A * ip address adr_u_char*type
2N/A *
2N/A */
2N/Aint
2N/Aip_addr_ex_token(parse_context_t *ctx)
2N/A{
2N/A int32_t type;
2N/A
2N/A adrm_int32(&(ctx->adr), &type, 1); /* ip type */
2N/A ctx->adr.adr_now += type * sizeof (uchar_t); /* ip address */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of ip token:
2N/A * ip header token id adr_char
2N/A * version adr_char
2N/A * type of service adr_char
2N/A * length adr_short
2N/A * id adr_u_short
2N/A * offset adr_u_short
2N/A * ttl adr_char
2N/A * protocol adr_char
2N/A * checksum adr_u_short
2N/A * source address adr_int32
2N/A * destination address adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aip_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += (2 * sizeof (char)) + (3 * sizeof (short)) +
2N/A (2 * sizeof (char)) + sizeof (short) + (2 * sizeof (int32_t));
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of iport token:
2N/A * ip port address token id adr_char
2N/A * port address adr_short
2N/A *
2N/A */
2N/Aint
2N/Aiport_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (short);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of groups token:
2N/A * group token id adr_char
2N/A * group list adr_int32, 16 times
2N/A *
2N/A */
2N/Aint
2N/Agroup_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 16 * sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of newgroups token:
2N/A * group token id adr_char
2N/A * number of groups adr_short
2N/A * group list adr_int32, "number" times
2N/A *
2N/A */
2N/Aint
2N/Anewgroup_token(parse_context_t *ctx)
2N/A{
2N/A short int number;
2N/A
2N/A adrm_short(&(ctx->adr), &number, 1);
2N/A
2N/A ctx->adr.adr_now += number * sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of argument32 token:
2N/A * argument token id adr_char
2N/A * argument number adr_char
2N/A * argument value adr_int32
2N/A * argument description adr_string
2N/A *
2N/A */
2N/Aint
2N/Aargument32_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (char) + sizeof (int32_t);
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of argument64 token:
2N/A * argument token id adr_char
2N/A * argument number adr_char
2N/A * argument value adr_int64
2N/A * argument description adr_string
2N/A *
2N/A */
2N/Aint
2N/Aargument64_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (char) + sizeof (int64_t);
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of acl token:
2N/A * acl token id adr_char
2N/A * type adr_u_int32
2N/A * value adr_u_int32
2N/A * mode adr_u_int32
2N/A */
2N/Aint
2N/Aacl_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 3 * sizeof (uint32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of ace token:
2N/A * ace token id adr_char
2N/A * id adr_u_int32
2N/A * access_mask adr_u_int32
2N/A * flags adr_u_short
2N/A * type adr_u_short
2N/A */
2N/Aint
2N/Aace_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 2 * sizeof (uint32_t) + 2 * sizeof (ushort_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of attribute token: (old pre SunOS 5.7 format)
2N/A * attribute token id adr_char
2N/A * mode adr_int32 (printed in octal)
2N/A * uid adr_int32
2N/A * gid adr_int32
2N/A * file system id adr_int32
2N/A * node id adr_int32
2N/A * device adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aattribute_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 6 * sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of attribute32 token:
2N/A * attribute token id adr_char
2N/A * mode adr_int32 (printed in octal)
2N/A * uid adr_int32
2N/A * gid adr_int32
2N/A * file system id adr_int32
2N/A * node id adr_int64
2N/A * device adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aattribute32_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += (5 * sizeof (int32_t)) + sizeof (int64_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of attribute64 token:
2N/A * attribute token id adr_char
2N/A * mode adr_int32 (printed in octal)
2N/A * uid adr_int32
2N/A * gid adr_int32
2N/A * file system id adr_int32
2N/A * node id adr_int64
2N/A * device adr_int64
2N/A *
2N/A */
2N/Aint
2N/Aattribute64_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += (4 * sizeof (int32_t)) + (2 * sizeof (int64_t));
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of command token:
2N/A * attribute token id adr_char
2N/A * argc adr_short
2N/A * argv len adr_short variable amount of argv len
2N/A * argv text argv len and text
2N/A * .
2N/A * .
2N/A * .
2N/A * envp count adr_short variable amount of envp len
2N/A * envp len adr_short and text
2N/A * envp text envp len
2N/A * .
2N/A * .
2N/A * .
2N/A *
2N/A */
2N/Aint
2N/Acmd_token(parse_context_t *ctx)
2N/A{
2N/A short cnt;
2N/A short i;
2N/A
2N/A adrm_short(&(ctx->adr), &cnt, 1);
2N/A
2N/A for (i = 0; i < cnt; i++)
2N/A skip_bytes(ctx);
2N/A
2N/A adrm_short(&(ctx->adr), &cnt, 1);
2N/A
2N/A for (i = 0; i < cnt; i++)
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of exit token:
2N/A * attribute token id adr_char
2N/A * return value adr_int32
2N/A * errno adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aexit_token(parse_context_t *ctx)
2N/A{
2N/A int32_t retval;
2N/A
2N/A adrm_int32(&(ctx->adr), &retval, 1);
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A ctx->out.sf_pass = (retval == 0) ? 1 : -1;
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of exec_args token:
2N/A * attribute token id adr_char
2N/A * count value adr_int32
2N/A * strings null terminated strings
2N/A *
2N/A */
2N/Aint
2N/Aexec_args_token(parse_context_t *ctx)
2N/A{
2N/A int count, i;
2N/A
2N/A adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
2N/A for (i = 1; i <= count; i++) {
2N/A skip_string(ctx);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of exec_env token:
2N/A * attribute token id adr_char
2N/A * count value adr_int32
2N/A * strings null terminated strings
2N/A *
2N/A */
2N/Aint
2N/Aexec_env_token(parse_context_t *ctx)
2N/A{
2N/A int count, i;
2N/A
2N/A adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
2N/A for (i = 1; i <= count; i++)
2N/A skip_string(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of liaison token:
2N/A */
2N/Aint
2N/Aliaison_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of path token:
2N/A * path adr_string
2N/A */
2N/Aint
2N/Apath_token(parse_context_t *ctx)
2N/A{
2N/A get_bytes_to_string(ctx, &(ctx->out.sf_pathlen), &(ctx->out.sf_path),
2N/A 0);
2N/A if (ctx->out.sf_path == NULL)
2N/A return (-1);
2N/A /*
2N/A * anchor the path because collapse_path needs it
2N/A */
2N/A if (*(ctx->out.sf_path) != '/') {
2N/A anchor_path(ctx->out.sf_path);
2N/A ctx->out.sf_pathlen++;
2N/A }
2N/A ctx->out.sf_pathlen = collapse_path(ctx->out.sf_path,
2N/A ctx->out.sf_pathlen);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * path attr token / AUT_XATPATH
2N/A *
2N/A * Format of path attr token:
2N/A * token id adr_char
2N/A * string count adr_int32
2N/A * strings adr_string
2N/A *
2N/A * the sequence of strings is converted to a single string with
2N/A * a blank separator replacing the EOS for all but the last
2N/A * string.
2N/A */
2N/Aint
2N/Apath_attr_token(parse_context_t *ctx)
2N/A{
2N/A int string_cnt, i;
2N/A size_t path_lens;
2N/A char *p;
2N/A
2N/A adrm_int32(&(ctx->adr), &string_cnt, 1);
2N/A
2N/A p = ctx->adr.adr_now;
2N/A for (i = 0; i < string_cnt; i++) {
2N/A while (*p++ != '\0') {
2N/A continue;
2N/A }
2N/A }
2N/A path_lens = p - ctx->adr.adr_now;
2N/A
2N/A if ((p = realloc(ctx->out.sf_atpath, path_lens)) == NULL) {
2N/A return (-1);
2N/A }
2N/A ctx->out.sf_atpath = p;
2N/A adrm_char(&(ctx->adr), ctx->out.sf_atpath, (int)path_lens);
2N/A ctx->out.sf_atpathlen = path_lens;
2N/A
2N/A /* fix up: replace each NUL except the last with ' ' */
2N/A
2N/A for (i = 0; i < (string_cnt-1); i++) {
2N/A while (*p++ != '\0') {
2N/A continue;
2N/A }
2N/A *(p - 1) = ' ';
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of System V IPC permission token:
2N/A * System V IPC permission token id adr_char
2N/A * uid adr_int32
2N/A * gid adr_int32
2N/A * cuid adr_int32
2N/A * cgid adr_int32
2N/A * mode adr_int32
2N/A * seq adr_int32
2N/A * key adr_int32
2N/A */
2N/Aint
2N/As5_IPC_perm_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += (7 * sizeof (int32_t));
2N/A return (0);
2N/A}
2N/A
2N/Astatic void
2N/Acommon_process(parse_context_t *ctx)
2N/A{
2N/A int32_t ruid, rgid, egid, pid;
2N/A uint32_t asid;
2N/A
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_pauid), 1);
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_peuid), 1);
2N/A adrm_int32(&(ctx->adr), &egid, 1);
2N/A adrm_int32(&(ctx->adr), &ruid, 1);
2N/A adrm_int32(&(ctx->adr), &rgid, 1);
2N/A adrm_int32(&(ctx->adr), &pid, 1);
2N/A adrm_u_int32(&(ctx->adr), &asid, 1);
2N/A}
2N/A
2N/A/*
2N/A * Format of process32 token:
2N/A * process token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid adr_int32*2
2N/A *
2N/A */
2N/Aint
2N/Aprocess32_token(parse_context_t *ctx)
2N/A{
2N/A int32_t port, machine;
2N/A
2N/A common_process(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &port, 1);
2N/A adrm_int32(&(ctx->adr), &machine, 1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of process32_ex token:
2N/A * process token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid
2N/A * port adr_int32
2N/A * type adr_int32
2N/A * ip address adr_u_char*type
2N/A *
2N/A */
2N/Aint
2N/Aprocess32_ex_token(parse_context_t *ctx)
2N/A{
2N/A int32_t port, type;
2N/A uchar_t addr[16];
2N/A
2N/A common_process(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &port, 1);
2N/A adrm_int32(&(ctx->adr), &type, 1);
2N/A adrm_u_char(&(ctx->adr), addr, type);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of process64 token:
2N/A * process token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid adr_int64+adr_int32
2N/A *
2N/A */
2N/Aint
2N/Aprocess64_token(parse_context_t *ctx)
2N/A{
2N/A int64_t port;
2N/A int32_t machine;
2N/A
2N/A common_process(ctx);
2N/A
2N/A adrm_int64(&(ctx->adr), &port, 1);
2N/A adrm_int32(&(ctx->adr), &machine, 1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of process64_ex token:
2N/A * process token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid
2N/A * port adr_int64
2N/A * type adr_int32
2N/A * ip address adr_u_char*type
2N/A *
2N/A */
2N/Aint
2N/Aprocess64_ex_token(parse_context_t *ctx)
2N/A{
2N/A int64_t port;
2N/A int32_t type;
2N/A uchar_t addr[16];
2N/A
2N/A common_process(ctx);
2N/A
2N/A adrm_int64(&(ctx->adr), &port, 1);
2N/A adrm_int32(&(ctx->adr), &type, 1);
2N/A adrm_u_char(&(ctx->adr), addr, type);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of System V IPC token:
2N/A * System V IPC token id adr_char
2N/A * System V IPC type adr_char
2N/A * object id adr_int32
2N/A *
2N/A */
2N/Aint
2N/As5_IPC_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (char);
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of socket token:
2N/A * socket_type adrm_short
2N/A * remote_port adrm_short
2N/A * remote_inaddr adrm_int32
2N/A *
2N/A */
2N/Aint
2N/Asocket_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += (2 * sizeof (short)) + sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of socket_ex token:
2N/A * socket_domain adrm_short
2N/A * socket_type adrm_short
2N/A * address_type adrm_short
2N/A * local_port adrm_short
2N/A * local_inaddr adrm_u_char*address_type
2N/A * remote_port adrm_short
2N/A * remote_inaddr adrm_u_char*address_type
2N/A *
2N/A */
2N/Aint
2N/Asocket_ex_token(parse_context_t *ctx)
2N/A{
2N/A short ip_size;
2N/A
2N/A ctx->adr.adr_now += (2 * sizeof (short));
2N/A adrm_short(&(ctx->adr), &ip_size, 1);
2N/A
2N/A ctx->adr.adr_now += sizeof (short) + (ip_size * sizeof (char)) +
2N/A sizeof (short) + (ip_size * sizeof (char));
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Acommon_subject(parse_context_t *ctx)
2N/A{
2N/A int32_t ruid, rgid, pid;
2N/A
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_auid), 1);
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_euid), 1);
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_egid), 1);
2N/A adrm_int32(&(ctx->adr), &ruid, 1);
2N/A adrm_int32(&(ctx->adr), &rgid, 1);
2N/A adrm_int32(&(ctx->adr), &pid, 1);
2N/A adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
2N/A}
2N/A
2N/A/*
2N/A * Format of subject32 token:
2N/A * subject token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid adr_int32*2
2N/A *
2N/A */
2N/Aint
2N/Asubject32_token(parse_context_t *ctx)
2N/A{
2N/A int32_t port; /* not used in output */
2N/A
2N/A common_subject(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &port, 1);
2N/A ctx->out.sf_tid.at_type = AU_IPv4;
2N/A adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 4);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of subject32_ex token:
2N/A * subject token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid
2N/A * port adr_int32
2N/A * type adr_int32
2N/A * ip address adr_u_char*type
2N/A *
2N/A */
2N/Aint
2N/Asubject32_ex_token(parse_context_t *ctx)
2N/A{
2N/A int32_t port; /* not used in output */
2N/A
2N/A common_subject(ctx);
2N/A
2N/A adrm_int32(&(ctx->adr), &port, 1);
2N/A adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
2N/A adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]),
2N/A ctx->out.sf_tid.at_type);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of subject64 token:
2N/A * subject token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid adr_int64+adr_int32
2N/A *
2N/A */
2N/Aint
2N/Asubject64_token(parse_context_t *ctx)
2N/A{
2N/A int64_t port;
2N/A
2N/A common_subject(ctx);
2N/A
2N/A adrm_int64(&(ctx->adr), &port, 1);
2N/A ctx->out.sf_tid.at_type = AU_IPv4;
2N/A adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]), 4);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of subject64_ex token:
2N/A * subject token id adr_char
2N/A * auid adr_int32
2N/A * euid adr_int32
2N/A * egid adr_int32
2N/A * ruid adr_int32
2N/A * rgid adr_int32
2N/A * pid adr_int32
2N/A * sid adr_int32
2N/A * termid
2N/A * port adr_int64
2N/A * type adr_int32
2N/A * ip address adr_u_char*type
2N/A *
2N/A */
2N/Aint
2N/Asubject64_ex_token(parse_context_t *ctx)
2N/A{
2N/A int64_t port;
2N/A
2N/A common_subject(ctx);
2N/A
2N/A adrm_int64(&(ctx->adr), &port, 1);
2N/A adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
2N/A adrm_u_char(&(ctx->adr), (uchar_t *)&(ctx->out.sf_tid.at_addr[0]),
2N/A ctx->out.sf_tid.at_type);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Aint
2N/Axatom_token(parse_context_t *ctx)
2N/A{
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/Aint
2N/Axselect_token(parse_context_t *ctx)
2N/A{
2N/A skip_bytes(ctx);
2N/A skip_bytes(ctx);
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * anchor a path name with a slash
2N/A * assume we have enough space
2N/A */
2N/Astatic void
2N/Aanchor_path(char *path)
2N/A{
2N/A
2N/A (void) memmove((void *)(path + 1), (void *)path, strlen(path) + 1);
2N/A *path = '/';
2N/A}
2N/A
2N/A
2N/A/*
2N/A * copy path to collapsed path.
2N/A * collapsed path does not contain:
2N/A * successive slashes
2N/A * instances of dot-slash
2N/A * instances of dot-dot-slash
2N/A * passed path must be anchored with a '/'
2N/A */
2N/Astatic size_t
2N/Acollapse_path(char *s, size_t ls)
2N/A{
2N/A int id; /* index of where we are in destination string */
2N/A int is; /* index of where we are in source string */
2N/A int slashseen; /* have we seen a slash */
2N/A
2N/A ls++; /* source length including '\0' */
2N/A
2N/A slashseen = 0;
2N/A for (is = 0, id = 0; is < ls; is++) {
2N/A if (s[is] == '\0') {
2N/A if (id > 1 && s[id-1] == '/') {
2N/A --id;
2N/A }
2N/A s[id++] = '\0';
2N/A break;
2N/A }
2N/A /* previous character was a / */
2N/A if (slashseen) {
2N/A if (s[is] == '/')
2N/A continue; /* another slash, ignore it */
2N/A } else if (s[is] == '/') {
2N/A /* we see a /, just copy it and try again */
2N/A slashseen = 1;
2N/A s[id++] = '/';
2N/A continue;
2N/A }
2N/A /* /./ seen */
2N/A if (s[is] == '.' && s[is+1] == '/') {
2N/A is += 1;
2N/A continue;
2N/A }
2N/A /* XXX/. seen */
2N/A if (s[is] == '.' && s[is+1] == '\0') {
2N/A if (id > 1)
2N/A id--;
2N/A continue;
2N/A }
2N/A /* XXX/.. seen */
2N/A if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '\0') {
2N/A is += 1;
2N/A if (id > 0)
2N/A id--;
2N/A while (id > 0 && s[--id] != '/')
2N/A ;
2N/A id++;
2N/A continue;
2N/A }
2N/A /* XXX/../ seen */
2N/A if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '/') {
2N/A is += 2;
2N/A if (id > 0)
2N/A id--;
2N/A while (id > 0 && s[--id] != '/')
2N/A ;
2N/A id++;
2N/A continue;
2N/A }
2N/A while (is < ls && (s[id++] = s[is++]) != '/')
2N/A ;
2N/A is--;
2N/A }
2N/A return ((size_t)id - 1);
2N/A}
2N/A
2N/A/*
2N/A * for tokens with sub-fields that include a length, this
2N/A * skips the sub-field.
2N/A */
2N/A
2N/Astatic void
2N/Askip_bytes(parse_context_t *ctx)
2N/A{
2N/A ushort_t c;
2N/A
2N/A adrm_u_short(&(ctx->adr), &c, 1);
2N/A ctx->adr.adr_now += c;
2N/A}
2N/A
2N/Astatic void
2N/Askip_string(parse_context_t *ctx)
2N/A{
2N/A char c;
2N/A
2N/A do {
2N/A adrm_char(&(ctx->adr), &c, 1);
2N/A } while (c != (char)0);
2N/A}
2N/A
2N/A/*
2N/A * add a byte to specified length so there can be a prefix of
2N/A * '/' added (if needed for paths). Another is added for '\0'
2N/A *
2N/A * if offset is zero, new data overwrites old, if any. Otherwise
2N/A * new data is appended to the end.
2N/A */
2N/Astatic void
2N/Aget_bytes_to_string(parse_context_t *ctx, size_t *l, char **p,
2N/A size_t offset)
2N/A{
2N/A ushort_t len;
2N/A char *bp;
2N/A
2N/A adrm_u_short(&(ctx->adr), &len, 1);
2N/A
2N/A len++; /* in case need to add '/' prefix */
2N/A *p = realloc(*p, 1 + (size_t)len + offset);
2N/A if (*p == NULL) {
2N/A perror("audit_sysudp.so");
2N/A return;
2N/A }
2N/A if (offset > 0)
2N/A offset--; /* overwrite end of string */
2N/A
2N/A *l = (size_t)len - 2 + offset;
2N/A
2N/A bp = *p + offset;
2N/A adrm_char(&(ctx->adr), bp, len - 1);
2N/A *(bp + len - 1) = '\0';
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of host token:
2N/A * host adr_uint32
2N/A */
2N/Aint
2N/Ahost_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of useofauth token:
2N/A * uauth token id adr_char
2N/A * uauth adr_string
2N/A *
2N/A */
2N/Aint
2N/Auseofauth_token(parse_context_t *ctx)
2N/A{
2N/A get_bytes_to_string(ctx, &(ctx->out.sf_uauthlen),
2N/A &(ctx->out.sf_uauth), 0);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of user token:
2N/A * user token id adr_char
2N/A * uid adr_uid
2N/A * username adr_string
2N/A *
2N/A */
2N/Aint
2N/Auser_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (uid_t);
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of zonename token:
2N/A * zonename token id adr_char
2N/A * zonename adr_string
2N/A *
2N/A */
2N/Aint
2N/Azonename_token(parse_context_t *ctx)
2N/A{
2N/A get_bytes_to_string(ctx,
2N/A &(ctx->out.sf_zonelen),
2N/A &(ctx->out.sf_zonename),
2N/A 0);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of fmri token:
2N/A * fmri token id adr_char
2N/A * fmri adr_string
2N/A */
2N/Aint
2N/Afmri_token(parse_context_t *ctx)
2N/A{
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Aint
2N/Axcolormap_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A
2N/Aint
2N/Axcursor_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A
2N/Aint
2N/Axfont_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A
2N/Aint
2N/Axgc_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A
2N/Aint
2N/Axpixmap_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A
2N/Aint
2N/Axwindow_token(parse_context_t *ctx)
2N/A{
2N/A return (xgeneric(ctx));
2N/A}
2N/A/*
2N/A * Format of xgeneric token:
2N/A * XID adr_int32
2N/A * creator UID adr_int32
2N/A *
2N/A * Includes: xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
2N/A */
2N/Astatic int
2N/Axgeneric(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 2 * sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A/*
2N/A * Format of xproperty token:
2N/A * XID adr_int32
2N/A * creator UID adr_int32
2N/A * atom string adr_string
2N/A */
2N/Aint
2N/Axproperty_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += 2 * sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A/*
2N/A * Format of xclient token:
2N/A * xclient id adr_int32
2N/A */
2N/Aint
2N/Axclient_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (int32_t);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * -----------------------------------------------------------------------
2N/A * privilege_token() : Process privilege token and display contents
2N/A *
2N/A * Format of privilege token:
2N/A * privilege token id adr_char
2N/A * privilege type adr_string
2N/A * privilege adr_string
2N/A * -----------------------------------------------------------------------
2N/A */
2N/A
2N/Aint
2N/Aprivilege_token(parse_context_t *ctx)
2N/A{
2N/A skip_bytes(ctx);
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Format of label token:
2N/A * label ID 1 byte
2N/A * compartment length 1 byte
2N/A * classification 2 bytes
2N/A * compartment words <compartment length> * 4 bytes
2N/A */
2N/Aint
2N/Alabel_token(parse_context_t *ctx)
2N/A{
2N/A char c;
2N/A
2N/A ctx->adr.adr_now += sizeof (char); /* label ID */
2N/A adrm_char(&(ctx->adr), &c, 1);
2N/A
2N/A ctx->adr.adr_now += sizeof (ushort_t); /* classification */
2N/A ctx->adr.adr_now += 4 * c; /* compartments */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Format of useofpriv token:
2N/A * priv_type adr_char
2N/A * priv_set_t adr_short
2N/A * priv_set adr_char*(sizeof (priv_set_t))
2N/A */
2N/Aint
2N/Auseofpriv_token(parse_context_t *ctx)
2N/A{
2N/A ctx->adr.adr_now += sizeof (char); /* success / fail */
2N/A skip_bytes(ctx);
2N/A
2N/A return (0);
2N/A}