systoken.c revision 7883e825152992a0f20c3f52f7c4bb902a56205c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Token processing for sysupd; each token function does one
* or more operations. All of them bump the buffer pointer
* to the next token; some of them extract one or more data
* from the token.
*/
#define DEBUG 0
#if DEBUG
#define DPRINT(x) {fprintf x; }
#else
#define DPRINT(x)
#endif
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <bsm/libbsm.h>
#include "toktable.h" /* ../praudit */
#include "sysplugin.h"
#include "systoken.h"
#include <audit_plugin.h>
#if DEBUG
static FILE *dbfp; /* debug file */
#endif
static void anchor_path(char *);
static size_t collapse_path(char *, size_t);
static void get_bytes_to_string(parse_context_t *, size_t *, char **,
size_t);
static void skip_bytes(parse_context_t *);
static void skip_string(parse_context_t *);
static int xgeneric(parse_context_t *);
/*
* Process a token in a record to (1) extract data of interest if any
* and (2) point to the next token.
*
* returns 0 if ok. + or - values are of debug value:
*
* returns -1 if the parsing of the token failed.
*
* returns +<previous id> if the token is not found. This value
* is used to help determine where in the record the problem
* occurred. The common failure case is that the parsing of
* token M is incorrect and the buffer pointer ends up pointing
* to garbage. The positive error value of M *may* be the id of
* the incorrectly parsed token.
*/
int
parse_token(parse_context_t *ctx)
{
char tokenid;
static char prev_tokenid = -1;
int rc;
#if DEBUG
static boolean_t first = 1;
if (first) {
dbfp = __auditd_debug_file_open();
first = 0;
}
#endif
adrm_char(&(ctx->adr), &tokenid, 1);
if ((tokenid > 0) && (tokentable[tokenid].func != NOFUNC)) {
rc = (*tokentable[tokenid].func)(ctx);
prev_tokenid = tokenid;
return (rc);
}
/* here if token id is not in table */
return (prev_tokenid);
}
/* There should not be any file tokens in the middle of a record */
/* ARGSUSED */
int
file_token(parse_context_t *ctx)
{
return (-1);
}
/* ARGSUSED */
int
file64_token(parse_context_t *ctx)
{
return (-1);
}
static void
common_header(parse_context_t *ctx)
{
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_reclen), 1);
ctx->adr.adr_now += sizeof (char); /* version number */
adrm_short(&(ctx->adr), &(ctx->out.sf_eventid), 1);
ctx->adr.adr_now += sizeof (short); /* modifier */
}
/*
* 32bit header
*/
int
header_token(parse_context_t *ctx)
{
common_header(ctx);
ctx->adr.adr_now += 2 * sizeof (int32_t); /* time */
return (0);
}
int
header32_ex_token(parse_context_t *ctx)
{
int32_t type;
common_header(ctx);
adrm_int32(&(ctx->adr), &type, 1); /* tid type */
ctx->adr.adr_now += type * sizeof (char); /* ip address */
ctx->adr.adr_now += 2 * sizeof (int32_t); /* time */
return (0);
}
int
header64_ex_token(parse_context_t *ctx)
{
int32_t type;
common_header(ctx);
adrm_int32(&(ctx->adr), &type, 1); /* tid type */
ctx->adr.adr_now += type * sizeof (char); /* ip address */
ctx->adr.adr_now += 2 * sizeof (int64_t); /* time */
return (0);
}
int
header64_token(parse_context_t *ctx)
{
common_header(ctx);
ctx->adr.adr_now += 2 * sizeof (int64_t); /* time */
return (0);
}
/*
* ======================================================
* The following token processing routines return
* 0: if parsed ok
* -1: can't parse and can't determine location of next token
* ======================================================
*/
int
trailer_token(parse_context_t *ctx)
{
short magic_number;
uint32_t bytes;
adrm_u_short(&(ctx->adr), (ushort_t *)&magic_number, 1);
if (magic_number != AUT_TRAILER_MAGIC)
return (-1);
adrm_u_int32(&(ctx->adr), &bytes, 1);
return (0);
}
/*
* Format of arbitrary data token:
* arbitrary data token id &(ctx->adr) char
* how to print adr_char
* basic unit adr_char
* unit count adr_char, specifying number of units of
* data items depends on basic unit
*
*/
int
arbitrary_data_token(parse_context_t *ctx)
{
char basic_unit, unit_count;
ctx->adr.adr_now += sizeof (char); /* how to print */
adrm_char(&(ctx->adr), &basic_unit, 1);
adrm_char(&(ctx->adr), &unit_count, 1);
switch (basic_unit) {
case AUR_CHAR: /* same as AUR_BYTE */
ctx->adr.adr_now += unit_count * sizeof (char);
break;
case AUR_SHORT:
ctx->adr.adr_now += unit_count * sizeof (short);
break;
case AUR_INT32: /* same as AUR_INT */
ctx->adr.adr_now += unit_count * sizeof (int32_t);
break;
case AUR_INT64:
ctx->adr.adr_now += unit_count * sizeof (int64_t);
break;
default:
return (-1);
break;
}
return (0);
}
/*
* Format of opaque token:
* opaque token id adr_char
* size adr_short
* data adr_char, size times
*
*/
int
opaque_token(parse_context_t *ctx)
{
skip_bytes(ctx);
return (0);
}
/*
* Format of return32 value token:
* return value token id adr_char
* error number adr_char
* return value adr_u_int32
*
*/
int
return_value32_token(parse_context_t *ctx)
{
char errnum;
adrm_char(&(ctx->adr), &errnum, 1); /* pass / fail */
ctx->adr.adr_now += sizeof (int32_t); /* error code */
ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
return (0);
}
/*
* Format of return64 value token:
* return value token id adr_char
* error number adr_char
* return value adr_u_int64
*
*/
int
return_value64_token(parse_context_t *ctx)
{
char errnum;
adrm_char(&(ctx->adr), &errnum, 1); /* pass / fail */
ctx->adr.adr_now += sizeof (int64_t); /* error code */
ctx->out.sf_pass = (errnum == 0) ? 1 : -1;
return (0);
}
/*
* Format of sequence token:
* sequence token id adr_char
* audit_count int32_t
*
*/
int
sequence_token(parse_context_t *ctx)
{
adrm_int32(&(ctx->adr), &(ctx->out.sf_sequence), 1);
return (0);
}
/*
* Format of text token:
* text token id adr_char
* text adr_string
*/
int
text_token(parse_context_t *ctx)
{
ushort_t len;
size_t separator_sz = 0;
char *bp; /* pointer to output string */
adrm_u_short(&(ctx->adr), &len, 1);
if (ctx->out.sf_textlen > 0)
separator_sz = sizeof (AU_TEXT_NAME) - 1;
DPRINT((dbfp, "text_token: start length=%d, add length=%d+%d\n",
ctx->out.sf_textlen, (size_t)len, separator_sz));
ctx->out.sf_text = realloc(ctx->out.sf_text,
ctx->out.sf_textlen + (size_t)len + separator_sz);
if (ctx->out.sf_text == NULL)
return (-1);
bp = ctx->out.sf_text;
if (ctx->out.sf_textlen != 0) { /* concatenation? */
bp += ctx->out.sf_textlen;
bp += strlcpy(bp, AU_TEXT_NAME, separator_sz + 1);
ctx->out.sf_textlen += separator_sz;
DPRINT((dbfp, "text_token: l is %d\n%s\n", ctx->out.sf_textlen,
ctx->out.sf_text));
}
adrm_char(&(ctx->adr), bp, len);
len--; /* includes EOS */
*(bp + len) = '\0';
ctx->out.sf_textlen += len;
DPRINT((dbfp, "text_token: l=%d\n%s\n", ctx->out.sf_textlen,
ctx->out.sf_text));
return (0);
}
/*
* Format of tid token:
* ip token id adr_char
* terminal type adr_char
* terminal type = AU_IPADR:
* remote port: ushort
* local port: ushort
* IP type: int32 -- AU_IPv4 or AU_IPv6
* address: int32 if IPv4, else 4 * int32
*/
int
tid_token(parse_context_t *ctx)
{
uchar_t type;
int32_t ip_length;
adrm_char(&(ctx->adr), (char *)&type, 1);
switch (type) {
default:
return (-1); /* other than IP type is not implemented */
case AU_IPADR:
ctx->adr.adr_now += 2 * sizeof (ushort_t);
adrm_int32(&(ctx->adr), &ip_length, 1);
ctx->adr.adr_now += ip_length;
break;
}
return (0);
}
/*
* Format of ip_addr token:
* ip token id adr_char
* address adr_int32
*
*/
int
ip_addr_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (int32_t);
return (0);
}
/*
* Format of ip_addr_ex token:
* ip token id adr_char
* ip type adr_int32
* address 4*adr_int32
*
*/
int
ip_addr_ex_token(parse_context_t *ctx)
{
ctx->adr.adr_now += 5 * sizeof (int32_t);
return (0);
}
/*
* Format of ip token:
* ip header token id adr_char
* version adr_char
* type of service adr_char
* length adr_short
* id adr_u_short
* offset adr_u_short
* ttl adr_char
* protocol adr_char
* checksum adr_u_short
* source address adr_int32
* destination address adr_int32
*
*/
int
ip_token(parse_context_t *ctx)
{
ctx->adr.adr_now += (2 * sizeof (char)) +
(3 * sizeof (short)) +
(2 * sizeof (char)) +
sizeof (short) +
(2 * sizeof (int32_t));
return (0);
}
/*
* Format of iport token:
* ip port address token id adr_char
* port address adr_short
*
*/
int
iport_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (short);
return (0);
}
/*
* Format of groups token:
* group token id adr_char
* group list adr_int32, 16 times
*
*/
int
group_token(parse_context_t *ctx)
{
ctx->adr.adr_now += 16 * sizeof (int32_t);
return (0);
}
/*
* Format of newgroups token:
* group token id adr_char
* number of groups adr_short
* group list adr_int32, "number" times
*
*/
int
newgroup_token(parse_context_t *ctx)
{
short int number;
adrm_short(&(ctx->adr), &number, 1);
ctx->adr.adr_now += number * sizeof (int32_t);
return (0);
}
/*
* Format of argument32 token:
* argument token id adr_char
* argument number adr_char
* argument value adr_int32
* argument description adr_string
*
*/
int
argument32_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (char) + sizeof (int32_t);
skip_bytes(ctx);
return (0);
}
/*
* Format of argument64 token:
* argument token id adr_char
* argument number adr_char
* argument value adr_int64
* argument description adr_string
*
*/
int
argument64_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (char) + sizeof (int64_t);
skip_bytes(ctx);
return (0);
}
int
acl_token(parse_context_t *ctx)
{
ctx->adr.adr_now += 3 * sizeof (int32_t);
return (0);
}
/*
* Format of attribute token: (old pre SunOS 5.7 format)
* attribute token id adr_char
* mode adr_int32 (printed in octal)
* uid adr_int32
* gid adr_int32
* file system id adr_int32
* node id adr_int32
* device adr_int32
*
*/
int
attribute_token(parse_context_t *ctx)
{
ctx->adr.adr_now += 6 * sizeof (int32_t);
return (0);
}
/*
* Format of attribute32 token:
* attribute token id adr_char
* mode adr_int32 (printed in octal)
* uid adr_int32
* gid adr_int32
* file system id adr_int32
* node id adr_int64
* device adr_int32
*
*/
int
attribute32_token(parse_context_t *ctx)
{
ctx->adr.adr_now += (5 * sizeof (int32_t)) + sizeof (int64_t);
return (0);
}
/*
* Format of attribute64 token:
* attribute token id adr_char
* mode adr_int32 (printed in octal)
* uid adr_int32
* gid adr_int32
* file system id adr_int32
* node id adr_int64
* device adr_int64
*
*/
int
attribute64_token(parse_context_t *ctx)
{
ctx->adr.adr_now += (4 * sizeof (int32_t)) + (2 * sizeof (int64_t));
return (0);
}
/*
* Format of command token:
* attribute token id adr_char
* argc adr_short
* argv len adr_short variable amount of argv len
* argv text argv len and text
* .
* .
* .
* envp count adr_short variable amount of envp len
* envp len adr_short and text
* envp text envp len
* .
* .
* .
*
*/
int
cmd_token(parse_context_t *ctx)
{
short cnt;
short i;
adrm_short(&(ctx->adr), &cnt, 1);
for (i = 0; i < cnt; i++)
skip_bytes(ctx);
adrm_short(&(ctx->adr), &cnt, 1);
for (i = 0; i < cnt; i++)
skip_bytes(ctx);
return (0);
}
/*
* Format of exit token:
* attribute token id adr_char
* return value adr_int32
* errno adr_int32
*
*/
int
exit_token(parse_context_t *ctx)
{
int32_t retval;
adrm_int32(&(ctx->adr), &retval, 1);
ctx->adr.adr_now += sizeof (int32_t);
ctx->out.sf_pass = (retval == 0) ? 1 : -1;
return (0);
}
/*
* Format of exec_args token:
* attribute token id adr_char
* count value adr_int32
* strings null terminated strings
*
*/
int
exec_args_token(parse_context_t *ctx)
{
int count, i;
adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
for (i = 1; i <= count; i++) {
skip_string(ctx);
}
return (0);
}
/*
* Format of exec_env token:
* attribute token id adr_char
* count value adr_int32
* strings null terminated strings
*
*/
int
exec_env_token(parse_context_t *ctx)
{
int count, i;
adrm_int32(&(ctx->adr), (int32_t *)&count, 1);
for (i = 1; i <= count; i++)
skip_string(ctx);
return (0);
}
/*
* Format of liaison token:
*/
int
liaison_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (int32_t);
return (0);
}
/*
* Format of path token:
* path adr_string
*/
int
path_token(parse_context_t *ctx)
{
get_bytes_to_string(ctx, &(ctx->out.sf_pathlen), &(ctx->out.sf_path),
0);
if (ctx->out.sf_path == NULL)
return (-1);
/*
* anchor the path because collapse_path needs it
*/
if (*(ctx->out.sf_path) != '/') {
anchor_path(ctx->out.sf_path);
ctx->out.sf_pathlen++;
}
ctx->out.sf_pathlen = collapse_path(ctx->out.sf_path,
ctx->out.sf_pathlen);
return (0);
}
/*
* path attr token / AUT_XATPATH
*
* Format of path attr token:
* token id adr_char
* string count adr_int32
* strings adr_string
*
* the sequence of strings is converted to a single string with
* a blank separator replacing the EOS for all but the last
* string.
*/
int
path_attr_token(parse_context_t *ctx)
{
int count, i;
int last_len;
size_t offset;
char *p;
adrm_int32(&(ctx->adr), &count, 1);
offset = ctx->out.sf_atpathlen;
p = ctx->adr.adr_now;
for (i = 0; i <= count; i++) {
last_len = strlen(p);
ctx->out.sf_atpathlen += last_len + 1;
p += last_len + 1;
}
ctx->out.sf_atpath = realloc(ctx->out.sf_atpath, ctx->out.sf_atpathlen);
ctx->out.sf_atpath += offset;
p = ctx->out.sf_atpath; /* save for fix up, below */
(void) memcpy(ctx->out.sf_atpath, ctx->adr.adr_now,
ctx->out.sf_atpathlen - offset);
ctx->out.sf_atpathlen--;
/* fix up: replace each eos except the last with ' ' */
for (i = 0; i < count; i++) {
while (*p++ != '\0');
*(p - 1) = ' ';
}
return (0);
}
/*
* Format of System V IPC permission token:
* System V IPC permission token id adr_char
* uid adr_int32
* gid adr_int32
* cuid adr_int32
* cgid adr_int32
* mode adr_int32
* seq adr_int32
* key adr_int32
* label adr_opaque, sizeof (bslabel_t)
* bytes
*/
int
s5_IPC_perm_token(parse_context_t *ctx)
{
ctx->adr.adr_now += (7 * sizeof (int32_t));
#if TSOL
ctx->adr.adr_now += sizeof (bslabel_t);
#endif
return (0);
}
static void
common_process(parse_context_t *ctx)
{
int32_t ruid, rgid, egid, pid;
uint32_t asid;
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_pauid), 1);
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_peuid), 1);
adrm_int32(&(ctx->adr), &egid, 1);
adrm_int32(&(ctx->adr), &ruid, 1);
adrm_int32(&(ctx->adr), &rgid, 1);
adrm_int32(&(ctx->adr), &pid, 1);
adrm_u_int32(&(ctx->adr), &asid, 1);
}
/*
* Format of process32 token:
* process token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int32*2
*
*/
int
process32_token(parse_context_t *ctx)
{
int32_t port, machine;
common_process(ctx);
adrm_int32(&(ctx->adr), &port, 1);
adrm_int32(&(ctx->adr), &machine, 1);
return (0);
}
/*
* Format of process32_ex token:
* process token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int32*6
*
*/
int
process32_ex_token(parse_context_t *ctx)
{
int32_t port, type, addr[4];
common_process(ctx);
adrm_int32(&(ctx->adr), &port, 1);
adrm_int32(&(ctx->adr), &type, 1);
adrm_int32(&(ctx->adr), &addr[0], 4);
return (0);
}
/*
* Format of process64 token:
* process token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int64+adr_int32
*
*/
int
process64_token(parse_context_t *ctx)
{
int64_t port;
int32_t machine;
common_process(ctx);
adrm_int64(&(ctx->adr), &port, 1);
adrm_int32(&(ctx->adr), &machine, 1);
return (0);
}
/*
* Format of process64 token:
* process token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int64+5*adr_int32
*
*/
int
process64_ex_token(parse_context_t *ctx)
{
int64_t port;
int32_t type, addr[4];
common_process(ctx);
adrm_int64(&(ctx->adr), &port, 1);
adrm_int32(&(ctx->adr), &type, 1);
adrm_int32(&(ctx->adr), &addr[0], 4);
return (0);
}
/*
* Format of System V IPC token:
* System V IPC token id adr_char
* System V IPC type adr_char
* object id adr_int32
*
*/
int
s5_IPC_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (char);
ctx->adr.adr_now += sizeof (int32_t);
return (0);
}
/*
* Format of socket token:
* socket_type adrm_short
* remote_port adrm_short
* remote_inaddr adrm_int32
*
*/
int
socket_token(parse_context_t *ctx)
{
ctx->adr.adr_now += (2 * sizeof (short)) + sizeof (int32_t);
return (0);
}
/*
* Format of socket token:
*
*/
int
socket_ex_token(parse_context_t *ctx)
{
short ip_size;
ctx->adr.adr_now += (2 * sizeof (short));
adrm_short(&(ctx->adr), &ip_size, 1);
ctx->adr.adr_now += sizeof (short) +
(ip_size * sizeof (char)) +
sizeof (short) +
(ip_size * sizeof (char));
return (0);
}
static void
common_subject(parse_context_t *ctx)
{
int32_t ruid, rgid, pid;
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_auid), 1);
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_euid), 1);
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_egid), 1);
adrm_int32(&(ctx->adr), &ruid, 1);
adrm_int32(&(ctx->adr), &rgid, 1);
adrm_int32(&(ctx->adr), &pid, 1);
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
}
/*
* Format of subject32 token:
* subject token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int32*2
*
*/
int
subject32_token(parse_context_t *ctx)
{
int32_t port; /* not used in output */
common_subject(ctx);
adrm_int32(&(ctx->adr), &port, 1);
ctx->out.sf_tid.at_type = AU_IPv4;
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 1);
return (0);
}
/*
* Format of subject32_ex token:
* subject token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid_addr adr_int32*6
*
*/
int
subject32_ex_token(parse_context_t *ctx)
{
int32_t port; /* not used in output */
common_subject(ctx);
adrm_int32(&(ctx->adr), &port, 1);
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 4);
return (0);
}
/*
* Format of subject64 token:
* subject token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int64+adr_int32
*
*/
int
subject64_token(parse_context_t *ctx)
{
int64_t port;
common_subject(ctx);
adrm_int64(&(ctx->adr), &port, 1);
ctx->out.sf_tid.at_type = AU_IPv4;
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 1);
return (0);
}
/*
* Format of subject64 token:
* subject token id adr_char
* auid adr_int32
* euid adr_int32
* egid adr_int32
* ruid adr_int32
* rgid adr_int32
* pid adr_int32
* sid adr_int32
* termid adr_int64+5*adr_int32
*
*/
int
subject64_ex_token(parse_context_t *ctx)
{
int64_t port;
common_subject(ctx);
adrm_u_int32(&(ctx->adr), (uint32_t *)&(ctx->out.sf_asid), 1);
adrm_int64(&(ctx->adr), &port, 1);
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_type), 1);
adrm_u_int32(&(ctx->adr), &(ctx->out.sf_tid.at_addr[0]), 4);
return (0);
}
int
xatom_token(parse_context_t *ctx)
{
skip_bytes(ctx);
return (0);
}
int
xselect_token(parse_context_t *ctx)
{
skip_bytes(ctx);
skip_bytes(ctx);
skip_bytes(ctx);
return (0);
}
/*
* anchor a path name with a slash
* assume we have enough space
*/
static void
anchor_path(char *path)
{
(void) memmove((void *)(path + 1), (void *)path, strlen(path) + 1);
*path = '/';
}
/*
* copy path to collapsed path.
* collapsed path does not contain:
* successive slashes
* instances of dot-slash
* instances of dot-dot-slash
* passed path must be anchored with a '/'
*/
static size_t
collapse_path(char *s, size_t ls)
{
int id; /* index of where we are in destination string */
int is; /* index of where we are in source string */
int slashseen; /* have we seen a slash */
ls++; /* source length including '\0' */
slashseen = 0;
for (is = 0, id = 0; is < ls; is++) {
if (s[is] == '\0') {
if (id > 1 && s[id-1] == '/') {
--id;
}
s[id++] = '\0';
break;
}
/* previous character was a / */
if (slashseen) {
if (s[is] == '/')
continue; /* another slash, ignore it */
} else if (s[is] == '/') {
/* we see a /, just copy it and try again */
slashseen = 1;
s[id++] = '/';
continue;
}
/* /./ seen */
if (s[is] == '.' && s[is+1] == '/') {
is += 1;
continue;
}
/* XXX/. seen */
if (s[is] == '.' && s[is+1] == '\0') {
if (id > 1)
id--;
continue;
}
/* XXX/.. seen */
if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '\0') {
is += 1;
if (id > 0)
id--;
while (id > 0 && s[--id] != '/');
id++;
continue;
}
/* XXX/../ seen */
if (s[is] == '.' && s[is+1] == '.' && s[is+2] == '/') {
is += 2;
if (id > 0)
id--;
while (id > 0 && s[--id] != '/');
id++;
continue;
}
while (is < ls && (s[id++] = s[is++]) != '/');
is--;
}
return ((size_t)id - 1);
}
/*
* for tokens with sub-fields that include a length, this
* skips the sub-field.
*/
static void
skip_bytes(parse_context_t *ctx)
{
ushort_t c;
adrm_u_short(&(ctx->adr), &c, 1);
ctx->adr.adr_now += c;
}
static void
skip_string(parse_context_t *ctx)
{
char c;
do {
adrm_char(&(ctx->adr), &c, 1);
} while (c != (char)0);
}
/*
* add a byte to specified length so there can be a prefix of
* '/' added (if needed for paths). Another is added for '\0'
*
* if offset is zero, new data overwrites old, if any. Otherwise
* new data is appended to the end.
*/
static void
get_bytes_to_string(parse_context_t *ctx, size_t *l, char **p,
size_t offset)
{
ushort_t len;
char *bp;
adrm_u_short(&(ctx->adr), &len, 1);
len++; /* in case need to add '/' prefix */
*p = realloc(*p, 1 + (size_t)len + offset);
if (*p == NULL) {
perror("audit_sysudp.so");
return;
}
if (offset > 0)
offset--; /* overwrite end of string */
*l = (size_t)len - 2 + offset;
bp = *p + offset;
adrm_char(&(ctx->adr), bp, len - 1);
*(bp + len - 1) = '\0';
}
/*
* Format of host token:
* host adr_uint32
*/
int
host_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (int32_t);
return (0);
}
/*
* Format of useofauth token:
* uauth token id adr_char
* uauth adr_string
*
*/
int
useofauth_token(parse_context_t *ctx)
{
get_bytes_to_string(ctx, &(ctx->out.sf_uauthlen),
&(ctx->out.sf_uauth), 0);
return (0);
}
/*
* Format of zonename token:
* zonename token id adr_char
* zonename adr_string
*
*/
int
zonename_token(parse_context_t *ctx)
{
get_bytes_to_string(ctx,
&(ctx->out.sf_zonelen),
&(ctx->out.sf_zonename),
0);
return (0);
}
int
xcolormap_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
int
xcursor_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
int
xfont_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
int
xgc_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
int
xpixmap_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
int
xwindow_token(parse_context_t *ctx)
{
return (xgeneric(ctx));
}
/*
* Format of xgeneric token:
* XID adr_int32
* creator UID adr_int32
*
* Includes: xcolormap, xcursor, xfont, xgc, xpixmap, and xwindow
*/
static int
xgeneric(parse_context_t *ctx)
{
ctx->adr.adr_now += 2 * sizeof (int32_t);
return (0);
}
/*
* Format of xproperty token:
* XID adr_int32
* creator UID adr_int32
* atom string adr_string
*/
int
xproperty_token(parse_context_t *ctx)
{
ctx->adr.adr_now += 2 * sizeof (int32_t);
return (0);
}
/*
* Format of xclient token:
* xclient id adr_int32
*/
int
xclient_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (int32_t);
return (0);
}
/*
* Format of clearance token:
* clearance adr_char*(sizeof (bclear_t))
*
* ifdef TSOL because of bclear_t
*/
#ifndef TSOL
/* ARGSUSED */
#endif /* !TSOL */
int
clearance_token(parse_context_t *ctx)
{
#ifdef TSOL
ctx->adr.adr_now += sizeof (bclear_t);
return (0);
#else /* !TSOL */
return (-1);
#endif /* TSOL */
}
/*
* Format of ilabel token:
* ilabel adr_char*(sizeof (bilabel_t))
*/
#ifndef TSOL
/* ARGSUSED */
#endif /* !TSOL */
int
ilabel_token(parse_context_t *ctx)
{
#ifdef TSOL
ctx->adr.adr_now += sizeof (bilabel_t);
return (0);
#else /* !TSOL */
return (-1);
#endif /* TSOL */
}
/*
* -----------------------------------------------------------------------
* privilege_token() : Process privilege token and display contents
*
* Format of privilege token:
* privilege token id adr_char
* privilege type adr_string
* privilege adr_string
* -----------------------------------------------------------------------
*/
int
privilege_token(parse_context_t *ctx)
{
skip_bytes(ctx);
skip_bytes(ctx);
return (0);
}
/*
* Format of slabel token:
* slabel adr_char*(sizeof (bslabel_t))
*/
#ifndef TSOL
/* ARGSUSED */
#endif /* !TSOL */
int
slabel_token(parse_context_t *ctx)
{
#ifdef TSOL
ctx->adr.adr_now += sizeof (bslabel_t);
return (0);
#else /* !TSOL */
return (-1);
#endif /* TSOL */
}
/*
* Format of useofpriv token:
* priv_type adr_char
* priv_set_t adr_short
* priv_set adr_char*(sizeof (priv_set_t))
*/
int
useofpriv_token(parse_context_t *ctx)
{
ctx->adr.adr_now += sizeof (char); /* success / fail */
skip_bytes(ctx);
return (0);
}