Move KDC audit functionality to lib/base/
authorNicolas Williams <nico@twosigma.com>
Tue, 3 Mar 2020 21:24:46 +0000 (15:24 -0600)
committerNicolas Williams <nico@twosigma.com>
Fri, 24 Apr 2020 21:02:35 +0000 (16:02 -0500)
kdc/bx509d.c
kdc/kdc_locl.h
kdc/process.c
lib/base/Makefile.am
lib/base/NTMakefile
lib/base/context.c
lib/base/heimbase-svc.h [new file with mode: 0644]
lib/base/heimbase.h
lib/base/log.c
lib/base/version-script.map

index 2c973268b2d297fccea7973f06de72b890516bb8..5419beb9fc16a4f166072f262c5e2d05bcd0cac4 100644 (file)
 #include "../lib/hx509/hx_locl.h"
 #include <hx509-private.h>
 
+#define heim_pcontext krb5_context
+#define heim_pconfig krb5_kdc_configuration *
+#include <heimbase-svc.h>
+
 struct bx509_request_desc {
-    KDC_REQUEST_DESC_COMMON_ELEMENTS;
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 
     struct MHD_Connection *connection;
     krb5_times token_times;
@@ -802,7 +806,9 @@ set_req_desc(struct MHD_Connection *connection,
     r->request.data = "<HTTP-REQUEST>";
     r->request.length = sizeof("<HTTP-REQUEST>");
     r->from = r->frombuf;
+    r->hcontext = r->context->hcontext;
     r->config = kdc_config;
+    r->logf = kdc_config->logf;
     r->reqtype = url;
     r->target = r->redir = NULL;
     r->pkix_store = NULL;
index 0ec773fda3566d2fc9542e97ec9e424bc74b4c65..faa89f9b96b58acae2db45bfc7ed7b933e693883 100644 (file)
@@ -46,45 +46,25 @@ typedef struct pk_client_params pk_client_params;
 
 #define FAST_EXPIRATION_TIME (3 * 60)
 
-#define KDC_AUDIT_EATWHITE     0x1
-#define KDC_AUDIT_VIS          0x2
-#define KDC_AUDIT_VISLAST      0x4
-
 /* KFE == KDC_FIND_ETYPE */
 #define KFE_IS_TGS     0x1
 #define KFE_IS_PREAUTH 0x2
 #define KFE_USE_CLIENT 0x4
 
-#define KDC_REQUEST_DESC_COMMON_ELEMENTS                       \
-    /* Input */                                                        \
-    krb5_context context;                                      \
-    krb5_kdc_configuration *config;                            \
-    const char *from;                                          \
-    struct sockaddr *addr;                                     \
-    int datagram_reply;                                                \
-    krb5_data request;                                         \
-                                                               \
-    /* Output */                                               \
-    krb5_data *reply;                                          \
-    krb5_boolean use_request_t;                                        \
-                                                               \
-    /* Common state, to be freed in process.c */               \
-    struct timeval tv_start;                                   \
-    struct timeval tv_end;                                     \
-    const char *reqtype;                                       \
-    char *cname;                                               \
-    char *sname;                                               \
-    const char *e_text;                                                \
-    char *e_text_buf;                                          \
-    heim_string_t reason;                                       \
-    heim_array_t kv
+#define heim_pcontext krb5_context
+#define heim_pconfig krb5_kdc_configuration *
+#include <heimbase-svc.h>
+
+#define KDC_AUDIT_EATWHITE      HEIM_SVC_AUDIT_EATWHITE
+#define KDC_AUDIT_VIS           HEIM_SVC_AUDIT_VIS
+#define KDC_AUDIT_VISLAST       HEIM_SVC_AUDIT_VISLAST
 
 struct kdc_request_desc {
-    KDC_REQUEST_DESC_COMMON_ELEMENTS;
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 };
 
 struct astgs_request_desc {
-    KDC_REQUEST_DESC_COMMON_ELEMENTS;
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 
     /* Both AS and TGS */
     KDC_REQ req;
@@ -116,7 +96,7 @@ struct astgs_request_desc {
 };
 
 typedef struct kx509_req_context_desc {
-    KDC_REQUEST_DESC_COMMON_ELEMENTS;
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 
     struct Kx509Request req;
     Kx509CSRPlus csr_plus;
@@ -129,6 +109,8 @@ typedef struct kx509_req_context_desc {
     unsigned int have_csr:1;            /* Client sent a CSR */
 } *kx509_req_context;
 
+#undef heim_pconfig
+#undef heim_pcontext
 
 extern sig_atomic_t exit_flag;
 extern size_t max_request_udp;
index 387e65c5c3f5239aff57368e3e6096b8bacd298d..d130ed70524dbf219006fb75c2552a784b2e8efd 100644 (file)
 #undef  __attribute__
 #define __attribute__(x)
 
-static heim_string_t
-fmtkv(int flags, const char *k, const char *fmt, va_list ap)
-        __attribute__ ((__format__ (__printf__, 3, 0)))
-{
-    heim_string_t str;
-    size_t i,j;
-    char *buf1;
-    char *buf2;
-    char *buf3;
-
-    vasprintf(&buf1, fmt, ap);
-    if (!buf1)
-       return NULL;;
-
-    j = asprintf(&buf2, "%s=%s", k, buf1);
-    free(buf1);
-    if (!buf2)
-       return NULL;;
-
-    /* We optionally eat the whitespace. */
-
-    if (flags & KDC_AUDIT_EATWHITE) {
-       for (i=0, j=0; buf2[i]; i++)
-           if (buf2[i] != ' ' && buf2[i] != '\t')
-               buf2[j++] = buf2[i];
-       buf2[j] = '\0';
-    }
-
-    if (flags & (KDC_AUDIT_VIS | KDC_AUDIT_VISLAST)) {
-        int vis_flags = VIS_CSTYLE | VIS_OCTAL | VIS_NL;
-
-        if (flags & KDC_AUDIT_VIS)
-            vis_flags |= VIS_WHITE;
-       buf3 = malloc((j + 1) * 4 + 1);
-       strvisx(buf3, buf2, j, vis_flags);
-       free(buf2);
-    } else
-       buf3 = buf2;
-
-    str = heim_string_create(buf3);
-    free(buf3);
-    return str;
-}
-
 void
 _kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 2, 0)))
 {
-    heim_string_t str;
-
-    str = fmtkv(KDC_AUDIT_VISLAST, "reason", fmt, ap);
-    if (!str) {
-       kdc_log(r->context, r->config, 1, "failed to add reason");
-        return;
-    }
-
-    kdc_log(r->context, r->config, 7, "_kdc_audit_addreason(): adding "
-            "reason %s", heim_string_get_utf8(str));
-    if (r->reason) {
-        heim_string_t str2;
-
-        str2 = heim_string_create_with_format("%s: %s",
-                                              heim_string_get_utf8(str),
-                                              heim_string_get_utf8(r->reason));
-        if (str2) {
-            heim_release(r->reason);
-            heim_release(str);
-            r->reason = str;
-        } /* else the earlier reason is likely better than the newer one */
-        return;
-    }
-    r->reason = str;
+    heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
 }
 
 void
@@ -123,7 +56,7 @@ _kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
     va_list ap;
 
     va_start(ap, fmt);
-    _kdc_audit_vaddreason(r, fmt, ap);
+    heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
     va_end(ap);
 }
 
@@ -138,18 +71,7 @@ _kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k,
                  const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 4, 0)))
 {
-    heim_string_t str;
-
-    str = fmtkv(flags, k, fmt, ap);
-    if (!str) {
-       kdc_log(r->context, r->config, 1, "failed to add kv pair");
-        return;
-    }
-
-    kdc_log(r->context, r->config, 7, "_kdc_audit_addkv(): adding "
-            "kv pair %s", heim_string_get_utf8(str));
-    heim_array_append_value(r->kv, str);
-    heim_release(str);
+    heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
 }
 
 void
@@ -160,7 +82,7 @@ _kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
     va_list ap;
 
     va_start(ap, fmt);
-    _kdc_audit_vaddkv(r, flags, k, fmt, ap);
+    heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
     va_end(ap);
 }
 
@@ -169,38 +91,16 @@ _kdc_audit_addkv_timediff(kdc_request_t r, const char *k,
                          const struct timeval *start,
                          const struct timeval *end)
 {
-    time_t sec;
-    int usec;
-    const char *sign = "";
-
-    if (end->tv_sec > start->tv_sec ||
-       (end->tv_sec == start->tv_sec && end->tv_usec >= start->tv_usec)) {
-       sec  = end->tv_sec  - start->tv_sec;
-       usec = end->tv_usec - start->tv_usec;
-    } else {
-       sec  = start->tv_sec  - end->tv_sec;
-       usec = start->tv_usec - end->tv_usec;
-       sign = "-";
-    }
-
-    if (usec < 0) {
-       usec += 1000000;
-       sec  -= 1;
-    }
-
-    _kdc_audit_addkv(r, 0, k, "%s%ld.%06d", sign, sec, usec);
+    heim_audit_addkv_timediff((heim_svc_req_desc)r,k, start, end);
 }
 
 void
 _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
 {
-    const char *retval;
-    char kvbuf[1024];
-    char retvalbuf[30]; /* Enough for UNKNOWN-%d */
-    size_t nelem;
-    size_t i, j;
+    const char *retname = NULL;
 
-#define CASE(x)        case x : retval = #x; break
+    /* Get a symbolic name for some error codes */
+#define CASE(x)        case x : retname = #x; break
     switch (ret) {
     CASE(ENOMEM);
     CASE(EACCES);
@@ -231,49 +131,20 @@ _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
     CASE(KRB5KDC_ERR_TRTYPE_NOSUPP);
     CASE(KRB5KRB_ERR_RESPONSE_TOO_BIG);
     case 0:
-       retval = "SUCCESS";
+       retname = "SUCCESS";
        break;
     default:
-        (void) snprintf(retvalbuf, sizeof(retvalbuf), "UNKNOWN-%d", ret);
-       retval = retvalbuf;
+        retname = NULL;
        break;
     }
 
     /* Let's save a few bytes */
 #define PREFIX "KRB5KDC_"
-    if (!strncmp(PREFIX, retval, strlen(PREFIX)))
-       retval += strlen(PREFIX);
+    if (retname && !strncmp(PREFIX, retname, strlen(PREFIX)))
+       retname += strlen(PREFIX);
 #undef PREFIX
 
-    /* Calculate metrics and add them */
-
-    _kdc_audit_addkv_timediff(r, "elapsed", &r->tv_start, &r->tv_end);
-
-    if (r->e_text)
-       _kdc_audit_addkv(r, KDC_AUDIT_VIS, "e-text", "%s", r->e_text);
-
-    nelem = heim_array_get_length(r->kv);
-    for (i=0, j=0; i < nelem; i++) {
-       heim_string_t s;
-       const char *kvpair;
-
-       s = heim_array_get_value(r->kv, i);
-       /* XXXrcd: in string.c the check? */
-       kvpair = heim_string_get_utf8(s);
-
-       if (j < sizeof(kvbuf) - 1)
-           kvbuf[j++] = ' ';
-       for (; *kvpair && j < sizeof(kvbuf) - 1; j++)
-           kvbuf[j] = *kvpair++;
-    }
-    kvbuf[j] = '\0';
-
-    kdc_log(r->context, r->config, 3, "%s %s %s %s %s%s%s%s",
-           r->reqtype, retval, r->from,
-            r->cname ? r->cname : "<unknown>",
-           r->sname ? r->sname : "<unknown>",
-            kvbuf, r->reason ? " " : "",
-            r->reason ? heim_string_get_utf8(r->reason) : "");
+    heim_audit_trail((heim_svc_req_desc)r, ret, retname);
 }
 
 void
@@ -430,7 +301,9 @@ process_request(krb5_context context,
        return krb5_enomem(context);
 
     r->context = context;
+    r->hcontext = context->hcontext;
     r->config = config;
+    r->logf = config->logf;
     r->from = from;
     r->request.data = buf;
     r->request.length = len;
index 9483a72e79bb7c94c9afaebfd51bf9393b0f9269..3a462caf799e22845b192b49c43a5b698b56999c 100644 (file)
@@ -30,7 +30,7 @@ endif
 
 libheimbase_la_LIBADD = $(PTHREAD_LIBADD) $(LIB_dlopen) $(LIB_com_err)
 
-include_HEADERS        = heimbase.h common_plugin.h
+include_HEADERS        = heimbase.h common_plugin.h heimbase-svc.h
 
 ERR_FILES = heim_err.c
 
index 71466779c326a54ea0097aa547622ef80e0b5f04..2b40715a00c10b19539ece5ab1e72460196affe6 100644 (file)
@@ -38,6 +38,7 @@ intcflags=-I$(SRCDIR) -I$(OBJ)
 INCFILES=                              \
        $(INCDIR)\heimbase.h            \
        $(INCDIR)\heimbase-protos.h     \
+       $(INCDIR)\heimbase-svc.h        \
        $(INCDIR)\heim_err.h            \
        $(INCDIR)\common_plugin.h
 
index c116c6269d39e9ebc4be4795a206ddab8353eb88..ee55adc606b07f02845d1cec96d18e5056b57d6f 100644 (file)
@@ -37,7 +37,8 @@
 #define __attribute__(X)
 
 struct heim_context_s {
-    heim_log_facility       *warn_dest; /* XXX Move warn.c into lib/base as well */
+    heim_log_facility       *log_dest;
+    heim_log_facility       *warn_dest;
     heim_log_facility       *debug_dest;
     char                    *time_fmt;
     unsigned int            log_utc:1;
@@ -69,6 +70,7 @@ heim_context_init(void)
     context->success = "Success";
     context->debug_dest = NULL;
     context->warn_dest = NULL;
+    context->log_dest = NULL;
     context->time_fmt = NULL;
     return context;
 }
@@ -83,6 +85,7 @@ heim_context_free(heim_context *contextp)
         return;
     heim_closelog(context, context->debug_dest);
     heim_closelog(context, context->warn_dest);
+    heim_closelog(context, context->log_dest);
     free(context->time_fmt);
     free(context);
 }
@@ -207,6 +210,12 @@ heim_enomem(heim_context context)
     return ENOMEM;
 }
 
+heim_log_facility *
+heim_get_log_dest(heim_context context)
+{
+    return context->log_dest;
+}
+
 heim_log_facility *
 heim_get_warn_dest(heim_context context)
 {
@@ -219,6 +228,13 @@ heim_get_debug_dest(heim_context context)
     return context->debug_dest;
 }
 
+heim_error_code
+heim_set_log_dest(heim_context context, heim_log_facility *fac)
+{
+    context->log_dest = fac;
+    return 0;
+}
+
 heim_error_code
 heim_set_warn_dest(heim_context context, heim_log_facility *fac)
 {
diff --git a/lib/base/heimbase-svc.h b/lib/base/heimbase-svc.h
new file mode 100644 (file)
index 0000000..6e7eb5f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifndef HEIMBASE_SVC_H
+#define HEIMBASE_SVC_H 1
+
+/*
+ * This file is meant to be included in services, which can
+ *
+ *  #define heim_pcontext krb5_context
+ *
+ * or whatever is appropriate.
+ */
+
+#define HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS                   \
+    /* Input */                                                 \
+    heim_pcontext context;                                      \
+    heim_pconfig config;                                        \
+    heim_context hcontext;                                      \
+    heim_log_facility *logf;                                    \
+    const char *from;                                           \
+    struct sockaddr *addr;                                      \
+    int datagram_reply;                                         \
+    heim_octet_string request;                                  \
+                                                                \
+    /* Output */                                                \
+    heim_octet_string *reply;                                   \
+    unsigned int use_request_t:1;                               \
+                                                                \
+    /* Common state, to be freed in process.c */                \
+    struct timeval tv_start;                                    \
+    struct timeval tv_end;                                      \
+    const char *reqtype;                                        \
+    char *cname;                                                \
+    char *sname;                                                \
+    const char *e_text;                                         \
+    char *e_text_buf;                                           \
+    heim_string_t reason;                                       \
+    heim_array_t kv
+
+#endif /* HEIMBASE_SVC_H */
index d0d397c28de15212e1ced4910ef313c3eadceb13..16f40c81990a0de72adb8116c2553ab0e03dafa2 100644 (file)
 #include "config.h"
 
 #include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#endif
 #if !defined(WIN32) && !defined(HAVE_DISPATCH_DISPATCH_H) && defined(ENABLE_PTHREAD_SUPPORT)
 #include <pthread.h>
 #endif
 #include <krb5-types.h>
 #include <stdarg.h>
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
 #ifdef HAVE_STDBOOL_H
 #include <stdbool.h>
 #else
 
 #define HEIM_BASE_API_VERSION 20130210
 
+/*
+ * Generic facilities (moved from lib/krb5/.
+ */
+
 typedef int32_t heim_error_code;
 typedef struct heim_context_s *heim_context;
 typedef struct heim_pcontext_s *heim_pcontext;
@@ -91,7 +101,6 @@ struct heim_log_facility_internal {
     void *data;
 };
 
-
 typedef struct heim_log_facility_s {
     char *program;
     int len;
@@ -138,6 +147,10 @@ struct heim_config_binding {
 };
 typedef struct heim_config_binding heim_config_section;
 
+/*
+ * CF-like, JSON APIs
+ */
+
 typedef void * heim_object_t;
 typedef unsigned int heim_tid_t;
 typedef heim_object_t heim_bool_t;
@@ -654,6 +667,18 @@ heim_base_exchange_pointer(void *target, void *value)
 #endif
 
 #include <heim_threads.h>
+#include <com_err.h>
+
+/*
+ * Service logging facility (moved from kdc/).
+ */
+
+#define HEIM_SVC_AUDIT_EATWHITE      0x1
+#define HEIM_SVC_AUDIT_VIS           0x2
+#define HEIM_SVC_AUDIT_VISLAST       0x4
+
+typedef struct heim_svc_req_desc_common_s *heim_svc_req_desc;
+
 #include <heimbase-protos.h>
 
 #endif /* HEIM_BASE_H */
index 6b6df2b3cc7a98a58b08e3ed0d5d0c66b545ec0d..bc987a860131eda06914269ce844b5819ea30966 100644 (file)
 
 #include "baselocl.h"
 #include "heim_threads.h"
+#include "heimbase-svc.h"
 #include <assert.h>
 #include <stdarg.h>
 #include <vis.h>
 
+typedef struct heim_pcontext_s *heim_pcontext;
+typedef struct heim_pconfig *heim_pconfig;
+struct heim_svc_req_desc_common_s {
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
+};
+
 static struct heim_log_facility_internal *
 log_realloc(heim_log_facility *f)
 {
@@ -624,3 +631,208 @@ heim_add_debug_dest(heim_context context, const char *program,
         return ret;
     return 0;
 }
+
+static heim_string_t
+fmtkv(int flags, const char *k, const char *fmt, va_list ap)
+        __attribute__ ((__format__ (__printf__, 3, 0)))
+{
+    heim_string_t str;
+    size_t i,j;
+    char *buf1;
+    char *buf2;
+    char *buf3;
+
+    vasprintf(&buf1, fmt, ap);
+    if (!buf1)
+       return NULL;;
+
+    j = asprintf(&buf2, "%s=%s", k, buf1);
+    free(buf1);
+    if (!buf2)
+       return NULL;;
+
+    /* We optionally eat the whitespace. */
+
+    if (flags & HEIM_SVC_AUDIT_EATWHITE) {
+       for (i=0, j=0; buf2[i]; i++)
+           if (buf2[i] != ' ' && buf2[i] != '\t')
+               buf2[j++] = buf2[i];
+       buf2[j] = '\0';
+    }
+
+    if (flags & (HEIM_SVC_AUDIT_VIS | HEIM_SVC_AUDIT_VISLAST)) {
+        int vis_flags = VIS_CSTYLE | VIS_OCTAL | VIS_NL;
+
+        if (flags & HEIM_SVC_AUDIT_VIS)
+            vis_flags |= VIS_WHITE;
+       buf3 = malloc((j + 1) * 4 + 1);
+       strvisx(buf3, buf2, j, vis_flags);
+       free(buf2);
+    } else
+       buf3 = buf2;
+
+    str = heim_string_create(buf3);
+    free(buf3);
+    return str;
+}
+
+void
+heim_audit_vaddreason(heim_svc_req_desc r, const char *fmt, va_list ap)
+       __attribute__ ((__format__ (__printf__, 2, 0)))
+{
+    heim_string_t str;
+
+    str = fmtkv(HEIM_SVC_AUDIT_VISLAST, "reason", fmt, ap);
+    if (!str) {
+        heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddreason: "
+                 "failed to add reason (out of memory)");
+        return;
+    }
+
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddreason(): "
+             "adding reason %s", heim_string_get_utf8(str));
+    if (r->reason) {
+        heim_string_t str2;
+
+        str2 = heim_string_create_with_format("%s: %s",
+                                              heim_string_get_utf8(str),
+                                              heim_string_get_utf8(r->reason));
+        if (str2) {
+            heim_release(r->reason);
+            heim_release(str);
+            r->reason = str;
+        } /* else the earlier reason is likely better than the newer one */
+        return;
+    }
+    r->reason = str;
+}
+
+void
+heim_audit_addreason(heim_svc_req_desc r, const char *fmt, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)))
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    heim_audit_vaddreason(r, fmt, ap);
+    va_end(ap);
+}
+
+/*
+ * append_token adds a token which is optionally a kv-pair and it
+ * also optionally eats the whitespace.  If k == NULL, then it's
+ * not a kv-pair.
+ */
+
+void
+heim_audit_vaddkv(heim_svc_req_desc r, int flags, const char *k,
+                 const char *fmt, va_list ap)
+       __attribute__ ((__format__ (__printf__, 4, 0)))
+{
+    heim_string_t str;
+
+    str = fmtkv(flags, k, fmt, ap);
+    if (!str) {
+        heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddkv: "
+                 "failed to add kv pair (out of memory)");
+        return;
+    }
+
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddkv(): "
+             "adding kv pair %s", heim_string_get_utf8(str));
+    heim_array_append_value(r->kv, str);
+    heim_release(str);
+}
+
+void
+heim_audit_addkv(heim_svc_req_desc r, int flags, const char *k,
+                const char *fmt, ...)
+       __attribute__ ((__format__ (__printf__, 4, 5)))
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    heim_audit_vaddkv(r, flags, k, fmt, ap);
+    va_end(ap);
+}
+
+void
+heim_audit_addkv_timediff(heim_svc_req_desc r, const char *k,
+                         const struct timeval *start,
+                         const struct timeval *end)
+{
+    time_t sec;
+    int usec;
+    const char *sign = "";
+
+    if (end->tv_sec > start->tv_sec ||
+       (end->tv_sec == start->tv_sec && end->tv_usec >= start->tv_usec)) {
+       sec  = end->tv_sec  - start->tv_sec;
+       usec = end->tv_usec - start->tv_usec;
+    } else {
+       sec  = start->tv_sec  - end->tv_sec;
+       usec = start->tv_usec - end->tv_usec;
+       sign = "-";
+    }
+
+    if (usec < 0) {
+       usec += 1000000;
+       sec  -= 1;
+    }
+
+    heim_audit_addkv(r, 0, k, "%s%ld.%06d", sign, sec, usec);
+}
+
+void
+heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname)
+{
+    const char *retval;
+    char kvbuf[1024];
+    char retvalbuf[30]; /* Enough for UNKNOWN-%d */
+    size_t nelem;
+    size_t i, j;
+
+#define CASE(x)        case x : retval = #x; break
+    if (retname) {
+        retval = retname;
+    } else switch (ret) {
+    CASE(ENOMEM);
+    CASE(ENOENT);
+    CASE(EACCES);
+    case 0:
+       retval = "SUCCESS";
+       break;
+    default:
+        /* Wish we had a com_err number->symbolic name function */
+        (void) snprintf(retvalbuf, sizeof(retvalbuf), "UNKNOWN-%d", ret);
+       retval = retvalbuf;
+       break;
+    }
+
+    heim_audit_addkv_timediff(r, "elapsed", &r->tv_start, &r->tv_end);
+    if (r->e_text)
+       heim_audit_addkv(r, HEIM_SVC_AUDIT_VIS, "e-text", "%s", r->e_text);
+
+    nelem = heim_array_get_length(r->kv);
+    for (i=0, j=0; i < nelem; i++) {
+       heim_string_t s;
+       const char *kvpair;
+
+        /* We know these are strings... */
+       s = heim_array_get_value(r->kv, i);
+       kvpair = heim_string_get_utf8(s);
+
+       if (j < sizeof(kvbuf) - 1)
+           kvbuf[j++] = ' ';
+       for (; *kvpair && j < sizeof(kvbuf) - 1; j++)
+           kvbuf[j] = *kvpair++;
+    }
+    kvbuf[j] = '\0';
+
+    heim_log(r->hcontext, r->logf, 3, "%s %s %s %s %s%s%s%s",
+             r->reqtype, retval, r->from,
+             r->cname ? r->cname : "<unknown>",
+             r->sname ? r->sname : "<unknown>",
+             kvbuf, r->reason ? " " : "",
+             r->reason ? heim_string_get_utf8(r->reason) : "");
+}
index e541435343cc1fd91f08b6b545f45d69c6106447..ecf2e7d4cfc70b389549403011d5af6bf8ab0648 100644 (file)
@@ -27,6 +27,12 @@ HEIMDAL_BASE_1.0 {
                heim_array_iterate_f;
                heim_array_iterate_reverse_f;
                heim_array_set_value;
+               heim_audit_addkv;
+               heim_audit_addkv_timediff;
+               heim_audit_addreason;
+               heim_audit_trail;
+               heim_audit_vaddkv;
+               heim_audit_vaddreason;
                heim_auto_release;
                heim_auto_release_create;
                heim_auto_release_drain;
@@ -124,6 +130,7 @@ HEIMDAL_BASE_1.0 {
                heim_get_hash;
                _heim_get_isa;
                _heim_get_isaextra;
+               heim_get_log_dest;
                heim_get_tid;
                heim_get_warn_dest;
                heim_have_debug;
@@ -158,6 +165,7 @@ HEIMDAL_BASE_1.0 {
                heim_set_config_files;
                heim_set_debug_dest;
                heim_set_error_message;
+               heim_set_log_dest;
                heim_set_warn_dest;
                heim_show;
                heim_sorted_text_file_dbtype;