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