aboutsummaryrefslogtreecommitdiffstats
path: root/common/audit.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2007-11-19 16:03:50 +0000
committerWerner Koch <[email protected]>2007-11-19 16:03:50 +0000
commit55ba204bfa848c2e591a29fedc9f103103493a57 (patch)
treee37263e4d3a25e2aa300faf4c5240191b54ea1a7 /common/audit.c
parentUpdated (diff)
downloadgnupg-55ba204bfa848c2e591a29fedc9f103103493a57.tar.gz
gnupg-55ba204bfa848c2e591a29fedc9f103103493a57.zip
Started to implement the audit log feature.
Pass PINENTRY_USER_DATA and XAUTHORITY to Pinentry. Improved support for the quality bar. Minor internal restructuring. Translation fixes.
Diffstat (limited to 'common/audit.c')
-rw-r--r--common/audit.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/common/audit.c b/common/audit.c
new file mode 100644
index 000000000..baa7d8d51
--- /dev/null
+++ b/common/audit.c
@@ -0,0 +1,336 @@
+/* audit.c - GnuPG's audit subsystem
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+
+#include "util.h"
+#include "audit.h"
+#include "audit-events.h"
+
+/* One log entry. */
+struct log_item_s
+{
+ audit_event_t event; /* The event. */
+ gpg_error_t err; /* The logged error code. */
+ int intvalue; /* A logged interger value. */
+ char *string; /* A malloced string or NULL. */
+ ksba_cert_t cert; /* A certifciate or NULL. */
+ int have_err:1;
+ int have_intvalue:1;
+};
+typedef struct log_item_s *log_item_t;
+
+
+
+/* The main audit object. */
+struct audit_ctx_s
+{
+ const char *failure; /* If set a description of the internal failure. */
+ audit_type_t type;
+
+ log_item_t log; /* The table with the log entries. */
+ size_t logsize; /* The allocated size for LOG. */
+ size_t logused; /* The used size of LOG. */
+
+};
+
+
+
+
+static const char *
+event2str (audit_event_t event)
+{
+ int idx = eventstr_msgidxof (event);
+ if (idx == -1)
+ return "Unknown event";
+ else
+ return eventstr_msgstr + eventstr_msgidx[idx];
+}
+
+
+
+/* Create a new audit context. In case of an error NULL is returned
+ and errno set appropriately. */
+audit_ctx_t
+audit_new (void)
+{
+ audit_ctx_t ctx;
+
+ ctx = xtrycalloc (1, sizeof *ctx);
+
+ return ctx;
+}
+
+
+/* Release an audit context. Passing NULL for CTX is allowed and does
+ nothing. */
+void
+audit_release (audit_ctx_t ctx)
+{
+ int idx;
+ if (!ctx)
+ return;
+ if (ctx->log)
+ {
+ for (idx=0; idx < ctx->logused; idx++)
+ {
+ if (ctx->log[idx].string)
+ xfree (ctx->log[idx].string);
+ if (ctx->log[idx].cert)
+ ksba_cert_release (ctx->log[idx].cert);
+ }
+ xfree (ctx->log);
+ }
+ xfree (ctx);
+}
+
+
+/* Set the type for the audit operation. If CTX is NULL, this is a
+ dummy fucntion. */
+void
+audit_set_type (audit_ctx_t ctx, audit_type_t type)
+{
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+
+ if (ctx->type && ctx->type != type)
+ {
+ ctx->failure = "conflict in type initialization";
+ return;
+ }
+ ctx->type = type;
+}
+
+
+/* Create a new log item and put it into the table. Return that log
+ item on success; return NULL on memory failure and mark that in
+ CTX. */
+static log_item_t
+create_log_item (audit_ctx_t ctx)
+{
+ log_item_t item, table;
+ size_t size;
+
+ if (!ctx->log)
+ {
+ size = 10;
+ table = xtrymalloc (size * sizeof *table);
+ if (!table)
+ {
+ ctx->failure = "Out of memory in create_log_item";
+ return NULL;
+ }
+ ctx->log = table;
+ ctx->logsize = size;
+ item = ctx->log + 0;
+ ctx->logused = 1;
+ }
+ else if (ctx->logused >= ctx->logsize)
+ {
+ size = ctx->logsize + 10;
+ table = xtryrealloc (ctx->log, size * sizeof *table);
+ if (!table)
+ {
+ ctx->failure = "Out of memory while reallocating in create_log_item";
+ return NULL;
+ }
+ ctx->log = table;
+ ctx->logsize = size;
+ item = ctx->log + ctx->logused++;
+ }
+ else
+ item = ctx->log + ctx->logused++;
+
+ item->event = AUDIT_NULL_EVENT;
+ item->err = 0;
+ item->have_err = 0;
+ item->intvalue = 0;
+ item->have_intvalue = 0;
+ item->string = NULL;
+ item->cert = NULL;
+
+ return item;
+
+}
+
+/* Add a new event to the audit log. If CTX is NULL, this function
+ does nothing. */
+void
+audit_log (audit_ctx_t ctx, audit_event_t event)
+{
+ log_item_t item;
+
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+ if (!event)
+ {
+ ctx->failure = "Invalid event passed to audit_log";
+ return;
+ }
+ if (!(item = create_log_item (ctx)))
+ return;
+ item->event = event;
+}
+
+/* Add a new event to the audit log. If CTX is NULL, this function
+ does nothing. This version also adds the result of the oepration
+ to the log.. */
+void
+audit_log_ok (audit_ctx_t ctx, audit_event_t event, gpg_error_t err)
+{
+ log_item_t item;
+
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+ if (!event)
+ {
+ ctx->failure = "Invalid event passed to audit_log_ok";
+ return;
+ }
+ if (!(item = create_log_item (ctx)))
+ return;
+ item->event = event;
+ item->err = err;
+ item->have_err = 1;
+}
+
+
+/* Add a new event to the audit log. If CTX is NULL, this function
+ does nothing. This version also add the integer VALUE to the log. */
+void
+audit_log_i (audit_ctx_t ctx, audit_event_t event, int value)
+{
+ log_item_t item;
+
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+ if (!event)
+ {
+ ctx->failure = "Invalid event passed to audit_log_i";
+ return;
+ }
+ if (!(item = create_log_item (ctx)))
+ return;
+ item->event = event;
+ item->intvalue = value;
+ item->have_intvalue = 1;
+}
+
+
+/* Add a new event to the audit log. If CTX is NULL, this function
+ does nothing. This version also add the integer VALUE to the log. */
+void
+audit_log_s (audit_ctx_t ctx, audit_event_t event, const char *value)
+{
+ log_item_t item;
+ char *tmp;
+
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+ if (!event)
+ {
+ ctx->failure = "Invalid event passed to audit_log_s";
+ return;
+ }
+ tmp = xtrystrdup (value? value : "");
+ if (!tmp)
+ {
+ ctx->failure = "Out of memory in audit_event";
+ return;
+ }
+ if (!(item = create_log_item (ctx)))
+ {
+ xfree (tmp);
+ return;
+ }
+ item->event = event;
+ item->string = tmp;
+}
+
+/* Add a new event to the audit log. If CTX is NULL, this function
+ does nothing. This version also adds the certificate CERT and the
+ result of an operation to the log. */
+void
+audit_log_cert (audit_ctx_t ctx, audit_event_t event,
+ ksba_cert_t cert, gpg_error_t err)
+{
+ log_item_t item;
+
+ if (!ctx || ctx->failure)
+ return; /* Audit not enabled or an internal error has occurred. */
+ if (!event)
+ {
+ ctx->failure = "Invalid event passed to audit_log_cert";
+ return;
+ }
+ if (!(item = create_log_item (ctx)))
+ return;
+ item->event = event;
+ item->err = err;
+ item->have_err = 1;
+ if (cert)
+ {
+ ksba_cert_ref (cert);
+ item->cert = cert;
+ }
+}
+
+
+
+/* Print the formatted audit result. THIS IS WORK IN PROGRESS. */
+void
+audit_print_result (audit_ctx_t ctx, FILE *fp)
+{
+ int idx;
+ int maxlen;
+ size_t n;
+
+ if (!ctx)
+ return;
+ if (!ctx->log || !ctx->logused)
+ {
+ fprintf (fp, "AUDIT-LOG: No entries\n");
+ return;
+ }
+
+ for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
+ {
+ n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
+ if (n > maxlen)
+ maxlen = n;
+ }
+
+ for (idx=0; idx < ctx->logused; idx++)
+ {
+ fprintf (fp, "AUDIT-LOG[%d]: %-*s",
+ idx, maxlen, event2str (ctx->log[idx].event));
+ if (ctx->log[idx].have_intvalue)
+ fprintf (fp, " i=%d", ctx->log[idx].intvalue);
+ if (ctx->log[idx].string)
+ fprintf (fp, " s=`%s'", ctx->log[idx].string);
+ if (ctx->log[idx].cert)
+ fprintf (fp, " has_cert");
+ if (ctx->log[idx].have_err)
+ fprintf (fp, " err=\"%s\"", gpg_strerror (ctx->log[idx].err));
+ putc ('\n', fp);
+ }
+}
+