diff options
Diffstat (limited to 'libseaudit/src/avc_message.c')
-rw-r--r-- | libseaudit/src/avc_message.c | 630 |
1 files changed, 630 insertions, 0 deletions
diff --git a/libseaudit/src/avc_message.c b/libseaudit/src/avc_message.c new file mode 100644 index 0000000..c054a72 --- /dev/null +++ b/libseaudit/src/avc_message.c @@ -0,0 +1,630 @@ +/** + * @file + * Implementation of a single avc log message. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * @author Jeremy Solt jsolt@tresys.com + * + * Copyright (C) 2006-2007 Tresys Technology, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "seaudit_internal.h" + +#include <apol/util.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +seaudit_avc_message_type_e seaudit_avc_message_get_message_type(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return SEAUDIT_AVC_UNKNOWN; + } + return avc->msg; +} + +long seaudit_avc_message_get_timestamp_nano(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->tm_stmp_sec; +} + +const char *seaudit_avc_message_get_source_user(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->suser; +} + +const char *seaudit_avc_message_get_source_role(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->srole; +} + +const char *seaudit_avc_message_get_source_type(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->stype; +} + +const char *seaudit_avc_message_get_source_mls_lvl(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->smls_lvl; +} + +const char *seaudit_avc_message_get_source_mls_clr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->smls_clr; +} + +const char *seaudit_avc_message_get_target_user(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->tuser; +} + +const char *seaudit_avc_message_get_target_role(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->trole; +} + +const char *seaudit_avc_message_get_target_type(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->ttype; +} + +const char *seaudit_avc_message_get_target_mls_lvl(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->tmls_lvl; +} + +const char *seaudit_avc_message_get_target_mls_clr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->tmls_clr; +} + +const char *seaudit_avc_message_get_object_class(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->tclass; +} + +const apol_vector_t *seaudit_avc_message_get_perm(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->perms; +} + +const char *seaudit_avc_message_get_exe(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->exe; +} + +const char *seaudit_avc_message_get_comm(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->comm; +} + +const char *seaudit_avc_message_get_name(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->name; +} + +unsigned int seaudit_avc_message_get_pid(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + if (!avc->is_pid) { + return 0; + } + return avc->pid; +} + +unsigned long seaudit_avc_message_get_inode(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + if (!avc->is_inode) { + return 0; + } + return avc->inode; +} + +const char *seaudit_avc_message_get_path(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->path; +} + +const char *seaudit_avc_message_get_dev(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->dev; +} + +const char *seaudit_avc_message_get_netif(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->netif; +} + +int seaudit_avc_message_get_port(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->port; +} + +const char *seaudit_avc_message_get_laddr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->laddr; +} + +int seaudit_avc_message_get_lport(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->lport; +} + +const char *seaudit_avc_message_get_faddr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->faddr; +} + +int seaudit_avc_message_get_fport(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->fport; +} + +const char *seaudit_avc_message_get_saddr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->saddr; +} + +int seaudit_avc_message_get_sport(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->source; +} + +const char *seaudit_avc_message_get_daddr(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return NULL; + } + return avc->daddr; +} + +int seaudit_avc_message_get_dport(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return 0; + } + return avc->dest; +} + +int seaudit_avc_message_get_key(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return -1; + } + if (!avc->is_key) { + return -1; + } + return avc->key; +} + +int seaudit_avc_message_get_cap(const seaudit_avc_message_t * avc) +{ + if (avc == NULL) { + errno = EINVAL; + return -1; + } + if (!avc->is_capability) { + return -1; + } + return avc->capability; +} + +/******************** protected functions below ********************/ + +seaudit_avc_message_t *avc_message_create(void) +{ + seaudit_avc_message_t *avc = calloc(1, sizeof(seaudit_avc_message_t)); + if (avc == NULL) { + return NULL; + } + if ((avc->perms = apol_vector_create_with_capacity(1, NULL)) == NULL) { + int error = errno; + avc_message_free(avc); + errno = error; + return NULL; + } + return avc; +} + +void avc_message_free(seaudit_avc_message_t * avc) +{ + if (avc != NULL) { + free(avc->exe); + free(avc->comm); + free(avc->path); + free(avc->dev); + free(avc->netif); + free(avc->laddr); + free(avc->faddr); + free(avc->saddr); + free(avc->daddr); + free(avc->name); + free(avc->ipaddr); + apol_vector_destroy(&avc->perms); + free(avc); + } +} + +/** + * Build the misc string sans timestamp and serial number. + */ +static char *avc_message_get_misc_string(const seaudit_avc_message_t * avc) +{ + char *s = NULL; + size_t len = 0; + if (avc->dev && apol_str_appendf(&s, &len, "dev=%s ", avc->dev) < 0) { + return NULL; + } + if (avc->ipaddr && apol_str_appendf(&s, &len, "ipaddr=%s ", avc->ipaddr) < 0) { + return NULL; + } + if (avc->laddr && apol_str_appendf(&s, &len, "laddr=%s ", avc->laddr) < 0) { + return NULL; + } + if (avc->lport != 0 && apol_str_appendf(&s, &len, "lport=%d ", avc->lport) < 0) { + return NULL; + } + if (avc->faddr && apol_str_appendf(&s, &len, "faddr=%s ", avc->faddr) < 0) { + return NULL; + } + if (avc->fport != 0 && apol_str_appendf(&s, &len, "fport=%d ", avc->fport) < 0) { + return NULL; + } + if (avc->daddr && apol_str_appendf(&s, &len, "daddr=%s ", avc->daddr) < 0) { + return NULL; + } + if (avc->dest != 0 && apol_str_appendf(&s, &len, "dest=%d ", avc->dest) < 0) { + return NULL; + } + if (avc->port != 0 && apol_str_appendf(&s, &len, "port=%d ", avc->port) < 0) { + return NULL; + } + if (avc->saddr && apol_str_appendf(&s, &len, "saddr=%s ", avc->saddr) < 0) { + return NULL; + } + if (avc->source != 0 && apol_str_appendf(&s, &len, "source=%d ", avc->source) < 0) { + return NULL; + } + if (avc->netif && apol_str_appendf(&s, &len, "netif=%s ", avc->netif) < 0) { + return NULL; + } + if (avc->is_key && apol_str_appendf(&s, &len, "key=%d ", avc->key) < 0) { + return NULL; + } + if (avc->is_capability && apol_str_appendf(&s, &len, "capability=%d ", avc->capability) < 0) { + return NULL; + } + if (s == NULL) { + return strdup(""); + } + return s; +} + +char *avc_message_to_string(const seaudit_message_t * msg, const char *date) +{ + seaudit_avc_message_t *avc = msg->data.avc; + const char *host = msg->host; + const char *manager = msg->manager; + char *s = NULL, *misc_string = NULL, *perm; + size_t i, len = 0; + if (apol_str_appendf(&s, &len, "%s %s %s: ", date, host, manager) < 0) { + return NULL; + } + if (!(avc->tm_stmp_sec == 0 && avc->tm_stmp_nano == 0 && avc->serial == 0)) { + if (apol_str_appendf(&s, &len, "audit(%lu.%03lu:%u): ", avc->tm_stmp_sec, avc->tm_stmp_nano, avc->serial) < 0) { + return NULL; + } + } + if (apol_str_appendf(&s, &len, + "avc: %s ", + (avc->msg == SEAUDIT_AVC_DENIED ? "denied" : + avc->msg == SEAUDIT_AVC_GRANTED ? "granted" : "<unknown>")) < 0) { + return NULL; + } + + if (apol_vector_get_size(avc->perms) > 0) { + if (apol_str_append(&s, &len, "{ ") < 0) { + return NULL; + } + for (i = 0; i < apol_vector_get_size(avc->perms); i++) { + perm = apol_vector_get_element(avc->perms, i); + if (apol_str_appendf(&s, &len, "%s ", perm) < 0) { + return NULL; + } + } + if (apol_str_append(&s, &len, "} for ") < 0) { + return NULL; + } + } + if (avc->is_pid && apol_str_appendf(&s, &len, "pid=%d ", avc->pid) < 0) { + return NULL; + } + if (avc->exe && apol_str_appendf(&s, &len, "exe=%s ", avc->exe) < 0) { + return NULL; + } + if (avc->comm && apol_str_appendf(&s, &len, "comm=%s ", avc->comm) < 0) { + return NULL; + } + if (avc->path && apol_str_appendf(&s, &len, "path=%s ", avc->path) < 0) { + return NULL; + } + if (avc->name && apol_str_appendf(&s, &len, "name=%s ", avc->name) < 0) { + return NULL; + } + if (avc->is_inode && apol_str_appendf(&s, &len, "ino=%lu ", avc->inode) < 0) { + return NULL; + } + if ((misc_string = avc_message_get_misc_string(avc)) == NULL || apol_str_append(&s, &len, misc_string) < 0) { + int error = errno; + free(misc_string); + errno = error; + return NULL; + } + free(misc_string); + + if (strcmp(avc->smls_lvl, avc->smls_clr)) { /* level and clearance are not the same - show both */ + if (avc->suser && apol_str_appendf(&s, &len, "scontext=%s:%s:%s:%s-%s ", avc->suser, avc->srole, avc->stype, avc->smls_lvl, avc->smls_clr) < 0) { + return NULL; + } + } else if (avc->suser && apol_str_appendf(&s, &len, "scontext=%s:%s:%s:%s ", avc->suser, avc->srole, avc->stype, avc->smls_lvl) < 0) { + /* level and clearance are the same - only show one */ + return NULL; + } + if (strcmp(avc->tmls_lvl, avc->tmls_clr)) { /* level and clearance are not the same - show both */ + if (avc->tuser && apol_str_appendf(&s, &len, "tcontext=%s:%s:%s:%s-%s ", avc->tuser, avc->trole, avc->ttype, avc->tmls_lvl, avc->tmls_clr) < 0) { + return NULL; + } + } else if (avc->tuser && apol_str_appendf(&s, &len, "tcontext=%s:%s:%s:%s ", avc->tuser, avc->trole, avc->ttype, avc->tmls_lvl) < 0) { + /* level and clearance are the same - only show one */ + return NULL; + } + if (avc->tclass && apol_str_appendf(&s, &len, "tclass=%s ", avc->tclass) < 0) { + return NULL; + } + return s; +} + +char *avc_message_to_string_html(const seaudit_message_t * msg, const char *date) +{ + seaudit_avc_message_t *avc = msg->data.avc; + const char *host = msg->host; + const char *manager = msg->manager; + char *s = NULL, *misc_string = NULL, *perm; + size_t i, len = 0; + if (apol_str_appendf(&s, &len, + "<font class=\"message_date\">%s</font> " + "<font class=\"host_name\">%s</font> " "%s: ", date, host, manager) < 0) { + return NULL; + } + if (!(avc->tm_stmp_sec == 0 && avc->tm_stmp_nano == 0 && avc->serial == 0)) { + if (apol_str_appendf(&s, &len, + "<font class=\"syscall_timestamp\">audit(%lu.%03lu:%u): </font>", + avc->tm_stmp_sec, avc->tm_stmp_nano, avc->serial) < 0) { + return NULL; + } + } + if (apol_str_appendf(&s, &len, + "avc: %s ", + (avc->msg == SEAUDIT_AVC_DENIED ? "<font class=\"avc_deny\">denied</font> " : + avc->msg == SEAUDIT_AVC_GRANTED ? "<font class=\"avc_grant\">granted</font>" : "<unknown>")) < 0) { + return NULL; + } + + if (apol_vector_get_size(avc->perms) > 0) { + if (apol_str_append(&s, &len, "{ ") < 0) { + return NULL; + } + for (i = 0; i < apol_vector_get_size(avc->perms); i++) { + perm = apol_vector_get_element(avc->perms, i); + if (apol_str_appendf(&s, &len, "%s ", perm) < 0) { + return NULL; + } + } + if (apol_str_append(&s, &len, "} for ") < 0) { + return NULL; + } + } + if (avc->is_pid && apol_str_appendf(&s, &len, "pid=%d ", avc->pid) < 0) { + return NULL; + } + if (avc->exe && apol_str_appendf(&s, &len, "<font class=\"exe\">exe=%s</font> ", avc->exe) < 0) { + return NULL; + } + if (avc->comm && apol_str_appendf(&s, &len, "comm=%s ", avc->comm) < 0) { + return NULL; + } + if (avc->path && apol_str_appendf(&s, &len, "path=%s ", avc->path) < 0) { + return NULL; + } + if (avc->name && apol_str_appendf(&s, &len, "name=%s ", avc->name) < 0) { + return NULL; + } + if (avc->is_inode && apol_str_appendf(&s, &len, "ino=%lu ", avc->inode) < 0) { + return NULL; + } + if ((misc_string = avc_message_get_misc_string(avc)) == NULL || apol_str_append(&s, &len, misc_string) < 0) { + int error = errno; + free(misc_string); + errno = error; + return NULL; + } + free(misc_string); + if(strcmp(avc->smls_lvl, avc->smls_clr)) { /* level and clearance are not the same - show both */ + if (avc->suser && + apol_str_appendf(&s, &len, "<font class=\"src_context\">scontext=%s:%s:%s:%s-%s</font> ", + avc->suser, avc->srole, avc->stype, avc->smls_lvl, avc->smls_clr) < 0) { + return NULL; + } + } else if (avc->suser && apol_str_appendf(&s, &len, "<font class=\"src_context\">scontext=%s:%s:%s:%s</font> ", + avc->suser, avc->srole, avc->stype, avc->smls_lvl) < 0) { + /* level and clearance are the same - only show one */ + return NULL; + } + if(strcmp(avc->tmls_lvl, avc->tmls_clr)) { /* level and clearance are not the same - show both */ + if (avc->tuser && + apol_str_appendf(&s, &len, "<font class=\"tgt_context\">tcontext=%s:%s:%s:%s-%s</font> ", + avc->tuser, avc->trole, avc->ttype, avc->tmls_lvl, avc->tmls_clr) < 0) { + return NULL; + } + } else if (avc->tuser && + apol_str_appendf(&s, &len, "<font class=\"tgt_context\">tcontext=%s:%s:%s:%s</font> ", + avc->tuser, avc->trole, avc->ttype, avc->tmls_lvl) < 0) { + /* level and clearance are the same - only show one */ + return NULL; + } + if (avc->tclass && apol_str_appendf(&s, &len, "<font class=\"obj_class\">tclass=%s</font> ", avc->tclass) < 0) { + return NULL; + } + if (apol_str_appendf(&s, &len, "<br>") < 0) { + return NULL; + } + return s; +} + +char *avc_message_to_misc_string(const seaudit_avc_message_t * avc) +{ + char *s = avc_message_get_misc_string(avc); + size_t len; + if (s == NULL) { + return NULL; + } + len = strlen(s) + 1; + if (!(avc->tm_stmp_sec == 0 && avc->tm_stmp_nano == 0 && avc->serial == 0)) { + if (apol_str_appendf(&s, &len, "%stimestamp=%lu.%03lu serial=%u", + (len > 1 ? " " : ""), avc->tm_stmp_sec, avc->tm_stmp_nano, avc->serial) < 0) { + return NULL; + } + } + return s; +} |