Skip to contentSkip to conversation

Add expression support to libauparse

RFC PATCH In review Miloslav Trmac 2 participants 2 messages Feb 29, 2008 – Mar 8, 2008

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Add expression support to libauparse

Hello,
this patch extends libauparse to support arbitrary boolean expressions and searching for record type ranges.

It seems best to define expression syntax and add a single ausearch_add_expression() call, rather than build the expression from atomic subexpressions. The defined syntax could be shared by all tools that link to libauparse, and programs would be able to run (and display meaningful error messages, as opposed to crashing when a relocation can not be resloved) even if the installed libauparse version does not support the used filter.

Attached is a description of the expression syntax. Please check whether the design is reasonably future-proof. A nicer alternative to using three different sets of comparison operators would be welcome.
Mirek

LEXICAL STRUCTURE
White space (ASCII space, tab and new-line characters) between tokens is ignored. The following tokens are recognized:

Punctuation
( ) \

Logical operators
! && ||

Comparison operators
< <= == > >= !== i= i!= r= r!=

Unquoted strings
Any non-empty sequence of ASCII letters, digits, and the _ sym- bol.

Quoted strings
A sequence of characters surrounded by the " quotes. The \
character starts an escape sequence. The only defined escape
sequences are \\ and \". The semantics of other escape
sequences is undefined.

Anywhere an unquoted string is valid, a quoted string is valid as well,
and vice versa. In particular, field names may be specified using
quoted strings, and field values may be specified using unquoted strings.

EXPRESSION SYNTAX
The primary expression has the following form:

field comparison-operator value

field is either a string, which specifies the first field with that name within the current audit record, or the \ escape character fol- lowed by a string, which specifies a virtual field with the specified name (virtual fields are defined in a later section).

field is a string. operator specifies the comparison to perform

r= r!= Get the "raw" string of field, and compare it to value. For
fields in audit records, the "raw" string is the exact string stored in the audit record (with all escaping and unprintable character encoding left alone); applications can read the "raw" string using auparse get field str(3). Each virtual field may
define a "raw" string. If field is not present or does not
define a "raw" string, the result of the comparison is false (regardless of the operator).

i= i!= Get the "interpreted" string of field, and compare it to value.
For fields in audit records, the "interpreted" string is an "user-readable" interpretation of the field value; applications
can read the "interpreted" string using auparse inter-
pret field(3). Each virtual field may define an "interpreted"
string. If field is not present or does not define an "inter- preted" string, the result of the comparison is false (regard- less of the operator).

< <= == > >= !==
Evaluate the "value" of field, and compare it to value. A
"value" may be defined for any field or virtual field, but no
"value" is currently defined for any audit record field. The
rules of parsing value for comparing it with the "value" of field are specific for each field. If field is not present, the result of the comparison is false (regardless of the operator). If field does not define a "value", an error is reported when parsing the expression.

If E1 and E2 are valid expressions, then ! E1, E1 && E2, and E1 || E2 are valid expressions as well, with the usual C semantics and evalua- tion priorities. Note that ! field op value is interpreted as !(field op value), not as (!field) op value.

VIRTUAL FIELDS
The following virtual fields are defined:

\timestamp
The value is the timestamp of the current event. value must
have the ts:seconds.milli format, where seconds and milli are decimal numbers specifying the seconds and milliseconds part of the timestamp, respectively.

\record_type
The value is the type of the current record. value is either the record type name, or a decimal number specifying the type.

SEMANTICS
The expression as a whole applies to a single record. The expression
is true for a specified event if it is true for any record associated with the event.

EXAMPLES
As a demonstration of the semantics of handling missing fields, the following expression is true if field is present:

(field r= "") || (field r!= "")

and the same expression surrounded by !( and ) is true if field is not present.

FUTURE DIRECTIONS
New escape sequences for quoted strings may be defined.

For currently defined virtual fields that do not define a "raw" or "interpreted" string, the definition may be added. Therefore, don’t rely on the fact that comparing the "raw" or "interpreted" string of the field with any value is false.

New formats of value constants for the \timestamp virtual field may be added.

auparse/auparse.c +119 -170
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/auparse/auparse.c audit-1.6.7/auparse/auparse.c
@@ -21,6 +21,7 @@
  */
 
 #include "config.h"
+#include "expression.h"
 #include "internal.h"
 #include "auparse.h"
 #include "interpret.h"
@@ -195,10 +196,10 @@
 	au->line_pushed = 0;
 	aup_list_create(&au->le);
 	au->parse_state = EVENT_EMPTY;
-	aurule_create(&au->rules);
+	au->expr = NULL;
 	au->find_field = NULL;
 	au->search_where = AUSEARCH_STOP_EVENT;
-	au->search_how = AUSEARCH_RULE_CLEAR;
+	au->regex_valid = 0;
 
 	return au;
 bad_exit:
@@ -297,67 +298,75 @@
 }
 
 
-static struct nv_pair optab[] = {
-	{AUSEARCH_EXISTS, "exists"},
-	{AUSEARCH_EQUAL, "="},
-	{AUSEARCH_NOT_EQUAL, "!="},
-};
-#define OP_NAMES (sizeof(optab)/sizeof(optab[0]))
-
-static int lookup_op(const char *op)
-{
-        int i;
-
-        for (i = 0; i < OP_NAMES; i++)
-                if (strcmp(optab[i].name, op) == 0)
-                        return optab[i].value;
+/* Add EXPR to AU, using HOW to select the combining operator.
+   On success, return 0.
+   On error, free EXPR set errno and return -1.
+   NOTE: EXPR is freed on error! */
+static int add_expr(auparse_state_t *au, struct expr *expr, ausearch_rule_t how)
+{
+	if (au->expr == NULL)
+		au->expr = expr;
+	else if (how == AUSEARCH_RULE_CLEAR) {
+		expr_free(au->expr);
+		au->expr = expr;
+	} else {
+		struct expr *e;
 
-        return -1;
+		e = expr_create_binary(how == AUSEARCH_RULE_OR ? EO_OR : EO_AND,
+				       au->expr, expr);
+		if (e == NULL) {
+			int err;
+
+			err = errno;
+			expr_free(expr);
+			errno = err;
+			return -1;
+		}
+		au->expr = e;
+	}
+	return 0;
 }
 
-
 static int ausearch_add_item_internal(auparse_state_t *au, const char *field,
-	const char *op, const char *value, ausearch_rule_t how,
-	ausearch_op_t op_flag)
+	const char *op, const char *value, ausearch_rule_t how, unsigned op_eq,
+	unsigned op_ne)
 {
-	aurulenode rn;
-	int t_op = lookup_op(op);
-	if (t_op < 0)
-		goto err_out;
+	struct expr *expr;
 
 	// Make sure there's a field
 	if (field == NULL)
 		goto err_out;
 
 	// Do not allow regex to get replaced this way
-	if (au->search_how == AUSEARCH_RULE_REGEX)
+	if (au->regex_valid != 0)
 		goto err_out;
 
 	// Make sure how is within range
 	if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
 		goto err_out;
-	if (how == AUSEARCH_RULE_CLEAR) {
-		aurule_clear(&au->rules);
-	} else if (how != au->search_how && 
-				au->search_how != AUSEARCH_RULE_CLEAR) {
-		errno = EEXIST;
-		return -1;
-	}
 
 	// All pre-checks are done, build a rule
-	rn.search_op = t_op | op_flag;
-	if (t_op == AUSEARCH_EXISTS)
-		rn.v.field.val = NULL;
+	if (strcmp(op, "exists") == 0)
+		expr = expr_create_field_exists(field);
 	else {
+		unsigned t_op;
+
+		if (strcmp(op, "=") == 0)
+			t_op = op_eq;
+		else if (strcmp(op, "!=") == 0)
+			t_op = op_ne;
+		else
+			goto err_out;
 		if (value == NULL)
 			goto err_out;
-		rn.v.field.val = strdup(value);
+		expr = expr_create_comparison(field, t_op, value);
 	}
-	rn.v.field.field = strdup(field);
-	aurule_append(&au->rules, &rn);
-	au->search_how = how;
-
+	if (expr == NULL)
+		return -1;
+	if (add_expr(au, expr, how) != 0)
+		return -1; /* expr is freed by add_expr() */
 	return 0;
+
 err_out:
 	errno = EINVAL;
 	return -1;
@@ -366,83 +375,104 @@
 int ausearch_add_item(auparse_state_t *au, const char *field, const char *op,
 	const char *value, ausearch_rule_t how)
 {
-	return ausearch_add_item_internal(au, field, op, value, how, 0);
+	return ausearch_add_item_internal(au, field, op, value, how, EO_RAW_EQ,
+					  EO_RAW_NE);
 }
 
 int ausearch_add_interpreted_item(auparse_state_t *au, const char *field,
 	const char *op, const char *value, ausearch_rule_t how)
 {
 	return ausearch_add_item_internal(au, field, op, value, how,
-					  AUSEARCH_INTERPRETED);
+					  EO_INTERPRETED_EQ, EO_INTERPRETED_NE);
 }
 
-static int lookup_ts_op(const char *op)
+int ausearch_add_timestamp_item(auparse_state_t *au, const char *op, time_t sec,
+				unsigned milli, ausearch_rule_t how)
 {
-	static const struct nv_pair ts_tab[] = {
-		{AUSEARCH_TIME_LT, "<"},
-		{AUSEARCH_TIME_LE, "<="},
-		{AUSEARCH_TIME_GE, ">="},
-		{AUSEARCH_TIME_GT, ">"},
-		{AUSEARCH_TIME_EQ, "="},
+	static const struct {
+		unsigned value;
+		char name[3];
+	} ts_tab[] = {
+		{EO_VALUE_LT, "<"},
+		{EO_VALUE_LE, "<="},
+		{EO_VALUE_GE, ">="},
+		{EO_VALUE_GT, ">"},
+		{EO_VALUE_EQ, "="},
 	};
 
+	struct expr *expr;
         size_t i;
+	unsigned t_op;
 
-        for (i = 0; i < sizeof(ts_tab) / sizeof(*ts_tab); i++)
+        for (i = 0; i < sizeof(ts_tab) / sizeof(*ts_tab); i++) {
                 if (strcmp(ts_tab[i].name, op) == 0)
-                        return ts_tab[i].value;
-
-        return -1;
-}
+			goto found_op;
+	}
+	goto err_out;
+found_op:
+	t_op = ts_tab[i].value;
 
-int ausearch_add_timestamp_item(auparse_state_t *au, const char *op, time_t sec,
-				unsigned milli, ausearch_rule_t how)
-{
-	aurulenode rn;
-	int t_op = lookup_ts_op(op);
-	if (op < 0)
-		goto err_out;
 	if (milli >= 1000)
 		goto err_out;
 
 	// Do not allow regex to get replaced this way
-	if (au->search_how == AUSEARCH_RULE_REGEX)
+	if (au->regex_valid != 0)
 		goto err_out;
 
 	// Make sure how is within range
 	if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
 		goto err_out;
-	if (how == AUSEARCH_RULE_CLEAR) {
-		aurule_clear(&au->rules);
-	} else if (how != au->search_how
-		   && au->search_how != AUSEARCH_RULE_CLEAR) {
-		errno = EEXIST;
-		return -1;
-	}
 
 	// All pre-checks are done, build a rule
-	rn.search_op = t_op;
-	rn.v.timestamp.sec = sec;
-	rn.v.timestamp.milli = milli;
-	aurule_append(&au->rules, &rn);
-	au->search_how = how;
-
+	expr = expr_create_timestamp_comparison(t_op, sec, milli);
+	if (expr == NULL)
+		return -1;
+	if (add_expr(au, expr, how) != 0)
+		return -1; /* expr is freed by add_expr() */
 	return 0;
+
 err_out:
 	errno = EINVAL;
 	return -1;
 }
 
+int ausearch_add_expression(auparse_state_t *au, const char *expression,
+			    char **error, ausearch_rule_t how)
+{
+	struct expr *expr;
+
+	// Do not allow regex to get replaced this way
+	if (au->regex_valid != 0)
+		goto err_einval;
+	if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
+		goto err_einval;
+
+	expr = expr_parse(expression, error);
+	if (expr == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (add_expr(au, expr, how) != 0)
+		goto err; /* expr is freed by add_expr() */
+	return 0;
+
+err_einval:
+	errno = EINVAL;
+err:
+	*error = NULL;
+	return -1;
+}
+
 int ausearch_add_regex(auparse_state_t *au, const char *expr)
 {
-	aurulenode rn;
 	int rc;
 
 	// Make sure there's an expression
 	if (expr == NULL)
 		goto err_out;
 
-	if (au->search_how != AUSEARCH_RULE_CLEAR)
+	if (au->regex_valid != 0 || au->expr != NULL)
 		goto err_out;
 
 	// Compile expression now to make sure the expression is correct
@@ -450,13 +480,7 @@
 	if (rc) {
 		goto err_out;
 	}
-
-	// Store it away just in case.
-	rn.search_op = AUSEARCH_UNSET;
-	rn.v.field.field = strdup(expr);
-	rn.v.field.val = NULL;
-	aurule_append(&au->rules, &rn);
-	au->search_how = AUSEARCH_RULE_REGEX;
+	au->regex_valid = 1;
 
 	return 0; 
 
@@ -478,11 +502,15 @@
 
 void ausearch_clear(auparse_state_t *au)
 {
-	if (au->search_how == AUSEARCH_RULE_REGEX && au->rules.cnt > 0)
+	if (au->regex_valid != 0) {
 		regfree(&au->regex);
-	aurule_clear(&au->rules);
+		au->regex_valid = 0;
+	}
+	if (au->expr != NULL) {
+		expr_free(au->expr);
+		au->expr = NULL;
+	}
 	au->search_where = AUSEARCH_STOP_EVENT;
-	au->search_how = AUSEARCH_RULE_CLEAR;
 }
 hidden_def(ausearch_clear)
 
@@ -856,76 +884,15 @@
 	return rc;
 }
 
-/* Return the result of interpreting rule on the event record r. */
-static int ausearch_interpret_rule(auparse_state_t *au, rnode *r,
-				   aurulenode *rule)
-{
-	int search_op;
-
-	search_op = (rule->search_op & ~AUSEARCH_INTERPRETED);
-	if (AUSEARCH_OP_IS_TIME__(search_op)) {
-		int val;
-
-		if (au->le.e.sec < rule->v.timestamp.sec)
-			val = -1;
-		else if (au->le.e.sec > rule->v.timestamp.sec)
-			val = 1;
-		else if (au->le.e.milli < rule->v.timestamp.milli)
-			val = -1;
-		else if (au->le.e.milli > rule->v.timestamp.milli)
-			val = 1;
-		else
-			val = 0;
-		switch (search_op) {
-		case AUSEARCH_TIME_LT:
-			return val < 0;
-		case AUSEARCH_TIME_LE:
-			return val <= 0;
-		case AUSEARCH_TIME_GE:
-			return val >= 0;
-		case AUSEARCH_TIME_GT:
-			return val > 0;
-		case AUSEARCH_TIME_EQ:
-			return val == 0;
-		default:
-			abort();
-		}
-	} else {
-		int found, rc;
-		const char *val;
-
-		found = nvlist_find_name(&r->nv, rule->v.field.field);
-		if (!found)
-			return 0;
-		if (search_op == AUSEARCH_EXISTS)
-			return 1;
-
-		val = NULL;
-		if ((rule->search_op & AUSEARCH_INTERPRETED) != 0)
-			val = nvlist_interp_cur_val(r);
-		if (val == NULL)
-			val = nvlist_get_cur_val(&r->nv);
-		rc = strcmp(rule->v.field.val, val);
-		if (search_op == AUSEARCH_EQUAL)
-			return rc == 0;
-		else
-			return rc != 0;
-	}
-}
-
 /* This is called during search once per each record. It walks the list
  * of nvpairs and decides if a field matches. */
 static int ausearch_compare(auparse_state_t *au)
 {
 	rnode *r;
 
-	if (au->search_how == AUSEARCH_RULE_REGEX) {
+	if (au->regex_valid != 0) {
 		int rc;
 
-		if (au->rules.cnt == 0) {
-			errno = EINVAL;
-			return -1;
-		}
 		r = aup_list_get_cur(&au->le);
 		rc = regexec(&au->regex, r->record, 0, NULL, 0);
 		if (rc == 0)
@@ -934,27 +901,9 @@
 			return 0;
 	}
 	r = aup_list_get_cur(&au->le);
-	if (r) {
-		// for each rule item
-		int results = (au->search_how == AUSEARCH_RULE_AND);
-		aurule_first(&au->rules);
-		do {
-			int tmp;
+	if (r)
+		return expr_eval(au, r, au->expr);
 
-			aurulenode *rule = aurule_get_cur(&au->rules);
-			if (rule == NULL) 
-				continue;
-			tmp = ausearch_interpret_rule(au, r, rule);
-			if (au->search_how == AUSEARCH_RULE_AND) {
-				if (tmp == 0)
-					return 0; /* all must match */
-			} else if (au->search_how <= AUSEARCH_RULE_OR && tmp)
-				return 1; /* Anytime tmp == 1 short circuit */
-		} while (aurule_next(&au->rules));
-		if (results)
-			return 1;
-	}
-	
 	return 0;
 }
 
@@ -963,7 +912,7 @@
 {
 	int rc;
 
-	if (au->rules.cnt == 0) {
+	if (au->expr == NULL && au->regex_valid == 0) {
 		errno = EINVAL;
 		return -1;
 	}
auparse/auparse-defs.h +2 -6
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/auparse/auparse-defs.h audit-1.6.7/auparse/auparse-defs.h
@@ -37,21 +37,17 @@
 	AUSOURCE_BUFFER, AUSOURCE_BUFFER_ARRAY,
 	AUSOURCE_DESCRIPTOR, AUSOURCE_FILE_POINTER, AUSOURCE_FEED } ausource_t;
 
-/* This defines the types of searches that can be done */
+/* This used to define the types of searches that can be done.  It is not used
+   any more. */
 typedef enum {
 	AUSEARCH_UNSET,
 	AUSEARCH_EXISTS,
 	AUSEARCH_EQUAL, AUSEARCH_NOT_EQUAL,
 	AUSEARCH_TIME_LT, AUSEARCH_TIME_LE, AUSEARCH_TIME_GE, AUSEARCH_TIME_GT,
 	AUSEARCH_TIME_EQ,
-	/* When comparing, use the value that would be returned by
-	   auparse_interpret_field() instead of the raw value. */
 	AUSEARCH_INTERPRETED = 0x40000000
 } ausearch_op_t;
 
-#define AUSEARCH_OP_IS_TIME__(OP) \
-  ((OP) >= AUSEARCH_TIME_LT && (OP) <= AUSEARCH_TIME_EQ)
-
 /* This determines where to position the cursor when a search completes */
 typedef enum { AUSEARCH_STOP_EVENT, AUSEARCH_STOP_RECORD,
 	AUSEARCH_STOP_FIELD } austop_t;
auparse/auparse.h +2 -0
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/auparse/auparse.h audit-1.6.7/auparse/auparse.h
@@ -49,6 +49,8 @@
 void auparse_destroy(auparse_state_t *au);
 
 /* Functions that are part of the search interface */
+int ausearch_add_expression(auparse_state_t *au, const char *expression,
+			    char **error, ausearch_rule_t how);
 int ausearch_add_item(auparse_state_t *au, const char *field, const char *op,
 			const char *value, ausearch_rule_t how);
 int ausearch_add_interpreted_item(auparse_state_t *au, const char *field,
auparse/expression.c +975 -0

975 lines not on this page · raw message

auparse/expression.h +112 -0

112 lines not on this page · raw message

auparse/internal.h +4 -5
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/auparse/internal.h audit-1.6.7/auparse/internal.h
@@ -19,12 +19,11 @@
  * Authors:
  *	Steve Grubb <[email protected]>
  */
-#ifndef AUPARSE_INTERNAL_HEADER_
+#ifndef AUPARSE_INTERNAL_HEADER
 #define AUPARSE_INTERNAL_HEADER
 
 #include "auparse-defs.h"
 #include "ellist.h"
-#include "rlist.h"
 #include "auditd-config.h"
 #include "data_buf.h"
 #include <stdio.h>
@@ -78,13 +77,13 @@
 	int line_pushed;		// True if retrieve_next_line() 
 					//	returns same input
 	event_list_t le;		// Linked list of record in same event
-	aurule_list_t rules;		// Search rules
+	struct expr *expr;		// Search expression or NULL
 	char *find_field;		// Used to store field name when
 					//	 searching
 	austop_t search_where;		// Where to put the cursors on a match
-	ausearch_rule_t search_how;	// How the rules are to be applied
 	auparser_state_t parse_state;	// parsing state
-	regex_t regex;			// compiled regex
+	regex_t regex;			// compiled regex if regex_valid != 0
+	int regex_valid;
 	DataBuf databuf;		// input data
 
 	// function to call to notify user of parsing changes
auparse/Makefile.am +6 -6
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/auparse/Makefile.am audit-1.6.7/auparse/Makefile.am
@@ -27,12 +27,12 @@
 LIBS =
 lib_LTLIBRARIES = libauparse.la
 include_HEADERS = auparse.h auparse-defs.h
-libauparse_la_SOURCES = rlist.c nvpair.c interpret.c nvlist.c ellist.c \
-	auparse.c auditd-config.c message.c data_buf.c auparse-defs.h   \
-	data_buf.h flagtab.h nvlist.h rlist.h auparse.h ellist.h        \
-	internal.h nvpair.h rnode.h captab.h famtab.h interpret.h       \
-	open-flagtab.h socktab.h clone-flagtab.h fcntl-cmdtab.h         \
-	ipctab.h private.h typetab.h
+libauparse_la_SOURCES = nvpair.c interpret.c nvlist.c ellist.c		\
+	auparse.c auditd-config.c message.c data_buf.c auparse-defs.h	\
+	data_buf.h flagtab.h nvlist.h auparse.h ellist.h		\
+	internal.h nvpair.h rnode.h captab.h famtab.h interpret.h	\
+	open-flagtab.h socktab.h clone-flagtab.h fcntl-cmdtab.h		\
+	ipctab.h private.h typetab.h expression.c expression.h
 
 libauparse_la_LIBADD = ${top_srcdir}/lib/libaudit.la
 libauparse_la_DEPENDENCIES = $(libauparse_la_SOURCES) ../config.h
auparse/rlist.c +0 -102

102 lines not on this page · raw message

auparse/rlist.h +0 -65

65 lines not on this page · raw message

bindings/python/auparse_python.c +90 -39

197 lines not on this page · raw message

docs/ausearch_add_expression.3 +71 -0

71 lines not on this page · raw message

docs/ausearch_add_interpreted_item.3 +12 -8
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/docs/ausearch_add_interpreted_item.3 audit-1.6.7/docs/ausearch_add_interpreted_item.3
@@ -8,7 +8,7 @@
 
 .SH "DESCRIPTION"
 
-ausearch_add_interpreted_item adds one search condition to the audit search API. The search conditions can then be used to scan logs, files, or buffers for something of interest. The field value is the field name that the value will be checked for. The op variable describes what kind of check is to be done. Legal op values are:
+ausearch_add_interpreted_item adds one search condition to the current audit search expression. The search conditions can then be used to scan logs, files, or buffers for something of interest. The field value is the field name that the value will be checked for. The op variable describes what kind of check is to be done. Legal op values are:
 
 .RS
 .TP
@@ -24,33 +24,37 @@
 
 The value parameter is compared to the interpreted field value (the value that would be returned by \fBauparse_interpret_field\fR(3)).
 
-The how value determines how this search condition will be stored internally. The possible values are:
+The how value determines how this search condition will affect the existing search expression if one is already defined. The possible values are:
 .RS
 .TP
 .I AUSEARCH_RULE_CLEAR
-When this is used, it clears any previous search condition and inserts it as the first one.
+Clear the current search expression, if any, and use only this search condition.
 .TP
 .I AUSEARCH_RULE_OR
-When this is used, it means that the results of its evaluation will be "or"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB || \fIthis_search_condition\fB)\fR.
 .TP
 .I AUSEARCH_RULE_AND
-When this is used, it means that the results of its evaluation will be "and"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB && \fIthis_search_condition\fB)\fR.
 .RE
 
-All search conditions must be the same type, you cannot mix "and" and "or".
-
 .SH "RETURN VALUE"
 
 Returns -1 if an error occurs; otherwise, 0 for success.
 
 .SH "SEE ALSO"
 
+.BR ausearch_add_expression (3),
 .BR ausearch_add_item (3),
 .BR ausearch_add_timestamp_item (3),
 .BR ausearch_add_regex (3),
 .BR ausearch_set_stop (3),
 .BR ausearch_clear (3),
-.BR ausearch_next_event (3).
+.BR ausearch_next_event (3),
+.BR ausearch-expression (5).
 
 .SH AUTHOR
 Steve Grubb
docs/ausearch_add_item.3 +12 -8
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/docs/ausearch_add_item.3 audit-1.6.7/docs/ausearch_add_item.3
@@ -8,7 +8,7 @@
 
 .SH "DESCRIPTION"
 
-ausearch_add_item adds one search condition to the audit search API. The search conditions can then be used to scan logs, files, or buffers for something of interest. The field value is the field name that the value will be checked for. The op variable describes what kind of check is to be done. Legal op values are:
+ausearch_add_item adds one search condition to the current audit search expression. The search conditions can then be used to scan logs, files, or buffers for something of interest. The field value is the field name that the value will be checked for. The op variable describes what kind of check is to be done. Legal op values are:
 
 .RS
 .TP
@@ -24,33 +24,37 @@
 
 The value parameter is compared to the uninterpreted field value.
 
-The how value determines how this search condition will be stored internally. The possible values are:
+The how value determines how this search condition will affect the existing search expression if one is already defined. The possible values are:
 .RS
 .TP
 .I AUSEARCH_RULE_CLEAR
-When this is used, it clears any previous search condition and inserts it as the first one.
+Clear the current search expression, if any, and use only this search condition.
 .TP
 .I AUSEARCH_RULE_OR
-When this is used, it means that the results of its evaluation will be "or"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB || \fIthis_search_condition\fB)\fR.
 .TP
 .I AUSEARCH_RULE_AND
-When this is used, it means that the results of its evaluation will be "and"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB && \fIthis_search_condition\fB)\fR.
 .RE
 
-All search conditions must be the same type, you cannot mix "and" and "or".
-
 .SH "RETURN VALUE"
 
 Returns -1 if an error occurs; otherwise, 0 for success.
 
 .SH "SEE ALSO"
 
+.BR ausearch_add_expression (3),
 .BR ausearch_add_interpreted_item (3),
 .BR ausearch_add_timestamp_item (3),
 .BR ausearch_add_regex (3), 
 .BR ausearch_set_stop (3), 
 .BR ausearch_clear (3), 
-.BR ausearch_next_event (3).
+.BR ausearch_next_event (3),
+.BR ausearch-expression (5).
 
 .SH AUTHOR
 Steve Grubb
docs/ausearch_add_regex.3 +4 -3
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/docs/ausearch_add_regex.3 audit-1.6.7/docs/ausearch_add_regex.3
@@ -8,7 +8,7 @@
 
 .SH "DESCRIPTION"
 
-ausearch_add_regex adds one search condition based on regular expressions to the audit search API. The search conditions can then be used to scan logs, files, or buffers for something of interest. You may not use this in combination with any other rule. The regular expression follows the posix regular expression conventions. The search results are at the record level and not the field.
+ausearch_add_regex adds one search condition based on regular expressions to the audit search API. The search conditions can then be used to scan logs, files, or buffers for something of interest. You may not use this in combination with any other search expression. The regular expression follows the posix regular expression conventions. The search results are at the record level and not the field.
 
 .SH "RETURN VALUE"
 
@@ -16,8 +16,9 @@
 
 .SH "SEE ALSO"
 
-.BR ausearch_add_item (3), 
-.BR ausearch_clear (3), 
+.BR ausearch_add_expression (3),
+.BR ausearch_add_item (3),
+.BR ausearch_clear (3),
 .BR ausearch_next_event (3),
 .BR regcomp (3).
 
docs/ausearch_add_timestamp_item.3 +15 -8
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/docs/ausearch_add_timestamp_item.3 audit-1.6.7/docs/ausearch_add_timestamp_item.3
@@ -8,23 +8,25 @@
 
 .SH "DESCRIPTION"
 
-ausearch_add_timestamp_item adds an event time condition to an audit search state. The search conditions can then be used to scan logs, files, or buffers for something of interest. The op parameter specifies the desired comparison. Legal op values are \fI<\fR, \fI<=\fR, \fI>=\fR, \fI>\fR and \fI=\fR.  The left operand of the comparison operator is the timestamp of the examined event, the right operand is specified by the sec and milli parameters.
+ausearch_add_timestamp_item adds an event time condition to the current audit search expression. The search conditions can then be used to scan logs, files, or buffers for something of interest. The op parameter specifies the desired comparison. Legal op values are \fI<\fR, \fI<=\fR, \fI>=\fR, \fI>\fR and \fI=\fR.  The left operand of the comparison operator is the timestamp of the examined event, the right operand is specified by the sec and milli parameters.
 
-The how value determines how this search condition will be stored internally. The possible values are:
+The how value determines how this search condition will affect the existing search expression if one is already defined. The possible values are:
 .RS
 .TP
 .I AUSEARCH_RULE_CLEAR
-When this is used, it clears any previous search condition and inserts it as the first one.
+Clear the current search expression, if any, and use only this search condition.
 .TP
 .I AUSEARCH_RULE_OR
-When this is used, it means that the results of its evaluation will be "or"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB || \fIthis_search_condition\fB)\fR.
 .TP
 .I AUSEARCH_RULE_AND
-When this is used, it means that the results of its evaluation will be "and"ed with other search conditions.
+If a search expression
+.I E
+is already configured, replace it by \fB(\fIE\fB && \fIthis_search_condition\fB)\fR.
 .RE
 
-All search conditions must be the same type, you cannot mix "and" and "or".
-
 .SH "RETURN VALUE"
 
 Returns -1 if an error occurs; otherwise, 0 for success.
@@ -36,15 +38,20 @@
 and
 .BR ausearch_add_interpreted_item (3)
 to add conditions that check audit record fields.
+Use
+.BR ausearch_add_expression (3)
+to add complex search expressions using a single function call.
 
 .SH "SEE ALSO"
 
+.BR ausearch_add_expression (3),
 .BR ausearch_add_item (3),
 .BR ausearch_add_interpreted_item (3),
 .BR ausearch_add_regex (3),
 .BR ausearch_set_stop (3),
 .BR ausearch_clear (3),
-.BR ausearch_next_event (3).
+.BR ausearch_next_event (3),
+.BR ausearch-expression (5).
 
 .SH AUTHOR
 Miloslav Trmac
docs/ausearch-expression.5 +212 -0

212 lines not on this page · raw message

docs/Makefile.am +3 -1
diff --exclude .deps --exclude '*.o' --exclude '*~' -urN audit/docs/Makefile.am audit-1.6.7/docs/Makefile.am
@@ -43,8 +43,10 @@
 auparse_get_type.3 auparse_init.3 auparse_interpret_field.3 \
 auparse_next_event.3 auparse_next_field.3 auparse_next_record.3 \
 auparse_node_compare.3 auparse_reset.3 auparse_timestamp_compare.3 \
+ausearch-expression.5 \
 aureport.8 ausearch.8 ausearch_add_item.3 ausearch_add_interpreted_item.3 \
-ausearch_add_timestamp_item.3 ausearch_add_regex.3 ausearch_clear.3 \
+ausearch_add_expression.3 ausearch_add_timestamp_item.3 ausearch_add_regex.3 \
+ausearch_clear.3 \
 ausearch_next_event.3 ausearch_set_stop.3 \
 autrace.8 get_auditfail_action.3 set_aumessage_mode.3 \
 audispd.8 audispd.conf.5 audispd-zos-remote.8 zos-remote.conf.5 \
#1 lore raw
Quoted 2 lines · On Friday 29 February 2008 14:00:56 Miloslav Trmac wrote:

this patch extends libauparse to support arbitrary boolean expressions and searching for record type ranges.

Applied thanks!

-Steve