summaryrefslogtreecommitdiffstats
path: root/src/kdc/kdc_audit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kdc/kdc_audit.c')
-rw-r--r--src/kdc/kdc_audit.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/src/kdc/kdc_audit.c b/src/kdc/kdc_audit.c
new file mode 100644
index 0000000000..c9a7f9f9d4
--- /dev/null
+++ b/src/kdc/kdc_audit.c
@@ -0,0 +1,331 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* kdc_audit.c - Interface for KDC audit plugins. */
+/*
+ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include "kdc_util.h"
+#include "kdc_audit.h"
+/* for krb5_klog_syslog */
+#include <syslog.h>
+#include "adm_proto.h"
+
+struct audit_module_handle_st {
+ struct krb5_audit_vtable_st vt;
+ krb5_audit_moddata auctx;
+};
+typedef struct audit_module_handle_st *audit_module_handle;
+
+static audit_module_handle *handles = NULL;
+
+static void
+free_handles(audit_module_handle *list)
+{
+ audit_module_handle *hp, hdl;
+
+ if (list == NULL)
+ return;
+
+ for (hp = list; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.close != NULL)
+ hdl->vt.close(hdl->auctx);
+ free(hdl);
+ }
+ free(list);
+}
+
+/*
+ * Load all available audit plugin modules and prepare for logging. The list of
+ * modules is stored as an array in handles. Use unload_audit_modules() to free
+ * resources allocated by this function.
+ */
+krb5_error_code
+load_audit_modules(krb5_context context)
+{
+ krb5_error_code ret = 0;
+ krb5_plugin_initvt_fn *modules = NULL, *mod;
+ struct krb5_audit_vtable_st vtable;
+ audit_module_handle *list = NULL, hdl = NULL;
+ krb5_audit_moddata auctx;
+ int count = 0;
+
+ if (context == NULL || handles != NULL)
+ return EINVAL;
+
+ /* Get audit plugin vtable. */
+ ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_AUDIT, &modules);
+ if (ret)
+ return ret;
+
+ /* Allocate handle, initialize vtable. */
+ for (count = 0; modules[count] != NULL; count++);
+ list = k5calloc(count + 1, sizeof(*list), &ret);
+ if (list == NULL)
+ goto cleanup;
+ count = 0;
+ for (mod = modules; *mod != NULL; mod++) {
+ hdl = k5alloc(sizeof(*hdl), &ret);
+ if (hdl == NULL)
+ goto cleanup;
+ ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&hdl->vt);
+ if (ret) {
+ free(hdl);
+ hdl = NULL;
+ continue;
+ }
+
+ vtable = hdl->vt;
+ if (vtable.open != NULL) {
+ ret = vtable.open(&auctx);
+ if (ret) {
+ krb5_klog_syslog(LOG_ERR,
+ _("audit plugin %s failed to open. error=%i"),
+ vtable.name, ret);
+ goto cleanup;
+ }
+ hdl->auctx = auctx;
+ }
+ list[count++] = hdl;
+ list[count] = NULL;
+ hdl = NULL;
+ }
+ list[count] = NULL;
+ handles = list;
+ list = NULL;
+ ret = 0;
+
+cleanup:
+ free(hdl);
+ k5_plugin_free_modules(context, modules);
+ free_handles(list);
+ return ret;
+}
+
+/* Free resources allocated by load_audit_modules() function. */
+void
+unload_audit_modules(krb5_context context)
+{
+ free_handles(handles);
+}
+
+/*
+ * Write the output ticket ID into newly-allocated buffer.
+ * Returns 0 on success.
+ */
+krb5_error_code
+kau_make_tkt_id(krb5_context context,
+ const krb5_ticket *ticket, char **out)
+{
+ krb5_error_code ret = 0;
+ char *hash = NULL, *ptr;
+ krb5_checksum cksum;
+ unsigned int i;
+
+ *out = NULL;
+
+ if (ticket == NULL)
+ return EINVAL;
+
+ ret = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, NULL, 0,
+ &ticket->enc_part.ciphertext, &cksum);
+ if (ret)
+ return ret;
+
+ hash = k5alloc(cksum.length * 2 + 1, &ret);
+ if (hash != NULL) {
+ for (i = 0, ptr = hash; i < cksum.length; i++, ptr += 2)
+ snprintf(ptr, 3, "%02X", cksum.contents[i]);
+ *ptr = '\0';
+ *out = hash;
+ }
+ krb5_free_checksum_contents(context, &cksum);
+
+ return 0;
+}
+
+/*
+ * Create and initialize krb5_audit_state structure.
+ * Returns 0 on success.
+ */
+krb5_error_code
+kau_init_kdc_req(krb5_context context,
+ krb5_kdc_req *request, const krb5_fulladdr *from,
+ krb5_audit_state **state_out)
+{
+ krb5_error_code ret = 0;
+ krb5_audit_state *state = NULL;
+
+ state = k5calloc(1, sizeof(*state), &ret);
+ if (state == NULL)
+ return ret;
+
+ state->request = request;
+ state->cl_addr = from->address;
+ state->cl_port = from->port;
+ state->stage = AUTHN_REQ_CL;
+ ret = krb5int_random_string(context, state->req_id,
+ sizeof(state->req_id));
+ if (ret) {
+ free(state);
+ return ret;
+ }
+ *state_out = state;
+
+ return 0;
+}
+
+/* Free resources allocated by kau_init_kdc_req() and kau_make_tkt_id()
+ * routines. */
+void
+kau_free_kdc_req(krb5_audit_state *state)
+{
+ free(state->tkt_in_id);
+ free(state->tkt_out_id);
+ free(state->evid_tkt_id);
+ free(state);
+}
+
+/* Call the KDC start/stop audit plugin entry points. */
+
+void
+kau_kdc_stop(krb5_context context, const krb5_boolean ev_success)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.kdc_stop != NULL)
+ hdl->vt.kdc_stop(hdl->auctx, ev_success);
+ }
+}
+
+void
+kau_kdc_start(krb5_context context, const krb5_boolean ev_success)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.kdc_start != NULL)
+ hdl->vt.kdc_start(hdl->auctx, ev_success);
+ }
+}
+
+/* Call the AS-REQ audit plugin entry point. */
+void
+kau_as_req(krb5_context context, const krb5_boolean ev_success,
+ krb5_audit_state *state)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.as_req != NULL)
+ hdl->vt.as_req(hdl->auctx, ev_success, state);
+ }
+}
+
+/* Call the TGS-REQ audit plugin entry point. */
+void
+kau_tgs_req(krb5_context context, const krb5_boolean ev_success,
+ krb5_audit_state *state)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.tgs_req != NULL)
+ hdl->vt.tgs_req(hdl->auctx, ev_success, state);
+ }
+}
+
+/* Call the S4U2Self audit plugin entry point. */
+void
+kau_s4u2self(krb5_context context, const krb5_boolean ev_success,
+ krb5_audit_state *state)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.tgs_s4u2self != NULL)
+ hdl->vt.tgs_s4u2self(hdl->auctx, ev_success, state);
+ }
+}
+
+/* Call the S4U2Proxy audit plugin entry point. */
+void
+kau_s4u2proxy(krb5_context context,const krb5_boolean ev_success,
+ krb5_audit_state *state)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.tgs_s4u2proxy != NULL)
+ hdl->vt.tgs_s4u2proxy(hdl->auctx, ev_success, state);
+ }
+}
+
+/* Call the U2U audit plugin entry point. */
+void
+kau_u2u(krb5_context context, const krb5_boolean ev_success,
+ krb5_audit_state *state)
+{
+ audit_module_handle *hp, hdl;
+
+ if (handles == NULL)
+ return;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ hdl = *hp;
+ if (hdl->vt.tgs_u2u != NULL)
+ hdl->vt.tgs_u2u(hdl->auctx, ev_success, state);
+ }
+}