~ubuntu-branches/ubuntu/maverick/audit/maverick

« back to all changes in this revision

Viewing changes to auparse/auparse.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2007-06-29 13:05:14 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070629130514-z798cz4lebiahj5w
Tags: 1.5.4-0ubuntu1
* New upstream version.
* debian/patches/audit-1.5.1-dist.patch:
  * update so that it applies for 1.5.4.
* debian/control:
  * update Maintainer and XSBC-Original-Maintainer fields.
* debian/rules:
  * enable apparmor support: add --with-apparmor to configure options.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include <unistd.h>
31
31
 
32
32
 
 
33
static int debug = 0;
 
34
 
 
35
/* like strchr except string is delimited by length, not null byte */
 
36
static char *strnchr(const char *s, int c, size_t n)
 
37
{
 
38
    char *p_char;
 
39
    const char *p_end = s + n;
 
40
 
 
41
    for (p_char = (char *)s; p_char < p_end && *p_char != c; p_char++);
 
42
    if (p_char == p_end) return NULL;
 
43
    return p_char;
 
44
}
 
45
 
33
46
static int setup_log_file_array(auparse_state_t *au)
34
47
{
35
48
        struct daemon_conf config;
87
100
/* General functions that affect operation of the library */
88
101
auparse_state_t *auparse_init(ausource_t source, const void *b)
89
102
{
90
 
        char **tmp, **bb = (char **)b;
 
103
        char **tmp, **bb = (char **)b, *buf = (char *)b;
91
104
        int n, i;
 
105
        size_t size, len;
92
106
 
93
107
        auparse_state_t *au = malloc(sizeof(auparse_state_t));
94
108
        if (au == NULL) {
98
112
 
99
113
        au->in = NULL;
100
114
        au->source_list = NULL;
 
115
        databuf_init(&au->databuf, 0, 0);
 
116
        au->callback = NULL;
 
117
        au->callback_user_data = NULL;
 
118
        au->callback_user_data_destroy = NULL;
101
119
        switch (source)
102
120
        {
103
121
                case AUSOURCE_LOGS:
129
147
                        au->source_list = tmp;
130
148
                        break;
131
149
                case AUSOURCE_BUFFER:
132
 
                        tmp = malloc(2*sizeof(char *));
133
 
                        tmp[0] = strdup(b);
134
 
                        tmp[1] = NULL;
135
 
                        au->source_list = tmp;
 
150
                        buf = buf;
 
151
                        len = strlen(buf);
 
152
                        if (databuf_init(&au->databuf, len, DATABUF_FLAG_PRESERVE_HEAD) < 0) goto bad_exit;
 
153
                        if (databuf_append(&au->databuf, buf, len) < 0) goto bad_exit;
136
154
                        break;
137
155
                case AUSOURCE_BUFFER_ARRAY:
138
 
                        n = 0;
139
 
                        while (bb[n])
140
 
                                n++;
141
 
                        tmp = malloc((n+1)*sizeof(char *));
142
 
                        for (i=0; i<n; i++)
143
 
                                tmp[i] = strdup(bb[i]);
144
 
                        tmp[n] = NULL;
145
 
                        au->source_list = tmp;
 
156
                        size = 0;
 
157
                        for (n = 0; (buf = bb[n]); n++) {
 
158
                                len = strlen(bb[n]);
 
159
                                if (bb[n][len-1] != '\n') {
 
160
                                        size += len + 1;
 
161
                                } else {
 
162
                                        size += len;
 
163
                                }
 
164
                        }
 
165
                        if (databuf_init(&au->databuf, size, DATABUF_FLAG_PRESERVE_HEAD) < 0) goto bad_exit;
 
166
                        for (n = 0; (buf = bb[n]); n++) {
 
167
                                len = strlen(buf);
 
168
                                if (databuf_append(&au->databuf, buf, len) < 0) goto bad_exit;
 
169
                        }
146
170
                        break;
147
171
                case AUSOURCE_DESCRIPTOR:
148
172
                        n = (long)b;
151
175
                case AUSOURCE_FILE_POINTER:
152
176
                        au->in = (FILE *)b;
153
177
                        break;
 
178
                case AUSOURCE_FEED:
 
179
                    if (databuf_init(&au->databuf, 0, 0) < 0) goto bad_exit;
 
180
                        break;
154
181
                default:
155
182
                        errno = EINVAL;
156
183
                        return NULL;
158
185
        }
159
186
        au->source = source;
160
187
        au->list_idx = 0;
 
188
        au->line_number = 0;
161
189
        au->next_buf = NULL;
162
190
        au->off = 0;
163
191
        au->cur_buf = NULL;
164
 
        au->saved_buf = NULL;
 
192
        au->line_pushed = 0;
165
193
        aup_list_create(&au->le);
 
194
        au->parse_state = EVENT_EMPTY;
166
195
        aurule_create(&au->rules);
167
196
        au->find_field = NULL;
168
197
        au->search_where = AUSEARCH_STOP_EVENT;
170
199
 
171
200
        return au;
172
201
bad_exit:
 
202
        databuf_free(&au->databuf);
173
203
        free(au);
174
204
        return NULL;
175
205
}
176
206
 
177
207
 
 
208
void auparse_add_callback(auparse_state_t *au, auparse_callback_ptr callback,
 
209
                          void *user_data, user_destroy user_destroy_func)
 
210
{
 
211
        if (au->callback_user_data_destroy) {
 
212
                (*au->callback_user_data_destroy)(au->callback_user_data);
 
213
                au->callback_user_data = NULL;
 
214
        }
 
215
 
 
216
        au->callback = callback;
 
217
        au->callback_user_data = user_data;
 
218
        au->callback_user_data_destroy = user_destroy_func;
 
219
}
 
220
 
 
221
static void consume_feed(auparse_state_t *au, int flush)
 
222
{
 
223
        while (auparse_next_event(au) > 0) {
 
224
                if (au->callback) (*au->callback)(au, AUPARSE_CB_EVENT_READY, au->callback_user_data);
 
225
        }
 
226
        if (flush) {
 
227
                // FIXME: We might have to add a call here to force auparse_next_event()
 
228
                // to consume any partial data not fully consumed.
 
229
                if (au->parse_state == EVENT_ACCUMULATING) {
 
230
                        // Emit the event, set event cursors to initial position
 
231
                        aup_list_first(&au->le);
 
232
                        aup_list_first_field(&au->le);
 
233
                        au->parse_state = EVENT_EMITTED;
 
234
                        if (au->callback) (*au->callback)(au, AUPARSE_CB_EVENT_READY, au->callback_user_data);
 
235
                }
 
236
        }
 
237
}
 
238
 
 
239
int auparse_feed(auparse_state_t *au, const char *data, size_t data_len)
 
240
{
 
241
        if (databuf_append(&au->databuf, data, data_len) < 0) return -1;
 
242
        //if (debug) databuf_print(&au->databuf, 1, "auparse_feed() added %d bytes", data_len);
 
243
        consume_feed(au, 0);
 
244
        return 0;
 
245
}
 
246
 
 
247
int auparse_flush_feed(auparse_state_t *au)
 
248
{
 
249
        consume_feed(au, 1);
 
250
        return 0;
 
251
}
 
252
 
178
253
int auparse_reset(auparse_state_t *au)
179
254
{
180
255
        if (au == NULL) {
182
257
                return -1;
183
258
        }
184
259
 
 
260
        aup_list_clear(&au->le);
 
261
        au->parse_state = EVENT_EMPTY;
185
262
        switch (au->source)
186
263
        {
187
264
                case AUSOURCE_LOGS:
200
277
                case AUSOURCE_BUFFER:
201
278
                case AUSOURCE_BUFFER_ARRAY:
202
279
                        au->list_idx = 0;
 
280
                        au->line_number = 0;
203
281
                        au->off = 0;
 
282
                        databuf_reset(&au->databuf);
204
283
                        break;
 
284
                default:
 
285
                        return -1;
205
286
        }
206
287
        return 0;
207
288
}
326
407
                free(au->source_list);
327
408
                au->source_list = NULL;
328
409
        }
329
 
//      free(au->next_buf);
 
410
 
330
411
        au->next_buf = NULL;
331
412
        free(au->cur_buf);
332
413
        au->cur_buf = NULL;
333
 
        free(au->saved_buf);
334
 
        au->saved_buf = NULL;
335
414
        aup_list_clear(&au->le);
 
415
        au->parse_state = EVENT_EMPTY;
336
416
        free(au->find_field);
337
417
        au->find_field = NULL;
338
418
        ausearch_clear(au);
339
 
 
 
419
        databuf_free(&au->databuf);
 
420
        if (au->callback_user_data_destroy) {
 
421
                (*au->callback_user_data_destroy)(au->callback_user_data);
 
422
                au->callback_user_data = NULL;
 
423
        }
340
424
        aulookup_destroy_uid_list();
341
425
        aulookup_destroy_gid_list();
342
426
        if (au->in) {
351
435
 * successfully read a blank line (e.g. containing only a single newline).
352
436
 * cur_buf will have been newly allocated with malloc.
353
437
 * 
354
 
 * Returns < 0 on error, 0 if input is exhausted, and 1 if success.
355
 
 * 
356
438
 * Note: cur_buf will be freed the next time this routine is called if
357
439
 * cur_buf is not NULL, callers who retain a reference to the cur_buf
358
440
 * pointer will need to set cur_buf to NULL to cause the previous cur_buf
359
 
 * allocation to persist.*/
 
441
 * allocation to persist.
 
442
 *
 
443
 * Returns:
 
444
 *     1 if successful (errno == 0)
 
445
 *     0 if non-blocking input unavailable (errno == 0)
 
446
 *    -1 if error (errno contains non-zero error code)
 
447
 *    -2 if EOF  (errno == 0)
 
448
 */
360
449
 
361
450
static int readline_file(auparse_state_t *au)
362
451
{
373
462
                return -1;
374
463
        }
375
464
        if ((rc = getline(&au->cur_buf, &n, au->in)) <= 0) {
376
 
                if (rc < 0 && !feof(au->in)) return -1;
377
 
                return 0;
 
465
                // Note: getline always malloc's if lineptr==NULL or n==0,
 
466
                // on failure malloc'ed memory is left uninitialized, caller must free it.
 
467
                free(au->cur_buf);
 
468
                au->cur_buf = NULL;
 
469
 
 
470
                // Note: feof() does not set errno
 
471
                if (feof(au->in)) {
 
472
                        // return EOF condition
 
473
                        errno = 0;
 
474
                        return -2;
 
475
                }
 
476
                // return error condition, error code in errno
 
477
                return -1;
378
478
        }
379
479
        p_last_char = au->cur_buf + (rc-1);
380
480
        if (*p_last_char == '\n') {     /* nuke newline */
381
481
                *p_last_char = 0;
382
482
        }
 
483
        // return success
 
484
        errno = 0;
383
485
        return 1;
384
486
}
385
487
 
390
492
 * successfully read a blank line (e.g. containing only a single
391
493
 * newline).
392
494
 * 
393
 
 * Returns < 0 on error, 0 if input is exhausted, and 1 if success.
394
 
 * 
395
495
 * Note: cur_buf will be freed the next time this routine is called if
396
496
 * cur_buf is not NULL, callers who retain a reference to the cur_buf
397
497
 * pointer will need to set cur_buf to NULL to cause the previous cur_buf
398
 
 * allocation to persist.*/
 
498
 * allocation to persist.
 
499
 *
 
500
 * Returns:
 
501
 *     1 if successful (errno == 0)
 
502
 *     0 if non-blocking input unavailable (errno == 0)
 
503
 *    -1 if error (errno contains non-zero error code)
 
504
 *    -2 if EOF  (errno == 0)
 
505
 */
399
506
 
 
507
 
400
508
static int readline_buf(auparse_state_t *au)
401
509
{
402
 
        char *ptr,*new_ptr=NULL;
 
510
        char *p_newline=NULL;
 
511
        size_t line_len;
403
512
 
404
513
        if (au->cur_buf != NULL) {
405
514
                free(au->cur_buf);
406
515
                au->cur_buf = NULL;
407
516
        }
408
517
 
409
 
        ptr = au->next_buf + au->off;
410
 
        if (*ptr == 0)
 
518
        //if (debug) databuf_print(&au->databuf, 1, "readline_buf");
 
519
        if (au->databuf.len == 0) {
 
520
                // return EOF condition
 
521
                errno = 0;
 
522
                return -2;
 
523
        }
 
524
 
 
525
        if ((p_newline = strnchr(databuf_beg(&au->databuf), '\n', au->databuf.len)) != NULL) {
 
526
                line_len = p_newline - databuf_beg(&au->databuf);
 
527
                
 
528
                /* dup the line */
 
529
                au->cur_buf = malloc(line_len+1);   // +1 for null terminator
 
530
                if (au->cur_buf == NULL) return -1; // return error condition, errno set
 
531
                strncpy(au->cur_buf, databuf_beg(&au->databuf), line_len);
 
532
                au->cur_buf[line_len] = 0;
 
533
 
 
534
                if (databuf_advance(&au->databuf, line_len+1) < 0) return -1;
 
535
                // return success
 
536
                errno = 0;
 
537
                return 1;
 
538
        
 
539
        } else {
 
540
                // return no data available
 
541
                errno = 0;
411
542
                return 0;
412
 
 
413
 
        new_ptr = strchr(ptr, '\n');
414
 
        if (new_ptr) {
415
 
                // found a line dup it
416
 
                char tmp = *new_ptr;
417
 
                *new_ptr = 0;
418
 
                au->cur_buf = strdup(ptr);
419
 
                *new_ptr = tmp;
420
 
                au->off += strlen(au->cur_buf)+1;
421
 
                return 1;
422
 
        } else if (*ptr) {
423
 
                // there is text but no new line
424
 
                au->cur_buf = strdup(ptr);
425
 
                au->off += strlen(au->cur_buf);
426
 
                return 1;
427
543
        }
428
 
        
429
 
        return 0;
430
544
}
431
545
 
432
546
static int str2event(char *s, au_event_t *e)
512
626
 * cur_buf data it should copy the cur_buf pointer and set cur_buf to
513
627
 * NULL.
514
628
 *
515
 
 * Returns < 0 on error, 0 if input is exhausted, and 1 if success. */
 
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
 */
516
635
 
517
636
static int retrieve_next_line(auparse_state_t *au)
518
637
{
519
638
        int rc;
520
639
 
 
640
        // If line was pushed back for re-reading return that
 
641
        if (au->line_pushed) {
 
642
                // Starting new event, clear previous event data,
 
643
                // previous line is returned again for new parsing
 
644
                au->line_pushed = 0;
 
645
                au->line_number++;
 
646
                return 1;
 
647
        }
 
648
 
521
649
        switch (au->source)
522
650
        {
523
651
                case AUSOURCE_DESCRIPTOR:
524
652
                case AUSOURCE_FILE_POINTER:
525
 
                        return 0;
 
653
                        rc = readline_file(au);
 
654
                        if (rc > 0) au->line_number++;
 
655
                        return rc;
526
656
                case AUSOURCE_LOGS:
527
657
                case AUSOURCE_FILE:
528
658
                case AUSOURCE_FILE_ARRAY:
529
659
                        // if the first time through, open file
530
660
                        if (au->list_idx == 0 && au->in == NULL) {
 
661
                                au->line_number = 0;
531
662
                                au->in = fopen(au->source_list[au->list_idx], "r");
532
663
                                if (au->in == NULL) return -1;
533
664
                        }
534
665
 
535
666
                        // loop reading lines from a file
536
667
                        while (au->in) {
537
 
                                // Get next buffer from file
538
 
                                if ((rc = readline_file(au)) > 0) return 1;
539
 
                                if (rc < 0) return -1;
540
 
                                // end of file, open next file, try readline again
541
 
                                fclose(au->in);
542
 
                                au->in = NULL;
543
 
                                au->list_idx++;
544
 
                                if (au->source_list[au->list_idx]) {
545
 
                                        au->in = fopen(au->source_list[au->list_idx], "r");
546
 
                                        if (au->in == NULL) return -1;
 
668
                                if ((rc = readline_file(au)) == -2) {
 
669
                                        // end of file, open next file, try readline again
 
670
                                        fclose(au->in);
 
671
                                        au->in = NULL;
 
672
                                        au->list_idx++;
 
673
                                        au->line_number = 0;
 
674
                                        if (au->source_list[au->list_idx]) {
 
675
                                                au->in = fopen(au->source_list[au->list_idx], "r");
 
676
                                                if (au->in == NULL) return -1;
 
677
                                        }
 
678
                                } else {
 
679
                                        if (rc > 0) au->line_number++;
 
680
                                        return rc;
547
681
                                }
548
682
                        }
549
 
                        return 0;
 
683
                        return -2;      // return EOF
550
684
                case AUSOURCE_BUFFER:
551
685
                case AUSOURCE_BUFFER_ARRAY:
552
 
                        if (au->list_idx == 0 && au->next_buf == NULL)
553
 
                                au->next_buf = au->source_list[au->list_idx];
554
 
 
555
 
                        while (au->next_buf) {
556
 
                                if (readline_buf(au) > 0) return 1;
557
 
                                // end of buffer, advance to next buffer, try readline again
558
 
                                au->off = 0;
559
 
                                au->list_idx++;
560
 
                                au->next_buf = au->source_list[au->list_idx];
561
 
                        }
562
 
                        return 0;
 
686
                        rc = readline_buf(au);
 
687
                        if (rc > 0) au->line_number++;
 
688
                        return rc;
 
689
                case AUSOURCE_FEED:
 
690
                        rc = readline_buf(au);
 
691
                        // No such thing as EOF for feed, translate EOF to data not available
 
692
                        if (rc == -2)
 
693
                                return 0;
 
694
                        else
 
695
                                if (rc > 0) au->line_number++;
 
696
                                return rc;
563
697
                default:
564
698
                        return -1;
565
699
        }
566
700
        return -1;              /* should never reach here */
567
701
}
568
702
 
 
703
static void push_line(auparse_state_t *au)
 
704
{
 
705
        au->line_number--;
 
706
        au->line_pushed = 1;
 
707
}
 
708
 
569
709
/*******
570
710
* Functions that traverse events.
571
711
********/
670
810
int auparse_next_event(auparse_state_t *au)
671
811
{
672
812
        int rc;
673
 
 
674
 
        if (au == NULL)
675
 
                return -1;
676
 
 
677
 
        // Tear down old event info
678
 
        aup_list_clear(&au->le);
679
 
 
680
 
        // Get the next line
681
 
        if (au->saved_buf) {
682
 
                au->cur_buf = au->saved_buf;
683
 
                au->saved_buf = NULL;
684
 
        } else {
 
813
        au_event_t event;
 
814
 
 
815
        if (au->parse_state == EVENT_EMITTED) {
 
816
                // If the last call resulted in emitting event data then
 
817
                // clear previous event data in preparation to accumulate new event data
 
818
                aup_list_clear(&au->le);
 
819
                au->parse_state = EVENT_EMPTY;
 
820
        }
 
821
 
 
822
        // accumulate new event data
 
823
        while (1) {
685
824
                rc = retrieve_next_line(au);
686
 
                if (rc <= 0)
687
 
                        return rc;      // Error or empty
688
 
        }
689
 
 
690
 
        do {
691
 
                au_event_t e;
692
 
 
693
 
                extract_timestamp(au->cur_buf, &e);
694
 
                if (au->le.cnt == 0)
695
 
                        aup_list_set_event(&au->le, &e);
696
 
 
697
 
                if (events_are_equal(&au->le.e, &e)) {
698
 
                        // If they are equal, add this to the event
699
 
                        aup_list_append(&au->le, &e, au->cur_buf);
700
 
 
701
 
                        // The list took custody of the line so empty pointer
702
 
                        au->cur_buf = NULL;
703
 
 
704
 
                        rc = retrieve_next_line(au);
705
 
                        if (rc < 0)
706
 
                                return rc;      // Error stop
707
 
                        else if (rc == 0) 
708
 
                                goto reset_current; // Consumed all data
709
 
                } else {
710
 
                        // Events are not equal...stop...emit event
711
 
                        au->saved_buf = au->cur_buf;
712
 
                        au->cur_buf = NULL;
713
 
                        goto reset_current;
714
 
                }
715
 
        } while (1);
716
 
 
717
 
reset_current:
718
 
        // Set cursor to first record of new event
719
 
        aup_list_first(&au->le);
720
 
        // Set field cursor to 1st field of cur record
721
 
        aup_list_first_field(&au->le);
722
 
        if (aup_list_get_cnt(&au->le))
723
 
                return 1;
724
 
        else
725
 
                return 0;
 
825
                if (debug) printf("next_line(%d) '%s'\n", rc, au->cur_buf);
 
826
                if (rc ==  0) return 0; // No data now
 
827
                if (rc == -2) {
 
828
                        // We're at EOF, did we read any data previously?
 
829
                        // If so return data available, else return no data available
 
830
                        if (au->parse_state == EVENT_ACCUMULATING) {
 
831
                                if (debug) printf("EOF, EVENT_EMITTED\n");
 
832
                                au->parse_state = EVENT_EMITTED;
 
833
                                return 1; // data is available
 
834
                        }
 
835
                        return 0;
 
836
                }
 
837
                if (rc > 0) {           // Input available
 
838
                        extract_timestamp(au->cur_buf, &event);
 
839
                        if (au->parse_state == EVENT_EMPTY) {
 
840
                                // First record in new event, initialize event
 
841
                                if (debug) printf("First record in new event, initialize event\n");
 
842
                                aup_list_set_event(&au->le, &event);
 
843
                                aup_list_append(&au->le, au->cur_buf, au->list_idx, au->line_number);
 
844
                                au->parse_state = EVENT_ACCUMULATING;
 
845
                                au->cur_buf = NULL; 
 
846
                        } else if (events_are_equal(&au->le.e, &event)) {
 
847
                                // Accumulate data into existing event
 
848
                                if (debug) printf("Accumulate data into existing event\n");
 
849
                                aup_list_append(&au->le, au->cur_buf, au->list_idx, au->line_number);
 
850
                                au->parse_state = EVENT_ACCUMULATING;
 
851
                                au->cur_buf = NULL; 
 
852
                        } else {
 
853
                                // New event, save current input for next invocation
 
854
                                if (debug) printf("New event, save current input for next invocation, EVENT_EMITTED\n");
 
855
                                push_line(au);
 
856
                                // Emit the event, set event cursors to initial position
 
857
                                aup_list_first(&au->le);
 
858
                                aup_list_first_field(&au->le);
 
859
                                au->parse_state = EVENT_EMITTED;
 
860
                                return 1; // data is available
 
861
                        }
 
862
                } else {                // Read error
 
863
                        return -1;
 
864
                }
 
865
        }       
726
866
}
727
867
 
728
868
 
838
978
}
839
979
 
840
980
 
 
981
unsigned int auparse_get_line_number(auparse_state_t *au)
 
982
{
 
983
        rnode *r = aup_list_get_cur(&au->le);
 
984
        if (r) 
 
985
                return r->line_number;
 
986
        else
 
987
                return 0;
 
988
}
 
989
 
 
990
 
 
991
const char *auparse_get_filename(auparse_state_t *au)
 
992
{
 
993
        switch (au->source)
 
994
        {
 
995
                case AUSOURCE_FILE:
 
996
                case AUSOURCE_FILE_ARRAY:
 
997
                        break;
 
998
                default:
 
999
                        return NULL;
 
1000
        }
 
1001
 
 
1002
        rnode *r = aup_list_get_cur(&au->le);
 
1003
        if (r) {
 
1004
                if (r->list_idx < 0) return NULL;
 
1005
                return au->source_list[r->list_idx];
 
1006
        } else {
 
1007
                return NULL;
 
1008
        }
 
1009
}
 
1010
 
 
1011
 
841
1012
int auparse_first_field(auparse_state_t *au)
842
1013
{
843
1014
        return aup_list_first_field(&au->le);