Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/kprop/kproplog.c
34869 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
4
* Use is subject to license terms.
5
*/
6
7
/*
8
* This module will parse the update logs on the primary or replica servers.
9
*/
10
11
#include "k5-int.h"
12
#include "k5-hex.h"
13
#include <locale.h>
14
#include <sys/types.h>
15
#include <sys/mman.h>
16
#include <time.h>
17
#include <limits.h>
18
#include <locale.h>
19
#include <syslog.h>
20
#include <kdb_log.h>
21
#include <kadm5/admin.h>
22
#include <adm_proto.h>
23
24
static char *progname;
25
26
static void
27
usage(void)
28
{
29
fprintf(stderr, _("\nUsage: %s [-h] [-v] [-v] [-e num]\n\t%s -R\n\n"),
30
progname, progname);
31
exit(1);
32
}
33
34
/*
35
* Print the attribute flags of principal in human readable form.
36
*/
37
static void
38
print_flags(unsigned int flags)
39
{
40
char **attrstrs, **sp;
41
42
if (krb5_flags_to_strings(flags, &attrstrs) != 0) {
43
printf("\t\t\t(error)\n");
44
return;
45
}
46
for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) {
47
printf("\t\t\t%s\n", *sp);
48
free(*sp);
49
}
50
free(attrstrs);
51
}
52
53
/* ctime() for uint32_t* */
54
static const char *
55
ctime_uint32(uint32_t *time32)
56
{
57
time_t tmp;
58
const char *r;
59
60
tmp = *time32;
61
r = ctime(&tmp);
62
return (r == NULL) ? "(error)" : r;
63
}
64
65
/* Display time information. */
66
static void
67
print_time(uint32_t *timep)
68
{
69
if (*timep == 0L)
70
printf("\t\t\tNone\n");
71
else
72
printf("\t\t\t%s", ctime_uint32(timep));
73
}
74
75
static void
76
print_deltat(uint32_t *deltat)
77
{
78
krb5_error_code ret;
79
static char buf[30];
80
81
ret = krb5_deltat_to_string(*deltat, buf, sizeof(buf));
82
if (ret)
83
printf("\t\t\t(error)\n");
84
else
85
printf("\t\t\t%s\n", buf);
86
}
87
88
/* Display string in hex primitive. */
89
static void
90
print_hex(const char *tag, utf8str_t *str)
91
{
92
unsigned int len;
93
char *hex;
94
95
len = str->utf8str_t_len;
96
97
if (k5_hex_encode(str->utf8str_t_val, len, FALSE, &hex) != 0)
98
abort();
99
printf("\t\t\t%s(%d): 0x%s\n", tag, len, hex);
100
free(hex);
101
}
102
103
/* Display string primitive. */
104
static void
105
print_str(const char *tag, utf8str_t *str)
106
{
107
krb5_error_code ret;
108
char *s;
109
110
s = k5memdup0(str->utf8str_t_val, str->utf8str_t_len, &ret);
111
if (s == NULL) {
112
fprintf(stderr, _("\nCouldn't allocate memory"));
113
exit(1);
114
}
115
printf("\t\t\t%s(%d): %s\n", tag, str->utf8str_t_len, s);
116
free(s);
117
}
118
119
/* Display data components. */
120
static void
121
print_data(const char *tag, kdbe_data_t *data)
122
{
123
printf("\t\t\tmagic: 0x%x\n", data->k_magic);
124
print_str(tag, &data->k_data);
125
}
126
127
/* Display the principal components. */
128
static void
129
print_princ(kdbe_princ_t *princ)
130
{
131
int i, len;
132
kdbe_data_t *data;
133
134
print_str("realm", &princ->k_realm);
135
136
len = princ->k_components.k_components_len;
137
data = princ->k_components.k_components_val;
138
for (i = 0; i < len; i++, data++)
139
print_data("princ", data);
140
}
141
142
/* Display individual key. */
143
static void
144
print_key(kdbe_key_t *k)
145
{
146
unsigned int i;
147
utf8str_t *str;
148
149
printf("\t\t\tver: %d\n", k->k_ver);
150
printf("\t\t\tkvno: %d\n", k->k_kvno);
151
152
for (i = 0; i < k->k_enctype.k_enctype_len; i++)
153
printf("\t\t\tenc type: 0x%x\n", k->k_enctype.k_enctype_val[i]);
154
155
str = k->k_contents.k_contents_val;
156
for (i = 0; i < k->k_contents.k_contents_len; i++, str++)
157
print_hex("key", str);
158
}
159
160
/* Display all key data. */
161
static void
162
print_keydata(kdbe_key_t *keys, unsigned int len)
163
{
164
unsigned int i;
165
166
for (i = 0; i < len; i++, keys++)
167
print_key(keys);
168
}
169
170
/* Display TL item. */
171
static void
172
print_tl(kdbe_tl_t *tl)
173
{
174
int i, len;
175
176
printf("\t\t\ttype: 0x%x\n", tl->tl_type);
177
178
len = tl->tl_data.tl_data_len;
179
180
printf("\t\t\tvalue(%d): 0x", len);
181
for (i = 0; i < len; i++)
182
printf("%02x", (krb5_octet)tl->tl_data.tl_data_val[i]);
183
printf("\n");
184
}
185
186
/* Display TL data items. */
187
static void
188
print_tldata(kdbe_tl_t *tldata, int len)
189
{
190
int i;
191
192
printf("\t\t\titems: %d\n", len);
193
for (i = 0; i < len; i++, tldata++)
194
print_tl(tldata);
195
}
196
197
/*
198
* Print the individual types if verbose mode was specified.
199
* If verbose-verbose then print types along with respective values.
200
*/
201
static void
202
print_attr(kdbe_val_t *val, int vverbose)
203
{
204
switch (val->av_type) {
205
case AT_ATTRFLAGS:
206
printf(_("\t\tAttribute flags\n"));
207
if (vverbose)
208
print_flags(val->kdbe_val_t_u.av_attrflags);
209
break;
210
case AT_MAX_LIFE:
211
printf(_("\t\tMaximum ticket life\n"));
212
if (vverbose)
213
print_deltat(&val->kdbe_val_t_u.av_max_life);
214
break;
215
case AT_MAX_RENEW_LIFE:
216
printf(_("\t\tMaximum renewable life\n"));
217
if (vverbose)
218
print_deltat(&val->kdbe_val_t_u.av_max_renew_life);
219
break;
220
case AT_EXP:
221
printf(_("\t\tPrincipal expiration\n"));
222
if (vverbose)
223
print_time(&val->kdbe_val_t_u.av_exp);
224
break;
225
case AT_PW_EXP:
226
printf(_("\t\tPassword expiration\n"));
227
if (vverbose)
228
print_time(&val->kdbe_val_t_u.av_pw_exp);
229
break;
230
case AT_LAST_SUCCESS:
231
printf(_("\t\tLast successful auth\n"));
232
if (vverbose)
233
print_time(&val->kdbe_val_t_u.av_last_success);
234
break;
235
case AT_LAST_FAILED:
236
printf(_("\t\tLast failed auth\n"));
237
if (vverbose)
238
print_time(&val->kdbe_val_t_u.av_last_failed);
239
break;
240
case AT_FAIL_AUTH_COUNT:
241
printf(_("\t\tFailed passwd attempt\n"));
242
if (vverbose)
243
printf("\t\t\t%d\n", val->kdbe_val_t_u.av_fail_auth_count);
244
break;
245
case AT_PRINC:
246
printf(_("\t\tPrincipal\n"));
247
if (vverbose)
248
print_princ(&val->kdbe_val_t_u.av_princ);
249
break;
250
case AT_KEYDATA:
251
printf(_("\t\tKey data\n"));
252
if (vverbose) {
253
print_keydata(val->kdbe_val_t_u.av_keydata.av_keydata_val,
254
val->kdbe_val_t_u.av_keydata.av_keydata_len);
255
}
256
break;
257
case AT_TL_DATA:
258
printf(_("\t\tTL data\n"));
259
if (vverbose) {
260
print_tldata(val->kdbe_val_t_u.av_tldata.av_tldata_val,
261
val->kdbe_val_t_u.av_tldata.av_tldata_len);
262
}
263
break;
264
case AT_LEN:
265
printf(_("\t\tLength\n"));
266
if (vverbose)
267
printf("\t\t\t%d\n", val->kdbe_val_t_u.av_len);
268
break;
269
case AT_PW_LAST_CHANGE:
270
printf(_("\t\tPassword last changed\n"));
271
if (vverbose)
272
print_time(&val->kdbe_val_t_u.av_pw_last_change);
273
break;
274
case AT_MOD_PRINC:
275
printf(_("\t\tModifying principal\n"));
276
if (vverbose)
277
print_princ(&val->kdbe_val_t_u.av_mod_princ);
278
break;
279
case AT_MOD_TIME:
280
printf(_("\t\tModification time\n"));
281
if (vverbose)
282
print_time(&val->kdbe_val_t_u.av_mod_time);
283
break;
284
case AT_MOD_WHERE:
285
printf(_("\t\tModified where\n"));
286
if (vverbose)
287
print_str("where", &val->kdbe_val_t_u.av_mod_where);
288
break;
289
case AT_PW_POLICY:
290
printf(_("\t\tPassword policy\n"));
291
if (vverbose)
292
print_str("policy", &val->kdbe_val_t_u.av_pw_policy);
293
break;
294
case AT_PW_POLICY_SWITCH:
295
printf(_("\t\tPassword policy switch\n"));
296
if (vverbose)
297
printf("\t\t\t%d\n", val->kdbe_val_t_u.av_pw_policy_switch);
298
break;
299
case AT_PW_HIST_KVNO:
300
printf(_("\t\tPassword history KVNO\n"));
301
if (vverbose)
302
printf("\t\t\t%d\n", val->kdbe_val_t_u.av_pw_hist_kvno);
303
break;
304
case AT_PW_HIST:
305
printf(_("\t\tPassword history\n"));
306
if (vverbose)
307
printf("\t\t\tPW history elided\n");
308
break;
309
} /* switch */
310
311
}
312
/*
313
* Print the update entry information
314
*/
315
static void
316
print_update(kdb_hlog_t *ulog, uint32_t entry, uint32_t ulogentries,
317
unsigned int verbose)
318
{
319
XDR xdrs;
320
uint32_t start_sno, i, j, indx;
321
char *dbprinc;
322
kdb_ent_header_t *indx_log;
323
kdb_incr_update_t upd;
324
325
if (entry && (entry < ulog->kdb_num))
326
start_sno = ulog->kdb_last_sno - entry;
327
else
328
start_sno = ulog->kdb_first_sno - 1;
329
330
for (i = start_sno; i < ulog->kdb_last_sno; i++) {
331
indx = i % ulogentries;
332
333
indx_log = ulog_index(ulog, indx);
334
335
/*
336
* Check for corrupt update entry
337
*/
338
if (indx_log->kdb_umagic != KDB_ULOG_MAGIC) {
339
fprintf(stderr, _("Corrupt update entry\n\n"));
340
exit(1);
341
}
342
343
printf("---\n");
344
printf(_("Update Entry\n"));
345
346
printf(_("\tUpdate serial # : %u\n"), indx_log->kdb_entry_sno);
347
348
/* The initial entry after a reset is a dummy entry; skip it. */
349
if (indx_log->kdb_entry_size == 0) {
350
printf(_("\tDummy entry\n"));
351
continue;
352
}
353
354
memset(&upd, 0, sizeof(kdb_incr_update_t));
355
xdrmem_create(&xdrs, (char *)indx_log->entry_data,
356
indx_log->kdb_entry_size, XDR_DECODE);
357
if (!xdr_kdb_incr_update_t(&xdrs, &upd)) {
358
printf(_("Entry data decode failure\n\n"));
359
exit(1);
360
}
361
362
printf(_("\tUpdate operation : "));
363
if (upd.kdb_deleted)
364
printf(_("Delete\n"));
365
else
366
printf(_("Add\n"));
367
368
dbprinc = malloc(upd.kdb_princ_name.utf8str_t_len + 1);
369
if (dbprinc == NULL) {
370
printf(_("Could not allocate principal name\n\n"));
371
exit(1);
372
}
373
strncpy(dbprinc, upd.kdb_princ_name.utf8str_t_val,
374
upd.kdb_princ_name.utf8str_t_len);
375
dbprinc[upd.kdb_princ_name.utf8str_t_len] = 0;
376
printf(_("\tUpdate principal : %s\n"), dbprinc);
377
378
printf(_("\tUpdate size : %u\n"), indx_log->kdb_entry_size);
379
printf(_("\tUpdate committed : %s\n"),
380
indx_log->kdb_commit ? "True" : "False");
381
382
if (indx_log->kdb_time.seconds == 0L) {
383
printf(_("\tUpdate time stamp : None\n"));
384
} else{
385
printf(_("\tUpdate time stamp : %s"),
386
ctime_uint32(&indx_log->kdb_time.seconds));
387
}
388
389
printf(_("\tAttributes changed : %d\n"), upd.kdb_update.kdbe_t_len);
390
391
if (verbose) {
392
for (j = 0; j < upd.kdb_update.kdbe_t_len; j++)
393
print_attr(&upd.kdb_update.kdbe_t_val[j], verbose > 1 ? 1 : 0);
394
}
395
396
xdr_free((xdrproc_t)xdr_kdb_incr_update_t, (char *)&upd);
397
free(dbprinc);
398
}
399
}
400
401
/* Return a read-only mmap of the ulog, or NULL on failure. */
402
static kdb_hlog_t *
403
map_ulog(const char *filename, int *fd_out)
404
{
405
int fd;
406
struct stat st;
407
kdb_hlog_t *ulog = MAP_FAILED;
408
409
*fd_out = -1;
410
411
fd = open(filename, O_RDONLY);
412
if (fd == -1)
413
return NULL;
414
if (fstat(fd, &st) < 0) {
415
close(fd);
416
return NULL;
417
}
418
ulog = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
419
if (ulog == MAP_FAILED) {
420
close(fd);
421
return NULL;
422
}
423
*fd_out = fd;
424
return ulog;
425
}
426
427
int
428
main(int argc, char **argv)
429
{
430
int c, ulog_fd = -1;
431
unsigned int verbose = 0;
432
bool_t headeronly = FALSE, reset = FALSE;
433
uint32_t entry = 0;
434
krb5_context context;
435
kadm5_config_params params;
436
kdb_hlog_t *ulog = NULL;
437
438
setlocale(LC_ALL, "");
439
440
progname = argv[0];
441
442
while ((c = getopt(argc, argv, "Rvhe:")) != -1) {
443
switch (c) {
444
case 'h':
445
headeronly = TRUE;
446
break;
447
case 'e':
448
entry = atoi(optarg);
449
break;
450
case 'R':
451
reset = TRUE;
452
break;
453
case 'v':
454
verbose++;
455
break;
456
default:
457
usage();
458
}
459
}
460
461
if (kadm5_init_krb5_context(&context)) {
462
fprintf(stderr, _("Unable to initialize Kerberos\n\n"));
463
exit(1);
464
}
465
466
memset(&params, 0, sizeof(params));
467
468
if (kadm5_get_config_params(context, 1, &params, &params)) {
469
fprintf(stderr, _("Couldn't read database_name\n\n"));
470
exit(1);
471
}
472
473
printf(_("\nKerberos update log (%s)\n"), params.iprop_logfile);
474
475
if (reset) {
476
if (ulog_map(context, params.iprop_logfile, params.iprop_ulogsize)) {
477
fprintf(stderr, _("Unable to map log file %s\n\n"),
478
params.iprop_logfile);
479
exit(1);
480
}
481
if (ulog_init_header(context) != 0) {
482
fprintf(stderr, _("Couldn't reinitialize ulog file %s\n\n"),
483
params.iprop_logfile);
484
exit(1);
485
}
486
printf(_("Reinitialized the ulog.\n"));
487
ulog_fini(context);
488
goto done;
489
}
490
491
ulog = map_ulog(params.iprop_logfile, &ulog_fd);
492
if (ulog == NULL) {
493
fprintf(stderr, _("Unable to map log file %s\n\n"),
494
params.iprop_logfile);
495
exit(1);
496
}
497
498
if (ulog->kdb_hmagic != KDB_ULOG_HDR_MAGIC) {
499
fprintf(stderr, _("Corrupt header log, exiting\n\n"));
500
exit(1);
501
}
502
503
printf(_("Update log dump :\n"));
504
printf(_("\tLog version # : %u\n"), ulog->db_version_num);
505
printf(_("\tLog state : "));
506
switch (ulog->kdb_state) {
507
case KDB_STABLE:
508
printf(_("Stable\n"));
509
break;
510
case KDB_UNSTABLE:
511
printf(_("Unstable\n"));
512
break;
513
case KDB_CORRUPT:
514
printf(_("Corrupt\n"));
515
break;
516
default:
517
printf(_("Unknown state: %d\n"), ulog->kdb_state);
518
break;
519
}
520
printf(_("\tEntry block size : %u\n"), ulog->kdb_block);
521
printf(_("\tNumber of entries : %u\n"), ulog->kdb_num);
522
523
if (ulog->kdb_last_sno == 0) {
524
printf(_("\tLast serial # : None\n"));
525
} else {
526
if (ulog->kdb_first_sno == 0) {
527
printf(_("\tFirst serial # : None\n"));
528
} else {
529
printf(_("\tFirst serial # : "));
530
printf("%u\n", ulog->kdb_first_sno);
531
}
532
533
printf(_("\tLast serial # : "));
534
printf("%u\n", ulog->kdb_last_sno);
535
}
536
537
if (ulog->kdb_last_time.seconds == 0L) {
538
printf(_("\tLast time stamp : None\n"));
539
} else {
540
if (ulog->kdb_first_time.seconds == 0L) {
541
printf(_("\tFirst time stamp : None\n"));
542
} else {
543
printf(_("\tFirst time stamp : %s"),
544
ctime_uint32(&ulog->kdb_first_time.seconds));
545
}
546
547
printf(_("\tLast time stamp : %s\n"),
548
ctime_uint32(&ulog->kdb_last_time.seconds));
549
}
550
551
if (!headeronly && ulog->kdb_num)
552
print_update(ulog, entry, params.iprop_ulogsize, verbose);
553
554
printf("\n");
555
556
done:
557
close(ulog_fd);
558
kadm5_free_config_params(context, &params);
559
krb5_free_context(context);
560
return 0;
561
}
562
563