Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/clients/klist/klist.c
34914 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* clients/klist/klist.c - List contents of credential cache or keytab */
3
/*
4
* Copyright 1990 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
#include "k5-int.h"
28
#include <krb5.h>
29
#include <com_err.h>
30
#include <locale.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <stdio.h>
34
#include <time.h>
35
36
/* Need definition of INET6 before network headers, for IRIX. */
37
#if defined(HAVE_ARPA_INET_H)
38
#include <arpa/inet.h>
39
#endif
40
41
#ifndef _WIN32
42
#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x))
43
#else
44
#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
45
#endif
46
47
#ifndef _WIN32
48
#include <sys/socket.h>
49
#include <netdb.h>
50
#endif
51
52
int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
53
int show_etype = 0, show_addresses = 0, no_resolve = 0, print_version = 0;
54
int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0;
55
int show_config = 0;
56
char *progname;
57
krb5_timestamp now;
58
unsigned int timestamp_width;
59
60
krb5_context context;
61
62
static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm);
63
static char *etype_string(krb5_enctype );
64
static void show_credential(krb5_creds *, const char *);
65
66
static void list_all_ccaches(void);
67
static int list_ccache(krb5_ccache);
68
static void show_all_ccaches(void);
69
static void do_ccache(void);
70
static int show_ccache(krb5_ccache);
71
static int check_ccache(krb5_ccache);
72
static void do_keytab(const char *);
73
static void printtime(krb5_timestamp);
74
static void one_addr(krb5_address *);
75
static void fillit(FILE *, unsigned int, int);
76
77
#define DEFAULT 0
78
#define CCACHE 1
79
#define KEYTAB 2
80
81
static void
82
usage(void)
83
{
84
fprintf(stderr, _("Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] "
85
"[-a [-n]]] [-k [-i] [-t] [-K]] [-C] [name]\n"),
86
progname);
87
fprintf(stderr, _("\t-c specifies credentials cache\n"));
88
fprintf(stderr, _("\t-k specifies keytab\n"));
89
fprintf(stderr, _("\t (Default is credentials cache)\n"));
90
fprintf(stderr, _("\t-i uses default client keytab if no name given\n"));
91
fprintf(stderr, _("\t-l lists credential caches in collection\n"));
92
fprintf(stderr, _("\t-A shows content of all credential caches\n"));
93
fprintf(stderr, _("\t-e shows the encryption type\n"));
94
fprintf(stderr, _("\t-V shows the Kerberos version and exits\n"));
95
fprintf(stderr, _("\toptions for credential caches:\n"));
96
fprintf(stderr, _("\t\t-d shows the submitted authorization data "
97
"types\n"));
98
fprintf(stderr, _("\t\t-f shows credentials flags\n"));
99
fprintf(stderr, _("\t\t-s sets exit status based on valid tgt "
100
"existence\n"));
101
fprintf(stderr, _("\t\t-a displays the address list\n"));
102
fprintf(stderr, _("\t\t\t-n do not reverse-resolve\n"));
103
fprintf(stderr, _("\toptions for keytabs:\n"));
104
fprintf(stderr, _("\t\t-t shows keytab entry timestamps\n"));
105
fprintf(stderr, _("\t\t-K shows keytab entry keys\n"));
106
fprintf(stderr, _("\t\t-C includes configuration data entries\n"));
107
exit(1);
108
}
109
110
static void
111
extended_com_err_fn(const char *prog, errcode_t code, const char *fmt,
112
va_list args)
113
{
114
const char *msg;
115
116
msg = krb5_get_error_message(context, code);
117
fprintf(stderr, "%s: %s%s", prog, msg, (*fmt == '\0') ? "" : " ");
118
krb5_free_error_message(context, msg);
119
vfprintf(stderr, fmt, args);
120
fprintf(stderr, "\n");
121
}
122
123
int
124
main(int argc, char *argv[])
125
{
126
krb5_error_code ret;
127
char *name, tmp[BUFSIZ];
128
int c, mode;
129
130
setlocale(LC_ALL, "");
131
progname = GET_PROGNAME(argv[0]);
132
set_com_err_hook(extended_com_err_fn);
133
134
name = NULL;
135
mode = DEFAULT;
136
/* V = version so v can be used for verbose later if desired. */
137
while ((c = getopt(argc, argv, "dfetKsnacki45lAVC")) != -1) {
138
switch (c) {
139
case 'd':
140
show_adtype = 1;
141
break;
142
case 'f':
143
show_flags = 1;
144
break;
145
case 'e':
146
show_etype = 1;
147
break;
148
case 't':
149
show_time = 1;
150
break;
151
case 'K':
152
show_keys = 1;
153
break;
154
case 's':
155
status_only = 1;
156
break;
157
case 'n':
158
no_resolve = 1;
159
break;
160
case 'a':
161
show_addresses = 1;
162
break;
163
case 'c':
164
if (mode != DEFAULT)
165
usage();
166
mode = CCACHE;
167
break;
168
case 'k':
169
if (mode != DEFAULT)
170
usage();
171
mode = KEYTAB;
172
break;
173
case 'i':
174
use_client_keytab = 1;
175
break;
176
case '4':
177
fprintf(stderr, _("Kerberos 4 is no longer supported\n"));
178
exit(3);
179
break;
180
case '5':
181
break;
182
case 'l':
183
list_all = 1;
184
break;
185
case 'A':
186
show_all = 1;
187
break;
188
case 'C':
189
show_config = 1;
190
break;
191
case 'V':
192
print_version = 1;
193
break;
194
default:
195
usage();
196
break;
197
}
198
}
199
200
if (no_resolve && !show_addresses)
201
usage();
202
203
if (mode == DEFAULT || mode == CCACHE) {
204
if (show_time || show_keys)
205
usage();
206
if ((show_all && list_all) || (status_only && list_all))
207
usage();
208
} else {
209
if (show_flags || status_only || show_addresses ||
210
show_all || list_all)
211
usage();
212
}
213
214
if (argc - optind > 1) {
215
fprintf(stderr, _("Extra arguments (starting with \"%s\").\n"),
216
argv[optind + 1]);
217
usage();
218
}
219
220
if (print_version) {
221
#ifdef _WIN32 /* No access to autoconf vars; fix somehow. */
222
printf("Kerberos for Windows\n");
223
#else
224
printf(_("%s version %s\n"), PACKAGE_NAME, PACKAGE_VERSION);
225
#endif
226
exit(0);
227
}
228
229
name = (optind == argc - 1) ? argv[optind] : NULL;
230
now = time(0);
231
232
if (!krb5_timestamp_to_sfstring(now, tmp, 20, NULL) ||
233
!krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), NULL))
234
timestamp_width = (int)strlen(tmp);
235
else
236
timestamp_width = 15;
237
238
ret = krb5_init_context(&context);
239
if (ret) {
240
com_err(progname, ret, _("while initializing krb5"));
241
exit(1);
242
}
243
244
if (name != NULL && mode != KEYTAB) {
245
ret = krb5_cc_set_default_name(context, name);
246
if (ret) {
247
com_err(progname, ret, _("while setting default cache name"));
248
exit(1);
249
}
250
}
251
252
if (list_all)
253
list_all_ccaches();
254
else if (show_all)
255
show_all_ccaches();
256
else if (mode == DEFAULT || mode == CCACHE)
257
do_ccache();
258
else
259
do_keytab(name);
260
return 0;
261
}
262
263
static void
264
do_keytab(const char *name)
265
{
266
krb5_error_code ret;
267
krb5_keytab kt;
268
krb5_keytab_entry entry;
269
krb5_kt_cursor cursor;
270
unsigned int i;
271
char buf[BUFSIZ]; /* Hopefully large enough for any type */
272
char *pname;
273
274
if (name == NULL && use_client_keytab) {
275
ret = krb5_kt_client_default(context, &kt);
276
if (ret) {
277
com_err(progname, ret, _("while getting default client keytab"));
278
exit(1);
279
}
280
} else if (name == NULL) {
281
ret = krb5_kt_default(context, &kt);
282
if (ret) {
283
com_err(progname, ret, _("while getting default keytab"));
284
exit(1);
285
}
286
} else {
287
ret = krb5_kt_resolve(context, name, &kt);
288
if (ret) {
289
com_err(progname, ret, _("while resolving keytab %s"), name);
290
exit(1);
291
}
292
}
293
294
ret = krb5_kt_get_name(context, kt, buf, BUFSIZ);
295
if (ret) {
296
com_err(progname, ret, _("while getting keytab name"));
297
exit(1);
298
}
299
300
printf("Keytab name: %s\n", buf);
301
302
ret = krb5_kt_start_seq_get(context, kt, &cursor);
303
if (ret) {
304
com_err(progname, ret, _("while starting keytab scan"));
305
exit(1);
306
}
307
308
/* XXX Translating would disturb table alignment; skip for now. */
309
if (show_time) {
310
printf("KVNO Timestamp");
311
fillit(stdout, timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
312
printf("Principal\n");
313
printf("---- ");
314
fillit(stdout, timestamp_width, (int) '-');
315
printf(" ");
316
fillit(stdout, 78 - timestamp_width - sizeof("KVNO"), (int) '-');
317
printf("\n");
318
} else {
319
printf("KVNO Principal\n");
320
printf("---- ------------------------------------------------"
321
"--------------------------\n");
322
}
323
324
while ((ret = krb5_kt_next_entry(context, kt, &entry, &cursor)) == 0) {
325
ret = krb5_unparse_name(context, entry.principal, &pname);
326
if (ret) {
327
com_err(progname, ret, _("while unparsing principal name"));
328
exit(1);
329
}
330
printf("%4d ", entry.vno);
331
if (show_time) {
332
printtime(entry.timestamp);
333
printf(" ");
334
}
335
printf("%s", pname);
336
if (show_etype)
337
printf(" (%s) " , etype_string(entry.key.enctype));
338
if (show_keys) {
339
printf(" (0x");
340
for (i = 0; i < entry.key.length; i++)
341
printf("%02x", entry.key.contents[i]);
342
printf(")");
343
}
344
printf("\n");
345
krb5_free_unparsed_name(context, pname);
346
krb5_free_keytab_entry_contents(context, &entry);
347
}
348
if (ret && ret != KRB5_KT_END) {
349
com_err(progname, ret, _("while scanning keytab"));
350
exit(1);
351
}
352
ret = krb5_kt_end_seq_get(context, kt, &cursor);
353
if (ret) {
354
com_err(progname, ret, _("while ending keytab scan"));
355
exit(1);
356
}
357
exit(0);
358
}
359
360
static void
361
list_all_ccaches(void)
362
{
363
krb5_error_code ret;
364
krb5_ccache cache;
365
krb5_cccol_cursor cursor;
366
int exit_status;
367
368
ret = krb5_cccol_cursor_new(context, &cursor);
369
if (ret) {
370
if (!status_only)
371
com_err(progname, ret, _("while listing ccache collection"));
372
exit(1);
373
}
374
375
/* XXX Translating would disturb table alignment; skip for now. */
376
printf("%-30s %s\n", "Principal name", "Cache name");
377
printf("%-30s %s\n", "--------------", "----------");
378
exit_status = 1;
379
while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 &&
380
cache != NULL) {
381
exit_status = list_ccache(cache) && exit_status;
382
krb5_cc_close(context, cache);
383
}
384
krb5_cccol_cursor_free(context, &cursor);
385
exit(exit_status);
386
}
387
388
static int
389
list_ccache(krb5_ccache cache)
390
{
391
krb5_error_code ret;
392
krb5_principal princ = NULL;
393
char *princname = NULL, *ccname = NULL;
394
int expired, status = 1;
395
396
ret = krb5_cc_get_principal(context, cache, &princ);
397
if (ret) /* Uninitialized cache file, probably. */
398
goto cleanup;
399
ret = krb5_unparse_name(context, princ, &princname);
400
if (ret)
401
goto cleanup;
402
ret = krb5_cc_get_full_name(context, cache, &ccname);
403
if (ret)
404
goto cleanup;
405
406
expired = check_ccache(cache);
407
408
printf("%-30.30s %s", princname, ccname);
409
if (expired)
410
printf(" %s", _("(Expired)"));
411
printf("\n");
412
413
status = 0;
414
415
cleanup:
416
krb5_free_principal(context, princ);
417
krb5_free_unparsed_name(context, princname);
418
krb5_free_string(context, ccname);
419
return status;
420
}
421
422
static void
423
show_all_ccaches(void)
424
{
425
krb5_error_code ret;
426
krb5_ccache cache;
427
krb5_cccol_cursor cursor;
428
krb5_boolean first;
429
int exit_status, st;
430
431
ret = krb5_cccol_cursor_new(context, &cursor);
432
if (ret) {
433
if (!status_only)
434
com_err(progname, ret, _("while listing ccache collection"));
435
exit(1);
436
}
437
exit_status = 1;
438
first = TRUE;
439
while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 &&
440
cache != NULL) {
441
if (!status_only && !first)
442
printf("\n");
443
first = FALSE;
444
st = status_only ? check_ccache(cache) : show_ccache(cache);
445
exit_status = st && exit_status;
446
krb5_cc_close(context, cache);
447
}
448
krb5_cccol_cursor_free(context, &cursor);
449
exit(exit_status);
450
}
451
452
static void
453
do_ccache(void)
454
{
455
krb5_error_code ret;
456
krb5_ccache cache;
457
458
ret = krb5_cc_default(context, &cache);
459
if (ret) {
460
if (!status_only)
461
com_err(progname, ret, _("while resolving ccache"));
462
exit(1);
463
}
464
exit(status_only ? check_ccache(cache) : show_ccache(cache));
465
}
466
467
/* Display the contents of cache. */
468
static int
469
show_ccache(krb5_ccache cache)
470
{
471
krb5_cc_cursor cur = NULL;
472
krb5_creds creds;
473
krb5_principal princ = NULL;
474
krb5_error_code ret;
475
char *defname = NULL;
476
int status = 1;
477
478
ret = krb5_cc_get_principal(context, cache, &princ);
479
if (ret) {
480
com_err(progname, ret, "");
481
goto cleanup;
482
}
483
ret = krb5_unparse_name(context, princ, &defname);
484
if (ret) {
485
com_err(progname, ret, _("while unparsing principal name"));
486
goto cleanup;
487
}
488
489
printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"),
490
krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache),
491
defname);
492
/* XXX Translating would disturb table alignment; skip for now. */
493
fputs("Valid starting", stdout);
494
fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' ');
495
fputs("Expires", stdout);
496
fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' ');
497
fputs("Service principal\n", stdout);
498
499
ret = krb5_cc_start_seq_get(context, cache, &cur);
500
if (ret) {
501
com_err(progname, ret, _("while starting to retrieve tickets"));
502
goto cleanup;
503
}
504
while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
505
if (show_config || !krb5_is_config_principal(context, creds.server))
506
show_credential(&creds, defname);
507
krb5_free_cred_contents(context, &creds);
508
}
509
if (ret == KRB5_CC_END) {
510
ret = krb5_cc_end_seq_get(context, cache, &cur);
511
cur = NULL;
512
if (ret) {
513
com_err(progname, ret, _("while finishing ticket retrieval"));
514
goto cleanup;
515
}
516
} else {
517
com_err(progname, ret, _("while retrieving a ticket"));
518
goto cleanup;
519
}
520
521
status = 0;
522
523
cleanup:
524
if (cur != NULL)
525
(void)krb5_cc_end_seq_get(context, cache, &cur);
526
krb5_free_principal(context, princ);
527
krb5_free_unparsed_name(context, defname);
528
return status;
529
}
530
531
/* Return 0 if cache is accessible, present, and unexpired; return 1 if not. */
532
static int
533
check_ccache(krb5_ccache cache)
534
{
535
krb5_error_code ret;
536
krb5_cc_cursor cur = NULL;
537
krb5_creds creds;
538
krb5_principal princ = NULL;
539
krb5_boolean found_tgt = FALSE, found_current_tgt = FALSE;
540
krb5_boolean found_current_cred = FALSE;
541
542
ret = krb5_cc_get_principal(context, cache, &princ);
543
if (ret)
544
goto cleanup;
545
ret = krb5_cc_start_seq_get(context, cache, &cur);
546
if (ret)
547
goto cleanup;
548
found_tgt = found_current_tgt = found_current_cred = FALSE;
549
while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
550
if (is_local_tgt(creds.server, &princ->realm)) {
551
found_tgt = TRUE;
552
if (ts_after(creds.times.endtime, now))
553
found_current_tgt = TRUE;
554
} else if (!krb5_is_config_principal(context, creds.server) &&
555
ts_after(creds.times.endtime, now)) {
556
found_current_cred = TRUE;
557
}
558
krb5_free_cred_contents(context, &creds);
559
}
560
if (ret != KRB5_CC_END)
561
goto cleanup;
562
ret = krb5_cc_end_seq_get(context, cache, &cur);
563
cur = NULL;
564
565
cleanup:
566
if (cur != NULL)
567
(void)krb5_cc_end_seq_get(context, cache, &cur);
568
krb5_free_principal(context, princ);
569
if (ret)
570
return 1;
571
/* If the cache contains at least one local TGT, require that it be
572
* current. Otherwise accept any current cred. */
573
if (found_tgt)
574
return found_current_tgt ? 0 : 1;
575
return found_current_cred ? 0 : 1;
576
}
577
578
/* Return true if princ is the local krbtgt principal for local_realm. */
579
static krb5_boolean
580
is_local_tgt(krb5_principal princ, krb5_data *realm)
581
{
582
return princ->length == 2 && data_eq(princ->realm, *realm) &&
583
data_eq_string(princ->data[0], KRB5_TGS_NAME) &&
584
data_eq(princ->data[1], *realm);
585
}
586
587
static char *
588
etype_string(krb5_enctype enctype)
589
{
590
static char buf[100];
591
char *bp = buf;
592
size_t deplen, buflen = sizeof(buf);
593
594
if (krb5int_c_deprecated_enctype(enctype)) {
595
deplen = strlcpy(bp, "DEPRECATED:", buflen);
596
buflen -= deplen;
597
bp += deplen;
598
}
599
600
if (krb5_enctype_to_name(enctype, FALSE, bp, buflen))
601
snprintf(bp, buflen, "etype %d", enctype);
602
return buf;
603
}
604
605
static char *
606
flags_string(krb5_creds *cred)
607
{
608
static char buf[32];
609
int i = 0;
610
611
if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
612
buf[i++] = 'F';
613
if (cred->ticket_flags & TKT_FLG_FORWARDED)
614
buf[i++] = 'f';
615
if (cred->ticket_flags & TKT_FLG_PROXIABLE)
616
buf[i++] = 'P';
617
if (cred->ticket_flags & TKT_FLG_PROXY)
618
buf[i++] = 'p';
619
if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
620
buf[i++] = 'D';
621
if (cred->ticket_flags & TKT_FLG_POSTDATED)
622
buf[i++] = 'd';
623
if (cred->ticket_flags & TKT_FLG_INVALID)
624
buf[i++] = 'i';
625
if (cred->ticket_flags & TKT_FLG_RENEWABLE)
626
buf[i++] = 'R';
627
if (cred->ticket_flags & TKT_FLG_INITIAL)
628
buf[i++] = 'I';
629
if (cred->ticket_flags & TKT_FLG_HW_AUTH)
630
buf[i++] = 'H';
631
if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
632
buf[i++] = 'A';
633
if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED)
634
buf[i++] = 'T';
635
if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)
636
buf[i++] = 'O'; /* D/d are taken. Use short strings? */
637
if (cred->ticket_flags & TKT_FLG_ANONYMOUS)
638
buf[i++] = 'a';
639
buf[i] = '\0';
640
return buf;
641
}
642
643
static void
644
printtime(krb5_timestamp ts)
645
{
646
char timestring[BUFSIZ], fill = ' ';
647
648
if (!krb5_timestamp_to_sfstring(ts, timestring, timestamp_width + 1,
649
&fill))
650
printf("%s", timestring);
651
}
652
653
static void
654
print_config_data(int col, krb5_data *data)
655
{
656
unsigned int i;
657
658
for (i = 0; i < data->length; i++) {
659
while (col < 8) {
660
putchar(' ');
661
col++;
662
}
663
if (data->data[i] > 0x20 && data->data[i] < 0x7f) {
664
putchar(data->data[i]);
665
col++;
666
} else {
667
col += printf("\\%03o", (unsigned char)data->data[i]);
668
}
669
if (col > 72) {
670
putchar('\n');
671
col = 0;
672
}
673
}
674
if (col > 0)
675
putchar('\n');
676
}
677
678
static void
679
show_credential(krb5_creds *cred, const char *defname)
680
{
681
krb5_error_code ret;
682
krb5_ticket *tkt = NULL;
683
char *name = NULL, *sname = NULL, *tktsname, *flags;
684
int extra_field = 0, ccol = 0, i, r;
685
krb5_boolean is_config = krb5_is_config_principal(context, cred->server);
686
687
ret = krb5_unparse_name(context, cred->client, &name);
688
if (ret) {
689
com_err(progname, ret, _("while unparsing client name"));
690
goto cleanup;
691
}
692
ret = krb5_unparse_name(context, cred->server, &sname);
693
if (ret) {
694
com_err(progname, ret, _("while unparsing server name"));
695
goto cleanup;
696
}
697
if (!is_config)
698
(void)krb5_decode_ticket(&cred->ticket, &tkt);
699
if (!cred->times.starttime)
700
cred->times.starttime = cred->times.authtime;
701
702
if (!is_config) {
703
printtime(cred->times.starttime);
704
putchar(' ');
705
putchar(' ');
706
printtime(cred->times.endtime);
707
putchar(' ');
708
putchar(' ');
709
printf("%s\n", sname);
710
} else {
711
fputs("config: ", stdout);
712
ccol = 8;
713
for (i = 1; i < cred->server->length; i++) {
714
r = printf("%s%.*s%s", i > 1 ? "(" : "",
715
(int)cred->server->data[i].length,
716
cred->server->data[i].data, i > 1 ? ")" : "");
717
if (r >= 0)
718
ccol += r;
719
}
720
fputs(" = ", stdout);
721
ccol += 3;
722
}
723
724
if (strcmp(name, defname)) {
725
printf(_("\tfor client %s"), name);
726
extra_field++;
727
}
728
729
if (is_config)
730
print_config_data(ccol, &cred->ticket);
731
732
if (cred->times.renew_till) {
733
if (!extra_field)
734
fputs("\t",stdout);
735
else
736
fputs(", ",stdout);
737
fputs(_("renew until "), stdout);
738
printtime(cred->times.renew_till);
739
extra_field += 2;
740
}
741
742
if (show_flags) {
743
flags = flags_string(cred);
744
if (flags && *flags) {
745
if (!extra_field)
746
fputs("\t",stdout);
747
else
748
fputs(", ",stdout);
749
printf(_("Flags: %s"), flags);
750
extra_field++;
751
}
752
}
753
754
if (extra_field > 2) {
755
fputs("\n", stdout);
756
extra_field = 0;
757
}
758
759
if (show_etype && tkt != NULL) {
760
if (!extra_field)
761
fputs("\t",stdout);
762
else
763
fputs(", ",stdout);
764
printf(_("Etype (skey, tkt): %s, "),
765
etype_string(cred->keyblock.enctype));
766
printf("%s ", etype_string(tkt->enc_part.enctype));
767
extra_field++;
768
}
769
770
if (show_adtype) {
771
if (cred->authdata != NULL) {
772
if (!extra_field)
773
fputs("\t",stdout);
774
else
775
fputs(", ",stdout);
776
printf(_("AD types: "));
777
for (i = 0; cred->authdata[i] != NULL; i++) {
778
if (i)
779
printf(", ");
780
printf("%d", cred->authdata[i]->ad_type);
781
}
782
extra_field++;
783
}
784
}
785
786
/* If any additional info was printed, extra_field is non-zero. */
787
if (extra_field)
788
putchar('\n');
789
790
if (show_addresses) {
791
if (cred->addresses == NULL || cred->addresses[0] == NULL) {
792
printf(_("\tAddresses: (none)\n"));
793
} else {
794
printf(_("\tAddresses: "));
795
one_addr(cred->addresses[0]);
796
797
for (i = 1; cred->addresses[i] != NULL; i++) {
798
printf(", ");
799
one_addr(cred->addresses[i]);
800
}
801
802
printf("\n");
803
}
804
}
805
806
/* Display the ticket server if it is different from the server name the
807
* entry was cached under (most commonly for referrals). */
808
if (tkt != NULL &&
809
!krb5_principal_compare(context, cred->server, tkt->server)) {
810
ret = krb5_unparse_name(context, tkt->server, &tktsname);
811
if (ret) {
812
com_err(progname, ret, _("while unparsing ticket server name"));
813
goto cleanup;
814
}
815
printf(_("\tTicket server: %s\n"), tktsname);
816
krb5_free_unparsed_name(context, tktsname);
817
}
818
819
cleanup:
820
krb5_free_unparsed_name(context, name);
821
krb5_free_unparsed_name(context, sname);
822
krb5_free_ticket(context, tkt);
823
}
824
825
#include "port-sockets.h"
826
#include "socket-utils.h" /* For ss2sin etc. */
827
#include "fake-addrinfo.h"
828
829
static void
830
one_addr(krb5_address *a)
831
{
832
struct sockaddr_storage ss;
833
struct sockaddr_in *sinp;
834
struct sockaddr_in6 *sin6p;
835
int err, i;
836
char namebuf[NI_MAXHOST];
837
const uint8_t *p;
838
839
memset(&ss, 0, sizeof(ss));
840
841
switch (a->addrtype) {
842
case ADDRTYPE_INET:
843
if (a->length != 4) {
844
printf(_("broken address (type %d length %d)"),
845
a->addrtype, a->length);
846
return;
847
}
848
sinp = ss2sin(&ss);
849
sinp->sin_family = AF_INET;
850
memcpy(&sinp->sin_addr, a->contents, 4);
851
break;
852
case ADDRTYPE_INET6:
853
if (a->length != 16) {
854
printf(_("broken address (type %d length %d)"),
855
a->addrtype, a->length);
856
return;
857
}
858
sin6p = ss2sin6(&ss);
859
sin6p->sin6_family = AF_INET6;
860
memcpy(&sin6p->sin6_addr, a->contents, 16);
861
break;
862
case ADDRTYPE_NETBIOS:
863
if (a->length != 16) {
864
printf(_("broken address (type %d length %d)"),
865
a->addrtype, a->length);
866
return;
867
}
868
p = a->contents;
869
for (i = 0; i < 15 && p[i] != '\0' && p[i] != ' '; i++)
870
putchar(p[i]);
871
return;
872
default:
873
printf(_("unknown addrtype %d"), a->addrtype);
874
return;
875
}
876
877
namebuf[0] = 0;
878
err = getnameinfo(ss2sa(&ss), sa_socklen(ss2sa(&ss)), namebuf,
879
sizeof(namebuf), 0, 0,
880
no_resolve ? NI_NUMERICHOST : 0U);
881
if (err) {
882
printf(_("unprintable address (type %d, error %d %s)"), a->addrtype,
883
err, gai_strerror(err));
884
return;
885
}
886
printf("%s", namebuf);
887
}
888
889
static void
890
fillit(FILE *f, unsigned int num, int c)
891
{
892
unsigned int i;
893
894
for (i = 0; i < num; i++)
895
fputc(c, f);
896
}
897
898