aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/auparse/auparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/auparse/auparse.c')
-rw-r--r--framework/src/audit/auparse/auparse.c1377
1 files changed, 0 insertions, 1377 deletions
diff --git a/framework/src/audit/auparse/auparse.c b/framework/src/audit/auparse/auparse.c
deleted file mode 100644
index cd3f1180..00000000
--- a/framework/src/audit/auparse/auparse.c
+++ /dev/null
@@ -1,1377 +0,0 @@
-/* auparse.c --
- * Copyright 2006-08,2012-15 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- */
-
-#include "config.h"
-#include "expression.h"
-#include "internal.h"
-#include "auparse.h"
-#include "interpret.h"
-#include "auparse-idata.h"
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio_ext.h>
-
-static int debug = 0;
-
-/* like strchr except string is delimited by length, not null byte */
-static char *strnchr(const char *s, int c, size_t n)
-{
- char *p_char;
- const char *p_end = s + n;
-
- for (p_char = (char *)s; p_char < p_end && *p_char != c; p_char++);
- if (p_char == p_end) return NULL;
- return p_char;
-}
-
-static int setup_log_file_array(auparse_state_t *au)
-{
- struct daemon_conf config;
- char *filename, **tmp;
- int len, num = 0, i = 0;
-
- /* Load config so we know where logs are */
- set_aumessage_mode(MSG_STDERR, DBG_NO);
- load_config(&config, TEST_SEARCH);
-
- /* for each file */
- len = strlen(config.log_file) + 16;
- filename = malloc(len);
- if (!filename) {
- fprintf(stderr, "No memory\n");
- free_config(&config);
- return 1;
- }
- /* Find oldest log file */
- snprintf(filename, len, "%s", config.log_file);
- do {
- if (access(filename, R_OK) != 0)
- break;
- num++;
- snprintf(filename, len, "%s.%d", config.log_file, num);
- } while (1);
-
- if (num == 0) {
- fprintf(stderr, "No log file\n");
- free_config(&config);
- free(filename);
- return 1;
- }
- num--;
- tmp = malloc((num+2)*sizeof(char *));
-
- /* Got it, now process logs from last to first */
- if (num > 0)
- snprintf(filename, len, "%s.%d", config.log_file, num);
- else
- snprintf(filename, len, "%s", config.log_file);
- do {
- tmp[i++] = strdup(filename);
-
- /* Get next log file */
- num--;
- if (num > 0)
- snprintf(filename, len, "%s.%d", config.log_file, num);
- else if (num == 0)
- snprintf(filename, len, "%s", config.log_file);
- else
- break;
- } while (1);
- free_config(&config);
- free(filename);
-
- // Terminate the list
- tmp[i] = NULL;
- au->source_list = tmp;
- return 0;
-}
-
-/* General functions that affect operation of the library */
-auparse_state_t *auparse_init(ausource_t source, const void *b)
-{
- char **tmp, **bb = (char **)b, *buf = (char *)b;
- int n, i;
- size_t size, len;
-
- auparse_state_t *au = malloc(sizeof(auparse_state_t));
- if (au == NULL) {
- errno = ENOMEM;
- return NULL;
- }
-
- au->in = NULL;
- au->source_list = NULL;
- databuf_init(&au->databuf, 0, 0);
- au->callback = NULL;
- au->callback_user_data = NULL;
- au->callback_user_data_destroy = NULL;
- switch (source)
- {
- case AUSOURCE_LOGS:
- if (geteuid()) {
- errno = EPERM;
- goto bad_exit;
- }
- setup_log_file_array(au);
- break;
- case AUSOURCE_FILE:
- if (access(b, R_OK))
- goto bad_exit;
- tmp = malloc(2*sizeof(char *));
- tmp[0] = strdup(b);
- tmp[1] = NULL;
- au->source_list = tmp;
- break;
- case AUSOURCE_FILE_ARRAY:
- n = 0;
- while (bb[n]) {
- if (access(bb[n], R_OK))
- goto bad_exit;
- n++;
- }
- tmp = malloc((n+1)*sizeof(char *));
- for (i=0; i<n; i++)
- tmp[i] = strdup(bb[i]);
- tmp[n] = NULL;
- au->source_list = tmp;
- break;
- case AUSOURCE_BUFFER:
- buf = buf;
- len = strlen(buf);
- if (databuf_init(&au->databuf, len,
- DATABUF_FLAG_PRESERVE_HEAD) < 0)
- goto bad_exit;
- if (databuf_append(&au->databuf, buf, len) < 0)
- goto bad_exit;
- break;
- case AUSOURCE_BUFFER_ARRAY:
- size = 0;
- for (n = 0; (buf = bb[n]); n++) {
- len = strlen(bb[n]);
- if (bb[n][len-1] != '\n') {
- size += len + 1;
- } else {
- size += len;
- }
- }
- if (databuf_init(&au->databuf, size,
- DATABUF_FLAG_PRESERVE_HEAD) < 0)
- goto bad_exit;
- for (n = 0; (buf = bb[n]); n++) {
- len = strlen(buf);
- if (databuf_append(&au->databuf, buf, len) < 0)
- goto bad_exit;
- }
- break;
- case AUSOURCE_DESCRIPTOR:
- n = (long)b;
- au->in = fdopen(n, "rm");
- break;
- case AUSOURCE_FILE_POINTER:
- au->in = (FILE *)b;
- break;
- case AUSOURCE_FEED:
- if (databuf_init(&au->databuf, 0, 0) < 0) goto bad_exit;
- break;
- default:
- errno = EINVAL;
- goto bad_exit;
- break;
- }
- au->source = source;
- au->list_idx = 0;
- au->line_number = 0;
- au->next_buf = NULL;
- au->off = 0;
- au->cur_buf = NULL;
- au->line_pushed = 0;
- aup_list_create(&au->le);
- au->parse_state = EVENT_EMPTY;
- au->expr = NULL;
- au->find_field = NULL;
- au->search_where = AUSEARCH_STOP_EVENT;
-
- return au;
-bad_exit:
- databuf_free(&au->databuf);
- free(au);
- return NULL;
-}
-
-
-void auparse_add_callback(auparse_state_t *au, auparse_callback_ptr callback,
- void *user_data, user_destroy user_destroy_func)
-{
- if (au == NULL) {
- errno = EINVAL;
- return;
- }
-
- if (au->callback_user_data_destroy) {
- (*au->callback_user_data_destroy)(au->callback_user_data);
- au->callback_user_data = NULL;
- }
-
- au->callback = callback;
- au->callback_user_data = user_data;
- au->callback_user_data_destroy = user_destroy_func;
-}
-
-static void consume_feed(auparse_state_t *au, int 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.
- if (au->parse_state == EVENT_ACCUMULATING) {
- // Emit the event, set event cursors to initial position
- aup_list_first(&au->le);
- aup_list_first_field(&au->le);
- au->parse_state = EVENT_EMITTED;
- if (au->callback) {
- (*au->callback)(au, AUPARSE_CB_EVENT_READY,
- au->callback_user_data);
- }
- }
- }
-}
-
-int auparse_feed(auparse_state_t *au, const char *data, size_t data_len)
-{
- if (databuf_append(&au->databuf, data, data_len) < 0)
- return -1;
- consume_feed(au, 0);
- return 0;
-}
-
-int auparse_flush_feed(auparse_state_t *au)
-{
- consume_feed(au, 1);
- return 0;
-}
-
-// If there is data in the state machine, return 1
-// Otherwise return 0 to indicate its empty
-int auparse_feed_has_data(const auparse_state_t *au)
-{
- if (au->parse_state == EVENT_ACCUMULATING)
- return 1;
- return 0;
-}
-
-void auparse_set_escape_mode(auparse_esc_t mode)
-{
- set_escape_mode(mode);
-}
-
-int auparse_reset(auparse_state_t *au)
-{
- if (au == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- aup_list_clear(&au->le);
- au->parse_state = EVENT_EMPTY;
- switch (au->source)
- {
- case AUSOURCE_LOGS:
- case AUSOURCE_FILE:
- case AUSOURCE_FILE_ARRAY:
- if (au->in) {
- fclose(au->in);
- au->in = NULL;
- }
- /* Fall through */
- case AUSOURCE_DESCRIPTOR:
- case AUSOURCE_FILE_POINTER:
- if (au->in)
- rewind(au->in);
- /* Fall through */
- case AUSOURCE_BUFFER:
- case AUSOURCE_BUFFER_ARRAY:
- au->list_idx = 0;
- au->line_number = 0;
- au->off = 0;
- databuf_reset(&au->databuf);
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-
-/* Add EXPR to AU, using HOW to select the combining operator.
- On success, return 0.
- On error, free EXPR set errno and return -1.
- NOTE: EXPR is freed on error! */
-static int add_expr(auparse_state_t *au, struct expr *expr, ausearch_rule_t how)
-{
- if (au->expr == NULL)
- au->expr = expr;
- else if (how == AUSEARCH_RULE_CLEAR) {
- expr_free(au->expr);
- au->expr = expr;
- } else {
- struct expr *e;
-
- e = expr_create_binary(how == AUSEARCH_RULE_OR ? EO_OR : EO_AND,
- au->expr, expr);
- if (e == NULL) {
- int err;
-
- err = errno;
- expr_free(expr);
- errno = err;
- return -1;
- }
- au->expr = e;
- }
- return 0;
-}
-
-static int ausearch_add_item_internal(auparse_state_t *au, const char *field,
- const char *op, const char *value, ausearch_rule_t how, unsigned op_eq,
- unsigned op_ne)
-{
- struct expr *expr;
-
- // Make sure there's a field
- if (field == NULL)
- goto err_out;
-
- // Make sure how is within range
- if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
- goto err_out;
-
- // All pre-checks are done, build a rule
- if (strcmp(op, "exists") == 0)
- expr = expr_create_field_exists(field);
- else {
- unsigned t_op;
-
- if (strcmp(op, "=") == 0)
- t_op = op_eq;
- else if (strcmp(op, "!=") == 0)
- t_op = op_ne;
- else
- goto err_out;
- if (value == NULL)
- goto err_out;
- expr = expr_create_comparison(field, t_op, value);
- }
- if (expr == NULL)
- return -1;
- if (add_expr(au, expr, how) != 0)
- return -1; /* expr is freed by add_expr() */
- return 0;
-
-err_out:
- errno = EINVAL;
- return -1;
-}
-
-int ausearch_add_item(auparse_state_t *au, const char *field, const char *op,
- const char *value, ausearch_rule_t how)
-{
- return ausearch_add_item_internal(au, field, op, value, how, EO_RAW_EQ,
- EO_RAW_NE);
-}
-
-int ausearch_add_interpreted_item(auparse_state_t *au, const char *field,
- const char *op, const char *value, ausearch_rule_t how)
-{
- return ausearch_add_item_internal(au, field, op, value, how,
- EO_INTERPRETED_EQ, EO_INTERPRETED_NE);
-}
-
-int ausearch_add_timestamp_item_ex(auparse_state_t *au, const char *op,
- time_t sec, unsigned milli, unsigned serial, ausearch_rule_t how)
-{
- static const struct {
- unsigned value;
- const char name[3];
- } ts_tab[] = {
- {EO_VALUE_LT, "<"},
- {EO_VALUE_LE, "<="},
- {EO_VALUE_GE, ">="},
- {EO_VALUE_GT, ">"},
- {EO_VALUE_EQ, "="},
- };
-
- struct expr *expr;
- size_t i;
- unsigned t_op;
-
- for (i = 0; i < sizeof(ts_tab) / sizeof(*ts_tab); i++) {
- if (strcmp(ts_tab[i].name, op) == 0)
- goto found_op;
- }
- goto err_out;
-found_op:
- t_op = ts_tab[i].value;
-
- if (milli >= 1000)
- goto err_out;
-
- // Make sure how is within range
- if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
- goto err_out;
-
- // All pre-checks are done, build a rule
- expr = expr_create_timestamp_comparison_ex(t_op, sec, milli, serial);
- if (expr == NULL)
- return -1;
- if (add_expr(au, expr, how) != 0)
- return -1; /* expr is freed by add_expr() */
- return 0;
-
-err_out:
- errno = EINVAL;
- return -1;
-}
-
-int ausearch_add_timestamp_item(auparse_state_t *au, const char *op, time_t sec,
- unsigned milli, ausearch_rule_t how)
-{
- return ausearch_add_timestamp_item_ex(au, op, sec, milli, 0, how);
-}
-
-int ausearch_add_expression(auparse_state_t *au, const char *expression,
- char **error, ausearch_rule_t how)
-{
- struct expr *expr;
-
- if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
- goto err_einval;
-
- expr = expr_parse(expression, error);
- if (expr == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (add_expr(au, expr, how) != 0)
- goto err; /* expr is freed by add_expr() */
- return 0;
-
-err_einval:
- errno = EINVAL;
-err:
- *error = NULL;
- return -1;
-}
-
-int ausearch_add_regex(auparse_state_t *au, const char *regexp)
-{
- struct expr *expr;
-
- // Make sure there's an expression
- if (regexp == NULL)
- goto err_out;
-
- expr = expr_create_regexp_expression(regexp);
- if (expr == NULL)
- return -1;
- if (add_expr(au, expr, AUSEARCH_RULE_AND) != 0)
- return -1; /* expr is freed by add_expr() */
- return 0;
-
-err_out:
- errno = EINVAL;
- return -1;
-}
-
-int ausearch_set_stop(auparse_state_t *au, austop_t where)
-{
- if (where < AUSEARCH_STOP_EVENT || where > AUSEARCH_STOP_FIELD) {
- errno = EINVAL;
- return -1;
- }
-
- au->search_where = where;
- return 0;
-}
-
-void ausearch_clear(auparse_state_t *au)
-{
- if (au->expr != NULL) {
- expr_free(au->expr);
- au->expr = NULL;
- }
- au->search_where = AUSEARCH_STOP_EVENT;
-}
-
-void auparse_destroy(auparse_state_t *au)
-{
- aulookup_destroy_uid_list();
- aulookup_destroy_gid_list();
- if (au == NULL)
- return;
-
- if (au->source_list) {
- int n = 0;
- while (au->source_list[n])
- free(au->source_list[n++]);
- free(au->source_list);
- au->source_list = NULL;
- }
-
- au->next_buf = NULL;
- free(au->cur_buf);
- au->cur_buf = NULL;
- aup_list_clear(&au->le);
- au->parse_state = EVENT_EMPTY;
- free(au->find_field);
- au->find_field = NULL;
- ausearch_clear(au);
- databuf_free(&au->databuf);
- if (au->callback_user_data_destroy) {
- (*au->callback_user_data_destroy)(au->callback_user_data);
- au->callback_user_data = NULL;
- }
- if (au->in) {
- fclose(au->in);
- au->in = NULL;
- }
- free(au);
-}
-
-/* alloc a new buffer, cur_buf which contains a null terminated line
- * without a newline (note, this implies the line may be empty (strlen == 0)) if
- * successfully read a blank line (e.g. containing only a single newline).
- * cur_buf will have been newly allocated with malloc.
- *
- * Note: cur_buf will be freed the next time this routine is called if
- * cur_buf is not NULL, callers who retain a reference to the cur_buf
- * pointer will need to set cur_buf to NULL to cause the previous cur_buf
- * allocation to persist.
- *
- * Returns:
- * 1 if successful (errno == 0)
- * 0 if non-blocking input unavailable (errno == 0)
- * -1 if error (errno contains non-zero error code)
- * -2 if EOF (errno == 0)
- */
-
-static int readline_file(auparse_state_t *au)
-{
- ssize_t rc;
- char *p_last_char;
- size_t n = 0;
-
- if (au->cur_buf != NULL) {
- free(au->cur_buf);
- au->cur_buf = NULL;
- }
- if (au->in == NULL) {
- errno = EBADF;
- return -1;
- }
- if ((rc = getline(&au->cur_buf, &n, au->in)) <= 0) {
- // Note: getline always malloc's if lineptr==NULL or n==0,
- // on failure malloc'ed memory is left uninitialized,
- // caller must free it.
- free(au->cur_buf);
- au->cur_buf = NULL;
-
- // Note: feof() does not set errno
- if (feof(au->in)) {
- // return EOF condition
- errno = 0;
- return -2;
- }
- // return error condition, error code in errno
- return -1;
- }
- p_last_char = au->cur_buf + (rc-1);
- if (*p_last_char == '\n') { /* nuke newline */
- *p_last_char = 0;
- }
- // return success
- errno = 0;
- return 1;
-}
-
-
-/* malloc & copy a line into cur_buf from the internal buffer,
- * next_buf. cur_buf will contain a null terminated line without a
- * newline (note, this implies the line may be empty (strlen == 0)) if
- * successfully read a blank line (e.g. containing only a single
- * newline).
- *
- * Note: cur_buf will be freed the next time this routine is called if
- * cur_buf is not NULL, callers who retain a reference to the cur_buf
- * pointer will need to set cur_buf to NULL to cause the previous cur_buf
- * allocation to persist.
- *
- * Returns:
- * 1 if successful (errno == 0)
- * 0 if non-blocking input unavailable (errno == 0)
- * -1 if error (errno contains non-zero error code)
- * -2 if EOF (errno == 0)
- */
-
-static int readline_buf(auparse_state_t *au)
-{
- char *p_newline=NULL;
- size_t line_len;
-
- if (au->cur_buf != NULL) {
- free(au->cur_buf);
- au->cur_buf = NULL;
- }
-
- //if (debug) databuf_print(&au->databuf, 1, "readline_buf");
- if (au->databuf.len == 0) {
- // return EOF condition
- errno = 0;
- return -2;
- }
-
- if ((p_newline = strnchr(databuf_beg(&au->databuf), '\n',
- au->databuf.len)) != NULL) {
- line_len = p_newline - databuf_beg(&au->databuf);
-
- /* dup the line */
- au->cur_buf = malloc(line_len+1); // +1 for null terminator
- if (au->cur_buf == NULL)
- return -1; // return error condition, errno set
- strncpy(au->cur_buf, databuf_beg(&au->databuf), line_len);
- au->cur_buf[line_len] = 0;
-
- if (databuf_advance(&au->databuf, line_len+1) < 0)
- return -1;
- // return success
- errno = 0;
- return 1;
-
- } else {
- // return no data available
- errno = 0;
- return 0;
- }
-}
-
-static int str2event(char *s, au_event_t *e)
-{
- char *ptr;
-
- errno = 0;
- ptr = strchr(s+10, ':');
- if (ptr) {
- e->serial = strtoul(ptr+1, NULL, 10);
- *ptr = 0;
- if (errno)
- return -1;
- } else
- e->serial = 0;
- ptr = strchr(s, '.');
- if (ptr) {
- e->milli = strtoul(ptr+1, NULL, 10);
- *ptr = 0;
- if (errno)
- return -1;
- } else
- e->milli = 0;
- e->sec = strtoul(s, NULL, 10);
- if (errno)
- return -1;
- return 0;
-}
-
-/* Returns 0 on success and 1 on error */
-static int extract_timestamp(const char *b, au_event_t *e)
-{
- char *ptr, *tmp;
- int rc = 1;
-
- e->host = NULL;
- if (*b == 'n')
- tmp = strndupa(b, 340);
- else
- tmp = strndupa(b, 80);
- ptr = audit_strsplit(tmp);
- if (ptr) {
- // Optionally grab the node - may or may not be included
- if (*ptr == 'n') {
- e->host = strdup(ptr+5);
- (void)audit_strsplit(NULL); // Bump along to the next one
- }
- // at this point we have type=
- ptr = audit_strsplit(NULL);
- if (ptr) {
- if (*(ptr+9) == '(')
- ptr+=9;
- else
- ptr = strchr(ptr, '(');
- if (ptr) {
- // now we should be pointed at the timestamp
- char *eptr;
- ptr++;
- eptr = strchr(ptr, ')');
- if (eptr)
- *eptr = 0;
-
- if (str2event(ptr, e) == 0)
- rc = 0;
-// else {
-// audit_msg(LOG_ERROR,
-// "Error extracting time stamp (%s)\n",
-// ptr);
-// }
- }
- // else we have a bad line
- }
- // else we have a bad line
- }
- // else we have a bad line
- return rc;
-}
-
-static int inline events_are_equal(au_event_t *e1, au_event_t *e2)
-{
- // Check time & serial first since its most likely way
- // to spot 2 different events
- if (!(e1->serial == e2->serial && e1->milli == e2->milli &&
- e1->sec == e2->sec))
- return 0;
- // Hmm...same so far, check if both have a host, only a string
- // compare can tell if they are the same. Otherwise, if only one
- // of them have a host, they are definitely not the same. Its
- // a boundary on daemon config.
- if (e1->host && e2->host) {
- if (strcmp(e1->host, e2->host))
- return 0;
- } else if (e1->host || e2->host)
- return 0;
- return 1;
-}
-
-/* This function will figure out how to get the next line of input.
- * storing it cur_buf. cur_buf will be NULL terminated but will not
- * contain a trailing newline. This implies a successful read
- * (result == 1) may result in a zero length cur_buf if a blank line
- * was read.
- *
- * cur_buf will have been allocated with malloc. The next time this
- * routine is called if cur_buf is non-NULL cur_buf will be freed,
- * thus if the caller wishes to retain a reference to malloc'ed
- * cur_buf data it should copy the cur_buf pointer and set cur_buf to
- * NULL.
- *
- * Returns:
- * 1 if successful (errno == 0)
- * 0 if non-blocking input unavailable (errno == 0)
- * -1 if error (errno contains non-zero error code)
- * -2 if EOF (errno == 0)
- */
-
-static int retrieve_next_line(auparse_state_t *au)
-{
- int rc;
-
- // If line was pushed back for re-reading return that
- if (au->line_pushed) {
- // Starting new event, clear previous event data,
- // previous line is returned again for new parsing
- au->line_pushed = 0;
- au->line_number++;
- return 1;
- }
-
- switch (au->source)
- {
- case AUSOURCE_DESCRIPTOR:
- case AUSOURCE_FILE_POINTER:
- rc = readline_file(au);
- if (rc > 0) au->line_number++;
- return rc;
- case AUSOURCE_LOGS:
- case AUSOURCE_FILE:
- case AUSOURCE_FILE_ARRAY:
- // if the first time through, open file
- if (au->list_idx == 0 && au->in == NULL &&
- au->source_list != NULL) {
- if (au->source_list[au->list_idx] == NULL) {
- errno = 0;
- return -2;
- }
- au->line_number = 0;
- au->in = fopen(au->source_list[au->list_idx],
- "rm");
- if (au->in == NULL)
- return -1;
- __fsetlocking(au->in, FSETLOCKING_BYCALLER);
- }
-
- // loop reading lines from a file
- while (au->in) {
- if ((rc = readline_file(au)) == -2) {
- // end of file, open next file,
- // try readline again
- fclose(au->in);
- au->in = NULL;
- au->list_idx++;
- au->line_number = 0;
- if (au->source_list[au->list_idx]) {
- au->in = fopen(
- au->source_list[au->list_idx],
- "rm");
- if (au->in == NULL)
- return -1;
- __fsetlocking(au->in,
- FSETLOCKING_BYCALLER);
- }
- } else {
- if (rc > 0)
- au->line_number++;
- return rc;
- }
- }
- return -2; // return EOF
- case AUSOURCE_BUFFER:
- case AUSOURCE_BUFFER_ARRAY:
- rc = readline_buf(au);
- if (rc > 0)
- au->line_number++;
- return rc;
- case AUSOURCE_FEED:
- rc = readline_buf(au);
- // No such thing as EOF for feed, translate EOF
- // to data not available
- if (rc == -2)
- return 0;
- else
- if (rc > 0)
- au->line_number++;
- return rc;
- default:
- return -1;
- }
- return -1; /* should never reach here */
-}
-
-static void push_line(auparse_state_t *au)
-{
- au->line_number--;
- au->line_pushed = 1;
-}
-
-/*******
-* Functions that traverse events.
-********/
-static int ausearch_reposition_cursors(auparse_state_t *au)
-{
- int rc = 0;
-
- switch (au->search_where)
- {
- case AUSEARCH_STOP_EVENT:
- aup_list_first(&au->le);
- aup_list_first_field(&au->le);
- break;
- case AUSEARCH_STOP_RECORD:
- aup_list_first_field(&au->le);
- break;
- case AUSEARCH_STOP_FIELD:
- // do nothing - this is the normal stopping point
- break;
- default:
- rc = -1;
- break;
- }
- return rc;
-}
-
-/* This is called during search once per each record. It walks the list
- * of nvpairs and decides if a field matches. */
-static int ausearch_compare(auparse_state_t *au)
-{
- rnode *r;
-
- r = aup_list_get_cur(&au->le);
- if (r)
- return expr_eval(au, r, au->expr);
-
- return 0;
-}
-
-// 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 ((rc = auparse_first_record(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;
-}
-
-// Brute force go to next event. Returns < 0 on error, 0 no data, > 0 success
-int auparse_next_event(auparse_state_t *au)
-{
- int rc;
- au_event_t event;
-
- if (au->parse_state == EVENT_EMITTED) {
- // If the last call resulted in emitting event data then
- // clear previous event data in preparation to accumulate
- // new event data
- aup_list_clear(&au->le);
- au->parse_state = EVENT_EMPTY;
- }
-
- // accumulate new event data
- while (1) {
- rc = retrieve_next_line(au);
- if (debug) printf("next_line(%d) '%s'\n", rc, au->cur_buf);
- if (rc == 0) return 0; // No data now
- if (rc == -2) {
- // We're at EOF, did we read any data previously?
- // If so return data available, else return no data
- // available
- if (au->parse_state == EVENT_ACCUMULATING) {
- if (debug) printf("EOF, EVENT_EMITTED\n");
- au->parse_state = EVENT_EMITTED;
- return 1; // data is available
- }
- return 0;
- }
- if (rc > 0) { // Input available
- rnode *r;
- if (extract_timestamp(au->cur_buf, &event)) {
- if (debug)
- printf("Malformed line:%s\n",
- au->cur_buf);
- continue;
- }
- if (au->parse_state == EVENT_EMPTY) {
- // First record in new event, initialize event
- if (debug)
- printf(
- "First record in new event, initialize event\n");
- aup_list_set_event(&au->le, &event);
- aup_list_append(&au->le, au->cur_buf,
- au->list_idx, au->line_number);
- au->parse_state = EVENT_ACCUMULATING;
- au->cur_buf = NULL;
- } else if (events_are_equal(&au->le.e, &event)) {
- // Accumulate data into existing event
- if (debug)
- printf(
- "Accumulate data into existing event\n");
- aup_list_append(&au->le, au->cur_buf,
- au->list_idx, au->line_number);
- au->parse_state = EVENT_ACCUMULATING;
- au->cur_buf = NULL;
- } else {
- // New event, save input for next invocation
- if (debug)
- printf(
- "New event, save current input for next invocation, EVENT_EMITTED\n");
- push_line(au);
- // Emit the event, set event cursors to
- // initial position
- aup_list_first(&au->le);
- aup_list_first_field(&au->le);
- au->parse_state = EVENT_EMITTED;
- free((char *)event.host);
- return 1; // data is available
- }
- free((char *)event.host);
- // Check to see if the event can be emitted due to EOE
- // or something we know is a single record event. At
- // this point, new record should be pointed at 'cur'
- if ((r = aup_list_get_cur(&au->le)) == NULL)
- continue;
- if ( r->type == AUDIT_EOE ||
- r->type < AUDIT_FIRST_EVENT ||
- r->type >= AUDIT_FIRST_ANOM_MSG) {
- // Emit the event, set event cursors to
- // initial position
- aup_list_first(&au->le);
- aup_list_first_field(&au->le);
- au->parse_state = EVENT_EMITTED;
- return 1; // data is available
- }
- } else { // Read error
- return -1;
- }
- }
-}
-
-/* Accessors to event data */
-const au_event_t *auparse_get_timestamp(auparse_state_t *au)
-{
- if (au && au->le.e.sec != 0)
- return &au->le.e;
- else
- return NULL;
-}
-
-
-time_t auparse_get_time(auparse_state_t *au)
-{
- if (au)
- return au->le.e.sec;
- else
- return 0;
-}
-
-
-unsigned int auparse_get_milli(auparse_state_t *au)
-{
- if (au)
- return au->le.e.milli;
- else
- return 0;
-}
-
-
-unsigned long auparse_get_serial(auparse_state_t *au)
-{
- if (au)
- return au->le.e.serial;
- else
- return 0;
-}
-
-
-// Gets the machine node name
-const char *auparse_get_node(auparse_state_t *au)
-{
- if (au && au->le.e.host != NULL)
- return strdup(au->le.e.host);
- else
- return NULL;
-}
-
-
-int auparse_node_compare(au_event_t *e1, au_event_t *e2)
-{
- // If both have a host, only a string compare can tell if they
- // are the same. Otherwise, if only one of them have a host, they
- // are definitely not the same. Its a boundary on daemon config.
- if (e1->host && e2->host)
- return strcmp(e1->host, e2->host);
- else if (e1->host)
- return 1;
- else if (e2->host)
- return -1;
-
- return 0;
-}
-
-
-int auparse_timestamp_compare(au_event_t *e1, au_event_t *e2)
-{
- if (e1->sec > e2->sec)
- return 1;
- if (e1->sec < e2->sec)
- return -1;
-
- if (e1->milli > e2->milli)
- return 1;
- if (e1->milli < e2->milli)
- return -1;
-
- if (e1->serial > e2->serial)
- return 1;
- if (e1->serial < e2->serial)
- return -1;
-
- return 0;
-}
-
-unsigned int auparse_get_num_records(auparse_state_t *au)
-{
- return aup_list_get_cnt(&au->le);
-}
-
-
-/* Functions that traverse records in the same event */
-int auparse_first_record(auparse_state_t *au)
-{
- int rc;
-
- if (aup_list_get_cnt(&au->le) == 0) {
- rc = auparse_next_event(au);
- if (rc <= 0)
- return rc;
- }
- aup_list_first(&au->le);
- aup_list_first_field(&au->le);
-
- return 1;
-}
-
-
-int auparse_next_record(auparse_state_t *au)
-{
- if (aup_list_get_cnt(&au->le) == 0) {
- int rc = auparse_first_record(au);
- if (rc <= 0)
- return rc;
- }
- if (aup_list_next(&au->le))
- return 1;
- else
- return 0;
-}
-
-
-int auparse_goto_record_num(auparse_state_t *au, unsigned int num)
-{
- /* Check if a request is out of range */
- if (num >= aup_list_get_cnt(&au->le))
- return 0;
-
- if (aup_list_goto_rec(&au->le, num) != NULL)
- return 1;
- else
- return 0;
-}
-
-
-/* Accessors to record data */
-int auparse_get_type(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return r->type;
- else
- return 0;
-}
-
-
-const char *auparse_get_type_name(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return audit_msg_type_to_name(r->type);
- else
- return NULL;
-}
-
-
-unsigned int auparse_get_line_number(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return r->line_number;
- else
- return 0;
-}
-
-
-const char *auparse_get_filename(auparse_state_t *au)
-{
- switch (au->source)
- {
- case AUSOURCE_FILE:
- case AUSOURCE_FILE_ARRAY:
- break;
- default:
- return NULL;
- }
-
- rnode *r = aup_list_get_cur(&au->le);
- if (r) {
- if (r->list_idx < 0) return NULL;
- return au->source_list[r->list_idx];
- } else {
- return NULL;
- }
-}
-
-
-int auparse_first_field(auparse_state_t *au)
-{
- return aup_list_first_field(&au->le);
-}
-
-
-int auparse_next_field(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r) {
- if (nvlist_next(&r->nv))
- return 1;
- else
- return 0;
- }
- return 0;
-}
-
-
-unsigned int auparse_get_num_fields(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return nvlist_get_cnt(&r->nv);
- else
- return 0;
-}
-
-const char *auparse_get_record_text(auparse_state_t *au)
-{
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return r->record;
- else
- return NULL;
-}
-
-
-/* scan from current location to end of event */
-const char *auparse_find_field(auparse_state_t *au, const char *name)
-{
- free(au->find_field);
- au->find_field = strdup(name);
-
- if (au->le.e.sec) {
- const char *cur_name;
- rnode *r;
-
- // look at current record before moving
- r = aup_list_get_cur(&au->le);
- if (r == NULL)
- return NULL;
- cur_name = nvlist_get_cur_name(&r->nv);
- if (cur_name && strcmp(cur_name, name) == 0)
- return nvlist_get_cur_val(&r->nv);
-
- return auparse_find_field_next(au);
- }
- return NULL;
-}
-
-/* Increment 1 location and then scan for next field */
-const char *auparse_find_field_next(auparse_state_t *au)
-{
- if (au->find_field == NULL) {
- errno = EINVAL;
- return NULL;
- }
- if (au->le.e.sec) {
- int moved = 0;
-
- rnode *r = aup_list_get_cur(&au->le);
- while (r) { // For each record in the event...
- if (!moved) {
- nvlist_next(&r->nv);
- moved=1;
- }
- if (nvlist_find_name(&r->nv, au->find_field))
- return nvlist_get_cur_val(&r->nv);
- r = aup_list_next(&au->le);
- if (r)
- aup_list_first_field(&au->le);
- }
- }
- return NULL;
-}
-
-
-/* Accessors to field data */
-const char *auparse_get_field_name(auparse_state_t *au)
-{
- if (au->le.e.sec) {
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return nvlist_get_cur_name(&r->nv);
- }
- return NULL;
-}
-
-
-const char *auparse_get_field_str(auparse_state_t *au)
-{
- if (au->le.e.sec) {
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return nvlist_get_cur_val(&r->nv);
- }
- return NULL;
-}
-
-int auparse_get_field_type(auparse_state_t *au)
-{
- if (au->le.e.sec) {
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return nvlist_get_cur_type(r);
- }
- return AUPARSE_TYPE_UNCLASSIFIED;
-}
-
-int auparse_get_field_int(auparse_state_t *au)
-{
- const char *v = auparse_get_field_str(au);
- if (v) {
- int val;
-
- errno = 0;
- val = strtol(v, NULL, 10);
- if (errno == 0)
- return val;
- } else
- errno = ENODATA;
- return -1;
-}
-
-const char *auparse_interpret_field(auparse_state_t *au)
-{
- if (au->le.e.sec) {
- rnode *r = aup_list_get_cur(&au->le);
- if (r)
- return nvlist_interp_cur_val(r);
- }
- return NULL;
-}
-