static void interpret(char *name, char *val, int comma, int rtype)
{
	int type;
	idata id;

	while (*name == ' '||*name == '(')
		name++;

	if (*name == 'a' && strcmp(name, "acct") == 0) {
		// Remove trailing punctuation
		int len = strlen(val);
		if (val[len-1] == ':')
			val[len-1] = 0;
	}
	type = auparse_interp_adjust_type(rtype, name, val);

	if (rtype == AUDIT_SYSCALL) {
		if (machine == (unsigned long)-1) 
			machine = audit_detect_machine();
		if (*name == 'a' && strcmp(name, "arch") == 0) {
			unsigned long ival;
			errno = 0;
			ival = strtoul(val, NULL, 16);
			if (errno) {
				printf("arch conversion error(%s) ", val);
				return;
			}
			machine = audit_elf_to_machine(ival);
		}
		if (cur_syscall < 0 && *name == 's' &&
				strcmp(name, "syscall") == 0) {
			unsigned long ival;
			errno = 0;
			ival = strtoul(val, NULL, 10);
			if (errno) {
				printf("syscall conversion error(%s) ", val);
				return;
			}
			cur_syscall = ival;
		}
		id.syscall = cur_syscall;
	} else
		id.syscall = 0;
	id.machine = machine;
	id.a0 = a0;
	id.a1 = a1;
	id.name = name;
	id.val = val;

	char *out = auparse_do_interpretation(type, &id);
	if (type == AUPARSE_TYPE_UNCLASSIFIED)
		printf("%s%c", val, comma ? ',' : ' ');
	else if (name[0] == 'k' && strcmp(name, "key") == 0) {
		char *str, *ptr = out;
		int count = 0;
		while ((str = strchr(ptr, AUDIT_KEY_SEPARATOR))) {
			*str = 0;
			if (count == 0) {
				printf("%s", ptr);
				count++;
			} else
				printf(" key=%s", ptr);
			ptr = str+1;
		}
		if (count == 0)
			printf("%s ", out);
		else
			printf(" key=%s ", ptr);
	} else if (type == AUPARSE_TYPE_TTY_DATA)
		printf("%s", out);
	else
		printf("%s ", out);
	free(out);
}
Exemple #2
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");
}
/*
 * 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");
}