Imported Upstream version 2.4.3
[platform/upstream/audit.git] / bindings / python / auparse_python.c
1 #include <Python.h>
2 #include "structmember.h"
3
4 #include <errno.h>
5 #include <time.h>
6 #include "auparse.h"
7
8 /*
9 auparse functions explicitly not exported in this binding and why:
10
11 auparse_destroy:        because this is handled by python object management
12 auparse_get_time:       because AuEvent provides this as an attribute
13 auparse_get_milli:      because AuEvent provides this as an attribute
14 auparse_get_serial:     because AuEvent provides this as an attribute
15 auparse_get_node:       because AuEvent provides this as an attribute
16 auparse_timestamp_compare: because AuEvent calls this via the cmp operator
17
18 */
19
20 #if PY_MAJOR_VERSION > 2
21 #define IS_PY3K
22 #define MODINITERROR return NULL
23 #define PYNUM_FROMLONG PyLong_FromLong
24 #define PYSTR_CHECK PyUnicode_Check
25 #define PYSTR_FROMSTRING PyUnicode_FromString
26 #define PYSTR_ASSTRING PyUnicode_AsUTF8
27 #define PYFILE_ASFILE(f) fdopen(PyObject_AsFileDescriptor(f), "r")
28 int PyFile_Check(PyObject *f) {
29     PyObject *io, *base;
30     if (!(io = PyImport_ImportModule("io"))) {
31         return 0;
32     } else {
33         if (!(base = PyObject_GetAttrString(io, "TextIOBase"))) {
34             return 0;
35         } else {
36             return PyObject_IsInstance(f, base);
37         }
38     }
39 }
40 #else
41 #define MODINITERROR return
42 #define PYNUM_FROMLONG PyInt_FromLong
43 #define PYSTR_CHECK PyString_Check
44 #define PYSTR_FROMSTRING PyString_FromString
45 #define PYSTR_ASSTRING PyString_AsString
46 #define PYFILE_ASFILE(f) PyFile_AsFile(f)
47 #endif
48
49 static int debug = 0;
50 static PyObject *NoParserError = NULL;
51
52 /*===========================================================================
53  *                                AuEvent
54  *===========================================================================*/
55
56 typedef struct {
57     PyObject_HEAD
58     PyObject *sec;
59     PyObject *milli;
60     PyObject *serial;
61     PyObject *host;
62     au_event_t event;
63 } AuEvent;
64
65 static void
66 AuEvent_dealloc(AuEvent* self)
67 {
68     Py_XDECREF(self->sec);
69     Py_XDECREF(self->milli);
70     Py_XDECREF(self->serial);
71     Py_XDECREF(self->host);
72     Py_TYPE(self)->tp_free((PyObject*)self);
73 }
74
75 static int
76 AuEvent_compare(PyObject *obj1, PyObject *obj2)
77 {
78     AuEvent *au_event1 = (AuEvent *) obj1;
79     AuEvent *au_event2 = (AuEvent *) obj2;
80
81     return auparse_timestamp_compare(&au_event1->event, &au_event2->event);
82 }
83
84 static PyObject *
85 AuEvent_get_sec(AuEvent *self, void *closure)
86 {
87     if (self->sec == NULL) {
88         if ((self->sec = PYNUM_FROMLONG(self->event.sec)) == NULL) return NULL;
89     }
90     Py_INCREF(self->sec);
91     return self->sec;
92 }
93
94 static PyObject *
95 AuEvent_get_milli(AuEvent *self, void *closure)
96 {
97     if (self->milli == NULL) {
98         if ((self->milli = PYNUM_FROMLONG(self->event.milli)) == NULL) return NULL;
99     }
100     Py_INCREF(self->milli);
101     return self->milli;
102 }
103
104 static PyObject *
105 AuEvent_get_serial(AuEvent *self, void *closure)
106 {
107     if (self->serial == NULL) {
108         if ((self->serial = PYNUM_FROMLONG(self->event.serial)) == NULL) return NULL;
109     }
110     Py_INCREF(self->serial);
111     return self->serial;
112 }
113
114 static PyObject *
115 AuEvent_get_host(AuEvent *self, void *closure)
116 {
117     if (self->event.host == NULL) {
118         Py_RETURN_NONE;
119     } else {
120         if (self->host == NULL) {
121             if ((self->host = PYSTR_FROMSTRING(self->event.host)) == NULL) return NULL;
122         }
123         Py_INCREF(self->host);
124         return self->host;
125     }
126 }
127
128 static PyGetSetDef AuEvent_getseters[] = {
129     {"sec",    (getter)AuEvent_get_sec,    (setter)NULL, "Event seconds", NULL},
130     {"milli",  (getter)AuEvent_get_milli,  (setter)NULL, "millisecond of the timestamp", NULL},
131     {"serial", (getter)AuEvent_get_serial, (setter)NULL, "Serial number of the event", NULL},
132     {"host",   (getter)AuEvent_get_host,   (setter)NULL, "Machine's name", NULL},
133     {NULL}  /* Sentinel */
134 };
135
136 static PyMemberDef AuEvent_members[] = {
137     {NULL}  /* Sentinel */
138 };
139
140 static char *
141 fmt_event(time_t seconds, unsigned int milli, unsigned long serial, const char *host)
142 {
143     static char buf1[200], buf2[200];
144     char fmt[] = "%a %b %d %H:%M:%S.%%ld %Y serial=%%ld host=%%s";
145     struct tm *tmp;
146
147     tmp = localtime(&seconds);
148     if (tmp == NULL) {
149         sprintf(buf2, "localtime error");
150         return buf2;
151     }
152
153     if (strftime(buf1, sizeof(buf1), fmt, tmp) == 0) {
154         sprintf(buf2, "strftime returned 0");
155         return buf2;
156     }
157
158     snprintf(buf2, sizeof(buf2), buf1, milli, serial, host, sizeof(buf2));
159     return buf2;
160 }
161
162 static PyObject *
163 AuEvent_str(PyObject * obj)
164 {
165     AuEvent *event = (AuEvent *) obj;
166     return PYSTR_FROMSTRING(fmt_event(event->event.sec, event->event.milli, event->event.serial, event->event.host));
167 }
168
169
170 static PyMethodDef AuEvent_methods[] = {
171     {NULL}  /* Sentinel */
172 };
173
174 PyDoc_STRVAR(AuEvent_doc,
175 "An internal object which encapsulates the timestamp, serial number\n\
176 and host information of an audit event. The object cannot be\n\
177 instantiated from python code, rather it is returned from the\n\
178 audit parsing API.");
179
180 static PyTypeObject AuEventType = {
181     PyVarObject_HEAD_INIT(NULL, 0)
182     "auparse.AuEvent",         /*tp_name*/
183     sizeof(AuEvent),           /*tp_basicsize*/
184     0,                         /*tp_itemsize*/
185     (destructor)AuEvent_dealloc, /*tp_dealloc*/
186     0,                         /*tp_print*/
187     0,                         /*tp_getattr*/
188     0,                         /*tp_setattr*/
189     AuEvent_compare,           /*tp_compare*/
190     0,                         /*tp_repr*/
191     0,                         /*tp_as_number*/
192     0,                         /*tp_as_sequence*/
193     0,                         /*tp_as_mapping*/
194     0,                         /*tp_hash */
195     0,                         /*tp_call*/
196     AuEvent_str,               /*tp_str*/
197     0,                         /*tp_getattro*/
198     0,                         /*tp_setattro*/
199     0,                         /*tp_as_buffer*/
200     Py_TPFLAGS_DEFAULT,        /*tp_flags*/
201     AuEvent_doc,               /* tp_doc */
202     0,                         /* tp_traverse */
203     0,                         /* tp_clear */
204     0,                         /* tp_richcompare */
205     0,                         /* tp_weaklistoffset */
206     0,                         /* tp_iter */
207     0,                         /* tp_iternext */
208     AuEvent_methods,           /* tp_methods */
209     AuEvent_members,                        /* tp_members */
210     AuEvent_getseters,         /* tp_getset */
211     0,                         /* tp_base */
212     0,                         /* tp_dict */
213     0,                         /* tp_descr_get */
214     0,                         /* tp_descr_set */
215     0,                         /* tp_dictoffset */
216     0,                         /* tp_init */
217     0,                         /* tp_alloc */
218     0,               /* tp_new */
219 };
220
221 static PyObject *
222 AuEvent_new_from_struct(au_event_t const *event_ptr)
223 {
224     AuEvent *self;
225
226     self = (AuEvent *)AuEventType.tp_alloc(&AuEventType, 0);
227     if (self != NULL) {
228         self->event = *event_ptr;
229     }
230
231     return (PyObject *)self;
232 }
233
234 /*===========================================================================
235  *                                AuParser
236  *===========================================================================*/
237
238 #define PARSER_CHECK                                                               \
239     if (self->au == NULL) {                                                        \
240         PyErr_SetString(NoParserError, "object has no parser associated with it"); \
241         return NULL;                                                               \
242     }
243
244 typedef struct {
245     PyObject_HEAD
246     auparse_state_t *au;
247 } AuParser;
248
249 typedef struct {
250     AuParser *py_AuParser;
251     PyObject *func;
252     PyObject *user_data;
253 } CallbackData;
254
255 void callback_data_destroy(void *user_data)
256 {
257     CallbackData *cb = (CallbackData *)user_data;
258
259     if (debug) printf("<< callback_data_destroy\n");
260     if (cb) {
261         Py_DECREF(cb->func);
262         Py_XDECREF(cb->user_data);
263         PyMem_Del(cb);
264     }
265 }
266
267 static void auparse_callback(auparse_state_t *au, auparse_cb_event_t cb_event_type, void *user_data)
268 {
269     CallbackData *cb = (CallbackData *)user_data;
270     PyObject *arglist;
271     PyObject *result;
272
273     arglist = Py_BuildValue("OiO", cb->py_AuParser, cb_event_type, cb->user_data);
274     result = PyEval_CallObject(cb->func, arglist);
275     Py_DECREF(arglist);
276     Py_XDECREF(result);
277 }
278
279 static void
280 AuParser_dealloc(AuParser* self)
281 {
282     if (debug) printf("<< AuParser_dealloc: self=%p au=%p\n", self, self->au);
283     if (self->au != NULL) {
284         auparse_destroy(self->au);
285     }
286     Py_TYPE(self)->tp_free((PyObject*)self);
287 }
288
289 static PyObject *
290 AuParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
291 {
292     AuParser *self;
293
294     self = (AuParser *)type->tp_alloc(type, 0);
295     if (self != NULL) {
296         self->au = NULL;
297     }
298     return (PyObject *)self;
299 }
300
301 /********************************
302  * auparse_init
303  ********************************/
304 static int
305 AuParser_init(AuParser *self, PyObject *args, PyObject *kwds)
306 {
307     static char *kwlist[] = {"source_type", "source", NULL};
308     int source_type = -1;
309     PyObject  *source=Py_None;
310
311     if (self->au != NULL) {
312         auparse_destroy(self->au);
313         self->au = NULL;
314     }
315
316     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &source_type, &source)) return -1; 
317
318     switch (source_type) {
319     case AUSOURCE_LOGS: {
320         if (source != Py_None) {
321             PyErr_SetString(PyExc_ValueError, "source must be None or not passed as a parameter when source_type is AUSOURCE_LOGS");
322             return -1;
323         }
324         if ((self->au = auparse_init(source_type, NULL)) == NULL) {
325             PyErr_SetFromErrno(PyExc_IOError);
326             return -1;
327         }
328     } break;
329     case AUSOURCE_FILE: {
330         char *filename = NULL;
331
332         if (!PYSTR_CHECK(source)) {
333             PyErr_SetString(PyExc_ValueError, "source must be a string when source_type is AUSOURCE_FILE");
334             return -1;
335         }
336         if ((filename = PYSTR_ASSTRING(source)) == NULL) return -1;
337         if ((self->au = auparse_init(source_type, filename)) == NULL) {
338             PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
339             return -1;
340         }
341     } break;
342     case AUSOURCE_FILE_ARRAY: {
343         int i, n;
344         PyObject *item = NULL;
345         char **files = NULL;
346
347         if (PySequence_Check(source)) {
348             n = PySequence_Size(source);
349             if ((files = PyMem_New(char *, n+1)) == NULL) {
350                 PyErr_NoMemory();
351                 return -1;
352             }
353             for (i = 0; i < n; i++) {
354                 item = PySequence_GetItem(source, i);
355                 if ((files[i] = PYSTR_ASSTRING(item)) == NULL) {
356                     PyErr_SetString(PyExc_ValueError, "members of source sequence must be a string when source_type is AUSOURCE_FILE_ARRAY");
357                     Py_DECREF(item);
358                     PyMem_Del(files);
359                     return -1;
360                 } else {
361                     Py_DECREF(item);
362                 }
363             }
364             files[i] = NULL;
365         } else {
366             PyErr_SetString(PyExc_ValueError, "source must be a sequence when source_type is AUSOURCE_FILE_ARRAY");
367             return -1;
368         }
369         
370         if ((self->au = auparse_init(source_type, files)) == NULL) {
371             PyErr_SetFromErrno(PyExc_IOError);
372             PyMem_Del(files);
373             return -1;
374         }
375         PyMem_Del(files);
376     } break;
377     case AUSOURCE_BUFFER: {
378         char *buf;
379         if ((buf = PYSTR_ASSTRING(source)) == NULL) return -1;
380         if ((self->au = auparse_init(source_type, buf)) == NULL) {
381             PyErr_SetFromErrno(PyExc_EnvironmentError);
382             return -1;
383         }
384     } break;
385     case AUSOURCE_BUFFER_ARRAY: {
386         int i, n;
387         PyObject *item = NULL;
388         char **buffers = NULL;
389
390         if (PySequence_Check(source)) {
391             n = PySequence_Size(source);
392             if ((buffers = PyMem_New(char *, n+1)) == NULL) {
393                 PyErr_NoMemory();
394                 return -1;
395             }
396             for (i = 0; i < n; i++) {
397                 item = PySequence_GetItem(source, i);
398                 if ((buffers[i] = PYSTR_ASSTRING(item)) == NULL) {
399                     PyErr_SetString(PyExc_ValueError, "members of source sequence must be a string when source_type is AUSOURCE_BUFFER_ARRAY");
400                     Py_DECREF(item);
401                     PyMem_Del(buffers);
402                     return -1;
403                 } else {
404                     Py_DECREF(item);
405                 }
406             }
407             buffers[i] = NULL;
408         } else {
409             PyErr_SetString(PyExc_ValueError, "source must be a sequence when source_type is AUSOURCE_FILE_ARRAY");
410             return -1;
411         }
412         
413         if ((self->au = auparse_init(source_type, buffers)) == NULL) {
414             PyErr_SetFromErrno(PyExc_EnvironmentError);
415             PyMem_Del(buffers);
416             return -1;
417         }
418         PyMem_Del(buffers);
419     } break;
420     case AUSOURCE_DESCRIPTOR: {
421         int fd;
422         fd = PyObject_AsFileDescriptor(source);
423         if (fd < 0) {
424             PyErr_SetString(PyExc_ValueError, "source must be resolvable to a file descriptor when source_type is AUSOURCE_DESCRIPTOR");
425             return -1;
426         }
427     } break;
428     case AUSOURCE_FILE_POINTER: {
429         FILE* fp;
430
431         if (!PyFile_Check(source)) {
432             PyErr_SetString(PyExc_ValueError, "source must be a file object when source_type is AUSOURCE_FILE_POINTER");
433             return -1;
434         }
435         if ((fp = PYFILE_ASFILE(source)) == NULL) {
436             PyErr_SetString(PyExc_TypeError, "source must be open file when source_type is AUSOURCE_FILE_POINTER");
437             return -1;
438         }
439         if ((self->au = auparse_init(source_type, fp)) == NULL) {
440             //char *filename = PYSTR_ASSTRING(PyFile_Name(source));
441             char *filename = "TODO";
442             PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
443             return -1;
444         }
445     } break;
446     case AUSOURCE_FEED: {
447         if (source != Py_None) {
448             PyErr_SetString(PyExc_ValueError, "source must be None when source_type is AUSOURCE_FEED");
449             return -1;
450         }
451         if ((self->au = auparse_init(source_type, NULL)) == NULL) {
452             PyErr_SetFromErrno(PyExc_EnvironmentError);
453             return -1;
454         }
455     } break;
456     default: {
457         PyErr_SetString(PyExc_ValueError, "Invalid source type");
458         return -1;
459     } break;
460     }
461
462     if (debug) printf(">> AuParser_init: self=%p au=%p\n", self, self->au);
463     return 0;
464 }
465
466 /********************************
467  * auparse_feed
468  ********************************/
469 PyDoc_STRVAR(feed_doc,
470 "feed(data) supplies new data for the parser to consume.\n\
471 \n\
472 AuParser() must have been called with a source type of AUSOURCE_FEED.\n\
473 The parser consumes as much data as it can invoking a user supplied\n\
474 callback specified with add_callback() with a cb_event_type of\n\
475 AUPARSE_CB_EVENT_READY each time the parser recognizes a complete event\n\
476 in the data stream. Data not fully parsed will persist and be prepended\n\
477 to the next feed data. After all data has been feed to the parser flush_feed()\n\
478 should be called to signal the end of input data and flush any pending\n\
479 parse data through the parsing system.\n\
480 \n\
481 Returns None.\n\
482 Raises exception (EnvironmentError) on error\n\
483 ");
484 static PyObject *
485 AuParser_feed(AuParser *self, PyObject *args)
486 {
487     char *data;
488     int data_len;
489     int result;
490
491     if (!PyArg_ParseTuple(args, "s#:feed", &data, &data_len)) return NULL;
492     PARSER_CHECK;
493     result = auparse_feed(self->au, data, data_len);
494     if (result ==  0) Py_RETURN_NONE;
495     PyErr_SetFromErrno(PyExc_EnvironmentError);
496     return NULL;
497 }
498
499 /********************************
500  * auparse_flush_feed
501  ********************************/
502 PyDoc_STRVAR(flush_feed_doc,
503 "flush_feed() flush any unconsumed feed data through parser\n\
504 \n\
505 flush_feed() should be called to signal the end of feed input data\n\
506 and flush any pending parse data through the parsing system.\n\
507 \n\
508 Returns None.\n\
509 Raises exception (EnvironmentError) on error\n\
510 ");
511 static PyObject *
512 AuParser_flush_feed(AuParser *self)
513 {
514     int result;
515
516     PARSER_CHECK;
517     result = auparse_flush_feed(self->au);
518     if (result ==  0) Py_RETURN_NONE;
519     PyErr_SetFromErrno(PyExc_EnvironmentError);
520     return NULL;
521 }
522
523 /********************************
524  * auparse_add_callback
525  ********************************/
526 PyDoc_STRVAR(add_callback_doc,
527 "add_callback(callback, user_data) add a callback handler for notifications.\n\
528 \n\
529 auparse_add_callback adds a callback function to the parse state which\n\
530 is invoked to notify the application of parsing events.\n\
531 \n\
532 The signature of the callback is:\n\
533 \n\
534 callback(au, cb_event_type,user_data)\n\
535 \n\
536 When the callback is invoked it is passed:\n\
537 au: the AuParser object\n\
538 cb_event_type: enumerated value indicating the reason why the callback was invoked\n\
539 user_data: user supplied private data\n\
540 \n\
541 The cb_event_type argument indicates why the callback was invoked.\n\
542 It's possible values are:\n\
543 \n\
544 AUPARSE_CB_EVENT_READY\n\
545 A complete event has been parsed and is ready to be examined.\n\
546 This is logically equivalent to the parse state immediately following\n\
547 auparse_next_event()\n\
548 \n\
549 Returns None.\n\
550 Raises exception (EnvironmentError) on error\n\
551 ");
552 static PyObject *
553 AuParser_add_callback(AuParser *self, PyObject *args)
554 {
555     PyObject *func;
556     PyObject *user_data;
557
558     if (!PyArg_ParseTuple(args, "O|O:add_callback", &func, &user_data)) return NULL;
559     if (!PyFunction_Check(func)) {
560         PyErr_SetString(PyExc_ValueError, "callback must be a function");
561         return NULL;
562     }
563     PARSER_CHECK;
564
565     {
566         CallbackData *cb;
567
568         cb = PyMem_New(CallbackData, 1);
569         if (cb == NULL)
570             return PyErr_NoMemory();
571         cb->py_AuParser = self;
572         cb->func = func;
573         cb->user_data = user_data;
574         Py_INCREF(cb->func);
575         Py_XINCREF(cb->user_data);
576         auparse_add_callback(self->au, auparse_callback, cb, callback_data_destroy);
577 }
578
579     Py_RETURN_NONE;
580 }
581
582 /********************************
583  * auparse_reset
584  ********************************/
585 PyDoc_STRVAR(reset_doc,
586 "reset() Reset audit parser instance\n\
587 \n\
588 reset resets all internal cursors to the beginning.\n\
589 It closes files and descriptors.\n\
590 \n\
591 Returns None.\n\
592 Raises exception (EnvironmentError) on error\n\
593 ");
594 static PyObject *
595 AuParser_reset(AuParser *self)
596 {
597     int result;
598
599     PARSER_CHECK;
600     result = auparse_reset(self->au);
601     if (result ==  0) Py_RETURN_NONE;
602     PyErr_SetFromErrno(PyExc_EnvironmentError);
603     return NULL;
604 }
605
606 /********************************
607  * ausearch_add_expression
608  ********************************/
609 PyDoc_STRVAR(search_add_expression_doc,
610 "search_add_expression(expression, how) Build up search expression\n\
611 \n\
612 \n\
613 ausearch_add_item adds an expression to the current audit search\n\
614 expression.  The search conditions can then be used to scan logs,\n\
615 files, or buffers for something of interest.  The expression parameter\n\
616 contains an expression, as specified in ausearch-expression(5).\n\
617 \n\
618 The how parameter determines how this search expression will affect the\n\
619 existing search expression, if one is already defined.  The possible\n\
620 values are:\n\
621 \n\
622 AUSEARCH_RULE_CLEAR:\n\
623 Clear the current search expression, if any, and use only this search\n\
624 expression.\n\
625 \n\
626 AUSEARCH_RULE_OR:\n\
627 \n\
628 If a search expression E is already configured, replace it by\n\
629 (E || this_search_expression).\n\
630 \n\
631 AUSEARCH_RULE_AND:\n\
632 If a search expression E is already configured, replace it by\n\
633 (E && this_search_expression).\n\
634 \n\
635 No Return value, raises exception (EnvironmentError) on error.\n\
636 ");
637 static PyObject *
638 AuParser_search_add_expression(AuParser *self, PyObject *args)
639 {
640     const char *expression;
641     char *error;
642     int how;
643     int result;
644
645     if (!PyArg_ParseTuple(args, "si", &expression, &how)) return NULL;
646     PARSER_CHECK;
647
648     result = ausearch_add_expression(self->au, expression, &error, how);
649     if (result == 0) Py_RETURN_NONE;
650     if (error == NULL)
651         PyErr_SetFromErrno(PyExc_EnvironmentError);
652     else {
653         PyErr_SetString(PyExc_EnvironmentError, error);
654         free(error);
655     }
656     return NULL;
657 }
658
659 /********************************
660  * ausearch_add_item
661  ********************************/
662 PyDoc_STRVAR(search_add_item_doc,
663 "search_add_item(field, op, value, how) Build up search rule\n\
664 \n\
665 \n\
666 search_add_item() adds one search condition to the current audit search\n\
667 expression. The search conditions can then be used to scan logs, files, or\n\
668 buffers for something of interest. The field value is the field name\n\
669 that the value will be checked for. The op variable describes what\n\
670 kind of check is to be done. Legal op values are:\n\
671 \n\
672 'exists':\n\
673 Just check that a field name exists\n\
674 \n\
675 '=':\n\
676 locate the field name and check that the value associated with it\n\
677 is equal to the value given in this rule.\n\
678 \n\
679 '!=':\n\
680 locate the field name and check that the value associated with\n\
681 it is NOT equal to the value given in this rule.\n\
682 \n\
683 The value parameter is compared to the uninterpreted field value.\n\
684 \n\
685 The how parameter determines how this search expression will affect the\n\
686 existing search expression, if one is already defined.  The possible\n\
687 values are:\n\
688 \n\
689 AUSEARCH_RULE_CLEAR:\n\
690 Clear the current search expression, if any, and use only this search\n\
691 expression.\n\
692 \n\
693 AUSEARCH_RULE_OR:\n\
694 \n\
695 If a search expression E is already configured, replace it by\n\
696 (E || this_search_expression).\n\
697 \n\
698 AUSEARCH_RULE_AND:\n\
699 If a search expression E is already configured, replace it by\n\
700 (E && this_search_expression).\n\
701 \n\
702 No Return value, raises exception (EnvironmentError) on error.\n\
703 ");
704
705 static PyObject *
706 AuParser_search_add_item(AuParser *self, PyObject *args)
707 {
708     const char *field;
709     const char *op;
710     const char *value;
711     int how;
712     int result;
713
714     if (!PyArg_ParseTuple(args, "sssi", &field, &op, &value, &how)) return NULL;
715     PARSER_CHECK;
716
717     result = ausearch_add_item(self->au, field, op, value, how);
718     if (result == 0) Py_RETURN_NONE;
719     PyErr_SetFromErrno(PyExc_EnvironmentError);
720     return NULL;
721 }
722
723 /********************************
724  * ausearch_add_interpreted_item
725  ********************************/
726 PyDoc_STRVAR(search_add_interpreted_item_doc,
727 "search_add_interpreted_item(field, op, value, how) Build up search rule\n\
728 \n\
729 \n\
730 search_add_interpreted_item() adds one search condition to the current audit\n\
731 search expression. The search conditions can then be used to scan logs,\n\
732 files, or buffers for something of interest. The field value is the field\n\
733 name that the value will be checked for. The op variable describes what\n\
734 kind of check is to be done. Legal op values are:\n\
735 \n\
736 'exists':\n\
737 Just check that a field name exists\n\
738 \n\
739 '=':\n\
740 locate the field name and check that the value associated with it\n\
741 is equal to the value given in this rule.\n\
742 \n\
743 '!=':\n\
744 locate the field name and check that the value associated with\n\
745 it is NOT equal to the value given in this rule.\n\
746 \n\
747 The value parameter is compared to the interpreted field value (the value\n\
748 that would be returned by AuParser.interpret_field).\n\
749 \n\
750 The how parameter determines how this search expression will affect the\n\
751 existing search expression, if one is already defined.  The possible\n\
752 values are:\n\
753 \n\
754 AUSEARCH_RULE_CLEAR:\n\
755 Clear the current search expression, if any, and use only this search\n\
756 expression.\n\
757 \n\
758 AUSEARCH_RULE_OR:\n\
759 \n\
760 If a search expression E is already configured, replace it by\n\
761 (E || this_search_expression).\n\
762 \n\
763 AUSEARCH_RULE_AND:\n\
764 If a search expression E is already configured, replace it by\n\
765 (E && this_search_expression).\n\
766 \n\
767 No Return value, raises exception (EnvironmentError) on error.\n\
768 ");
769
770 static PyObject *
771 AuParser_search_add_interpreted_item(AuParser *self, PyObject *args)
772 {
773     const char *field;
774     const char *op;
775     const char *value;
776     int how;
777     int result;
778
779     if (!PyArg_ParseTuple(args, "sssi", &field, &op, &value, &how)) return NULL;
780     PARSER_CHECK;
781
782     result = ausearch_add_interpreted_item(self->au, field, op, value, how);
783     if (result == 0) Py_RETURN_NONE;
784     PyErr_SetFromErrno(PyExc_EnvironmentError);
785     return NULL;
786 }
787
788 /********************************
789  * ausearch_add_timestamp_item
790  ********************************/
791 PyDoc_STRVAR(search_add_timestamp_item_doc,
792 "search_add_timestamp_item(op, sec, milli, how) Build up search rule\n\
793 \n\
794 \n\
795 search_add_timestamp_item adds an event time condition to the current audit\n\
796 search expression. The search conditions can then be used to scan logs,\n\
797 files, or buffers for something of interest. The op parameter specifies the\n\
798 desired comparison. Legal op values are \"<\", \"<=\", \">=\", \">\" and\n\
799 \"=\". The left operand of the comparison operator is the timestamp of the\n\
800 examined event, the right operand is specified by the sec and milli\n\
801 parameters.\n\
802 \n\
803 The how parameter determines how this search expression will affect the\n\
804 existing search expression, if one is already defined.  The possible\n\
805 values are:\n\
806 \n\
807 AUSEARCH_RULE_CLEAR:\n\
808 Clear the current search expression, if any, and use only this search\n\
809 expression.\n\
810 \n\
811 AUSEARCH_RULE_OR:\n\
812 \n\
813 If a search expression E is already configured, replace it by\n\
814 (E || this_search_expression).\n\
815 \n\
816 AUSEARCH_RULE_AND:\n\
817 If a search expression E is already configured, replace it by\n\
818 (E && this_search_expression).\n\
819 \n\
820 No Return value, raises exception (EnvironmentError) on error.\n\
821 ");
822
823 static PyObject *
824 AuParser_search_add_timestamp_item(AuParser *self, PyObject *args)
825 {
826     const char *op;
827     PY_LONG_LONG sec;
828     int milli;
829     int how;
830     int result;
831
832     /* There's no completely portable way to handle time_t values from Python;
833        note that time_t might even be a floating-point type!  PY_LONG_LONG
834        is at least enough not to worry about year 2038.
835
836        milli is int because Python's 'I' format does no overflow checking.
837        Negative milli values will wrap to values > 1000 and
838        ausearch_add_timestamp_item will reject them. */
839     if (!PyArg_ParseTuple(args, "sLii", &op, &sec, &milli, &how))
840             return NULL;
841     PARSER_CHECK;
842
843     result = ausearch_add_timestamp_item(self->au, op, sec, (unsigned)milli,
844                                          how);
845     if (result == 0)
846             Py_RETURN_NONE;
847     PyErr_SetFromErrno(PyExc_EnvironmentError);
848     return NULL;
849 }
850
851 /********************************
852  * ausearch_add_timestamp_item_ex
853  ********************************/
854 PyDoc_STRVAR(search_add_timestamp_item_ex_doc,
855 "search_add_timestamp_item_ex(op, sec, milli, serial, how) Build up search rule\n\
856 search_add_timestamp_item_ex adds an event time condition to the current audit\n\
857 search expression. Its similar to search_add_timestamp_item except it adds\n\
858 the event serial number.\n\
859 ");
860
861 static PyObject *
862 AuParser_search_add_timestamp_item_ex(AuParser *self, PyObject *args)
863 {
864     const char *op;
865     PY_LONG_LONG sec;
866     int milli;
867     int serial;
868     int how;
869     int result;
870
871     /* There's no completely portable way to handle time_t values from Python;
872        note that time_t might even be a floating-point type!  PY_LONG_LONG
873        is at least enough not to worry about year 2038.
874
875        milli is int because Python's 'I' format does no overflow checking.
876        Negative milli values will wrap to values > 1000 and
877        ausearch_add_timestamp_item will reject them. */
878     if (!PyArg_ParseTuple(args, "sLiiii", &op, &sec, &milli, &serial, &how))
879             return NULL;
880     PARSER_CHECK;
881
882     result = ausearch_add_timestamp_item_ex(self->au, op, sec, (unsigned)milli,
883                                          (unsigned)serial, how);
884     if (result == 0)
885             Py_RETURN_NONE;
886     PyErr_SetFromErrno(PyExc_EnvironmentError);
887     return NULL;
888 }
889
890 /********************************
891  * ausearch_add_regex
892  ********************************/
893 PyDoc_STRVAR(search_add_regex_doc,
894 "search_add_regex(regexp) Add a regular expression to the search criteria.\n\
895 \n\
896 No Return value, raises exception (EnvironmentError) on error.\n\
897 ");
898 static PyObject *
899 AuParser_search_add_regex(AuParser *self, PyObject *args)
900 {
901     const char* regexp;
902     int result;
903
904     if (!PyArg_ParseTuple(args, "s", &regexp)) return NULL;
905     PARSER_CHECK;
906     result = ausearch_add_regex(self->au, regexp);
907     if (result == 0) Py_RETURN_NONE;
908     PyErr_SetFromErrno(PyExc_EnvironmentError);
909     return NULL;
910 }
911
912 /********************************
913  * ausearch_set_stop
914  ********************************/
915 PyDoc_STRVAR(search_set_stop_doc,
916 "search_set_stop(where) Set where cursor is positioned on search match.\n\
917 \n\
918 search_set_stop() determines where the internal cursor will stop when\n\
919 a search condition is met. The possible values are:\n\
920 \n\
921 AUSEARCH_STOP_EVENT:\n\
922 This one repositions the cursors to the first field of the first\n\
923 record of the event con- taining the items searched for.\n\
924 \n\
925 AUSEARCH_STOP_RECORD:\n\
926 This one repositions the cursors to the first field of the record\n\
927 containing the items searched for.\n\
928 \n\
929 AUSEARCH_STOP_FIELD:\n\
930 This one simply stops on the current field when the evaluation of the\n\
931 rules becomes true.\n\
932 \n\
933 No Return value, raises exception (ValueError) on error.\n\
934 ");
935 static PyObject *
936 AuParser_search_set_stop(AuParser *self, PyObject *args)
937 {
938     int where;
939     int result;
940
941     if (!PyArg_ParseTuple(args, "i", &where)) return NULL;
942     PARSER_CHECK;
943     result = ausearch_set_stop(self->au, where);
944     if (result == 0) Py_RETURN_NONE;
945     PyErr_SetFromErrno(PyExc_ValueError);
946     return NULL;
947 }
948
949 /********************************
950  * ausearch_clear
951  ********************************/
952 PyDoc_STRVAR(search_clear_doc,
953 "search_clear() Clear search parameters.\n\
954 \n\
955 ausearch_clear clears any search parameters stored in the parser\n\
956 instance and frees memory associated with it.\n\
957 \n\
958 No Return value.\n\
959 ");
960 static PyObject *
961 AuParser_search_clear(AuParser *self)
962 {
963     PARSER_CHECK;
964     ausearch_clear(self->au);
965     Py_RETURN_NONE;
966 }
967
968 /********************************
969  * ausearch_next_event
970  ********************************/
971 PyDoc_STRVAR(search_next_event_doc,
972 "search_next_event() Find the next event that meets search criteria.\n\
973 \n\
974 search_next_event() will scan the input source and evaluate whether\n\
975 any record in an event contains the data being searched\n\
976 for. Evaluation is done at the record level.\n\
977 \n\
978 Returns True if a match was found\n\
979 Returns False if a match was not found.\n\
980 \n\
981 Raises exception (EnvironmentError) on error\n\
982 ");
983 static PyObject *
984 AuParser_search_next_event(AuParser *self)
985 {
986     int result;
987
988     PARSER_CHECK;
989     result = ausearch_next_event(self->au);
990     if (result >  0) Py_RETURN_TRUE;
991     if (result == 0) Py_RETURN_FALSE;
992     PyErr_SetFromErrno(PyExc_EnvironmentError);
993     return NULL;
994 }
995
996 /********************************
997  * auparse_next_event
998  ********************************/
999 PyDoc_STRVAR(parse_next_event_doc,
1000 "parse_next_event() Advance the parser to the next event.\n\
1001 \n\
1002 parse_next_event() will position the cursors at the first field of the first\n\
1003 record of the next event in a file or buffer. It does not skip events\n\
1004 or honor any search criteria that may be stored.\n\
1005 \n\
1006 Returns True if parser advances to next event.\n\
1007 Returns False if there are no more events to parse\n\
1008 \n\
1009 Raises exception (EnvironmentError) on error\n\
1010 ");
1011 static PyObject *
1012 AuParser_parse_next_event(AuParser *self)
1013 {
1014     int result;
1015
1016     PARSER_CHECK;
1017     result = auparse_next_event(self->au);
1018     if (result >  0) Py_RETURN_TRUE;
1019     if (result == 0) Py_RETURN_FALSE;
1020     PyErr_SetFromErrno(PyExc_EnvironmentError);
1021     return NULL;
1022 }
1023
1024 /********************************
1025  * auparse_get_timestamp
1026  ********************************/
1027 PyDoc_STRVAR(get_timestamp_doc,
1028 "get_timestamp() Return current event's timestamp.\n\
1029 \n\
1030 Returns the current event's timestamp info as an AuEvent object.\n\
1031 No Return value, raises exception (EnvironmentError) on error.\n\
1032 ");
1033 static PyObject *
1034 AuParser_get_timestamp(AuParser *self)
1035 {
1036     const au_event_t *event_ptr;
1037     PyObject *py_event;
1038
1039     PARSER_CHECK;
1040     event_ptr = auparse_get_timestamp(self->au);
1041
1042     if (event_ptr == NULL) {
1043         if (errno) {
1044             PyErr_SetFromErrno(PyExc_EnvironmentError);
1045             return NULL;
1046         } else {
1047             Py_RETURN_NONE;
1048         }
1049     }
1050     py_event = AuEvent_new_from_struct(event_ptr);
1051     Py_INCREF(py_event);        /* FIXME: should we be bumping the ref count? */
1052     return py_event;
1053 }
1054
1055 /********************************
1056  * auparse_get_num_records
1057  ********************************/
1058 PyDoc_STRVAR(get_num_records_doc,
1059 "get_num_records() Get the number of records.\n\
1060 \n\
1061 Returns the number of records in the current event.\n\
1062 Raises exception (EnvironmentError) on error.\n\
1063 ");
1064 static PyObject *
1065 AuParser_get_num_records(AuParser *self)
1066 {
1067     int num_records;
1068
1069     PARSER_CHECK;
1070     num_records = auparse_get_num_records(self->au);
1071     if (num_records == 0) {
1072         PyErr_SetFromErrno(PyExc_EnvironmentError);
1073         return NULL;
1074     }
1075     return Py_BuildValue("i", num_records);
1076 }
1077
1078 /********************************
1079  * auparse_first_record
1080  ********************************/
1081 PyDoc_STRVAR(first_record_doc,
1082 "first_record() Reposition record cursor.\n\
1083 \n\
1084 first_record() repositions the internal cursors of the parsing library\n\
1085 to point to the first record in the current event.\n\
1086 \n\
1087 Return True for success, False if there is no event data.\n\
1088 Raises exception (EnvironmentError) on error.\n\
1089 ");
1090 static PyObject *
1091 AuParser_first_record(AuParser *self)
1092 {
1093     int result;
1094
1095     PARSER_CHECK;
1096     result = auparse_first_record(self->au);
1097     if (result >  0) Py_RETURN_TRUE;
1098     if (result == 0) Py_RETURN_FALSE;
1099     PyErr_SetFromErrno(PyExc_EnvironmentError);
1100     return NULL;
1101 }
1102
1103 /********************************
1104  * auparse_next_record
1105  ********************************/
1106 PyDoc_STRVAR(next_record_doc,
1107 "next_record() Advance record cursor.\n\
1108 \n\
1109 next_record() will move the internal library cursors to point to the\n\
1110 next record of the current event.\n\
1111 \n\
1112 Returns True on success, False if no more records in current event\n\
1113 Raises exception (EnvironmentError) on error.\n\
1114 ");
1115 static PyObject *
1116 AuParser_next_record(AuParser *self)
1117 {
1118     int result;
1119
1120     PARSER_CHECK;
1121     result = auparse_next_record(self->au);
1122
1123     if (result >  0) Py_RETURN_TRUE;
1124     if (result == 0) Py_RETURN_FALSE;
1125     PyErr_SetFromErrno(PyExc_EnvironmentError);
1126     return NULL;
1127 }
1128
1129 /********************************
1130  * auparse_goto_record_num
1131  ********************************/
1132 PyDoc_STRVAR(goto_record_num_doc,
1133 "goto_record_num() Move record cursor to specific position.\n\
1134 \n\
1135 goto_record_num() will move the internal library cursors to point\n\
1136 to a specific physical record number. Records within the same event are\n\
1137 numbered  starting  from  0. This is generally not needed but there are\n\
1138 some cases where one may want precise control  over  the  exact  record\n\
1139 being looked at.\n\
1140 \n\
1141 Returns True on success, False if no more records in current event\n\
1142 Raises exception (EnvironmentError) on error.\n\
1143 ");
1144 static PyObject *
1145 AuParser_goto_record_num(AuParser *self, PyObject *args)
1146 {
1147     int result;
1148     unsigned int num;
1149
1150     if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
1151     PARSER_CHECK;
1152     result = auparse_goto_record_num(self->au, num);
1153
1154     if (result >  0) Py_RETURN_TRUE;
1155     if (result == 0) Py_RETURN_FALSE;
1156     PyErr_SetFromErrno(PyExc_EnvironmentError);
1157     return NULL;
1158 }
1159
1160 /********************************
1161  * auparse_get_type
1162  ********************************/
1163 PyDoc_STRVAR(get_type_doc,
1164 "get_type() Get record’s type.\n\
1165 \n\
1166 get_type() will return the integer value for the current record of the\n\
1167 current event.\n\
1168 \n\
1169 Returns record type.\n\
1170 Raises exception (LookupError) on error.\n\
1171 ");
1172 static PyObject *
1173 AuParser_get_type(AuParser *self)
1174 {
1175     int value;
1176
1177     PARSER_CHECK;
1178     value = auparse_get_type(self->au);
1179
1180     if (value == 0) {
1181         PyErr_SetString(PyExc_LookupError, "Not found");
1182         return NULL;
1183     }
1184     return Py_BuildValue("i", value);
1185 }
1186
1187 /********************************
1188  * auparse_get_type_name
1189  ********************************/
1190 PyDoc_STRVAR(get_type_name_doc,
1191 "get_type_name() Get current record’s type name.\n\
1192 \n\
1193 get_type_name() allows access to the current record type name in the\n\
1194 current event.\n\
1195 \n\
1196 Returns None if the record type name is unavailable.\n\
1197 ");
1198 static PyObject *
1199 AuParser_get_type_name(AuParser *self)
1200 {
1201     const char *name = NULL;
1202
1203     PARSER_CHECK;
1204     name = auparse_get_type_name(self->au);
1205     return Py_BuildValue("s", name);
1206 }
1207
1208 /********************************
1209  * auparse_get_line_number
1210  ********************************/
1211 PyDoc_STRVAR(get_line_number_doc,
1212 "auparse_get_line_number() get line number where record was found\n\
1213 \n\
1214 get_line_number will return the source input line number for\n\
1215 the current record of the current event. Line numbers start at 1.  If\n\
1216 the source input type is AUSOURCE_FILE_ARRAY the line numbering will\n\
1217 reset back to 1 each time a new life in the file array is opened.\n\
1218 ");
1219 static PyObject *
1220 AuParser_get_line_number(AuParser *self)
1221 {
1222     unsigned int value;
1223
1224     PARSER_CHECK;
1225     value = auparse_get_line_number(self->au);
1226     return Py_BuildValue("I", value);
1227 }
1228
1229 /********************************
1230  * auparse_get_filename
1231  ********************************/
1232 PyDoc_STRVAR(get_filename_doc,
1233 "auparse_get_filename() get the filename where record was found\n\
1234 get_filename() will return the name of the source file where the\n\
1235 record was found if the source type is AUSOURCE_FILE or\n\
1236 AUSOURCE_FILE_ARRAY. For other source types the return value will be\n\
1237 None.\n\
1238 ");
1239 static PyObject *
1240 AuParser_get_filename(AuParser *self)
1241 {
1242     const char *value;
1243
1244     PARSER_CHECK;
1245     value = auparse_get_filename(self->au);
1246
1247     if (value == NULL) Py_RETURN_NONE;
1248     return Py_BuildValue("s", value);
1249 }
1250
1251 /********************************
1252  * auparse_first_field
1253  ********************************/
1254 PyDoc_STRVAR(first_field_doc,
1255 "first_field() Reposition field cursor.\n\
1256 \n\
1257 Returns True on success, False if there is no event data\n\
1258 ");
1259 static PyObject *
1260 AuParser_first_field(AuParser *self)
1261 {
1262     int result;
1263
1264     PARSER_CHECK;
1265     result = auparse_first_field(self->au);
1266
1267     if (result == 0) Py_RETURN_FALSE;
1268     Py_RETURN_TRUE;
1269 }
1270
1271 /********************************
1272  * auparse_next_field
1273  ********************************/
1274 PyDoc_STRVAR(next_field_doc,
1275 "next_field() Advance the field cursor.\n\
1276 \n\
1277 next_field() moves the library’s internal cursor to point to the next\n\
1278 field in the current record of the current event.\n\
1279 \n\
1280 Returns True on success, False if there is no more fields exist\n\
1281 ");
1282 static PyObject *
1283 AuParser_next_field(AuParser *self)
1284 {
1285     int result;
1286
1287     PARSER_CHECK;
1288     result = auparse_next_field(self->au);
1289
1290     if (result == 0) Py_RETURN_FALSE;
1291     Py_RETURN_TRUE;
1292 }
1293
1294 /********************************
1295  * auparse_get_num_fields
1296  ********************************/
1297 PyDoc_STRVAR(get_num_fields_doc,
1298 "get_num_fields() Get the number of fields.\n\
1299 \n\
1300 Returns the number of fields in the current event.\n\
1301 Raises exception (EnvironmentError) on error.\n\
1302 ");
1303 static PyObject *
1304 AuParser_get_num_fields(AuParser *self)
1305 {
1306     int num_fields;
1307
1308     PARSER_CHECK;
1309     num_fields = auparse_get_num_fields(self->au);
1310     if (num_fields == 0) {
1311         PyErr_SetFromErrno(PyExc_EnvironmentError);
1312         return NULL;
1313     }
1314     return Py_BuildValue("i", num_fields);
1315 }
1316
1317 /********************************
1318  * auparse_get_record_text
1319  ********************************/
1320 PyDoc_STRVAR(get_record_text_doc,
1321 "get_record_text() Return unparsed record data\n\
1322 \n\
1323 get_record_text() returns the full unparsed record.\n\
1324 Raises exception (EnvironmentError) on error.\n\
1325 ");
1326 static PyObject *
1327 AuParser_get_record_text(AuParser *self)
1328 {
1329     const char *text;
1330
1331     PARSER_CHECK;
1332     text = auparse_get_record_text(self->au);
1333
1334     if (text == NULL) {
1335         PyErr_SetFromErrno(PyExc_EnvironmentError);
1336         return NULL;
1337     }
1338     return Py_BuildValue("s", text);
1339 }
1340
1341 /********************************
1342  * auparse_find_field
1343  ********************************/
1344 PyDoc_STRVAR(find_field_doc,
1345 "find_field(name) Search for field name.\n\
1346 \n\
1347 find_field() will scan all records in an event to find the first\n\
1348 occurance of the field name passed to it. Searching begins from the\n\
1349 cursor’s current position. The field name is stored for subsequent\n\
1350 searching.\n\
1351 \n\
1352 Returns value associated with field or None if not found.\n\
1353 ");
1354 static PyObject *
1355 AuParser_find_field(AuParser *self, PyObject *args)
1356 {
1357     char *name = NULL;
1358     const char *value;
1359
1360     if (!PyArg_ParseTuple(args, "s:find_field", &name)) return NULL;
1361     PARSER_CHECK;
1362     if ((value =auparse_find_field(self->au, name)) == NULL) {
1363         if (errno) {
1364             PyErr_SetFromErrno(PyExc_EnvironmentError);
1365             return NULL;
1366         } else {
1367             Py_RETURN_NONE;
1368         }
1369     }
1370     return Py_BuildValue("s", value);
1371 }
1372
1373 const char *auparse_find_field_next(auparse_state_t *au);
1374 /********************************
1375  * auparse_find_field_next
1376  ********************************/
1377 PyDoc_STRVAR(find_field_next_doc,
1378 "find_field_next() Get next occurrance of field name\n\
1379 \n\
1380 find_field_next() returns the value associated next occurrance of field name.\n\
1381 Returns value associated with field or None if there is no next field.\n\
1382 Raises exception (EnvironmentError) on error.\n\
1383 ");
1384 static PyObject *
1385 AuParser_find_field_next(AuParser *self)
1386 {
1387     const char *value;
1388
1389     PARSER_CHECK;
1390     if ((value = auparse_find_field_next(self->au)) == NULL) {
1391         if (errno) {
1392             PyErr_SetFromErrno(PyExc_EnvironmentError);
1393             return NULL;
1394         } else {
1395             Py_RETURN_NONE;
1396         }
1397     }
1398     return Py_BuildValue("s", value);
1399 }
1400
1401 /********************************
1402  * auparse_get_field_name
1403  ********************************/
1404 PyDoc_STRVAR(get_field_name_doc,
1405 "get_field_name() Get current field’s name.\n\
1406 \n\
1407 get_field_name() allows access to the current field name of the\n\
1408 current record in the current event.\n\
1409 \n\
1410 Returns None if the field value is unavailable.\n\
1411 ");
1412 static PyObject *
1413 AuParser_get_field_name(AuParser *self)
1414 {
1415     const char *name = NULL;
1416
1417     PARSER_CHECK;
1418     name = auparse_get_field_name(self->au);
1419     return Py_BuildValue("s", name);
1420 }
1421
1422 /********************************
1423  * auparse_get_field_str
1424  ********************************/
1425 PyDoc_STRVAR(get_field_str_doc,
1426 "get_field_str() get current field’s value\n\
1427 \n\
1428 get_field_str() allows access to the value in the current field of the\n\
1429 current record in the current event.\n\
1430 \n\
1431 Returns None if the field value is unavailable.\n\
1432 ");
1433 static PyObject *
1434 AuParser_get_field_str(AuParser *self)
1435 {
1436     const char *value = NULL;
1437
1438     PARSER_CHECK;
1439     value = auparse_get_field_str(self->au);
1440     return Py_BuildValue("s", value);
1441 }
1442
1443 /********************************
1444  * auparse_get_field_type
1445  ********************************/
1446 PyDoc_STRVAR(get_field_type_doc,
1447 "get_field_type() Get current field’s data type value.\n\
1448 \n\
1449 get_field_type() returns a value from the auparse_type_t enum that\n\
1450 describes the kind of data in the current field of the current record\n\
1451 in the current event.\n\
1452 \n\
1453 Returns AUPARSE_TYPE_UNCLASSIFIED if the field’s data type has no\n\
1454 known description or is an integer. Otherwise it returns another enum.\n\
1455 Fields with the type AUPARSE_TYPE_ESCAPED must be interpretted to access\n\
1456 their value since those field’s raw value is encoded.\n\
1457 ");
1458 static PyObject *
1459 AuParser_get_field_type(AuParser *self)
1460 {
1461     int value;
1462
1463     PARSER_CHECK;
1464     value = auparse_get_field_type(self->au);
1465     return Py_BuildValue("i", value);
1466 }
1467
1468 /********************************
1469  * auparse_get_field_int
1470  ********************************/
1471 PyDoc_STRVAR(get_field_int_doc,
1472 "get_field_int() Get current field’s value as an integer.\n\
1473 \n\
1474 get_field_int() allows access to the value as an int of the current\n\
1475 field of the current record in the current event.\n\
1476 \n\
1477 Returns None if the field value is unavailable.\n\
1478 ");
1479 static PyObject *
1480 AuParser_get_field_int(AuParser *self)
1481 {
1482     int value;
1483
1484     PARSER_CHECK;
1485     value = auparse_get_field_int(self->au);
1486     if (errno == 0) return Py_BuildValue("i", value);
1487     Py_RETURN_NONE;
1488 }
1489
1490 // FIXME: can't tell if interpret is succesful, always returns some string in somewhat arbitrary format.
1491 PyDoc_STRVAR(interpret_field_doc,
1492 "interpret_field() Return an interpretation of the current field as a string.\n\
1493 \n\
1494 If the field cannot be interpreted the field is returned unmodified.\n\
1495 Returns None if the field value is unavailable.\n\
1496 ");
1497 static PyObject *
1498 AuParser_interpret_field(AuParser *self)
1499 {
1500     const char *value = NULL;
1501
1502     PARSER_CHECK;
1503     value = auparse_interpret_field(self->au);
1504     return Py_BuildValue("s", value);
1505 }
1506
1507 static
1508 PyGetSetDef AuParser_getseters[] = {
1509     {NULL}  /* Sentinel */
1510 };
1511
1512 static
1513 PyMemberDef AuParser_members[] = {
1514     {NULL}  /* Sentinel */
1515 };
1516
1517 static PyMethodDef AuParser_methods[] = {
1518     {"feed",              (PyCFunction)AuParser_feed,              METH_VARARGS, feed_doc},
1519     {"flush_feed",        (PyCFunction)AuParser_flush_feed,        METH_NOARGS,  flush_feed_doc},
1520     {"add_callback",      (PyCFunction)AuParser_add_callback,      METH_VARARGS, add_callback_doc},
1521     {"reset",             (PyCFunction)AuParser_reset,             METH_NOARGS,  reset_doc},
1522     {"search_add_expression", (PyCFunction)AuParser_search_add_expression, METH_VARARGS, search_add_expression_doc},
1523     {"search_add_item",   (PyCFunction)AuParser_search_add_item,   METH_VARARGS, search_add_item_doc},
1524     {"search_add_interpreted_item", (PyCFunction)AuParser_search_add_interpreted_item, METH_VARARGS, search_add_interpreted_item_doc},
1525     {"search_add_timestamp_item", (PyCFunction)AuParser_search_add_timestamp_item, METH_VARARGS, search_add_timestamp_item_doc},
1526     {"search_add_timestamp_item_ex", (PyCFunction)AuParser_search_add_timestamp_item_ex, METH_VARARGS, search_add_timestamp_item_ex_doc},
1527     {"search_add_regex",  (PyCFunction)AuParser_search_add_regex,  METH_VARARGS, search_add_regex_doc},
1528     {"search_set_stop",   (PyCFunction)AuParser_search_set_stop,   METH_VARARGS, search_set_stop_doc},
1529     {"search_clear",      (PyCFunction)AuParser_search_clear,      METH_NOARGS,  search_clear_doc},
1530     {"search_next_event", (PyCFunction)AuParser_search_next_event, METH_NOARGS,  search_next_event_doc},
1531     {"parse_next_event",  (PyCFunction)AuParser_parse_next_event,  METH_NOARGS,  parse_next_event_doc},
1532     {"get_timestamp",     (PyCFunction)AuParser_get_timestamp,     METH_NOARGS,  get_timestamp_doc},
1533     {"get_num_records",   (PyCFunction)AuParser_get_num_records,   METH_NOARGS,  get_num_records_doc},
1534     {"first_record",      (PyCFunction)AuParser_first_record,      METH_NOARGS,  first_record_doc},
1535     {"next_record",       (PyCFunction)AuParser_next_record,       METH_NOARGS,  next_record_doc},
1536     {"goto_record_num",   (PyCFunction)AuParser_goto_record_num,   METH_VARARGS,  goto_record_num_doc},
1537     {"get_type",          (PyCFunction)AuParser_get_type,          METH_NOARGS,  get_type_doc},
1538     {"get_type_name",     (PyCFunction)AuParser_get_type_name,     METH_NOARGS,  get_type_name_doc},
1539     {"get_line_number",   (PyCFunction)AuParser_get_line_number,   METH_NOARGS,  get_line_number_doc},
1540     {"get_filename",      (PyCFunction)AuParser_get_filename,      METH_NOARGS,  get_filename_doc},
1541     {"first_field",       (PyCFunction)AuParser_first_field,       METH_NOARGS,  first_field_doc},
1542     {"next_field",        (PyCFunction)AuParser_next_field,        METH_NOARGS,  next_field_doc},
1543     {"get_num_fields",    (PyCFunction)AuParser_get_num_fields,    METH_NOARGS,  get_num_fields_doc},
1544     {"get_record_text",   (PyCFunction)AuParser_get_record_text,   METH_NOARGS,  get_record_text_doc},
1545     {"find_field_next",   (PyCFunction)AuParser_find_field_next,   METH_NOARGS,  find_field_next_doc},
1546     {"find_field",        (PyCFunction)AuParser_find_field,        METH_VARARGS, find_field_doc},
1547     {"get_field_name",    (PyCFunction)AuParser_get_field_name,    METH_NOARGS,  get_field_name_doc},
1548     {"get_field_str",     (PyCFunction)AuParser_get_field_str,     METH_NOARGS,  get_field_str_doc},
1549     {"get_field_type",    (PyCFunction)AuParser_get_field_type,    METH_NOARGS,  get_field_type_doc},
1550     {"get_field_int",     (PyCFunction)AuParser_get_field_int,     METH_NOARGS,  get_field_int_doc},
1551     {"interpret_field",   (PyCFunction)AuParser_interpret_field,   METH_NOARGS,  interpret_field_doc},
1552     {NULL, NULL}  /* Sentinel */
1553 };
1554
1555 PyDoc_STRVAR(AuParser_doc,
1556 "AuParser(source_type, source)\n\
1557 \n\
1558 Construct a new audit parser object and bind it to input data.\n\
1559 source_type: one of the AUSOURCE_* constants.\n\
1560 source:      the input data, dependent on the source_type as follows:\n\
1561 \n\
1562 AUSOURCE_LOGS:         None (system log files will be parsed)\n\
1563 AUSOURCE_FILE:         string containing file path name\n\
1564 AUSOURCE_FILE_ARRAY:   list or tuple of strings each containing a file path name\n\
1565 AUSOURCE_BUFFER:       string containing audit data to parse\n\
1566 AUSOURCE_BUFFER_ARRAY: list or tuple of strings each containing audit data to parse\n\
1567 AUSOURCE_DESCRIPTOR:   integer file descriptor (e.g. fileno)\n\
1568 AUSOURCE_FILE_POINTER: file object (e.g. types.FileType)\n\
1569 AUSOURCE_FEED:         None (data supplied via feed()\n\
1570 ");
1571
1572 static PyTypeObject AuParserType = {
1573     PyVarObject_HEAD_INIT(NULL, 0)
1574     "auparse.AuParser",         /*tp_name*/
1575     sizeof(AuParser),           /*tp_basicsize*/
1576     0,                         /*tp_itemsize*/
1577     (destructor)AuParser_dealloc, /*tp_dealloc*/
1578     0,                         /*tp_print*/
1579     0,                         /*tp_getattr*/
1580     0,                         /*tp_setattr*/
1581     0,                         /*tp_compare*/
1582     0,                         /*tp_repr*/
1583     0,                         /*tp_as_number*/
1584     0,                         /*tp_as_sequence*/
1585     0,                         /*tp_as_mapping*/
1586     0,                         /*tp_hash */
1587     0,                         /*tp_call*/
1588     0,                         /*tp_str*/
1589     0,                         /*tp_getattro*/
1590     0,                         /*tp_setattro*/
1591     0,                         /*tp_as_buffer*/
1592     Py_TPFLAGS_DEFAULT,        /*tp_flags*/
1593     AuParser_doc,              /* tp_doc */
1594     0,                         /* tp_traverse */
1595     0,                         /* tp_clear */
1596     0,                         /* tp_richcompare */
1597     0,                         /* tp_weaklistoffset */
1598     0,                         /* tp_iter */
1599     0,                         /* tp_iternext */
1600     AuParser_methods,           /* tp_methods */
1601     AuParser_members,                        /* tp_members */
1602     AuParser_getseters,         /* tp_getset */
1603     0,                         /* tp_base */
1604     0,                         /* tp_dict */
1605     0,                         /* tp_descr_get */
1606     0,                         /* tp_descr_set */
1607     0,                         /* tp_dictoffset */
1608     (initproc)AuParser_init,  /* tp_init */
1609     0,                         /* tp_alloc */
1610     AuParser_new,              /* tp_new */
1611 };
1612
1613
1614
1615 /*===========================================================================
1616  *                                Module
1617  *===========================================================================*/
1618
1619 PyDoc_STRVAR(auparse_doc,
1620 "Parsing library for audit messages.\n\
1621 \n\
1622 The module defines the following exceptions:\n\
1623 \n\
1624 NoParser: Raised if the underlying C code parser is not bound to the AuParser object.\n\
1625 ");
1626
1627 static PyMethodDef module_methods[] = {
1628     {NULL}  /* Sentinel */
1629 };
1630
1631 #ifdef IS_PY3K
1632 static struct PyModuleDef auparse_def = {
1633     PyModuleDef_HEAD_INIT,
1634     "auparse",
1635     NULL,
1636     -1,
1637     module_methods,
1638     NULL,
1639     NULL,
1640     NULL,
1641     NULL
1642 };
1643
1644 PyMODINIT_FUNC
1645 PyInit_auparse(void)
1646 #else
1647 PyMODINIT_FUNC
1648 initauparse(void) 
1649 #endif
1650 {
1651     PyObject* m;
1652
1653     if (PyType_Ready(&AuEventType) < 0) MODINITERROR;
1654     if (PyType_Ready(&AuParserType) < 0) MODINITERROR;
1655
1656 #ifdef IS_PY3K
1657     m = PyModule_Create(&auparse_def);
1658 #else
1659     m = Py_InitModule3("auparse", module_methods, auparse_doc);
1660 #endif
1661
1662     if (m == NULL)
1663       MODINITERROR;
1664
1665     Py_INCREF(&AuParserType);
1666     PyModule_AddObject(m, "AuParser", (PyObject *)&AuParserType);
1667
1668     Py_INCREF(&AuEventType);
1669     PyModule_AddObject(m, "AuEvent", (PyObject *)&AuEventType);
1670
1671     /* exceptions */
1672     NoParserError = PyErr_NewException("auparse.NoParser", NULL, NULL);
1673     Py_INCREF(NoParserError);
1674     PyModule_AddObject(m, "NoParser", NoParserError);
1675
1676     /* ausource_t */
1677     PyModule_AddIntConstant(m, "AUSOURCE_LOGS",          AUSOURCE_LOGS);
1678     PyModule_AddIntConstant(m, "AUSOURCE_FILE",          AUSOURCE_FILE);
1679     PyModule_AddIntConstant(m, "AUSOURCE_FILE_ARRAY",    AUSOURCE_FILE_ARRAY);
1680     PyModule_AddIntConstant(m, "AUSOURCE_BUFFER",        AUSOURCE_BUFFER);
1681     PyModule_AddIntConstant(m, "AUSOURCE_BUFFER_ARRAY",  AUSOURCE_BUFFER_ARRAY);
1682     PyModule_AddIntConstant(m, "AUSOURCE_DESCRIPTOR",    AUSOURCE_DESCRIPTOR);
1683     PyModule_AddIntConstant(m, "AUSOURCE_FILE_POINTER",  AUSOURCE_FILE_POINTER);
1684     PyModule_AddIntConstant(m, "AUSOURCE_FEED",          AUSOURCE_FEED);
1685
1686     /* ausearch_op_t */
1687     PyModule_AddIntConstant(m, "AUSEARCH_UNSET",         AUSEARCH_UNSET);
1688     PyModule_AddIntConstant(m, "AUSEARCH_EXISTS",        AUSEARCH_EXISTS);
1689     PyModule_AddIntConstant(m, "AUSEARCH_EQUAL",         AUSEARCH_EQUAL);
1690     PyModule_AddIntConstant(m, "AUSEARCH_NOT_EQUAL",     AUSEARCH_NOT_EQUAL);
1691
1692     /* austop_t */
1693     PyModule_AddIntConstant(m, "AUSEARCH_STOP_EVENT",    AUSEARCH_STOP_EVENT);
1694     PyModule_AddIntConstant(m, "AUSEARCH_STOP_RECORD",   AUSEARCH_STOP_RECORD);
1695     PyModule_AddIntConstant(m, "AUSEARCH_STOP_FIELD",    AUSEARCH_STOP_FIELD);
1696
1697     /* ausearch_rule_t */
1698     PyModule_AddIntConstant(m, "AUSEARCH_RULE_CLEAR",    AUSEARCH_RULE_CLEAR);
1699     PyModule_AddIntConstant(m, "AUSEARCH_RULE_OR",       AUSEARCH_RULE_OR);
1700     PyModule_AddIntConstant(m, "AUSEARCH_RULE_AND",      AUSEARCH_RULE_AND);
1701     PyModule_AddIntConstant(m, "AUSEARCH_RULE_REGEX",    AUSEARCH_RULE_REGEX);
1702
1703     /* auparse_cb_event_t */
1704     PyModule_AddIntConstant(m, "AUPARSE_CB_EVENT_READY", AUPARSE_CB_EVENT_READY);
1705     /* auparse_type_t */
1706     PyModule_AddIntConstant(m, "AUPARSE_TYPE_UNCLASSIFIED", AUPARSE_TYPE_UNCLASSIFIED);
1707     PyModule_AddIntConstant(m, "AUPARSE_TYPE_UID",     AUPARSE_TYPE_UID);
1708     PyModule_AddIntConstant(m, "AUPARSE_TYPE_GID",     AUPARSE_TYPE_GID);
1709     PyModule_AddIntConstant(m, "AUPARSE_TYPE_SYSCALL", AUPARSE_TYPE_SYSCALL);
1710     PyModule_AddIntConstant(m, "AUPARSE_TYPE_ARCH",    AUPARSE_TYPE_ARCH);
1711     PyModule_AddIntConstant(m, "AUPARSE_TYPE_EXIT",    AUPARSE_TYPE_EXIT);
1712     PyModule_AddIntConstant(m, "AUPARSE_TYPE_ESCAPED", AUPARSE_TYPE_ESCAPED);
1713     PyModule_AddIntConstant(m, "AUPARSE_TYPE_PERM",    AUPARSE_TYPE_PERM);
1714     PyModule_AddIntConstant(m, "AUPARSE_TYPE_MODE",    AUPARSE_TYPE_MODE);
1715     PyModule_AddIntConstant(m, "AUPARSE_TYPE_SOCKADDR", AUPARSE_TYPE_SOCKADDR);
1716     PyModule_AddIntConstant(m, "AUPARSE_TYPE_FLAGS",   AUPARSE_TYPE_FLAGS);
1717     PyModule_AddIntConstant(m, "AUPARSE_TYPE_PROMISC", AUPARSE_TYPE_PROMISC);
1718     PyModule_AddIntConstant(m, "AUPARSE_TYPE_CAPABILITY", AUPARSE_TYPE_CAPABILITY);
1719     PyModule_AddIntConstant(m, "AUPARSE_TYPE_SUCCESS", AUPARSE_TYPE_SUCCESS);
1720     PyModule_AddIntConstant(m, "AUPARSE_TYPE_A0",      AUPARSE_TYPE_A0);
1721     PyModule_AddIntConstant(m, "AUPARSE_TYPE_A1",      AUPARSE_TYPE_A1);
1722     PyModule_AddIntConstant(m, "AUPARSE_TYPE_A2",      AUPARSE_TYPE_A2);
1723     PyModule_AddIntConstant(m, "AUPARSE_TYPE_SIGNAL",  AUPARSE_TYPE_SIGNAL);
1724     PyModule_AddIntConstant(m, "AUPARSE_TYPE_LIST",    AUPARSE_TYPE_LIST);
1725
1726 #ifdef IS_PY3K
1727     return m;
1728 #endif
1729 }