diff options
Diffstat (limited to 'seaudit/seaudit.c')
-rw-r--r-- | seaudit/seaudit.c | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/seaudit/seaudit.c b/seaudit/seaudit.c new file mode 100644 index 0000000..ff542a9 --- /dev/null +++ b/seaudit/seaudit.c @@ -0,0 +1,418 @@ +/** + * @file + * Main driver for the seaudit application. This file also + * implements the main class seaudit_t. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * @author Jeremy Solt jsolt@tresys.com + * + * Copyright (C) 2003-2007 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include "seaudit.h" +#include "toplevel.h" + +#include <apol/util.h> +#include <seaudit/model.h> +#include <seaudit/parse.h> +#include <seaudit/util.h> + +#include <errno.h> +#include <getopt.h> +#include <stdlib.h> +#include <string.h> +#include <glade/glade.h> +#include <glib.h> +#include <gtk/gtk.h> + +struct seaudit +{ + preferences_t *prefs; + apol_policy_t *policy; + apol_policy_path_t *policy_path; + seaudit_log_t *log; + FILE *file; + char *log_path; + size_t num_log_messages; + const struct tm *first, *last; + toplevel_t *top; +}; + +static struct option const opts[] = { + {"log", required_argument, NULL, 'l'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} +}; + +preferences_t *seaudit_get_prefs(seaudit_t * s) +{ + return s->prefs; +} + +void seaudit_set_policy(seaudit_t * s, apol_policy_t * policy, apol_policy_path_t * path) +{ + if (policy != NULL) { + if (preferences_add_recent_policy(s->prefs, path) < 0) { + toplevel_ERR(s->top, "%s", strerror(errno)); + apol_policy_destroy(&policy); + return; + } + apol_policy_destroy(&s->policy); + s->policy = policy; + if (path != s->policy_path) { + apol_policy_path_destroy(&s->policy_path); + } + s->policy_path = path; + } else { + apol_policy_destroy(&s->policy); + apol_policy_path_destroy(&s->policy_path); + } +} + +apol_policy_t *seaudit_get_policy(seaudit_t * s) +{ + return s->policy; +} + +apol_policy_path_t *seaudit_get_policy_path(seaudit_t * s) +{ + return s->policy_path; +} + +void seaudit_set_log(seaudit_t * s, seaudit_log_t * log, FILE * f, const char *filename) +{ + if (s->file != NULL) { + fclose(s->file); + s->file = NULL; + } + if (log != NULL) { + seaudit_model_t *model = NULL; + apol_vector_t *messages = NULL; + char *t = NULL; + if ((model = seaudit_model_create(NULL, log)) == NULL || + (messages = seaudit_model_get_messages(log, model)) == NULL || + (t = strdup(filename)) == NULL || preferences_add_recent_log(s->prefs, filename) < 0) { + toplevel_ERR(s->top, "%s", strerror(errno)); + seaudit_log_destroy(&log); + seaudit_model_destroy(&model); + apol_vector_destroy(&messages); + free(t); + return; + } + /* do it in this order, for filename could be pointing to + * s->log_path */ + seaudit_log_destroy(&s->log); + s->log = log; + s->file = f; + free(s->log_path); + s->log_path = t; + s->num_log_messages = apol_vector_get_size(messages); + if (s->num_log_messages == 0) { + s->first = s->last = NULL; + } else { + seaudit_message_t *message = apol_vector_get_element(messages, 0); + s->first = seaudit_message_get_time(message); + message = apol_vector_get_element(messages, s->num_log_messages - 1); + s->last = seaudit_message_get_time(message); + } + seaudit_model_destroy(&model); + apol_vector_destroy(&messages); + } else { + seaudit_log_destroy(&s->log); + free(s->log_path); + s->log_path = NULL; + s->num_log_messages = 0; + s->first = s->last = NULL; + } +} + +int seaudit_parse_log(seaudit_t * s) +{ + return seaudit_log_parse(s->log, s->file); +} + +seaudit_log_t *seaudit_get_log(seaudit_t * s) +{ + return s->log; +} + +char *seaudit_get_log_path(seaudit_t * s) +{ + return s->log_path; +} + +apol_vector_t *seaudit_get_log_users(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_users(s->log); + } +} + +apol_vector_t *seaudit_get_log_roles(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_roles(s->log); + } +} + +apol_vector_t *seaudit_get_log_types(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_types(s->log); + } +} + +apol_vector_t *seaudit_get_log_mls_lvl(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_mls_lvl(s->log); + } +} + +apol_vector_t *seaudit_get_log_mls_clr(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_mls_clr(s->log); + } +} + +apol_vector_t *seaudit_get_log_classes(seaudit_t * s) +{ + if (s->log == NULL) { + return NULL; + } else { + return seaudit_log_get_classes(s->log); + } +} + +size_t seaudit_get_num_log_messages(seaudit_t * s) +{ + return s->num_log_messages; +} + +const struct tm *seaudit_get_log_first(seaudit_t * s) +{ + return s->first; +} + +const struct tm *seaudit_get_log_last(seaudit_t * s) +{ + return s->last; +} + +static seaudit_t *seaudit_create(preferences_t * prefs) +{ + seaudit_t *s = calloc(1, sizeof(*s)); + if (s != NULL) { + s->prefs = prefs; + } + return s; +} + +static void seaudit_destroy(seaudit_t ** s) +{ + if (s != NULL && *s != NULL) { + apol_policy_destroy(&(*s)->policy); + seaudit_log_destroy(&(*s)->log); + if ((*s)->file != NULL) { + fclose((*s)->file); + } + preferences_destroy(&(*s)->prefs); + toplevel_destroy(&(*s)->top); + free((*s)->policy_path); + free((*s)->log_path); + free(*s); + *s = NULL; + } +} + +static void print_version_info(void) +{ + printf("seaudit %s\n%s\n", VERSION, COPYRIGHT_INFO); +} + +static void print_usage_info(const char *program_name, int brief) +{ + printf("Usage: %s [OPTIONS] [POLICY ...]\n\n", program_name); + if (brief) { + printf("\tTry %s --help for more help.\n\n", program_name); + return; + } + printf("Audit Log analysis tool for Security Enhanced Linux.\n\n"); + printf(" -l FILE, --log=FILE open the log FILE\n"); + printf(" -h, --help print this help text and exit\n"); + printf(" -V, --version print version information and exit\n\n"); +} + +static void seaudit_parse_command_line(seaudit_t * seaudit, int argc, char **argv, const char **log, apol_policy_path_t ** policy) +{ + int optc; + *log = NULL; + *policy = NULL; + apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + char *primary_path = NULL; + apol_vector_t *modules = NULL; + while ((optc = getopt_long(argc, argv, "l:hV", opts, NULL)) != -1) { + switch (optc) { + case 'l': + { + *log = optarg; + break; + } + case 'h': + { + print_usage_info(argv[0], 0); + seaudit_destroy(&seaudit); + exit(EXIT_SUCCESS); + } + case 'V': + { + print_version_info(); + seaudit_destroy(&seaudit); + exit(EXIT_SUCCESS); + } + default: + { + /* unrecognized argument give full usage */ + print_usage_info(argv[0], 1); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + } + } + if (optind < argc) { /* modules */ + if ((modules = apol_vector_create(NULL)) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + primary_path = argv[optind++]; + while (argc - optind) { + if (apol_vector_append(modules, argv[optind])) { + ERR(NULL, "%s", strerror(ENOMEM)); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + path_type = APOL_POLICY_PATH_TYPE_MODULAR; + optind++; + } + } + if (*log == NULL) { + *log = preferences_get_log(seaudit->prefs); + } + if (primary_path != NULL && strcmp(primary_path, "") != 0) { + if (apol_file_is_policy_path_list(primary_path)) { + if ((*policy = apol_policy_path_create_from_file(primary_path)) == NULL) { + ERR(NULL, "%s", "invalid policy list"); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + } else { + if ((*policy = apol_policy_path_create(path_type, primary_path, modules)) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + } + } else { + const apol_policy_path_t *path = preferences_get_policy(seaudit->prefs); + if (path != NULL && (*policy = apol_policy_path_create_from_policy_path(path)) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + seaudit_destroy(&seaudit); + exit(EXIT_FAILURE); + } + } + apol_vector_destroy(&modules); +} + +/* + * We don't want to do the heavy work of loading and displaying the + * log and policy before the main loop has started because it will + * freeze the gui for too long. To solve this, the function is called + * from an idle callback set-up in main. + */ +struct delay_file_data +{ + toplevel_t *top; + const char *log_filename; + apol_policy_path_t *policy_path; +}; + +static gboolean delayed_main(gpointer data) +{ + struct delay_file_data *dfd = (struct delay_file_data *)data; + if (dfd->log_filename != NULL && strcmp(dfd->log_filename, "") != 0) { + toplevel_open_log(dfd->top, dfd->log_filename); + } + if (dfd->policy_path != NULL) { + toplevel_open_policy(dfd->top, dfd->policy_path); + } + return FALSE; +} + +int main(int argc, char **argv) +{ + preferences_t *prefs; + seaudit_t *app; + const char *log; + apol_policy_path_t *policy; + struct delay_file_data file_data; + + gtk_init(&argc, &argv); + glade_init(); + if (!g_thread_supported()) + g_thread_init(NULL); + if ((prefs = preferences_create()) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + exit(EXIT_FAILURE); + } + if ((app = seaudit_create(prefs)) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + exit(EXIT_FAILURE); + } + seaudit_parse_command_line(app, argc, argv, &log, &policy); + if ((app->top = toplevel_create(app)) == NULL) { + ERR(NULL, "%s", strerror(ENOMEM)); + seaudit_destroy(&app); + exit(EXIT_FAILURE); + } + file_data.top = app->top; + file_data.log_filename = log; + file_data.policy_path = policy; + g_idle_add(&delayed_main, &file_data); + gtk_main(); + if (preferences_write_to_conf_file(app->prefs) < 0) { + ERR(NULL, "%s", strerror(ENOMEM)); + } + seaudit_destroy(&app); + exit(EXIT_SUCCESS); +} |