xref: /freebsd/crypto/krb5/src/plugins/audit/kdc_j_encode.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* plugins/audit/kdc_j_encode.c - Utilities to json encode KDC audit stuff */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright (C) 2013 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All rights reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert  * modification, are permitted provided that the following conditions
9*7f2fe78bSCy Schubert  * are met:
10*7f2fe78bSCy Schubert  *
11*7f2fe78bSCy Schubert  * * Redistributions of source code must retain the above copyright
12*7f2fe78bSCy Schubert  *   notice, this list of conditions and the following disclaimer.
13*7f2fe78bSCy Schubert  *
14*7f2fe78bSCy Schubert  * * Redistributions in binary form must reproduce the above copyright
15*7f2fe78bSCy Schubert  *   notice, this list of conditions and the following disclaimer in
16*7f2fe78bSCy Schubert  *   the documentation and/or other materials provided with the
17*7f2fe78bSCy Schubert  *   distribution.
18*7f2fe78bSCy Schubert  *
19*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*7f2fe78bSCy Schubert  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*7f2fe78bSCy Schubert  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22*7f2fe78bSCy Schubert  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23*7f2fe78bSCy Schubert  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24*7f2fe78bSCy Schubert  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25*7f2fe78bSCy Schubert  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26*7f2fe78bSCy Schubert  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*7f2fe78bSCy Schubert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28*7f2fe78bSCy Schubert  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*7f2fe78bSCy Schubert  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30*7f2fe78bSCy Schubert  * OF THE POSSIBILITY OF SUCH DAMAGE.
31*7f2fe78bSCy Schubert  */
32*7f2fe78bSCy Schubert 
33*7f2fe78bSCy Schubert #include <k5-int.h>
34*7f2fe78bSCy Schubert #include <k5-json.h>
35*7f2fe78bSCy Schubert #include "kdc_j_encode.h"
36*7f2fe78bSCy Schubert #include "j_dict.h"
37*7f2fe78bSCy Schubert #include <krb5/audit_plugin.h>
38*7f2fe78bSCy Schubert #include <syslog.h>
39*7f2fe78bSCy Schubert 
40*7f2fe78bSCy Schubert static krb5_error_code
41*7f2fe78bSCy Schubert string_to_value(const char *in, k5_json_object obj, const char *key);
42*7f2fe78bSCy Schubert static krb5_error_code
43*7f2fe78bSCy Schubert princ_to_value(krb5_principal princ, k5_json_object obj, const char *key);
44*7f2fe78bSCy Schubert static krb5_error_code
45*7f2fe78bSCy Schubert data_to_value(krb5_data *data, k5_json_object obj, const char *key);
46*7f2fe78bSCy Schubert static krb5_error_code
47*7f2fe78bSCy Schubert int32_to_value(krb5_int32 int32, k5_json_object obj, const char *key);
48*7f2fe78bSCy Schubert static krb5_error_code
49*7f2fe78bSCy Schubert bool_to_value(krb5_boolean b, k5_json_object obj, const char *key);
50*7f2fe78bSCy Schubert static krb5_error_code
51*7f2fe78bSCy Schubert addr_to_obj(krb5_address *a, k5_json_object obj);
52*7f2fe78bSCy Schubert static krb5_error_code
53*7f2fe78bSCy Schubert eventinfo_to_value(k5_json_object obj, const char *name,
54*7f2fe78bSCy Schubert                    const int stage, const krb5_boolean ev_success);
55*7f2fe78bSCy Schubert static krb5_error_code
56*7f2fe78bSCy Schubert addr_to_value(const krb5_address *address, k5_json_object obj,
57*7f2fe78bSCy Schubert               const char *key);
58*7f2fe78bSCy Schubert static krb5_error_code
59*7f2fe78bSCy Schubert req_to_value(krb5_kdc_req *req, const krb5_boolean ev_success,
60*7f2fe78bSCy Schubert              k5_json_object obj);
61*7f2fe78bSCy Schubert static krb5_error_code
62*7f2fe78bSCy Schubert rep_to_value(krb5_kdc_rep *rep, const krb5_boolean ev_success,
63*7f2fe78bSCy Schubert              k5_json_object obj);
64*7f2fe78bSCy Schubert static krb5_error_code
65*7f2fe78bSCy Schubert tkt_to_value(krb5_ticket *tkt, k5_json_object obj, const char *key);
66*7f2fe78bSCy Schubert static char *map_patype(krb5_preauthtype pa_type);
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert #define NULL_STATE "state is NULL"
69*7f2fe78bSCy Schubert #define T_RENEWED 1
70*7f2fe78bSCy Schubert #define T_NOT_RENEWED 2
71*7f2fe78bSCy Schubert #define T_VALIDATED 1
72*7f2fe78bSCy Schubert #define T_NOT_VALIDATED 2
73*7f2fe78bSCy Schubert 
74*7f2fe78bSCy Schubert /* KDC server STOP. Returns 0 on success. */
75*7f2fe78bSCy Schubert krb5_error_code
kau_j_kdc_stop(const krb5_boolean ev_success,char ** jout)76*7f2fe78bSCy Schubert kau_j_kdc_stop(const krb5_boolean ev_success, char **jout)
77*7f2fe78bSCy Schubert {
78*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
79*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
80*7f2fe78bSCy Schubert 
81*7f2fe78bSCy Schubert     *jout = NULL;
82*7f2fe78bSCy Schubert 
83*7f2fe78bSCy Schubert     /* Main object. */
84*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
85*7f2fe78bSCy Schubert         return ENOMEM;
86*7f2fe78bSCy Schubert 
87*7f2fe78bSCy Schubert     /* Audit event_ID and ev_success. */
88*7f2fe78bSCy Schubert     ret = string_to_value("KDC_STOP", obj, AU_EVENT_NAME);
89*7f2fe78bSCy Schubert     if (!ret)
90*7f2fe78bSCy Schubert         ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS);
91*7f2fe78bSCy Schubert     if (!ret)
92*7f2fe78bSCy Schubert         ret = k5_json_encode(obj, jout);
93*7f2fe78bSCy Schubert     k5_json_release(obj);
94*7f2fe78bSCy Schubert 
95*7f2fe78bSCy Schubert     return ret;
96*7f2fe78bSCy Schubert }
97*7f2fe78bSCy Schubert 
98*7f2fe78bSCy Schubert /* KDC server START. Returns 0 on success. */
99*7f2fe78bSCy Schubert krb5_error_code
kau_j_kdc_start(const krb5_boolean ev_success,char ** jout)100*7f2fe78bSCy Schubert kau_j_kdc_start(const krb5_boolean ev_success, char **jout)
101*7f2fe78bSCy Schubert {
102*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
103*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
104*7f2fe78bSCy Schubert 
105*7f2fe78bSCy Schubert     *jout = NULL;
106*7f2fe78bSCy Schubert 
107*7f2fe78bSCy Schubert     /* Main object. */
108*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
109*7f2fe78bSCy Schubert         return ENOMEM;
110*7f2fe78bSCy Schubert 
111*7f2fe78bSCy Schubert     /* Audit event_ID and ev_success. */
112*7f2fe78bSCy Schubert     ret = string_to_value("KDC_START", obj, AU_EVENT_NAME);
113*7f2fe78bSCy Schubert     if (!ret)
114*7f2fe78bSCy Schubert         ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS);
115*7f2fe78bSCy Schubert     if (!ret)
116*7f2fe78bSCy Schubert         ret = k5_json_encode(obj, jout);
117*7f2fe78bSCy Schubert     k5_json_release(obj);
118*7f2fe78bSCy Schubert 
119*7f2fe78bSCy Schubert     return ret;
120*7f2fe78bSCy Schubert }
121*7f2fe78bSCy Schubert 
122*7f2fe78bSCy Schubert /* AS-REQ. Returns 0 on success. */
123*7f2fe78bSCy Schubert krb5_error_code
kau_j_as_req(const krb5_boolean ev_success,krb5_audit_state * state,char ** jout)124*7f2fe78bSCy Schubert kau_j_as_req(const krb5_boolean ev_success, krb5_audit_state *state,
125*7f2fe78bSCy Schubert              char **jout)
126*7f2fe78bSCy Schubert {
127*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
128*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
129*7f2fe78bSCy Schubert 
130*7f2fe78bSCy Schubert     *jout = NULL;
131*7f2fe78bSCy Schubert 
132*7f2fe78bSCy Schubert     if (!state) {
133*7f2fe78bSCy Schubert         *jout = NULL_STATE;
134*7f2fe78bSCy Schubert         return 0;
135*7f2fe78bSCy Schubert     }
136*7f2fe78bSCy Schubert 
137*7f2fe78bSCy Schubert     /* Main object. */
138*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
139*7f2fe78bSCy Schubert         return ENOMEM;
140*7f2fe78bSCy Schubert     /* Audit event_ID and ev_success. */
141*7f2fe78bSCy Schubert     ret = eventinfo_to_value(obj, "AS_REQ", state->stage, ev_success);
142*7f2fe78bSCy Schubert     if (ret)
143*7f2fe78bSCy Schubert         goto error;
144*7f2fe78bSCy Schubert     /* TGT ticket ID */
145*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID);
146*7f2fe78bSCy Schubert     if (ret)
147*7f2fe78bSCy Schubert         goto error;
148*7f2fe78bSCy Schubert     /* Request ID. */
149*7f2fe78bSCy Schubert     ret = string_to_value(state->req_id, obj, AU_REQ_ID);
150*7f2fe78bSCy Schubert     if (ret)
151*7f2fe78bSCy Schubert         goto error;
152*7f2fe78bSCy Schubert     /* Client's port and address. */
153*7f2fe78bSCy Schubert     ret = int32_to_value(state->cl_port, obj, AU_FROMPORT);
154*7f2fe78bSCy Schubert     if (ret)
155*7f2fe78bSCy Schubert         goto error;
156*7f2fe78bSCy Schubert     ret = addr_to_value(state->cl_addr, obj, AU_FROMADDR);
157*7f2fe78bSCy Schubert     if (ret)
158*7f2fe78bSCy Schubert         goto error;
159*7f2fe78bSCy Schubert     /* KDC status msg */
160*7f2fe78bSCy Schubert     ret = string_to_value(state->status, obj, AU_KDC_STATUS);
161*7f2fe78bSCy Schubert     if (ret)
162*7f2fe78bSCy Schubert         goto error;
163*7f2fe78bSCy Schubert     /* non-local client's referral realm. */
164*7f2fe78bSCy Schubert     ret = data_to_value(state->cl_realm, obj, AU_CREF_REALM);
165*7f2fe78bSCy Schubert     if (ret)
166*7f2fe78bSCy Schubert         goto error;
167*7f2fe78bSCy Schubert     /* Request. */
168*7f2fe78bSCy Schubert     ret = req_to_value(state->request, ev_success, obj);
169*7f2fe78bSCy Schubert     if (ret == ENOMEM)
170*7f2fe78bSCy Schubert         goto error;
171*7f2fe78bSCy Schubert     /* Reply/ticket info. */
172*7f2fe78bSCy Schubert     ret = rep_to_value(state->reply, ev_success, obj);
173*7f2fe78bSCy Schubert     if (ret == ENOMEM)
174*7f2fe78bSCy Schubert         goto error;
175*7f2fe78bSCy Schubert     ret = k5_json_encode(obj, jout);
176*7f2fe78bSCy Schubert 
177*7f2fe78bSCy Schubert error:
178*7f2fe78bSCy Schubert     k5_json_release(obj);
179*7f2fe78bSCy Schubert     return ret;
180*7f2fe78bSCy Schubert }
181*7f2fe78bSCy Schubert 
182*7f2fe78bSCy Schubert /* TGS-REQ. Returns 0 on success. */
183*7f2fe78bSCy Schubert krb5_error_code
kau_j_tgs_req(const krb5_boolean ev_success,krb5_audit_state * state,char ** jout)184*7f2fe78bSCy Schubert kau_j_tgs_req(const krb5_boolean ev_success, krb5_audit_state *state,
185*7f2fe78bSCy Schubert               char **jout)
186*7f2fe78bSCy Schubert {
187*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
188*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
189*7f2fe78bSCy Schubert     krb5_kdc_req *req = state->request;
190*7f2fe78bSCy Schubert     int tkt_validated = 0, tkt_renewed = 0;
191*7f2fe78bSCy Schubert 
192*7f2fe78bSCy Schubert     *jout = NULL;
193*7f2fe78bSCy Schubert 
194*7f2fe78bSCy Schubert     if (!state) {
195*7f2fe78bSCy Schubert         *jout = NULL_STATE;
196*7f2fe78bSCy Schubert         return 0;
197*7f2fe78bSCy Schubert     }
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert     /* Main object. */
200*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
201*7f2fe78bSCy Schubert         return ENOMEM;
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert     /* Audit Event ID and ev_success. */
204*7f2fe78bSCy Schubert     ret = eventinfo_to_value(obj, "TGS_REQ", state->stage, ev_success);
205*7f2fe78bSCy Schubert     if (ret)
206*7f2fe78bSCy Schubert         goto error;
207*7f2fe78bSCy Schubert     /* Primary and derived ticket IDs. */
208*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID);
209*7f2fe78bSCy Schubert     if (ret)
210*7f2fe78bSCy Schubert         goto error;
211*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID);
212*7f2fe78bSCy Schubert     if (ret)
213*7f2fe78bSCy Schubert         goto error;
214*7f2fe78bSCy Schubert     /* Request ID */
215*7f2fe78bSCy Schubert     ret = string_to_value(state->req_id, obj, AU_REQ_ID);
216*7f2fe78bSCy Schubert     if (ret)
217*7f2fe78bSCy Schubert         goto error;
218*7f2fe78bSCy Schubert     /* client’s address and port. */
219*7f2fe78bSCy Schubert     ret = int32_to_value(state->cl_port, obj, AU_FROMPORT);
220*7f2fe78bSCy Schubert     if (ret)
221*7f2fe78bSCy Schubert         goto error;
222*7f2fe78bSCy Schubert     ret = addr_to_value(state->cl_addr, obj, AU_FROMADDR);
223*7f2fe78bSCy Schubert     if (ret)
224*7f2fe78bSCy Schubert         goto error;
225*7f2fe78bSCy Schubert     /* Ticket was renewed, validated. */
226*7f2fe78bSCy Schubert     if ((ev_success == TRUE) && (req != NULL)) {
227*7f2fe78bSCy Schubert         tkt_renewed = (req->kdc_options & KDC_OPT_RENEW) ?
228*7f2fe78bSCy Schubert                       T_RENEWED : T_NOT_RENEWED;
229*7f2fe78bSCy Schubert         tkt_validated = (req->kdc_options & KDC_OPT_VALIDATE) ?
230*7f2fe78bSCy Schubert                       T_VALIDATED : T_NOT_VALIDATED;
231*7f2fe78bSCy Schubert     }
232*7f2fe78bSCy Schubert     ret = int32_to_value(tkt_renewed, obj, AU_TKT_RENEWED);
233*7f2fe78bSCy Schubert     if (ret)
234*7f2fe78bSCy Schubert         goto error;
235*7f2fe78bSCy Schubert     ret = int32_to_value(tkt_validated, obj, AU_TKT_VALIDATED);
236*7f2fe78bSCy Schubert     if (ret)
237*7f2fe78bSCy Schubert         goto error;
238*7f2fe78bSCy Schubert     /* KDC status msg, including "ISSUE". */
239*7f2fe78bSCy Schubert     ret = string_to_value(state->status, obj, AU_KDC_STATUS);
240*7f2fe78bSCy Schubert     if (ret)
241*7f2fe78bSCy Schubert         goto error;
242*7f2fe78bSCy Schubert     /* request */
243*7f2fe78bSCy Schubert     ret = req_to_value(req, ev_success, obj);
244*7f2fe78bSCy Schubert     if (ret == ENOMEM)
245*7f2fe78bSCy Schubert         goto error;
246*7f2fe78bSCy Schubert     /* reply/ticket */
247*7f2fe78bSCy Schubert     ret = rep_to_value(state->reply, ev_success, obj);
248*7f2fe78bSCy Schubert     if (ret == ENOMEM)
249*7f2fe78bSCy Schubert         goto error;
250*7f2fe78bSCy Schubert     ret = k5_json_encode(obj, jout);
251*7f2fe78bSCy Schubert 
252*7f2fe78bSCy Schubert error:
253*7f2fe78bSCy Schubert     k5_json_release(obj);
254*7f2fe78bSCy Schubert     return ret;
255*7f2fe78bSCy Schubert }
256*7f2fe78bSCy Schubert 
257*7f2fe78bSCy Schubert /* S4U2Self protocol extension. Returns 0 on success. */
258*7f2fe78bSCy Schubert krb5_error_code
kau_j_tgs_s4u2self(const krb5_boolean ev_success,krb5_audit_state * state,char ** jout)259*7f2fe78bSCy Schubert kau_j_tgs_s4u2self(const krb5_boolean ev_success, krb5_audit_state *state,
260*7f2fe78bSCy Schubert                    char **jout)
261*7f2fe78bSCy Schubert {
262*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
263*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
264*7f2fe78bSCy Schubert 
265*7f2fe78bSCy Schubert     *jout = NULL;
266*7f2fe78bSCy Schubert 
267*7f2fe78bSCy Schubert     if (!state) {
268*7f2fe78bSCy Schubert         *jout = NULL_STATE;
269*7f2fe78bSCy Schubert         return 0;
270*7f2fe78bSCy Schubert     }
271*7f2fe78bSCy Schubert 
272*7f2fe78bSCy Schubert     /* Main object. */
273*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
274*7f2fe78bSCy Schubert         return ENOMEM;
275*7f2fe78bSCy Schubert 
276*7f2fe78bSCy Schubert     /* Audit Event ID and ev_success. */
277*7f2fe78bSCy Schubert     ret = eventinfo_to_value(obj, "S4U2SELF", state->stage, ev_success);
278*7f2fe78bSCy Schubert     if (ret)
279*7f2fe78bSCy Schubert         goto error;
280*7f2fe78bSCy Schubert     /* Front-end server's TGT ticket ID. */
281*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID);
282*7f2fe78bSCy Schubert     if (ret)
283*7f2fe78bSCy Schubert         goto error;
284*7f2fe78bSCy Schubert     /* service "to self" ticket or referral TGT ticket ID. */
285*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID);
286*7f2fe78bSCy Schubert     if (ret)
287*7f2fe78bSCy Schubert         goto error;
288*7f2fe78bSCy Schubert     /* Request ID. */
289*7f2fe78bSCy Schubert     ret = string_to_value(state->req_id, obj, AU_REQ_ID);
290*7f2fe78bSCy Schubert     if (ret)
291*7f2fe78bSCy Schubert         goto error;
292*7f2fe78bSCy Schubert     if (ev_success == FALSE) {
293*7f2fe78bSCy Schubert         /* KDC status msg. */
294*7f2fe78bSCy Schubert         ret = string_to_value(state->status, obj, AU_KDC_STATUS);
295*7f2fe78bSCy Schubert         if (ret)
296*7f2fe78bSCy Schubert             goto error;
297*7f2fe78bSCy Schubert         /* Local policy or S4U protocol constraints. */
298*7f2fe78bSCy Schubert         ret = int32_to_value(state->violation, obj, AU_VIOLATION);
299*7f2fe78bSCy Schubert         if (ret)
300*7f2fe78bSCy Schubert             goto error;
301*7f2fe78bSCy Schubert     }
302*7f2fe78bSCy Schubert     /* Impersonated user. */
303*7f2fe78bSCy Schubert     ret = princ_to_value(state->s4u2self_user, obj, AU_REQ_S4U2S_USER);
304*7f2fe78bSCy Schubert     if (ret)
305*7f2fe78bSCy Schubert         goto error;
306*7f2fe78bSCy Schubert 
307*7f2fe78bSCy Schubert     ret = k5_json_encode(obj, jout);
308*7f2fe78bSCy Schubert 
309*7f2fe78bSCy Schubert error:
310*7f2fe78bSCy Schubert     k5_json_release(obj);
311*7f2fe78bSCy Schubert     return ret;
312*7f2fe78bSCy Schubert }
313*7f2fe78bSCy Schubert 
314*7f2fe78bSCy Schubert /* S4U2Proxy protocol extension. Returns 0 on success. */
315*7f2fe78bSCy Schubert krb5_error_code
kau_j_tgs_s4u2proxy(const krb5_boolean ev_success,krb5_audit_state * state,char ** jout)316*7f2fe78bSCy Schubert kau_j_tgs_s4u2proxy(const krb5_boolean ev_success, krb5_audit_state *state,
317*7f2fe78bSCy Schubert                     char **jout)
318*7f2fe78bSCy Schubert {
319*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
320*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
321*7f2fe78bSCy Schubert     krb5_kdc_req *req = state->request;
322*7f2fe78bSCy Schubert 
323*7f2fe78bSCy Schubert     *jout = NULL;
324*7f2fe78bSCy Schubert 
325*7f2fe78bSCy Schubert     if (!state) {
326*7f2fe78bSCy Schubert         *jout = NULL_STATE;
327*7f2fe78bSCy Schubert         return 0;
328*7f2fe78bSCy Schubert     }
329*7f2fe78bSCy Schubert 
330*7f2fe78bSCy Schubert     /* Main object. */
331*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
332*7f2fe78bSCy Schubert         return ENOMEM;
333*7f2fe78bSCy Schubert 
334*7f2fe78bSCy Schubert     /* Audit Event ID and ev_success. */
335*7f2fe78bSCy Schubert     ret = eventinfo_to_value(obj, "S4U2PROXY", state->stage, ev_success);
336*7f2fe78bSCy Schubert     if (ret)
337*7f2fe78bSCy Schubert         goto error;
338*7f2fe78bSCy Schubert     /* Front-end server's TGT ticket ID. */
339*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID);
340*7f2fe78bSCy Schubert     if (ret)
341*7f2fe78bSCy Schubert         goto error;
342*7f2fe78bSCy Schubert     /* Resource service or referral TGT ticket ID. */
343*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID);
344*7f2fe78bSCy Schubert     if (ret)
345*7f2fe78bSCy Schubert         goto error;
346*7f2fe78bSCy Schubert     /* User's evidence ticket ID. */
347*7f2fe78bSCy Schubert     ret = string_to_value(state->evid_tkt_id, obj, AU_EVIDENCE_TKT_ID);
348*7f2fe78bSCy Schubert     if (ret)
349*7f2fe78bSCy Schubert         goto error;
350*7f2fe78bSCy Schubert     /* Request ID. */
351*7f2fe78bSCy Schubert     ret = string_to_value(state->req_id, obj, AU_REQ_ID);
352*7f2fe78bSCy Schubert     if (ret)
353*7f2fe78bSCy Schubert         goto error;
354*7f2fe78bSCy Schubert 
355*7f2fe78bSCy Schubert     if (ev_success == FALSE) {
356*7f2fe78bSCy Schubert         /* KDC status msg. */
357*7f2fe78bSCy Schubert         ret = string_to_value(state->status, obj, AU_KDC_STATUS);
358*7f2fe78bSCy Schubert         if (ret)
359*7f2fe78bSCy Schubert             goto error;
360*7f2fe78bSCy Schubert         /* Local policy or S4U protocol constraints. */
361*7f2fe78bSCy Schubert         ret = int32_to_value(state->violation, obj, AU_VIOLATION);
362*7f2fe78bSCy Schubert         if (ret)
363*7f2fe78bSCy Schubert             goto error;
364*7f2fe78bSCy Schubert     }
365*7f2fe78bSCy Schubert     /* Delegated user. */
366*7f2fe78bSCy Schubert     if (req != NULL) {
367*7f2fe78bSCy Schubert         ret = princ_to_value(req->second_ticket[0]->enc_part2->client,
368*7f2fe78bSCy Schubert                              obj, AU_REQ_S4U2P_USER);
369*7f2fe78bSCy Schubert         if (ret)
370*7f2fe78bSCy Schubert             goto error;
371*7f2fe78bSCy Schubert     }
372*7f2fe78bSCy Schubert     ret = k5_json_encode(obj, jout);
373*7f2fe78bSCy Schubert 
374*7f2fe78bSCy Schubert error:
375*7f2fe78bSCy Schubert     k5_json_release(obj);
376*7f2fe78bSCy Schubert     return ret;
377*7f2fe78bSCy Schubert }
378*7f2fe78bSCy Schubert 
379*7f2fe78bSCy Schubert /* U2U. Returns 0 on success. */
380*7f2fe78bSCy Schubert krb5_error_code
kau_j_tgs_u2u(const krb5_boolean ev_success,krb5_audit_state * state,char ** jout)381*7f2fe78bSCy Schubert kau_j_tgs_u2u(const krb5_boolean ev_success, krb5_audit_state *state,
382*7f2fe78bSCy Schubert               char **jout)
383*7f2fe78bSCy Schubert {
384*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
385*7f2fe78bSCy Schubert     k5_json_object obj = NULL;
386*7f2fe78bSCy Schubert     krb5_kdc_req *req = state->request;
387*7f2fe78bSCy Schubert 
388*7f2fe78bSCy Schubert     if (!state) {
389*7f2fe78bSCy Schubert         *jout = NULL_STATE;
390*7f2fe78bSCy Schubert         return 0;
391*7f2fe78bSCy Schubert     }
392*7f2fe78bSCy Schubert 
393*7f2fe78bSCy Schubert     *jout = NULL;
394*7f2fe78bSCy Schubert 
395*7f2fe78bSCy Schubert     /* Main object. */
396*7f2fe78bSCy Schubert     if (k5_json_object_create(&obj))
397*7f2fe78bSCy Schubert         return ENOMEM;
398*7f2fe78bSCy Schubert     /* Audit Event ID and ev_success. */
399*7f2fe78bSCy Schubert     ret = eventinfo_to_value(obj, "U2U", state->stage, ev_success);
400*7f2fe78bSCy Schubert     if (ret)
401*7f2fe78bSCy Schubert         goto error;
402*7f2fe78bSCy Schubert     /* Front-end server's TGT ticket ID. */
403*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_in_id, obj, AU_TKT_IN_ID);
404*7f2fe78bSCy Schubert     if (ret)
405*7f2fe78bSCy Schubert         goto error;
406*7f2fe78bSCy Schubert     /* Service ticket ID. */
407*7f2fe78bSCy Schubert     ret = string_to_value(state->tkt_out_id, obj, AU_TKT_OUT_ID);
408*7f2fe78bSCy Schubert     if (ret)
409*7f2fe78bSCy Schubert         goto error;
410*7f2fe78bSCy Schubert     /* Request ID. */
411*7f2fe78bSCy Schubert     ret = string_to_value(state->req_id, obj, AU_REQ_ID);
412*7f2fe78bSCy Schubert     if (ret)
413*7f2fe78bSCy Schubert         goto error;
414*7f2fe78bSCy Schubert 
415*7f2fe78bSCy Schubert     if (ev_success == FALSE) {
416*7f2fe78bSCy Schubert         /* KDC status msg. */
417*7f2fe78bSCy Schubert         ret = string_to_value(state->status, obj, AU_KDC_STATUS);
418*7f2fe78bSCy Schubert         if (ret)
419*7f2fe78bSCy Schubert             goto error;
420*7f2fe78bSCy Schubert     }
421*7f2fe78bSCy Schubert     /* Client in the second ticket. */
422*7f2fe78bSCy Schubert     if (req != NULL) {
423*7f2fe78bSCy Schubert         ret = princ_to_value(req->second_ticket[0]->enc_part2->client,
424*7f2fe78bSCy Schubert                              obj, AU_REQ_U2U_USER);
425*7f2fe78bSCy Schubert         if (ret)
426*7f2fe78bSCy Schubert             goto error;
427*7f2fe78bSCy Schubert     }
428*7f2fe78bSCy Schubert     /* Enctype of a session key of the second ticket. */
429*7f2fe78bSCy Schubert     ret = int32_to_value(req->second_ticket[0]->enc_part2->session->enctype,
430*7f2fe78bSCy Schubert                          obj, AU_SRV_ETYPE);
431*7f2fe78bSCy Schubert     if (ret)
432*7f2fe78bSCy Schubert         goto error;
433*7f2fe78bSCy Schubert 
434*7f2fe78bSCy Schubert     ret = k5_json_encode(obj, jout);
435*7f2fe78bSCy Schubert 
436*7f2fe78bSCy Schubert error:
437*7f2fe78bSCy Schubert     k5_json_release(obj);
438*7f2fe78bSCy Schubert     return ret;
439*7f2fe78bSCy Schubert }
440*7f2fe78bSCy Schubert 
441*7f2fe78bSCy Schubert /* Low level utilities */
442*7f2fe78bSCy Schubert 
443*7f2fe78bSCy Schubert /* Converts string into a property of a JSON object. Returns 0 on success.*/
444*7f2fe78bSCy Schubert static krb5_error_code
string_to_value(const char * in,k5_json_object obj,const char * key)445*7f2fe78bSCy Schubert string_to_value(const char *in, k5_json_object obj, const char *key)
446*7f2fe78bSCy Schubert {
447*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
448*7f2fe78bSCy Schubert     k5_json_string str = NULL;
449*7f2fe78bSCy Schubert 
450*7f2fe78bSCy Schubert     if (in == NULL)
451*7f2fe78bSCy Schubert         return 0;
452*7f2fe78bSCy Schubert 
453*7f2fe78bSCy Schubert     ret = k5_json_string_create(in, &str);
454*7f2fe78bSCy Schubert     if (ret)
455*7f2fe78bSCy Schubert         return ret;
456*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, key, str);
457*7f2fe78bSCy Schubert     k5_json_release(str);
458*7f2fe78bSCy Schubert 
459*7f2fe78bSCy Schubert     return ret;
460*7f2fe78bSCy Schubert }
461*7f2fe78bSCy Schubert 
462*7f2fe78bSCy Schubert /*
463*7f2fe78bSCy Schubert  * Converts a krb5_data struct into a property of a JSON object.
464*7f2fe78bSCy Schubert  * (Borrowed from preauth_otp.c)
465*7f2fe78bSCy Schubert  * Returns 0 on success.
466*7f2fe78bSCy Schubert  */
467*7f2fe78bSCy Schubert static krb5_error_code
data_to_value(krb5_data * data,k5_json_object obj,const char * key)468*7f2fe78bSCy Schubert data_to_value(krb5_data *data, k5_json_object obj, const char *key)
469*7f2fe78bSCy Schubert {
470*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
471*7f2fe78bSCy Schubert     k5_json_string str = NULL;
472*7f2fe78bSCy Schubert 
473*7f2fe78bSCy Schubert     if (data == NULL || data->data == NULL || data->length < 1)
474*7f2fe78bSCy Schubert         return 0;
475*7f2fe78bSCy Schubert 
476*7f2fe78bSCy Schubert     ret = k5_json_string_create_len(data->data, data->length, &str);
477*7f2fe78bSCy Schubert     if (ret)
478*7f2fe78bSCy Schubert         return ret;
479*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, key, str);
480*7f2fe78bSCy Schubert     k5_json_release(str);
481*7f2fe78bSCy Schubert 
482*7f2fe78bSCy Schubert     return ret;
483*7f2fe78bSCy Schubert }
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert /*
486*7f2fe78bSCy Schubert  * Converts krb5_int32 into a property of a JSON object.
487*7f2fe78bSCy Schubert  * Returns 0 on success.
488*7f2fe78bSCy Schubert  */
489*7f2fe78bSCy Schubert static krb5_error_code
int32_to_value(krb5_int32 int32,k5_json_object obj,const char * key)490*7f2fe78bSCy Schubert int32_to_value(krb5_int32 int32, k5_json_object obj, const char *key)
491*7f2fe78bSCy Schubert {
492*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
493*7f2fe78bSCy Schubert     k5_json_number num = NULL;
494*7f2fe78bSCy Schubert 
495*7f2fe78bSCy Schubert     ret = k5_json_number_create(int32, &num);
496*7f2fe78bSCy Schubert     if (ret)
497*7f2fe78bSCy Schubert         return ENOMEM;
498*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, key, num);
499*7f2fe78bSCy Schubert     k5_json_release(num);
500*7f2fe78bSCy Schubert 
501*7f2fe78bSCy Schubert     return ret;
502*7f2fe78bSCy Schubert }
503*7f2fe78bSCy Schubert 
504*7f2fe78bSCy Schubert /*
505*7f2fe78bSCy Schubert  * Converts krb5_boolean into a property of a JSON object.
506*7f2fe78bSCy Schubert  * Returns 0 on success.
507*7f2fe78bSCy Schubert  */
508*7f2fe78bSCy Schubert static krb5_error_code
bool_to_value(krb5_boolean in,k5_json_object obj,const char * key)509*7f2fe78bSCy Schubert bool_to_value(krb5_boolean in, k5_json_object obj, const char *key)
510*7f2fe78bSCy Schubert {
511*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
512*7f2fe78bSCy Schubert     k5_json_bool b = 0;
513*7f2fe78bSCy Schubert 
514*7f2fe78bSCy Schubert     ret = k5_json_bool_create(in, &b);
515*7f2fe78bSCy Schubert     if (ret)
516*7f2fe78bSCy Schubert         return ENOMEM;
517*7f2fe78bSCy Schubert 
518*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, key, b);
519*7f2fe78bSCy Schubert     k5_json_release(b);
520*7f2fe78bSCy Schubert 
521*7f2fe78bSCy Schubert     return ret;
522*7f2fe78bSCy Schubert }
523*7f2fe78bSCy Schubert 
524*7f2fe78bSCy Schubert /* Wrapper-level utilities */
525*7f2fe78bSCy Schubert 
526*7f2fe78bSCy Schubert /* Wrapper for stage and event_status tags. Returns 0 on success. */
527*7f2fe78bSCy Schubert static krb5_error_code
eventinfo_to_value(k5_json_object obj,const char * name,const int stage,const krb5_boolean ev_success)528*7f2fe78bSCy Schubert eventinfo_to_value(k5_json_object obj, const char *name,
529*7f2fe78bSCy Schubert                    const int stage, const krb5_boolean ev_success)
530*7f2fe78bSCy Schubert {
531*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
532*7f2fe78bSCy Schubert 
533*7f2fe78bSCy Schubert     ret = string_to_value(name, obj, AU_EVENT_NAME);
534*7f2fe78bSCy Schubert     if (ret)
535*7f2fe78bSCy Schubert         return ret;
536*7f2fe78bSCy Schubert     ret = int32_to_value(stage, obj, AU_STAGE);
537*7f2fe78bSCy Schubert     if (!ret)
538*7f2fe78bSCy Schubert         ret = bool_to_value(ev_success, obj, AU_EVENT_STATUS);
539*7f2fe78bSCy Schubert 
540*7f2fe78bSCy Schubert     return ret;
541*7f2fe78bSCy Schubert }
542*7f2fe78bSCy Schubert 
543*7f2fe78bSCy Schubert /*
544*7f2fe78bSCy Schubert  * Converts krb5_principal into a property of a JSON object.
545*7f2fe78bSCy Schubert  * Returns 0 on success.
546*7f2fe78bSCy Schubert  */
547*7f2fe78bSCy Schubert static krb5_error_code
princ_to_value(krb5_principal princ,k5_json_object obj,const char * key)548*7f2fe78bSCy Schubert princ_to_value(krb5_principal princ, k5_json_object obj, const char *key)
549*7f2fe78bSCy Schubert {
550*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
551*7f2fe78bSCy Schubert     k5_json_object tmp = NULL;
552*7f2fe78bSCy Schubert     k5_json_array arr = NULL;
553*7f2fe78bSCy Schubert     k5_json_string str = NULL;
554*7f2fe78bSCy Schubert     int i = 0;
555*7f2fe78bSCy Schubert 
556*7f2fe78bSCy Schubert     if (princ == NULL || princ->data == NULL)
557*7f2fe78bSCy Schubert         return 0;
558*7f2fe78bSCy Schubert 
559*7f2fe78bSCy Schubert     /* Main object. */
560*7f2fe78bSCy Schubert     if (k5_json_object_create(&tmp))
561*7f2fe78bSCy Schubert         return ENOMEM;
562*7f2fe78bSCy Schubert 
563*7f2fe78bSCy Schubert     ret = k5_json_array_create(&arr);
564*7f2fe78bSCy Schubert     if (ret)
565*7f2fe78bSCy Schubert         goto error;
566*7f2fe78bSCy Schubert     for (i = 0; i < princ->length; i++) {
567*7f2fe78bSCy Schubert         ret = k5_json_string_create_len((&princ->data[i])->data,
568*7f2fe78bSCy Schubert                                        (&princ->data[i])->length, &str);
569*7f2fe78bSCy Schubert         if (ret)
570*7f2fe78bSCy Schubert             goto error;
571*7f2fe78bSCy Schubert         ret = k5_json_array_add(arr, str);
572*7f2fe78bSCy Schubert         k5_json_release(str);
573*7f2fe78bSCy Schubert         if (ret)
574*7f2fe78bSCy Schubert             goto error;
575*7f2fe78bSCy Schubert     }
576*7f2fe78bSCy Schubert     ret = k5_json_object_set(tmp, AU_COMPONENTS, arr);
577*7f2fe78bSCy Schubert     if (ret)
578*7f2fe78bSCy Schubert         goto error;
579*7f2fe78bSCy Schubert     ret = data_to_value(&princ->realm, tmp, AU_REALM);
580*7f2fe78bSCy Schubert     if (ret)
581*7f2fe78bSCy Schubert         goto error;
582*7f2fe78bSCy Schubert     ret = int32_to_value(princ->length, tmp, AU_LENGTH);
583*7f2fe78bSCy Schubert     if (ret)
584*7f2fe78bSCy Schubert         goto error;
585*7f2fe78bSCy Schubert     ret = int32_to_value(princ->type, tmp, AU_TYPE);
586*7f2fe78bSCy Schubert     if (ret)
587*7f2fe78bSCy Schubert         goto error;
588*7f2fe78bSCy Schubert 
589*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, key, tmp);
590*7f2fe78bSCy Schubert 
591*7f2fe78bSCy Schubert error:
592*7f2fe78bSCy Schubert     k5_json_release(tmp);
593*7f2fe78bSCy Schubert     k5_json_release(arr);
594*7f2fe78bSCy Schubert     return ret;
595*7f2fe78bSCy Schubert }
596*7f2fe78bSCy Schubert 
597*7f2fe78bSCy Schubert /*
598*7f2fe78bSCy Schubert  * Helper for JSON encoding of krb5_address.
599*7f2fe78bSCy Schubert  * Returns 0 on success.
600*7f2fe78bSCy Schubert  */
601*7f2fe78bSCy Schubert static krb5_error_code
addr_to_obj(krb5_address * a,k5_json_object obj)602*7f2fe78bSCy Schubert addr_to_obj(krb5_address *a, k5_json_object obj)
603*7f2fe78bSCy Schubert {
604*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
605*7f2fe78bSCy Schubert     k5_json_number num = NULL;
606*7f2fe78bSCy Schubert     k5_json_array arr = NULL;
607*7f2fe78bSCy Schubert     int i;
608*7f2fe78bSCy Schubert 
609*7f2fe78bSCy Schubert     if (a == NULL || a->contents == NULL || a->length <= 0)
610*7f2fe78bSCy Schubert         return 0;
611*7f2fe78bSCy Schubert 
612*7f2fe78bSCy Schubert     ret = int32_to_value(a->addrtype, obj, AU_TYPE);
613*7f2fe78bSCy Schubert     if (ret)
614*7f2fe78bSCy Schubert         goto error;
615*7f2fe78bSCy Schubert     ret = int32_to_value(a->length, obj, AU_LENGTH);
616*7f2fe78bSCy Schubert     if (ret)
617*7f2fe78bSCy Schubert         goto error;
618*7f2fe78bSCy Schubert 
619*7f2fe78bSCy Schubert     if (a->addrtype == ADDRTYPE_INET || a->addrtype == ADDRTYPE_INET6) {
620*7f2fe78bSCy Schubert         ret = k5_json_array_create(&arr);
621*7f2fe78bSCy Schubert         if (ret)
622*7f2fe78bSCy Schubert             goto error;
623*7f2fe78bSCy Schubert         for (i = 0; i < (int)a->length; i++) {
624*7f2fe78bSCy Schubert             ret = k5_json_number_create(a->contents[i], &num);
625*7f2fe78bSCy Schubert             if (ret)
626*7f2fe78bSCy Schubert                 goto error;
627*7f2fe78bSCy Schubert             ret = k5_json_array_add(arr, num);
628*7f2fe78bSCy Schubert             k5_json_release(num);
629*7f2fe78bSCy Schubert             if (ret)
630*7f2fe78bSCy Schubert                 goto error;
631*7f2fe78bSCy Schubert         }
632*7f2fe78bSCy Schubert         ret = k5_json_object_set(obj, AU_IP, arr);
633*7f2fe78bSCy Schubert         if (ret)
634*7f2fe78bSCy Schubert             goto error;
635*7f2fe78bSCy Schubert     }
636*7f2fe78bSCy Schubert 
637*7f2fe78bSCy Schubert error:
638*7f2fe78bSCy Schubert     k5_json_release(arr);
639*7f2fe78bSCy Schubert     return ret;
640*7f2fe78bSCy Schubert }
641*7f2fe78bSCy Schubert 
642*7f2fe78bSCy Schubert /*
643*7f2fe78bSCy Schubert  * Converts krb5_fulladdr into a property of a JSON object.
644*7f2fe78bSCy Schubert  * Returns 0 on success.
645*7f2fe78bSCy Schubert  */
646*7f2fe78bSCy Schubert static krb5_error_code
addr_to_value(const krb5_address * address,k5_json_object obj,const char * key)647*7f2fe78bSCy Schubert addr_to_value(const krb5_address *address, k5_json_object obj, const char *key)
648*7f2fe78bSCy Schubert {
649*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
650*7f2fe78bSCy Schubert     k5_json_object addr_obj = NULL;
651*7f2fe78bSCy Schubert 
652*7f2fe78bSCy Schubert     if (address == NULL)
653*7f2fe78bSCy Schubert         return 0;
654*7f2fe78bSCy Schubert 
655*7f2fe78bSCy Schubert     ret = k5_json_object_create(&addr_obj);
656*7f2fe78bSCy Schubert     if (ret)
657*7f2fe78bSCy Schubert         return ret;
658*7f2fe78bSCy Schubert     ret = addr_to_obj((krb5_address *)address, addr_obj);
659*7f2fe78bSCy Schubert     if (!ret)
660*7f2fe78bSCy Schubert         ret = k5_json_object_set(obj, key, addr_obj);
661*7f2fe78bSCy Schubert     k5_json_release(addr_obj);
662*7f2fe78bSCy Schubert 
663*7f2fe78bSCy Schubert     return ret;
664*7f2fe78bSCy Schubert }
665*7f2fe78bSCy Schubert 
666*7f2fe78bSCy Schubert /*
667*7f2fe78bSCy Schubert  * Helper for JSON encoding of krb5_kdc_req.
668*7f2fe78bSCy Schubert  * Returns 0 on success.
669*7f2fe78bSCy Schubert  */
670*7f2fe78bSCy Schubert static krb5_error_code
req_to_value(krb5_kdc_req * req,const krb5_boolean ev_success,k5_json_object obj)671*7f2fe78bSCy Schubert req_to_value(krb5_kdc_req *req, const krb5_boolean ev_success,
672*7f2fe78bSCy Schubert              k5_json_object obj)
673*7f2fe78bSCy Schubert {
674*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
675*7f2fe78bSCy Schubert     k5_json_number num = NULL;
676*7f2fe78bSCy Schubert     k5_json_string str = NULL;
677*7f2fe78bSCy Schubert     k5_json_object tmpa = NULL;
678*7f2fe78bSCy Schubert     k5_json_array arr = NULL, arra = NULL, arrpa = NULL;
679*7f2fe78bSCy Schubert     krb5_pa_data **padata;
680*7f2fe78bSCy Schubert     int i = 0;
681*7f2fe78bSCy Schubert 
682*7f2fe78bSCy Schubert     if (req == NULL)
683*7f2fe78bSCy Schubert         return 0;
684*7f2fe78bSCy Schubert 
685*7f2fe78bSCy Schubert     ret = princ_to_value(req->client, obj, AU_REQ_CLIENT);
686*7f2fe78bSCy Schubert     if (ret)
687*7f2fe78bSCy Schubert         goto error;
688*7f2fe78bSCy Schubert     ret = princ_to_value(req->server, obj, AU_REQ_SERVER);
689*7f2fe78bSCy Schubert     if (ret)
690*7f2fe78bSCy Schubert         goto error;
691*7f2fe78bSCy Schubert 
692*7f2fe78bSCy Schubert     ret = int32_to_value(req->kdc_options, obj, AU_REQ_KDC_OPTIONS);
693*7f2fe78bSCy Schubert         if (ret)
694*7f2fe78bSCy Schubert             goto error;
695*7f2fe78bSCy Schubert     ret = int32_to_value(req->from, obj, AU_REQ_TKT_START);
696*7f2fe78bSCy Schubert         if (ret)
697*7f2fe78bSCy Schubert             goto error;
698*7f2fe78bSCy Schubert     ret = int32_to_value(req->till, obj, AU_REQ_TKT_END);
699*7f2fe78bSCy Schubert         if (ret)
700*7f2fe78bSCy Schubert             goto error;
701*7f2fe78bSCy Schubert     ret = int32_to_value(req->rtime, obj, AU_REQ_TKT_RENEW_TILL);
702*7f2fe78bSCy Schubert         if (ret)
703*7f2fe78bSCy Schubert             goto error;
704*7f2fe78bSCy Schubert     /* Available/requested enctypes. */
705*7f2fe78bSCy Schubert     ret = k5_json_array_create(&arr);
706*7f2fe78bSCy Schubert     if (ret)
707*7f2fe78bSCy Schubert         goto error;
708*7f2fe78bSCy Schubert     for (i = 0; (i < req->nktypes); i++) {
709*7f2fe78bSCy Schubert         if (req->ktype[i] > 0) {
710*7f2fe78bSCy Schubert             ret = k5_json_number_create(req->ktype[i], &num);
711*7f2fe78bSCy Schubert             if (ret)
712*7f2fe78bSCy Schubert                 goto error;
713*7f2fe78bSCy Schubert             ret = k5_json_array_add(arr, num);
714*7f2fe78bSCy Schubert             k5_json_release(num);
715*7f2fe78bSCy Schubert             if (ret)
716*7f2fe78bSCy Schubert                 goto error;
717*7f2fe78bSCy Schubert         }
718*7f2fe78bSCy Schubert     }
719*7f2fe78bSCy Schubert     ret = k5_json_object_set(obj, AU_REQ_AVAIL_ETYPES, arr);
720*7f2fe78bSCy Schubert     if (ret)
721*7f2fe78bSCy Schubert         goto error;
722*7f2fe78bSCy Schubert     /* Pre-auth types. */
723*7f2fe78bSCy Schubert     if (ev_success == TRUE && req->padata) {
724*7f2fe78bSCy Schubert             ret = k5_json_array_create(&arrpa);
725*7f2fe78bSCy Schubert             if (ret)
726*7f2fe78bSCy Schubert                 goto error;
727*7f2fe78bSCy Schubert             for (padata = req->padata; *padata; padata++) {
728*7f2fe78bSCy Schubert                 if (strlen(map_patype((*padata)->pa_type)) > 1) {
729*7f2fe78bSCy Schubert                     ret = k5_json_string_create(map_patype((*padata)->pa_type),
730*7f2fe78bSCy Schubert                                                 &str);
731*7f2fe78bSCy Schubert                     if (ret)
732*7f2fe78bSCy Schubert                         goto error;
733*7f2fe78bSCy Schubert                     ret = k5_json_array_add(arrpa, str);
734*7f2fe78bSCy Schubert                     k5_json_release(str);
735*7f2fe78bSCy Schubert                     if (ret)
736*7f2fe78bSCy Schubert                         goto error;
737*7f2fe78bSCy Schubert                 }
738*7f2fe78bSCy Schubert             }
739*7f2fe78bSCy Schubert             ret = k5_json_object_set(obj, AU_REQ_PA_TYPE, arrpa);
740*7f2fe78bSCy Schubert     }
741*7f2fe78bSCy Schubert     /* List of requested addresses. */
742*7f2fe78bSCy Schubert     if (req->addresses) {
743*7f2fe78bSCy Schubert         ret = k5_json_array_create(&arra);
744*7f2fe78bSCy Schubert         if (ret)
745*7f2fe78bSCy Schubert                 goto error;
746*7f2fe78bSCy Schubert         for (i = 0; req->addresses[i] != NULL; i++) {
747*7f2fe78bSCy Schubert             ret = k5_json_object_create(&tmpa);
748*7f2fe78bSCy Schubert             if (ret)
749*7f2fe78bSCy Schubert                 goto error;
750*7f2fe78bSCy Schubert             ret = addr_to_obj(req->addresses[i], tmpa);
751*7f2fe78bSCy Schubert             if (!ret)
752*7f2fe78bSCy Schubert                 ret = k5_json_array_add(arra, tmpa);
753*7f2fe78bSCy Schubert             k5_json_release(tmpa);
754*7f2fe78bSCy Schubert             if (ret)
755*7f2fe78bSCy Schubert                 goto error;
756*7f2fe78bSCy Schubert         }
757*7f2fe78bSCy Schubert         ret = k5_json_object_set(obj, AU_REQ_ADDRESSES, arra);
758*7f2fe78bSCy Schubert         if (ret)
759*7f2fe78bSCy Schubert             goto error;
760*7f2fe78bSCy Schubert     }
761*7f2fe78bSCy Schubert error:
762*7f2fe78bSCy Schubert     k5_json_release(arr);
763*7f2fe78bSCy Schubert     k5_json_release(arra);
764*7f2fe78bSCy Schubert     k5_json_release(arrpa);
765*7f2fe78bSCy Schubert     return ret;
766*7f2fe78bSCy Schubert }
767*7f2fe78bSCy Schubert 
768*7f2fe78bSCy Schubert /*
769*7f2fe78bSCy Schubert  * Helper for JSON encoding of krb5_kdc_rep.
770*7f2fe78bSCy Schubert  * Returns 0 on success.
771*7f2fe78bSCy Schubert  */
772*7f2fe78bSCy Schubert static krb5_error_code
rep_to_value(krb5_kdc_rep * rep,const krb5_boolean ev_success,k5_json_object obj)773*7f2fe78bSCy Schubert rep_to_value(krb5_kdc_rep *rep, const krb5_boolean ev_success,
774*7f2fe78bSCy Schubert              k5_json_object obj)
775*7f2fe78bSCy Schubert {
776*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
777*7f2fe78bSCy Schubert     krb5_pa_data **padata;
778*7f2fe78bSCy Schubert     k5_json_array arrpa = NULL;
779*7f2fe78bSCy Schubert     k5_json_string str = NULL;
780*7f2fe78bSCy Schubert 
781*7f2fe78bSCy Schubert     if (rep == NULL)
782*7f2fe78bSCy Schubert         return 0;
783*7f2fe78bSCy Schubert 
784*7f2fe78bSCy Schubert     if (ev_success == TRUE) {
785*7f2fe78bSCy Schubert         ret = tkt_to_value(rep->ticket, obj, AU_REP_TICKET);
786*7f2fe78bSCy Schubert         /* Enctype of the reply-encrypting key. */
787*7f2fe78bSCy Schubert         ret = int32_to_value(rep->enc_part.enctype, obj, AU_REP_ETYPE);
788*7f2fe78bSCy Schubert         if (ret)
789*7f2fe78bSCy Schubert             goto error;
790*7f2fe78bSCy Schubert     } else {
791*7f2fe78bSCy Schubert 
792*7f2fe78bSCy Schubert         if (rep->padata) {
793*7f2fe78bSCy Schubert             ret = k5_json_array_create(&arrpa);
794*7f2fe78bSCy Schubert             if (ret)
795*7f2fe78bSCy Schubert                 goto error;
796*7f2fe78bSCy Schubert             for (padata = rep->padata; *padata; padata++) {
797*7f2fe78bSCy Schubert                 if (strlen(map_patype((*padata)->pa_type)) > 1) {
798*7f2fe78bSCy Schubert                     ret = k5_json_string_create(map_patype((*padata)->pa_type),
799*7f2fe78bSCy Schubert                                                           &str);
800*7f2fe78bSCy Schubert                     if (ret)
801*7f2fe78bSCy Schubert                         goto error;
802*7f2fe78bSCy Schubert                     ret = k5_json_array_add(arrpa, str);
803*7f2fe78bSCy Schubert                     k5_json_release(str);
804*7f2fe78bSCy Schubert                     if (ret)
805*7f2fe78bSCy Schubert                         goto error;
806*7f2fe78bSCy Schubert                 }
807*7f2fe78bSCy Schubert             }
808*7f2fe78bSCy Schubert         }
809*7f2fe78bSCy Schubert         ret = k5_json_object_set(obj, AU_REP_PA_TYPE, arrpa);
810*7f2fe78bSCy Schubert     }
811*7f2fe78bSCy Schubert error:
812*7f2fe78bSCy Schubert     k5_json_release(arrpa);
813*7f2fe78bSCy Schubert     return ret;
814*7f2fe78bSCy Schubert }
815*7f2fe78bSCy Schubert 
816*7f2fe78bSCy Schubert /*
817*7f2fe78bSCy Schubert  * Converts krb5_ticket into a property of a JSON object.
818*7f2fe78bSCy Schubert  * Returns 0 on success.
819*7f2fe78bSCy Schubert  */
820*7f2fe78bSCy Schubert static krb5_error_code
tkt_to_value(krb5_ticket * tkt,k5_json_object obj,const char * key)821*7f2fe78bSCy Schubert tkt_to_value(krb5_ticket *tkt, k5_json_object obj,
822*7f2fe78bSCy Schubert               const char *key)
823*7f2fe78bSCy Schubert {
824*7f2fe78bSCy Schubert     krb5_error_code ret = 0;
825*7f2fe78bSCy Schubert     k5_json_object tmp = NULL;
826*7f2fe78bSCy Schubert     krb5_enc_tkt_part *part2 = NULL;
827*7f2fe78bSCy Schubert 
828*7f2fe78bSCy Schubert     if (tkt == NULL)
829*7f2fe78bSCy Schubert         return 0;
830*7f2fe78bSCy Schubert 
831*7f2fe78bSCy Schubert     /* Main object. */
832*7f2fe78bSCy Schubert     if (k5_json_object_create(&tmp))
833*7f2fe78bSCy Schubert         return ENOMEM;
834*7f2fe78bSCy Schubert 
835*7f2fe78bSCy Schubert     /*
836*7f2fe78bSCy Schubert      * CNAME - potentially redundant data...
837*7f2fe78bSCy Schubert      * ...but it is part of the ticket. So, record it as such.
838*7f2fe78bSCy Schubert      */
839*7f2fe78bSCy Schubert     ret = princ_to_value(tkt->server, tmp, AU_CNAME);
840*7f2fe78bSCy Schubert     if (ret)
841*7f2fe78bSCy Schubert         goto error;
842*7f2fe78bSCy Schubert     ret = princ_to_value(tkt->server, tmp, AU_SNAME);
843*7f2fe78bSCy Schubert     if (ret)
844*7f2fe78bSCy Schubert         goto error;
845*7f2fe78bSCy Schubert     /* Enctype of a long-term key of service. */
846*7f2fe78bSCy Schubert     if (tkt->enc_part.enctype)
847*7f2fe78bSCy Schubert         ret = int32_to_value(tkt->enc_part.enctype, tmp, AU_SRV_ETYPE);
848*7f2fe78bSCy Schubert     if (ret)
849*7f2fe78bSCy Schubert         goto error;
850*7f2fe78bSCy Schubert     if (tkt->enc_part2)
851*7f2fe78bSCy Schubert         part2 = tkt->enc_part2;
852*7f2fe78bSCy Schubert     if (part2) {
853*7f2fe78bSCy Schubert         ret = princ_to_value(part2->client, tmp, AU_CNAME);
854*7f2fe78bSCy Schubert         if (ret)
855*7f2fe78bSCy Schubert             goto error;
856*7f2fe78bSCy Schubert         ret = int32_to_value(part2->flags, tmp, AU_FLAGS);
857*7f2fe78bSCy Schubert         if (ret)
858*7f2fe78bSCy Schubert             goto error;
859*7f2fe78bSCy Schubert         /* Chosen by KDC session key enctype (short-term key). */
860*7f2fe78bSCy Schubert         ret = int32_to_value(part2->session->enctype, tmp, AU_SESS_ETYPE);
861*7f2fe78bSCy Schubert         if (ret)
862*7f2fe78bSCy Schubert             goto error;
863*7f2fe78bSCy Schubert         ret = int32_to_value(part2->times.starttime, tmp, AU_START);
864*7f2fe78bSCy Schubert         if (ret)
865*7f2fe78bSCy Schubert             goto error;
866*7f2fe78bSCy Schubert         ret = int32_to_value(part2->times.endtime, tmp, AU_END);
867*7f2fe78bSCy Schubert         if (ret)
868*7f2fe78bSCy Schubert             goto error;
869*7f2fe78bSCy Schubert         ret = int32_to_value(part2->times.renew_till, tmp, AU_RENEW_TILL);
870*7f2fe78bSCy Schubert         if (ret)
871*7f2fe78bSCy Schubert             goto error;
872*7f2fe78bSCy Schubert         ret = int32_to_value(part2->times.authtime, tmp, AU_AUTHTIME);
873*7f2fe78bSCy Schubert         if (ret)
874*7f2fe78bSCy Schubert             goto error;
875*7f2fe78bSCy Schubert         if (part2->transited.tr_contents.length > 0) {
876*7f2fe78bSCy Schubert             ret = data_to_value(&part2->transited.tr_contents,
877*7f2fe78bSCy Schubert                                tmp, AU_TR_CONTENTS);
878*7f2fe78bSCy Schubert             if (ret)
879*7f2fe78bSCy Schubert                 goto error;
880*7f2fe78bSCy Schubert         }
881*7f2fe78bSCy Schubert     } /* part2 != NULL */
882*7f2fe78bSCy Schubert 
883*7f2fe78bSCy Schubert     if (!ret)
884*7f2fe78bSCy Schubert         ret = k5_json_object_set(obj, key, tmp);
885*7f2fe78bSCy Schubert 
886*7f2fe78bSCy Schubert error:
887*7f2fe78bSCy Schubert     k5_json_release(tmp);
888*7f2fe78bSCy Schubert     return ret;
889*7f2fe78bSCy Schubert }
890*7f2fe78bSCy Schubert 
891*7f2fe78bSCy Schubert /* Map preauth numeric type to the naming string. */
892*7f2fe78bSCy Schubert struct _patype_str {
893*7f2fe78bSCy Schubert     krb5_preauthtype id;
894*7f2fe78bSCy Schubert     char *name;
895*7f2fe78bSCy Schubert };
896*7f2fe78bSCy Schubert struct _patype_str  patype_str[] = {
897*7f2fe78bSCy Schubert     {KRB5_PADATA_ENC_TIMESTAMP, "ENC_TIMESTAMP"},
898*7f2fe78bSCy Schubert     {KRB5_PADATA_PW_SALT, "PW_SALT"},
899*7f2fe78bSCy Schubert     {KRB5_PADATA_ENC_UNIX_TIME, "ENC_UNIX_TIME"},
900*7f2fe78bSCy Schubert     {KRB5_PADATA_SAM_CHALLENGE, "SAM_CHALLENGE"},
901*7f2fe78bSCy Schubert     {KRB5_PADATA_SAM_RESPONSE, "SAM_RESPONSE"},
902*7f2fe78bSCy Schubert     {KRB5_PADATA_PK_AS_REQ_OLD, "PK_AS_REQ_OLD"},
903*7f2fe78bSCy Schubert     {KRB5_PADATA_PK_AS_REP_OLD, "PK_AS_REP_OLD"},
904*7f2fe78bSCy Schubert     {KRB5_PADATA_PK_AS_REQ, "PK_AS_REQ"},
905*7f2fe78bSCy Schubert     {KRB5_PADATA_PK_AS_REP, "PK_AS_REP"},
906*7f2fe78bSCy Schubert     {KRB5_PADATA_ETYPE_INFO2, "ETYPE_INFO2"},
907*7f2fe78bSCy Schubert     {KRB5_PADATA_SAM_CHALLENGE_2, "SAM_CHALLENGE_2"},
908*7f2fe78bSCy Schubert     {KRB5_PADATA_SAM_RESPONSE_2, "SAM_RESPONSE_2"},
909*7f2fe78bSCy Schubert     {KRB5_PADATA_PAC_REQUEST, "PAC_REQUEST"},
910*7f2fe78bSCy Schubert     {KRB5_PADATA_FOR_USER, "FOR_USER"},
911*7f2fe78bSCy Schubert     {KRB5_PADATA_S4U_X509_USER, "S4U_X509_USER"},
912*7f2fe78bSCy Schubert     {KRB5_PADATA_ENCRYPTED_CHALLENGE, "ENCRYPTED_CHALLENGE"},
913*7f2fe78bSCy Schubert     {KRB5_PADATA_OTP_CHALLENGE, "OTP_CHALLENGE"},
914*7f2fe78bSCy Schubert     {KRB5_PADATA_OTP_REQUEST, "OTP_REQUEST"},
915*7f2fe78bSCy Schubert     {KRB5_PADATA_OTP_PIN_CHANGE, "OTP_PIN_CHANGE"}
916*7f2fe78bSCy Schubert };
917*7f2fe78bSCy Schubert 
918*7f2fe78bSCy Schubert 
919*7f2fe78bSCy Schubert static char *
map_patype(krb5_preauthtype pa_type)920*7f2fe78bSCy Schubert map_patype(krb5_preauthtype pa_type)
921*7f2fe78bSCy Schubert {
922*7f2fe78bSCy Schubert     int i = 0;
923*7f2fe78bSCy Schubert     int n = sizeof(patype_str)/sizeof(patype_str[0]);
924*7f2fe78bSCy Schubert 
925*7f2fe78bSCy Schubert     for (i = 0; i < n; i++) {
926*7f2fe78bSCy Schubert         if (pa_type == patype_str[i].id)
927*7f2fe78bSCy Schubert             return patype_str[i].name;
928*7f2fe78bSCy Schubert     }
929*7f2fe78bSCy Schubert     return "";
930*7f2fe78bSCy Schubert }
931