コード例 #1
0
ファイル: audisp-example.c プロジェクト: Distrotech/libaudit
/* 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");
}
コード例 #2
0
/* this may seem a bit overmuch, but there are some issues with the auparse_interpret_field function
   not providing anything but a NULL back which makes all the smoke leak out...
 */
const char* auparse_interpret_field_wrap(auparse_state_t *_au)
{
	const char* ret_val;
	const char* nval = "NULL";

	ret_val = (char*)auparse_interpret_field(_au);

	if ( ret_val == NULL ) {
		return nval;
		}
	else
		return ret_val;
}
コード例 #3
0
ファイル: auvirt.c プロジェクト: yubo/audit
int add_resource(auparse_state_t *au, const char *uuid, uid_t uid, time_t time,
		const char *name, int success, const char *reason,
		const char *res_type, const char *res)
{
	if (!is_resource(res))
		return 0;

	struct event *event = event_alloc();
	if (event == NULL)
		return 1;
	event->type = ET_RES;
	event->uuid = copy_str(uuid);
	event->name = copy_str(name);
	event->success = success;
	event->reason = copy_str(reason);
	event->res_type = copy_str(res_type);
	event->res = copy_str(res);
	event->uid = uid;
	event->start = time;
	add_proof(event, au);

	/* Get cgroup specific fields. */
	if (strcmp("cgroup", res_type) == 0) {
		event->cgroup_class = copy_str(auparse_find_field(au, "class"));
		if (event->cgroup_class) {
			const char *detail = NULL;
			if (strcmp("path", event->cgroup_class) == 0) {
				if (auparse_find_field(au, "path"))
					detail = auparse_interpret_field(au);
			} else if (strcmp("major", event->cgroup_class) == 0) {
				detail = auparse_find_field(au, "category");
			}
			event->cgroup_detail = copy_str(detail);
		}
		event->cgroup_acl = copy_str(auparse_find_field(au, "acl"));
	}

	if (list_append(events, event) == NULL) {
		event_free(event);
		return 1;
	}
	return 0;
}
コード例 #4
0
ファイル: auvirt.c プロジェクト: yubo/audit
/* Extract the most common fields from virtualization-related records. */
int extract_virt_fields(auparse_state_t *au, const char **p_uuid,
		uid_t *p_uid, time_t *p_time, const char **p_name,
		int *p_suc)
{
	const char *field;
	auparse_first_record(au);
	/* Order matters */
	if (p_uid) {
		if (!auparse_find_field(au, field = "uid"))
			goto error;
		*p_uid = auparse_get_field_int(au);
	}
	if (p_name) {
		if (!auparse_find_field(au, field = "vm"))
			goto error;
		*p_name = auparse_interpret_field(au);
	}
	if (p_uuid) {
		if (!auparse_find_field(au, field = "uuid"))
			goto error;
		*p_uuid = auparse_get_field_str(au);
	}
	if (p_suc) {
		const char *res = auparse_find_field(au, field = "res");
		if (res == NULL)
			goto error;
		*p_suc = (strcmp("success", res) == 0) ? 1 : 0;
	}
	if (p_time) {
		*p_time = auparse_get_time(au);
	}
	return 0;

error:
	if (debug) {
		fprintf(stderr, "Failed to get field \"%s\" for record "
				"%ld.%03u:%lu\n", field ? field : "",
				auparse_get_time(au),
				auparse_get_milli(au),
				auparse_get_serial(au));
	}
	return 1;
}
コード例 #5
0
ファイル: aulast.c プロジェクト: Distrotech/libaudit
static void update_session_login(auparse_state_t *au)
{
	const char *tpid, *tses, *tuid, *tacct=NULL, *host, *term, *tres;
	int pid = -1, uid = -1, ses = -1, result = -1;
	time_t start;
	lnode *cur;

	// Get pid
	tpid = auparse_find_field(au, "pid");
	if (tpid)
		pid = auparse_get_field_int(au);

	// Get ses field
	tses = auparse_find_field(au, "ses");
	if (tses)
		ses = auparse_get_field_int(au);

	// Get second uid field - we should be positioned past the first one
	// gdm sends uid, everything else sends id, we try acct as last resort
	tuid = auparse_find_field(au, "uid");
	if (tuid)
		uid = auparse_get_field_int(au);
	else {
		auparse_first_record(au);
		tuid = auparse_find_field(au, "id");
		if (tuid)
			uid = auparse_get_field_int(au);
		else {
			auparse_first_record(au);
			tuid = auparse_find_field(au, "acct");
			if (tuid) {
				const char *tacct = auparse_interpret_field(au);
				struct passwd *pw = getpwnam (tacct);
				if (pw != NULL)
					uid = pw->pw_uid;
			} else
				auparse_first_record(au);
		}
	}

	start = auparse_get_time(au);

	host = auparse_find_field(au, "hostname");
	if (host && strcmp(host, "?") == 0)
		host = auparse_find_field(au, "addr");

	term = auparse_find_field(au, "terminal");
	if (term == NULL)
		term = "?";
	tres = auparse_find_field(au, "res");
	if (tres)
		tres = auparse_interpret_field(au);
	if (tres) {
		if (strcmp(tres, "success") == 0)
			result = 0;
		else
			result = 1;
	}
	// We only get tacct when its a bad login
	if (result == 1) {
		auparse_first_record(au);
		tacct = auparse_find_field(au, "acct");
		if (tacct)
			tacct = auparse_interpret_field(au);
	} else {
		// Check that they are valid
		if (pid == -1 || uid ==-1 || ses == -1) { 
			if (debug)
				fprintf(stderr,
					"Bad user login for event: %lu\n",
					auparse_get_serial(au));
			return;
		}
	}

	// See if this session is already open
	if (result == 0)
		cur = list_find_auid(&l, uid, pid, ses);
	else
		cur = NULL;
	if (cur) {
		// If we are limited to a specific terminal and
		// we find out the session is not associated with
		// the terminal of interest, delete the current node
		if (cterm && strstr(term, cterm) == NULL) {
			list_delete_cur(&l);
			if (debug)
				fprintf(stderr,
				"User login limited to %s for event: %lu\n",
					cterm, auparse_get_serial(au));
			return;
		}

		// This means we have an open session - update it
		list_update_start(&l, start, host, term, result,
				auparse_get_serial(au));

		// If the results were failed, we can close it out
		/* FIXME: result cannot be true. This is dead code.
		if (result) {
			report_session(cur);
			list_delete_cur(&l);
		} */
	} else if (bad == 1 && result == 1) {
		// If it were a bad login and we are wanting bad logins
		// create the record and report it.
		lnode n;

		n.auid = uid;
		n.start = start;
		n.end = start;
		n.name = tacct;
		n.host = host;
		n.term = term;
		n.result = result;
		n.status = LOG_OUT;
		n.loginuid_proof = auparse_get_serial(au);
		report_session(&n); 
	}
}
コード例 #6
0
ファイル: auvirt.c プロジェクト: yubo/audit
int process_avc_apparmor_source(auparse_state_t *au)
{
	uid_t uid = -1;
	time_t time = 0;
	struct event *avc;
	const char *target;

	/* Get the target object. */
	if (auparse_find_field(au, "name") == NULL) {
		if (debug) {
			auparse_first_record(au);
			fprintf(stderr, "Couldn't get the resource name from "
					"the AVC record: %s\n",
					auparse_get_record_text(au));
		}
		return 0;
	}
	target = auparse_interpret_field(au);

	/* Loop backwards to find a guest session with the target object
	 * assigned to. */
	struct list_node_t *it;
	struct event *res = NULL;
	for (it = events->tail; it; it = it->prev) {
		struct event *event = it->data;
		if (event->success) {
			if (event->type == ET_DOWN) {
				/* It's just possible to find a matching guest
				 * session in the current host session.
				 */
				break;
			} else if (event->type == ET_RES &&
			           event->end == 0 &&
			           event->res != NULL &&
		                   strcmp(target, event->res) == 0) {
				res = event;
				break;
			}
		}
	}

	/* Check if a resource event was found. */
	if (res == NULL) {
		if (debug) {
			fprintf(stderr, "Target object not found for AVC "
					"event.\n");
		}
		return 0;
	}

	if (extract_virt_fields(au, NULL, &uid, &time, NULL, NULL))
		return 0;

	avc = event_alloc();
	if (avc == NULL)
		return 1;
	avc->type = ET_AVC;

	/* Guest info */
	avc->uuid = copy_str(res->uuid);
	avc->name = copy_str(res->name);
	memcpy(avc->proof, res->proof, sizeof(avc->proof));

	/* AVC info */
	avc->start = time;
	avc->uid = uid;
	auparse_first_record(au);
	if (auparse_find_field(au, "apparmor")) {
		int i;
		avc->avc_result = copy_str(auparse_interpret_field(au));
		for (i = 0; avc->avc_result && avc->avc_result[i]; i++) {
			avc->avc_result[i] = tolower(avc->avc_result[i]);
		}
	}
	if (auparse_find_field(au, "operation"))
		avc->avc_operation = copy_str(auparse_interpret_field(au));
	avc->target = copy_str(target);
	if (auparse_find_field(au, "comm"))
		avc->comm = copy_str(auparse_interpret_field(au));

	add_proof(avc, au);
	if (list_append(events, avc) == NULL) {
		event_free(avc);
		return 1;
	}
	return 0;
}
コード例 #7
0
ファイル: auvirt.c プロジェクト: yubo/audit
int process_avc_selinux_context(auparse_state_t *au, const char *context)
{
	const char *seclevel;
	struct event *machine_id, *avc;
	uid_t uid;
	time_t time;

	seclevel = get_seclevel(auparse_find_field(au, context));
	if (seclevel == NULL) {
		if (debug) {
			fprintf(stderr, "Security context not found "
					"for AVC event.\n");
		}
		return 0;
	}

	if (extract_virt_fields(au, NULL, &uid, &time, NULL, NULL))
		return 0;

	machine_id = get_machine_id_by_seclevel(seclevel);
	if (machine_id == NULL) {
		if (debug) {
			fprintf(stderr, "Couldn't get the security "
					"level from the AVC event.\n");
		}
		return 0;
	}

	avc = event_alloc();
	if (avc == NULL)
		return 1;
	avc->type = ET_AVC;

	/* Guest info */
	avc->uuid = copy_str(machine_id->uuid);
	avc->name = copy_str(machine_id->name);
	memcpy(avc->proof, machine_id->proof, sizeof(avc->proof));

	/* AVC info */
	avc->start = time;
	avc->uid = uid;
	avc->seclevel = copy_str(seclevel);
	auparse_first_record(au);
	avc->avc_result = copy_str(auparse_find_field(au, "seresult"));
	avc->avc_operation = copy_str(auparse_find_field(au, "seperms"));
	if (auparse_find_field(au, "comm"))
		avc->comm = copy_str(auparse_interpret_field(au));
	if (auparse_find_field(au, "name"))
		avc->target = copy_str(auparse_interpret_field(au));

	/* get the context related to the permission that was denied. */
	if (avc->avc_operation) {
		const char *ctx = NULL;
		if (strcmp("relabelfrom", avc->avc_operation) == 0) {
			ctx = auparse_find_field(au, "scontext");
		} else if (strcmp("relabelto", avc->avc_operation) == 0) {
			ctx = auparse_find_field(au, "tcontext");
		}
		avc->context = copy_str(ctx);
	}

	add_proof(avc, au);
	if (list_append(events, avc) == NULL) {
		event_free(avc);
		return 1;
	}
	return 0;
}
コード例 #8
0
ファイル: auvirt.c プロジェクト: yubo/audit
int process_resource_event(auparse_state_t *au)
{
	uid_t uid;
	time_t time;
	const char *res_type, *uuid, *name;
	char field[64];
	const char *reason;
	int success;

	/* Just skip this record if it failed to get some of the fields */
	if (extract_virt_fields(au, &uuid, &uid, &time, &name, &success))
		return 0;

	/* Get the resource type */
	auparse_first_record(au);
	res_type = auparse_find_field(au, "resrc");
	reason = auparse_find_field(au, "reason");
	if (res_type == NULL) {
		if (debug)
			fprintf(stderr, "Invalid resrc field.\n");
		return 0;
	}

	/* Resource records with these types have old and new values. New
	 * values indicate resources assignments and are added to the event
	 * list. Old values are used to update the end time of a resource
	 * assignment.
	 */
	int rc = 0;
	if (strcmp("disk", res_type) == 0 ||
	    strcmp("vcpu", res_type) == 0 ||
	    strcmp("mem", res_type) == 0 ||
	    strcmp("rng", res_type) == 0 ||
	    strcmp("net", res_type) == 0) {
		const char *res = NULL;
		/* Resource removed */
		snprintf(field, sizeof(field), "old-%s", res_type);
		if(auparse_find_field(au, field))
			res = auparse_interpret_field(au);
		if (res == NULL && debug) {
			fprintf(stderr, "Failed to get %s field.\n", field);
		} else {
			rc += update_resource(au, uuid, uid, time, name,
					success, reason, res_type, res);
		}

		/* Resource added */
		res = NULL;
		snprintf(field, sizeof(field), "new-%s", res_type);
		if (auparse_find_field(au, field))
			res = auparse_interpret_field(au);
		if (res == NULL && debug) {
			fprintf(stderr, "Failed to get %s field.\n", field);
		} else {
			rc += add_resource(au, uuid, uid, time, name, success,
					reason, res_type, res);
		}
	} else if (strcmp("cgroup", res_type) == 0) {
		auparse_first_record(au);
		const char *cgroup = NULL;
		if (auparse_find_field(au, "cgroup"))
			cgroup = auparse_interpret_field(au);
		rc += add_resource(au, uuid, uid, time, name, success, reason,
				res_type, cgroup);
	} else if (debug) {
		fprintf(stderr, "Found an unknown resource: %s.\n",
				res_type);
	}
	return rc;
}
コード例 #9
0
ファイル: auvirt.c プロジェクト: yubo/audit
int process_avc_apparmor_target(auparse_state_t *au)
{
	uid_t uid;
	time_t time;
	const char *profile;
	struct event *avc;

	/* Get profile associated with the AVC record */
	if (auparse_find_field(au, "profile") == NULL) {
		if (debug) {
			auparse_first_record(au);
			fprintf(stderr, "AppArmor profile not found for AVC "
					"record: %s\n",
					auparse_get_record_text(au));
		}
		return 0;
	}
	profile = auparse_interpret_field(au);

	/* Break path to get just the basename */
	const char *basename = profile + strlen(profile);
	while (basename != profile && *basename != '/')
		basename--;
	if (*basename == '/')
		basename++;

	/* Check if it is an apparmor profile generated by libvirt and get the
	 * guest UUID from it */
	const char *prefix = "libvirt-";
	if (strncmp(prefix, basename, strlen(prefix)) != 0) {
		if (debug) {
			fprintf(stderr, "Found a profile which is not "
					"generated by libvirt: %s\n", profile);
		}
		return 0;
	}

	/* Try to find a valid guest session */
	const char *uuid = basename + strlen(prefix);
	struct list_node_t *it;
	struct event *machine_id = NULL;
	for (it = events->tail; it; it = it->prev) {
		struct event *event = it->data;
		if (event->success) {
			if (event->uuid != NULL &&
			    strcmp(event->uuid, uuid) == 0) {
				/* machine_id is used here instead of the start
				 * event because it is generated before any
				 * other event when a guest is started. So,
				 * it's possible to correlate AVC events that
				 * occurs during a guest start.
				 */
				if (event->type == ET_MACHINE_ID) {
					machine_id = event;
					break;
				} else if (event->type == ET_STOP) {
					break;
				}
			} else if (event->type == ET_DOWN) {
				break;
			}
		}
	}
	if (machine_id == NULL) {
		if (debug) {
			fprintf(stderr, "Found an AVC record for an unknown "
					"guest.\n");
		}
		return 0;
	}

	if (extract_virt_fields(au, NULL, &uid, &time, NULL, NULL))
		return 0;

	avc = event_alloc();
	if (avc == NULL)
		return 1;
	avc->type = ET_AVC;

	/* Guest info */
	avc->uuid = copy_str(machine_id->uuid);
	avc->name = copy_str(machine_id->name);
	memcpy(avc->proof, machine_id->proof, sizeof(avc->proof));

	/* AVC info */
	avc->start = time;
	avc->uid = uid;
	auparse_first_record(au);
	if (auparse_find_field(au, "apparmor")) {
		int i;
		avc->avc_result = copy_str(auparse_interpret_field(au));
		for (i = 0; avc->avc_result && avc->avc_result[i]; i++) {
			avc->avc_result[i] = tolower(avc->avc_result[i]);
		}
	}
	if (auparse_find_field(au, "operation"))
		avc->avc_operation = copy_str(auparse_interpret_field(au));
	if (auparse_find_field(au, "name"))
		avc->target = copy_str(auparse_interpret_field(au));
	if (auparse_find_field(au, "comm"))
		avc->comm = copy_str(auparse_interpret_field(au));

	add_proof(avc, au);
	if (list_append(events, avc) == NULL) {
		event_free(avc);
		return 1;
	}
	return 0;
}
コード例 #10
0
ファイル: zos-remote-plugin.c プロジェクト: pexip/os-audit
/* 
 * auparse library callback that's called when an event is ready
 */
void
push_event(auparse_state_t * au, auparse_cb_event_t cb_event_type,
           void *user_data)
{
        int rc;
        BerElement *ber;
        int qualifier;
        char timestamp[26];
        char linkValue[ZOS_REMOTE_LINK_VALUE_SIZE];
        char logString[ZOS_REMOTE_LOGSTRING_SIZE];
        unsigned long linkValue_tmp;

        if (cb_event_type != AUPARSE_CB_EVENT_READY)
                return;
                
        const au_event_t *e = auparse_get_timestamp(au);
        if (e == NULL)
                return;
        /*
         * we have an event. Each record will result in a different 'Item'
         * (refer ASN.1 definition in zos-remote-ldap.h) 
         */
        
        /*
         * Create a new BER element to encode the request
         */
        ber = ber_alloc_t(LBER_USE_DER);
        if (ber == NULL) {
            log_err("Error allocating memory for BER element");
            goto fatal;
        }

        /*
         * Collect some information to fill in every item
         */
        const char *node = auparse_get_node(au);
        const char *orig_type = auparse_find_field(au, "type");
        /* roll back event to get 'success' */
        auparse_first_record(au);
        const char *success = auparse_find_field(au, "success");
        /* roll back event to get 'res' */
        auparse_first_record(au);
        const char *res = auparse_find_field(au, "res");
        
        /* check if this event is a success or failure one */
        if (success) {
                if (strncmp(success, "0", 1) == 0 ||
                    strncmp(success, "no", 2) == 0)
                        qualifier = ZOS_REMOTE_QUALIF_FAIL;
                else
                        qualifier = ZOS_REMOTE_QUALIF_SUCCESS;
        } else if (res) {
                if (strncmp(res, "0", 1) == 0
                    || strncmp(res, "failed", 6) == 0)
                        qualifier = ZOS_REMOTE_QUALIF_FAIL;
                else
                        qualifier = ZOS_REMOTE_QUALIF_SUCCESS;
        } else
                qualifier = ZOS_REMOTE_QUALIF_INFO;
                
        /* get timestamp text */
        ctime_r(&e->sec, timestamp);
        timestamp[24] = '\0';    /* strip \n' */
        
        /* prepare linkValue which will be used for every item */
        linkValue_tmp = htonl(e->serial);        /* padronize to use network
                                                  * byte order 
                                                  */
        memset(&linkValue, 0, ZOS_REMOTE_LINK_VALUE_SIZE);
        memcpy(&linkValue, &linkValue_tmp, sizeof(unsigned long));        

        /* 
         * Prepare the logString with some meaningful text
         * We assume the first record type found is the
         * 'originating' audit record
         */
        sprintf(logString, "Linux (%s): type: %s", node, orig_type);

        /* 
         * Start writing to BER element.
         * There's only one field (version) out of the item sequence.
         * Also open item sequence
         */
        rc = ber_printf(ber, "{i{", ICTX_REQUESTVER);
        if (rc < 0)
                goto skip_event;

        /* 
         * Roll back to first record and iterate through all records
         */
        auparse_first_record(au);
        do {
                const char *type = auparse_find_field(au, "type");
                if (type == NULL)
                        goto skip_event;
                
                log_debug("got record: %s", auparse_get_record_text(au));

                /* 
                 * First field is item Version, same as global version
                 */
                rc = ber_printf(ber, "{i", ICTX_REQUESTVER);

                /*
                 * Second field is the itemTag
                 * use our internal event counter, increasing it
                 */
                rc |= ber_printf(ber, "i", conf.counter++);

                /*
                 * Third field is the linkValue
                 * using ber_put_ostring since it is not null-terminated
                 */
                rc |= ber_put_ostring(ber, linkValue,
                                      ZOS_REMOTE_LINK_VALUE_SIZE,
                                      LBER_OCTETSTRING);
                /*
                 * Fourth field is the violation
                 * Don't have anything better yet to put here
                 */
                rc |= ber_printf(ber, "b", 0);
                
                /* 
                 * Fifth field is the event.
                 * FIXME: this might be the place to switch on the
                 * audit record type and map to a more meaningful
                 * SMF type 83, subtype 4 event here
                 */
                rc |= ber_printf(ber, "i", ZOS_REMOTE_EVENT_AUTHORIZATION);
                
                /*
                 * Sixth field is the qualifier. We map 'success' or
                 * 'res' to this field
                 */
                rc |= ber_printf(ber, "i", qualifier);
                
                /* 
                 * Seventh field is the Class
                 * always use '@LINUX' for this version
                 * max size ZOS_REMOTE_CLASS_SIZE
                 */
                rc |= ber_printf(ber, "t", ASN1_IA5STRING_TAG);
                rc |= ber_printf(ber, "s", "@LINUX");
                
                /* 
                 * Eighth field is the resource
                 * use the record type (name) as the resource
                 * max size ZOS_REMOTE_RESOURCE_SIZE
                 */
                rc |= ber_printf(ber, "t", ASN1_IA5STRING_TAG);
                rc |= ber_printf(ber, "s", type);
                
                /* 
                 * Nineth field is the LogString
                 * we try to put something meaningful here
                 * we also start the relocations sequence
                 */
                rc |= ber_printf(ber, "t", ASN1_IA5STRING_TAG);
                rc |= ber_printf(ber, "s{", logString);

                /*
                 * Now we start adding the relocations.
                 * Let's add the timestamp as the first one
                 * so it's out of the field loop
                 */
                rc |= ber_printf(ber, "{i", ZOS_REMOTE_RELOC_TIMESTAMP);
                rc |= ber_printf(ber, "t", ASN1_IA5STRING_TAG);
                rc |= ber_printf(ber, "s}", timestamp);

                /* 
                 * Check that encoding is going OK until now
                 */
                if (rc < 0)
                        goto skip_event;

                /* 
                 * Now go to first field,
                 * and iterate through all fields
                 */
                auparse_first_field(au);
                do {
                        /* 
                         * we set a maximum of 1024 chars for
                         * relocation data (field=value pairs)
                         * Hopefuly this wont overflow too often
                         */
                        char data[1024];
                        const char *name = auparse_get_field_name(au);
                        const char *value = auparse_interpret_field(au);
                        if (name == NULL || value == NULL)
                                goto skip_event;
                        
                        /*
                         * First reloc field is the Relocation type
                         * We use 'OTHER' here since we don't have
                         * anything better
                         */
                        rc |= ber_printf(ber, "{i", ZOS_REMOTE_RELOC_OTHER);
                        
                        /*
                         * Second field is the relocation data
                         * We use a 'name=value' pair here
                         * Use up to 1023 chars (one char left for '\0')
                         */
                        snprintf(data, 1023, "%s=%s", name, value);
                        rc |= ber_printf(ber, "t", ASN1_IA5STRING_TAG);
                        rc |= ber_printf(ber, "s}", data);
                        
                        /*
                         * Check encoding status
                         */
                        if (rc < 0)
                                goto skip_event;
                } while (auparse_next_field(au) > 0);
                
                /* 
                 * After adding all relocations we are done with
                 * this item - finalize relocs and item 
                 */
                rc |= ber_printf(ber, "}}");
                
                /*
                 * Check if we are doing well with encoding
                 */
                if (rc < 0)
                        goto skip_event;            

        } while (auparse_next_record(au) > 0);
        
        /*
         * We have all items in - finalize item sequence & request
         */
        rc |= ber_printf(ber, "}}");

        /*
         * Check if everything went alright with encoding
         */
        if (rc < 0)
                goto skip_event;

        /* 
         * finally, enqueue request and let the other
         * thread process it
         */
        log_debug("Encoding done, enqueuing event");
        enqueue(ber);

        return;
        
skip_event:
        log_warn("Warning - error encoding request, skipping event");
        ber_free(ber, 1);        /* free it since we're not enqueuing it */
        return;

fatal:
        log_err("Error - Fatal error while encoding request. Aborting");
        stop = 1;
}
コード例 #11
0
/* This function will output a normalized line of audit
 * fields one line per event as an english sentence */
static void text_event(auparse_state_t *au,
		auparse_cb_event_t cb_event_type, void *user_data)
{
	if (cb_event_type != AUPARSE_CB_EVENT_READY)
		return;

	char tmp[20];
        const char *item, *action, *how;
        int rc, type, id = -2;
        time_t t = auparse_get_time(au);
        struct tm *tv = localtime(&t);

	if (tv)
		strftime(tmp, sizeof(tmp), "%T %x", tv);
	else
		strcpy(tmp, "?");
	type = auparse_get_type(au);
	auparse_normalize(au, NORM_OPT_NO_ATTRS);
	item = auparse_get_node(au);
	if (item) {
		printf("On %s at %s ", auparse_interpret_field(au), tmp);
		free((void *)item);
	} else
		printf("At %s ", tmp);

	rc = auparse_normalize_subject_primary(au);
	if (rc == 1) {
		const char *subj = auparse_interpret_field(au);
		id = auparse_get_field_int(au);
		if (strcmp(subj, "unset") == 0)
			subj = "system";
		printf("%s", subj);
	}

	// Need to compare auid and uid before doing this
	rc = auparse_normalize_subject_secondary(au);
	if (rc == 1) {
		int uid = auparse_get_field_int(au);
		if (uid != id && id != -2)
			printf(", acting as %s,", auparse_interpret_field(au));
	}

	rc = auparse_normalize_get_results(au);
	if (rc == 1) {
		int i = 0;
		const char *res[] = { "unsuccessfully", "successfully" };
		item = auparse_interpret_field(au);
		if (strcmp(item, "yes") == 0)
			i = 1;
		else if (strncmp(item, "suc", 3) == 0)
			i = 1;
		else if (auparse_get_field_type(au) == AUPARSE_TYPE_SECCOMP &&
				strcmp(item, "allow") == 0)
			i = 1;
		printf(" %s ", res[i]);
	} else
		putchar(' ');

	action = auparse_normalize_get_action(au);

	if (event_debug) {
		if (action == NULL)
			printf("error on type:%d\n", type);
	}
	printf("%s ", action ? action : "did-unknown");

	rc = auparse_normalize_object_primary(au);
	if (rc == 1) {
		const char *val = NULL;
		int ftype;

		// If we have an object and this is an AVC, add some words
		if (action && strstr(action, "violated"))
			val = "accessing ";

		ftype = auparse_get_field_type(au);
		if (ftype == AUPARSE_TYPE_ESCAPED_FILE)
			val = auparse_interpret_realpath(au);
		else if (ftype == AUPARSE_TYPE_SOCKADDR) {
			val = auparse_interpret_sock_address(au);
			if (val == NULL)
				val = auparse_interpret_sock_family(au);
		}

		if (val == NULL)
			val = auparse_interpret_field(au);

		printf("%s ", val);
	}

	rc = auparse_normalize_object_primary2(au);
	if (rc == 1) {
		const char *val;

		if (auparse_get_field_type(au) == AUPARSE_TYPE_ESCAPED_FILE)
			val = auparse_interpret_realpath(au);
		else
			val = auparse_interpret_field(au);
		printf("to %s ", val);
	}

	how = auparse_normalize_how(au);
	if (how && action && *action != 'e')   // Don't print for ended-session
		printf("using %s", how);

	printf("\n");
}
コード例 #12
0
static void csv_event(auparse_state_t *au,
		auparse_cb_event_t cb_event_type, void *user_data)
{
	if (cb_event_type != AUPARSE_CB_EVENT_READY)
		return;

	if (csv_header_done == 0) {
		csv_header_done = 1;
		printf( "NODE,EVENT,DATE,TIME,%sSERIAL_NUM,EVENT_KIND,"
			"SESSION,SUBJ_PRIME,SUBJ_SEC,SUBJ_KIND,%sACTION,"
			"RESULT,OBJ_PRIME,OBJ_SEC,%s%sOBJ_KIND,HOW%s\n",
		    extra_time ? "YEAR,MONTH,DAY,WEEKDAY,HOUR,GMT_OFFSET," : "",
			extra_labels ? "SUBJ_LABEL," : "",
			extra_obj2 ? "OBJ2," : "",
			extra_labels ? "OBJ_LABEL," : "",
			extra_keys ? ",KEY" : "");
	}

	char tmp[20];
	const char *item, *type, *evkind, *subj_kind, *action, *str, *how;
	int rc;
	time_t t = auparse_get_time(au);
	struct tm *tv = localtime(&t);

	// NODE
	item = auparse_get_node(au);
	if (item) {
		printf("%s", auparse_interpret_field(au));
		free((void *)item);
	}
	putchar(',');

	// Event
	type = auparse_get_type_name(au);
	if (type)
		printf("%s", type);
	putchar(',');

	// Normalize
	rc = auparse_normalize(au,
			extra_labels ? NORM_OPT_ALL : NORM_OPT_NO_ATTRS);

	//DATE
	if (tv) {
		strftime(tmp, sizeof(tmp), "%x", tv);
		printf("%s", tmp);
	}
	putchar(',');

	// TIME
	if (tv) {
		strftime(tmp, sizeof(tmp), "%T", tv);
		printf("%s", tmp);
	}
	putchar(',');

	if (extra_time) {
		// YEAR
		if (tv) {
			strftime(tmp, sizeof(tmp), "%Y", tv);
			printf("%s", tmp);
		}
		putchar(',');

		// MONTH
		if (tv) {
			strftime(tmp, sizeof(tmp), "%m", tv);
			printf("%s", tmp);
		}
		putchar(',');

		// DAY
		if (tv) {
			strftime(tmp, sizeof(tmp), "%d", tv);
			printf("%s", tmp);
		}
		putchar(',');

		// WEEKDAY
		if (tv) {
			strftime(tmp, sizeof(tmp), "%u", tv);
			printf("%s", tmp);
		}
		putchar(',');

		// HOUR
		if (tv) {
			strftime(tmp, sizeof(tmp), "%k", tv);
			printf("%s", tmp);
		}
		putchar(',');
		if (tv) {
			char sign = tv->tm_gmtoff >= 0 ? '+' : '-';
			unsigned long total = labs(tv->tm_gmtoff);
			unsigned long hour = total/3600;
			unsigned long min = (total - (hour * 3600))%60;
			printf("%c%02lu:%02lu", sign, hour, min);
		}
		putchar(',');
	}

	// SERIAL_NUMBER
	printf("%lu,", auparse_get_serial(au));

	if (rc) {
		fprintf(stderr, "error normalizing %s\n", type);

		// Just dump an empty frame
		printf(",,,,,,,,,%s%s\n", extra_labels ? ",," : "",
			extra_keys ? "," : "");
		return;
	}

	// EVENT_KIND
	evkind = auparse_normalize_get_event_kind(au);
	printf("%s", evkind ? evkind : "unknown");
	putchar(',');

	// SESSION
	rc = auparse_normalize_session(au);
	if (rc == 1)
		printf("%s", auparse_interpret_field(au));
	putchar(',');

	// SUBJ_PRIME
	rc = auparse_normalize_subject_primary(au);
	if (rc == 1) {
		const char *subj = auparse_interpret_field(au);
		if (strcmp(subj, "unset") == 0)
			subj = "system";
		printf("%s", subj);
	}
	putchar(',');

	// SUBJ_SEC
	rc = auparse_normalize_subject_secondary(au);
	if (rc == 1)
		printf("%s", auparse_interpret_field(au));
	putchar(',');

	// SUBJ_KIND
	subj_kind = auparse_normalize_subject_kind(au);
	if (subj_kind)
		printf("%s", subj_kind);
	putchar(',');

	// SUBJ_LABEL
	if (extra_labels) {
		rc = auparse_normalize_subject_first_attribute(au);
		do {
			if (rc == 1) {
				const char *name = auparse_get_field_name(au);
				if (strcmp(name, "subj") == 0) {
					printf("%s",
						auparse_interpret_field(au));
					break;
				}
			}
		} while (auparse_normalize_subject_next_attribute(au) == 1);
		putchar(',');
	}

	// ACTION
	action = auparse_normalize_get_action(au);
	printf("%s", action ? action : "did-unknown");
	putchar(',');

	// RESULT
	rc = auparse_normalize_get_results(au);
	if (rc == 1) {
		int i = 0;
		const char *res[] = { "failed", "success" };
		item = auparse_interpret_field(au);
		if (strcmp(item, "yes") == 0)
			i = 1;
		else if (strncmp(item, "suc", 3) == 0)
			i = 1;
		else if (auparse_get_field_type(au) == AUPARSE_TYPE_SECCOMP &&
				strcmp(item, "allow") == 0)
			i = 1;
		printf("%s", res[i]);
	}
	putchar(',');

	// OBJ_PRIME
	rc = auparse_normalize_object_primary(au);
	if (rc == 1) {
		const char *val;

		if (auparse_get_field_type(au) == AUPARSE_TYPE_ESCAPED_FILE)
			val = auparse_interpret_realpath(au);
		else
			val = auparse_interpret_field(au);
		printf("%s", val);
	}
	putchar(',');

	// OBJ_SEC
	rc = auparse_normalize_object_secondary(au);
	if (rc == 1)
		printf("%s", auparse_interpret_field(au));
	putchar(',');

	// OBJECT 2
	if (extra_obj2) {
		rc = auparse_normalize_object_primary2(au);
		if (rc == 1) {
			const char *val;

			if (auparse_get_field_type(au) ==
						AUPARSE_TYPE_ESCAPED_FILE)
				val = auparse_interpret_realpath(au);
			else
				val = auparse_interpret_field(au);
			printf("%s", val);
		}
		putchar(',');
	}

	// OBJ_LABEL
	if (extra_labels) {
		rc = auparse_normalize_object_first_attribute(au);
		do {
			if (rc == 1) {
				const char *name = auparse_get_field_name(au);
				if (strcmp(name, "obj") == 0) {
					printf("%s",
						auparse_interpret_field(au));
					break;
				}
			}
		} while (auparse_normalize_object_next_attribute(au) == 1);
		putchar(',');
	}

	// OBJ_KIND
	str = auparse_normalize_object_kind(au);
	printf("%s,", str);

	// HOW
	how = auparse_normalize_how(au);
	if (how)
		printf("%s", how);

	// KEY
	if (extra_keys) {
		putchar(','); // This is to close out HOW
		rc = auparse_normalize_key(au);
		if (rc == 1)
			printf("%s", auparse_interpret_field(au));
	}
	printf("\n");
}
コード例 #13
0
ファイル: auparselol_test.c プロジェクト: 0mp/audit-userspace
/*
 * auparse_callback - callback routine to be executed once a complete event is composed
 */
void
auparse_callback(auparse_state_t * au, auparse_cb_event_t cb_event_type,
                 void *user_data)
{
    int *event_cnt = (int *) user_data;

    if (cb_event_type == AUPARSE_CB_EVENT_READY) {
        if (auparse_first_record(au) <= 0)
            return;             /* If no first record, then no event ! */

        if (!(flags & F_CHECK))
            printf("event=%d records=%d\n", *event_cnt,
                   auparse_get_num_records(au));
        do {
            const au_event_t *e = auparse_get_timestamp(au);
            if (e == NULL)
                return;         /* If no timestamp, then no event */

            /* If checking, we just emit the raw record again
             */
            if (flags & F_CHECK) {
                if (e->host != NULL)
                    printf("node=%s type=%s msg=audit(%u.%3.3u:%lu):",
                           e->host, auparse_get_type_name(au),
                           (unsigned) e->sec, e->milli, e->serial);
                else
                    printf("type=%s msg=audit(%u.%3.3u:%lu):",
                           auparse_get_type_name(au),
                           (unsigned) e->sec, e->milli, e->serial);
                auparse_first_field(au);        /* Move to first field */
                do {
                    const char *fname = auparse_get_field_name(au);

                    /* We ignore the node and type fields */
                    if (strcmp(fname, "type") == 0
                        || strcmp(fname, "node") == 0)
                        continue;
                    printf(" %s=%s", fname, auparse_get_field_str(au));
                } while (auparse_next_field(au) > 0);
                printf("\n");
                continue;
            }

            printf("fields=%d\t", auparse_get_num_fields(au));
            printf("type=%d (%s) ", auparse_get_type(au),
                   auparse_get_type_name(au));
            printf("event_tid=%u.%3.3u:%lu ",
                   (unsigned) e->sec, e->milli, e->serial);
            if (flags & F_VERBOSE) {
                char *fv, *ifv = NULL;
                auparse_first_field(au);        /* Move to first field */
                do {
                    fv = (char *) auparse_get_field_str(au);
                    ifv = (char *) auparse_interpret_field(au);
                    printf("%s=", auparse_get_field_name(au));
                    print_escape(stdout, fv, "=()");
                    printf(" (");
                    print_escape(stdout, ifv, "=()");
                    printf(") ");
                }
                while (auparse_next_field(au) > 0);
            }
            printf("\n");
        }
        while (auparse_next_record(au) > 0);
        (*event_cnt)++;
    }
}
コード例 #14
0
ファイル: exemon.c プロジェクト: FxChiP/exemon
int main(int argc, char **argv) {
	/* we're probably going to be started by auditd so, you know, whatever */
	/* set up stdin to be searched ruthlessly */

	FILE *log;
	auparse_state_t *auparse;
	uint32_t syscall;
	int auid, uid;
	int wtf;
	uint32_t _argc, i; 
	const char *exe, *path, *success;
	char *cmdline, *tmp_cmd; 
	char _argv[8];
	struct passwd *au, *u;
	char *real_user, *apparent_user; 

	_argc = 0;
	cmdline = NULL;

	log = fopen("/tmp/exemon.log", "w");

/*	auparse = auparse_init(AUSOURCE_LOGS, NULL); */
	auparse = auparse_init(AUSOURCE_FILE_POINTER, stdin); 

	if (!auparse) {
		fprintf(log, "Couldn't do the thing with the thing.\n");
		exit(1);
	}

	while ((wtf = auparse_next_event(auparse)) > 0) {
		/* Start fresh */
		auid = -1;
		uid = -1;
		exe = NULL;
		path = NULL;
		success = NULL;
		_argc = 0;
		if (cmdline) free(cmdline);
		cmdline = NULL;

		/* Now we're doing the thing */
/*		auparse_first_field(auparse); */
/*		auparse_first_record(auparse); */
		auparse_first_field(auparse);
		if (auparse_find_field(auparse, "syscall")) {
			syscall = auparse_get_field_int(auparse);
			if (syscall == 59 || syscall == 11) {
				if (auparse_exhaustive_find_field(auparse, "auid")) {
					auid = auparse_get_field_int(auparse);
					au = getpwuid(auid);
					if (au) real_user = strdup(au->pw_name);
					else asprintf(&real_user, "UID_%i", auid);
					au = NULL;
				}

				if (auparse_exhaustive_find_field(auparse, "uid")) {
					uid = auparse_get_field_int(auparse);
					u = getpwuid(uid);
					if (u) apparent_user = strdup(u->pw_name);
					else asprintf(&apparent_user, "UID_%i", uid);
					u = NULL;
				}

				if (auparse_exhaustive_find_field(auparse, "success"))
					success = auparse_get_field_str(auparse);

				if (auparse_exhaustive_find_field(auparse, "exe"))
					exe = auparse_get_field_str(auparse);

				if (auparse_exhaustive_find_field(auparse, "argc")) {
					_argc = auparse_get_field_int(auparse);
					for (i = 0; i < _argc; i++) {
						snprintf(_argv, 8, "a%i", i);
						if (auparse_find_field(auparse, _argv)) {
							if (!cmdline) asprintf(&cmdline, "%s", auparse_interpret_field(auparse));
							else {
								asprintf(&tmp_cmd, "%s %s", cmdline, auparse_interpret_field(auparse));
								free(cmdline); /* avoid leaking cmdline */
								cmdline = tmp_cmd;
							}
						}
					}
				}

				if (auparse_exhaustive_find_field(auparse, "cwd"))
					path = auparse_get_field_str(auparse);
				else path = strdup("(unknown)");

				if (exe && uid >= 0 && path && success) {
					if (auid == uid || auid == -1) {
						if (cmdline && (success[0] == 'y' || success[0] == 'Y')) {
							fprintf(log, "%s ran %s in path %s with args: %s\n", apparent_user, exe, path, cmdline);
						} else {
							fprintf(log, "%s failed to run %s in path %s\n", apparent_user, exe, path); 
							if (!cmdline) { fprintf(log, "note: no cmdline: record: \n"); auparse_dump_records(auparse, log); }
						}
					} else {
						if (cmdline && (success[0] == 'y' || success[0] == 'Y')) {
							fprintf(log, "%s (as %s) ran %s in path %s with args: %s\n", real_user, apparent_user, exe, path, cmdline);
						} else {
							fprintf(log, "%s (as %s) failed to run %s in path %s\n", real_user, apparent_user, exe, path);
						}
					}
				} else {
					fprintf(log, "Incomplete record? path = %x, success = %x, uid = %i, exe = %x\n", path, success, uid, exe);
					fprintf(log, "record:\n");
					auparse_dump_records(auparse, log);
				}
				fflush(log);

				/* avoid leaking on usernames and unknown paths */
				free(apparent_user);
				free(real_user);
				if (path[0] == '(') { free(path); path = NULL; }
				apparent_user = NULL;
				real_user = NULL;
			}
		}
	}

	fprintf(log, "destroyed\n");
	fclose(log); 

	auparse_destroy(auparse);

	return 0;
}