static void process_bootup(auparse_state_t *au) { lnode *cur; int start; // See if we have unclosed boot up and make into CRASH record list_first(&l); cur = list_get_cur(&l); while (cur) { if (cur->name) { cur->user_end_proof = auparse_get_serial(au); cur->status = CRASH; cur->end = auparse_get_time(au); report_session(cur); } cur = list_next(&l); } // Logout and process anyone still left in the machine list_first(&l); cur = list_get_cur(&l); while (cur) { if (cur->status != CRASH) { cur->user_end_proof = auparse_get_serial(au); cur->status = DOWN; cur->end = auparse_get_time(au); report_session(cur); } cur = list_next(&l); } // Since this is a boot message, all old entries should be gone list_clear(&l); list_create(&l); // make reboot record - user:reboot, tty:system boot, host: kernel start = auparse_get_time(au); list_create_session(&l, 0, 0, 0, auparse_get_serial(au)); cur = list_get_cur(&l); cur->start = start; cur->name = strdup("reboot"); cur->term = strdup("system boot"); if (kernel) cur->host = strdup(kernel); cur->result = 0; }
static void process_bootup(auparse_state_t *au) { lnode *cur; int start; struct utsname ubuf; // See if we have unclosed boot up and make into CRASH record list_first(&l); cur = list_get_cur(&l); while(cur) { if (cur->name) { cur->user_end_proof = auparse_get_serial(au); cur->status = CRASH; cur->end = auparse_get_time(au); report_session(cur); } cur = list_next(&l); } // Logout and process anyone still left in the machine list_first(&l); cur = list_get_cur(&l); while(cur) { if (cur->status != CRASH) { cur->user_end_proof = auparse_get_serial(au); cur->status = DOWN; cur->end = auparse_get_time(au); report_session(cur); } cur = list_next(&l); } list_clear(&l); list_create(&l); // make reboot record - user:reboot, tty:system boot, host: uname -r uname(&ubuf); start = auparse_get_time(au); list_create_session(&l, 0, 0, 0, auparse_get_serial(au)); cur = list_get_cur(&l); cur->start = start; cur->name = strdup("reboot"); cur->term = strdup("system boot"); cur->host = strdup(ubuf.release); cur->result = 0; }
static void create_new_session(auparse_state_t *au) { const char *tpid, *tses, *tauid; int pid = -1, auid = -1, ses = -1; lnode *cur; // Get pid tpid = auparse_find_field(au, "pid"); if (tpid) pid = auparse_get_field_int(au); // Get second auid field auparse_find_field(au, "auid"); auparse_next_field(au); tauid = auparse_find_field(au, "auid"); if (tauid) auid = auparse_get_field_int(au); // Get second ses field auparse_find_field(au, "ses"); auparse_next_field(au); tses = auparse_find_field(au, "ses"); if (tses) ses = auparse_get_field_int(au); // Check that they are valid if (pid == -1 || auid ==-1 || ses == -1) { if (debug) fprintf(stderr, "Bad login for event: %lu\n", auparse_get_serial(au)); return; } // See if this session is already open //cur = list_find_auid(&l, auid, pid, ses); cur = list_find_session(&l, ses); if (cur) { // This means we have an open session close it out cur->status = GONE; cur->end = auparse_get_time(au); report_session(cur); list_delete_cur(&l); } // If this is supposed to be limited to a specific // uid and we don't have that record, skip creating it if (cuid != -1 && cuid != auid) { if (debug) fprintf(stderr, "login reporting limited to %d for event: %lu\n", cuid, auparse_get_serial(au)); return; } list_create_session(&l, auid, pid, ses, auparse_get_serial(au)); }
/* Extract the most common fields from virtualization-related records. */ int extract_virt_fields(auparse_state_t *au, const char **p_uuid, uid_t *p_uid, time_t *p_time, const char **p_name, int *p_suc) { const char *field; auparse_first_record(au); /* Order matters */ if (p_uid) { if (!auparse_find_field(au, field = "uid")) goto error; *p_uid = auparse_get_field_int(au); } if (p_name) { if (!auparse_find_field(au, field = "vm")) goto error; *p_name = auparse_interpret_field(au); } if (p_uuid) { if (!auparse_find_field(au, field = "uuid")) goto error; *p_uuid = auparse_get_field_str(au); } if (p_suc) { const char *res = auparse_find_field(au, field = "res"); if (res == NULL) goto error; *p_suc = (strcmp("success", res) == 0) ? 1 : 0; } if (p_time) { *p_time = auparse_get_time(au); } return 0; error: if (debug) { fprintf(stderr, "Failed to get field \"%s\" for record " "%ld.%03u:%lu\n", field ? field : "", auparse_get_time(au), auparse_get_milli(au), auparse_get_serial(au)); } return 1; }
static void update_session_logout(auparse_state_t *au) { const char *tses, *tauid, *tpid; int pid = -1, auid = -1, ses = -1; lnode *cur; // Get pid field tpid = auparse_find_field(au, "pid"); if (tpid) pid = auparse_get_field_int(au); // Get auid field tauid = auparse_find_field(au, "auid"); if (tauid) auid = auparse_get_field_int(au); // Get ses field tses = auparse_find_field(au, "ses"); if (tses) ses = auparse_get_field_int(au); // Check that they are valid if (pid == -1 || auid ==-1 || ses == -1) { if (debug) fprintf(stderr, "Bad user logout for event: %lu\n", auparse_get_serial(au)); return; } // See if this session is already open cur = list_find_auid(&l, auid, pid, ses); if (cur) { // if time never got updated, this must be a cron or su // session...so we will just delete it. if (cur->start) { // This means we have an open session close it out time_t end = auparse_get_time(au); list_update_logout(&l, end, auparse_get_serial(au)); report_session(cur); } else if (debug) fprintf(stderr, "start time error for event: %lu\n", auparse_get_serial(au)); list_delete_cur(&l); } }
static void process_shutdown(auparse_state_t *au) { lnode *cur; // Find reboot record list_first(&l); cur = list_get_cur(&l); while (cur) { if (cur->name) { // Found it - close it out and display it time_t end = auparse_get_time(au); list_update_logout(&l, end, auparse_get_serial(au)); report_session(cur); list_delete_cur(&l); return; } cur = list_next(&l); } }
int add_proof(struct event *event, auparse_state_t *au) { if (!proof_flag) return 0; size_t i, proof_len = sizeof(event->proof)/sizeof(event->proof[0]); for (i = 0; i < proof_len; i++) { if (event->proof[i].time == 0) break; } if (i == proof_len) { if (debug) fprintf(stderr, "Failed to add proof.\n"); return 1; } event->proof[i].time = auparse_get_time(au); event->proof[i].milli = auparse_get_milli(au); event->proof[i].serial = auparse_get_serial(au); return 0; }
static void update_session_login(auparse_state_t *au) { const char *tpid, *tses, *tuid, *tacct=NULL, *host, *term, *tres; int pid = -1, uid = -1, ses = -1, result = -1; time_t start; lnode *cur; // Get pid tpid = auparse_find_field(au, "pid"); if (tpid) pid = auparse_get_field_int(au); // Get ses field tses = auparse_find_field(au, "ses"); if (tses) ses = auparse_get_field_int(au); // Get second uid field - we should be positioned past the first one // gdm sends uid, everything else sends id, we try acct as last resort tuid = auparse_find_field(au, "uid"); if (tuid) uid = auparse_get_field_int(au); else { auparse_first_record(au); tuid = auparse_find_field(au, "id"); if (tuid) uid = auparse_get_field_int(au); else { auparse_first_record(au); tuid = auparse_find_field(au, "acct"); if (tuid) { const char *tacct = auparse_interpret_field(au); struct passwd *pw = getpwnam (tacct); if (pw != NULL) uid = pw->pw_uid; } else auparse_first_record(au); } } start = auparse_get_time(au); host = auparse_find_field(au, "hostname"); if (host && strcmp(host, "?") == 0) host = auparse_find_field(au, "addr"); term = auparse_find_field(au, "terminal"); if (term == NULL) term = "?"; tres = auparse_find_field(au, "res"); if (tres) tres = auparse_interpret_field(au); if (tres) { if (strcmp(tres, "success") == 0) result = 0; else result = 1; } // We only get tacct when its a bad login if (result == 1) { auparse_first_record(au); tacct = auparse_find_field(au, "acct"); if (tacct) tacct = auparse_interpret_field(au); } else { // Check that they are valid if (pid == -1 || uid ==-1 || ses == -1) { if (debug) fprintf(stderr, "Bad user login for event: %lu\n", auparse_get_serial(au)); return; } } // See if this session is already open if (result == 0) cur = list_find_auid(&l, uid, pid, ses); else cur = NULL; if (cur) { // If we are limited to a specific terminal and // we find out the session is not associated with // the terminal of interest, delete the current node if (cterm && strstr(term, cterm) == NULL) { list_delete_cur(&l); if (debug) fprintf(stderr, "User login limited to %s for event: %lu\n", cterm, auparse_get_serial(au)); return; } // This means we have an open session - update it list_update_start(&l, start, host, term, result, auparse_get_serial(au)); // If the results were failed, we can close it out /* FIXME: result cannot be true. This is dead code. if (result) { report_session(cur); list_delete_cur(&l); } */ } else if (bad == 1 && result == 1) { // If it were a bad login and we are wanting bad logins // create the record and report it. lnode n; n.auid = uid; n.start = start; n.end = start; n.name = tacct; n.host = host; n.term = term; n.result = result; n.status = LOG_OUT; n.loginuid_proof = auparse_get_serial(au); report_session(&n); } }
/* This function will output a normalized line of audit * fields one line per event as an english sentence */ static void text_event(auparse_state_t *au, auparse_cb_event_t cb_event_type, void *user_data) { if (cb_event_type != AUPARSE_CB_EVENT_READY) return; char tmp[20]; const char *item, *action, *how; int rc, type, id = -2; time_t t = auparse_get_time(au); struct tm *tv = localtime(&t); if (tv) strftime(tmp, sizeof(tmp), "%T %x", tv); else strcpy(tmp, "?"); type = auparse_get_type(au); auparse_normalize(au, NORM_OPT_NO_ATTRS); item = auparse_get_node(au); if (item) { printf("On %s at %s ", auparse_interpret_field(au), tmp); free((void *)item); } else printf("At %s ", tmp); rc = auparse_normalize_subject_primary(au); if (rc == 1) { const char *subj = auparse_interpret_field(au); id = auparse_get_field_int(au); if (strcmp(subj, "unset") == 0) subj = "system"; printf("%s", subj); } // Need to compare auid and uid before doing this rc = auparse_normalize_subject_secondary(au); if (rc == 1) { int uid = auparse_get_field_int(au); if (uid != id && id != -2) printf(", acting as %s,", auparse_interpret_field(au)); } rc = auparse_normalize_get_results(au); if (rc == 1) { int i = 0; const char *res[] = { "unsuccessfully", "successfully" }; item = auparse_interpret_field(au); if (strcmp(item, "yes") == 0) i = 1; else if (strncmp(item, "suc", 3) == 0) i = 1; else if (auparse_get_field_type(au) == AUPARSE_TYPE_SECCOMP && strcmp(item, "allow") == 0) i = 1; printf(" %s ", res[i]); } else putchar(' '); action = auparse_normalize_get_action(au); if (event_debug) { if (action == NULL) printf("error on type:%d\n", type); } printf("%s ", action ? action : "did-unknown"); rc = auparse_normalize_object_primary(au); if (rc == 1) { const char *val = NULL; int ftype; // If we have an object and this is an AVC, add some words if (action && strstr(action, "violated")) val = "accessing "; ftype = auparse_get_field_type(au); if (ftype == AUPARSE_TYPE_ESCAPED_FILE) val = auparse_interpret_realpath(au); else if (ftype == AUPARSE_TYPE_SOCKADDR) { val = auparse_interpret_sock_address(au); if (val == NULL) val = auparse_interpret_sock_family(au); } if (val == NULL) val = auparse_interpret_field(au); printf("%s ", val); } rc = auparse_normalize_object_primary2(au); if (rc == 1) { const char *val; if (auparse_get_field_type(au) == AUPARSE_TYPE_ESCAPED_FILE) val = auparse_interpret_realpath(au); else val = auparse_interpret_field(au); printf("to %s ", val); } how = auparse_normalize_how(au); if (how && action && *action != 'e') // Don't print for ended-session printf("using %s", how); printf("\n"); }
static void csv_event(auparse_state_t *au, auparse_cb_event_t cb_event_type, void *user_data) { if (cb_event_type != AUPARSE_CB_EVENT_READY) return; if (csv_header_done == 0) { csv_header_done = 1; printf( "NODE,EVENT,DATE,TIME,%sSERIAL_NUM,EVENT_KIND," "SESSION,SUBJ_PRIME,SUBJ_SEC,SUBJ_KIND,%sACTION," "RESULT,OBJ_PRIME,OBJ_SEC,%s%sOBJ_KIND,HOW%s\n", extra_time ? "YEAR,MONTH,DAY,WEEKDAY,HOUR,GMT_OFFSET," : "", extra_labels ? "SUBJ_LABEL," : "", extra_obj2 ? "OBJ2," : "", extra_labels ? "OBJ_LABEL," : "", extra_keys ? ",KEY" : ""); } char tmp[20]; const char *item, *type, *evkind, *subj_kind, *action, *str, *how; int rc; time_t t = auparse_get_time(au); struct tm *tv = localtime(&t); // NODE item = auparse_get_node(au); if (item) { printf("%s", auparse_interpret_field(au)); free((void *)item); } putchar(','); // Event type = auparse_get_type_name(au); if (type) printf("%s", type); putchar(','); // Normalize rc = auparse_normalize(au, extra_labels ? NORM_OPT_ALL : NORM_OPT_NO_ATTRS); //DATE if (tv) { strftime(tmp, sizeof(tmp), "%x", tv); printf("%s", tmp); } putchar(','); // TIME if (tv) { strftime(tmp, sizeof(tmp), "%T", tv); printf("%s", tmp); } putchar(','); if (extra_time) { // YEAR if (tv) { strftime(tmp, sizeof(tmp), "%Y", tv); printf("%s", tmp); } putchar(','); // MONTH if (tv) { strftime(tmp, sizeof(tmp), "%m", tv); printf("%s", tmp); } putchar(','); // DAY if (tv) { strftime(tmp, sizeof(tmp), "%d", tv); printf("%s", tmp); } putchar(','); // WEEKDAY if (tv) { strftime(tmp, sizeof(tmp), "%u", tv); printf("%s", tmp); } putchar(','); // HOUR if (tv) { strftime(tmp, sizeof(tmp), "%k", tv); printf("%s", tmp); } putchar(','); if (tv) { char sign = tv->tm_gmtoff >= 0 ? '+' : '-'; unsigned long total = labs(tv->tm_gmtoff); unsigned long hour = total/3600; unsigned long min = (total - (hour * 3600))%60; printf("%c%02lu:%02lu", sign, hour, min); } putchar(','); } // SERIAL_NUMBER printf("%lu,", auparse_get_serial(au)); if (rc) { fprintf(stderr, "error normalizing %s\n", type); // Just dump an empty frame printf(",,,,,,,,,%s%s\n", extra_labels ? ",," : "", extra_keys ? "," : ""); return; } // EVENT_KIND evkind = auparse_normalize_get_event_kind(au); printf("%s", evkind ? evkind : "unknown"); putchar(','); // SESSION rc = auparse_normalize_session(au); if (rc == 1) printf("%s", auparse_interpret_field(au)); putchar(','); // SUBJ_PRIME rc = auparse_normalize_subject_primary(au); if (rc == 1) { const char *subj = auparse_interpret_field(au); if (strcmp(subj, "unset") == 0) subj = "system"; printf("%s", subj); } putchar(','); // SUBJ_SEC rc = auparse_normalize_subject_secondary(au); if (rc == 1) printf("%s", auparse_interpret_field(au)); putchar(','); // SUBJ_KIND subj_kind = auparse_normalize_subject_kind(au); if (subj_kind) printf("%s", subj_kind); putchar(','); // SUBJ_LABEL if (extra_labels) { rc = auparse_normalize_subject_first_attribute(au); do { if (rc == 1) { const char *name = auparse_get_field_name(au); if (strcmp(name, "subj") == 0) { printf("%s", auparse_interpret_field(au)); break; } } } while (auparse_normalize_subject_next_attribute(au) == 1); putchar(','); } // ACTION action = auparse_normalize_get_action(au); printf("%s", action ? action : "did-unknown"); putchar(','); // RESULT rc = auparse_normalize_get_results(au); if (rc == 1) { int i = 0; const char *res[] = { "failed", "success" }; item = auparse_interpret_field(au); if (strcmp(item, "yes") == 0) i = 1; else if (strncmp(item, "suc", 3) == 0) i = 1; else if (auparse_get_field_type(au) == AUPARSE_TYPE_SECCOMP && strcmp(item, "allow") == 0) i = 1; printf("%s", res[i]); } putchar(','); // OBJ_PRIME rc = auparse_normalize_object_primary(au); if (rc == 1) { const char *val; if (auparse_get_field_type(au) == AUPARSE_TYPE_ESCAPED_FILE) val = auparse_interpret_realpath(au); else val = auparse_interpret_field(au); printf("%s", val); } putchar(','); // OBJ_SEC rc = auparse_normalize_object_secondary(au); if (rc == 1) printf("%s", auparse_interpret_field(au)); putchar(','); // OBJECT 2 if (extra_obj2) { rc = auparse_normalize_object_primary2(au); if (rc == 1) { const char *val; if (auparse_get_field_type(au) == AUPARSE_TYPE_ESCAPED_FILE) val = auparse_interpret_realpath(au); else val = auparse_interpret_field(au); printf("%s", val); } putchar(','); } // OBJ_LABEL if (extra_labels) { rc = auparse_normalize_object_first_attribute(au); do { if (rc == 1) { const char *name = auparse_get_field_name(au); if (strcmp(name, "obj") == 0) { printf("%s", auparse_interpret_field(au)); break; } } } while (auparse_normalize_object_next_attribute(au) == 1); putchar(','); } // OBJ_KIND str = auparse_normalize_object_kind(au); printf("%s,", str); // HOW how = auparse_normalize_how(au); if (how) printf("%s", how); // KEY if (extra_keys) { putchar(','); // This is to close out HOW rc = auparse_normalize_key(au); if (rc == 1) printf("%s", auparse_interpret_field(au)); } printf("\n"); }