From 19d701ddf07d855128ded0cf2b573ce468e3bdd6 Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 20 Jan 2016 01:10:01 +0000 Subject: Removing Suricata and Audit from source repo, and updated build.sh to avoid building suricata. Will re-address this in C release via tar balls. Change-Id: I3710076f8b7f3313cb3cb5260c4eb0a6834d4f6e Signed-off-by: Ashlee Young --- framework/src/audit/tools/auvirt/Makefile.am | 40 - framework/src/audit/tools/auvirt/auvirt-list.c | 105 -- framework/src/audit/tools/auvirt/auvirt-list.h | 31 - framework/src/audit/tools/auvirt/auvirt.8 | 121 -- framework/src/audit/tools/auvirt/auvirt.c | 1595 ------------------------ 5 files changed, 1892 deletions(-) delete mode 100644 framework/src/audit/tools/auvirt/Makefile.am delete mode 100644 framework/src/audit/tools/auvirt/auvirt-list.c delete mode 100644 framework/src/audit/tools/auvirt/auvirt-list.h delete mode 100644 framework/src/audit/tools/auvirt/auvirt.8 delete mode 100644 framework/src/audit/tools/auvirt/auvirt.c (limited to 'framework/src/audit/tools/auvirt') diff --git a/framework/src/audit/tools/auvirt/Makefile.am b/framework/src/audit/tools/auvirt/Makefile.am deleted file mode 100644 index 5f6490a4..00000000 --- a/framework/src/audit/tools/auvirt/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -# -# Makefile.am -- -# Copyright (c) 2011 IBM Corp. -# Copyright (C) 2015 Red Hat, Inc. -# All Rights Reserved. -# -# This software may be freely redistributed and/or modified under the -# terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# Authors: -# Marcelo Henrique Cerri -# - -CONFIG_CLEAN_FILES = *.loT *.rej *.orig -AUTOMAKE_OPTIONS = no-dependencies -EXTRA_DIST = $(man_MANS) -AM_CPPFLAGS = -I${top_srcdir} \ - -I${top_srcdir}/lib \ - -I${top_srcdir}/auparse \ - -I${top_srcdir}/src -LIBS = -L${top_builddir}/auparse -lauparse -AM_CFLAGS = -D_GNU_SOURCE -bin_PROGRAMS = auvirt -noinst_HEADERS = auvirt-list.h -man_MANS = auvirt.8 - -auvirt_SOURCES = auvirt.c \ - auvirt-list.c \ - ${top_srcdir}/src/ausearch-time.c diff --git a/framework/src/audit/tools/auvirt/auvirt-list.c b/framework/src/audit/tools/auvirt/auvirt-list.c deleted file mode 100644 index 75021889..00000000 --- a/framework/src/audit/tools/auvirt/auvirt-list.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "auvirt-list.h" -#include - -list_t *list_init(list_t *list, list_free_data_fn *free_data_fn) -{ - if (list == NULL) - return NULL; - list->head = list->tail = NULL; - list->free_data_fn = free_data_fn; - return list; -} - -list_t *list_new(list_free_data_fn *free_data_fn) -{ - return list_init(malloc(sizeof(list_t)), free_data_fn); -} - -void list_free_node(list_node_t *node, list_free_data_fn *free_data_fn) -{ - if (node) { - if (free_data_fn) - free_data_fn(node->data); - free(node); - } -} - -void list_free_(list_t *list, list_free_data_fn *free_data_fn) -{ - if (list != NULL) { - list_node_t *it = list->head; - while (it && it->next) { - it = it->next; - list_free_node(it->prev, free_data_fn); - } - list_free_node(it, free_data_fn); - free(list); - } -} - -void list_free(list_t *list) -{ - if (list) - list_free_(list, list->free_data_fn); -} - -list_node_t *list_insert_after(list_t *list, list_node_t *it, - void *data) -{ - list_node_t *node = NULL; - if (list == NULL) - return NULL; - - /* allocate node */ - node = malloc(sizeof(list_node_t)); - if (node == NULL) - return NULL; - node->data = data; - - /* insert the new node after it */ - node->prev = it; - if (it) { - node->next = it->next; - it->next = node; - } - else - node->next = list->head; - if (node->next) - node->next->prev = node; - - /* update list's head and tail */ - if (it == list->tail) - list->tail = node; - if (it == NULL) - list->head = node; - - return node; -} - -list_node_t *list_append(list_t *list, void *data) -{ - return list_insert_after(list, list->tail, data); -} - -int list_remove_(list_t *list, list_node_t *it, - list_free_data_fn *free_data_fn) -{ - if (list == NULL || it == NULL) - return 1; - if (list->head == it) - list->head = it->next; - if (list->tail == it) - list->tail = it->prev; - if (it->next) - it->next->prev = it->prev; - if (it->prev) - it->prev->next = it->next; - list_free_node(it, free_data_fn); - return 0; -} - -int list_remove(list_t *list, list_node_t *it) -{ - return list_remove_(list, it, list->free_data_fn); -} - diff --git a/framework/src/audit/tools/auvirt/auvirt-list.h b/framework/src/audit/tools/auvirt/auvirt-list.h deleted file mode 100644 index fb587468..00000000 --- a/framework/src/audit/tools/auvirt/auvirt-list.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef AUVIRT_LIST_HEADER -#define AUVIRT_LIST_HEADER - -typedef void (list_free_data_fn)(void *data); - -typedef struct list_node_t { - void *data; - struct list_node_t *prev; - struct list_node_t *next; -} list_node_t; - -typedef struct list_t { - list_node_t *head; - list_node_t *tail; - list_free_data_fn *free_data_fn; -} list_t; - -list_t *list_init(list_t *list, list_free_data_fn *free_data_fn); -list_t *list_new(list_free_data_fn *free_data_fn); -void list_free_(list_t *list, list_free_data_fn *free_data_fn); -void list_free(list_t *list); -list_node_t *list_insert_after(list_t *list, list_node_t *it, - void *data); -list_node_t *list_append(list_t *list, void *data); -int list_remove_(list_t *list, list_node_t *it, - list_free_data_fn *free_data_fn); -int list_remove(list_t *list, list_node_t *it); - -#endif - diff --git a/framework/src/audit/tools/auvirt/auvirt.8 b/framework/src/audit/tools/auvirt/auvirt.8 deleted file mode 100644 index 96123f45..00000000 --- a/framework/src/audit/tools/auvirt/auvirt.8 +++ /dev/null @@ -1,121 +0,0 @@ -.TH AUVIRT 8 "Dec 2011" "IBM Corp" "System Administration Utilities" -.SH NAME -auvirt - a program that shows data related to virtual machines - -.SH SYNOPSIS -.B auvirt -[ \fIOPTIONS\fP ] - -.SH DESCRIPTION -\fBauvirt\fP shows a list of guest sessions found in the audit logs. If a guest -is specified, only the events related to that guest is considered. To specify a -guest, both UUID or VM name can be given. - -For each guest session the tool prints a record with the domain name, the user -that started the guest, the time when the guest was started and the time when -the guest was stoped. - -If the option "\-\-all\-events" is given a more detailed output is shown. In this -mode other records are shown for guest's stops, resource -assignments, host shutdowns and AVC and anomaly events. The first field -indicates the event type and can have the following values: start, stop, -res, avc, anom and down (for host shutdowns). - -Resource assignments have the additional fields: resource type, reason and -resource. And AVC records have the following additional fields: operation, -result, command and target. - -By default, auvirt reads records from the system audit log file. But -\fB--stdin\fP and \fB--file\fP options can be specified to change this -behavior. - -.SH OPTIONS -.TP -\fB--all-events\fP -Show records for all virtualization related events. -.TP -\fB--debug\fP -Print debug messages to standard output. -.TP -\fB-f\fP, \fB--file\fP \fIfile\fP -Read records from the given \fIfile\fP instead from the system audit log file. -.TP -\fB-h\fP, \fB--help\fP -Print help message and exit. -.TP -\fB--proof\fP -Add after each event a line containing all the identifiers of the audit records -used to calculate the event. Each identifier consists of unix time, -milliseconds and serial number. -.TP -\fB--show-uuid\fP -Add the guest's UUID to each record. -.TP -\fB--stdin\fP -Read records from the standard input instead from the system audit log file. -This option cannot be specified with \fB--file\fP. -.TP -\fB--summary\fP -Print a summary with information about the events found. The summary contains -the considered range of time, the number of guest starts and stops, the number -of resource assignments, the number of AVC and anomaly events, the number of -host shutdowns and the number of failed operations. -.TP -.BR \-te ,\ \-\-end \ [\fIend-date\fP]\ [\fIend-time\fP] -Search for events with time stamps equal to or before the given end time. The -format of end time depends on your locale. If the date is omitted, -.B today -is assumed. If the time is omitted, -.B now -is assumed. Use 24 hour clock time rather than AM or PM to specify time. -An example date using the en_US.utf8 locale is 09/03/2009. An example of time -is 18:00:00. The date format accepted is influenced by the LC_TIME -environmental variable. - -You may also use the word: \fBnow\fP, \fBrecent\fP, \fBtoday\fP, -\fByesterday\fP, \fBthis\-week\fP, \fBweek\-ago\fP, \fBthis\-month\fP, -\fBthis\-year\fP. \fBToday\fP means starting now. \fBRecent\fP is 10 minutes -ago. \fBYesterday\fP is 1 second after midnight the previous day. -\fBThis\-week\fP means starting 1 second after midnight on day 0 of the week -determined by your locale (see \fBlocaltime\fP). \fBThis\-month\fP means 1 -second after midnight on day 1 of the month. \fBThis\-year\fP means the 1 -second after midnight on the first day of the first month. -.TP -.BR \-ts ,\ \-\-start \ [\fIstart-date\fP]\ [\fIstart-time\fP] -Search for events with time stamps equal to or after the given end time. The -format of end time depends on your locale. If the date is omitted, -.B today -is assumed. If the time is omitted, -.B midnight -is assumed. Use 24 hour clock time rather than AM or PM to specify time. An -example date using the en_US.utf8 locale is 09/03/2009. An example of time is -18:00:00. The date format accepted is influenced by the LC_TIME environmental -variable. - -You may also use the word: \fBnow\fP, \fBrecent\fP, \fBtoday\fP, -\fByesterday\fP, \fBthis\-week\fP, \fBthis\-month\fP, \fBthis\-year\fP. -\fBToday\fP means starting at 1 second after midnight. \fBRecent\fP is 10 -minutes ago. \fBYesterday\fP is 1 second after midnight the previous day. -\fBThis\-week\fP means starting 1 second after midnight on day 0 of the week -determined by your locale (see \fBlocaltime\fP). \fBThis\-month\fP means 1 -second after midnight on day 1 of the month. \fBThis\-year\fP means the 1 -second after midnight on the first day of the first month. -.TP -\fB-u\fP, \fB--uuid\fP \ \fIUUID\fP -Only show events related to the guest with the given UUID. -.TP -\fB-v\fP, \fB--vm\fP \ \fIname\fP -Only show events related to the guest with the given name. - -.SH EXAMPLES -To see all the records in this month for a guest - -\fBauvirt \-\-start this\-month \-\-vm GuestVmName \-\-all\-events\fP - -.SH SEE ALSO -.BR aulast (8), -.BR ausearch (8), -.BR aureport (8). - -.SH AUTHOR -Marcelo Cerri diff --git a/framework/src/audit/tools/auvirt/auvirt.c b/framework/src/audit/tools/auvirt/auvirt.c deleted file mode 100644 index 655c4541..00000000 --- a/framework/src/audit/tools/auvirt/auvirt.c +++ /dev/null @@ -1,1595 +0,0 @@ -/* - * auvirt.c - A tool to extract data related to virtualization. - * Copyright (c) 2011 IBM Corp. - * All Rights Reserved. - * - * This software may be freely redistributed and/or modified under the - * terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Authors: - * Marcelo Henrique Cerri - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "auparse.h" -#include "libaudit.h" -#include "ausearch-time.h" -#include "auvirt-list.h" - -/* Command line parameters */ -static int help_flag = 0; -static int stdin_flag = 0; -static int summary_flag = 0; -static int all_events_flag = 0; -static int uuid_flag = 0; -static int proof_flag = 0; -static const char *vm = NULL; -static const char *uuid = NULL; -static const char *file = NULL; -static int debug = 0; -/* - * The start time and end time given in the command line is stored respectively - * in the variables start_time and end_time that are declared/defined in the - * files ausearch-time.h and ausearch-time.c. These files are reused from the - * ausearch tool source code: - * - * time_t start_time = 0; - * time_t end_time = 0; - */ - -/* List of events */ -enum event_type { - ET_NONE = 0, ET_START, ET_STOP, ET_MACHINE_ID, ET_AVC, ET_RES, ET_ANOM, - ET_DOWN -}; -struct record_id { - time_t time; - unsigned int milli; - unsigned long serial; -}; -struct event { - enum event_type type; - time_t start; - time_t end; - uid_t uid; - char *uuid; - char *name; - int success; - pid_t pid; - /* Fields specific for resource events: */ - char *reason; - char *res_type; - char *res; - /* Fields specific for cgroup resources */ - char *cgroup_class; - char *cgroup_detail; - char *cgroup_acl; - /* Fields specific for machine id events: */ - char *seclevel; - /* Fields specific for avc events: */ - char *avc_result; - char *avc_operation; - char *target; - char *comm; - char *context; - /* Fields to print proof information: */ - struct record_id proof[4]; -}; -list_t *events = NULL; - - -/* Auxiliary functions to allocate and to free events. */ -struct event *event_alloc(void) -{ - struct event *event = malloc(sizeof(struct event)); - if (event) { - /* The new event is initialized with values that represents - * unset values: -1 for uid and pid and 0 (or NULL) for numbers - * and pointers. For example, event->end = 0 represents an - * unfinished event. - */ - memset(event, 0, sizeof(struct event)); - event->uid = -1; - event->pid = -1; - } - return event; -} - -void event_free(struct event *event) -{ - if (event) { - free(event->uuid); - free(event->name); - free(event->reason); - free(event->res_type); - free(event->res); - free(event->avc_result); - free(event->avc_operation); - free(event->seclevel); - free(event->target); - free(event->comm); - free(event->cgroup_class); - free(event->cgroup_detail); - free(event->cgroup_acl); - free(event->context); - free(event); - } -} - -inline char *copy_str(const char *str) -{ - return (str) ? strdup(str) : NULL; -} - -void usage(FILE *output) -{ - fprintf(output, "usage: auvirt [--stdin] [--all-events] [--summary] " - "[--start start-date [start-time]] " - "[--end end-date [end-time]] [--file file-name] " - "[--show-uuid] [--proof] " - "[--uuid uuid] [--vm vm-name]\n"); -} - -/* Parse and check command line arguments */ -int parse_args(int argc, char **argv) -{ - /* Based on http://www.ietf.org/rfc/rfc4122.txt */ - const char *uuid_pattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-" - "[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"; - int i, rc = 0; - regex_t uuid_regex; - - if (regcomp(&uuid_regex, uuid_pattern, REG_EXTENDED)) { - fprintf(stderr, "Failed to initialize program.\n"); - return 1; - } - - for (i = 1; i < argc; i++) { - const char *opt = argv[i]; - if (opt[0] != '-') { - fprintf(stderr, "Argument not expected: %s\n", opt); - goto error; - } else if (strcmp("--vm", opt) == 0 || - strcmp("-v", opt) == 0) { - if ((i + 1) >= argc || argv[i + 1][0] == '-') { - fprintf(stderr, "\"%s\" option requires " - "an argument.\n", opt); - goto error; - } - vm = argv[++i]; - } else if (strcmp("--uuid", opt) == 0 || - strcmp("-u", opt) == 0) { - if ((i + 1) >= argc || argv[i + 1][0] == '-') { - fprintf(stderr, "\"%s\" option requires " - "an argument.\n", opt); - goto error; - } - if (regexec(&uuid_regex, argv[i + 1], 0, NULL, 0)) { - fprintf(stderr, "Invalid uuid: %s\n", - argv[i + 1]); - goto error; - } - uuid = argv[++i]; - } else if (strcmp("--all-events", opt) == 0 || - strcmp("-a", opt) == 0) { - all_events_flag = 1; - } else if (strcmp("--summary", opt) == 0 || - strcmp("-s", opt) == 0) { - summary_flag = 1; - } else if (strcmp("--file", opt) == 0 || - strcmp("-f", opt) == 0) { - if ((i + 1) >= argc || argv[i + 1][0] == '-') { - fprintf(stderr, "\"%s\" option requires " - "an argument.\n", opt); - goto error; - } - file = argv[++i]; - } else if (strcmp("--show-uuid", opt) == 0) { - uuid_flag = 1; - } else if (strcmp("--stdin", opt) == 0) { - stdin_flag = 1; - } else if (strcmp("--proof", opt) == 0) { - proof_flag = 1; - } else if (strcmp("--help", opt) == 0 || - strcmp("-h", opt) == 0) { - help_flag = 1; - goto exit; - } else if (strcmp("--start", opt) == 0 || - strcmp("-ts", opt) == 0) { - const char *date, *time = NULL; - if ((i + 1) >= argc || argv[i + 1][0] == '-') { - fprintf(stderr, "\"%s\" option requires at " - "least one argument.\n", opt); - goto error; - } - date = argv[++i]; - if ((i + 1) < argc && argv[i + 1][0] != '-') - time = argv[++i]; - /* This will set start_time */ - if(ausearch_time_start(date, time)) - goto error; - } else if (strcmp("--end", opt) == 0 || - strcmp("-te", opt) == 0) { - const char *date, *time = NULL; - if ((i + 1) >= argc || argv[i + 1][0] == '-') { - fprintf(stderr, "\"%s\" option requires at " - "least one argument.\n", opt); - goto error; - } - date = argv[++i]; - if ((i + 1) < argc && argv[i + 1][0] != '-') - time = argv[++i]; - /* This will set end_time */ - if (ausearch_time_end(date, time)) - goto error; - } else if (strcmp("--debug", opt) == 0) { - debug = 1; - } else { - fprintf(stderr, "Unknown option \"%s\".\n", opt); - goto error; - } - } - - /* Validate conflicting options */ - if (stdin_flag && file) { - fprintf(stderr, "\"--sdtin\" and \"--file\" options " - "must not be specified together.\n"); - goto error; - } - - if (debug) { - fprintf(stderr, "help_flag='%i'\n", help_flag); - fprintf(stderr, "stdin_flag='%i'\n", stdin_flag); - fprintf(stderr, "all_events_flag='%i'\n", all_events_flag); - fprintf(stderr, "summary_flag='%i'\n", summary_flag); - fprintf(stderr, "uuid='%s'\n", uuid ? uuid : "(null)"); - fprintf(stderr, "vm='%s'\n", vm ? vm : "(null)"); - fprintf(stderr, "file='%s'\n", file ? file : "(null)"); - fprintf(stderr, "start_time='%-.16s'\n", (start_time == 0L) ? - "" : ctime(&start_time)); - fprintf(stderr, "end_time='%-.16s'\n", (end_time == 0L) ? - "" : ctime(&end_time)); - } - -exit: - regfree(&uuid_regex); - return rc; -error: - rc = 1; - goto exit; -} - -/* Initialize an auparse_state_t with the correct log source. */ -auparse_state_t *init_auparse(void) -{ - auparse_state_t *au = NULL; - if (stdin_flag) { - au = auparse_init(AUSOURCE_FILE_POINTER, stdin); - } else if (file) { - au = auparse_init(AUSOURCE_FILE, file); - } else { - if (getuid()) { - fprintf(stderr, "You probably need to be root for " - "this to work\n"); - } - au = auparse_init(AUSOURCE_LOGS, NULL); - } - if (au == NULL) { - fprintf(stderr, "Error: %s\n", strerror(errno)); - } - return au; -} - -/* Create a criteria to search for the virtualization related records */ -int create_search_criteria(auparse_state_t *au) -{ - char *error = NULL; - char expr[1024]; - snprintf(expr, sizeof(expr), - "(\\record_type >= %d && \\record_type <= %d)", - AUDIT_FIRST_VIRT_MSG, AUDIT_LAST_VIRT_MSG); - if (ausearch_add_expression(au, expr, &error, AUSEARCH_RULE_CLEAR)) { - fprintf(stderr, "Criteria error: %s\n", error); - free(error); - return 1; - } - if (uuid) { - if (ausearch_add_item(au, "uuid", "=", uuid, - AUSEARCH_RULE_AND)) { - fprintf(stderr, "Criteria error: uuid\n"); - return 1; - } - } - if (vm) { - if (ausearch_add_interpreted_item(au, "vm", "=", vm, - AUSEARCH_RULE_AND)) { - fprintf(stderr, "Criteria error: id\n"); - return 1; - } - } - if (all_events_flag || summary_flag) { - if (ausearch_add_item(au, "type", "=", "AVC", - AUSEARCH_RULE_OR)) { - fprintf(stderr, "Criteria error: AVC\n"); - return 1; - } - if (ausearch_add_item(au, "type", "=", "SYSTEM_SHUTDOWN", - AUSEARCH_RULE_OR)) { - fprintf(stderr, "Criteria error: shutdown\n"); - return 1; - } - snprintf(expr, sizeof(expr), - "(\\record_type >= %d && \\record_type <= %d) ||" - "(\\record_type >= %d && \\record_type <= %d)", - AUDIT_FIRST_ANOM_MSG, AUDIT_LAST_ANOM_MSG, - AUDIT_FIRST_KERN_ANOM_MSG, AUDIT_LAST_KERN_ANOM_MSG); - if (ausearch_add_expression(au, expr, &error, - AUSEARCH_RULE_OR)) { - fprintf(stderr, "Criteria error: %s\n", error); - free(error); - return 1; - } - } - if (start_time) { - if (ausearch_add_timestamp_item(au, ">=", start_time, 0, - AUSEARCH_RULE_AND)) { - fprintf(stderr, "Criteria error: start_time\n"); - return 1; - } - } - if (end_time) { - if (ausearch_add_timestamp_item(au, "<=", end_time, 0, - AUSEARCH_RULE_AND)) { - fprintf(stderr, "Criteria error: end_time\n"); - return 1; - } - } - return 0; -} - -/* 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; -} - -/* Return label and categories from a security context. */ -const char *get_seclevel(const char *seclabel) -{ - /* - * system_u:system_r:svirt_t:s0:c107,c434 - * \____ _____/ - * ' - * level + cat - */ - int c = 0; - for (;seclabel && *seclabel; seclabel++) { - if (*seclabel == ':') - c += 1; - if (c == 3) - return seclabel + 1; - } - return NULL; -} - -int add_proof(struct event *event, auparse_state_t *au) -{ - if (!proof_flag) - return 0; - - size_t i, proof_len = sizeof(event->proof)/sizeof(event->proof[0]); - for (i = 0; i < proof_len; i++) { - if (event->proof[i].time == 0) - break; - } - if (i == proof_len) { - if (debug) - fprintf(stderr, "Failed to add proof.\n"); - return 1; - } - - event->proof[i].time = auparse_get_time(au); - event->proof[i].milli = auparse_get_milli(au); - event->proof[i].serial = auparse_get_serial(au); - return 0; -} - -/* - * machine_id records are used to get the selinux context associated to a - * guest. - */ -int process_machine_id_event(auparse_state_t *au) -{ - uid_t uid; - time_t time; - const char *seclevel, *uuid, *name; - struct event *event; - int success; - - seclevel = get_seclevel(auparse_find_field(au, "vm-ctx")); - if (seclevel == NULL) { - if (debug) - fprintf(stderr, "Security context not found for " - "MACHINE_ID event.\n"); - } - - if (extract_virt_fields(au, &uuid, &uid, &time, &name, &success)) - return 0; - - event = event_alloc(); - if (event == NULL) - return 1; - event->type = ET_MACHINE_ID; - event->uuid = copy_str(uuid); - event->name = copy_str(name); - event->success = success; - event->seclevel = copy_str(seclevel); - event->uid = uid; - event->start = time; - add_proof(event, au); - if (list_append(events, event) == NULL) { - event_free(event); - return 1; - } - return 0; -} - -int add_start_guest_event(auparse_state_t *au) -{ - struct event *start; - uid_t uid; - time_t time; - const char *uuid, *name; - int success; - list_node_t *it; - - /* 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; - - /* On failure, loop backwards to update all the resources associated to - * the last session of this guest. When a machine_id or a stop event is - * found the loop can be broken because a machine_id is created at the - * beginning of a session and a stop event indicates a previous - * session. - */ - if (!success) { - for (it = events->tail; it; it = it->prev) { - struct event *event = it->data; - if (event->success && event->uuid && - strcmp(uuid, event->uuid) == 0) { - if (event->type == ET_STOP || - event->type == ET_MACHINE_ID) { - /* An old session found. */ - break; - } else if (event->type == ET_RES && - event->end == 0) { - event->end = time; - add_proof(event, au); - } - } - } - } - - start = event_alloc(); - if (start == NULL) - return 1; - start->type = ET_START; - start->uuid = copy_str(uuid); - start->name = copy_str(name); - start->success = success; - start->uid = uid; - start->start = time; - auparse_first_record(au); - if (auparse_find_field(au, "vm-pid")) - start->pid = auparse_get_field_int(au); - add_proof(start, au); - if (list_append(events, start) == NULL) { - event_free(start); - return 1; - } - return 0; -} - -int add_stop_guest_event(auparse_state_t *au) -{ - list_node_t *it; - struct event *stop, *start = NULL, *event = NULL; - uid_t uid; - time_t time; - const char *uuid, *name; - 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; - - /* Loop backwards to find the last start event for the uuid and - * update all resource records related to that guest session. - */ - for (it = events->tail; it; it = it->prev) { - event = it->data; - if (event->success && event->uuid && - strcmp(uuid, event->uuid) == 0) { - if (event->type == ET_START) { - /* If an old session is found it's no longer - * necessary to update the resource records. - */ - if (event->end || start) - break; - /* This is the start event related to the - * current session. */ - start = event; - } else if (event->type == ET_STOP || - event->type == ET_MACHINE_ID) { - /* Old session found. */ - break; - } else if (event->type == ET_RES && event->end == 0) { - /* Update the resource assignments. */ - event->end = time; - add_proof(event, au); - } - } - } - if (start == NULL) { - if (debug) { - fprintf(stderr, "Couldn't find the correlated start " - "record to the stop event.\n"); - } - return 0; - } - - /* Create a new stop event */ - stop = event_alloc(); - if (stop == NULL) - return 1; - stop->type = ET_STOP; - stop->uuid = copy_str(uuid); - stop->name = copy_str(name); - stop->success = success; - stop->uid = uid; - stop->start = time; - auparse_first_record(au); - if (auparse_find_field(au, "vm-pid")) - stop->pid = auparse_get_field_int(au); - add_proof(stop, au); - if (list_append(events, stop) == NULL) { - event_free(stop); - return 1; - } - - /* Update the correlated start event. */ - if (success) { - start->end = time; - add_proof(start, au); - } - return 0; -} - -int process_control_event(auparse_state_t *au) -{ - const char *op; - - op = auparse_find_field(au, "op"); - if (op == NULL) { - if (debug) - fprintf(stderr, "Invalid op field.\n"); - return 0; - } - - if (strcmp("start", op) == 0) { - if (add_start_guest_event(au)) - return 1; - } else if (strcmp("stop", op) == 0) { - if (add_stop_guest_event(au)) - return 1; - } else if (debug) { - fprintf(stderr, "Unknown op: %s\n", op); - } - return 0; -} - -inline int is_resource(const char *res) -{ - if (res == NULL || - res[0] == '\0' || - strcmp("0", res) == 0 || - strcmp("?", res) == 0) - return 0; - return 1; -} - -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; -} - -int update_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) || !success) - return 0; - - list_node_t *it; - struct event *start = NULL; - - /* Find the last start event for the uuid */ - for (it = events->tail; it; it = it->prev) { - start = it->data; - if (start->type == ET_RES && - start->success && - start->uuid && - strcmp(uuid, start->uuid) == 0 && - strcmp(res_type, start->res_type) == 0 && - strcmp(res, start->res) == 0) - break; - } - if (it == NULL) { - if (debug) { - fprintf(stderr, "Couldn't find the correlated resource" - " record to update for %s.\n", res_type); - } - return 0; - } - - start->end = time; - add_proof(start, au); - return 0; -} - -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; -} - -/* Search for the last machine_id record with the given seclevel */ -struct event *get_machine_id_by_seclevel(const char *seclevel) -{ - struct event *machine_id = NULL; - list_node_t *it; - - for (it = events->tail; it; it = it->prev) { - struct event *event = it->data; - if (event->type == ET_MACHINE_ID && - event->seclevel != NULL && - strcmp(event->seclevel, seclevel) == 0) { - machine_id = event; - break; - } - } - - return machine_id; -} - -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; -} - -/* AVC records are correlated to guest through the selinux context. */ -int process_avc_selinux(auparse_state_t *au) -{ - const char **context; - const char *contexts[] = { "tcontext", "scontext", NULL }; - - for (context = contexts; context && *context; context++) { - if (process_avc_selinux_context(au, *context)) - return 1; - } - return 0; -} - -#ifdef WITH_APPARMOR -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; -} - -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; -} - -/* AVC records are correlated to guest through the apparmor path name. */ -int process_avc_apparmor(auparse_state_t *au) -{ - if (process_avc_apparmor_target(au)) - return 1; - auparse_first_record(au); - return process_avc_apparmor_source(au); -} -#endif - -int process_avc(auparse_state_t *au) -{ - /* Check if it is a SELinux AVC record */ - if (auparse_find_field(au, "tcontext")) { - auparse_first_record(au); - return process_avc_selinux(au); - } - -#ifdef WITH_APPARMOR - /* Check if it is an AppArmor AVC record */ - auparse_first_record(au); - if (auparse_find_field(au, "apparmor")) { - auparse_first_record(au); - return process_avc_apparmor(au); - } -#endif - return 0; -} - -/* 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; -} - -int process_shutdown(auparse_state_t *au) -{ - uid_t uid = -1; - time_t time = 0; - struct event *down; - list_node_t *it; - int success = 0; - - if (extract_virt_fields(au, NULL, &uid, &time, NULL, &success)) - return 0; - - for (it = events->tail; it; it = it->prev) { - struct event *event = it->data; - if (event->success) { - if (event->type == ET_START || event->type == ET_RES) { - if (event->end == 0) { - event->end = time; - add_proof(event, au); - } - } else if (event->type == ET_DOWN) { - break; - } - } - } - - down = event_alloc(); - if (down == NULL) - return 1; - down->type = ET_DOWN; - down->uid = uid; - down->start = time; - down->success = success; - add_proof(down, au); - if (list_append(events, down) == NULL) { - event_free(down); - return 1; - } - return 0; -} - -/* Convert record type to a string */ -const char *get_rec_type(struct event *e) -{ - static char buf[64]; - if (e == NULL) - return ""; - - switch (e->type) { - case ET_START: - return "start"; - case ET_STOP: - return "stop"; - case ET_RES: - return "res"; - case ET_AVC: - return "avc"; - case ET_ANOM: - return "anom"; - case ET_DOWN: - return "down"; - } - - snprintf(buf, sizeof(buf), "%d", e->type); - return buf; -} - -/* Convert uid to a string */ -const char *get_username(struct event *e) -{ - static char s[256]; - if (!e || (int)e->uid == -1) { - s[0] = '?'; - s[1] = '\0'; - } else { - struct passwd *passwd = getpwuid(e->uid); - if (passwd == NULL || passwd->pw_name == NULL) { - snprintf(s, sizeof(s), "%d", e->uid); - } else { - snprintf(s, sizeof(s), "%s", passwd->pw_name); - } - } - return s; -} - -/* Convert a time period to string */ -const char *get_time_period(struct event *event) -{ - size_t i = 0; - static char buf[128]; - - i += sprintf(buf + i, "%-16.16s", ctime(&event->start)); - if (event->end) { - time_t secs = event->end - event->start; - int mins, hours, days; - i += sprintf(buf + i, " - %-7.5s", ctime(&event->end) + 11); - mins = (secs / 60) % 60; - hours = (secs / 3600) % 24; - days = secs / 86400; - if (days) { - i += sprintf(buf + i, "(%d+%02d:%02d)", days, hours, - mins); - } else { - i += sprintf(buf + i, "(%02d:%02d)", hours, mins); - } - } else { - if (!event->success && - event->type != ET_AVC && - event->type != ET_ANOM) { - i += sprintf(buf + i, " - failed"); - } - } - return buf; -} - -void print_event(struct event *event) -{ - /* Auxiliary macro to convert NULL to "" */ - #define N(str) ((str) ? str : "") - - /* machine id records are used just to get information about - * the guests. */ - if (event->type == ET_MACHINE_ID) - return; - /* If "--all-events" is not given, only the start event is shown. */ - if (!all_events_flag && event->type != ET_START) - return; - /* The type of event is shown only when all records are shown */ - if (all_events_flag) - printf("%-5.5s ", get_rec_type(event)); - - /* Print common fields */ - printf("%-25.25s", N(event->name)); - if (uuid_flag) - printf("\t%-36.36s", N(event->uuid)); - printf("\t%-11.11s\t%-35.35s", get_username(event), - get_time_period(event)); - - /* Print type specific fields */ - if (event->type == ET_RES) { - printf("\t%-12.12s", N(event->res_type)); - printf("\t%-10.10s", N(event->reason)); - if (strcmp("cgroup", event->res_type) != 0) { - printf("\t%s", N(event->res)); - } else { - printf("\t%s\t%s\t%s", N(event->cgroup_class), - N(event->cgroup_acl), - N(event->cgroup_detail)); - } - } else if (event->type == ET_MACHINE_ID) { - printf("\t%s", N(event->seclevel)); - } else if (event->type == ET_AVC) { - printf("\t%-12.12s", N(event->avc_operation)); - printf("\t%-10.10s", N(event->avc_result)); - printf("\t%s\t%s\t%s", N(event->comm), N(event->target), - N(event->context)); - } - printf("\n"); - - /* Print proof */ - if (proof_flag) { - int first = 1; - int i, len = sizeof(event->proof)/sizeof(event->proof[0]); - printf(" Proof:"); - for (i = 0; i < len; i++) { - if (event->proof[i].time) { - printf("%s %ld.%03u:%lu", - (first) ? "" : ",", - event->proof[i].time, - event->proof[i].milli, - event->proof[i].serial); - first = 0; - } - } - printf("\n\n"); - } -} - -/* Print all events */ -void print_events(void) -{ - list_node_t *it; - for (it = events->head; it; it = it->next) { - struct event *event = it->data; - if (event) - print_event(event); - } -} - -/* Count and print summary */ -void print_summary(void) -{ - /* Summary numbers */ - time_t start_time = 0, end_time = 0; - long start = 0, stop = 0, res = 0, avc = 0, anom = 0, - shutdown = 0, failure = 0; - char start_buf[32], end_buf[32]; - - /* Calculate summary */ - list_node_t *it; - for (it = events->head; it; it = it->next) { - struct event *event = it->data; - if (event->success == 0 && - (event->type == ET_START || - event->type == ET_STOP || - event->type == ET_RES)) { - failure++; - } else { - switch (event->type) { - case ET_START: - start++; - break; - case ET_STOP: - stop++; - break; - case ET_RES: - res++; - break; - case ET_AVC: - avc++; - break; - case ET_ANOM: - anom++; - break; - case ET_DOWN: - shutdown++; - break; - } - } - - /* Calculate time range */ - if (event->start) { - if (start_time == 0 || event->start < start_time) { - start_time = event->start; - } - if (end_time == 0 || event->start > end_time) { - end_time = event->start; - } - } - if (event->end) { - if (start_time == 0 || event->end < start_time) { - start_time = event->end; - } - if (end_time == 0 || event->end > end_time) { - end_time = event->end; - } - } - - } - - if (start_time) - ctime_r(&start_time, start_buf); - else - strcpy(start_buf, "undef"); - if (end_time) - ctime_r(&end_time, end_buf); - else - strcpy(end_buf, "undef"); - - /* Print summary */ - printf("Range of time for report: %-.16s - %-.16s\n", - start_buf, end_buf); - printf("Number of guest starts: %ld\n", start); - printf("Number of guest stops: %ld\n", stop); - printf("Number of resource assignments: %ld\n", res); - printf("Number of related AVCs: %ld\n", avc); - printf("Number of related anomalies: %ld\n", anom); - printf("Number of host shutdowns: %ld\n", shutdown); - printf("Number of failed operations: %ld\n", failure); -} - -int main(int argc, char **argv) -{ - int rc = 0; - auparse_state_t *au = NULL; - - setlocale(LC_ALL, ""); - if (parse_args(argc, argv)) - goto error; - if (help_flag) { - usage(stdout); - goto exit; - } - - /* Initialize event list*/ - events = list_new((list_free_data_fn*) event_free); - if (events == NULL) - goto unexpected_error; - - /* Initialize auparse */ - au = init_auparse(); - if (au == NULL) - goto error; - if (create_search_criteria(au)) - goto error; - - while (ausearch_next_event(au) > 0) { - int err = 0; - - switch(auparse_get_type(au)) { - case AUDIT_VIRT_MACHINE_ID: - err = process_machine_id_event(au); - break; - case AUDIT_VIRT_CONTROL: - err = process_control_event(au); - break; - case AUDIT_VIRT_RESOURCE: - err = process_resource_event(au); - break; - case AUDIT_AVC: - err = process_avc(au); - break; - case AUDIT_FIRST_ANOM_MSG ... AUDIT_LAST_ANOM_MSG: - case AUDIT_FIRST_KERN_ANOM_MSG ... AUDIT_LAST_KERN_ANOM_MSG: - err = process_anom(au); - break; - case AUDIT_SYSTEM_SHUTDOWN: - err = process_shutdown(au); - break; - } - if (err) { - goto unexpected_error; - } - auparse_next_event(au); - } - - /* Show results */ - if (summary_flag) { - print_summary(); - } else { - print_events(); - } - - /* success */ - goto exit; - -unexpected_error: - fprintf(stderr, "Unexpected error\n"); -error: - rc = 1; -exit: - if (au) - auparse_destroy(au); - list_free(events); - if (debug) - fprintf(stdout, "Exit code: %d\n", rc); - return rc; -} - -- cgit 1.2.3-korg