diff options
Diffstat (limited to 'framework/src/audit/src/ausearch-parse.c')
-rw-r--r-- | framework/src/audit/src/ausearch-parse.c | 2310 |
1 files changed, 2310 insertions, 0 deletions
diff --git a/framework/src/audit/src/ausearch-parse.c b/framework/src/audit/src/ausearch-parse.c new file mode 100644 index 00000000..1fb1c151 --- /dev/null +++ b/framework/src/audit/src/ausearch-parse.c @@ -0,0 +1,2310 @@ +/* +* ausearch-parse.c - Extract interesting fields and check for match +* Copyright (c) 2005-08,2011,2013-14 Red Hat Inc., Durham, North Carolina. +* Copyright (c) 2011 IBM Corp. +* All Rights Reserved. +* +* This software may be freely redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free +* Software Foundation; either version 2, or (at your option) any +* later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to the +* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Authors: +* Steve Grubb <sgrubb@redhat.com> +* Marcelo Henrique Cerri <mhcerri@br.ibm.com> +*/ + +#include "config.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netdb.h> +#include <limits.h> /* PATH_MAX */ +#include <ctype.h> +#include "libaudit.h" +#include "ausearch-options.h" +#include "ausearch-lookup.h" +#include "ausearch-parse.h" + +#define NAME_OFFSET 36 +static const char key_sep[2] = { AUDIT_KEY_SEPARATOR, 0 }; + +static int parse_syscall(lnode *n, search_items *s); +static int parse_dir(const lnode *n, search_items *s); +static int common_path_parser(search_items *s, char *path); +static int avc_parse_path(const lnode *n, search_items *s); +static int parse_path(const lnode *n, search_items *s); +static int parse_user(const lnode *n, search_items *s); +static int parse_obj(const lnode *n, search_items *s); +static int parse_login(const lnode *n, search_items *s); +static int parse_daemon1(const lnode *n, search_items *s); +static int parse_daemon2(const lnode *n, search_items *s); +static int parse_sockaddr(const lnode *n, search_items *s); +static int parse_avc(const lnode *n, search_items *s); +static int parse_integrity(const lnode *n, search_items *s); +static int parse_kernel_anom(const lnode *n, search_items *s); +static int parse_simple_message(const lnode *n, search_items *s); +static int parse_tty(const lnode *n, search_items *s); +static int parse_pkt(const lnode *n, search_items *s); + + +static int audit_avc_init(search_items *s) +{ + if (s->avc == NULL) { + //create + s->avc = malloc(sizeof(alist)); + if (s->avc == NULL) + return -1; + alist_create(s->avc); + } + return 0; +} + +/* + * This function will take the list and extract the searchable fields from it. + * It returns 0 on success and 1 on failure. + */ +int extract_search_items(llist *l) +{ + int ret = 0; + lnode *n; + search_items *s = &l->s; + list_first(l); + n = list_get_cur(l); + if (n) { + do { + switch (n->type) { + case AUDIT_SYSCALL: + ret = parse_syscall(n, s); + break; + case AUDIT_CWD: + ret = parse_dir(n, s); + break; + case AUDIT_AVC_PATH: + ret = avc_parse_path(n, s); + break; + case AUDIT_PATH: + ret = parse_path(n, s); + break; + case AUDIT_USER: + case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: + case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: + ret = parse_user(n, s); + break; + case AUDIT_SOCKADDR: + ret = parse_sockaddr(n, s); + break; + case AUDIT_LOGIN: + ret = parse_login(n, s); + break; + case AUDIT_IPC: + case AUDIT_OBJ_PID: + ret = parse_obj(n, s); + break; + case AUDIT_DAEMON_START: + case AUDIT_DAEMON_END: + case AUDIT_DAEMON_ABORT: + case AUDIT_DAEMON_CONFIG: + case AUDIT_DAEMON_ROTATE: + case AUDIT_DAEMON_RESUME: + ret = parse_daemon1(n, s); + break; + case AUDIT_DAEMON_ACCEPT: + case AUDIT_DAEMON_CLOSE: + ret = parse_daemon2(n, s); + break; + case AUDIT_CONFIG_CHANGE: + ret = parse_simple_message(n, s); + // We use AVC parser because it just looks for + // the one field. We don't care about return + // code since older events don't have path= + avc_parse_path(n, s); + break; + case AUDIT_AVC: + ret = parse_avc(n, s); + break; + case AUDIT_NETFILTER_PKT: + ret = parse_pkt(n, s); + break; + case AUDIT_SECCOMP: + case + AUDIT_FIRST_KERN_ANOM_MSG...AUDIT_LAST_KERN_ANOM_MSG: + ret = parse_kernel_anom(n, s); + break; + case AUDIT_MAC_POLICY_LOAD...AUDIT_MAC_UNLBL_STCDEL: + ret = parse_simple_message(n, s); + break; + case AUDIT_INTEGRITY_DATA...AUDIT_INTEGRITY_RULE: + ret = parse_integrity(n, s); + break; + case AUDIT_KERNEL: + case AUDIT_SELINUX_ERR: + case AUDIT_EXECVE: + case AUDIT_IPC_SET_PERM: + case AUDIT_MQ_OPEN: + case AUDIT_MQ_SENDRECV: + case AUDIT_MQ_NOTIFY: + case AUDIT_MQ_GETSETATTR: + case AUDIT_FD_PAIR: + case AUDIT_BPRM_FCAPS: + case AUDIT_CAPSET: + case AUDIT_MMAP: + case AUDIT_NETFILTER_CFG: + // Nothing to parse + break; + case AUDIT_TTY: + ret = parse_tty(n, s); + break; + default: + if (event_debug) + fprintf(stderr, + "Unparsed type:%d\n - skipped", + n->type); + break; + } + if (event_debug && ret) + fprintf(stderr, + "Malformed event skipped, rc=%d. %s\n", + ret, n->message); + } while ((n=list_next(l)) && ret == 0); + } + return ret; +} + +static int parse_syscall(lnode *n, search_items *s) +{ + char *ptr, *str, *term; + extern int event_machine; + + term = n->message; + if (report_format > RPT_DEFAULT || event_machine != -1) { + // get arch + str = strstr(term, "arch="); + if (str == NULL) + return 1; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 2; + *term = 0; + errno = 0; + s->arch = (int)strtoul(ptr, NULL, 16); + if (errno) + return 3; + *term = ' '; + } + // get syscall + str = strstr(term, "syscall="); + if (str == NULL) + return 4; + ptr = str + 8; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + *term = 0; + errno = 0; + s->syscall = (int)strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = ' '; + // get success + if (event_success != S_UNSET) { + str = strstr(term, "success="); + if (str) { // exit_group does not set success !?! + ptr = str + 8; + term = strchr(ptr, ' '); + if (term == NULL) + return 7; + *term = 0; + if (strcmp(ptr, "yes") == 0) + s->success = S_SUCCESS; + else + s->success = S_FAILED; + *term = ' '; + } + } + // get exit + if (event_exit_is_set) { + str = strstr(term, "exit="); + if (str == NULL) + return 8; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 9; + *term = 0; + errno = 0; + s->exit = strtoll(ptr, NULL, 0); + if (errno) + return 10; + s->exit_is_set = 1; + *term = ' '; + } + // get a0 + str = strstr(term, "a0="); + if (str == NULL) + return 11; + ptr = str + 3; + term = strchr(ptr, ' '); + if (term == NULL) + return 12; + *term = 0; + errno = 0; + // 64 bit dump on 32 bit machine looks bad here - need long long + n->a0 = strtoull(ptr, NULL, 16); // Hex + if (errno) + return 13; + *term = ' '; + // get a1 + str = strstr(term, "a1="); + if (str == NULL) + return 11; + ptr = str + 3; + term = strchr(ptr, ' '); + if (term == NULL) + return 12; + *term = 0; + errno = 0; + // 64 bit dump on 32 bit machine looks bad here - need long long + n->a1 = strtoull(ptr, NULL, 16); // Hex + if (errno) + return 13; + *term = ' '; + // ppid + if (event_ppid != -1) { + str = strstr(term, "ppid="); + if (str != NULL) { // ppid is an optional field + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 14; + *term = 0; + errno = 0; + s->ppid = strtoul(ptr, NULL, 10); + if (errno) + return 15; + *term = ' '; + } + } + // pid + if (event_pid != -1) { + str = strstr(term, " pid="); + if (str == NULL) + return 16; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 17; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 18; + *term = ' '; + } + // optionally get loginuid + if (event_loginuid != -2) { + str = strstr(term, "auid="); + if (str == NULL) { + str = strstr(term, "loginuid="); + if (str == NULL) + return 19; + ptr = str + 9; + } else + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 20; + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 21; + *term = ' '; + } + // optionally get uid + if (event_uid != -1) { + str = strstr(term, "uid="); + if (str == NULL) + return 22; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 23; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 24; + *term = ' '; + } + + // optionally get gid + if (event_gid != -1) { + str = strstr(term, "gid="); + if (str == NULL) + return 25; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 26; + *term = 0; + errno = 0; + s->gid = strtoul(ptr, NULL, 10); + if (errno) + return 27; + *term = ' '; + } + + // euid + if (event_euid != -1) { + str = strstr(term, "euid="); + if (str == NULL) + return 28; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 29; + *term = 0; + errno = 0; + s->euid = strtoul(ptr, NULL, 10); + if (errno) + return 30; + *term = ' '; + } + + // egid + if (event_egid != -1) { + str = strstr(term, "egid="); + if (str == NULL) + return 31; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 32; + *term = 0; + errno = 0; + s->egid = strtoul(ptr, NULL, 10); + if (errno) + return 33; + *term = ' '; + } + + if (event_terminal) { + // dont do this search unless needed + str = strstr(term, "tty="); + if (str) { + str += 4; + term = strchr(str, ' '); + if (term == NULL) + return 34; + *term = 0; + s->terminal = strdup(str); + *term = ' '; + } + } + // ses + if (event_session_id != -2 ) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 35; + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 36; + *term = ' '; + } + } + if (event_comm) { + // dont do this search unless needed + str = strstr(term, "comm="); + if (str) { + /* Make the syscall one override */ + if (s->comm) + free(s->comm); + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 37; + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else + s->comm = unescape(str); + } else + return 38; + } + if (event_exe) { + // dont do this search unless needed + str = strstr(n->message, "exe="); + if (str) { + str += 4; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 39; + *term = 0; + s->exe = strdup(str); + *term = '"'; + } else + s->exe = unescape(str); + } else + return 40; + } + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str != NULL) { + str += 5; + term = strchr(str, ' '); + if (term == NULL) + return 41; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 42; + } + } + if (event_key) { + str = strstr(term, "key="); + if (str) { + if (!s->key) { + //create + s->key = malloc(sizeof(slist)); + if (s->key == NULL) + return 43; + slist_create(s->key); + } + str += 4; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 44; + *term = 0; + if (s->key) { + // append + snode sn; + sn.str = strdup(str); + sn.key = NULL; + sn.hits = 1; + slist_append(s->key, &sn); + } + *term = '"'; + } else { + if (s->key) { + char *saved; + char *keyptr = unescape(str); + char *kptr = strtok_r(keyptr, + key_sep, &saved); + while (kptr) { + snode sn; + // append + sn.str = strdup(kptr); + sn.key = NULL; + sn.hits = 1; + slist_append(s->key, &sn); + kptr = strtok_r(NULL, + key_sep, &saved); + } + free(keyptr); + + } + } + } + } + return 0; +} + +static int parse_dir(const lnode *n, search_items *s) +{ + char *str, *term; + + if (event_filename) { + // dont do this search unless needed + str = strstr(n->message+NAME_OFFSET, " cwd="); + if (str) { + str += 5; + if (*str == '"') { + /* string is normal */ + str++; + term = strchr(str, '"'); + if (term == NULL) + return 1; + *term = 0; + if (!s->cwd) + s->cwd = strdup(str); + *term = '"'; + } else if (!s->cwd) + s->cwd = unescape(str); + } + } + return 0; +} + +static int common_path_parser(search_items *s, char *path) +{ + char *term; + + if (!s->filename) { + //create + s->filename = malloc(sizeof(slist)); + if (s->filename == NULL) + return 1; + slist_create(s->filename); + } + if (*path == '"') { + /* string is normal */ + path++; + term = strchr(path, '"'); + if (term == NULL) + return 2; + *term = 0; + if (s->filename) { + // append + snode sn; + sn.str = strdup(path); + sn.key = NULL; + sn.hits = 1; + // Attempt to rebuild path if relative + if ((sn.str[0] == '.') && ((sn.str[1] == '.') || + (sn.str[1] == '/')) && s->cwd) { + char *tmp = malloc(PATH_MAX); + if (tmp == NULL) { + free(sn.str); + return 3; + } + snprintf(tmp, PATH_MAX, + "%s/%s", s->cwd, sn.str); + free(sn.str); + sn.str = tmp; + } + slist_append(s->filename, &sn); + } + *term = '"'; + } else { + if (s->filename) { + // append + snode sn; + sn.key = NULL; + sn.hits = 1; + if (strncmp(path, "(null)", 6) == 0) { + sn.str = strdup("(null)"); + goto append; + } + if (!isxdigit(path[0])) + return 4; + if (path[0] == '0' && path[1] == '0') + sn.str = unescape(&path[2]); // Abstract name + else { + term = strchr(path, ' '); + if (term == NULL) + return 5; + *term = 0; + sn.str = unescape(path); + *term = ' '; + } + // Attempt to rebuild path if relative + if ((sn.str[0] == '.') && ((sn.str[1] == '.') || + (sn.str[1] == '/')) && s->cwd) { + char *tmp = malloc(PATH_MAX); + if (tmp == NULL) + return 6; + snprintf(tmp, PATH_MAX, "%s/%s", + s->cwd, sn.str); + free(sn.str); + sn.str = tmp; + } +append: + slist_append(s->filename, &sn); + } + } + return 0; +} + +/* Older AVCs have path separate from the AVC record */ +static int avc_parse_path(const lnode *n, search_items *s) +{ + char *str; + + if (event_filename) { + // dont do this search unless needed + str = strstr(n->message, " path="); + if (str) { + str += 6; + return common_path_parser(s, str); + } + return 1; + } + return 0; +} + +static int parse_path(const lnode *n, search_items *s) +{ + // We add 32 to message because we do not nee to look at + // anything before that. Its only time and type. + char *str, *term = n->message+NAME_OFFSET; + + if (event_filename) { + // dont do this search unless needed + str = strstr(term, " name="); + if (str) { + int rc; + str += 6; + rc = common_path_parser(s, str); + if (rc) + return rc; + } + } + if (event_object) { + // tcontext + str = strstr(term, "obj="); + if (str != NULL) { + str += 4; + term = strchr(str, ' '); + if (term) + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.tcontext = strdup(str); + alist_append(s->avc, &an); + if (term) + *term = ' '; + } else + return 7; + } + } + return 0; +} + +static int parse_obj(const lnode *n, search_items *s) +{ + char *str, *term; + + term = n->message; + if (event_object) { + // obj context + str = strstr(term, "obj="); + if (str != NULL) { + str += 4; + term = strchr(str, ' '); + if (term) + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.tcontext = strdup(str); + alist_append(s->avc, &an); + if (term) + *term = ' '; + } else + return 1; + } + } + return 0; +} + +static int parse_user(const lnode *n, search_items *s) +{ + char *ptr, *str, *term, saved, *mptr; + + term = n->message; + + // get pid + if (event_pid != -1) { + str = strstr(term, "pid="); + if (str == NULL) + return 1; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 2; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 3; + *term = ' '; + } + // optionally get uid + if (event_uid != -1) { + str = strstr(term, "uid="); + if (str == NULL) + return 4; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = ' '; + } + // optionally get loginuid + if (event_loginuid != -2) { + *term = ' '; + str = strstr(term, "auid="); + if (str == NULL) { // Try the older one + str = strstr(term, "loginuid="); + if (str == NULL) + return 7; + ptr = str + 9; + } else + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 8; + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 9; + *term = ' '; + } + // ses + if (event_session_id != -2 ) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 10; + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 11; + *term = ' '; + } + } + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str != NULL) { + str += 5; + term = strchr(str, ' '); + if (term == NULL) + return 12; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 13; + } + } + // optionally get gid + if (event_gid != -1) { + if (n->type == AUDIT_ADD_GROUP || n->type == AUDIT_DEL_GROUP || + n->type == AUDIT_GRP_MGMT) { + str = strstr(term, " id="); + // Take second shot in the case of MGMT events + if (str == NULL && n->type == AUDIT_GRP_MGMT) + str = strstr(term, "gid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 31; + *term = 0; + errno = 0; + s->gid = strtoul(ptr, NULL, 10); + if (errno) + return 32; + *term = ' '; + } + } + } + if (event_vmname) { + str = strstr(term, "vm="); + if (str) { + str += 3; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 23; + *term = 0; + s->vmname = strdup(str); + *term = '"'; + } else + s->vmname = unescape(str); + } + } + if (event_uuid) { + str = strstr(term, "uuid="); + if (str) { + str += 5; + term = str; + while (*term != ' ' && *term != ':') + term++; + if (term == str) + return 24; + saved = *term; + *term = 0; + s->uuid = strdup(str); + *term = saved; + } + } + if (event_subject) { + str = strstr(term, "vm-ctx="); + if (str != NULL) { + str += 7; + term = strchr(str, ' '); + if (term == NULL) + return 27; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 28; + } + } + if (event_object) { + str = strstr(term, "img-ctx="); + if (str != NULL) { + str += 8; + term = strchr(str, ' '); + if (term == NULL) + return 29; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.tcontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 30; + } + } + // optionally get uid - some records the second uid is what we want. + // USER_LOGIN for example. + if (event_uid != -1) { + str = strstr(term, "uid="); + if (str) { + if (*(str - 1) == 'a' || *(str - 1) == 's' || + *(str - 1) == 'u') + goto skip; + if (!(*(str - 1) == '\'' || *(str - 1) == ' ')) + return 25; + ptr = str + 4; + term = ptr; + while (isdigit(*term)) + term++; + if (term == ptr) + return 14; + + saved = *term; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 15; + *term = saved; + } + } +skip: + mptr = term + 1; + + if (event_comm) { + // dont do this search unless needed + str = strstr(mptr, "comm="); + if (str) { + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 16; + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else + s->comm = unescape(str); + } + } + + // Get acct for user/group add/del + str = strstr(mptr, "acct="); + if (str != NULL) { + ptr = str + 5; + term = ptr + 1; + if (*ptr == '"') { + while (*term != '"') + term++; + saved = *term; + *term = 0; + ptr++; + s->acct = strdup(ptr); + *term = saved; + } else { + /* Handle legacy accts */ + char *end = ptr; + int legacy = 0; + + while (*end != ' ') { + if (!isxdigit(*end)) + legacy = 1; + end++; + } + term = end; + if (!legacy) + s->acct = unescape(ptr); + else { + saved = *term; + *term = 0; + s->acct = strdup(ptr); + *term = saved; + } + } + } + mptr = term + 1; + + // get hostname + if (event_hostname) { + // dont do this search unless needed + str = strstr(mptr, "hostname="); + if (str) { + str += 9; + term = strchr(str, ','); + if (term == NULL) { + term = strchr(str, ' '); + if (term == NULL) + return 17; + } + saved = *term; + *term = 0; + s->hostname = strdup(str); + *term = saved; + + // Lets see if there is something more + // meaningful in addr + if (strcmp(s->hostname, "?") == 0) { + term++; + str = strstr(term, "addr="); + if (str) { + str += 5; + term = strchr(str, ','); + if (term == NULL) { + term = strchr(str, ' '); + if (term == NULL) + return 18; + } + saved = *term; + *term = 0; + free(s->hostname); + s->hostname = strdup(str); + *term = saved; + } + } + } + } + if (event_filename) { + // dont do this search unless needed + str = strstr(mptr, "cwd="); + if (str) { + str += 4; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 20; + *term = 0; + s->cwd = strdup(str); + *term = '"'; + } else { + char *end = str; + int legacy = 0; + + while (*end != ' ') { + if (!isxdigit(*end)) { + legacy = 1; + } + end++; + } + term = end; + if (!legacy) + s->cwd = unescape(str); + else { + saved = *term; + *term = 0; + s->cwd = strdup(str); + *term = saved; + } + } + } + } + if (event_terminal) { + // dont do this search unless needed + str = strstr(mptr, "terminal="); + if (str) { + str += 9; + term = strchr(str, ' '); + if (term == NULL) { + term = strchr(str, ')'); + if (term == NULL) + return 19; + } + *term = 0; + s->terminal = strdup(str); + *term = ' '; + } + } + if (event_exe) { + // dont do this search unless needed + str = strstr(mptr, "exe="); + if (str) { + str += 4; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 26; + *term = 0; + s->exe = strdup(str); + *term = '"'; + } else { + char *end = str; + int legacy = 0; + + while (*end != ' ') { + if (!isxdigit(*end)) { + legacy = 1; + } + end++; + } + term = end; + if (!legacy) + s->exe = unescape(str); + else { + saved = *term; + *term = 0; + s->exe = strdup(str); + *term = saved; + } + } + } + } + + // get success + if (event_success != S_UNSET) { + str = strstr(mptr, "res="); + if (str) { + ptr = str + 4; + term = strchr(ptr, '\''); + if (term == NULL) + return 21; + *term = 0; + if (strncmp(ptr, "failed", 6) == 0) + s->success = S_FAILED; + else + s->success = S_SUCCESS; + *term = '\''; + } else if ((str = strstr(mptr, "result="))) { + ptr = str + 7; + term = strchr(ptr, ')'); + if (term == NULL) + return 22; + *term = 0; + if (strcasecmp(ptr, "success") == 0) + s->success = S_SUCCESS; + else + s->success = S_FAILED; + *term = ')'; + } + } + /* last return code used = 24 */ + return 0; +} + +static int parse_login(const lnode *n, search_items *s) +{ + char *ptr, *str, *term = n->message; + + // get pid + if (event_pid != -1) { + str = strstr(term, "pid="); + if (str == NULL) + return 1; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 2; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 3; + *term = ' '; + } + // optionally get uid + if (event_uid != -1) { + str = strstr(term, "uid="); + if (str == NULL) + return 4; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = ' '; + } + // optionally get subj + if (event_subject) { + str = strstr(term, "subj="); + if (str) { + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 12; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 13; + *term = ' '; + } + } + // optionally get loginuid + if (event_loginuid != -2) { + str = strstr(term, "new auid="); + if (str == NULL) { + // 3.14 kernel changed it to the next line + str = strstr(term, " auid="); + if (str == NULL) { + str = strstr(term, "new loginuid="); + if (str == NULL) + return 7; + ptr = str + 13; + } else + ptr = str + 6; + } else + ptr = str + 9; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 8; + if (term) + *term = ' '; + } + + // success + if (event_success != S_UNSET) { + if (term == NULL) + term = n->message; + str = strstr(term, "res="); + if (str != NULL) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->success = strtoul(ptr, NULL, 10); + if (errno) + return 9; + if (term) + *term = ' '; + } else // Assume older kernel where always successful + s->success = S_SUCCESS; + } + // ses + if (event_session_id != -2 ) { + if (term == NULL) + term = n->message; + str = strstr(term, "new ses="); + if (str == NULL) { + // The 3.14 kernel changed it to the next line + str = strstr(term, " ses="); + if (str == NULL) + return 14; + ptr = str + 5; + } + else + ptr = str + 8; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 11; + if (term) + *term = ' '; + } + return 0; +} + +static int parse_daemon1(const lnode *n, search_items *s) +{ + char *ptr, *str, *term, saved, *mptr; + + // Not all messages have a ')', use it if its there + mptr = strchr(n->message, ')'); + if (mptr == NULL) + mptr = n->message; + term = mptr; + + // optionally get auid + if (event_loginuid != -2 ) { + str = strstr(mptr, "auid="); + if (str == NULL) + return 1; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 2; + saved = *term; + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 3; + *term = saved; + } + + // pid + if (event_pid != -1) { + str = strstr(term, "pid="); + if (str == NULL) + return 4; + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + saved = *term; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = saved; + } + + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str != NULL) { + str += 5; + term = strchr(str, ' '); + if (term) + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + } else + return 7; + if (term) + *term = ' '; + } + } + + // success + if (event_success != S_UNSET) { + str = strstr(mptr, "res="); + if (str) { + ptr = term = str + 4; + while (isalpha(*term)) + term++; + if (term == ptr) + return 9; + saved = *term; + *term = 0; + if (strncmp(ptr, "failed", 6) == 0) + s->success = S_FAILED; + else + s->success = S_SUCCESS; + *term = saved; + } + } + + return 0; +} + +static int parse_daemon2(const lnode *n, search_items *s) +{ + char *str, saved, *term = n->message; + + if (event_hostname) { + str = strstr(term, "addr="); + if (str) { + str += 5; + term = strchr(str, ':'); + if (term == NULL) { + term = strchr(str, ' '); + if (term == NULL) + return 1; + } + saved = *term; + *term = 0; + free(s->hostname); + s->hostname = strdup(str); + *term = saved; + } + } + + if (event_success != S_UNSET) { + char *str = strstr(term, "res="); + if (str) { + char *ptr, *term, saved; + + ptr = term = str + 4; + while (isalpha(*term)) + term++; + if (term == ptr) + return 2; + saved = *term; + *term = 0; + if (strncmp(ptr, "failed", 6) == 0) + s->success = S_FAILED; + else + s->success = S_SUCCESS; + *term = saved; + } + } + + return 0; +} + +static int parse_sockaddr(const lnode *n, search_items *s) +{ + char *str; + + if (event_hostname || event_filename) { + str = strstr(n->message, "saddr="); + if (str) { + int len; + struct sockaddr *saddr; + char name[NI_MAXHOST]; + + str += 6; + len = strlen(str)/2; + s->hostname = unescape(str); + saddr = (struct sockaddr *)s->hostname; + if (saddr->sa_family == AF_INET) { + if (len < sizeof(struct sockaddr_in)) { + fprintf(stderr, + "sockaddr len too short\n"); + return 1; + } + len = sizeof(struct sockaddr_in); + } else if (saddr->sa_family == AF_INET6) { + if (len < sizeof(struct sockaddr_in6)) { + fprintf(stderr, + "sockaddr6 len too short\n"); + return 2; + } + len = sizeof(struct sockaddr_in6); + } else if (saddr->sa_family == AF_UNIX) { + struct sockaddr_un *un = + (struct sockaddr_un *)saddr; + if (un->sun_path[0]) + len = strlen(un->sun_path); + else // abstract name + len = strlen(&un->sun_path[1]); + if (len == 0) { + fprintf(stderr, + "sun_path len too short\n"); + return 3; + } + if (event_filename) { + if (!s->filename) { + //create + s->filename = + malloc(sizeof(slist)); + if (s->filename == NULL) + return 4; + slist_create(s->filename); + } + if (s->filename) { + // append + snode sn; + sn.str = strdup(un->sun_path); + sn.key = NULL; + sn.hits = 1; + slist_append(s->filename, &sn); + } + free(s->hostname); + s->hostname = NULL; + return 0; + } else { // No file name - no need for socket + free(s->hostname); + s->hostname = NULL; + return 0; + } + } else { + // addr family we don't care about + free(s->hostname); + s->hostname = NULL; + return 0; + } + if (!event_hostname) { + // we entered here for files - discard + free(s->hostname); + s->hostname = NULL; + return 0; + } + if (getnameinfo(saddr, len, name, NI_MAXHOST, + NULL, 0, NI_NUMERICHOST) ) { + free(s->hostname); + s->hostname = NULL; + } else { + free(s->hostname); + s->hostname = strdup(name); + } + } + } + return 0; +} + +static int parse_integrity(const lnode *n, search_items *s) +{ + char *ptr, *str, *term; + + term = n->message; + // get pid + str = strstr(term, "pid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 1; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 2; + *term = ' '; + } + + // optionally get uid + if (event_uid != -1) { + str = strstr(term, " uid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 3; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 4; + *term = ' '; + } + } + + // optionally get loginuid + if (event_loginuid != -2) { + str = strstr(n->message, "auid="); + if (str) { + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = ' '; + } + } + + // ses + if (event_session_id != -2 ) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 10; + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 11; + *term = ' '; + } + } + + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str) { + str += 5; + term = strchr(str, ' '); + if (term == NULL) + return 12; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 13; + } + } + + if (event_comm) { + str = strstr(term, "comm="); + if (str) { + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 7; + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else + s->comm = unescape(str); + } + } + + if (event_filename) { + str = strstr(term, " name="); + if (str) { + str += 6; + if (common_path_parser(s, str)) + return 8; + } + } + + // and results (usually last) + if (event_success != S_UNSET) { + str = strstr(term, "res="); + if (str != NULL) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->success = strtoul(ptr, NULL, 10); + if (errno) + return 9; + if (term) + *term = ' '; + } + } + + return 0; +} + + +/* FIXME: If they are in permissive mode or hit an auditallow, there can + * be more that 1 avc in the same syscall. For now, we pickup just the first. + */ +static int parse_avc(const lnode *n, search_items *s) +{ + char *str, *term; + anode an; + int rc=0; + + term = n->message; + anode_init(&an); + + // get the avc message info. + str = strstr(term, "avc: "); + if (str) { + str += 5; + term = strchr(str, '{'); + if (term == NULL) + return 1; + if (event_success != S_UNSET) { + *term = 0; + // FIXME. Do not override syscall success if already + // set. Syscall pass/fail is the authoritative value. + if (strstr(str, "denied")) { + s->success = S_FAILED; + an.avc_result = AVC_DENIED; + } else { + s->success = S_SUCCESS; + an.avc_result = AVC_GRANTED; + } + *term = '{'; + } + + // Now get permission + str = term + 1; + while (*str == ' ') + str++; + term = strchr(str, '}'); + if (term == NULL) + return 2; + while (*(term-1) == ' ') + term--; + *term = 0; + an.avc_perm = strdup(str); + *term = ' '; + } + + // get pid + if (event_pid != -1) { + str = strstr(term, "pid="); + if (str) { + str = str + 4; + term = strchr(str, ' '); + if (term == NULL) { + rc = 3; + goto err; + } + *term = 0; + errno = 0; + s->pid = strtoul(str, NULL, 10); + if (errno) { + rc = 4; + goto err; + } + *term = ' '; + } + } + + if (event_comm && s->comm == NULL) { + // dont do this search unless needed + str = strstr(term, "comm="); + if (str == NULL) { + rc = 5; + goto err; + } + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) { + rc = 6; + goto err; + } + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else { + s->comm = unescape(str); + term = str + 6; + } + } + if (event_filename) { + // do we have a path? + str = strstr(term, " path="); + if (str) { + str += 6; + rc = common_path_parser(s, str); + if (rc) + goto err; + term += 7; + } else { + str = strstr(term, " name="); + if (str) { + str += 6; + rc = common_path_parser(s, str); + if (rc) + goto err; + term += 7; + } + } + } + if (event_subject) { + // scontext + str = strstr(term, "scontext="); + if (str != NULL) { + str += 9; + term = strchr(str, ' '); + if (term == NULL) { + rc = 7; + goto err; + } + *term = 0; + an.scontext = strdup(str); + *term = ' '; + } + } + + if (event_object) { + // tcontext + str = strstr(term, "tcontext="); + if (str != NULL) { + str += 9; + term = strchr(str, ' '); + if (term == NULL) { + rc = 8; + goto err; + } + *term = 0; + an.tcontext = strdup(str); + *term = ' '; + } + } + + // Now get the class...its at the end, so we do things different + str = strstr(term, "tclass="); + if (str == NULL) { + rc = 9; + goto err; + } + str += 7; + term = strchr(str, ' '); + if (term) + *term = 0; + an.avc_class = strdup(str); + if (term) + *term = ' '; + + if (audit_avc_init(s) == 0) { + alist_append(s->avc, &an); + } else { + rc = 10; + goto err; + } + + return 0; +err: + anode_clear(&an); + return rc; +} + +static int parse_kernel_anom(const lnode *n, search_items *s) +{ + char *str, *ptr, *term = n->message; + + // optionally get loginuid + if (event_loginuid != -2) { + str = strstr(term, "auid="); + if (str == NULL) + return 1; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 2; + if (term) + *term = ' '; + else + term = ptr; + } + + // optionally get uid + if (event_uid != -1) { + str = strstr(term, "uid="); // if promiscuous, we start over + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 3; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 4; + *term = ' '; + } + } + + // optionally get gid + if (event_gid != -1) { + str = strstr(term, "gid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 5; + *term = 0; + errno = 0; + s->gid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + *term = ' '; + } + } + + if (event_session_id != -2) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 7; + if (term) + *term = ' '; + else + term = ptr; + } + } + + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str) { + str += 5; + term = strchr(str, ' '); + if (term == NULL) + return 8; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 9; + } + } + + // get pid + if (event_pid != -1) { + str = strstr(term, "pid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 10; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 11; + *term = ' '; + } + } + + if (event_comm) { + // dont do this search unless needed + str = strstr(term, "comm="); + if (str) { + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 12; + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else + s->comm = unescape(str); + } + } + + if (n->type == AUDIT_SECCOMP) { + if (event_exe) { + // dont do this search unless needed + str = strstr(n->message, "exe="); + if (str) { + str += 4; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 13; + *term = 0; + s->exe = strdup(str); + *term = '"'; + } else + s->exe = unescape(str); + } else + return 14; + } + + // get arch + str = strstr(term, "arch="); + if (str == NULL) + return 0; // A few kernel versions don't have it + ptr = str + 5; + term = strchr(ptr, ' '); + if (term == NULL) + return 15; + *term = 0; + errno = 0; + s->arch = (int)strtoul(ptr, NULL, 16); + if (errno) + return 16; + *term = ' '; + // get syscall + str = strstr(term, "syscall="); + if (str == NULL) + return 17; + ptr = str + 8; + term = strchr(ptr, ' '); + if (term == NULL) + return 18; + *term = 0; + errno = 0; + s->syscall = (int)strtoul(ptr, NULL, 10); + if (errno) + return 19; + *term = ' '; + } + + return 0; +} + +// This is for messages that only have the loginuid as the item +// of interest. +static int parse_simple_message(const lnode *n, search_items *s) +{ + char *str, *ptr, *term = n->message; + + // optionally get loginuid - old kernels skip auid for CONFIG_CHANGE + if (event_loginuid != -2) { + str = strstr(term, "auid="); + if (str == NULL && n->type != AUDIT_CONFIG_CHANGE) + return 1; + if (str) { + ptr = str + 5; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 2; + if (term) + *term = ' '; + else + term = ptr; + } + } + + // ses + if (event_session_id != -2 ) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 3; + if (term) + *term = ' '; + else + term = ptr; + } + } + + // Now get subj label + if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str != NULL) { + str += 5; + term = strchr(str, ' '); + if (term) + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + if (term) + *term = ' '; + else // Set it back to something sane + term = str; + } else + return 4; + } + } + + if (event_key) { + str = strstr(term, "key="); + if (str != NULL) { + if (!s->key) { + //create + s->key = malloc(sizeof(slist)); + if (s->key == NULL) + return 5; + slist_create(s->key); + } + ptr = str + 4; + if (*ptr == '"') { + ptr++; + term = strchr(ptr, '"'); + if (term != NULL) { + *term = 0; + if (s->key) { + // append + snode sn; + sn.str = strdup(ptr); + sn.key = NULL; + sn.hits = 1; + slist_append(s->key, &sn); + } + *term = '"'; + } else + return 6; + } else { + if (s->key) { + char *saved; + char *keyptr = unescape(ptr); + char *kptr = strtok_r(keyptr, + key_sep, &saved); + while (kptr) { + snode sn; + // append + sn.str = strdup(kptr); + sn.key = NULL; + sn.hits = 1; + slist_append(s->key, &sn); + kptr = strtok_r(NULL, + key_sep, &saved); + } + free(keyptr); + } + } + } + } + + // defaulting this to 1 for these messages. The kernel generally + // does not log the res since it can be nothing but success. + // But it can still be overriden below if res= is found in the event + if (n->type == AUDIT_CONFIG_CHANGE) + s->success = S_SUCCESS; + + // and results (usually last) + if (event_success != S_UNSET) { + str = strstr(term, "res="); + if (str != NULL) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->success = strtoul(ptr, NULL, 10); + if (errno) + return 7; + if (term) + *term = ' '; + } + } + + return 0; +} + +static int parse_tty(const lnode *n, search_items *s) +{ + char *str, *ptr, *term=n->message; + + // get pid + if (event_pid != -1) { + str = strstr(n->message, "pid="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 1; + *term = 0; + errno = 0; + s->pid = strtoul(ptr, NULL, 10); + if (errno) + return 2; + *term = ' '; + } + } + + // optionally get uid + if (event_uid != -1) { + str = strstr(term, " uid="); // if promiscuous, we start over + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 3; + *term = 0; + errno = 0; + s->uid = strtoul(ptr, NULL, 10); + if (errno) + return 4; + *term = ' '; + } + } + + // optionally get loginuid + if (event_loginuid != -2) { + str = strstr(term, "auid="); + if (str == NULL) + return 5; + ptr = str + 5; + term = strchr(ptr, ' '); + if (term) + *term = 0; + errno = 0; + s->loginuid = strtoul(ptr, NULL, 10); + if (errno) + return 6; + if (term) + *term = ' '; + else + term = ptr; + } + + // ses + if (event_session_id != -2 ) { + str = strstr(term, "ses="); + if (str) { + ptr = str + 4; + term = strchr(ptr, ' '); + if (term == NULL) + return 7; + *term = 0; + errno = 0; + s->session_id = strtoul(ptr, NULL, 10); + if (errno) + return 8; + *term = ' '; + } + } + +/* if (event_subject) { + // scontext + str = strstr(term, "subj="); + if (str) { + str += 5; + term = strchr(str, ' '); + if (term == NULL) + return 9; + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.scontext = strdup(str); + alist_append(s->avc, &an); + *term = ' '; + } else + return 10; + } + } */ + + if (event_comm) { + // dont do this search unless needed + str = strstr(term, "comm="); + if (str) { + str += 5; + if (*str == '"') { + str++; + term = strchr(str, '"'); + if (term == NULL) + return 11; + *term = 0; + s->comm = strdup(str); + *term = '"'; + } else + s->comm = unescape(str); + } + } + + return 0; +} + +static int parse_pkt(const lnode *n, search_items *s) +{ + char *str, *ptr, *term=n->message; + + // get hostname + if (event_hostname) { + str = strstr(n->message, "saddr="); + if (str) { + ptr = str + 6; + term = strchr(ptr, ' '); + if (term == NULL) + return 1; + *term = 0; + s->hostname = strdup(ptr); + *term = ' '; + } + } + + // obj context + if (event_object) { + str = strstr(term, "obj="); + if (str != NULL) { + str += 4; + term = strchr(str, ' '); + if (term) + *term = 0; + if (audit_avc_init(s) == 0) { + anode an; + + anode_init(&an); + an.tcontext = strdup(str); + alist_append(s->avc, &an); + if (term) + *term = ' '; + } else + return 2; + } + } + + return 0; +} + |