Audit Parsing Library Requirements

John D. Ramsdell ramsdell at mitre.org
Thu Mar 16 14:26:51 UTC 2006


Steve,

I decided to write a simple program against the interface defined by
the Audit Event Parsing Library Specifications, but found a function
missing from the specification.  I could find no way to get the name
associated with the current field.  Let me suggest the addition of a
function with the following prototype.

const char *auparse_get_field_name(auparse_state_t *au) - return
current field name as a string

With this addition, I'm guessing I can translate a log into a textual
form similar to what is produced by ausearch, but with quoting, by
using a program with a main routine something like the following.

int 
main(int argc, char **argv)
{
  auparse_state_t *au = auparse_init(AUSOURCE_LOGS, NULL);
  
  while (auparse_next_event(au)) {
    if (auparse_first_record(au)) {
      printf("---\n");
      do {			/* for each record in this event */
	if (auparse_first_field(au)) {
	  int not_first = 0;
	  do {			/* for each field in this record */
	    if (not_first) 
	      putchar(' ');
	    else
	      not_first = 1;
	    const char *name = auparse_get_field_name(au);
	    const char *value = auparse_interpret_field(au);
	    if (!name || !value) {
	      fprintf(stderr, "Internal error\n");
	      return 1;
	    }
	    putitem(name);
	    putchar('=');
	    putitem(value);    /* Putitem quotes an item as needed. */
	  } while (auparse_next_field(au));
	}
	putchar('\n');
      } while (auparse_next_record(au));
    }
  }
  return 0;
}

John

Steve Grubb <sgrubb at redhat.com> writes:

> On Friday 10 March 2006 16:33, Steve Grubb wrote:
> > OK. I think the last round of comments was helpful.
> 
> 
> 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.
> 
> 
> 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 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.
> 
> 
> Name-Value Matching Operators
> -----------------------------
> The ausearch_ functions will select records in its search results based on
> operators used for matching name/value pairs. For fields that are numeric,
> the following mathematical operators are allowed:  =,!=,>,=>,<,<=. The field
> is converted to a number before matching is done.
> 
> For fields that are non-numeric, the operators in use will be:
>         =       The string completely matches
>         !=      The string does not match
>         ~       A substring match is done
>         regex   Regular expression is used
> 
> 
> Functions
> ---------
> auparse_state_t - is an opaque data type used for maintaining library state.
> 
> typedef enum { AUSOURCE_LOGS, AUSOURCE_FILE, AUSOURCE_FILE_ARRAY,
>         AUSOURCE_BUFFER, AUSOURCE_BUFFER_ARRAY } ausource_t;
> 
> auparse_state_t *auparse_init(ausource_t source, const void *b) - allow init 
> of library. Set data source: logs, file, null terminated array of filenames,
> buffer, null terminated array of addresses. 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, const char *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 the operator described in the section above telling 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_node(auparse_state_t *au) - retrieve host (node) 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));
>                 }
>         }
>         auparse_destroy(au);
>         return 0;
> }
> 
> --
> Linux-audit mailing list
> Linux-audit at redhat.com
> https://www.redhat.com/mailman/listinfo/linux-audit




More information about the Linux-audit mailing list