diff options
Diffstat (limited to 'src/plugins/audit')
-rw-r--r-- | src/plugins/audit/Makefile.in | 22 | ||||
-rw-r--r-- | src/plugins/audit/deps | 15 | ||||
-rw-r--r-- | src/plugins/audit/j_dict.h | 88 | ||||
-rwxr-xr-x | src/plugins/audit/kdc_j_encode.c | 934 | ||||
-rw-r--r-- | src/plugins/audit/kdc_j_encode.h | 66 | ||||
-rw-r--r-- | src/plugins/audit/libauditjenc.exports | 7 | ||||
-rw-r--r-- | src/plugins/audit/simple/Makefile.in | 27 | ||||
-rw-r--r-- | src/plugins/audit/simple/au_simple_main.c | 263 | ||||
-rw-r--r-- | src/plugins/audit/simple/deps | 15 | ||||
-rw-r--r-- | src/plugins/audit/simple/k5audit.exports | 1 | ||||
-rw-r--r-- | src/plugins/audit/test/Makefile.in | 21 | ||||
-rw-r--r-- | src/plugins/audit/test/au_test.c | 228 | ||||
-rw-r--r-- | src/plugins/audit/test/deps | 14 | ||||
-rw-r--r-- | src/plugins/audit/test/k5audit_test.exports | 1 |
14 files changed, 1702 insertions, 0 deletions
diff --git a/src/plugins/audit/Makefile.in b/src/plugins/audit/Makefile.in new file mode 100644 index 0000000..812af60 --- /dev/null +++ b/src/plugins/audit/Makefile.in @@ -0,0 +1,22 @@ +mydir=plugins$(S)audit +BUILDTOP=$(REL)..$(S).. + +STLIBOBJS=kdc_j_encode.o +LIBOBJS=$(OUTPRE)kdc_j_encode.$(OBJEXT) +SRCS=kdc_j_encode.c + +AUJENC_HDR=$(BUILDTOP)$(S)include$(S)kdc_j_encode.h + +all-unix:: all-libobjs includes + +clean-unix:: clean-libobjs + $(RM) $(AUJENC_HDR) + +includes:: $(AUJENC_HDR) +depend:: $(AUJENC_HDR) + +$(AUJENC_HDR): $(srcdir)/kdc_j_encode.h + $(RM) $@ + $(CP) $(srcdir)/kdc_j_encode.h $@ + +@libobj_frag@ diff --git a/src/plugins/audit/deps b/src/plugins/audit/deps new file mode 100644 index 0000000..e2efc84 --- /dev/null +++ b/src/plugins/audit/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +kdc_j_encode.so kdc_j_encode.po $(OUTPRE)kdc_j_encode.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/audit_plugin.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + j_dict.h kdc_j_encode.c kdc_j_encode.h diff --git a/src/plugins/audit/j_dict.h b/src/plugins/audit/j_dict.h new file mode 100644 index 0000000..2ca48b0 --- /dev/null +++ b/src/plugins/audit/j_dict.h @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* j_dict.h - Dictionary file for json implementation of audit system */ +/* + * 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. + */ + +#ifndef KRB5_J_DICT_H_INCLUDED +#define KRB5_J_DICT_H_INCLUDED + +/* Dictionary for KDC events */ +#define AU_STAGE "stage" +#define AU_EVENT_NAME "event_name" +#define AU_EVENT_STATUS "event_success" +#define AU_TKT_IN_ID "tkt_in_id" +#define AU_TKT_OUT_ID "tkt_out_id" +#define AU_REQ_ID "req_id" +#define AU_KDC_STATUS "kdc_status" +#define AU_FROMPORT "fromport" +#define AU_FROMADDR "fromaddr" +#define AU_TYPE "type" /* used by fromaddr */ +#define AU_IPV4 "ipv4" /* used by fromaddr */ +#define AU_SESS_ETYPE "sess_etype" +#define AU_SRV_ETYPE "srv_etype" +#define AU_REP_ETYPE "rep_etype" +#define AU_REALM "realm" +#define AU_LENGTH "length" +#define AU_COMPONENTS "components" +#define AU_TKT_RENEWED "tkt_renewed" +#define AU_TKT_VALIDATED "tkt_validated" +/* referrals */ +#define AU_CREF_REALM "clreferral_realm" +/* request */ +#define AU_REQ_KDC_OPTIONS "req.kdc_options" +#define AU_REQ_SERVER "req.server" +#define AU_REQ_CLIENT "req.client" +#define AU_REQ_AVAIL_ETYPES "req.avail_etypes" +#define AU_EVIDENCE_TKT "evidence_tkt" +#define AU_REQ_ADDRESSES "req.addresses" +#define AU_REQ_TKT_START "req.tkt_start" +#define AU_REQ_TKT_END "req.tkt_end" +#define AU_REQ_TKT_RENEW_TILL "req.tkt_renew_till" +#define AU_REQ_PA_TYPE "req.pa_type" +/* reply */ +#define AU_REP_TICKET "rep.ticket" +#define AU_REP_PA_TYPE "rep.pa_type" +/* ticket */ +#define AU_SNAME "sname" +#define AU_CNAME "cname" +#define AU_FLAGS "flags" +#define AU_START "start" +#define AU_END "end" +#define AU_RENEW_TILL "renew_till" +#define AU_AUTHTIME "authtime" +#define AU_TR_CONTENTS "tr_contents" +#define AU_CADDRS "caddrs" +/* S4U and U2U */ +#define AU_VIOLATION "violation" /* policy or protocol restrictions */ +#define AU_REQ_S4U2S_USER "s4u2self_user" +#define AU_REQ_S4U2P_USER "s4u2proxy_user" +#define AU_REQ_U2U_USER "u2u_user" +#define AU_EVIDENCE_TKT_ID "evidence_tkt_id" /* 2nd ticket in s4u2proxy req */ +#endif /* KRB5_J_DICT_H_INCLUDED */ diff --git a/src/plugins/audit/kdc_j_encode.c b/src/plugins/audit/kdc_j_encode.c new file mode 100755 index 0000000..da5a9d8 --- /dev/null +++ b/src/plugins/audit/kdc_j_encode.c @@ -0,0 +1,934 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/audit/kdc_j_encode.c - Utilities to json encode KDC audit stuff */ +/* + * 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 <syslog.h> +#include <k5-int.h> +#include <k5-json.h> +#include "kdc_j_encode.h" +#include "j_dict.h" +#include <krb5/audit_plugin.h> + +static krb5_error_code +string_to_value(const char *in, k5_json_object obj, const char *key); +static krb5_error_code +princ_to_value(krb5_principal princ, k5_json_object obj, const char *key); +static krb5_error_code +data_to_value(krb5_data *data, k5_json_object obj, const char *key); +static krb5_error_code +int32_to_value(krb5_int32 int32, k5_json_object obj, const char *key); +static krb5_error_code +bool_to_value(krb5_boolean b, k5_json_object obj, const char *key); +static krb5_error_code +addr_to_obj(krb5_address *a, k5_json_object obj); +static krb5_error_code +eventinfo_to_value(k5_json_object obj, const char *name, + const int stage, const krb5_boolean ev_success); +static krb5_error_code +addr_to_value(const krb5_address *address, k5_json_object obj, + const char *key); +static krb5_error_code +req_to_value(krb5_kdc_req *req, const krb5_boolean ev_success, + k5_json_object obj); +static krb5_error_code +rep_to_value(krb5_kdc_rep *rep, const krb5_boolean ev_success, + k5_json_object obj); +static krb5_error_code +tkt_to_value(krb5_ticket *tkt, k5_json_object obj, const char *key); +static char *map_patype(krb5_preauthtype pa_type); + +#define NULL_STATE "state is NULL" +#define T_RENEWED 1 +#define T_NOT_RENEWED 2 +#define T_VALIDATED 1 +#define T_NOT_VALIDATED 2 + +/* KDC server STOP. Returns 0 on success. */ +krb5_error_code +kau_j_kdc_stop(const krb5_boolean ev_success, char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + + *jout = NULL; + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + + /* Audit event_ID and ev_success. */ + ret = string_to_value("KDC_STOP", obj, AU_EVENT_NAME); + if (!ret) + ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS); + if (!ret) + ret = k5_json_encode(obj, jout); + k5_json_release(obj); + + return ret; +} + +/* KDC server START. Returns 0 on success. */ +krb5_error_code +kau_j_kdc_start(const krb5_boolean ev_success, char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + + *jout = NULL; + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + + /* Audit event_ID and ev_success. */ + ret = string_to_value("KDC_START", obj, AU_EVENT_NAME); + if (!ret) + ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS); + if (!ret) + ret = k5_json_encode(obj, jout); + k5_json_release(obj); + + return ret; +} + +/* AS-REQ. Returns 0 on success. */ +krb5_error_code +kau_j_as_req(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + + *jout = NULL; + + if (!state) { + *jout = NULL_STATE; + return 0; + } + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + /* Audit event_ID and ev_success. */ + ret = eventinfo_to_value(obj, "AS_REQ", state->stage, ev_success); + if (ret) + goto error; + /* TGT ticket ID */ + ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID); + if (ret) + goto error; + /* Request ID. */ + ret = string_to_value(state->req_id, obj, AU_REQ_ID); + if (ret) + goto error; + /* Client's port and address. */ + ret = int32_to_value(state->cl_port, obj, AU_FROMPORT); + if (ret) + goto error; + ret = addr_to_value(state->cl_addr, obj, AU_FROMADDR); + if (ret) + goto error; + /* KDC status msg */ + ret = string_to_value(state->status, obj, AU_KDC_STATUS); + if (ret) + goto error; + /* non-local client's referral realm. */ + ret = data_to_value(state->cl_realm, obj, AU_CREF_REALM); + if (ret) + goto error; + /* Request. */ + ret = req_to_value(state->request, ev_success, obj); + if (ret == ENOMEM) + goto error; + /* Reply/ticket info. */ + ret = rep_to_value(state->reply, ev_success, obj); + if (ret == ENOMEM) + goto error; + ret = k5_json_encode(obj, jout); + +error: + k5_json_release(obj); + return ret; +} + +/* TGS-REQ. Returns 0 on success. */ +krb5_error_code +kau_j_tgs_req(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + krb5_kdc_req *req = state->request; + int tkt_validated = 0, tkt_renewed = 0; + + *jout = NULL; + + if (!state) { + *jout = NULL_STATE; + return 0; + } + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + + /* Audit Event ID and ev_success. */ + ret = eventinfo_to_value(obj, "TGS_REQ", state->stage, ev_success); + if (ret) + goto error; + /* Primary and derived ticket IDs. */ + ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID); + if (ret) + goto error; + ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID); + if (ret) + goto error; + /* Request ID */ + ret = string_to_value(state->req_id, obj, AU_REQ_ID); + if (ret) + goto error; + /* client’s address and port. */ + ret = int32_to_value(state->cl_port, obj, AU_FROMPORT); + if (ret) + goto error; + ret = addr_to_value(state->cl_addr, obj, AU_FROMADDR); + if (ret) + goto error; + /* Ticket was renewed, validated. */ + if ((ev_success == TRUE) && (req != NULL)) { + tkt_renewed = (req->kdc_options & KDC_OPT_RENEW) ? + T_RENEWED : T_NOT_RENEWED; + tkt_validated = (req->kdc_options & KDC_OPT_VALIDATE) ? + T_VALIDATED : T_NOT_VALIDATED; + } + ret = int32_to_value(tkt_renewed, obj, AU_TKT_RENEWED); + if (ret) + goto error; + ret = int32_to_value(tkt_validated, obj, AU_TKT_VALIDATED); + if (ret) + goto error; + /* KDC status msg, including "ISSUE". */ + ret = string_to_value(state->status, obj, AU_KDC_STATUS); + if (ret) + goto error; + /* request */ + ret = req_to_value(req, ev_success, obj); + if (ret == ENOMEM) + goto error; + /* reply/ticket */ + ret = rep_to_value(state->reply, ev_success, obj); + if (ret == ENOMEM) + goto error; + ret = k5_json_encode(obj, jout); + +error: + k5_json_release(obj); + return ret; +} + +/* S4U2Self protocol extension. Returns 0 on success. */ +krb5_error_code +kau_j_tgs_s4u2self(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + + *jout = NULL; + + if (!state) { + *jout = NULL_STATE; + return 0; + } + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + + /* Audit Event ID and ev_success. */ + ret = eventinfo_to_value(obj, "S4U2SELF", state->stage, ev_success); + if (ret) + goto error; + /* Front-end server's TGT ticket ID. */ + ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID); + if (ret) + goto error; + /* service "to self" ticket or referral TGT ticket ID. */ + ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID); + if (ret) + goto error; + /* Request ID. */ + ret = string_to_value(state->req_id, obj, AU_REQ_ID); + if (ret) + goto error; + if (ev_success == FALSE) { + /* KDC status msg. */ + ret = string_to_value(state->status, obj, AU_KDC_STATUS); + if (ret) + goto error; + /* Local policy or S4U protocol constraints. */ + ret = int32_to_value(state->violation, obj, AU_VIOLATION); + if (ret) + goto error; + } + /* Impersonated user. */ + ret = princ_to_value(state->s4u2self_user, obj, AU_REQ_S4U2S_USER); + if (ret) + goto error; + + ret = k5_json_encode(obj, jout); + +error: + k5_json_release(obj); + return ret; +} + +/* S4U2Proxy protocol extension. Returns 0 on success. */ +krb5_error_code +kau_j_tgs_s4u2proxy(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + krb5_kdc_req *req = state->request; + + *jout = NULL; + + if (!state) { + *jout = NULL_STATE; + return 0; + } + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + + /* Audit Event ID and ev_success. */ + ret = eventinfo_to_value(obj, "S4U2PROXY", state->stage, ev_success); + if (ret) + goto error; + /* Front-end server's TGT ticket ID. */ + ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID); + if (ret) + goto error; + /* Resource service or referral TGT ticket ID. */ + ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID); + if (ret) + goto error; + /* User's evidence ticket ID. */ + ret = string_to_value(state->evid_tkt_id, obj, AU_EVIDENCE_TKT_ID); + if (ret) + goto error; + /* Request ID. */ + ret = string_to_value(state->req_id, obj, AU_REQ_ID); + if (ret) + goto error; + + if (ev_success == FALSE) { + /* KDC status msg. */ + ret = string_to_value(state->status, obj, AU_KDC_STATUS); + if (ret) + goto error; + /* Local policy or S4U protocol constraints. */ + ret = int32_to_value(state->violation, obj, AU_VIOLATION); + if (ret) + goto error; + } + /* Delegated user. */ + if (req != NULL) { + ret = princ_to_value(req->second_ticket[0]->enc_part2->client, + obj, AU_REQ_S4U2P_USER); + if (ret) + goto error; + } + ret = k5_json_encode(obj, jout); + +error: + k5_json_release(obj); + return ret; +} + +/* U2U. Returns 0 on success. */ +krb5_error_code +kau_j_tgs_u2u(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout) +{ + krb5_error_code ret = 0; + k5_json_object obj = NULL; + krb5_kdc_req *req = state->request; + + if (!state) { + *jout = NULL_STATE; + return 0; + } + + *jout = NULL; + + /* Main object. */ + if (k5_json_object_create(&obj)) + return ENOMEM; + /* Audit Event ID and ev_success. */ + ret = eventinfo_to_value(obj, "U2U", state->stage, ev_success); + if (ret) + goto error; + /* Front-end server's TGT ticket ID. */ + ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID); + if (ret) + goto error; + /* Service ticket ID. */ + ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID); + if (ret) + goto error; + /* Request ID. */ + ret = string_to_value(state->req_id, obj, AU_REQ_ID); + if (ret) + goto error; + + if (ev_success == FALSE) { + /* KDC status msg. */ + ret = string_to_value(state->status, obj, AU_KDC_STATUS); + if (ret) + goto error; + } + /* Client in the second ticket. */ + if (req != NULL) { + ret = princ_to_value(req->second_ticket[0]->enc_part2->client, + obj, AU_REQ_U2U_USER); + if (ret) + goto error; + } + /* Enctype of a session key of the second ticket. */ + ret = int32_to_value(req->second_ticket[0]->enc_part2->session->enctype, + obj, AU_SRV_ETYPE); + if (ret) + goto error; + + ret = k5_json_encode(obj, jout); + +error: + k5_json_release(obj); + return ret; +} + +/* Low level utilities */ + +/* Converts string into a property of a JSON object. Returns 0 on success.*/ +static krb5_error_code +string_to_value(const char *in, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_string str = NULL; + + if (in == NULL) + return 0; + + ret = k5_json_string_create(in, &str); + if (ret) + return ret; + ret = k5_json_object_set(obj, key, str); + k5_json_release(str); + + return ret; +} + +/* + * Converts a krb5_data struct into a property of a JSON object. + * (Borrowed from preauth_otp.c) + * Returns 0 on success. + */ +static krb5_error_code +data_to_value(krb5_data *data, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_string str = NULL; + + if (data == NULL || data->data == NULL || data->length < 1) + return 0; + + ret = k5_json_string_create_len(data->data, data->length, &str); + if (ret) + return ret; + ret = k5_json_object_set(obj, key, str); + k5_json_release(str); + + return ret; +} + +/* + * Converts krb5_int32 into a property of a JSON object. + * Returns 0 on success. + */ +static krb5_error_code +int32_to_value(krb5_int32 int32, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_number num = NULL; + + ret = k5_json_number_create(int32, &num); + if (ret) + return ENOMEM; + ret = k5_json_object_set(obj, key, num); + k5_json_release(num); + + return ret; +} + +/* + * Converts krb5_boolean into a property of a JSON object. + * Returns 0 on success. + */ +static krb5_error_code +bool_to_value(krb5_boolean in, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_bool b = 0; + + ret = k5_json_bool_create(in, &b); + if (ret) + return ENOMEM; + + ret = k5_json_object_set(obj, key, b); + k5_json_release(b); + + return ret; +} + +/* Wrapper-level utilities */ + +/* Wrapper for stage and event_status tags. Returns 0 on success. */ +static krb5_error_code +eventinfo_to_value(k5_json_object obj, const char *name, + const int stage, const krb5_boolean ev_success) +{ + krb5_error_code ret = 0; + + ret = string_to_value(name, obj, AU_EVENT_NAME); + if (ret) + return ret; + ret = int32_to_value(stage, obj, AU_STAGE); + if (!ret) + ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS); + + return ret; +} + +/* + * Converts krb5_principal into a property of a JSON object. + * Returns 0 on success. + */ +static krb5_error_code +princ_to_value(krb5_principal princ, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_object tmp = NULL; + k5_json_array arr = NULL; + k5_json_string str = NULL; + int i = 0; + + if (princ == NULL || princ->data == NULL) + return 0; + + /* Main object. */ + if (k5_json_object_create(&tmp)) + return ENOMEM; + + ret = k5_json_array_create(&arr); + if (ret) + goto error; + for (i = 0; i < princ->length; i++) { + ret = k5_json_string_create_len((&princ->data[i])->data, + (&princ->data[i])->length, &str); + if (ret) + goto error; + ret = k5_json_array_add(arr, str); + k5_json_release(str); + if (ret) + goto error; + } + ret = k5_json_object_set(tmp, AU_COMPONENTS, arr); + if (ret) + goto error; + ret = data_to_value(&princ->realm, tmp, AU_REALM); + if (ret) + goto error; + ret = int32_to_value(princ->length, tmp, AU_LENGTH); + if (ret) + goto error; + ret = int32_to_value(princ->type, tmp, AU_TYPE); + if (ret) + goto error; + + ret = k5_json_object_set(obj, key, tmp); + +error: + k5_json_release(tmp); + k5_json_release(arr); + return ret; +} + +/* + * Helper for JSON encoding of krb5_address. + * Returns 0 on success. + */ +static krb5_error_code +addr_to_obj(krb5_address *a, k5_json_object obj) +{ + krb5_error_code ret = 0; + k5_json_number num = NULL; + k5_json_array arr = NULL; + int i; + + if (a == NULL || a->contents == NULL || a->length <= 0) + return 0; + + ret = int32_to_value(a->addrtype, obj, AU_TYPE); + if (ret) + goto error; + ret = int32_to_value(a->length, obj, AU_LENGTH); + if (ret) + goto error; + + if (a->addrtype == ADDRTYPE_INET) { + ret = k5_json_array_create(&arr); + if (ret) + goto error; + for (i = 0; i < (int)a->length; i++) { + ret = k5_json_number_create(a->contents[i], &num); + if (ret) + goto error; + ret = k5_json_array_add(arr, num); + k5_json_release(num); + if (ret) + goto error; + } + ret = k5_json_object_set(obj, AU_IPV4, arr); + if (ret) + goto error; + } + +error: + k5_json_release(arr); + return ret; +} + +/* + * Converts krb5_fulladdr into a property of a JSON object. + * Returns 0 on success. + */ +static krb5_error_code +addr_to_value(const krb5_address *address, k5_json_object obj, const char *key) +{ + krb5_error_code ret = 0; + k5_json_object addr_obj = NULL; + + if (address == NULL) + return 0; + + ret = k5_json_object_create(&addr_obj); + if (ret) + return ret; + ret = addr_to_obj((krb5_address *)address, addr_obj); + if (!ret) + ret = k5_json_object_set(obj, key, addr_obj); + k5_json_release(addr_obj); + + return ret; +} + +/* + * Helper for JSON encoding of krb5_kdc_req. + * Returns 0 on success. + */ +static krb5_error_code +req_to_value(krb5_kdc_req *req, const krb5_boolean ev_success, + k5_json_object obj) +{ + krb5_error_code ret = 0; + k5_json_number num = NULL; + k5_json_string str = NULL; + k5_json_object tmpa = NULL; + k5_json_array arr = NULL, arra = NULL, arrpa = NULL; + krb5_pa_data **padata; + int i = 0; + + if (req == NULL) + return 0; + + ret = princ_to_value(req->client, obj, AU_REQ_CLIENT); + if (ret) + goto error; + ret = princ_to_value(req->server, obj, AU_REQ_SERVER); + if (ret) + goto error; + + ret = int32_to_value(req->kdc_options, obj, AU_REQ_KDC_OPTIONS); + if (ret) + goto error; + ret = int32_to_value(req->from, obj, AU_REQ_TKT_START); + if (ret) + goto error; + ret = int32_to_value(req->till, obj, AU_REQ_TKT_END); + if (ret) + goto error; + ret = int32_to_value(req->rtime, obj, AU_REQ_TKT_RENEW_TILL); + if (ret) + goto error; + /* Available/requested enctypes. */ + ret = k5_json_array_create(&arr); + if (ret) + goto error; + for (i = 0; (i < req->nktypes); i++) { + if (req->ktype[i] > 0) { + ret = k5_json_number_create(req->ktype[i], &num); + if (ret) + goto error; + ret = k5_json_array_add(arr, num); + k5_json_release(num); + if (ret) + goto error; + } + } + ret = k5_json_object_set(obj, AU_REQ_AVAIL_ETYPES, arr); + if (ret) + goto error; + /* Pre-auth types. */ + if (ev_success == TRUE && req->padata) { + ret = k5_json_array_create(&arrpa); + if (ret) + goto error; + for (padata = req->padata; *padata; padata++) { + if (strlen(map_patype((*padata)->pa_type)) > 1) { + ret = k5_json_string_create(map_patype((*padata)->pa_type), + &str); + if (ret) + goto error; + ret = k5_json_array_add(arrpa, str); + k5_json_release(str); + if (ret) + goto error; + } + } + ret = k5_json_object_set(obj, AU_REQ_PA_TYPE, arrpa); + } + /* List of requested addresses. */ + if (req->addresses) { + ret = k5_json_array_create(&arra); + if (ret) + goto error; + for (i = 0; req->addresses[i] != NULL; i++) { + ret = k5_json_object_create(&tmpa); + if (ret) + goto error; + ret = addr_to_obj(req->addresses[i], tmpa); + if (ret) + goto error; + ret = k5_json_array_add(arra, tmpa); + k5_json_release(tmpa); + if (ret) + goto error; + } + ret = k5_json_object_set(obj, AU_REQ_ADDRESSES, arra); + if (ret) + goto error; + } +error: + k5_json_release(arr); + k5_json_release(arra); + k5_json_release(arrpa); + return ret; +} + +/* + * Helper for JSON encoding of krb5_kdc_rep. + * Returns 0 on success. + */ +static krb5_error_code +rep_to_value(krb5_kdc_rep *rep, const krb5_boolean ev_success, + k5_json_object obj) +{ + krb5_error_code ret = 0; + krb5_pa_data **padata; + k5_json_array arrpa = NULL; + k5_json_string str = NULL; + + if (rep == NULL) + return 0; + + if (ev_success == TRUE) { + ret = tkt_to_value(rep->ticket, obj, AU_REP_TICKET); + /* Enctype of the reply-encrypting key. */ + ret = int32_to_value(rep->enc_part.enctype, obj, AU_REP_ETYPE); + if (ret) + goto error; + } else { + + if (rep->padata) { + ret = k5_json_array_create(&arrpa); + if (ret) + goto error; + for (padata = rep->padata; *padata; padata++) { + if (strlen(map_patype((*padata)->pa_type)) > 1) { + ret = k5_json_string_create(map_patype((*padata)->pa_type), + &str); + if (ret) + goto error; + ret = k5_json_array_add(arrpa, str); + k5_json_release(str); + if (ret) + goto error; + } + } + } + ret = k5_json_object_set(obj, AU_REP_PA_TYPE, arrpa); + } +error: + k5_json_release(arrpa); + return ret; +} + +/* + * Converts krb5_ticket into a property of a JSON object. + * Returns 0 on success. + */ +static krb5_error_code +tkt_to_value(krb5_ticket *tkt, k5_json_object obj, + const char *key) +{ + krb5_error_code ret = 0; + k5_json_object tmp = NULL; + krb5_enc_tkt_part *part2 = NULL; + + if (tkt == NULL) + return 0; + + /* Main object. */ + if (k5_json_object_create(&tmp)) + return ENOMEM; + + /* + * CNAME - potentially redundant data... + * ...but it is part of the ticket. So, record it as such. + */ + ret = princ_to_value(tkt->server, tmp, AU_CNAME); + if (ret) + goto error; + ret = princ_to_value(tkt->server, tmp, AU_SNAME); + if (ret) + goto error; + /* Enctype of a long-term key of service. */ + if (tkt->enc_part.enctype) + ret = int32_to_value(tkt->enc_part.enctype, tmp, AU_SRV_ETYPE); + if (ret) + goto error; + if (tkt->enc_part2) + part2 = tkt->enc_part2; + if (part2) { + ret = princ_to_value(part2->client, tmp, AU_CNAME); + if (ret) + goto error; + ret = int32_to_value(part2->flags, tmp, AU_FLAGS); + if (ret) + goto error; + /* Chosen by KDC session key enctype (short-term key). */ + ret = int32_to_value(part2->session->enctype, tmp, AU_SESS_ETYPE); + if (ret) + goto error; + if (&part2->times) { + ret = int32_to_value(part2->times.starttime, tmp, AU_START); + if (ret) + goto error; + ret = int32_to_value(part2->times.endtime, tmp, AU_END); + if (ret) + goto error; + ret = int32_to_value(part2->times.renew_till, tmp, AU_RENEW_TILL); + if (ret) + goto error; + ret = int32_to_value(part2->times.authtime, tmp, AU_AUTHTIME); + if (ret) + goto error; + } + if (&part2->transited && &part2->transited.tr_contents && + part2->transited.tr_contents.length > 0) { + ret = data_to_value(&part2->transited.tr_contents, + tmp, AU_TR_CONTENTS); + if (ret) + goto error; + } + } /* part2 != NULL */ + + if (!ret) + ret = k5_json_object_set(obj, key, tmp); + +error: + k5_json_release(tmp); + return ret; +} + +/* Map preauth numeric type to the naming string. */ +struct _patype_str { + krb5_preauthtype id; + char *name; +}; +struct _patype_str patype_str[] = { + {KRB5_PADATA_ENC_TIMESTAMP, "ENC_TIMESTAMP"}, + {KRB5_PADATA_PW_SALT, "PW_SALT"}, + {KRB5_PADATA_ENC_UNIX_TIME, "ENC_UNIX_TIME"}, + {KRB5_PADATA_SAM_CHALLENGE, "SAM_CHALLENGE"}, + {KRB5_PADATA_SAM_RESPONSE, "SAM_RESPONSE"}, + {KRB5_PADATA_PK_AS_REQ_OLD, "PK_AS_REQ_OLD"}, + {KRB5_PADATA_PK_AS_REP_OLD, "PK_AS_REP_OLD"}, + {KRB5_PADATA_PK_AS_REQ, "PK_AS_REQ"}, + {KRB5_PADATA_PK_AS_REP, "PK_AS_REP"}, + {KRB5_PADATA_ETYPE_INFO2, "ETYPE_INFO2"}, + {KRB5_PADATA_SAM_CHALLENGE_2, "SAM_CHALLENGE_2"}, + {KRB5_PADATA_SAM_RESPONSE_2, "SAM_RESPONSE_2"}, + {KRB5_PADATA_PAC_REQUEST, "PAC_REQUEST"}, + {KRB5_PADATA_FOR_USER, "FOR_USER"}, + {KRB5_PADATA_S4U_X509_USER, "S4U_X509_USER"}, + {KRB5_PADATA_ENCRYPTED_CHALLENGE, "ENCRYPTED_CHALLENGE"}, + {KRB5_PADATA_OTP_CHALLENGE, "OTP_CHALLENGE"}, + {KRB5_PADATA_OTP_REQUEST, "OTP_REQUEST"}, + {KRB5_PADATA_OTP_PIN_CHANGE, "OTP_PIN_CHANGE"} +}; + + +static char * +map_patype(krb5_preauthtype pa_type) +{ + int i = 0; + int n = sizeof(patype_str)/sizeof(patype_str[0]); + + for (i = 0; i < n; i++) { + if (pa_type == patype_str[i].id) + return patype_str[i].name; + } + return ""; +} diff --git a/src/plugins/audit/kdc_j_encode.h b/src/plugins/audit/kdc_j_encode.h new file mode 100644 index 0000000..0c59adc --- /dev/null +++ b/src/plugins/audit/kdc_j_encode.h @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/audit/kdc_j_encode.h - Declarations for KDC audit json encoders */ +/* + * Copyright 2013 by the Massachusetts Institute of Technology. + * + * 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. + */ + +#ifndef KRB5_KDC_J_ENCODE_H_INCLUDED +#define KRB5_KDC_J_ENCODE_H_INCLUDED + +#include <krb5/audit_plugin.h> + +/* Maximum length of the name of preauth type. */ +#define MAX_PATYPE_NAME_LEN 32 + +krb5_error_code +kau_j_kdc_stop(const krb5_boolean ev_success, char **jout); + +krb5_error_code +kau_j_kdc_start(const krb5_boolean ev_success, char **jout); + +krb5_error_code +kau_j_as_req(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout); + +krb5_error_code +kau_j_tgs_req(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout); + +krb5_error_code +kau_j_tgs_s4u2self(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout); + +krb5_error_code +kau_j_tgs_s4u2proxy(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout); + +krb5_error_code +kau_j_tgs_u2u(const krb5_boolean ev_success, krb5_audit_state *state, + char **jout); + +#endif /* KRB5_KDC_J_ENCODE_H_INCLUDED */ diff --git a/src/plugins/audit/libauditjenc.exports b/src/plugins/audit/libauditjenc.exports new file mode 100644 index 0000000..da7120f --- /dev/null +++ b/src/plugins/audit/libauditjenc.exports @@ -0,0 +1,7 @@ +kau_j_kdc_stop +kau_j_kdc_start +kau_j_as_req +kau_j_tgs_req +kau_j_tgs_s4u2self +kau_j_tgs_s4u2proxy +kau_j_tgs_u2u diff --git a/src/plugins/audit/simple/Makefile.in b/src/plugins/audit/simple/Makefile.in new file mode 100644 index 0000000..54961c4 --- /dev/null +++ b/src/plugins/audit/simple/Makefile.in @@ -0,0 +1,27 @@ +mydir=plugins$(S)audit$(S)simple +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=k5audit +LIBMAJOR=1 +LIBMINOR=1 +RELDIR=../plugins/audit/simple + +#Depends on libkrb5 and libkrb5support. +SHLIB_EXPDEPS= $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS= $(KRB5_BASE_LIBS) + +STOBJLISTS= OBJS.ST ../OBJS.ST +STLIBOBJS= au_simple_main.o + +SRCS= $(srcdir)/au_simple_main.c + +all-unix:: all-liblinks +install-unix:: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +clean:: + $(RM) au_simple_main.o kdc_j_encode.o + $(RM) lib$(LIBBASE)$(SO_EXT) + +@libnover_frag@ +@libobj_frag@ diff --git a/src/plugins/audit/simple/au_simple_main.c b/src/plugins/audit/simple/au_simple_main.c new file mode 100644 index 0000000..87a2c55 --- /dev/null +++ b/src/plugins/audit/simple/au_simple_main.c @@ -0,0 +1,263 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/audit/au_simple_main.c - Sample Audit plugin implementation */ +/* + * 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. + */ + +/* + * This is a demo implementation of Audit JSON-based module. + * It utilizes MIT Kerberos <kdc_j_encode.h> routines for JSON processing and + * the Fedora/Debian libaudit library for audit logs. + */ + +#include <k5-int.h> +#include <krb5/audit_plugin.h> +#include <libaudit.h> +#include <kdc_j_encode.h> + +krb5_error_code +audit_simple_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +struct krb5_audit_moddata_st { + int fd; +}; + +/* Open connection to the audit system. Returns 0 on success. */ +static krb5_error_code +open_au(krb5_audit_moddata *auctx_out) +{ + krb5_error_code ret; + int fd = 0; + krb5_audit_moddata auctx; + + auctx = k5calloc(1, sizeof(*auctx), &ret); + if (ret) + return ENOMEM; + fd = audit_open(); + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + auctx->fd = fd; + *auctx_out = auctx; + + return 0; +} + +/* Close connection to the audit system. Returns 0 on success. */ +static krb5_error_code +close_au(krb5_audit_moddata auctx) +{ + int fd = auctx->fd; + + audit_close(fd); + return 0; +} + +/* Log KDC-start event. Returns 0 on success. */ +static krb5_error_code +j_kdc_start(krb5_audit_moddata auctx, krb5_boolean ev_success) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_START; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_kdc_start(ev_success, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log KDC-stop event. Returns 0 on success. */ +static krb5_error_code +j_kdc_stop(krb5_audit_moddata auctx, krb5_boolean ev_success) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_END; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_kdc_stop(ev_success, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log AS_REQ event. Returns 0 on success */ +static krb5_error_code +j_as_req(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_AUTH; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_as_req(ev_success, state, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log TGS_REQ event. Returns 0 on success */ +static krb5_error_code +j_tgs_req(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_AUTH; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_tgs_req(ev_success, state, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log S4U2SELF event. Returns 0 on success */ +static krb5_error_code +j_tgs_s4u2self(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_AUTH; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_tgs_s4u2self(ev_success, state, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log S4U2PROXY event. Returns 0 on success */ +static krb5_error_code +j_tgs_s4u2proxy(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_AUTH; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_tgs_s4u2proxy(ev_success, state, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +/* Log user-to-user event. Returns 0 on success */ +static krb5_error_code +j_tgs_u2u(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + int local_type = AUDIT_USER_AUTH; + int fd = auctx->fd; + char *jout = NULL; + + if (fd < 0) + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + + ret = kau_j_tgs_u2u(ev_success, state, &jout); + if (ret) + return ret; + if (audit_log_user_message(fd, local_type, jout, + NULL, NULL, NULL, ev_success) <= 0) + ret = EIO; + free(jout); + return ret; +} + +krb5_error_code +audit_simple_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_audit_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + + vt = (krb5_audit_vtable)vtable; + vt->name = "simple"; + vt->open = open_au; + vt->close = close_au; + vt->kdc_start = j_kdc_start; + vt->kdc_stop = j_kdc_stop; + vt->as_req = j_as_req; + vt->tgs_req = j_tgs_req; + vt->tgs_s4u2self = j_tgs_s4u2self; + vt->tgs_s4u2proxy = j_tgs_s4u2proxy; + vt->tgs_u2u = j_tgs_u2u; + return 0; +} diff --git a/src/plugins/audit/simple/deps b/src/plugins/audit/simple/deps new file mode 100644 index 0000000..84d4f04 --- /dev/null +++ b/src/plugins/audit/simple/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +au_simple_main.so au_simple_main.po $(OUTPRE)au_simple_main.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/kdc_j_encode.h \ + $(BUILDTOP)/include/krb5/audit_plugin.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + au_simple_main.c diff --git a/src/plugins/audit/simple/k5audit.exports b/src/plugins/audit/simple/k5audit.exports new file mode 100644 index 0000000..2070538 --- /dev/null +++ b/src/plugins/audit/simple/k5audit.exports @@ -0,0 +1 @@ +audit_simple_initvt diff --git a/src/plugins/audit/test/Makefile.in b/src/plugins/audit/test/Makefile.in new file mode 100644 index 0000000..130b024 --- /dev/null +++ b/src/plugins/audit/test/Makefile.in @@ -0,0 +1,21 @@ +mydir=plugins$(S)audit$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=k5audit_test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/audit/test +# Depends on libkrb5 and libkrb5support. +SHLIB_EXPDEPS= $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS= $(KRB5_BASE_LIBS) + +STOBJLISTS= OBJS.ST ../OBJS.ST +STLIBOBJS= au_test.o + +SRCS= $(srcdir)/au_test.c + +all-unix:: all-liblinks +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/src/plugins/audit/test/au_test.c b/src/plugins/audit/test/au_test.c new file mode 100644 index 0000000..54bf564 --- /dev/null +++ b/src/plugins/audit/test/au_test.c @@ -0,0 +1,228 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/audit/au_test.c - Test Audit plugin implementation */ +/* + * 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. + */ +/* + * This test is to verify the JSON-based KDC audit functionality. + * It utilized MIT Kerberos <kdc_j_encode.h> routines for JSON processing. + */ + +#include <k5-int.h> +#include <krb5/audit_plugin.h> +#include <kdc_j_encode.h> +#include "k5-thread.h" + +struct krb5_audit_moddata_st { + int au_fd; +}; + +krb5_error_code +audit_test_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +static FILE *au_fd; +static k5_mutex_t lock = K5_MUTEX_PARTIAL_INITIALIZER; + +/* Open connection to the audit system. Returns 0 on success. */ +static krb5_error_code +open_au(krb5_audit_moddata *auctx) +{ + au_fd = fopen("au.log", "a+"); + if ( au_fd < 0) { + return KRB5_PLUGIN_NO_HANDLE; /* audit module is unavailable */ + } + k5_mutex_init(&lock); + return 0; +} + +/* Close connection to the audit system. Returns 0. */ +static krb5_error_code +close_au(krb5_audit_moddata auctx) +{ + fclose(au_fd); + k5_mutex_destroy(&lock); + return 0; +} + +/* Log KDC-start event. Returns 0 on success. */ +static krb5_error_code +j_kdc_start(krb5_audit_moddata auctx, krb5_boolean ev_success) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_kdc_start(ev_success, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log KDC-stop event. Returns 0 on success. */ +static krb5_error_code +j_kdc_stop(krb5_audit_moddata auctx, krb5_boolean ev_success) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_kdc_stop(ev_success, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log AS_REQ event. Returns 0 on success. */ +static krb5_error_code +j_as_req(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_as_req(ev_success, state, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log TGS_REQ event. Returns 0 on success. */ +static krb5_error_code +j_tgs_req(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_tgs_req(ev_success, state, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log S4U2SELF event. Returns 0 on success. */ +static krb5_error_code +j_tgs_s4u2self(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_tgs_s4u2self(ev_success, state, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log S4U2PROXY event. Returns 0 on success. */ +static krb5_error_code +j_tgs_s4u2proxy(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_tgs_s4u2proxy(ev_success, state, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +/* Log user-to-user event. Returns 0 on success. */ +static krb5_error_code +j_tgs_u2u(krb5_audit_moddata auctx, krb5_boolean ev_success, + krb5_audit_state *state) +{ + krb5_error_code ret = 0; + char *jout = NULL; + + ret = kau_j_tgs_u2u(ev_success, state, &jout); + if (ret) + return ret; + k5_mutex_lock(&lock); + fprintf(au_fd,"%s\n", jout); + fflush(au_fd); + k5_mutex_unlock(&lock); + free(jout); + return ret; +} + +krb5_error_code +audit_test_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_audit_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + + vt = (krb5_audit_vtable)vtable; + vt->name = "test"; + + vt->open = open_au; + vt->close = close_au; + vt->kdc_start = j_kdc_start; + vt->kdc_stop = j_kdc_stop; + vt->as_req = j_as_req; + vt->tgs_req = j_tgs_req; + vt->tgs_s4u2self = j_tgs_s4u2self; + vt->tgs_s4u2proxy = j_tgs_s4u2proxy; + vt->tgs_u2u = j_tgs_u2u; + + return 0; +} diff --git a/src/plugins/audit/test/deps b/src/plugins/audit/test/deps new file mode 100644 index 0000000..f4f76ae --- /dev/null +++ b/src/plugins/audit/test/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +au_test.so au_test.po $(OUTPRE)au_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/kdc_j_encode.h $(BUILDTOP)/include/krb5/audit_plugin.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h au_test.c diff --git a/src/plugins/audit/test/k5audit_test.exports b/src/plugins/audit/test/k5audit_test.exports new file mode 100644 index 0000000..8f69363 --- /dev/null +++ b/src/plugins/audit/test/k5audit_test.exports @@ -0,0 +1 @@ +audit_test_initvt |