linux-audit-bounces(a)redhat.com wrote on 03/10/2006 03:33:12 PM:
On Friday 10 March 2006 12:05, Steve Grubb wrote:
> so this is another round of updates with more details fleshed out.
OK. I think the last round of comments was helpful. I added some
language to
define the concept of multiple hosts in one log. This is the final
draft
unless there is an omission.
-Steve
Audit Event Parsing Library Specifications
==========================================
Definitions
-----------
An audit event is all records that have the same host, timestamp, and
serial number. Each event on a host has a unique timestamp and serial
number. An event is composed of multiple records which have information
about
different aspects of an audit event. Each record is denoted by a type
which
indicates what fields will follow. Information in the fields are held
by
a
name/value pair that contains an '=' between them. Each field
is
separated
from one another by a space or comma.
I know this is not likely to change, but is there a reason why we don't
have a common delimiter? I understand that going through the code and
modifying this would be a large undertaking, and I'm not even saying I
will do it (although I believe Loulwa was consider doing at one point, but
don't hold me to that). Removing inconstancies in the records, such as
using '_' in place of spaces in field names and removing these commas,
would seem like a good thing to do, but before anyone does that work, will
making that change be acceptable from a code point of view? (Discount any
work which might be needed to update parsing code from ausearch etc,
although there would be a fair amount to change I imagine).
Ground Rules
------------
All functions that begin with ausearch are related to searching for a
subset
of events based on certain criteria. All functions that begin with
auparse
are used to access events, records, and fields sequentially and
without
regard to any search options that may be in effect. All functions return
1
on success and 0 on failure unless otherwise noted. Where the return
type is
a char pointer, NULL will indicate failure. The data structures would
be
Typo: The data structures [would -> will] be
hidden from the external application. Access to fields is a
name/value
style.
You access the fields through functions that either return a pointer
to
an
immutable, zero-terminated array of ASCII characters or integral
values.
Every
function (except auparse_init) takes a parameter, au, which is the
internal
state information for the current query.
Although it is clear from the code example (and I am sure this is not
going to be the final version of the document, it would probably be nice
to mention that auparse will, when not using auparse_next_event, will be
parsing the record that was found (and is current being pointed to) by
ausearch_* functions, for example. Your comment in the above, "without
regard to any search options that may be in effect", is somewhat
befuddling on this point. A clear statement such as "auparse_* functions
will parse the current event found either through ausearch_* functions or
auparse_* functions." I am not a writer though, so don't use my suggestion
verbatim.
Functions
---------
auparse_state_t - is an opaque data type used for maintaining library
state.
typedef enum { AUSOURCE_LOGS, AUSOURCE_FILE, AUSOURCE_BUFFER }
ausource_t;
auparse_state_t *auparse_init(ausource_t source, const void *b) - allow
init
of library. Set data source: logs, file, buffer. The pointer
'b' is used
to
set the file name or pass the buff when those types are given.
typedef enum { AUSEARCH_STOP_EVENT, AUSEARCH_STOP_RECORD,
AUSEARCH_STOP_FIELD } austop_t;
int ausearch_set_param(auparse_state_t *au, const char *field, constchar
*op,
const char *value, austop_t where) - set
search
options. The field would be the left hand side of the audit name/value
pairs.
The op would be how to match: =,!=,>,<. The value would be the
right
hand
side of the audit field name/value pairs. The where parameter tells
the
search library where to place the internal cursor when a match is found.
It
could be on first field of first record, first field of record
containing the
match, or the field that matches.
int ausearch_next_event(auparse_state_t *au) - traverse to the next
event that
yields a match based on the given search criteria.
int auparse_next_event(auparse_state_t *au) - traverse to next event.
This
allows access to time and serial number.
typedef struct
{
time_t sec; // Event seconds
unsigned int milli; // millisecond of the timestamp
unsigned long serial; // Serial number of the event
const char *host; // Machine's name
} event_t;
event_t auparse_get_timestamp(auparse_state_t *au) - retrieve time stamp
of
current record
time_t auparse_get_time(auparse_state_t *au) - retrieve time in seconds
of
current record
time_t auparse_get_milli(auparse_state_t *au) - retrieve milliseconds
time of
current record
unsigned long auparse_get_serial(auparse_state_t *au) - retrieve serial
number
of current record
const char *auparse_get_host(auparse_state_t *au) - retrieve host name
of current record
int auparse_first_record(auparse_state_t *au) - set iterator to first
record
in current event
int auparse_next_record(auparse_state_t *au) - traverse to next record
in
event. This allows access to the event type
int auparse_get_type(auparse_state_t *au) - retrieve type of current
record
int auparse_first_field(auparse_state_t *au) - set field pointer to
first in
current record
int auparse_next_field(auparse_state_t *au) - traverse the fields in a
record
const char *auparse_find_field(auparse_state_t *au, const char *name) -
find a
given field in a event or record. Name is the left hand side of the
name/value
pair. Returns pointer to the value as ascii text.
const char *auparse_find_field_next(auparse_state_t *au) - find the next
occurance of that field in the same record. Returns pointer to the value
as
ascii text.
const char *auparse_get_field_str(auparse_state_t *au) - return current
field
value as a string
int auparse_get_field_int(auparse_state_t *au) - return current field
value
as an int
const char *auparse_interpret_field(auparse_state_t *au) - interpret the
current field
int auparse_destroy(auparse_state_t *au) - free all data structures and
close
file descriptors
Code Example
------------
int main(void)
{
auparse_state_t *au = auparse_init(AUSOURCE_LOGS, NULL);
if (au == NULL)
exit(1);
if (!ausearch_set_param(au, "auid", "=", "500",
AUSEARCH_STOP_EVENT))
exit(1);
while (ausearch_next_event(au)) {
if (auparse_find_field(au, "auid")) {
printf("auid=%s\n", auparse_interpret_field(au));
}
}
return 0;
}
--
Linux-audit mailing list
Linux-audit(a)redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit