コード例 #1
0
ファイル: exemon.c プロジェクト: FxChiP/exemon
void auparse_dump_records(auparse_state_t *auparse, FILE *fp) {
	auparse_first_record(auparse);
	if (!fp) fp = stdout;

	fprintf(fp, "%s\n", auparse_get_record_text(auparse));
	while (auparse_next_record(auparse)) {
		fprintf(fp, "%s\n", auparse_get_record_text(auparse));
	}
}
コード例 #2
0
ファイル: aulast.c プロジェクト: Distrotech/libaudit
static void extract_record(auparse_state_t *au)
{
	if (f == NULL)
		return;

	fprintf(f, "%s\n", auparse_get_record_text(au));
}
コード例 #3
0
ファイル: audisp-example.c プロジェクト: Distrotech/libaudit
/* This function shows how to dump a whole event by iterating over records */
static void dump_whole_event(auparse_state_t *au)
{
	auparse_first_record(au);
	do {
		printf("%s\n", auparse_get_record_text(au));
	} while (auparse_next_record(au) > 0);
	printf("\n");
}
コード例 #4
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;
}
コード例 #5
0
ファイル: auvirt.c プロジェクト: yubo/audit
/* This function tries to correlate an anomaly record to a guest using the qemu
 * pid or the selinux context. */
int process_anom(auparse_state_t *au)
{
	uid_t uid;
	time_t time;
	pid_t pid = -1;
	list_node_t *it;
	struct event *anom, *start = NULL;

	/* An anomaly record is correlated to a guest by the process id */
	if (auparse_find_field(au, "pid")) {
		pid = auparse_get_field_int(au);
	} else {
		if (debug) {
			fprintf(stderr, "Found an anomaly record "
					"without pid.\n");
		}
	}

	/* Loop backwards to find a running guest with the same pid. */
	if (pid >= 0) {
		for (it = events->tail; it; it = it->next) {
			struct event *event = it->data;
			if (event->pid == pid && event->success) {
				if (event->type == ET_STOP) {
					break;
				} else if (event->type == ET_START) {
					if (event->end == 0)
						start = event;
					break;
				}
			}
		}
	}

	/* Try to match using selinux context */
	if (start == NULL) {
		const char *seclevel;
		struct event *machine_id;

		seclevel = get_seclevel(auparse_find_field(au, "subj"));
		if (seclevel == NULL) {
			if (debug) {
				auparse_first_record(au);
				const char *text = auparse_get_record_text(au);
				fprintf(stderr, "Security context not found "
						"for anomaly event: %s\n",
						text ? text : "");
			}
			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 anomaly event.\n");
			}
			return 0;
		}

		for (it = events->tail; it; it = it->next) {
			struct event *event = it->data;
			if (event->success && machine_id->uuid && event->uuid &&
			    strcmp(machine_id->uuid, event->uuid) == 0) {
				if (event->type == ET_STOP) {
					break;
				} else if (event->type == ET_START) {
					if (event->end == 0)
						start = event;
					break;
				}
			}
		}
	}

	if (start == NULL) {
		if (debug) {
			const char *text = auparse_get_record_text(au);
			fprintf(stderr, "Guest not found for "
					"anomaly record: %s.\n",
					text ? text : "");
		}
		return 0;
	}

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

	anom = event_alloc();
	if (anom == NULL)
		return 1;
	anom->type = ET_ANOM;
	anom->uuid = copy_str(start->uuid);
	anom->name = copy_str(start->name);
	anom->uid = uid;
	anom->start = time;
	anom->pid = pid;
	memcpy(anom->proof, start->proof, sizeof(anom->proof));
	add_proof(anom, au);
	if (list_append(events, anom) == NULL) {
		event_free(anom);
		return 1;
	}
	return 0;
}
コード例 #6
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;
}
コード例 #7
0
ファイル: audisp-example.c プロジェクト: Distrotech/libaudit
/* 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");
}
コード例 #8
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;
}