From 47be9ff57e72906660bb62a515222f482131e1fb Mon Sep 17 00:00:00 2001 From: Miroslav Grepl Date: Fri, 11 Apr 2014 09:37:53 +0200 Subject: Create setools-3.3.7 git repo --- seaudit/preferences.c | 585 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 seaudit/preferences.c (limited to 'seaudit/preferences.c') diff --git a/seaudit/preferences.c b/seaudit/preferences.c new file mode 100644 index 0000000..5e65385 --- /dev/null +++ b/seaudit/preferences.c @@ -0,0 +1,585 @@ +/** + * @file + * Implementation of the storage class preferences_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 + +#include "preferences.h" + +#include +#include +#include +#include +#include + +/** default frequency, in milliseconds, to poll log file for changes */ +#define DEFAULT_LOG_UPDATE_INTERVAL 1000 + +/** maximum number of recent log files and recent policy files to remember */ +#define MAX_RECENT_ENTRIES 5 + +/** name of the user's seaudit personal preferences file */ +#define USER_SEAUDIT_CONF ".seaudit" + +/** name of the system seaudit preference file */ +#define SYSTEM_SEAUDIT_CONF "dot_seaudit" + +struct visible_field +{ + preference_field_e id; + const char *field; + int visible; +}; + +static const struct visible_field default_visible_fields[] = { + {HOST_FIELD, "host_field", 1}, + {MESSAGE_FIELD, "msg_field", 1}, + {DATE_FIELD, "date_field", 1}, + {SUSER_FIELD, "src_usr_field", 0}, + {SROLE_FIELD, "src_role_field", 0}, + {STYPE_FIELD, "src_type_field", 1}, + {SMLS_LVL_FIELD, "src_mls_lvl_field", 0}, + {SMLS_CLR_FIELD, "src_mls_clr_field", 0}, + {TUSER_FIELD, "tgt_usr_field", 0}, + {TROLE_FIELD, "tgt_role_field", 0}, + {TTYPE_FIELD, "tgt_type_field", 1}, + {TMLS_LVL_FIELD, "tgt_mls_lvl_field", 0}, + {TMLS_CLR_FIELD, "tgt_mls_clr_field", 0}, + {OBJCLASS_FIELD, "obj_class_field", 1}, + {PERM_FIELD, "perm_field", 1}, + {EXECUTABLE_FIELD, "exe_field", 1}, + {COMMAND_FIELD, "comm_field", 1}, + {NAME_FIELD, "name_field", 0}, + {PID_FIELD, "pid_field", 0}, + {INODE_FIELD, "inode_field", 0}, + {PATH_FIELD, "path_field", 0}, + {OTHER_FIELD, "other_field", 1} +}; + +static const size_t num_visible_fields = sizeof(default_visible_fields) / sizeof(default_visible_fields[0]); + +struct preferences +{ + /** path to default system log file */ + char *log; + /** path to default policy */ + apol_policy_path_t *policy; + /** default path when writing reports */ + char *report; + /** default path to the stylesheet, used during report writing */ + char *stylesheet; + /** vector of paths (strings) to recently opened log files */ + apol_vector_t *recent_log_files; + /** vector of apol_policy_path_t objects to recently opened + policies */ + apol_vector_t *recent_policy_files; + /** non-zero if seaudit should poll the log file for changes */ + int real_time_log; + /** frequency, in milliesconds, to poll log file */ + int real_time_interval; + struct visible_field *fields; +}; + +void preferences_apol_policy_path_free(void *elem) +{ + apol_policy_path_t *path = elem; + apol_policy_path_destroy(&path); +} + +/** + * Parse the old-style recent policies list (a ':' separated list of + * paths) into the recent_policy_files field. + */ +static int preferences_parse_old_recent_files(preferences_t * prefs, const char *s) +{ + apol_vector_t *v = NULL; + size_t i; + char *base; + apol_policy_path_t *path; + int error = 0; + + if ((v = apol_str_split(s, ":")) == NULL) { + error = errno; + goto cleanup; + } + for (i = 0; i < apol_vector_get_size(v); i++) { + base = apol_vector_get_element(v, i); + if ((path = apol_policy_path_create(APOL_POLICY_PATH_TYPE_MONOLITHIC, base, NULL)) == NULL || + apol_vector_append(prefs->recent_policy_files, path) < 0) { + error = errno; + apol_policy_path_destroy(&path); + goto cleanup; + } + } + + cleanup: + apol_vector_destroy(&v); + if (error != 0) { + errno = error; + return -1; + } + return 0; +} + +/** + * Parse the new recent policy files, which now spans across multiple + * lines. + */ +static int preferences_parse_new_recent_files(preferences_t * prefs, FILE * f, int num_files) +{ + int count; + for (count = 0; count < num_files; count++) { + char *var_name, *value = NULL; + apol_policy_path_t *p = NULL; + if (asprintf(&var_name, "RECENT_POLICY_PATH_%d", count) < 0) { + return -1; + } + value = apol_config_get_var(var_name, f); + free(var_name); + if (value == NULL || + (p = apol_policy_path_create_from_string(value)) == NULL || + apol_vector_append(prefs->recent_policy_files, p) < 0) { + free(value); + apol_policy_path_destroy(&p); + return -1; + } + free(value); + } + return 0; +} + +preferences_t *preferences_create(void) +{ + preferences_t *prefs = NULL; + FILE *file = NULL; + char *path = NULL, *value; + apol_vector_t *v = NULL; + size_t i, j; + int error = 0; + + if ((prefs = calloc(1, sizeof(*prefs))) == NULL || + (prefs->log = strdup("")) == NULL || + (prefs->report = strdup("")) == NULL || + (prefs->stylesheet = strdup("")) == NULL || + (prefs->recent_log_files = apol_vector_create(free)) == NULL || + (prefs->recent_policy_files = apol_vector_create(preferences_apol_policy_path_free)) == NULL || + (prefs->fields = calloc(num_visible_fields, sizeof(struct visible_field))) == NULL) { + error = errno; + goto cleanup; + } + prefs->real_time_interval = DEFAULT_LOG_UPDATE_INTERVAL; + memcpy(prefs->fields, default_visible_fields, num_visible_fields * sizeof(struct visible_field)); + path = apol_file_find_user_config(USER_SEAUDIT_CONF); + if (!path) { + if ((path = apol_file_find_path(SYSTEM_SEAUDIT_CONF)) == NULL) { + return prefs; + } + } + if ((file = fopen(path, "r")) == NULL) { + error = errno; + goto cleanup; + } + if ((value = apol_config_get_var("DEFAULT_LOG_FILE", file)) != NULL) { + free(prefs->log); + prefs->log = value; + } + if ((value = apol_config_get_var("DEFAULT_POLICY_FILE", file)) != NULL) { + apol_policy_path_destroy(&prefs->policy); + if (apol_policy_path_create(APOL_POLICY_PATH_TYPE_MONOLITHIC, value, NULL) == NULL) { + error = errno; + free(value); + goto cleanup; + } + free(value); + } + if ((value = apol_config_get_var("DEFAULT_POLICY_PATH", file)) != NULL) { + apol_policy_path_destroy(&prefs->policy); + if ((prefs->policy = apol_policy_path_create_from_string(value)) == NULL) { + error = errno; + free(value); + goto cleanup; + } + free(value); + } + if ((value = apol_config_get_var("DEFAULT_REPORT_CONFIG_FILE", file)) != NULL) { + free(prefs->report); + prefs->report = value; + } + if ((value = apol_config_get_var("DEFAULT_REPORT_CSS_FILE", file)) != NULL) { + free(prefs->stylesheet); + prefs->stylesheet = value; + } + if ((value = apol_config_get_var("RECENT_LOG_FILES", file)) == NULL || (v = apol_str_split(value, ":")) == NULL) { + error = errno; + free(value); + goto cleanup; + } + free(value); + apol_vector_destroy(&prefs->recent_log_files); + prefs->recent_log_files = v; + + /* test if there exists the new recent list that contains + * module filenames */ + if ((value = apol_config_get_var("RECENT_POLICY_PATH_FILES", file)) != NULL) { + if (preferences_parse_new_recent_files(prefs, file, atoi(value)) < 0) { + error = errno; + free(value); + goto cleanup; + } + } else { + /* use older style that could only handle monolithic policies */ + if ((value = apol_config_get_var("RECENT_POLICY_FILES", file)) == NULL + || preferences_parse_old_recent_files(prefs, value) < 0) { + error = errno; + free(value); + goto cleanup; + } + } + free(value); + + if ((value = apol_config_get_var("LOG_COLUMNS_HIDDEN", file)) == NULL || (v = apol_str_split(value, ":")) == NULL) { + error = errno; + goto cleanup; + } + for (j = 0; j < num_visible_fields; j++) { + prefs->fields[j].visible = 1; + } + for (i = 0; i < apol_vector_get_size(v); i++) { + char *s = apol_vector_get_element(v, i); + for (j = 0; j < num_visible_fields; j++) { + if (strcmp(s, prefs->fields[j].field) == 0) { + prefs->fields[j].visible = 0; + break; + } + } + } + free(value); + apol_vector_destroy(&v); + value = apol_config_get_var("REAL_TIME_LOG_MONITORING", file); + if (value != NULL && value[0] != '0') { + prefs->real_time_log = 1; + } + free(value); + value = apol_config_get_var("REAL_TIME_LOG_UPDATE_INTERVAL", file); + if (value != NULL) { + prefs->real_time_interval = atoi(value); + } + free(value); + cleanup: + free(path); + if (file != NULL) { + fclose(file); + } + if (error != 0) { + preferences_destroy(&prefs); + errno = error; + return NULL; + } + return prefs; +} + +void preferences_destroy(preferences_t ** prefs) +{ + if (prefs != NULL && *prefs != NULL) { + free((*prefs)->log); + apol_policy_path_destroy(&(*prefs)->policy); + free((*prefs)->report); + free((*prefs)->stylesheet); + apol_vector_destroy(&(*prefs)->recent_log_files); + apol_vector_destroy(&(*prefs)->recent_policy_files); + free((*prefs)->fields); + free(*prefs); + *prefs = NULL; + } +} + +int preferences_write_to_conf_file(preferences_t * prefs) +{ + FILE *file = NULL; + char *home, *conf_file = NULL, *value; + apol_vector_t *hidden_fields = NULL; + size_t i; + int retval = 0, error = 0; + + /* we need to open ~/.seaudit */ + home = getenv("HOME"); + if (!home) { + error = EBADRQC; + goto cleanup; + } + if (asprintf(&conf_file, "%s/%s", home, USER_SEAUDIT_CONF) < 0) { + error = errno; + goto cleanup; + } + + if ((file = fopen(conf_file, "w")) == NULL) { + error = errno; + goto cleanup; + } + + fprintf(file, "# configuration file for seaudit - an audit log tool for Security Enhanced Linux.\n"); + fprintf(file, "# this file is auto-generated\n\n"); + + if (strcmp(prefs->log, "") != 0) { + fprintf(file, "DEFAULT_LOG_FILE %s\n", prefs->log); + } + if (prefs->policy != NULL) { + value = apol_policy_path_to_string(prefs->policy); + if (value == NULL) { + error = errno; + goto cleanup; + } + fprintf(file, "DEFAULT_POLICY_PATH %s\n", value); + free(value); + } + if (strcmp(prefs->report, "") != 0) { + fprintf(file, "DEFAULT_REPORT_CONFIG_FILE %s\n", prefs->report); + } + if (strcmp(prefs->stylesheet, "") != 0) { + fprintf(file, "DEFAULT_REPORT_CSS_FILE %s\n", prefs->stylesheet); + } + if ((value = apol_str_join(prefs->recent_log_files, ":")) == NULL) { + error = errno; + goto cleanup; + } + fprintf(file, "RECENT_LOG_FILES %s\n", value); + free(value); + + fprintf(file, "RECENT_POLICY_PATH_FILES %zd\n", apol_vector_get_size(prefs->recent_policy_files)); + for (i = 0; i < apol_vector_get_size(prefs->recent_policy_files); i++) { + apol_policy_path_t *p = apol_vector_get_element(prefs->recent_policy_files, i); + if ((value = apol_policy_path_to_string(p)) == NULL) { + error = errno; + goto cleanup; + } + fprintf(file, "RECENT_POLICY_PATH_%zd %s\n", i, value); + free(value); + } + + if ((hidden_fields = apol_vector_create(NULL)) == NULL) { + error = errno; + goto cleanup; + } + for (i = 0; i < num_visible_fields; i++) { + if (!prefs->fields[i].visible && apol_vector_append(hidden_fields, (char *)prefs->fields[i].field) < 0) { + error = errno; + goto cleanup; + } + } + if ((value = apol_str_join(hidden_fields, ":")) == NULL) { + error = errno; + goto cleanup; + } + fprintf(file, "LOG_COLUMNS_HIDDEN %s\n", value); + free(value); + fprintf(file, "REAL_TIME_LOG_MONITORING %d\n", prefs->real_time_log); + fprintf(file, "REAL_TIME_LOG_UPDATE_INTERVAL %d\n", prefs->real_time_interval); + retval = 0; + cleanup: + free(conf_file); + apol_vector_destroy(&hidden_fields); + if (file != NULL) { + fclose(file); + } + errno = error; + return retval; +} + +int preferences_is_column_visible(preferences_t * prefs, preference_field_e id) +{ + size_t i; + for (i = 0; i < num_visible_fields; i++) { + if (prefs->fields[i].id == id) { + return prefs->fields[i].visible; + } + } + assert(0); + return -1; +} + +void preferences_set_column_visible(preferences_t * prefs, preference_field_e id, int visible) +{ + size_t i; + for (i = 0; i < num_visible_fields; i++) { + if (prefs->fields[i].id == id) { + prefs->fields[i].visible = visible; + return; + } + } + assert(0); +} + +int preferences_set_log(preferences_t * prefs, const char *log) +{ + char *s; + if ((s = strdup(log)) == NULL) { + return -1; + } + free(prefs->log); + prefs->log = s; + return 0; +} + +const char *preferences_get_log(preferences_t * prefs) +{ + return prefs->log; +} + +int preferences_set_policy(preferences_t * prefs, const apol_policy_path_t * policy) +{ + apol_policy_path_t *new_policy; + if ((new_policy = apol_policy_path_create_from_policy_path(policy)) == NULL) { + return -1; + } + apol_policy_path_destroy(&prefs->policy); + prefs->policy = new_policy; + return 0; +} + +const apol_policy_path_t *preferences_get_policy(preferences_t * prefs) +{ + return prefs->policy; +} + +int preferences_set_report(preferences_t * prefs, const char *report) +{ + char *s; + if ((s = strdup(report)) == NULL) { + return -1; + } + free(prefs->report); + prefs->report = s; + return 0; +} + +const char *preferences_get_report(preferences_t * prefs) +{ + return prefs->report; +} + +int preferences_set_stylesheet(preferences_t * prefs, const char *stylesheet) +{ + char *s; + if ((s = strdup(stylesheet)) == NULL) { + return -1; + } + free(prefs->stylesheet); + prefs->stylesheet = s; + return 0; +} + +const char *preferences_get_stylesheet(preferences_t * prefs) +{ + return prefs->stylesheet; +} + +void preferences_set_real_time_at_startup(preferences_t * prefs, int startup) +{ + prefs->real_time_log = startup; +} + +int preferences_get_real_time_at_startup(preferences_t * prefs) +{ + return prefs->real_time_log; +} + +void preferences_set_real_time_interval(preferences_t * prefs, int interval) +{ + if (interval <= 0) { + prefs->real_time_interval = 0; + } else { + prefs->real_time_interval = interval; + } +} + +int preferences_get_real_time_interval(preferences_t * prefs) +{ + return prefs->real_time_interval; +} + +/** + * Add an entry to a vector, discarding the oldest entry if the vector + * size is too large. + */ +static int prefs_add_recent_vector(apol_vector_t * v, const char *entry) +{ + size_t i; + char *s; + if (apol_vector_get_index(v, (void *)entry, apol_str_strcmp, NULL, &i) == 0) { + return 0; + } + if ((s = strdup(entry)) == NULL || apol_vector_append(v, s) < 0) { + int error = errno; + free(s); + errno = error; + return -1; + } + if (apol_vector_get_size(v) >= MAX_RECENT_ENTRIES) { + s = apol_vector_get_element(v, 0); + free(s); + return apol_vector_remove(v, 0); + } + return 0; +} + +int preferences_add_recent_log(preferences_t * prefs, const char *log) +{ + return prefs_add_recent_vector(prefs->recent_log_files, log); +} + +apol_vector_t *preferences_get_recent_logs(preferences_t * prefs) +{ + return prefs->recent_log_files; +} + +static int preferences_policy_path_compare(const void *a, const void *b, void *data __attribute__ ((unused))) +{ + return apol_policy_path_compare((const apol_policy_path_t *)a, (const apol_policy_path_t *)b); +} + +int preferences_add_recent_policy(preferences_t * prefs, const apol_policy_path_t * policy) +{ + size_t i; + apol_policy_path_t *p = NULL; + if (apol_vector_get_index(prefs->recent_policy_files, policy, preferences_policy_path_compare, NULL, &i) == 0) { + return 0; + } + if ((p = apol_policy_path_create_from_policy_path(policy)) == NULL || apol_vector_append(prefs->recent_policy_files, p) < 0) { + int error = errno; + apol_policy_path_destroy(&p); + errno = error; + return -1; + } + if (apol_vector_get_size(prefs->recent_policy_files) >= MAX_RECENT_ENTRIES) { + p = apol_vector_get_element(prefs->recent_policy_files, 0); + apol_policy_path_destroy(&p); + return apol_vector_remove(prefs->recent_policy_files, 0); + } + return 0; +} + +apol_vector_t *preferences_get_recent_policies(preferences_t * prefs) +{ + return prefs->recent_policy_files; +} -- cgit