#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#include <errno.h>
#include "libaudit.h"
#include "auparse.h"
static const char *buf[] = {
"type=LOGIN msg=audit(1143146623.787:142): login pid=2027 uid=0 old auid=4294967295 new auid=848\n"
"type=SYSCALL msg=audit(1143146623.875:143): arch=c000003e syscall=188 success=yes exit=0 a0=7fffffa9a9f0 a1=3958d11333 a2=5131f0 a3=20 items=1 pid=2027 auid=848 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty3 comm=\"login\" exe=\"/bin/login\" subj=system_u:system_r:local_login_t:s0-s0:c0.c255\n",
"type=USER_LOGIN msg=audit(1143146623.879:146): user pid=2027 uid=0 auid=848 msg=\'uid=848: exe=\"/bin/login\" (hostname=?, addr=?, terminal=tty3 res=success)\'\n",
NULL
};
unsigned int walked_fields = 0;
#define FIELDS_EXPECTED 403
static void walk_test(auparse_state_t *au)
{
int event_cnt = 1, record_cnt;
do {
if (auparse_first_record(au) <= 0) {
printf("Error getting first record (%s)\n",
strerror(errno));
exit(1);
}
printf("event %d has %u records\n", event_cnt,
auparse_get_num_records(au));
record_cnt = 1;
do {
printf(" record %d of type %d(%s) has %u fields\n",
record_cnt,
auparse_get_type(au),
audit_msg_type_to_name(auparse_get_type(au)),
auparse_get_num_fields(au));
printf(" line=%u file=%s\n",
auparse_get_line_number(au),
auparse_get_filename(au) ?
auparse_get_filename(au) : "None");
const au_event_t *e = auparse_get_timestamp(au);
if (e == NULL) {
printf("Error getting timestamp - aborting\n");
exit(1);
}
printf(" event time: %u.%u:%lu, host=%s\n",
(unsigned)e->sec,
e->milli, e->serial, e->host ? e->host : "?");
auparse_first_field(au);
do {
printf(" %s=%s (%s)\n",
auparse_get_field_name(au),
auparse_get_field_str(au),
auparse_interpret_field(au));
walked_fields++;
} while (auparse_next_field(au) > 0);
printf("\n");
record_cnt++;
} while(auparse_next_record(au) > 0);
event_cnt++;
} while (auparse_next_event(au) > 0);
}
void light_test(auparse_state_t *au)
{
int record_cnt;
do {
if (auparse_first_record(au) <= 0) {
puts("Error getting first record");
exit(1);
}
printf("event has %u records\n", auparse_get_num_records(au));
record_cnt = 1;
do {
printf(" record %d of type %d(%s) has %u fields\n",
record_cnt,
auparse_get_type(au),
audit_msg_type_to_name(auparse_get_type(au)),
auparse_get_num_fields(au));
printf(" line=%u file=%s\n",
auparse_get_line_number(au),
auparse_get_filename(au) ?
auparse_get_filename(au) : "None");
const au_event_t *e = auparse_get_timestamp(au);
if (e == NULL) {
printf("Error getting timestamp - aborting\n");
exit(1);
}
printf(" event time: %u.%u:%lu, host=%s\n",
(unsigned)e->sec,
e->milli, e->serial,
e->host ? e->host : "?");
printf("\n");
record_cnt++;
} while(auparse_next_record(au) > 0);
} while (auparse_next_event(au) > 0);
}
void simple_search(ausource_t source, austop_t where)
{
auparse_state_t *au;
const char *val;
if (source == AUSOURCE_FILE) {
au = auparse_init(AUSOURCE_FILE, "./test.log");
val = "4294967295";
} else {
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
val = "848";
}
if (au == NULL) {
printf("auparse_init error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_add_item(au, "auid", "=", val, AUSEARCH_RULE_CLEAR)){
printf("ausearch_add_item error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_set_stop(au, where)){
printf("ausearch_set_stop error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_next_event(au) <= 0)
printf("Error searching for auid - %s\n", strerror(errno));
else
printf("Found %s = %s\n", auparse_get_field_name(au),
auparse_get_field_str(au));
auparse_destroy(au);
}
void compound_search(ausearch_rule_t how)
{
auparse_state_t *au;
au = auparse_init(AUSOURCE_FILE, "./test.log");
if (au == NULL) {
printf("auparse_init error - %s\n", strerror(errno));
exit(1);
}
if (how == AUSEARCH_RULE_AND) {
if (ausearch_add_item(au, "uid", "=", "0",
AUSEARCH_RULE_CLEAR)){
printf("ausearch_add_item 1 error - %s\n",
strerror(errno));
exit(1);
}
if (ausearch_add_item(au, "pid", "=", "13015", how)){
printf("ausearch_add_item 2 error - %s\n",
strerror(errno));
exit(1);
}
if (ausearch_add_item(au, "type", "=", "USER_START", how)){
printf("ausearch_add_item 3 error - %s\n",
strerror(errno));
exit(1);
}
} else {
if (ausearch_add_item(au, "auid", "=", "42",
AUSEARCH_RULE_CLEAR)){
printf("ausearch_add_item 4 error - %s\n",
strerror(errno));
exit(1);
}
if (ausearch_add_item(au, "auid", "=", "0", how)){
printf("ausearch_add_item 5 error - %s\n",
strerror(errno));
exit(1);
}
if (ausearch_add_item(au, "auid", "=", "500", how)){
printf("ausearch_add_item 6 error - %s\n",
strerror(errno));
exit(1);
}
}
if (ausearch_set_stop(au, AUSEARCH_STOP_FIELD)){
printf("ausearch_set_stop error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_next_event(au) <= 0)
printf("Error searching for auid - %s\n", strerror(errno));
else
printf("Found %s = %s\n", auparse_get_field_name(au),
auparse_get_field_str(au));
auparse_destroy(au);
}
void regex_search(const char *expr)
{
auparse_state_t *au;
int rc;
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
if (au == NULL) {
printf("auparse_init error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_add_regex(au, expr)){
printf("ausearch_add_regex error - %s\n", strerror(errno));
exit(1);
}
if (ausearch_set_stop(au, AUSEARCH_STOP_RECORD)){
printf("ausearch_set_stop error - %s\n", strerror(errno));
exit(1);
}
rc = ausearch_next_event(au);
if (rc < 0)
printf("Error searching for %s - %s\n", expr, strerror(errno));
else if (rc == 0)
printf("Not found\n");
else
printf("Found %s = %s\n", auparse_get_field_name(au),
auparse_get_field_str(au));
auparse_destroy(au);
}
static void auparse_callback(auparse_state_t *au, auparse_cb_event_t cb_event_type, void *user_data)
{
int *event_cnt = (int *)user_data;
int record_cnt;
if (cb_event_type == AUPARSE_CB_EVENT_READY) {
if (auparse_first_record(au) <= 0) {
printf("can't get first record\n");
return;
}
printf("event %d has %u records\n", *event_cnt,
auparse_get_num_records(au));
record_cnt = 1;
do {
printf(" record %d of type %d(%s) has %u fields\n",
record_cnt,
auparse_get_type(au),
audit_msg_type_to_name(auparse_get_type(au)),
auparse_get_num_fields(au));
printf(" line=%u file=%s\n",
auparse_get_line_number(au),
auparse_get_filename(au) ?
auparse_get_filename(au) : "None");
const au_event_t *e = auparse_get_timestamp(au);
if (e == NULL) {
return;
}
printf(" event time: %u.%u:%lu, host=%s\n",
(unsigned)e->sec,
e->milli, e->serial,
e->host ? e->host : "?");
auparse_first_field(au);
do {
printf(" %s=%s (%s)\n",
auparse_get_field_name(au),
auparse_get_field_str(au),
auparse_interpret_field(au));
} while (auparse_next_field(au) > 0);
printf("\n");
record_cnt++;
} while(auparse_next_record(au) > 0);
(*event_cnt)++;
}
}
int main(void)
{
char *files[3] = { "test.log", "test2.log", NULL };
setlocale (LC_ALL, "");
auparse_state_t *au;
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
printf("Starting Test 1, iterate...\n");
while (auparse_next_event(au) > 0) {
if (auparse_find_field(au, "auid")) {
printf("%s=%s\n", auparse_get_field_name(au),
auparse_get_field_str(au));
printf("interp auid=%s\n", auparse_interpret_field(au));
} else
printf("Error iterating to auid\n");
}
auparse_reset(au);
while (auparse_next_event(au) > 0) {
if (auparse_find_field(au, "auid")) {
do {
printf("%s=%s\n", auparse_get_field_name(au),
auparse_get_field_str(au));
printf("interp auid=%s\n", auparse_interpret_field(au));
} while (auparse_find_field_next(au));
} else
printf("Error iterating to auid\n");
}
printf("Test 1 Done\n\n");
printf("Starting Test 2, walk events, records, and fields...\n");
auparse_reset(au);
walk_test(au);
auparse_destroy(au);
printf("Test 2 Done\n\n");
printf("Starting Test 3, walk events, records of 1 buffer...\n");
au = auparse_init(AUSOURCE_BUFFER, buf[1]);
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
light_test(au);
auparse_destroy(au);
printf("Test 3 Done\n\n");
printf("Starting Test 4, walk events, records of 1 file...\n");
au = auparse_init(AUSOURCE_FILE, "./test.log");
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
walk_test(au);
auparse_destroy(au);
printf("Test 4 Done\n\n");
printf("Starting Test 5, walk events, records of 2 files...\n");
au = auparse_init(AUSOURCE_FILE_ARRAY, files);
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
walk_test(au);
auparse_destroy(au);
printf("Test 5 Done\n\n");
printf("Starting Test 6, search...\n");
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
if (ausearch_add_item(au, "auid", "=", "500", AUSEARCH_RULE_CLEAR)){
printf("Error - %s", strerror(errno));
return 1;
}
if (ausearch_set_stop(au, AUSEARCH_STOP_EVENT)){
printf("Error - %s", strerror(errno));
exit(1);
}
if (ausearch_next_event(au) != 0) {
printf("Error search found something it shouldn't have\n");
}
puts("auid = 500 not found...which is correct");
ausearch_clear(au);
auparse_destroy(au);
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
if (ausearch_add_item(au,"auid", "exists", NULL, AUSEARCH_RULE_CLEAR)){
printf("Error - %s", strerror(errno));
return 1;
}
if (ausearch_set_stop(au, AUSEARCH_STOP_EVENT)){
printf("Error - %s", strerror(errno));
exit(1);
}
if (ausearch_next_event(au) <= 0) {
printf("Error searching for existence of auid\n");
}
puts("auid exists...which is correct");
puts("Testing BUFFER_ARRAY, stop on field");
simple_search(AUSOURCE_BUFFER_ARRAY, AUSEARCH_STOP_FIELD);
puts("Testing BUFFER_ARRAY, stop on record");
simple_search(AUSOURCE_BUFFER_ARRAY, AUSEARCH_STOP_RECORD);
puts("Testing BUFFER_ARRAY, stop on event");
simple_search(AUSOURCE_BUFFER_ARRAY, AUSEARCH_STOP_EVENT);
puts("Testing test.log, stop on field");
simple_search(AUSOURCE_FILE, AUSEARCH_STOP_FIELD);
puts("Testing test.log, stop on record");
simple_search(AUSOURCE_FILE, AUSEARCH_STOP_RECORD);
puts("Testing test.log, stop on event");
simple_search(AUSOURCE_FILE, AUSEARCH_STOP_EVENT);
auparse_destroy(au);
printf("Test 6 Done\n\n");
printf("Starting Test 7, compound search...\n");
au = auparse_init(AUSOURCE_BUFFER_ARRAY, buf);
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
compound_search(AUSEARCH_RULE_AND);
compound_search(AUSEARCH_RULE_OR);
auparse_destroy(au);
printf("Test 7 Done\n\n");
printf("Starting Test 8, regex search...\n");
puts("Doing regex match...");
regex_search("1143146623");
puts("Doing regex wildcard search...");
regex_search("11431466.*146");
printf("Test 8 Done\n\n");
printf("Starting Test 9, buffer feed...\n");
{
int event_cnt = 1;
size_t len, chunk_len = 3;
const char **cur_buf, *p_beg, *p_end, *p_chunk_beg,
*p_chunk_end;
au = auparse_init(AUSOURCE_FEED, 0);
auparse_add_callback(au, auparse_callback, &event_cnt, NULL);
for (cur_buf = buf, p_beg = *cur_buf; *cur_buf;
cur_buf++, p_beg = *cur_buf) {
len = strlen(p_beg);
p_end = p_beg + len;
p_chunk_beg = p_beg;
while (p_chunk_beg < p_end) {
p_chunk_end = p_chunk_beg + chunk_len;
if (p_chunk_end > p_end)
p_chunk_end = p_end;
auparse_feed(au, p_chunk_beg,
p_chunk_end-p_chunk_beg);
p_chunk_beg = p_chunk_end;
}
}
auparse_flush_feed(au);
auparse_destroy(au);
}
printf("Test 9 Done\n\n");
printf("Starting Test 10, file feed...\n");
{
int *event_cnt = malloc(sizeof(int));
size_t len;
char filename[] = "./test.log";
char buf[4];
FILE *fp;
*event_cnt = 1;
au = auparse_init(AUSOURCE_FEED, 0);
auparse_add_callback(au, auparse_callback, event_cnt, free);
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "could not open '%s', %s\n",
filename, strerror(errno));
return 1;
}
while ((len = fread(buf, 1, sizeof(buf), fp))) {
auparse_feed(au, buf, len);
}
fclose(fp);
auparse_flush_feed(au);
auparse_destroy(au);
}
printf("Test 10 Done\n\n");
printf("Starting Test 11, walk LONG event records from a file...\n");
au = auparse_init(AUSOURCE_FILE, "test4.log");
if (au == NULL) {
printf("Error - %s\n", strerror(errno));
return 1;
}
walked_fields = 0;
walk_test(au);
auparse_destroy(au);
if (walked_fields != FIELDS_EXPECTED) {
printf("Error: %i fields expected, but %i read!\n",
FIELDS_EXPECTED, walked_fields);
}
printf("Test 11 Done\n\n");
puts("Finished non-admin tests\n");
return 0;
}