int audit_rule_syscallbyname(struct audit_rule *rule, const char *scall) { int nr, i; int machine; if (!strcmp(scall, "all")) { for (i = 0; i < (AUDIT_BITMASK_SIZE-1); i++) rule->mask[i] = ~0; return 0; } if (!audit_elf) machine = audit_detect_machine(); else machine = audit_elf_to_machine(audit_elf); if (machine < 0) return -2; nr = audit_name_to_syscall(scall, machine); if (nr < 0) { if (isdigit(scall[0])) nr = strtol(scall, NULL, 0); } if (nr >= 0) return audit_rule_syscall(rule, nr); return -1; }
const char *aulookup_syscall(llist *l, char *buf, size_t size) { const char *sys; if (report_format <= RPT_DEFAULT) { snprintf(buf, size, "%d", l->s.syscall); return buf; } machine = audit_elf_to_machine(l->s.arch); if (machine < 0) return Q; sys = audit_syscall_to_name(l->s.syscall, machine); if (sys) { const char *func = NULL; if (strcmp(sys, "socketcall") == 0) { if (list_find_item(l, AUDIT_SYSCALL)) func = aulookup_socketcall((long)l->cur->a0); } else if (strcmp(sys, "ipc") == 0) { if(list_find_item(l, AUDIT_SYSCALL)) func = aulookup_ipccall((long)l->cur->a0); } if (func) { snprintf(buf, size, "%s(%s)", sys, func); return buf; } return sys; } snprintf(buf, size, "%d", l->s.syscall); return buf; }
static int print_syscall(const struct audit_rule_data *r, unsigned int *sc) { int count = 0; int all = 1; unsigned int i; int machine = audit_detect_machine(); /* Rules on the following filters do not take a syscall */ if (((r->flags & AUDIT_FILTER_MASK) == AUDIT_FILTER_USER) || ((r->flags & AUDIT_FILTER_MASK) == AUDIT_FILTER_TASK) || ((r->flags &AUDIT_FILTER_MASK) == AUDIT_FILTER_EXCLUDE)) return 0; /* See if its all or specific syscalls */ for (i = 0; i < (AUDIT_BITMASK_SIZE-1); i++) { if (r->mask[i] != (uint32_t)~0) { all = 0; break; } } if (all) { printf(" -S all"); count = i; } else for (i = 0; i < AUDIT_BITMASK_SIZE * 32; i++) { int word = AUDIT_WORD(i); int bit = AUDIT_BIT(i); if (r->mask[word] & bit) { const char *ptr; if (_audit_elf) machine = audit_elf_to_machine(_audit_elf); if (machine < 0) ptr = NULL; else ptr = audit_syscall_to_name(i, machine); if (!count) printf(" -S "); if (ptr) printf("%s%s", !count ? "" : ",", ptr); else printf("%s%d", !count ? "" : ",", i); count++; *sc = i; } } return count; }
static void print_arch(const char *val) { unsigned int ival; const char *ptr; errno = 0; ival = strtoul(val, NULL, 16); if (errno) { printf("conversion error(%s) ", val); return; } machine = audit_elf_to_machine(ival); if (machine < 0) { printf("unknown elf type(%s) ", val); return; } ptr = audit_machine_to_name(machine); printf("%s ", ptr); }
static int print_arch(unsigned int value, int op) { int machine; _audit_elf = value; machine = audit_elf_to_machine(_audit_elf); if (machine < 0) printf(" -F arch%s0x%X", audit_operator_to_symbol(op), (unsigned)value); else { if (interpret == 0) { if (__AUDIT_ARCH_64BIT & _audit_elf) printf(" -F arch%sb64", audit_operator_to_symbol(op)); else printf(" -F arch%sb32", audit_operator_to_symbol(op)); } else { const char *ptr = audit_machine_to_name(machine); printf(" -F arch%s%s", audit_operator_to_symbol(op), ptr); } } return machine; }
static void interpret(char *name, char *val, int comma, int rtype) { int type; idata id; while (*name == ' '||*name == '(') name++; if (*name == 'a' && strcmp(name, "acct") == 0) { // Remove trailing punctuation int len = strlen(val); if (val[len-1] == ':') val[len-1] = 0; } type = auparse_interp_adjust_type(rtype, name, val); if (rtype == AUDIT_SYSCALL) { if (machine == (unsigned long)-1) machine = audit_detect_machine(); if (*name == 'a' && strcmp(name, "arch") == 0) { unsigned long ival; errno = 0; ival = strtoul(val, NULL, 16); if (errno) { printf("arch conversion error(%s) ", val); return; } machine = audit_elf_to_machine(ival); } if (cur_syscall < 0 && *name == 's' && strcmp(name, "syscall") == 0) { unsigned long ival; errno = 0; ival = strtoul(val, NULL, 10); if (errno) { printf("syscall conversion error(%s) ", val); return; } cur_syscall = ival; } id.syscall = cur_syscall; } else id.syscall = 0; id.machine = machine; id.a0 = a0; id.a1 = a1; id.name = name; id.val = val; char *out = auparse_do_interpretation(type, &id); if (type == AUPARSE_TYPE_UNCLASSIFIED) printf("%s%c", val, comma ? ',' : ' '); else if (name[0] == 'k' && strcmp(name, "key") == 0) { char *str, *ptr = out; int count = 0; while ((str = strchr(ptr, AUDIT_KEY_SEPARATOR))) { *str = 0; if (count == 0) { printf("%s", ptr); count++; } else printf(" key=%s", ptr); ptr = str+1; } if (count == 0) printf("%s ", out); else printf(" key=%s ", ptr); } else if (type == AUPARSE_TYPE_TTY_DATA) printf("%s", out); else printf("%s ", out); free(out); }
/* * This function interprets the reply and prints it to stdout. It returns * 0 if no more should be read and 1 to indicate that more messages of this * type may need to be read. */ static int audit_print_reply(struct audit_reply *rep) { unsigned int i; int first; int sparse; int machine = audit_detect_machine(); size_t boffset; int show_syscall; _audit_elf = 0; switch (rep->type) { case NLMSG_NOOP: return 1; case NLMSG_DONE: if (printed == 0) printf("No rules\n"); return 0; case NLMSG_ERROR: printf("NLMSG_ERROR %d (%s)\n", -rep->error->error, strerror(-rep->error->error)); printed = 1; return 0; case AUDIT_GET: printf("AUDIT_STATUS: enabled=%d flag=%d pid=%d" " rate_limit=%d backlog_limit=%d lost=%d backlog=%u\n", rep->status->enabled, rep->status->failure, rep->status->pid, rep->status->rate_limit, rep->status->backlog_limit, rep->status->lost, rep->status->backlog); printed = 1; return 0; case AUDIT_LIST_RULES: list_requested = 0; boffset = 0; show_syscall = 1; if (key_match(rep) == 0) return 1; printed = 1; printf("%s: %s,%s", audit_msg_type_to_name(rep->type), audit_flag_to_name((int)rep->ruledata->flags), audit_action_to_name(rep->ruledata->action)); for (i = 0; i < rep->ruledata->field_count; i++) { const char *name; int op = rep->ruledata->fieldflags[i] & AUDIT_OPERATORS; int field = rep->ruledata->fields[i] & ~AUDIT_OPERATORS; name = audit_field_to_name(field); if (name) { if (strcmp(name, "arch") == 0) { _audit_elf = rep->ruledata->values[i]; printf(" %s%s%u", name, audit_operator_to_symbol(op), (unsigned)rep->ruledata->values[i]); } else if (strcmp(name, "msgtype") == 0) { if (!audit_msg_type_to_name( rep->ruledata->values[i])) printf(" %s%s%d", name, audit_operator_to_symbol(op), rep->ruledata->values[i]); else { printf(" %s%s%s", name, audit_operator_to_symbol(op), audit_msg_type_to_name(rep->ruledata->values[i])); } } else if ((field >= AUDIT_SUBJ_USER && field <= AUDIT_OBJ_LEV_HIGH) && field != AUDIT_PPID && rep->type == AUDIT_LIST_RULES) { printf(" %s%s%.*s", name, audit_operator_to_symbol(op), rep->ruledata->values[i], &rep->ruledata->buf[boffset]); boffset += rep->ruledata->values[i]; } else if (field == AUDIT_WATCH) { printf(" watch=%.*s", rep->ruledata->values[i], &rep->ruledata->buf[boffset]); boffset += rep->ruledata->values[i]; } else if (field == AUDIT_DIR) { printf(" dir=%.*s", rep->ruledata->values[i], &rep->ruledata->buf[boffset]); boffset += rep->ruledata->values[i]; } else if (field == AUDIT_FILTERKEY) { char *rkey, *ptr; asprintf(&rkey, "%.*s", rep->ruledata->values[i], &rep->ruledata->buf[boffset]); boffset += rep->ruledata->values[i]; ptr = strtok(rkey, key_sep); while (ptr) { printf(" key=%s", ptr); ptr = strtok(NULL, key_sep); } free(rkey); } else if (field == AUDIT_PERM) { char perms[5]; int val=rep->ruledata->values[i]; perms[0] = 0; if (val & AUDIT_PERM_READ) strcat(perms, "r"); if (val & AUDIT_PERM_WRITE) strcat(perms, "w"); if (val & AUDIT_PERM_EXEC) strcat(perms, "x"); if (val & AUDIT_PERM_ATTR) strcat(perms, "a"); printf(" perm=%s", perms); show_syscall = 0; } else if (field == AUDIT_INODE) { // Unsigned items printf(" %s%s%u", name, audit_operator_to_symbol(op), rep->ruledata->values[i]); } else if (field == AUDIT_FIELD_COMPARE) { switch (rep->ruledata->values[i]) { case AUDIT_COMPARE_UID_TO_OBJ_UID: printf(" uid%sobj_uid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_GID_TO_OBJ_GID: printf(" gid%sobj_gid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EUID_TO_OBJ_UID: printf(" euid%sobj_uid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EGID_TO_OBJ_GID: printf(" egid%sobj_gid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_AUID_TO_OBJ_UID: printf(" auid%sobj_uid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_SUID_TO_OBJ_UID: printf(" suid%sobj_uid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_SGID_TO_OBJ_GID: printf(" sgid%sobj_gid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_FSUID_TO_OBJ_UID: printf(" fsuid%sobj_uid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_FSGID_TO_OBJ_GID: printf(" fsgid%sobj_gid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_UID_TO_AUID: printf(" uid%sauid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_UID_TO_EUID: printf(" uid%seuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_UID_TO_FSUID: printf(" uid%sfsuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_UID_TO_SUID: printf(" uid%ssuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_AUID_TO_FSUID: printf(" auid%sfsuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_AUID_TO_SUID: printf(" auid%ssuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_AUID_TO_EUID: printf(" auid%seuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EUID_TO_SUID: printf(" euid%ssuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EUID_TO_FSUID: printf(" euid%sfsuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_SUID_TO_FSUID: printf(" suid%sfsuid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_GID_TO_EGID: printf(" gid%segid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_GID_TO_FSGID: printf(" gid%sfsgid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_GID_TO_SGID: printf(" gid%ssgid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EGID_TO_FSGID: printf(" egid%sfsgid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_EGID_TO_SGID: printf(" egid%ssgid",audit_operator_to_symbol(op)); break; case AUDIT_COMPARE_SGID_TO_FSGID: printf(" sgid%sfsgid",audit_operator_to_symbol(op)); break; } } else { // Signed items printf(" %s%s%d", name, audit_operator_to_symbol(op), rep->ruledata->values[i]); } } else { printf(" f%d%s%d", rep->ruledata->fields[i], audit_operator_to_symbol(op), rep->ruledata->values[i]); } /* Avoid printing value if the field type is * known to return a string. */ if (rep->ruledata->values[i] && (field < AUDIT_SUBJ_USER || field > AUDIT_SUBJ_CLR) && field != AUDIT_WATCH && field != AUDIT_FILTERKEY && field != AUDIT_PERM && field != AUDIT_FIELD_COMPARE) printf(" (0x%x)", rep->ruledata->values[i]); } if (show_syscall && ((rep->ruledata->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_USER) && ((rep->ruledata->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK) && ((rep->ruledata->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_EXCLUDE)) { printf(" syscall="); for (sparse = 0, i = 0; i < (AUDIT_BITMASK_SIZE-1); i++) { if (rep->ruledata->mask[i] != (uint32_t)~0) sparse = 1; } if (!sparse) { printf("all"); } else for (first = 1, i = 0; i < AUDIT_BITMASK_SIZE * 32; i++) { int word = AUDIT_WORD(i); int bit = AUDIT_BIT(i); if (rep->ruledata->mask[word] & bit) { const char *ptr; if (_audit_elf) machine = audit_elf_to_machine( _audit_elf); if (machine < 0) ptr = NULL; else ptr = audit_syscall_to_name(i, machine); if (ptr) printf("%s%s", first ? "" : ",", ptr); else printf("%s%d", first ? "" : ",", i); first = 0; } } } printf("\n"); return 1; /* get more messages until NLMSG_DONE */ default: printf("Unknown: type=%d, len=%d\n", rep->type, rep->nlh->nlmsg_len); printed = 1; return 0; } }
int audit_rule_fieldpair(struct audit_rule *rule, const char *pair, int flags) { const char *f = pair; char *v; int op; int field; int vlen; if (f == NULL) return -1; /* look for 2-char operators first then look for 1-char operators afterwards when found, null out the bytes under the operators to split and set value pointer just past operator bytes */ if ( (v = strstr(pair, "!=")) ) { *v++ = '\0'; *v++ = '\0'; op = AUDIT_NEGATE; // legacy // op = AUDIT_NOT_EQUAL; } else if ( (v = strstr(pair, ">")) ) { return -10; } else if ( (v = strstr(pair, "<")) ) { return -10; } else if ( (v = strstr(pair, "&")) ) { return -10; } else if ( (v = strstr(pair, "=")) ) { *v++ = '\0'; op = 0; // legacy // op = AUDIT_EQUAL; } if (v == NULL) return -1; if (*f == 0) return -22; if (*v == 0) return -20; audit_msg(LOG_DEBUG,"pair=%s\n", f); if ((field = audit_name_to_field(f)) < 0) return -2; /* Exclude filter can be used only with MSGTYPE field */ if (flags == AUDIT_FILTER_EXCLUDE && field != AUDIT_MSGTYPE) return -12; audit_msg(LOG_DEBUG,"f%d%s%s\n", field, audit_operator_to_symbol(op),v); rule->fields[rule->field_count] = field | op; switch (field) { case AUDIT_UID: case AUDIT_EUID: case AUDIT_SUID: case AUDIT_FSUID: case AUDIT_LOGINUID: // Do positive & negative separate for 32 bit systems vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtoul(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { if (name_to_uid(v, &rule->values[rule->field_count])) { audit_msg(LOG_ERR, "Unknown user: %s", v); return -2; } } break; case AUDIT_GID: case AUDIT_EGID: case AUDIT_SGID: case AUDIT_FSGID: if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { if (name_to_gid(v, &rule->values[rule->field_count])) { audit_msg(LOG_ERR, "Unknown group: %s", v); return -2; } } break; case AUDIT_EXIT: if (flags != AUDIT_FILTER_EXIT) return -7; vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { rule->values[rule->field_count] = audit_name_to_errno(v); if (rule->values[rule->field_count] == 0) return -15; } break; case AUDIT_MSGTYPE: if (flags != AUDIT_FILTER_EXCLUDE) return -9; if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else if (audit_name_to_msg_type(v) > 0) rule->values[rule->field_count] = audit_name_to_msg_type(v); else return -8; break; case AUDIT_ARCH: if (audit_syscalladded) return -3; if (!(op == AUDIT_NEGATE || op == 0)) return -13; if (isdigit((char)*(v))) { int machine; errno = 0; audit_elf = strtoul(v, NULL, 0); if (errno) return -5; // Make sure we have a valid mapping machine = audit_elf_to_machine(audit_elf); if (machine < 0) return -5; } else { // what do we want? i686, x86_64, ia64 // or b64, b32 int machine; unsigned int bits=0, elf; const char *arch=v; if (strcasecmp("b64", arch) == 0) { bits = __AUDIT_ARCH_64BIT; machine = audit_detect_machine(); } else if (strcasecmp("b32", arch) == 0) { bits = ~__AUDIT_ARCH_64BIT; machine = audit_detect_machine(); } else machine = audit_name_to_machine(arch); if (machine < 0) return -4; /* Here's where we fixup the machine. * for example, they give x86_64 & want 32 bits. * we translate that to i686. */ if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_86_64) machine = MACH_X86; else if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_PPC64) machine = MACH_PPC; else if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_S390X) machine = MACH_S390; /* Check for errors - return -6 * We don't allow 32 bit machines to specify * 64 bit. */ switch (machine) { case MACH_X86: if (bits == __AUDIT_ARCH_64BIT) return -6; break; case MACH_IA64: if (bits == ~__AUDIT_ARCH_64BIT) return -6; break; case MACH_PPC: if (bits == __AUDIT_ARCH_64BIT) return -6; break; case MACH_S390: if (bits == __AUDIT_ARCH_64BIT) return -6; break; case MACH_86_64: /* fallthrough */ case MACH_PPC64: /* fallthrough */ case MACH_S390X: /* fallthrough */ break; default: return -6; } /* OK, we have the machine type, now convert to elf. */ elf = audit_machine_to_elf(machine); if (elf == 0) return -5; audit_elf = elf; } rule->values[rule->field_count] = audit_elf; audit_archadded = 1; break; case AUDIT_FILETYPE: if (flags != AUDIT_FILTER_EXIT && flags != AUDIT_FILTER_ENTRY) return -17; rule->values[rule->field_count] = audit_name_to_ftype(v); if (rule->values[rule->field_count] < 0) { return -16; } break; /* These are strings */ case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_SEN: case AUDIT_SUBJ_CLR: case AUDIT_OBJ_USER: case AUDIT_OBJ_ROLE: case AUDIT_OBJ_TYPE: case AUDIT_OBJ_LEV_LOW: case AUDIT_OBJ_LEV_HIGH: case AUDIT_WATCH: case AUDIT_PERM: case AUDIT_DIR: case AUDIT_FILTERKEY: return -10; case AUDIT_ARG0...AUDIT_ARG3: vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtoul(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else return -21; break; case AUDIT_DEVMAJOR...AUDIT_INODE: case AUDIT_SUCCESS: if (flags != AUDIT_FILTER_EXIT) return -7; /* fallthrough */ default: if (field == AUDIT_INODE) { if (!(op == AUDIT_NEGATE || op == 0)) return -13; } if (field == AUDIT_PPID && (flags != AUDIT_FILTER_EXIT && flags != AUDIT_FILTER_ENTRY)) return -17; if (flags == AUDIT_FILTER_EXCLUDE) return -18; if (!isdigit((char)*(v))) return -21; if (field == AUDIT_INODE) rule->values[rule->field_count] = strtoul(v, NULL, 0); else rule->values[rule->field_count] = strtol(v, NULL, 0); break; } ++rule->field_count; return 0; }
int match(llist *l) { // Are we within time range? if (start_time == 0 || l->e.sec >= start_time) { if (end_time == 0 || l->e.sec <= end_time) { if (event_id == -1 || event_id == l->e.serial) { // OK - do the heavier checking if (extract_search_items(l)) { return 0; } // perform additional tests for the field if (event_node_list) { const snode *sn; int found=0; slist *sptr = event_node_list; if (l->e.node == NULL) return 0; slist_first(sptr); sn=slist_get_cur(sptr); while (sn && !found) { if (sn->str && (!strcmp(sn->str, l->e.node))) found++; else sn=slist_next(sptr); } if (!found) return 0; } if (user_match(l) == 0) return 0; if (group_match(l) == 0) return 0; if ((event_ppid != -1) && (event_ppid != l->s.ppid)) return 0; if ((event_pid != -1) && (event_pid != l->s.pid)) return 0; if (event_machine != -1 && (event_machine != audit_elf_to_machine(l->s.arch))) return 0; if ((event_syscall != -1) && (event_syscall != l->s.syscall)) return 0; if ((event_session_id != -2) && (event_session_id != l->s.session_id)) return 0; if (event_exit_is_set) { if (l->s.exit_is_set == 0) return 0; if (event_exit != l->s.exit) return 0; } if ((event_success != S_UNSET) && (event_success != l->s.success)) return 0; // event_type requires looking at each item if (event_type != NULL) { int found = 0; const lnode *n; list_first(l); n = list_get_cur(l); do { int_node *in; ilist_first(event_type); in = ilist_get_cur(event_type); do { if (in->num == n->type){ found = 1; break; } } while((in = ilist_next(event_type))); if (found) break; } while ((n = list_next(l))); if (!found) return 0; } // Done all the easy compares, now do the // string searches. if (event_filename) { int found = 0; if (l->s.filename == NULL && l->s.cwd == NULL) return 0; if (l->s.filename) { const snode *sn; slist *sptr = l->s.filename; slist_first(sptr); sn=slist_get_cur(sptr); do { if (sn->str == NULL) return 0; if (strmatch( event_filename, sn->str)) { found = 1; break; } } while ((sn=slist_next(sptr))); if (!found && l->s.cwd == NULL) return 0; } if (l->s.cwd && !found) { /* Check cwd, too */ if (strmatch(event_filename, l->s.cwd) == 0) return 0; } } if (event_hostname) { if (l->s.hostname == NULL) return 0; if (strmatch(event_hostname, l->s.hostname) == 0) return 0; } if (event_terminal) { if (l->s.terminal == NULL) return 0; if (strmatch(event_terminal, l->s.terminal) == 0) return 0; } if (event_exe) { if (l->s.exe == NULL) return 0; if (strmatch(event_exe, l->s.exe) == 0) return 0; } if (event_comm) { if (l->s.comm == NULL) return 0; if (strmatch(event_comm, l->s.comm) == 0) return 0; } if (event_key) { if (l->s.key == NULL) return 0; else { int found = 0; const snode *sn; slist *sptr = l->s.key; slist_first(sptr); sn=slist_get_cur(sptr); do { if (sn->str == NULL) return 0; if (strmatch( event_key, sn->str)) { found = 1; break; } } while ((sn=slist_next(sptr))); if (!found) return 0; } } if (event_vmname) { if (l->s.vmname == NULL) return 0; if (strmatch(event_vmname, l->s.vmname) == 0) return 0; } if (event_uuid) { if (l->s.uuid == NULL) return 0; if (strmatch(event_uuid, l->s.uuid) == 0) return 0; } if (context_match(l) == 0) return 0; return 1; } } } return 0; }
int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair, int flags) { const char *f = pair; char *v; int op; int field; int vlen; int offset; struct audit_rule_data *rule = *rulep; if (f == NULL) return -1; /* look for 2-char operators first then look for 1-char operators afterwards when found, null out the bytes under the operators to split and set value pointer just past operator bytes */ if ( (v = strstr(pair, "!=")) ) { *v++ = '\0'; *v++ = '\0'; op = AUDIT_NOT_EQUAL; } else if ( (v = strstr(pair, ">=")) ) { *v++ = '\0'; *v++ = '\0'; op = AUDIT_GREATER_THAN_OR_EQUAL; } else if ( (v = strstr(pair, "<=")) ) { *v++ = '\0'; *v++ = '\0'; op = AUDIT_LESS_THAN_OR_EQUAL; } else if ( (v = strstr(pair, "&=")) ) { *v++ = '\0'; *v++ = '\0'; op = AUDIT_BIT_TEST; } else if ( (v = strstr(pair, "=")) ) { *v++ = '\0'; op = AUDIT_EQUAL; } else if ( (v = strstr(pair, ">")) ) { *v++ = '\0'; op = AUDIT_GREATER_THAN; } else if ( (v = strstr(pair, "<")) ) { *v++ = '\0'; op = AUDIT_LESS_THAN; } else if ( (v = strstr(pair, "&")) ) { *v++ = '\0'; op = AUDIT_BIT_MASK; } if (v == NULL) return -1; if (*f == 0) return -22; if (*v == 0) return -20; if ((field = audit_name_to_field(f)) < 0) return -2; /* Exclude filter can be used only with MSGTYPE field */ if (flags == AUDIT_FILTER_EXCLUDE && field != AUDIT_MSGTYPE) return -12; rule->fields[rule->field_count] = field; rule->fieldflags[rule->field_count] = op; switch (field) { case AUDIT_UID: case AUDIT_EUID: case AUDIT_SUID: case AUDIT_FSUID: case AUDIT_LOGINUID: case AUDIT_OBJ_UID: case AUDIT_OBJ_GID: // Do positive & negative separate for 32 bit systems vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtoul(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { if (strcmp(v, "unset") == 0) rule->values[rule->field_count] = 4294967295; else if (audit_name_to_uid(v, &rule->values[rule->field_count])) { audit_msg(LOG_ERR, "Unknown user: %s", v); return -2; } } break; case AUDIT_GID: case AUDIT_EGID: case AUDIT_SGID: case AUDIT_FSGID: if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { if (audit_name_to_gid(v, &rule->values[rule->field_count])) { audit_msg(LOG_ERR, "Unknown group: %s", v); return -2; } } break; case AUDIT_EXIT: if (flags != AUDIT_FILTER_EXIT) return -7; vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else { rule->values[rule->field_count] = audit_name_to_errno(v); if (rule->values[rule->field_count] == 0) return -15; } break; case AUDIT_MSGTYPE: if (flags != AUDIT_FILTER_EXCLUDE && flags != AUDIT_FILTER_USER) return -9; if (isdigit((char)*(v))) rule->values[rule->field_count] = strtol(v, NULL, 0); else if (audit_name_to_msg_type(v) > 0) rule->values[rule->field_count] = audit_name_to_msg_type(v); else return -8; break; /* These next few are strings */ case AUDIT_OBJ_USER: case AUDIT_OBJ_ROLE: case AUDIT_OBJ_TYPE: case AUDIT_OBJ_LEV_LOW: case AUDIT_OBJ_LEV_HIGH: case AUDIT_WATCH: case AUDIT_DIR: /* Watch & object filtering is invalid on anything * but exit */ if (flags != AUDIT_FILTER_EXIT) return -7; if (field == AUDIT_WATCH || field == AUDIT_DIR) _audit_permadded = 1; /* fallthrough */ case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_SEN: case AUDIT_SUBJ_CLR: case AUDIT_FILTERKEY: if (field == AUDIT_FILTERKEY && !(_audit_syscalladded || _audit_permadded)) return -19; vlen = strlen(v); if (field == AUDIT_FILTERKEY && vlen > AUDIT_MAX_KEY_LEN) return -11; else if (vlen > PATH_MAX) return -11; rule->values[rule->field_count] = vlen; offset = rule->buflen; rule->buflen += vlen; *rulep = realloc(rule, sizeof(*rule) + rule->buflen); if (*rulep == NULL) { free(rule); audit_msg(LOG_ERR, "Cannot realloc memory!\n"); return -3; } else { rule = *rulep; } strncpy(&rule->buf[offset], v, vlen); break; case AUDIT_ARCH: if (_audit_syscalladded) return -3; if (!(op == AUDIT_NOT_EQUAL || op == AUDIT_EQUAL)) return -13; if (isdigit((char)*(v))) { int machine; errno = 0; _audit_elf = strtoul(v, NULL, 0); if (errno) return -5; // Make sure we have a valid mapping machine = audit_elf_to_machine(_audit_elf); if (machine < 0) return -5; } else { // what do we want? i686, x86_64, ia64 // or b64, b32 int machine; unsigned int bits=0, elf; const char *arch=v; if (strcasecmp("b64", arch) == 0) { bits = __AUDIT_ARCH_64BIT; machine = audit_detect_machine(); } else if (strcasecmp("b32", arch) == 0) { bits = ~__AUDIT_ARCH_64BIT; machine = audit_detect_machine(); } else machine = audit_name_to_machine(arch); if (machine < 0) return -4; /* Here's where we fixup the machine. * for example, they give x86_64 & want 32 bits. * we translate that to i686. */ if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_86_64) machine = MACH_X86; else if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_PPC64) machine = MACH_PPC; else if (bits == ~__AUDIT_ARCH_64BIT && machine == MACH_S390X) machine = MACH_S390; /* Check for errors - return -6 * We don't allow 32 bit machines to specify * 64 bit. */ switch (machine) { case MACH_X86: if (bits == __AUDIT_ARCH_64BIT) return -6; break; case MACH_IA64: if (bits == ~__AUDIT_ARCH_64BIT) return -6; break; case MACH_PPC: if (bits == __AUDIT_ARCH_64BIT) return -6; break; case MACH_S390: if (bits == __AUDIT_ARCH_64BIT) return -6; break; #ifdef WITH_ARMEB case MACH_ARMEB: if (bits == __AUDIT_ARCH_64BIT) return -6; break; #endif #ifdef WITH_AARCH64 case MACH_AARCH64: if (bits != __AUDIT_ARCH_64BIT) return -6; break; #endif case MACH_86_64: /* fallthrough */ case MACH_PPC64: /* fallthrough */ case MACH_S390X: /* fallthrough */ break; default: return -6; } /* OK, we have the machine type, now convert to elf. */ elf = audit_machine_to_elf(machine); if (elf == 0) return -5; _audit_elf = elf; } rule->values[rule->field_count] = _audit_elf; _audit_archadded = 1; break; case AUDIT_PERM: if (flags != AUDIT_FILTER_EXIT) return -7; else if (op != AUDIT_EQUAL) return -13; else { unsigned int i, len, val = 0; len = strlen(v); if (len > 4) return -11; for (i = 0; i < len; i++) { switch (tolower(v[i])) { case 'r': val |= AUDIT_PERM_READ; break; case 'w': val |= AUDIT_PERM_WRITE; break; case 'x': val |= AUDIT_PERM_EXEC; break; case 'a': val |= AUDIT_PERM_ATTR; break; default: return -14; } } rule->values[rule->field_count] = val; } break; case AUDIT_FILETYPE: if (!(flags == AUDIT_FILTER_EXIT || flags == AUDIT_FILTER_ENTRY)) return -17; rule->values[rule->field_count] = audit_name_to_ftype(v); if ((int)rule->values[rule->field_count] < 0) { return -16; } break; case AUDIT_ARG0...AUDIT_ARG3: vlen = strlen(v); if (isdigit((char)*(v))) rule->values[rule->field_count] = strtoul(v, NULL, 0); else if (vlen >= 2 && *(v)=='-' && (isdigit((char)*(v+1)))) rule->values[rule->field_count] = strtol(v, NULL, 0); else return -21; break; case AUDIT_DEVMAJOR...AUDIT_INODE: case AUDIT_SUCCESS: if (flags != AUDIT_FILTER_EXIT) return -7; /* fallthrough */ default: if (field == AUDIT_INODE) { if (!(op == AUDIT_NOT_EQUAL || op == AUDIT_EQUAL)) return -13; } if (field == AUDIT_PPID && !(flags == AUDIT_FILTER_EXIT || flags == AUDIT_FILTER_ENTRY)) return -17; if (!isdigit((char)*(v))) return -21; if (field == AUDIT_INODE) rule->values[rule->field_count] = strtoul(v, NULL, 0); else rule->values[rule->field_count] = strtol(v, NULL, 0); break; } rule->field_count++; return 0; }