Imported Upstream version 2.4.3
[platform/upstream/audit.git] / auparse / auparse.c
1 /* auparse.c --
2  * Copyright 2006-08,2012-14 Red Hat Inc., Durham, North Carolina.
3  * All Rights Reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Authors:
20  *      Steve Grubb <sgrubb@redhat.com>
21  */
22
23 #include "config.h"
24 #include "expression.h"
25 #include "internal.h"
26 #include "auparse.h"
27 #include "interpret.h"
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <stdio_ext.h>
33
34 static int debug = 0;
35
36 /* like strchr except string is delimited by length, not null byte */
37 static char *strnchr(const char *s, int c, size_t n)
38 {
39     char *p_char;
40     const char *p_end = s + n;
41
42     for (p_char = (char *)s; p_char < p_end && *p_char != c; p_char++);
43     if (p_char == p_end) return NULL;
44     return p_char;
45 }
46
47 static int setup_log_file_array(auparse_state_t *au)
48 {
49         struct daemon_conf config;
50         char *filename, **tmp;
51         int len, num = 0, i = 0;
52
53         /* Load config so we know where logs are */
54         set_aumessage_mode(MSG_STDERR, DBG_NO);
55         load_config(&config, TEST_SEARCH);
56
57         /* for each file */
58         len = strlen(config.log_file) + 16;
59         filename = malloc(len);
60         if (!filename) {
61                 fprintf(stderr, "No memory\n");
62                 free_config(&config);
63                 return 1;
64         }
65         /* Find oldest log file */
66         snprintf(filename, len, "%s", config.log_file);
67         do {
68                 if (access(filename, R_OK) != 0)
69                         break;
70                 num++;
71                 snprintf(filename, len, "%s.%d", config.log_file, num);
72         } while (1);
73
74         if (num == 0) {
75                 fprintf(stderr, "No log file\n");
76                 free_config(&config);
77                 free(filename);
78                 return 1;
79         }
80         num--;
81         tmp = malloc((num+2)*sizeof(char *));
82
83         /* Got it, now process logs from last to first */
84         if (num > 0)
85                 snprintf(filename, len, "%s.%d", config.log_file, num);
86         else
87                 snprintf(filename, len, "%s", config.log_file);
88         do {
89                 tmp[i++] = strdup(filename);
90
91                 /* Get next log file */
92                 num--;
93                 if (num > 0)
94                         snprintf(filename, len, "%s.%d", config.log_file, num);
95                 else if (num == 0)
96                         snprintf(filename, len, "%s", config.log_file);
97                 else
98                         break;
99         } while (1);
100         free_config(&config);
101         free(filename);
102
103         // Terminate the list
104         tmp[i] = NULL; 
105         au->source_list = tmp;
106         return 0;
107 }
108
109 /* General functions that affect operation of the library */
110 auparse_state_t *auparse_init(ausource_t source, const void *b)
111 {
112         char **tmp, **bb = (char **)b, *buf = (char *)b;
113         int n, i;
114         size_t size, len;
115
116         auparse_state_t *au = malloc(sizeof(auparse_state_t));
117         if (au == NULL) {
118                 errno = ENOMEM;
119                 return NULL;
120         }
121
122         au->in = NULL;
123         au->source_list = NULL;
124         databuf_init(&au->databuf, 0, 0);
125         au->callback = NULL;
126         au->callback_user_data = NULL;
127         au->callback_user_data_destroy = NULL;
128         switch (source)
129         {
130                 case AUSOURCE_LOGS:
131                         if (geteuid()) {
132                                 errno = EPERM;
133                                 goto bad_exit;
134                         }
135                         setup_log_file_array(au);
136                         break;
137                 case AUSOURCE_FILE:
138                         if (access(b, R_OK))
139                                 goto bad_exit;
140                         tmp = malloc(2*sizeof(char *));
141                         tmp[0] = strdup(b);
142                         tmp[1] = NULL;
143                         au->source_list = tmp;
144                         break;
145                 case AUSOURCE_FILE_ARRAY:
146                         n = 0;
147                         while (bb[n]) {
148                                 if (access(bb[n], R_OK))
149                                         goto bad_exit;
150                                 n++;
151                         }
152                         tmp = malloc((n+1)*sizeof(char *));
153                         for (i=0; i<n; i++)
154                                 tmp[i] = strdup(bb[i]);
155                         tmp[n] = NULL;
156                         au->source_list = tmp;
157                         break;
158                 case AUSOURCE_BUFFER:
159                         buf = buf;
160                         len = strlen(buf);
161                         if (databuf_init(&au->databuf, len,
162                                          DATABUF_FLAG_PRESERVE_HEAD) < 0)
163                                 goto bad_exit;
164                         if (databuf_append(&au->databuf, buf, len) < 0)
165                                 goto bad_exit;
166                         break;
167                 case AUSOURCE_BUFFER_ARRAY:
168                         size = 0;
169                         for (n = 0; (buf = bb[n]); n++) {
170                                 len = strlen(bb[n]);
171                                 if (bb[n][len-1] != '\n') {
172                                         size += len + 1;
173                                 } else {
174                                         size += len;
175                                 }
176                         }
177                         if (databuf_init(&au->databuf, size,
178                                         DATABUF_FLAG_PRESERVE_HEAD) < 0)
179                                 goto bad_exit;
180                         for (n = 0; (buf = bb[n]); n++) {
181                                 len = strlen(buf);
182                                 if (databuf_append(&au->databuf, buf, len) < 0)
183                                         goto bad_exit;
184                         }
185                         break;
186                 case AUSOURCE_DESCRIPTOR:
187                         n = (long)b;
188                         au->in = fdopen(n, "rm");
189                         break;
190                 case AUSOURCE_FILE_POINTER:
191                         au->in = (FILE *)b;
192                         break;
193                 case AUSOURCE_FEED:
194                     if (databuf_init(&au->databuf, 0, 0) < 0) goto bad_exit;
195                         break;
196                 default:
197                         errno = EINVAL;
198                         goto bad_exit;
199                         break;
200         }
201         au->source = source;
202         au->list_idx = 0;
203         au->line_number = 0;
204         au->next_buf = NULL;
205         au->off = 0;
206         au->cur_buf = NULL;
207         au->line_pushed = 0;
208         aup_list_create(&au->le);
209         au->parse_state = EVENT_EMPTY;
210         au->expr = NULL;
211         au->find_field = NULL;
212         au->search_where = AUSEARCH_STOP_EVENT;
213
214         return au;
215 bad_exit:
216         databuf_free(&au->databuf);
217         free(au);
218         return NULL;
219 }
220
221
222 void auparse_add_callback(auparse_state_t *au, auparse_callback_ptr callback,
223                           void *user_data, user_destroy user_destroy_func)
224 {
225         if (au == NULL) {
226                 errno = EINVAL;
227                 return;
228         }
229
230         if (au->callback_user_data_destroy) {
231                 (*au->callback_user_data_destroy)(au->callback_user_data);
232                 au->callback_user_data = NULL;
233         }
234
235         au->callback = callback;
236         au->callback_user_data = user_data;
237         au->callback_user_data_destroy = user_destroy_func;
238 }
239
240 static void consume_feed(auparse_state_t *au, int flush)
241 {
242         while (auparse_next_event(au) > 0) {
243                 if (au->callback) {
244                         (*au->callback)(au, AUPARSE_CB_EVENT_READY,
245                                         au->callback_user_data);
246                 }
247         }
248         if (flush) {
249                 // FIXME: might need a call here to force auparse_next_event()
250                 // to consume any partial data not fully consumed.
251                 if (au->parse_state == EVENT_ACCUMULATING) {
252                         // Emit the event, set event cursors to initial position
253                         aup_list_first(&au->le);
254                         aup_list_first_field(&au->le);
255                         au->parse_state = EVENT_EMITTED;
256                         if (au->callback) {
257                                  (*au->callback)(au, AUPARSE_CB_EVENT_READY,
258                                                  au->callback_user_data);
259                         }
260                 }
261         }
262 }
263
264 int auparse_feed(auparse_state_t *au, const char *data, size_t data_len)
265 {
266         if (databuf_append(&au->databuf, data, data_len) < 0)
267                 return -1;
268         consume_feed(au, 0);
269         return 0;
270 }
271
272 int auparse_flush_feed(auparse_state_t *au)
273 {
274         consume_feed(au, 1);
275         return 0;
276 }
277
278 // If there is data in the state machine, return 1
279 // Otherwise return 0 to indicate its empty
280 int auparse_feed_has_data(const auparse_state_t *au)
281 {
282         if (au->parse_state == EVENT_ACCUMULATING)
283                 return 1;
284         return 0;
285 }
286
287 int auparse_reset(auparse_state_t *au)
288 {
289         if (au == NULL) {
290                 errno = EINVAL;
291                 return -1;
292         }
293
294         aup_list_clear(&au->le);
295         au->parse_state = EVENT_EMPTY;
296         switch (au->source)
297         {
298                 case AUSOURCE_LOGS:
299                 case AUSOURCE_FILE:
300                 case AUSOURCE_FILE_ARRAY:
301                         if (au->in) {
302                                 fclose(au->in);
303                                 au->in = NULL;
304                         }
305                 /* Fall through */
306                 case AUSOURCE_DESCRIPTOR:
307                 case AUSOURCE_FILE_POINTER:
308                         if (au->in) 
309                                 rewind(au->in);
310                 /* Fall through */
311                 case AUSOURCE_BUFFER:
312                 case AUSOURCE_BUFFER_ARRAY:
313                         au->list_idx = 0;
314                         au->line_number = 0;
315                         au->off = 0;
316                         databuf_reset(&au->databuf);
317                         break;
318                 default:
319                         return -1;
320         }
321         return 0;
322 }
323
324
325 /* Add EXPR to AU, using HOW to select the combining operator.
326    On success, return 0.
327    On error, free EXPR set errno and return -1.
328    NOTE: EXPR is freed on error! */
329 static int add_expr(auparse_state_t *au, struct expr *expr, ausearch_rule_t how)
330 {
331         if (au->expr == NULL)
332                 au->expr = expr;
333         else if (how == AUSEARCH_RULE_CLEAR) {
334                 expr_free(au->expr);
335                 au->expr = expr;
336         } else {
337                 struct expr *e;
338
339                 e = expr_create_binary(how == AUSEARCH_RULE_OR ? EO_OR : EO_AND,
340                                        au->expr, expr);
341                 if (e == NULL) {
342                         int err;
343
344                         err = errno;
345                         expr_free(expr);
346                         errno = err;
347                         return -1;
348                 }
349                 au->expr = e;
350         }
351         return 0;
352 }
353
354 static int ausearch_add_item_internal(auparse_state_t *au, const char *field,
355         const char *op, const char *value, ausearch_rule_t how, unsigned op_eq,
356         unsigned op_ne)
357 {
358         struct expr *expr;
359
360         // Make sure there's a field
361         if (field == NULL)
362                 goto err_out;
363
364         // Make sure how is within range
365         if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
366                 goto err_out;
367
368         // All pre-checks are done, build a rule
369         if (strcmp(op, "exists") == 0)
370                 expr = expr_create_field_exists(field);
371         else {
372                 unsigned t_op;
373
374                 if (strcmp(op, "=") == 0)
375                         t_op = op_eq;
376                 else if (strcmp(op, "!=") == 0)
377                         t_op = op_ne;
378                 else
379                         goto err_out;
380                 if (value == NULL)
381                         goto err_out;
382                 expr = expr_create_comparison(field, t_op, value);
383         }
384         if (expr == NULL)
385                 return -1;
386         if (add_expr(au, expr, how) != 0)
387                 return -1; /* expr is freed by add_expr() */
388         return 0;
389
390 err_out:
391         errno = EINVAL;
392         return -1;
393 }
394
395 int ausearch_add_item(auparse_state_t *au, const char *field, const char *op,
396         const char *value, ausearch_rule_t how)
397 {
398         return ausearch_add_item_internal(au, field, op, value, how, EO_RAW_EQ,
399                                           EO_RAW_NE);
400 }
401
402 int ausearch_add_interpreted_item(auparse_state_t *au, const char *field,
403         const char *op, const char *value, ausearch_rule_t how)
404 {
405         return ausearch_add_item_internal(au, field, op, value, how,
406                                           EO_INTERPRETED_EQ, EO_INTERPRETED_NE);
407 }
408
409 int ausearch_add_timestamp_item_ex(auparse_state_t *au, const char *op,
410         time_t sec, unsigned milli, unsigned serial, ausearch_rule_t how)
411 {
412         static const struct {
413                 unsigned value;
414                 const char name[3];
415         } ts_tab[] = {
416                 {EO_VALUE_LT, "<"},
417                 {EO_VALUE_LE, "<="},
418                 {EO_VALUE_GE, ">="},
419                 {EO_VALUE_GT, ">"},
420                 {EO_VALUE_EQ, "="},
421         };
422
423         struct expr *expr;
424         size_t i;
425         unsigned t_op;
426
427         for (i = 0; i < sizeof(ts_tab) / sizeof(*ts_tab); i++) {
428                 if (strcmp(ts_tab[i].name, op) == 0)
429                         goto found_op;
430         }
431         goto err_out;
432 found_op:
433         t_op = ts_tab[i].value;
434
435         if (milli >= 1000)
436                 goto err_out;
437
438         // Make sure how is within range
439         if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
440                 goto err_out;
441
442         // All pre-checks are done, build a rule
443         expr = expr_create_timestamp_comparison_ex(t_op, sec, milli, serial);
444         if (expr == NULL)
445                 return -1;
446         if (add_expr(au, expr, how) != 0)
447                 return -1; /* expr is freed by add_expr() */
448         return 0;
449
450 err_out:
451         errno = EINVAL;
452         return -1;
453 }
454
455 int ausearch_add_timestamp_item(auparse_state_t *au, const char *op, time_t sec,
456                                 unsigned milli, ausearch_rule_t how)
457 {
458         return ausearch_add_timestamp_item_ex(au, op, sec, milli, 0, how);
459 }
460
461 int ausearch_add_expression(auparse_state_t *au, const char *expression,
462                             char **error, ausearch_rule_t how)
463 {
464         struct expr *expr;
465
466         if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
467                 goto err_einval;
468
469         expr = expr_parse(expression, error);
470         if (expr == NULL) {
471                 errno = EINVAL;
472                 return -1;
473         }
474
475         if (add_expr(au, expr, how) != 0)
476                 goto err; /* expr is freed by add_expr() */
477         return 0;
478
479 err_einval:
480         errno = EINVAL;
481 err:
482         *error = NULL;
483         return -1;
484 }
485
486 int ausearch_add_regex(auparse_state_t *au, const char *regexp)
487 {
488         struct expr *expr;
489
490         // Make sure there's an expression
491         if (regexp == NULL)
492                 goto err_out;
493
494         expr = expr_create_regexp_expression(regexp);
495         if (expr == NULL)
496                 return -1;
497         if (add_expr(au, expr, AUSEARCH_RULE_AND) != 0)
498                 return -1; /* expr is freed by add_expr() */
499         return 0;
500
501 err_out:
502         errno = EINVAL;
503         return -1;
504 }
505
506 int ausearch_set_stop(auparse_state_t *au, austop_t where)
507 {
508         if (where < AUSEARCH_STOP_EVENT || where > AUSEARCH_STOP_FIELD) {
509                 errno = EINVAL;
510                 return -1;
511         }
512
513         au->search_where = where;
514         return 0;
515 }
516
517 void ausearch_clear(auparse_state_t *au)
518 {
519         if (au->expr != NULL) {
520                 expr_free(au->expr);
521                 au->expr = NULL;
522         }
523         au->search_where = AUSEARCH_STOP_EVENT;
524 }
525
526 void auparse_destroy(auparse_state_t *au)
527 {
528         aulookup_destroy_uid_list();
529         aulookup_destroy_gid_list();
530         if (au == NULL)
531                 return;
532
533         if (au->source_list) {
534                 int n = 0;
535                 while (au->source_list[n]) 
536                         free(au->source_list[n++]);
537                 free(au->source_list);
538                 au->source_list = NULL;
539         }
540
541         au->next_buf = NULL;
542         free(au->cur_buf);
543         au->cur_buf = NULL;
544         aup_list_clear(&au->le);
545         au->parse_state = EVENT_EMPTY;
546         free(au->find_field);
547         au->find_field = NULL;
548         ausearch_clear(au);
549         databuf_free(&au->databuf);
550         if (au->callback_user_data_destroy) {
551                 (*au->callback_user_data_destroy)(au->callback_user_data);
552                 au->callback_user_data = NULL;
553         }
554         if (au->in) {
555                 fclose(au->in);
556                 au->in = NULL;
557         }
558         free(au);
559 }
560
561 /* alloc a new buffer, cur_buf which contains a null terminated line
562  * without a newline (note, this implies the line may be empty (strlen == 0)) if
563  * successfully read a blank line (e.g. containing only a single newline).
564  * cur_buf will have been newly allocated with malloc.
565  * 
566  * Note: cur_buf will be freed the next time this routine is called if
567  * cur_buf is not NULL, callers who retain a reference to the cur_buf
568  * pointer will need to set cur_buf to NULL to cause the previous cur_buf
569  * allocation to persist.
570  *
571  * Returns:
572  *     1 if successful (errno == 0)
573  *     0 if non-blocking input unavailable (errno == 0)
574  *    -1 if error (errno contains non-zero error code)
575  *    -2 if EOF  (errno == 0)
576  */
577
578 static int readline_file(auparse_state_t *au)
579 {
580         ssize_t rc;
581         char *p_last_char;
582         size_t n = 0;
583
584         if (au->cur_buf != NULL) {
585                 free(au->cur_buf);
586                 au->cur_buf = NULL;
587         }
588         if (au->in == NULL) {
589                 errno = EBADF;
590                 return -1;
591         }
592         if ((rc = getline(&au->cur_buf, &n, au->in)) <= 0) {
593                 // Note: getline always malloc's if lineptr==NULL or n==0,
594                 // on failure malloc'ed memory is left uninitialized,
595                 // caller must free it.
596                 free(au->cur_buf);
597                 au->cur_buf = NULL;
598
599                 // Note: feof() does not set errno
600                 if (feof(au->in)) {
601                         // return EOF condition
602                         errno = 0;
603                         return -2;
604                 }
605                 // return error condition, error code in errno
606                 return -1;
607         }
608         p_last_char = au->cur_buf + (rc-1);
609         if (*p_last_char == '\n') {     /* nuke newline */
610                 *p_last_char = 0;
611         }
612         // return success
613         errno = 0;
614         return 1;
615 }
616
617
618 /* malloc & copy a line into cur_buf from the internal buffer,
619  * next_buf.  cur_buf will contain a null terminated line without a
620  * newline (note, this implies the line may be empty (strlen == 0)) if
621  * successfully read a blank line (e.g. containing only a single
622  * newline).
623  * 
624  * Note: cur_buf will be freed the next time this routine is called if
625  * cur_buf is not NULL, callers who retain a reference to the cur_buf
626  * pointer will need to set cur_buf to NULL to cause the previous cur_buf
627  * allocation to persist.
628  *
629  * Returns:
630  *     1 if successful (errno == 0)
631  *     0 if non-blocking input unavailable (errno == 0)
632  *    -1 if error (errno contains non-zero error code)
633  *    -2 if EOF  (errno == 0)
634  */
635
636 static int readline_buf(auparse_state_t *au)
637 {
638         char *p_newline=NULL;
639         size_t line_len;
640
641         if (au->cur_buf != NULL) {
642                 free(au->cur_buf);
643                 au->cur_buf = NULL;
644         }
645
646         //if (debug) databuf_print(&au->databuf, 1, "readline_buf");
647         if (au->databuf.len == 0) {
648                 // return EOF condition
649                 errno = 0;
650                 return -2;
651         }
652
653         if ((p_newline = strnchr(databuf_beg(&au->databuf), '\n',
654                                                 au->databuf.len)) != NULL) {
655                 line_len = p_newline - databuf_beg(&au->databuf);
656                 
657                 /* dup the line */
658                 au->cur_buf = malloc(line_len+1);   // +1 for null terminator
659                 if (au->cur_buf == NULL)
660                         return -1; // return error condition, errno set
661                 strncpy(au->cur_buf, databuf_beg(&au->databuf), line_len);
662                 au->cur_buf[line_len] = 0;
663
664                 if (databuf_advance(&au->databuf, line_len+1) < 0)
665                         return -1;
666                 // return success
667                 errno = 0;
668                 return 1;
669         
670         } else {
671                 // return no data available
672                 errno = 0;
673                 return 0;
674         }
675 }
676
677 static int str2event(char *s, au_event_t *e)
678 {
679         char *ptr;
680
681         errno = 0;
682         ptr = strchr(s+10, ':');
683         if (ptr) {
684                 e->serial = strtoul(ptr+1, NULL, 10);
685                 *ptr = 0;
686                 if (errno)
687                         return -1;
688         } else
689                 e->serial = 0;
690         ptr = strchr(s, '.');
691         if (ptr) {
692                 e->milli = strtoul(ptr+1, NULL, 10);
693                 *ptr = 0;
694                 if (errno)
695                         return -1;
696         } else
697                 e->milli = 0;
698         e->sec = strtoul(s, NULL, 10);
699         if (errno)
700                 return -1;
701         return 0;
702 }
703
704 /* Returns 0 on success and 1 on error */
705 static int extract_timestamp(const char *b, au_event_t *e)
706 {
707         char *ptr, *tmp;
708         int rc = 1;
709
710         e->host = NULL;
711         if (*b == 'n')
712                 tmp = strndupa(b, 340);
713         else
714                 tmp = strndupa(b, 80);
715         ptr = audit_strsplit(tmp);
716         if (ptr) {
717                 // Optionally grab the node - may or may not be included
718                 if (*ptr == 'n') {
719                         e->host = strdup(ptr+5);
720                         (void)audit_strsplit(NULL); // Bump along to the next one
721                 }
722                 // at this point we have type=
723                 ptr = audit_strsplit(NULL);
724                 if (ptr) {
725                         if (*(ptr+9) == '(')
726                                 ptr+=9;
727                         else
728                                 ptr = strchr(ptr, '(');
729                         if (ptr) {
730                                 // now we should be pointed at the timestamp
731                                 char *eptr;
732                                 ptr++;
733                                 eptr = strchr(ptr, ')');
734                                 if (eptr)
735                                         *eptr = 0;
736
737                                 if (str2event(ptr, e) == 0)
738                                         rc = 0;
739 //                              else {
740 //                                      audit_msg(LOG_ERROR,
741 //                                        "Error extracting time stamp (%s)\n",
742 //                                              ptr);
743 //                              }
744                         }
745                         // else we have a bad line
746                 }
747                 // else we have a bad line
748         }
749         // else we have a bad line
750         return rc;
751 }
752
753 static int inline events_are_equal(au_event_t *e1, au_event_t *e2)
754 {
755         // Check time & serial first since its most likely way
756         // to spot 2 different events
757         if (!(e1->serial == e2->serial && e1->milli == e2->milli &&
758                                         e1->sec == e2->sec))
759                 return 0;
760         // Hmm...same so far, check if both have a host, only a string
761         // compare can tell if they are the same. Otherwise, if only one
762         // of them have a host, they are definitely not the same. Its
763         // a boundary on daemon config.
764         if (e1->host && e2->host) {
765                 if (strcmp(e1->host, e2->host))
766                         return 0;
767         } else if (e1->host || e2->host)
768                 return 0;
769         return 1;
770 }
771
772 /* This function will figure out how to get the next line of input.
773  * storing it cur_buf. cur_buf will be NULL terminated but will not
774  * contain a trailing newline. This implies a successful read 
775  * (result == 1) may result in a zero length cur_buf if a blank line
776  * was read.
777  *
778  * cur_buf will have been allocated with malloc. The next time this
779  * routine is called if cur_buf is non-NULL cur_buf will be freed,
780  * thus if the caller wishes to retain a reference to malloc'ed
781  * cur_buf data it should copy the cur_buf pointer and set cur_buf to
782  * NULL.
783  *
784  * Returns:
785  *     1 if successful (errno == 0)
786  *     0 if non-blocking input unavailable (errno == 0)
787  *    -1 if error (errno contains non-zero error code)
788  *    -2 if EOF  (errno == 0)
789  */
790
791 static int retrieve_next_line(auparse_state_t *au)
792 {
793         int rc;
794
795         // If line was pushed back for re-reading return that
796         if (au->line_pushed) {
797                 // Starting new event, clear previous event data,
798                 // previous line is returned again for new parsing
799                 au->line_pushed = 0;
800                 au->line_number++;
801                 return 1;
802         }
803
804         switch (au->source)
805         {
806                 case AUSOURCE_DESCRIPTOR:
807                 case AUSOURCE_FILE_POINTER:
808                         rc = readline_file(au);
809                         if (rc > 0) au->line_number++;
810                         return rc;
811                 case AUSOURCE_LOGS:
812                 case AUSOURCE_FILE:
813                 case AUSOURCE_FILE_ARRAY:
814                         // if the first time through, open file
815                         if (au->list_idx == 0 && au->in == NULL &&
816                                                 au->source_list != NULL) {
817                                 if (au->source_list[au->list_idx] == NULL) {
818                                         errno = 0;
819                                         return -2;
820                                 }
821                                 au->line_number = 0;
822                                 au->in = fopen(au->source_list[au->list_idx],
823                                                                         "rm");
824                                 if (au->in == NULL)
825                                         return -1;
826                                 __fsetlocking(au->in, FSETLOCKING_BYCALLER);
827                         }
828
829                         // loop reading lines from a file
830                         while (au->in) {
831                                 if ((rc = readline_file(au)) == -2) {
832                                         // end of file, open next file,
833                                         // try readline again
834                                         fclose(au->in);
835                                         au->in = NULL;
836                                         au->list_idx++;
837                                         au->line_number = 0;
838                                         if (au->source_list[au->list_idx]) {
839                                                 au->in = fopen(
840                                                   au->source_list[au->list_idx],
841                                                   "rm");
842                                                 if (au->in == NULL)
843                                                         return -1;
844                                                 __fsetlocking(au->in,
845                                                         FSETLOCKING_BYCALLER);
846                                         }
847                                 } else {
848                                         if (rc > 0)
849                                                 au->line_number++;
850                                         return rc;
851                                 }
852                         }
853                         return -2;      // return EOF
854                 case AUSOURCE_BUFFER:
855                 case AUSOURCE_BUFFER_ARRAY:
856                         rc = readline_buf(au);
857                         if (rc > 0)
858                                 au->line_number++;
859                         return rc;
860                 case AUSOURCE_FEED:
861                         rc = readline_buf(au);
862                         // No such thing as EOF for feed, translate EOF
863                         // to data not available
864                         if (rc == -2)
865                                 return 0;
866                         else
867                                 if (rc > 0)
868                                         au->line_number++;
869                                 return rc;
870                 default:
871                         return -1;
872         }
873         return -1;              /* should never reach here */
874 }
875
876 static void push_line(auparse_state_t *au)
877 {
878         au->line_number--;
879         au->line_pushed = 1;
880 }
881
882 /*******
883 * Functions that traverse events.
884 ********/
885 static int ausearch_reposition_cursors(auparse_state_t *au)
886 {
887         int rc = 0;
888
889         switch (au->search_where)
890         {
891                 case AUSEARCH_STOP_EVENT:
892                         aup_list_first(&au->le);
893                         aup_list_first_field(&au->le);
894                         break;
895                 case AUSEARCH_STOP_RECORD:
896                         aup_list_first_field(&au->le);
897                         break;
898                 case AUSEARCH_STOP_FIELD:
899                         // do nothing - this is the normal stopping point
900                         break;
901                 default:
902                         rc = -1;
903                         break;
904         }
905         return rc;
906 }
907
908 /* This is called during search once per each record. It walks the list
909  * of nvpairs and decides if a field matches. */
910 static int ausearch_compare(auparse_state_t *au)
911 {
912         rnode *r;
913
914         r = aup_list_get_cur(&au->le);
915         if (r)
916                 return expr_eval(au, r, au->expr);
917
918         return 0;
919 }
920
921 // Returns < 0 on error, 0 no data, > 0 success
922 int ausearch_next_event(auparse_state_t *au)
923 {
924         int rc;
925
926         if (au->expr == NULL) {
927                 errno = EINVAL;
928                 return -1;
929         }
930         if ((rc = auparse_first_record(au)) <= 0)
931                 return rc;
932         do {
933                 do {
934                         if ((rc = ausearch_compare(au)) > 0) {
935                                 ausearch_reposition_cursors(au);
936                                 return 1;
937                         } else if (rc < 0)
938                                 return rc;
939                 } while ((rc = auparse_next_record(au)) > 0);
940                 if (rc < 0)
941                         return rc;
942         } while ((rc = auparse_next_event(au)) > 0);
943         if (rc < 0)
944                 return rc;
945         
946         return 0;
947 }
948
949 // Brute force go to next event. Returns < 0 on error, 0 no data, > 0 success
950 int auparse_next_event(auparse_state_t *au)
951 {
952         int rc;
953         au_event_t event;
954
955         if (au->parse_state == EVENT_EMITTED) {
956                 // If the last call resulted in emitting event data then
957                 // clear previous event data in preparation to accumulate
958                 // new event data
959                 aup_list_clear(&au->le);
960                 au->parse_state = EVENT_EMPTY;
961         }
962
963         // accumulate new event data
964         while (1) {
965                 rc = retrieve_next_line(au);
966                 if (debug) printf("next_line(%d) '%s'\n", rc, au->cur_buf);
967                 if (rc ==  0) return 0; // No data now
968                 if (rc == -2) {
969                         // We're at EOF, did we read any data previously?
970                         // If so return data available, else return no data
971                         // available
972                         if (au->parse_state == EVENT_ACCUMULATING) {
973                                 if (debug) printf("EOF, EVENT_EMITTED\n");
974                                 au->parse_state = EVENT_EMITTED;
975                                 return 1; // data is available
976                         }
977                         return 0;
978                 }
979                 if (rc > 0) {           // Input available
980                         rnode *r;
981                         if (extract_timestamp(au->cur_buf, &event)) {
982                                 if (debug)
983                                         printf("Malformed line:%s\n",
984                                                          au->cur_buf);
985                                 continue;
986                         }
987                         if (au->parse_state == EVENT_EMPTY) {
988                                 // First record in new event, initialize event
989                                 if (debug)
990                                         printf(
991                         "First record in new event, initialize event\n");
992                                 aup_list_set_event(&au->le, &event);
993                                 aup_list_append(&au->le, au->cur_buf,
994                                                 au->list_idx, au->line_number);
995                                 au->parse_state = EVENT_ACCUMULATING;
996                                 au->cur_buf = NULL; 
997                         } else if (events_are_equal(&au->le.e, &event)) {
998                                 // Accumulate data into existing event
999                                 if (debug)
1000                                         printf(
1001                                     "Accumulate data into existing event\n");
1002                                 aup_list_append(&au->le, au->cur_buf,
1003                                                 au->list_idx, au->line_number);
1004                                 au->parse_state = EVENT_ACCUMULATING;
1005                                 au->cur_buf = NULL; 
1006                         } else {
1007                                 // New event, save input for next invocation
1008                                 if (debug)
1009                                         printf(
1010         "New event, save current input for next invocation, EVENT_EMITTED\n");
1011                                 push_line(au);
1012                                 // Emit the event, set event cursors to 
1013                                 // initial position
1014                                 aup_list_first(&au->le);
1015                                 aup_list_first_field(&au->le);
1016                                 au->parse_state = EVENT_EMITTED;
1017                                 free((char *)event.host);
1018                                 return 1; // data is available
1019                         }
1020                         free((char *)event.host);
1021                         // Check to see if the event can be emitted due to EOE
1022                         // or something we know is a single record event. At
1023                         // this point, new record should be pointed at 'cur'
1024                         if ((r = aup_list_get_cur(&au->le)) == NULL)
1025                                 continue;
1026                         if (    r->type == AUDIT_EOE ||
1027                                 r->type < AUDIT_FIRST_EVENT ||
1028                                 r->type >= AUDIT_FIRST_ANOM_MSG) {
1029                                 // Emit the event, set event cursors to 
1030                                 // initial position
1031                                 aup_list_first(&au->le);
1032                                 aup_list_first_field(&au->le);
1033                                 au->parse_state = EVENT_EMITTED;
1034                                 return 1; // data is available
1035                         }
1036                 } else {                // Read error
1037                         return -1;
1038                 }
1039         }       
1040 }
1041
1042 /* Accessors to event data */
1043 const au_event_t *auparse_get_timestamp(auparse_state_t *au)
1044 {
1045         if (au && au->le.e.sec != 0)
1046                 return &au->le.e;
1047         else
1048                 return NULL;
1049 }
1050
1051
1052 time_t auparse_get_time(auparse_state_t *au)
1053 {
1054         if (au)
1055                 return au->le.e.sec;
1056         else
1057                 return 0;
1058 }
1059
1060
1061 unsigned int auparse_get_milli(auparse_state_t *au)
1062 {
1063         if (au)
1064                 return au->le.e.milli;
1065         else
1066                 return 0;
1067 }
1068
1069
1070 unsigned long auparse_get_serial(auparse_state_t *au)
1071 {
1072         if (au)
1073                 return au->le.e.serial;
1074         else
1075                 return 0;
1076 }
1077
1078
1079 // Gets the machine node name
1080 const char *auparse_get_node(auparse_state_t *au)
1081 {
1082         if (au && au->le.e.host != NULL)
1083                 return strdup(au->le.e.host);
1084         else
1085                 return NULL;
1086 }
1087
1088
1089 int auparse_node_compare(au_event_t *e1, au_event_t *e2)
1090 {
1091         // If both have a host, only a string compare can tell if they
1092         // are the same. Otherwise, if only one of them have a host, they
1093         // are definitely not the same. Its a boundary on daemon config.
1094         if (e1->host && e2->host) 
1095                 return strcmp(e1->host, e2->host);
1096         else if (e1->host)
1097                 return 1;
1098         else if (e2->host)
1099                 return -1;
1100
1101         return 0;
1102 }
1103
1104
1105 int auparse_timestamp_compare(au_event_t *e1, au_event_t *e2)
1106 {
1107         if (e1->sec > e2->sec)
1108                 return 1;
1109         if (e1->sec < e2->sec)
1110                 return -1;
1111
1112         if (e1->milli > e2->milli)
1113                 return 1;
1114         if (e1->milli < e2->milli)
1115                 return -1;
1116
1117         if (e1->serial > e2->serial)
1118                 return 1;
1119         if (e1->serial < e2->serial)
1120                 return -1;
1121
1122         return 0;
1123 }
1124
1125 unsigned int auparse_get_num_records(auparse_state_t *au)
1126 {
1127         return aup_list_get_cnt(&au->le);
1128 }
1129
1130
1131 /* Functions that traverse records in the same event */
1132 int auparse_first_record(auparse_state_t *au)
1133 {
1134         int rc;
1135
1136         if (aup_list_get_cnt(&au->le) == 0) {
1137                 rc = auparse_next_event(au);
1138                 if (rc <= 0)
1139                         return rc;
1140         }
1141         aup_list_first(&au->le);
1142         aup_list_first_field(&au->le);
1143         
1144         return 1;
1145 }
1146
1147
1148 int auparse_next_record(auparse_state_t *au)
1149 {
1150         if (aup_list_get_cnt(&au->le) == 0) { 
1151                 int rc = auparse_first_record(au);
1152                 if (rc <= 0)
1153                         return rc;
1154         }
1155         if (aup_list_next(&au->le))
1156                 return 1;
1157         else
1158                 return 0;
1159 }
1160
1161
1162 int auparse_goto_record_num(auparse_state_t *au, unsigned int num)
1163 {
1164         /* Check if a request is out of range */
1165         if (num >= aup_list_get_cnt(&au->le))
1166                 return 0;
1167
1168         if (aup_list_goto_rec(&au->le, num) != NULL)
1169                 return 1;
1170         else
1171                 return 0;
1172 }
1173
1174
1175 /* Accessors to record data */
1176 int auparse_get_type(auparse_state_t *au)
1177 {
1178         rnode *r = aup_list_get_cur(&au->le);
1179         if (r) 
1180                 return r->type;
1181         else
1182                 return 0;
1183 }
1184
1185
1186 const char *auparse_get_type_name(auparse_state_t *au)
1187 {
1188         rnode *r = aup_list_get_cur(&au->le);
1189         if (r)
1190                 return audit_msg_type_to_name(r->type);
1191         else
1192                 return NULL;
1193 }
1194
1195
1196 unsigned int auparse_get_line_number(auparse_state_t *au)
1197 {
1198         rnode *r = aup_list_get_cur(&au->le);
1199         if (r) 
1200                 return r->line_number;
1201         else
1202                 return 0;
1203 }
1204
1205
1206 const char *auparse_get_filename(auparse_state_t *au)
1207 {
1208         switch (au->source)
1209         {
1210                 case AUSOURCE_FILE:
1211                 case AUSOURCE_FILE_ARRAY:
1212                         break;
1213                 default:
1214                         return NULL;
1215         }
1216
1217         rnode *r = aup_list_get_cur(&au->le);
1218         if (r) {
1219                 if (r->list_idx < 0) return NULL;
1220                 return au->source_list[r->list_idx];
1221         } else {
1222                 return NULL;
1223         }
1224 }
1225
1226
1227 int auparse_first_field(auparse_state_t *au)
1228 {
1229         return aup_list_first_field(&au->le);
1230 }
1231
1232
1233 int auparse_next_field(auparse_state_t *au)
1234 {
1235         rnode *r = aup_list_get_cur(&au->le);
1236         if (r) {
1237                 if (nvlist_next(&r->nv))
1238                         return 1;
1239                 else
1240                         return 0;
1241         }
1242         return 0;
1243 }
1244
1245
1246 unsigned int auparse_get_num_fields(auparse_state_t *au)
1247 {
1248         rnode *r = aup_list_get_cur(&au->le);
1249         if (r)
1250                 return nvlist_get_cnt(&r->nv);
1251         else
1252                 return 0;
1253 }
1254
1255 const char *auparse_get_record_text(auparse_state_t *au)
1256 {
1257         rnode *r = aup_list_get_cur(&au->le);
1258         if (r) 
1259                 return r->record;
1260         else
1261                 return NULL;
1262 }
1263
1264
1265 /* scan from current location to end of event */
1266 const char *auparse_find_field(auparse_state_t *au, const char *name)
1267 {
1268         free(au->find_field);
1269         au->find_field = strdup(name);
1270
1271         if (au->le.e.sec) {
1272                 const char *cur_name;
1273                 rnode *r;
1274
1275                 // look at current record before moving
1276                 r = aup_list_get_cur(&au->le);
1277                 if (r == NULL)
1278                         return NULL;
1279                 cur_name = nvlist_get_cur_name(&r->nv);
1280                 if (cur_name && strcmp(cur_name, name) == 0)
1281                         return nvlist_get_cur_val(&r->nv);
1282
1283                 return auparse_find_field_next(au);
1284         }
1285         return NULL;
1286 }
1287
1288 /* Increment 1 location and then scan for next field */
1289 const char *auparse_find_field_next(auparse_state_t *au)
1290 {
1291         if (au->find_field == NULL) {
1292                 errno = EINVAL;
1293                 return NULL;
1294         }
1295         if (au->le.e.sec) {
1296                 int moved = 0;
1297
1298                 rnode *r = aup_list_get_cur(&au->le);
1299                 while (r) {     // For each record in the event...
1300                         if (!moved) {
1301                                 nvlist_next(&r->nv);
1302                                 moved=1;
1303                         }
1304                         if (nvlist_find_name(&r->nv, au->find_field))
1305                                 return nvlist_get_cur_val(&r->nv);
1306                         r = aup_list_next(&au->le);
1307                         if (r)
1308                                 aup_list_first_field(&au->le);
1309                 }
1310         }
1311         return NULL;
1312 }
1313
1314
1315 /* Accessors to field data */
1316 const char *auparse_get_field_name(auparse_state_t *au)
1317 {
1318         if (au->le.e.sec) {
1319                 rnode *r = aup_list_get_cur(&au->le);
1320                 if (r) 
1321                         return nvlist_get_cur_name(&r->nv);
1322         }
1323         return NULL;
1324 }
1325
1326
1327 const char *auparse_get_field_str(auparse_state_t *au)
1328 {
1329         if (au->le.e.sec) {
1330                 rnode *r = aup_list_get_cur(&au->le);
1331                 if (r) 
1332                         return nvlist_get_cur_val(&r->nv);
1333         }
1334         return NULL;
1335 }
1336
1337 int auparse_get_field_type(auparse_state_t *au)
1338 {
1339         if (au->le.e.sec) {
1340                 rnode *r = aup_list_get_cur(&au->le);
1341                 if (r)
1342                         return nvlist_get_cur_type(r);
1343         }
1344         return AUPARSE_TYPE_UNCLASSIFIED;
1345 }
1346
1347 int auparse_get_field_int(auparse_state_t *au)
1348 {
1349         const char *v = auparse_get_field_str(au);
1350         if (v) {
1351                 int val;
1352
1353                 errno = 0;
1354                 val = strtol(v, NULL, 10);
1355                 if (errno == 0)
1356                         return val;
1357         } else
1358                 errno = ENODATA;
1359         return -1;
1360 }
1361
1362
1363 const char *auparse_interpret_field(auparse_state_t *au)
1364 {
1365         if (au->le.e.sec) {
1366                 rnode *r = aup_list_get_cur(&au->le);
1367                 if (r)
1368                         return nvlist_interp_cur_val(r);
1369         }
1370         return NULL;
1371 }
1372