Example #1
0
/* This function shows how to iterate through the fields of a record
 * and print its name and raw value and interpretted value. */
static void dump_fields_of_record(auparse_state_t *au)
{
	printf("record type %d(%s) has %d fields\n", auparse_get_type(au),
		audit_msg_type_to_name(auparse_get_type(au)),
		auparse_get_num_fields(au));

	printf("line=%d file=%s\n", auparse_get_line_number(au),
		auparse_get_filename(au) ? auparse_get_filename(au) : "stdin");

	const au_event_t *e = auparse_get_timestamp(au);
	if (e == NULL) {
		printf("Error getting timestamp - aborting\n");
		return;
	}
	/* Note that e->sec can be treated as time_t data if you want
	 * something a little more readable */
	printf("event time: %u.%u:%lu, host=%s\n", (unsigned)e->sec,
		e->milli, e->serial, e->host ? e->host : "?");
		auparse_first_field(au);

	do {
		printf("field: %s=%s (%s)\n",
		auparse_get_field_name(au),
		auparse_get_field_str(au),
		auparse_interpret_field(au));
	} while (auparse_next_field(au) > 0);
	printf("\n");
}
Example #2
0
const char *auparse_get_type_name(auparse_state_t *au)
{
	if (au->le == NULL)
		return NULL;

	rnode *r = aup_list_get_cur(au->le);
	if (r)
		return audit_msg_type_to_name(r->type);
	else
		return NULL;
}
static void do_type_summary_output(ilist *sptr)
{
	const int_node *in;

	if (sptr->cnt == 0) {
		printf("<no events of interest were found>\n\n");
		return;
	}
	ilist_first(sptr);
	in=ilist_get_cur(sptr);
	while (in) {
		const char *name = audit_msg_type_to_name(in->num);
		if (report_format == RPT_DEFAULT)
			printf("%u  %d\n", in->hits, in->num);
		else
			printf("%u  %s\n", in->hits, name);
		in=ilist_next(sptr);
	}
}
void print_per_event_item(llist *l)
{
	char buf[128];
	char name[64];
	char date[32];
	struct tm *tv;

	// The beginning is common to all reports
	tv = localtime(&l->e.sec);
	if (tv)
		strftime(date, sizeof(date), "%x %T", tv);
	else
		strcpy(date, "?");
	if (report_type != RPT_AVC) {
		line_item++;
		printf("%u. %s ", line_item, date);
	}

	switch (report_type)
	{
		case RPT_AVC:
			alist_find_avc(l->s.avc);
			do {
				anode *an = l->s.avc->cur;
				line_item++;
				printf("%u. %s ", line_item, date);
		// command subject syscall action obj res event
			safe_print_string(l->s.comm ? l->s.comm : "?", 0);
			printf(" %s %s %s %s %s %s %lu\n", 
				an->scontext, 
				aulookup_syscall(l, buf,sizeof(buf)),
				an->avc_class, an->avc_perm,
				an->tcontext, aulookup_result(an->avc_result),
				l->e.serial);
//printf("items:%d\n", l->s.avc->cnt);
			} while (alist_next_avc(l->s.avc));
			break;
		case RPT_CONFIG:
			// FIXME:who, action, what, outcome, event
			// NOW: type auid success event
			printf("%s %s %s %lu\n",
				audit_msg_type_to_name(l->head->type),
				aulookup_uid(l->s.loginuid, name, sizeof(name)),
				aulookup_success(l->s.success), l->e.serial);
			break;
		case RPT_AUTH:
			// who, addr, terminal, exe, success, event
			// Special note...uid is used here because that is
			// the way that the message works. This is because
			// on failed logins, loginuid is not set.
			safe_print_string(l->s.acct ? l->s.acct :
				aulookup_uid(l->s.uid, name, sizeof(name)), 0);
			printf(" %s %s %s %s %lu\n",
				l->s.hostname, l->s.terminal,
				l->s.exe, aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_LOGIN:
			// who, addr, terminal, exe, success, event
			// Special note...loginuid can be used here for
			// successful logins. loginuid is not set on failed
			// logins so acct is used in that situation.
			safe_print_string(((l->s.success == S_FAILED) &&
				l->s.acct) ? l->s.acct :
				aulookup_uid(l->s.loginuid,
						name, sizeof(name)), 0);
			printf(" %s %s %s %s %lu\n", 
				l->s.hostname, l->s.terminal,
				l->s.exe, aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_ACCT_MOD:
			// who, addr, terminal, exe, success, event
			safe_print_string(
				aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %s %s %s %s %s %lu\n",
				l->s.hostname ? l->s.hostname : "?",
				l->s.terminal ? l->s.terminal : "?",
				l->s.exe ? l->s.exe : "?",
				l->s.acct ? l->s.acct : "?",
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_EVENT:	// report_detail == D_DETAILED
			//        event, type, who, success
			printf("%lu %s ",
				l->e.serial,
				audit_msg_type_to_name(l->head->type));
			safe_print_string(aulookup_uid(l->s.loginuid, name, 
					sizeof(name)), 0);
			printf(" %s\n",	aulookup_success(l->s.success));
			break;
		case RPT_FILE:	// report_detail == D_DETAILED
			// file, syscall, success, exe, who, event
			{
			slist *s = l->s.filename;
			slist_first(s);
			if (s->cnt > 1) {
				char *key = s->cur ? s->cur->key : NULL;
				while (key && strcmp(key, "PARENT") == 0) {
					slist_next(s);
					key = s->cur ? s->cur->key : NULL;
				}
			}
			safe_print_string(s->cur ? s->cur->str : "", 0);
			printf(" %s %s ",
				aulookup_syscall(l,buf,sizeof(buf)),
				aulookup_success(l->s.success));
			safe_print_string(l->s.exe ? l->s.exe : "?", 0);
			putchar(' ');
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			}
			break;
		case RPT_HOST:	// report_detail == D_DETAILED
			// host, syscall, who, event
			printf("%s %s ",
				l->s.hostname,
				aulookup_syscall(l,buf,sizeof(buf)));
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_PID:	// report_detail == D_DETAILED
			// pid, exe, syscall, who, event
			printf("%u ", l->s.pid);
			safe_print_string(l->s.exe ? l->s.exe : "?", 0);
			printf(" %s ", aulookup_syscall(l,buf,sizeof(buf)));
			safe_print_string(aulookup_uid(l->s.loginuid, name,
				sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_SYSCALL:	// report_detail == D_DETAILED
			// syscall, pid, comm, who, event
			printf("%s %u ", aulookup_syscall(l,buf,sizeof(buf)),
				l->s.pid);
			safe_print_string(l->s.comm ? l->s.comm : "?", 0);
			putchar(' ');
			safe_print_string(aulookup_uid(l->s.loginuid, name,
				sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_TERM:	// report_detail == D_DETAILED
			// terminal, host, exe, who, event
			printf("%s %s ",
				l->s.terminal, l->s.hostname);
			safe_print_string(l->s.exe, 0);
			putchar(' ');
			safe_print_string(aulookup_uid(l->s.loginuid, name,
				sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_USER:	// report_detail == D_DETAILED
			// who, terminal, host, exe, event
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %s %s ",
				l->s.terminal ? l->s.terminal : "?",
				l->s.hostname ? l->s.hostname : "?");
			safe_print_string(l->s.exe ? l->s.exe : "?", 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_EXE:	// report_detail == D_DETAILED
			// exe, terminal, host, who, event
			safe_print_string(l->s.exe ? l->s.exe : "?", 0);
			printf(" %s %s ",
				l->s.terminal ? l->s.terminal : "?",
				l->s.hostname ? l->s.hostname : "?");
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_COMM:	// report_detail == D_DETAILED
			// comm, terminal, host, who, event
			safe_print_string(l->s.comm ? l->s.comm : "?", 0);
			printf(" %s %s ",
				l->s.terminal ? l->s.terminal : "?",
				l->s.hostname ? l->s.hostname : "?");
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_ANOMALY:	// report_detail == D_DETAILED
			// type exe term host auid event
			printf("%s ", audit_msg_type_to_name(l->head->type));
			safe_print_string(l->s.exe ? l->s.exe :
					l->s.comm ? l->s.comm: "?", 0);
			printf(" %s %s ",
				l->s.terminal ? l->s.terminal : "?",
				l->s.hostname ? l->s.hostname : "?");
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_RESPONSE:	// report_detail == D_DETAILED
			// type success event
			printf("%s %s %lu\n",
				audit_msg_type_to_name(l->head->type),
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_MAC:
			// auid type success event
			printf("%s %s %s %lu\n",
				aulookup_uid(l->s.loginuid, name, sizeof(name)),
				audit_msg_type_to_name(l->head->type),
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_INTEG:
			// type success event
			printf("%s %s %lu\n",
				audit_msg_type_to_name(l->head->type),
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_VIRT:
			// type success event
			printf("%s %s %lu\n",
				audit_msg_type_to_name(l->head->type),
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_CRYPTO:
			// auid type success event
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %s %s %lu\n",
				audit_msg_type_to_name(l->head->type),
				aulookup_success(l->s.success),
				l->e.serial);
			break;
		case RPT_KEY:	// report_detail == D_DETAILED
			// key, success, exe, who, event
			slist_first(l->s.key);
			printf("%s %s ", l->s.key->cur->str,
				aulookup_success(l->s.success));
			safe_print_string(l->s.exe ? l->s.exe : "?", 0);
			putchar(' ');
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %lu\n", l->e.serial);
			break;
		case RPT_TTY: {
			char *ch, *ptr = strstr(l->head->message, "data=");
			if (!ptr)
				break;
			ptr += 5;
			ch = strrchr(ptr, ' ');
			if (ch)
				*ch = 0;
			// event who term sess data
			printf("%lu ", l->e.serial);
			safe_print_string(aulookup_uid(l->s.loginuid, name,
					sizeof(name)), 0);
			printf(" %s %u ",
				l->s.terminal ? l->s.terminal : "?",
				l->s.session_id);
			safe_print_string(l->s.comm ? l->s.comm: "?", 0);
			putchar(' ');
			print_tty_data(ptr);
			printf("\n");
			}
			break;
		default:
			break;
	}
}
Example #5
0
/*
 *  This function prints 1 rule from the kernel reply
 */
static void print_rule(const struct audit_rule_data *r)
{
	unsigned int i, count = 0, sc = 0;
	size_t boffset = 0;
	int mach = -1, watch = is_watch(r);
	unsigned long long a0 = 0, a1 = 0;

	if (!watch) { /* This is syscall auditing */
		printf("-a %s,%s",
			audit_action_to_name((int)r->action),
				audit_flag_to_name(r->flags));

		// Now find the arch and print it
		for (i = 0; i < r->field_count; i++) {
			int field = r->fields[i] & ~AUDIT_OPERATORS;
			if (field == AUDIT_ARCH) {
				int op = r->fieldflags[i] & AUDIT_OPERATORS;
				mach = print_arch(r->values[i], op);
			}
		}
		// And last do the syscalls
		count = print_syscall(r, &sc);
	}

	// Now iterate over the fields
	for (i = 0; i < r->field_count; i++) {
		const char *name;
		int op = r->fieldflags[i] & AUDIT_OPERATORS;
		int field = r->fields[i] & ~AUDIT_OPERATORS;

		if (field == AUDIT_ARCH)
			continue;	// already printed

		name = audit_field_to_name(field);
		if (name) {
			// Special cases to print the different field types
			// in a meaningful way.
			if (field == AUDIT_MSGTYPE) {
				if (!audit_msg_type_to_name(r->values[i]))
					printf(" -F %s%s%d", name,
						audit_operator_to_symbol(op),
						r->values[i]);
				else
					printf(" -F %s%s%s", name,
						audit_operator_to_symbol(op),
						audit_msg_type_to_name(
						r->values[i]));
			} else if ((field >= AUDIT_SUBJ_USER &&
						field <= AUDIT_OBJ_LEV_HIGH)
						&& field != AUDIT_PPID) {
				printf(" -F %s%s%.*s", name,
						audit_operator_to_symbol(op),
						r->values[i], &r->buf[boffset]);
				boffset += r->values[i];
			} else if (field == AUDIT_WATCH) {
				if (watch)
					printf("-w %.*s", r->values[i],
						&r->buf[boffset]);
				else
					printf(" -F path=%.*s",	r->values[i],
						&r->buf[boffset]);
				boffset += r->values[i];
			} else if (field == AUDIT_DIR) {
				if (watch)
					printf("-w %.*s/", r->values[i],
						&r->buf[boffset]);
				else
					printf(" -F dir=%.*s", r->values[i],
						&r->buf[boffset]);

				boffset += r->values[i];
			} else if (field == AUDIT_FILTERKEY) {
				char *rkey, *ptr, *saved;
				if (asprintf(&rkey, "%.*s", r->values[i],
					      &r->buf[boffset]) < 0)
					rkey = NULL;
				boffset += r->values[i];
				ptr = strtok_r(rkey, key_sep, &saved);
				while (ptr) {
					if (watch)
						printf(" -k %s", ptr);
					else
						printf(" -F key=%s", ptr);
					ptr = strtok_r(NULL, key_sep, &saved);
				}
				free(rkey);
			} else if (field == AUDIT_PERM) {
				char perms[5];
				int val=r->values[i];
				perms[0] = 0;
				if (val & AUDIT_PERM_READ)
					strcat(perms, "r");
				if (val & AUDIT_PERM_WRITE)
					strcat(perms, "w");
				if (val & AUDIT_PERM_EXEC)
					strcat(perms, "x");
				if (val & AUDIT_PERM_ATTR)
					strcat(perms, "a");
				if (watch)
					printf(" -p %s", perms);
				else
					printf(" -F perm=%s", perms);
			} else if (field == AUDIT_INODE) {
				// This is unsigned
				printf(" -F %s%s%u", name, 
						audit_operator_to_symbol(op),
						r->values[i]);
			} else if (field == AUDIT_FIELD_COMPARE) {
				print_field_cmp(r->values[i], op);
			} else if (field >= AUDIT_ARG0 && field <= AUDIT_ARG3){
				if (field == AUDIT_ARG0)
					a0 = r->values[i];
				else if (field == AUDIT_ARG1)
					a1 = r->values[i];

				// Show these as hex
				if (count > 1 || interpret == 0)
					printf(" -F %s%s0x%X", name, 
						audit_operator_to_symbol(op),
						r->values[i]);
				else {	// Use ignore to mean interpret
					const char *out;
					idata id;
					char val[32];
					int type;

					id.syscall = sc;
					id.machine = mach;
					id.a0 = a0;
					id.a1 = a1;
					id.name = name;
					snprintf(val, 32, "%x", r->values[i]);
					id.val = val;
					type = auparse_interp_adjust_type(
						AUDIT_SYSCALL, name, val);
					out = auparse_do_interpretation(type,
								 &id);
					printf(" -F %s%s%s", name,
						audit_operator_to_symbol(op),
								out);
					free((void *)out);
				}
			} else if (field == AUDIT_EXIT) {
				int e = abs((int)r->values[i]);
				const char *err = audit_errno_to_name(e);

				if (((int)r->values[i] < 0) && err)
					printf(" -F %s%s-%s", name,
						audit_operator_to_symbol(op),
						err);
				else
					printf(" -F %s%s%d", name,
						audit_operator_to_symbol(op),
						(int)r->values[i]);
			} else {
				// The default is signed decimal
				printf(" -F %s%s%d", name, 
						audit_operator_to_symbol(op),
						r->values[i]);
			}
		} else {
			 // The field name is unknown 
			printf(" f%d%s%d", r->fields[i],
						audit_operator_to_symbol(op),
						r->values[i]);
		}
	}
	printf("\n");
}
Example #6
0
/*
 * This function will cycle through a single record and lookup each field's
 * value that it finds. 
 */
static void output_interpreted_node(const lnode *n)
{
	char *ptr, *str = n->message, *node = NULL;
	int found;

	// Reset these because each record could be different
	machine = -1;
	cur_syscall = -1;

	/* Check and see if we start with a node */
	if (str[0] == 'n') {
		ptr=strchr(str, ' ');
		if (ptr) {
			*ptr = 0;
			node = str;
			str = ptr+1;
		}
	}

	// First locate time stamp.
	ptr = strchr(str, '(');
	if (ptr == NULL) {
		fprintf(stderr, "can't find time stamp\n");
		return;
	} else {
		time_t t;
		int milli,num = n->type;
		unsigned long serial;
		struct tm *btm;
		char tmp[32];
		const char *bptr;

		*ptr++ = 0;
		if (num == -1) {
			// see if we are older and wiser now.
			bptr = strchr(str, '[');
			if (bptr && bptr < ptr) {
				char *eptr;
				bptr++;
				eptr = strchr(bptr, ']');
				if (eptr) {
					*eptr = 0;
					errno = 0;
					num = strtoul(bptr, NULL, 10);
					*eptr = ']';
					if (errno) 
						num = -1;
				}
			}
		}

		// print everything up to it.
		if (num >= 0) {
			bptr = audit_msg_type_to_name(num);
			if (bptr) {
				if (node)
					printf("%s ", node);
				printf("type=%s msg=audit(", bptr);
				goto no_print;
			}
		} 
		if (node)
			printf("%s ", node);
		printf("%s(", str);
no_print:

		// output formatted time.
		str = strchr(ptr, '.');
		if (str == NULL)
			return;
		*str++ = 0;
		errno = 0;
		t = strtoul(ptr, NULL, 10);
		if (errno)
			return;
		ptr = strchr(str, ':');
		if (ptr == NULL)
			return;
		*ptr++ = 0;
		milli = strtoul(str, NULL, 10);
		if (errno)
			return;
		str = strchr(ptr, ')');
		if(str == NULL)
			return;
		*str++ = 0;
		serial = strtoul(ptr, NULL, 10);
		if (errno)
			return;
		btm = localtime(&t);
		strftime(tmp, sizeof(tmp), "%x %T", btm);
		printf("%s", tmp);
		printf(".%03d:%lu) ", milli, serial);
	}

	if (n->type == AUDIT_SYSCALL) { 
		a0 = n->a0;
		a1 = n->a1;
	}

	// for each item.
	found = 0;
	while (str && *str && (ptr = strchr(str, '='))) {
		char *name, *val;
		int comma = 0;
		found = 1;

		// look back to last space - this is name
		name = ptr;
		while (*name != ' ' && name > str)
			--name;
		*ptr++ = 0;

		// print everything up to the '='
		printf("%s=", str);

		// Some user messages have msg='uid=500   in this case
		// skip the msg= piece since the real stuff is the uid=
		if (strcmp(name, "msg") == 0) {
			str = ptr;
			continue;
		}

		// In the above case, after msg= we need to trim the ' from uid
		if (*name == '\'')
			name++;

		// get string after = to the next space or end - this is value
		if (*ptr == '\'' || *ptr == '"') {
			str = strchr(ptr+1, *ptr);
			if (str) {
				str++;
				if (*str)
					*str++ = 0;
			}
		} else {
			str = strchr(ptr, ',');
			val = strchr(ptr, ' ');
			if (str && val && (str < val)) {
				*str++ = 0;
				comma = 1;
			} else if (str && (val == NULL)) {
				*str++ = 0;
				comma = 1;
			} else if (val) {
				str = val;
				*str++ = 0;
			}
		}
		// val points to begin & str 1 past end
		val = ptr;
		
		// print interpreted string
		interpret(name, val, comma, n->type);
	}
	// If nothing found, just print out as is
	if (!found && ptr == NULL && str)
		printf("%s", str);
	printf("\n");
}
Example #7
0
/* Returns 0 on stop, and 1 on HUP */
static int event_loop(void)
{
	char *name = NULL, tmp_name[255];

	/* Get the host name representation */
	switch (daemon_config.node_name_format)
	{
		case N_NONE:
			break;
		case N_HOSTNAME:
			if (gethostname(tmp_name, sizeof(tmp_name))) {
				syslog(LOG_ERR, "Unable to get machine name");
				name = strdup("?");
			} else
				name = strdup(tmp_name);
			break;
		case N_USER:
			if (daemon_config.name)
				name = strdup(daemon_config.name);
			else {
				syslog(LOG_ERR, "User defined name missing");
				name = strdup("?");
			}
			break;
		case N_FQD:
			if (gethostname(tmp_name, sizeof(tmp_name))) {
				syslog(LOG_ERR, "Unable to get machine name");
				name = strdup("?");
			} else {
				int rc;
				struct addrinfo *ai;
				struct addrinfo hints;

				memset(&hints, 0, sizeof(hints));
				hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
				hints.ai_socktype = SOCK_STREAM;

				rc = getaddrinfo(tmp_name, NULL, &hints, &ai);
				if (rc != 0) {
					syslog(LOG_ERR,
					"Cannot resolve hostname %s (%s)",
					tmp_name, gai_strerror(rc));
					name = strdup("?");
					break;
				}
				name = strdup(ai->ai_canonname);
				freeaddrinfo(ai);
			}
			break;
		case N_NUMERIC:
			if (gethostname(tmp_name, sizeof(tmp_name))) {
				syslog(LOG_ERR, "Unable to get machine name");
				name = strdup("?");
			} else {
				int rc;
				struct addrinfo *ai;
				struct addrinfo hints;

				memset(&hints, 0, sizeof(hints));
				hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
				hints.ai_socktype = SOCK_STREAM;

				rc = getaddrinfo(tmp_name, NULL, &hints, &ai);
				if (rc != 0) {
					syslog(LOG_ERR,
					"Cannot resolve hostname %s (%s)",
					tmp_name, gai_strerror(rc));
					name = strdup("?");
					break;
				}
				inet_ntop(ai->ai_family,
						ai->ai_family == AF_INET ?
		(void *) &((struct sockaddr_in *)ai->ai_addr)->sin_addr :
		(void *) &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr,
						tmp_name, INET6_ADDRSTRLEN);
				freeaddrinfo(ai);
				name = strdup(tmp_name);
			}
			break;
	}

	/* Figure out the format for the af_unix socket */
	while (stop == 0) {
		event_t *e;
		const char *type;
		char *v, *ptr, unknown[32];
		unsigned int len;
		lnode *conf;

		/* This is where we block until we have an event */
		e = dequeue();
		if (e == NULL) {
			if (hup) {
				free(name);
				return 1;
			}
			continue;
		}

		/* Get the event formatted */
		type = audit_msg_type_to_name(e->hdr.type);
		if (type == NULL) {
			snprintf(unknown, sizeof(unknown),
				"UNKNOWN[%d]", e->hdr.type);
			type = unknown;
		}

		if (daemon_config.node_name_format != N_NONE) {
			len = asprintf(&v, "node=%s type=%s msg=%.*s\n", 
				name, type, e->hdr.size, e->data);
		} else
			len = asprintf(&v, "type=%s msg=%.*s\n", 
				type, e->hdr.size, e->data);
		if (len <= 0) {
			free(e); /* Either corrupted event or no memory */
			continue;
		}

		/* Strip newlines from event record */
		ptr = v;
		while ((ptr = strchr(ptr, 0x0A)) != NULL) {
			if (ptr != &v[len-1])
				*ptr = ' ';
			else
				break; /* Done - exit loop */
		}

		/* Distribute event to the plugins */
		plist_first(&plugin_conf);
		conf = plist_get_cur(&plugin_conf);
		do {
			if (conf == NULL || conf->p == NULL)
				continue;
			if (conf->p->active == A_NO)
				continue;

			/* Now send the event to the right child */
			if (conf->p->type == S_SYSLOG) 
				send_syslog(v);
			else if (conf->p->type == S_AF_UNIX) {
				if (conf->p->format == F_STRING)
					send_af_unix_string(v, len);
				else
					send_af_unix_binary(e);
			} else if (conf->p->type == S_ALWAYS) {
				int rc;
				rc = write_to_plugin(e, v, len, conf);
				if (rc < 0 && errno == EPIPE) {
					/* Child disappeared ? */
					syslog(LOG_ERR,
					"plugin %s terminated unexpectedly", 
								conf->p->path);
					conf->p->pid = 0;
					conf->p->restart_cnt++;
					if (conf->p->restart_cnt >
						daemon_config.max_restarts) {
						syslog(LOG_ERR,
					"plugin %s has exceeded max_restarts",
								conf->p->path);
					}
					close(conf->p->plug_pipe[1]);
					conf->p->plug_pipe[1] = -1;
					conf->p->active = A_NO;
					if (start_one_plugin(conf)) {
						rc = write_to_plugin(e, v, len,
								     conf);
						syslog(LOG_NOTICE,
						"plugin %s was restarted",
							conf->p->path);
						conf->p->active = A_YES;
					} 
				}
			}
		} while ((conf = plist_next(&plugin_conf)));

		/* Done with the memory...release it */
		free(v);
		free(e);
		if (hup)
			break;
	}
	free(name);
	if (stop)
		return 0;
	else
		return 1;
}
Example #8
0
/* This function shows how to dump a whole record's text */
static void dump_whole_record(auparse_state_t *au)
{
	printf("%s: %s\n", audit_msg_type_to_name(auparse_get_type(au)),
		auparse_get_record_text(au));
	printf("\n");
}
Example #9
0
/*
 * This function interprets the reply and prints it to stdout. It returns
 * 0 if no more should be read and 1 to indicate that more messages of this
 * type may need to be read. 
 */
static int audit_print_reply(struct audit_reply *rep)
{
	unsigned int i;
	int first;
	int sparse;
	int machine = audit_detect_machine();
	size_t boffset;
	int show_syscall;

	_audit_elf = 0; 
	switch (rep->type) {
		case NLMSG_NOOP:
			return 1;
		case NLMSG_DONE:
			if (printed == 0)
				printf("No rules\n");
			return 0;
		case NLMSG_ERROR: 
		        printf("NLMSG_ERROR %d (%s)\n",
				-rep->error->error, 
				strerror(-rep->error->error));
			printed = 1;
			return 0;
		case AUDIT_GET:
			printf("AUDIT_STATUS: enabled=%d flag=%d pid=%d"
			" rate_limit=%d backlog_limit=%d lost=%d backlog=%u\n",
			rep->status->enabled, rep->status->failure,
			rep->status->pid, rep->status->rate_limit,
			rep->status->backlog_limit, rep->status->lost,
			rep->status->backlog);
			printed = 1;
			return 0;
		case AUDIT_LIST_RULES:
			list_requested = 0;
			boffset = 0;
			show_syscall = 1;
			if (key_match(rep) == 0)
				return 1;
			printed = 1;
			printf("%s: %s,%s", audit_msg_type_to_name(rep->type),
				audit_flag_to_name((int)rep->ruledata->flags),
				audit_action_to_name(rep->ruledata->action));

			for (i = 0; i < rep->ruledata->field_count; i++) {
				const char *name;
				int op = rep->ruledata->fieldflags[i] &
						AUDIT_OPERATORS;
				int field = rep->ruledata->fields[i] &
						~AUDIT_OPERATORS;
                
				name = audit_field_to_name(field);
				if (name) {
					if (strcmp(name, "arch") == 0) { 
						_audit_elf =
						    rep->ruledata->values[i];
						printf(" %s%s%u", name, 
						  audit_operator_to_symbol(op),
					    (unsigned)rep->ruledata->values[i]);
					}
					else if (strcmp(name, "msgtype") == 0) {
						if (!audit_msg_type_to_name(
						      rep->ruledata->values[i]))
							printf(" %s%s%d", name,
								audit_operator_to_symbol(op),
								rep->ruledata->values[i]);
						else {
							printf(" %s%s%s", name,
								audit_operator_to_symbol(op),
								audit_msg_type_to_name(rep->ruledata->values[i]));
						}
					} else if ((field >= AUDIT_SUBJ_USER &&
						  field <= AUDIT_OBJ_LEV_HIGH)
						&& field != AUDIT_PPID &&
					       rep->type == AUDIT_LIST_RULES) {
						printf(" %s%s%.*s", name,
						  audit_operator_to_symbol(op),
						  rep->ruledata->values[i],
						  &rep->ruledata->buf[boffset]);
						boffset +=
						    rep->ruledata->values[i];
					} else if (field == AUDIT_WATCH) {
						printf(" watch=%.*s", 
						  rep->ruledata->values[i],
						  &rep->ruledata->buf[boffset]);
						boffset +=
						    rep->ruledata->values[i];
					} else if (field == AUDIT_DIR) {
						printf(" dir=%.*s", 
						  rep->ruledata->values[i],
						  &rep->ruledata->buf[boffset]);
						boffset +=
						    rep->ruledata->values[i];
					} else if (field == AUDIT_FILTERKEY) {
						char *rkey, *ptr;
						asprintf(&rkey, "%.*s",
						rep->ruledata->values[i],
						&rep->ruledata->buf[boffset]);
						boffset +=
						    rep->ruledata->values[i];
						ptr = strtok(rkey, key_sep);
						while (ptr) {
							printf(" key=%s", ptr);
							ptr = strtok(NULL,
								key_sep);
						}
						free(rkey);
					} else if (field == AUDIT_PERM) {
						char perms[5];
						int val=rep->ruledata->values[i];
						perms[0] = 0;
						if (val & AUDIT_PERM_READ)
							strcat(perms, "r");
						if (val & AUDIT_PERM_WRITE)
							strcat(perms, "w");
						if (val & AUDIT_PERM_EXEC)
							strcat(perms, "x");
						if (val & AUDIT_PERM_ATTR)
							strcat(perms, "a");
						printf(" perm=%s", perms);
						show_syscall = 0;
					} else if (field == AUDIT_INODE) {
						// Unsigned items
						printf(" %s%s%u", name, 
							audit_operator_to_symbol(op),
							rep->ruledata->values[i]);
					} else if (field == AUDIT_FIELD_COMPARE) {
						switch (rep->ruledata->values[i])
						{
						case AUDIT_COMPARE_UID_TO_OBJ_UID:
							printf(" uid%sobj_uid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_GID_TO_OBJ_GID:
							printf(" gid%sobj_gid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EUID_TO_OBJ_UID:
							printf(" euid%sobj_uid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EGID_TO_OBJ_GID:
							printf(" egid%sobj_gid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_AUID_TO_OBJ_UID:
							printf(" auid%sobj_uid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_SUID_TO_OBJ_UID:
							printf(" suid%sobj_uid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_SGID_TO_OBJ_GID:
							printf(" sgid%sobj_gid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
							printf(" fsuid%sobj_uid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
							printf(" fsgid%sobj_gid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_UID_TO_AUID:
							printf(" uid%sauid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_UID_TO_EUID:
							printf(" uid%seuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_UID_TO_FSUID:
							printf(" uid%sfsuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_UID_TO_SUID:
							printf(" uid%ssuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_AUID_TO_FSUID:
							printf(" auid%sfsuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_AUID_TO_SUID:
							printf(" auid%ssuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_AUID_TO_EUID:
							printf(" auid%seuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EUID_TO_SUID:
							printf(" euid%ssuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EUID_TO_FSUID:
							printf(" euid%sfsuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_SUID_TO_FSUID:
							printf(" suid%sfsuid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_GID_TO_EGID:
							printf(" gid%segid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_GID_TO_FSGID:
							printf(" gid%sfsgid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_GID_TO_SGID:
							printf(" gid%ssgid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EGID_TO_FSGID:
							printf(" egid%sfsgid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_EGID_TO_SGID:
							printf(" egid%ssgid",audit_operator_to_symbol(op));
							break;
						case AUDIT_COMPARE_SGID_TO_FSGID:
							printf(" sgid%sfsgid",audit_operator_to_symbol(op));
							break;
						}
					} else {
						// Signed items
						printf(" %s%s%d", name, 
							audit_operator_to_symbol(op),
							rep->ruledata->values[i]);
					}
				} else { 
					printf(" f%d%s%d", rep->ruledata->fields[i],
						audit_operator_to_symbol(op),
						rep->ruledata->values[i]);
				}
				/* Avoid printing value if the field type is 
				 * known to return a string. */
				if (rep->ruledata->values[i] && 
						(field < AUDIT_SUBJ_USER ||
						 field > AUDIT_SUBJ_CLR) &&
						field != AUDIT_WATCH &&
						field != AUDIT_FILTERKEY &&
						field != AUDIT_PERM &&
						field != AUDIT_FIELD_COMPARE)
					printf(" (0x%x)", rep->ruledata->values[i]);
			}
			if (show_syscall &&
				((rep->ruledata->flags & AUDIT_FILTER_MASK) != 
						AUDIT_FILTER_USER) &&
				((rep->ruledata->flags & AUDIT_FILTER_MASK) !=
						AUDIT_FILTER_TASK) &&
				((rep->ruledata->flags & AUDIT_FILTER_MASK) !=
						AUDIT_FILTER_EXCLUDE)) {
				printf(" syscall=");
				for (sparse = 0, i = 0; 
					i < (AUDIT_BITMASK_SIZE-1); i++) {
					if (rep->ruledata->mask[i] != (uint32_t)~0)
						sparse = 1;
				}
				if (!sparse) {
					printf("all");
				} else for (first = 1, i = 0;
					i < AUDIT_BITMASK_SIZE * 32; i++) {
					int word = AUDIT_WORD(i);
					int bit  = AUDIT_BIT(i);
					if (rep->ruledata->mask[word] & bit) {
						const char *ptr;
						if (_audit_elf)
							machine = 
							audit_elf_to_machine(
								_audit_elf);
						if (machine < 0)
							ptr = NULL;
						else
							ptr = 
							audit_syscall_to_name(i, 
							machine);
						if (ptr)
							printf("%s%s", 
							first ? "" : ",", ptr);
						else
							printf("%s%d", 
							first ? "" : ",", i);
						first = 0;
					}
				}
			}
			printf("\n");
			return 1; /* get more messages until NLMSG_DONE */
		default:
			printf("Unknown: type=%d, len=%d\n", rep->type, 
				rep->nlh->nlmsg_len);
			printed = 1;
			return 0;
	}
}
Example #10
0
/*
 * This function examines the commandline parameters and sets various
 * search options. It returns a 0 on success and < 0 on failure
 */
int check_params(int count, char *vars[])
{
	int c = 1;
	int retval = 0;
	const char *optarg;

	if (count < 2) {
		usage();
		return -1;
	}
	while (c < count && retval == 0) {
		// Go ahead and point to the next argument
		if (c+1 < count) {
			if (vars[c+1][0] != '-')
				optarg = vars[c+1];
			else
				optarg = NULL;
		} else
			optarg = NULL;

		switch (audit_lookup_option(vars[c])) {
		case S_EVENT:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
			if (isdigit(optarg[0])) {
				errno = 0;
				event_id = strtoul(optarg, NULL, 10);
				if (errno) {
					fprintf(stderr,
					"Illegal value for audit event ID");
					retval = -1;
				}
				c++;
			} else {
				fprintf(stderr, 
			"Audit event id must be a numeric value, was %s\n",
					optarg);
				retval = -1;
			}
			break;
		case S_COMM:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			} else {
				event_comm = strdup(optarg);
        	                if (event_comm == NULL)
                	                retval = -1;
				c++;
			}
			break;
		case S_FILENAME:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				event_filename = strdup(optarg);
        	                if (event_filename == NULL)
                	                retval = -1;
				c++;
			}
			break;
		case S_KEY:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				event_key = strdup(optarg);
        	                if (event_key == NULL)
                	                retval = -1;
				c++;
			}
			break;
		case S_ALL_GID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_gid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric group ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct group *gr ;

				gr = getgrnam(optarg) ;
				if (gr == NULL) {
                        		fprintf(stderr, 
				"Group ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_gid = gr->gr_gid;
                	}
			event_egid = event_gid;
			event_ga = 1;
			c++;
			break;
		case S_EFF_GID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_egid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric group ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct group *gr ;

				gr = getgrnam(optarg) ;
				if (gr == NULL) {
                        		fprintf(stderr, 
			"Effective group ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_egid = gr->gr_gid;
                	}
			c++;
			break;
		case S_GID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_gid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric group ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct group *gr ;

				gr = getgrnam(optarg) ;
				if (gr == NULL) {
                        		fprintf(stderr, 
				"Group ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_gid = gr->gr_gid;
                	}
			c++;
			break;
		case S_HELP:
			usage();
			exit(0);
			break;
		case S_HOSTNAME:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				event_hostname = strdup(optarg);
				if (event_hostname == NULL)
					retval = -1;
				c++;
			}
			break;
		case S_INTERP:
			if (report_format == RPT_DEFAULT)
				report_format = RPT_INTERP;
			else {
				fprintf(stderr, 
					"Conflicting output format %s\n",
					vars[c]);
        	                retval = -1;
			}
			if (optarg) {
				fprintf(stderr, 
					"Argument is NOT required for %s\n",
					vars[c]);
        	                retval = -1;
			}
			break;
		case S_INFILE:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				user_file = strdup(optarg);
				if (user_file == NULL)
					retval = -1;
				c++;
			}
			break;
		case S_MESSAGE_TYPE:
	                if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
        	                retval = -1;
	                } else {
				if (strcasecmp(optarg, "ALL") != 0) {
					retval = parse_msg(optarg);
				}
				c++;
			}
			if (retval < 0) {
				int i;
                        	fprintf(stderr, 
					"Valid message types are: ALL ");
				for (i=AUDIT_USER;i<=AUDIT_LAST_VIRT_MSG;i++){
					const char *name;
					if (i == AUDIT_WATCH_INS) // Skip a few
						i = AUDIT_FIRST_USER_MSG;
					name = audit_msg_type_to_name(i);
					if (name)
		                        	fprintf(stderr, "%s ", name);
				}
                        	fprintf(stderr, "\n");
			}
			break;
		case S_OBJECT:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			} else {
				event_object = strdup(optarg);
        	                if (event_object == NULL)
                	                retval = -1;
				c++;
			}
			break;
		case S_PPID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
			if (isdigit(optarg[0])) {
				errno = 0;
				event_ppid = strtol(optarg,NULL,10);
				if (errno)
					retval = -1;
				c++;
			} else {
				fprintf(stderr, 
			"Parent process id must be a numeric value, was %s\n",
					optarg);
				retval = -1;
			}
			break;
		case S_PID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
			if (isdigit(optarg[0])) {
				errno = 0;
				event_pid = strtol(optarg,NULL,10);
				if (errno)
					retval = -1;
				c++;
			} else {
				fprintf(stderr, 
				"Process id must be a numeric value, was %s\n",
					optarg);
				retval = -1;
			}
			break;
		case S_RAW:
			if (report_format == RPT_DEFAULT)
				report_format = RPT_RAW;
			else {
				fprintf(stderr, 
					"Conflicting output format --raw\n");
        	                retval = -1;
			}
			if (optarg) {
				fprintf(stderr, 
					"Argument is NOT required for --raw\n");
        	                retval = -1;
			}
			break;
		case S_NODE:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				snode sn;
				c++;

				if (!event_node_list) {
					event_node_list = malloc(sizeof (slist));
					if (!event_node_list) {
						retval = -1;
						break;
					}
					slist_create(event_node_list);
				}
				
				sn.str = strdup(optarg);
				sn.key = NULL;
				sn.hits=0;
				slist_append(event_node_list, &sn);
			}
			break;
		case S_SYSCALL:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
			if (isdigit(optarg[0])) {
				errno = 0;
				event_syscall = (int)strtoul(optarg, NULL, 10);
				if (errno) {
                        		fprintf(stderr, 
			"Syscall numeric conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
			} else {
                                int machine;
                                machine = audit_detect_machine();
                                if (machine < 0) {
                                        fprintf(stderr,
                                            "Error detecting machine type");
                                        retval = -1;
					break;
                                }
				event_syscall = audit_name_to_syscall(optarg, 
					machine);
				if (event_syscall == -1) {
					fprintf(stderr, 
						"Syscall %s not found\n",
						optarg);
                                        retval = -1;
				}
                        }
			c++;
			break;
		case S_CONTEXT:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			} else {
				event_subject = strdup(optarg);
        	                if (event_subject == NULL)
                	                retval = -1;
				event_object = strdup(optarg);
        	                if (event_object == NULL)
                	                retval = -1;
				event_se = 1;
				c++;
			}
			break;
		case S_SUBJECT:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			} else {
				event_subject = strdup(optarg);
        	                if (event_subject == NULL)
                	                retval = -1;
				c++;
			}
			break;
		case S_OSUCCESS:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if ( (strstr(optarg, "yes")!=NULL) || 
					(strstr(optarg, "no")!=NULL) ) {
                        	if (strcmp(optarg, "yes") == 0)
					event_success = S_SUCCESS;
				else
					event_success = S_FAILED;
                	} else {
                        	fprintf(stderr, 
					"Success must be 'yes' or 'no'.\n");
                        	retval = -1;
                	}
			c++;
			break;
		case S_SESSION:
			if (!optarg) {
				if ((c+1 < count) && vars[c+1])
					optarg = vars[c+1];
				else {
					fprintf(stderr,
						"Argument is required for %s\n",
						vars[c]);
					retval = -1;
					break;
				}
			}
			{ 
			size_t len = strlen(optarg);
			if (isdigit(optarg[0])) {
				errno = 0;
				event_session_id = strtol(optarg,NULL,10);
				if (errno)
					retval = -1;
				c++;
                        } else if (len >= 2 && *(optarg)=='-' &&
                                                (isdigit(optarg[1]))) {
				errno = 0;
                                event_session_id = strtol(optarg, NULL, 0);
				if (errno) {
					retval = -1;
					fprintf(stderr, "Error converting %s\n",
						optarg);
				}
				c++;
			} else {
				fprintf(stderr, 
				"Session id must be a numeric value, was %s\n",
					optarg);
				retval = -1;
			}
			}
			break;
		case S_EXIT:
			if (!optarg) {
				if ((c+1 < count) && vars[c+1])
					optarg = vars[c+1];
				else {
					fprintf(stderr,
						"Argument is required for %s\n",
						vars[c]);
					retval = -1;
					break;
				}
			} 
			{
			size_t len = strlen(optarg);
                        if (isdigit(optarg[0])) {
				errno = 0;
                                event_exit = strtol(optarg, NULL, 0);
				if (errno) {
					retval = -1;
					fprintf(stderr, "Error converting %s\n",
						optarg);
				}
                        } else if (len >= 2 && *(optarg)=='-' &&
                                                (isdigit(optarg[1]))) {
				errno = 0;
                                event_exit = strtol(optarg, NULL, 0);
				if (errno) {
					retval = -1;
					fprintf(stderr, "Error converting %s\n",
						optarg);
				}
                        } else {
                                event_exit = audit_name_to_errno(optarg);
                                if (event_exit == 0) {
					retval = -1;
					fprintf(stderr, 
						"Unknown errno, was %s\n",
						optarg);
				}
                        }
			c++;
			if (retval != -1)
				event_exit_is_set = 1;
			}
			break;
		case S_TIME_END:
			if (optarg) {
				if ( (c+2 < count) && vars[c+2] && 
					(vars[c+2][0] != '-') ) {
				/* Have both date and time - check order*/
					if (strchr(optarg, ':')) {
						if (ausearch_time_end(vars[c+2],
								 optarg) != 0) 
							retval = -1;
					} else {
						if (ausearch_time_end(optarg, 
								vars[c+2]) != 0)
							retval = -1;
					}
					c++;			
				} else {
					// Check against recognized words
					int t = lookup_time(optarg);
					if (t >= 0) {
						if (ausearch_time_end(optarg,
								NULL) != 0)
							retval = -1;
					} else if ( (strchr(optarg, ':')) == NULL) {
						/* Only have date */
						if (ausearch_time_end(optarg,
								NULL) != 0)
							retval = -1;
					} else {
						/* Only have time */
						if (ausearch_time_end(NULL,
								optarg) != 0)
							retval = -1;
					}
				}
				c++;			
				break;
			} 
			fprintf(stderr, 
				"%s requires either date and/or time\n",
				vars[c]);
			retval = -1;
			break;
		case S_TIME_START:
			if (optarg) {
				if ( (c+2 < count) && vars[c+2] && 
					(vars[c+2][0] != '-') ) {
				/* Have both date and time - check order */
					if (strchr(optarg, ':')) {
						if (ausearch_time_start(
							vars[c+2], optarg) != 0)
							retval = -1;
					} else {
						if (ausearch_time_start(optarg, 
								vars[c+2]) != 0)
							retval = -1;
					}
					c++;
				} else {
					// Check against recognized words
					int t = lookup_time(optarg);
					if (t >= 0) {
						if (ausearch_time_start(optarg,
							"00:00:00") != 0)
							retval = -1;
					}
					else if ( strchr(optarg, ':') == NULL) {
						/* Only have date */
						if (ausearch_time_start(optarg,
							"00:00:00") != 0)
							retval = -1;
					} else {
						/* Only have time */
						if (ausearch_time_start(NULL,
								optarg) != 0)
							retval = -1;
					}
				}
				c++;
				break;
			}
			fprintf(stderr, 
				"%s requires either date and/or time\n",
				vars[c]);
			retval = -1;
			break;
		case S_TERMINAL:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
                	} else { 
				event_terminal = strdup(optarg);
				if (event_terminal == NULL)
        	                        retval = -1;
				c++;
			}
			break;
		case S_UID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_uid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric user ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct passwd *pw;

				pw = getpwnam(optarg);
				if (pw == NULL) {
                        		fprintf(stderr, 
			"Effective user ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_uid = pw->pw_uid;
                	}
			c++;
			break;
		case S_EFF_UID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_euid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric user ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct passwd *pw ;

				pw = getpwnam(optarg) ;
				if (pw == NULL) {
                        		fprintf(stderr, 
				"User ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_euid = pw->pw_uid;
                	}
			c++;
			break;
		case S_ALL_UID:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
				break;
			}
                	if (isdigit(optarg[0])) {
				errno = 0;
                        	event_uid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric user ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                	retval = -1;
				}
                	} else {
				struct passwd *pw ;

				pw = getpwnam(optarg) ;
				if (pw == NULL) {
                        		fprintf(stderr, 
				"User ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_uid = pw->pw_uid;
                	}
			event_ua = 1;
			event_euid = event_uid;
			event_loginuid = event_uid;
			c++;
			break;
		case S_LOGINID:
			if (!optarg) {
				if ((c+1 < count) && vars[c+1])
					optarg = vars[c+1];
				else {
					fprintf(stderr,
						"Argument is required for %s\n",
						vars[c]);
					retval = -1;
					break;
				}
			}
			{
			size_t len = strlen(optarg);
                        if (isdigit(optarg[0])) {
				errno = 0;
                        	event_loginuid = strtoul(optarg,NULL,10);
				if (errno) {
                        		fprintf(stderr, 
			"Numeric user ID conversion error (%s) for %s\n",
						strerror(errno), optarg);
                                        retval = -1;
				}
                        } else if (len >= 2 && *(optarg)=='-' &&
                                                (isdigit(optarg[1]))) {
				errno = 0;
                                event_loginuid = strtol(optarg, NULL, 0);
				if (errno) {
					retval = -1;
					fprintf(stderr, "Error converting %s\n",
						optarg);
				}
                        } else {
				struct passwd *pw ;

				pw = getpwnam(optarg) ;
				if (pw == NULL) {
                        		fprintf(stderr, 
			"Login user ID is non-numeric and unknown (%s)\n",
						optarg);
					retval = -1;
					break;
				}
				event_loginuid = pw->pw_uid;
                        }
			}
			c++;
			break;
		case S_UUID:
			if (!optarg) {
				fprintf(stderr,
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				event_uuid = strdup(optarg);
				if (event_uuid == NULL) {
					retval = -1;
				}
				c++;
			}
			break;
		case S_VMNAME:
			if (!optarg) {
				fprintf(stderr,
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
			} else {
				event_vmname= strdup(optarg);
				if (event_vmname == NULL) {
					retval = -1;
				}
				c++;
			}
			break;
		case S_VERSION:
	                printf("ausearch version %s\n", VERSION);
			exit(0);
			break;
		case S_EXACT_MATCH:
			event_exact_match=1;
			break;
		case S_IN_LOGS:
			force_logs = 1;
			break;
		case S_JUST_ONE:
			just_one = 1;
			break;
		case S_EXECUTABLE:
			if (!optarg) {
				fprintf(stderr, 
					"Argument is required for %s\n",
					vars[c]);
				retval = -1;
	               	} else { 
				event_exe = strdup(optarg);
				if (event_exe == NULL)
       	                	        retval = -1;
				c++;
			}
			break;
		case S_LINEBUFFERED:
			line_buffered = 1;
			break;
		default:
			fprintf(stderr, "%s is an unsupported option\n", 
				vars[c]);
			retval = -1;
			break;
		}
		c++;
	}

	return retval;
}
/*
 * This function will cycle through a single record and lookup each field's
 * value that it finds. 
 */
static void output_interpreted_record(const lnode *n, const event *e)
{
	char *ptr, *str = n->message;
	int found, comma = 0;
	int num = n->type;
	struct tm *btm;
	char tmp[32];

	// Reset these because each record could be different
	machine = -1;
	cur_syscall = -1;

	/* Check and see if we start with a node
 	 * If we do, and there is a space in the line
 	 * move the pointer to the first character past
 	 * the space
  	 */
	if (e->node) {
		if ((ptr=strchr(str, ' ')) != NULL) {
			str = ptr+1;
		}
	}

	// First locate time stamp.
	ptr = strchr(str, '(');
	if (ptr == NULL) {
		fprintf(stderr, "can't find time stamp\n");
		return;
	}

	*ptr++ = 0;	/* move to the start of the timestamp */

	// print everything up to it.
	if (num >= 0) {
		const char	* bptr;
		bptr = audit_msg_type_to_name(num);
		if (bptr) {
			if (e->node)
				printf("node=%s ", e->node);
			printf("type=%s msg=audit(", bptr);
			goto no_print;
		}
	} 
	if (e->node)
		printf("node=%s ", e->node);
	printf("%s(", str);
no_print:

	str = strchr(ptr, ')');
	if(str == NULL)
		return;
	*str++ = 0;
	btm = localtime(&e->sec);
	if (btm)
		strftime(tmp, sizeof(tmp), "%x %T", btm);
	else
		strcpy(tmp, "?");
	printf("%s", tmp);
	printf(".%03u:%lu) ", e->milli, e->serial);

	if (n->type == AUDIT_SYSCALL) { 
		a0 = n->a0;
		a1 = n->a1;
	}

	// for each item.
	ausearch_load_interpretations(n);
	found = 0;
	while (str && *str && (ptr = strchr(str, '='))) {
		char *name, *val;
		comma = 0;
		found = 1;

		// look back to last space - this is name
		name = ptr;
		while (*name != ' ' && name > str)
			--name;
		*ptr++ = 0;

		// print everything up to the '='
		printf("%s=", str);

		// Some user messages have msg='uid=500   in this case
		// skip the msg= piece since the real stuff is the uid=
		if (strcmp(name, "msg") == 0) {
			str = ptr;
			continue;
		}

		// In the above case, after msg= we need to trim the ' from uid
		if (*name == '\'')
			name++;

		// get string after = to the next space or end - this is value
		if (*ptr == '\'' || *ptr == '"') {
			str = strchr(ptr+1, *ptr);
			if (str) {
				str++;
				if (*str)
					*str++ = 0;
			}
		} else {
			str = strchr(ptr, ',');
			val = strchr(ptr, ' ');
			if (str && val && (str < val)) {
			// Value side  has commas and another field exists
			// Known: LABEL_LEVEL_CHANGE banners=none,none
			// Known: ROLL_ASSIGN new-role=r,r
			// Known: any MAC LABEL can potentially have commas
				int ftype = auparse_interp_adjust_type(n->type,
								name, val);
				if (ftype == AUPARSE_TYPE_MAC_LABEL) {
					str = val;
					*str++ = 0;
				} else {
					*str++ = 0;
					comma = 1;
				}
			} else if (str && (val == NULL)) {
			// Goes all the way to the end. Done parsing
			// Known: MCS context in PATH rec obj=u:r:t:s0:c2,c7
				int ftype = auparse_interp_adjust_type(n->type,
								name, ptr);
				if (ftype == AUPARSE_TYPE_MAC_LABEL)
					str = NULL;
				else {
					*str++ = 0;
					comma = 1;
				}
			} else if (val) {
			// There is another field, point to next (normal path)
				str = val;
				*str++ = 0;
			}
		}
		// val points to begin & str 1 past end
		val = ptr;
		
		// print interpreted string
		interpret(name, val, comma, n->type);
	}
	ausearch_free_interpretations();

	// If nothing found, just print out as is
	if (!found && ptr == NULL && str)
		safe_print_string(str, 1);

	// If last field had comma, output the rest
	else if (comma)
		safe_print_string(str, 1);
	printf("\n");
}