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