summaryrefslogtreecommitdiffstats
path: root/libseaudit/src/avc_message.c
diff options
context:
space:
mode:
Diffstat (limited to 'libseaudit/src/avc_message.c')
-rw-r--r--libseaudit/src/avc_message.c630
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;
+}