// Returns < 0 on error, 0 no data, > 0 success int ausearch_next_event(auparse_state_t *au) { int rc; if (au->expr == NULL) { errno = EINVAL; return -1; } if (au->expr->started == 0) { if ((rc = auparse_first_record(au)) <= 0) return rc; au->expr->started = 1; } else { if ((rc = auparse_next_event(au)) <= 0) return rc; } do { do { if ((rc = ausearch_compare(au)) > 0) { ausearch_reposition_cursors(au); return 1; } else if (rc < 0) return rc; } while ((rc = auparse_next_record(au)) > 0); if (rc < 0) return rc; } while ((rc = auparse_next_event(au)) > 0); if (rc < 0) return rc; return 0; }
/* Functions that traverse records in the same event */ int auparse_first_record(auparse_state_t *au) { int rc; rnode *r; // Its OK if au->le == NULL because get_cnt handles it if (aup_list_get_cnt(au->le) == 0) { // This function loads interpretations rc = auparse_next_event(au); if (rc <= 0) return rc; } aup_list_first(au->le); r = aup_list_get_cur(au->le); free_interpretation_list(); load_interpretation_list(r->interp); aup_list_first_field(au->le); return 1; }
static void consume_feed(auparse_state_t *au, int flush) { //if (debug) printf("consume feed, flush %d\n", flush); while (auparse_next_event(au) > 0) { if (au->callback) { (*au->callback)(au, AUPARSE_CB_EVENT_READY, au->callback_user_data); } } if (flush) { // FIXME: might need a call here to force auparse_next_event() // to consume any partial data not fully consumed. /* Terminate all outstanding events, as we are at end of input * (ie mark BUILDING events as COMPLETE events) then if we * have a callback execute the callback on each event * FIXME: Should we implement a 'checkpoint' concept as per * ausearch or accept these 'partial' events? */ event_list_t *l; //if (debug) printf("terminate all events in flush\n"); au_terminate_all_events(au); while ((l = au_get_ready_event(au, 0)) != NULL) { rnode *r; au->le = l; // make this current the event of interest aup_list_first(l); r = aup_list_get_cur(l); free_interpretation_list(); load_interpretation_list(r->interp); aup_list_first_field(l); if (au->callback) { (*au->callback)(au, AUPARSE_CB_EVENT_READY, au->callback_user_data); } } } }
int main(int argc, char *argv[]) { int i, use_stdin = 0; char *user = NULL, *file = NULL; struct passwd *p; auparse_state_t *au; setlocale (LC_ALL, ""); for (i=1; i<argc; i++) { if (argv[i][0] != '-') { //take input and lookup as if it were a user name //if that fails assume its a tty if (user == NULL) { p = getpwnam(argv[i]); if (p) { cuid = p->pw_uid; user = argv[i]; continue; } } if (cterm == NULL) { cterm = argv[i]; } else { usage(); return 1; } } else { if (strcmp(argv[i], "-f") == 0) { if (use_stdin == 0) { i++; file = argv[i]; } else { fprintf(stderr,"stdin already given\n"); return 1; } } else if (strcmp(argv[i], "--bad") == 0) { bad = 1; } else if (strcmp(argv[i], "--proof") == 0) { proof = 1; } else if (strcmp(argv[i], "--extract") == 0) { f = fopen("aulast.log", "wt"); } else if (strcmp(argv[i], "--stdin") == 0) { if (file == NULL) use_stdin = 1; else { fprintf(stderr, "file already given\n"); return 1; } } else if (strcmp(argv[i], "--debug") == 0) { debug = 1; } else { usage(); return 1; } } } list_create(&l); // Search for successful user logins if (file) au = auparse_init(AUSOURCE_FILE, file); else if (use_stdin) au = auparse_init(AUSOURCE_FILE_POINTER, stdin); else { if (getuid()) { fprintf(stderr, "You probably need to be root for this to work\n"); } au = auparse_init(AUSOURCE_LOGS, NULL); } if (au == NULL) { fprintf(stderr, "Error - %s\n", strerror(errno)); goto error_exit_1; } // The theory: iterate though events // 1) when LOGIN is found, create a new session node // 2) if that session number exists, close out the old one // 3) when USER_LOGIN is found, update session node // 4) When USER_END is found update session node and close it out // 5) When BOOT record found make new record and check for previous // 6) If previous boot found, set status to crash and logout everyone // 7) When SHUTDOWN found, close out reboot record while (auparse_next_event(au) > 0) { // We will take advantage of the fact that all events // of interest are one record long int type = auparse_get_type(au); if (type < 0) continue; switch (type) { case AUDIT_LOGIN: create_new_session(au); extract_record(au); break; case AUDIT_USER_LOGIN: update_session_login(au); extract_record(au); break; case AUDIT_USER_END: update_session_logout(au); extract_record(au); break; case AUDIT_SYSTEM_BOOT: process_bootup(au); extract_record(au); break; case AUDIT_SYSTEM_SHUTDOWN: process_shutdown(au); extract_record(au); break; case AUDIT_DAEMON_START: process_kernel(au); extract_record(au); break; } } auparse_destroy(au); // Now output the leftovers list_first(&l); do { lnode *cur = list_get_cur(&l); report_session(cur); } while (list_next(&l)); free(kernel); list_clear(&l); if (f) fclose(f); return 0; error_exit_1: list_clear(&l); if (f) fclose(f); return 1; }
int main(int argc, char **argv) { int rc = 0; auparse_state_t *au = NULL; setlocale(LC_ALL, ""); if (parse_args(argc, argv)) goto error; if (help_flag) { usage(stdout); goto exit; } /* Initialize event list*/ events = list_new((list_free_data_fn*) event_free); if (events == NULL) goto unexpected_error; /* Initialize auparse */ au = init_auparse(); if (au == NULL) goto error; if (create_search_criteria(au)) goto error; while (ausearch_next_event(au) > 0) { int err = 0; switch(auparse_get_type(au)) { case AUDIT_VIRT_MACHINE_ID: err = process_machine_id_event(au); break; case AUDIT_VIRT_CONTROL: err = process_control_event(au); break; case AUDIT_VIRT_RESOURCE: err = process_resource_event(au); break; case AUDIT_AVC: err = process_avc(au); break; case AUDIT_FIRST_ANOM_MSG ... AUDIT_LAST_ANOM_MSG: case AUDIT_FIRST_KERN_ANOM_MSG ... AUDIT_LAST_KERN_ANOM_MSG: err = process_anom(au); break; case AUDIT_SYSTEM_SHUTDOWN: err = process_shutdown(au); break; } if (err) { goto unexpected_error; } auparse_next_event(au); } /* Show results */ if (summary_flag) { print_summary(); } else { print_events(); } /* success */ goto exit; unexpected_error: fprintf(stderr, "Unexpected error\n"); error: rc = 1; exit: if (au) auparse_destroy(au); list_free(events); if (debug) fprintf(stdout, "Exit code: %d\n", rc); return rc; }
int main(int argc, char **argv) { /* we're probably going to be started by auditd so, you know, whatever */ /* set up stdin to be searched ruthlessly */ FILE *log; auparse_state_t *auparse; uint32_t syscall; int auid, uid; int wtf; uint32_t _argc, i; const char *exe, *path, *success; char *cmdline, *tmp_cmd; char _argv[8]; struct passwd *au, *u; char *real_user, *apparent_user; _argc = 0; cmdline = NULL; log = fopen("/tmp/exemon.log", "w"); /* auparse = auparse_init(AUSOURCE_LOGS, NULL); */ auparse = auparse_init(AUSOURCE_FILE_POINTER, stdin); if (!auparse) { fprintf(log, "Couldn't do the thing with the thing.\n"); exit(1); } while ((wtf = auparse_next_event(auparse)) > 0) { /* Start fresh */ auid = -1; uid = -1; exe = NULL; path = NULL; success = NULL; _argc = 0; if (cmdline) free(cmdline); cmdline = NULL; /* Now we're doing the thing */ /* auparse_first_field(auparse); */ /* auparse_first_record(auparse); */ auparse_first_field(auparse); if (auparse_find_field(auparse, "syscall")) { syscall = auparse_get_field_int(auparse); if (syscall == 59 || syscall == 11) { if (auparse_exhaustive_find_field(auparse, "auid")) { auid = auparse_get_field_int(auparse); au = getpwuid(auid); if (au) real_user = strdup(au->pw_name); else asprintf(&real_user, "UID_%i", auid); au = NULL; } if (auparse_exhaustive_find_field(auparse, "uid")) { uid = auparse_get_field_int(auparse); u = getpwuid(uid); if (u) apparent_user = strdup(u->pw_name); else asprintf(&apparent_user, "UID_%i", uid); u = NULL; } if (auparse_exhaustive_find_field(auparse, "success")) success = auparse_get_field_str(auparse); if (auparse_exhaustive_find_field(auparse, "exe")) exe = auparse_get_field_str(auparse); if (auparse_exhaustive_find_field(auparse, "argc")) { _argc = auparse_get_field_int(auparse); for (i = 0; i < _argc; i++) { snprintf(_argv, 8, "a%i", i); if (auparse_find_field(auparse, _argv)) { if (!cmdline) asprintf(&cmdline, "%s", auparse_interpret_field(auparse)); else { asprintf(&tmp_cmd, "%s %s", cmdline, auparse_interpret_field(auparse)); free(cmdline); /* avoid leaking cmdline */ cmdline = tmp_cmd; } } } } if (auparse_exhaustive_find_field(auparse, "cwd")) path = auparse_get_field_str(auparse); else path = strdup("(unknown)"); if (exe && uid >= 0 && path && success) { if (auid == uid || auid == -1) { if (cmdline && (success[0] == 'y' || success[0] == 'Y')) { fprintf(log, "%s ran %s in path %s with args: %s\n", apparent_user, exe, path, cmdline); } else { fprintf(log, "%s failed to run %s in path %s\n", apparent_user, exe, path); if (!cmdline) { fprintf(log, "note: no cmdline: record: \n"); auparse_dump_records(auparse, log); } } } else { if (cmdline && (success[0] == 'y' || success[0] == 'Y')) { fprintf(log, "%s (as %s) ran %s in path %s with args: %s\n", real_user, apparent_user, exe, path, cmdline); } else { fprintf(log, "%s (as %s) failed to run %s in path %s\n", real_user, apparent_user, exe, path); } } } else { fprintf(log, "Incomplete record? path = %x, success = %x, uid = %i, exe = %x\n", path, success, uid, exe); fprintf(log, "record:\n"); auparse_dump_records(auparse, log); } fflush(log); /* avoid leaking on usernames and unknown paths */ free(apparent_user); free(real_user); if (path[0] == '(') { free(path); path = NULL; } apparent_user = NULL; real_user = NULL; } } } fprintf(log, "destroyed\n"); fclose(log); auparse_destroy(auparse); return 0; }