| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (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 2006 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 <sys/tsol/label.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); |
| } |
| |
| /* |
| * ----------------------------------------------------------------------- |
| * 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: |
| * label ID 1 byte |
| * compartment length 1 byte |
| * classification 2 bytes |
| * compartment words <compartment length> * 4 bytes |
| */ |
| int |
| slabel_token(parse_context_t *ctx) |
| { |
| char c; |
| |
| ctx->adr.adr_now += sizeof (char); /* label ID */ |
| adrm_char(&(ctx->adr), &c, 1); |
| |
| ctx->adr.adr_now += sizeof (ushort_t); /* classification */ |
| ctx->adr.adr_now += 4 * c; /* compartments */ |
| |
| return (0); |
| } |
| |
| /* |
| * 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); |
| } |