1 /*
2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * clients/klist/klist.c
8 *
9 * Copyright 1990 by the Massachusetts Institute of Technology.
10 * All Rights Reserved.
11 *
12 * Export of this software from the United States of America may
13 * require a specific license from the United States Government.
14 * It is the responsibility of any person or organization contemplating
15 * export to obtain such a license before exporting.
16 *
17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18 * distribute this software and its documentation for any purpose and
19 * without fee is hereby granted, provided that the above copyright
20 * notice appear in all copies and that both that copyright notice and
21 * this permission notice appear in supporting documentation, and that
22 * the name of M.I.T. not be used in advertising or publicity pertaining
23 * to distribution of the software without specific, written prior
24 * permission. Furthermore if you modify this software you must label
25 * your software as modified software and not distribute it in such a
26 * fashion that it might be confused with the original M.I.T. software.
27 * M.I.T. makes no representations about the suitability of
28 * this software for any purpose. It is provided "as is" without express
29 * or implied warranty.
30 *
31 *
32 * List out the contents of your credential cache or keytab.
33 */
34
35 #include <k5-int.h>
36 #include "com_err.h"
37 #include <krb5.h>
38 #ifdef KRB5_KRB4_COMPAT
39 #include <kerberosIV/krb.h>
40 #endif /* KRB5_KRB4_COMPAT */
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <time.h>
46 #include <libintl.h>
47 #include <locale.h>
48 #include <netinet/in.h>
49 #if defined(HAVE_ARPA_INET_H)
50 #include <arpa/inet.h>
51 #endif
52 #include <inet/ip.h>
53 #include <inet/ip6.h>
54
55 #ifndef _WIN32
56 #define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
57 #else
58 #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
59 #endif /* _WIN32 */
60
61 #ifndef _WIN32
62 #include <sys/socket.h>
63 #include <netdb.h>
64 #endif
65
66 extern int optind;
67
68 int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
69 int show_etype = 0, show_addresses = 0, no_resolve = 0;
70 char *defname;
71 char *progname;
72 krb5_int32 now;
73 size_t timestamp_width;
74
75 krb5_context kcontext;
76
77 char * etype_string (krb5_enctype );
78 void show_credential (krb5_creds *);
79
80 void do_ccache (char *);
81 void do_keytab (char *);
82 void printtime (time_t);
83 void one_addr (krb5_address *);
84 void fillit (FILE *, unsigned int, int);
85 void show_addr(krb5_address *a);
86
87 #ifdef KRB5_KRB4_COMPAT
88 void do_v4_ccache (char *);
89 #endif /* KRB5_KRB4_COMPAT */
90
91 #define DEFAULT 0
92 #define CCACHE 1
93 #define KEYTAB 2
94
95 /*
96 * The reason we start out with got_k4 and got_k5 as zero (false) is
97 * so that we can easily add dynamic loading support for determining
98 * whether Kerberos 4 and Keberos 5 libraries are available
99 */
100
101 static int got_k5 = 0;
102 static int got_k4 = 0;
103
104 static int default_k5 = 1;
105 #ifdef KRB5_KRB4_COMPAT
106 static int default_k4 = 1;
107 #else /* KRB5_KRB4_COMPAT */
108 static int default_k4 = 0;
109 #endif /* KRB5_KRB4_COMPAT */
110
usage()111 static void usage()
112 {
113 #define KRB_AVAIL_STRING(x) ((x)?gettext("available"):gettext("not available"))
114
115 fprintf(stderr, gettext("Usage: %s [-5] [-4] [-e]"
116 " [[-c] [-f] [-s] [-a [-n]]] "
117 "[-k [-t] [-K]] [name]\n"), progname);
118 fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
119 fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
120 fprintf(stderr, gettext("\t (Default is %s%s%s%s)\n"),
121 default_k5?"Kerberos 5":"",
122 (default_k5 && default_k4)?gettext(" and "):"",
123 default_k4?"Kerberos 4":"",
124 (!default_k5 && !default_k4)?gettext("neither"):"");
125 fprintf(stderr, gettext("\t-c specifies credentials cache\n"));
126 fprintf(stderr, gettext("\t-k specifies keytab\n"));
127 fprintf(stderr, gettext("\t (Default is credentials cache)\n"));
128 fprintf(stderr, gettext("\t-e shows the encryption type\n"));
129 fprintf(stderr, gettext("\toptions for credential caches:\n"));
130 fprintf(stderr, gettext("\t\t-f shows credentials flags\n"));
131 fprintf(stderr, gettext("\t\t-s sets exit status based on valid tgt existence\n"));
132 fprintf(stderr, gettext("\t\t-a displays the address list\n"));
133 fprintf(stderr, gettext("\t\t-n do not reverse-resolve\n"));
134 fprintf(stderr, gettext("\toptions for keytabs:\n"));
135 fprintf(stderr, gettext("\t\t-t shows keytab entry timestamps\n"));
136 fprintf(stderr, gettext("\t\t-K shows keytab entry DES keys\n"));
137 exit(1);
138 }
139
140
141 int
main(argc,argv)142 main(argc, argv)
143 int argc;
144 char **argv;
145 {
146 int c;
147 char *name;
148 int mode;
149 int use_k5 = 0, use_k4 = 0;
150
151 got_k5 = 1;
152 #ifdef KRB5_KRB4_COMPAT
153 got_k4 = 1;
154 #endif /* KRB5_KRB4_COMPAT */
155
156 (void) setlocale(LC_ALL, "");
157
158 #if !defined(TEXT_DOMAIN)
159 #define TEXT_DOMAIN "SYS_TEST"
160 #endif /* !TEXT_DOMAIN */
161
162 (void) textdomain(TEXT_DOMAIN);
163
164 progname = GET_PROGNAME(argv[0]);
165
166 name = NULL;
167 mode = DEFAULT;
168 while ((c = getopt(argc, argv, "fetKsnack45")) != -1) {
169 switch (c) {
170 case 'f':
171 show_flags = 1;
172 break;
173 case 'e':
174 show_etype = 1;
175 break;
176 case 't':
177 show_time = 1;
178 break;
179 case 'K':
180 show_keys = 1;
181 break;
182 case 's':
183 status_only = 1;
184 break;
185 case 'n':
186 no_resolve = 1;
187 break;
188 case 'a':
189 show_addresses = 1;
190 break;
191 case 'c':
192 if (mode != DEFAULT) usage();
193 mode = CCACHE;
194 break;
195 case 'k':
196 if (mode != DEFAULT) usage();
197 mode = KEYTAB;
198 break;
199 case '4':
200 if (!got_k4)
201 {
202 #ifdef KRB5_KRB4_COMPAT
203 fprintf(stderr, "Kerberos 4 support could not be loaded\n");
204 #else /* KRB5_KRB4_COMPAT */
205 fprintf(stderr, gettext("This was not built with Kerberos 4 support\n"));
206 #endif /* KRB5_KRB4_COMPAT */
207 exit(3);
208 }
209 use_k4 = 1;
210 break;
211 case '5':
212 if (!got_k5)
213 {
214 fprintf(stderr, gettext("Kerberos 5 support could not be loaded\n"));
215 exit(3);
216 }
217 use_k5 = 1;
218 break;
219 default:
220 usage();
221 break;
222 }
223 }
224
225 if (no_resolve && !show_addresses) {
226 usage();
227 }
228
229 if (mode == DEFAULT || mode == CCACHE) {
230 if (show_time || show_keys)
231 usage();
232 } else {
233 if (show_flags || status_only || show_addresses)
234 usage();
235 }
236
237 if (argc - optind > 1) {
238 fprintf(stderr,
239 gettext("Extra arguments (starting with \"%s\").\n"),
240 argv[optind+1]);
241 usage();
242 }
243
244 name = (optind == argc-1) ? argv[optind] : 0;
245
246 if (!use_k5 && !use_k4)
247 {
248 use_k5 = default_k5;
249 use_k4 = default_k4;
250 }
251
252 if (!use_k5)
253 got_k5 = 0;
254 if (!use_k4)
255 got_k4 = 0;
256
257 now = time(0);
258 {
259 char tmp[BUFSIZ];
260
261 if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
262 !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp),
263 (char *) NULL))
264 timestamp_width = (int) strlen(tmp);
265 else
266 timestamp_width = 15;
267 }
268
269 if (got_k5)
270 {
271 krb5_error_code retval;
272 retval = krb5_init_context(&kcontext);
273 if (retval) {
274 com_err(progname, retval, gettext("while initializing krb5"));
275 exit(1);
276 }
277
278 if (mode == DEFAULT || mode == CCACHE)
279 do_ccache(name);
280 else
281 do_keytab(name);
282 } else {
283 #ifdef KRB5_KRB4_COMPAT
284 if (mode == DEFAULT || mode == CCACHE)
285 do_v4_ccache(name);
286 else {
287 /* We may want to add v4 srvtab support */
288 fprintf(stderr,
289 "%s: srvtab option not supported for Kerberos 4\n",
290 progname);
291 exit(1);
292 }
293 #endif /* KRB4_KRB5_COMPAT */
294 }
295
296 return 0;
297 }
298
do_keytab(name)299 void do_keytab(name)
300 char *name;
301 {
302 krb5_keytab kt;
303 krb5_keytab_entry entry;
304 krb5_kt_cursor cursor;
305 char buf[BUFSIZ]; /* hopefully large enough for any type */
306 char *pname;
307 int code;
308
309 if (name == NULL) {
310 if ((code = krb5_kt_default(kcontext, &kt))) {
311 com_err(progname, code,
312 gettext("while getting default keytab"));
313 exit(1);
314 }
315 } else {
316 if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
317 com_err(progname, code,
318 gettext("while resolving keytab %s"),
319 name);
320 exit(1);
321 }
322 }
323
324 if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
325 com_err(progname, code,
326 gettext("while getting keytab name"));
327 exit(1);
328 }
329
330 printf(gettext("Keytab name: %s\n"), buf);
331
332 if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
333 com_err(progname, code,
334 gettext("while starting keytab scan"));
335 exit(1);
336 }
337
338 if (show_time) {
339 printf(gettext("KVNO Timestamp"));
340 fillit(stdout, timestamp_width -
341 sizeof (gettext("Timestamp")) + 2, (int)' ');
342 printf(gettext("Principal\n"));
343 printf("---- ");
344 fillit(stdout, timestamp_width, (int) '-');
345 printf(" ");
346 fillit(stdout, 78 - timestamp_width -
347 sizeof (gettext("KVNO")), (int)'-');
348 printf("\n");
349 } else {
350 printf(gettext("KVNO Principal\n"));
351 printf("---- ------------------------------"
352 "--------------------------------------"
353 "------\n");
354 }
355
356 while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
357 if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
358 com_err(progname, code,
359 gettext("while unparsing principal name"));
360 exit(1);
361 }
362 printf("%4d ", entry.vno);
363 if (show_time) {
364 printtime(entry.timestamp);
365 printf(" ");
366 }
367 printf("%s", pname);
368 if (show_etype)
369 printf(" (%s) " , etype_string(entry.key.enctype));
370 if (show_keys) {
371 printf(" (0x");
372 {
373 int i;
374 for (i = 0; i < entry.key.length; i++)
375 printf("%02x", entry.key.contents[i]);
376 }
377 printf(")");
378 }
379 printf("\n");
380 krb5_free_unparsed_name(kcontext, pname);
381 }
382 if (code && code != KRB5_KT_END) {
383 com_err(progname, code,
384 gettext("while scanning keytab"));
385 exit(1);
386 }
387 if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
388 com_err(progname, code,
389 gettext("while ending keytab scan"));
390 exit(1);
391 }
392 exit(0);
393 }
do_ccache(name)394 void do_ccache(name)
395 char *name;
396 {
397 krb5_ccache cache = NULL;
398 krb5_cc_cursor cur;
399 krb5_creds creds;
400 krb5_principal princ;
401 krb5_flags flags;
402 krb5_error_code code;
403 int exit_status = 0;
404
405 if (status_only)
406 /* exit_status is set back to 0 if a valid tgt is found */
407 exit_status = 1;
408
409 if (name == NULL) {
410 if ((code = krb5_cc_default(kcontext, &cache))) {
411 if (!status_only)
412 com_err(progname, code,
413 gettext("while getting default "
414 "ccache"));
415 exit(1);
416 }
417 } else {
418 if ((code = krb5_cc_resolve(kcontext, name, &cache))) {
419 if (!status_only)
420 com_err(progname, code,
421 gettext("while resolving ccache %s"),
422 name);
423 exit(1);
424 }
425 }
426
427 flags = 0; /* turns off OPENCLOSE mode */
428 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
429 if (code == KRB5_FCC_NOFILE) {
430 if (!status_only) {
431 com_err(progname, code, gettext("(ticket cache %s:%s)"),
432 krb5_cc_get_type(kcontext, cache),
433 krb5_cc_get_name(kcontext, cache));
434 #ifdef KRB5_KRB4_COMPAT
435 if (name == NULL)
436 do_v4_ccache(0);
437 #endif /* KRB5_KRB4_COMPAT */
438 }
439 } else {
440 if (!status_only)
441 com_err(progname, code,
442 gettext("while setting cache "
443 "flags(ticket cache %s:%s)"),
444 krb5_cc_get_type(kcontext, cache),
445 krb5_cc_get_name(kcontext, cache));
446 }
447 exit(1);
448 }
449 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
450 if (!status_only)
451 com_err(progname, code,
452 gettext("while retrieving principal name"));
453 exit(1);
454 }
455 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
456 if (!status_only)
457 com_err(progname, code,
458 gettext("while unparsing principal name"));
459 exit(1);
460 }
461 if (!status_only) {
462 printf(gettext("Ticket cache: %s:%s\nDefault principal: "
463 "%s\n\n"),
464 krb5_cc_get_type(kcontext, cache),
465 krb5_cc_get_name(kcontext, cache), defname);
466 fputs(gettext("Valid starting"), stdout);
467 fillit(stdout, timestamp_width -
468 sizeof (gettext("Valid starting")) + 3, (int)' ');
469 fputs(gettext("Expires"), stdout);
470 fillit(stdout, timestamp_width -
471 sizeof (gettext("Expires")) + 3, (int)' ');
472 fputs(gettext("Service principal\n"), stdout);
473 }
474 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
475 if (!status_only)
476 com_err(progname, code,
477 gettext("while starting to retrieve tickets"));
478 exit(1);
479 }
480 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
481 if (status_only) {
482 if (exit_status && creds.server->length == 2 &&
483 strcmp(creds.server->realm.data,
484 princ->realm.data) == 0 &&
485 strcmp((char *)creds.server->data[0].data,
486 "krbtgt") == 0 &&
487 strcmp((char *)creds.server->data[1].data,
488 princ->realm.data) == 0 &&
489 creds.times.endtime > now)
490 exit_status = 0;
491 } else {
492 show_credential(&creds);
493 }
494 krb5_free_cred_contents(kcontext, &creds);
495 }
496 if (code == KRB5_CC_END) {
497 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
498 if (!status_only)
499 com_err(progname, code,
500 gettext("while finishing ticket "
501 "retrieval"));
502 exit(1);
503 }
504 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
505 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
506 if (!status_only)
507 com_err(progname, code,
508 gettext("while closing ccache"));
509 exit(1);
510 }
511 #ifdef KRB5_KRB4_COMPAT
512 if (name == NULL && !status_only)
513 do_v4_ccache(0);
514 #endif /* KRB5_KRB4_COMPAT */
515 exit(exit_status);
516 } else {
517 if (!status_only)
518 com_err(progname, code,
519 gettext("while retrieving a ticket"));
520 exit(1);
521 }
522 }
523
524 char *
etype_string(enctype)525 etype_string(enctype)
526 krb5_enctype enctype;
527 {
528 static char buf[256];
529 krb5_error_code retval;
530
531 if ((retval = krb5_enctype_to_string(enctype, buf, sizeof(buf)))) {
532 /* XXX if there's an error != EINVAL, I should probably report it */
533 snprintf(buf, sizeof(buf), gettext("unsupported encryption type %d"), enctype);
534 }
535
536 return buf;
537 }
538
539 static char *
flags_string(cred)540 flags_string(cred)
541 register krb5_creds *cred;
542 {
543 static char buf[32];
544 int i = 0;
545
546 if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
547 buf[i++] = 'F';
548 if (cred->ticket_flags & TKT_FLG_FORWARDED)
549 buf[i++] = 'f';
550 if (cred->ticket_flags & TKT_FLG_PROXIABLE)
551 buf[i++] = 'P';
552 if (cred->ticket_flags & TKT_FLG_PROXY)
553 buf[i++] = 'p';
554 if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
555 buf[i++] = 'D';
556 if (cred->ticket_flags & TKT_FLG_POSTDATED)
557 buf[i++] = 'd';
558 if (cred->ticket_flags & TKT_FLG_INVALID)
559 buf[i++] = 'i';
560 if (cred->ticket_flags & TKT_FLG_RENEWABLE)
561 buf[i++] = 'R';
562 if (cred->ticket_flags & TKT_FLG_INITIAL)
563 buf[i++] = 'I';
564 if (cred->ticket_flags & TKT_FLG_HW_AUTH)
565 buf[i++] = 'H';
566 if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
567 buf[i++] = 'A';
568 if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED)
569 buf[i++] = 'T';
570 if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)
571 buf[i++] = 'O'; /* D/d are taken. Use short strings? */
572 if (cred->ticket_flags & TKT_FLG_ANONYMOUS)
573 buf[i++] = 'a';
574 buf[i] = '\0';
575 return(buf);
576 }
577
578 void
printtime(tv)579 printtime(tv)
580 time_t tv;
581 {
582 char timestring[BUFSIZ];
583 char fill;
584
585 fill = ' ';
586 if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv, timestring,
587 timestamp_width+1, &fill)) {
588 printf(timestring);
589 }
590 }
591
592 void
show_credential(cred)593 show_credential(cred)
594 register krb5_creds * cred;
595 {
596 krb5_error_code retval;
597 krb5_ticket *tkt;
598 char *name, *sname, *flags;
599 int extra_field = 0;
600
601 retval = krb5_unparse_name(kcontext, cred->client, &name);
602 if (retval) {
603 com_err(progname, retval,
604 gettext("while unparsing client name"));
605 return;
606 }
607 retval = krb5_unparse_name(kcontext, cred->server, &sname);
608 if (retval) {
609 com_err(progname, retval,
610 gettext("while unparsing server name"));
611 krb5_free_unparsed_name(kcontext, name);
612 return;
613 }
614 if (!cred->times.starttime)
615 cred->times.starttime = cred->times.authtime;
616
617 printtime(cred->times.starttime);
618 putchar(' '); putchar(' ');
619 printtime(cred->times.endtime);
620 putchar(' '); putchar(' ');
621
622 printf("%s\n", sname);
623
624 if (strcmp(name, defname)) {
625 printf(gettext("\tfor client %s"), name);
626 extra_field++;
627 }
628
629 if (cred->times.renew_till) {
630 if (!extra_field)
631 fputs("\t",stdout);
632 else
633 fputs(", ",stdout);
634 fputs(gettext("renew until "), stdout);
635 printtime(cred->times.renew_till);
636 extra_field += 2;
637 }
638
639 if (extra_field > 3) {
640 fputs("\n", stdout);
641 extra_field = 0;
642 }
643
644 if (show_flags) {
645 flags = flags_string(cred);
646 if (flags && *flags) {
647 if (!extra_field)
648 fputs("\t",stdout);
649 else
650 fputs(", ",stdout);
651 printf(gettext("Flags: %s"), flags);
652 extra_field++;
653 }
654 }
655
656 if (extra_field > 2) {
657 fputs("\n", stdout);
658 extra_field = 0;
659 }
660
661 if (show_etype) {
662 retval = decode_krb5_ticket(&cred->ticket, &tkt);
663 if (retval)
664 goto err_tkt;
665
666 if (!extra_field)
667 fputs("\t",stdout);
668 else
669 fputs(", ",stdout);
670 printf(gettext("Etype(skey, tkt): %s, "),
671 etype_string(cred->keyblock.enctype));
672 printf("%s ",
673 etype_string(tkt->enc_part.enctype));
674 extra_field++;
675
676 err_tkt:
677 if (tkt != NULL)
678 krb5_free_ticket(kcontext, tkt);
679 }
680
681 /* if any additional info was printed, extra_field is non-zero */
682 if (extra_field)
683 putchar('\n');
684
685
686 if (show_addresses) {
687 if (!cred->addresses || !cred->addresses[0]) {
688 printf(gettext("\tAddresses: (none)\n"));
689 } else {
690 int i;
691
692 printf(gettext("\tAddresses: "));
693 one_addr(cred->addresses[0]);
694
695 for (i=1; cred->addresses[i]; i++) {
696 printf(", ");
697 one_addr(cred->addresses[i]);
698 }
699
700 printf("\n");
701 }
702 }
703
704 krb5_free_unparsed_name(kcontext, name);
705 krb5_free_unparsed_name(kcontext, sname);
706 }
707
708 #include "port-sockets.h"
709 #include "socket-utils.h" /* for ss2sin etc */
710 #include <fake-addrinfo.h>
711
one_addr(a)712 void one_addr(a)
713 krb5_address *a;
714 {
715 struct sockaddr_storage ss;
716 int err;
717 char namebuf[NI_MAXHOST];
718
719 memset (&ss, 0, sizeof (ss));
720
721 switch (a->addrtype) {
722 case ADDRTYPE_INET:
723 if (a->length != IPV4_ADDR_LEN) {
724 broken:
725 printf ("broken address (type %d length %d)",
726 a->addrtype, a->length);
727 return;
728 }
729 {
730 struct sockaddr_in *sinp = ss2sin (&ss);
731 sinp->sin_family = AF_INET;
732 #ifdef HAVE_SA_LEN
733 sinp->sin_len = sizeof (struct sockaddr_in);
734 #endif
735 memcpy (&sinp->sin_addr, a->contents, IPV4_ADDR_LEN);
736 }
737 break;
738 #ifdef KRB5_USE_INET6
739 case ADDRTYPE_INET6:
740 if (a->length != IPV6_ADDR_LEN)
741 goto broken;
742 {
743 struct sockaddr_in6 *sin6p = ss2sin6 (&ss);
744 sin6p->sin6_family = AF_INET6;
745 #ifdef HAVE_SA_LEN
746 sin6p->sin6_len = sizeof (struct sockaddr_in6);
747 #endif
748 memcpy (&sin6p->sin6_addr, a->contents, IPV6_ADDR_LEN);
749 }
750 break;
751 #endif
752 default:
753 printf(gettext("unknown addr type %d"), a->addrtype);
754 return;
755 }
756
757 namebuf[0] = 0;
758 err = getnameinfo (ss2sa (&ss), socklen (ss2sa (&ss)),
759 namebuf, sizeof (namebuf), 0, 0,
760 no_resolve ? NI_NUMERICHOST : 0U);
761 if (err) {
762 printf (gettext("unprintable address (type %d, error %d %s)"), a->addrtype, err,
763 gai_strerror (err));
764 return;
765 }
766 printf ("%s", namebuf);
767 }
768
769 void
fillit(f,num,c)770 fillit(f, num, c)
771 FILE *f;
772 unsigned int num;
773 int c;
774 {
775 int i;
776
777 for (i=0; i<num; i++)
778 fputc(c, f);
779 }
780
781 #ifdef KRB5_KRB4_COMPAT
782 void
do_v4_ccache(name)783 do_v4_ccache(name)
784 char * name;
785 {
786 char pname[ANAME_SZ];
787 char pinst[INST_SZ];
788 char prealm[REALM_SZ];
789 char *file;
790 int k_errno;
791 CREDENTIALS c;
792 int header = 1;
793
794 if (!got_k4)
795 return;
796
797 file = name?name:tkt_string();
798
799 if (status_only) {
800 fprintf(stderr,
801 "%s: exit status option not supported for Kerberos 4\n",
802 progname);
803 exit(1);
804 }
805
806 if (got_k5)
807 printf("\n\n");
808
809 printf("Kerberos 4 ticket cache: %s\n", file);
810
811 /*
812 * Since krb_get_tf_realm will return a ticket_file error,
813 * we will call tf_init and tf_close first to filter out
814 * things like no ticket file. Otherwise, the error that
815 * the user would see would be
816 * klist: can't find realm of ticket file: No ticket file (tf_util)
817 * instead of
818 * klist: No ticket file (tf_util)
819 */
820
821 /* Open ticket file */
822 k_errno = tf_init(file, R_TKT_FIL);
823 if (k_errno) {
824 fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
825 exit(1);
826 }
827 /* Close ticket file */
828 (void) tf_close();
829
830 /*
831 * We must find the realm of the ticket file here before calling
832 * tf_init because since the realm of the ticket file is not
833 * really stored in the principal section of the file, the
834 * routine we use must itself call tf_init and tf_close.
835 */
836 if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) {
837 fprintf(stderr, "%s: can't find realm of ticket file: %s\n",
838 progname, krb_get_err_text (k_errno));
839 exit(1);
840 }
841
842 /* Open ticket file */
843 if ((k_errno = tf_init(file, R_TKT_FIL))) {
844 fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
845 exit(1);
846 }
847 /* Get principal name and instance */
848 if ((k_errno = tf_get_pname(pname)) ||
849 (k_errno = tf_get_pinst(pinst))) {
850 fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
851 exit(1);
852 }
853
854 /*
855 * You may think that this is the obvious place to get the
856 * realm of the ticket file, but it can't be done here as the
857 * routine to do this must open the ticket file. This is why
858 * it was done before tf_init.
859 */
860
861 printf("Principal: %s%s%s%s%s\n\n", pname,
862 (pinst[0] ? "." : ""), pinst,
863 (prealm[0] ? "@" : ""), prealm);
864 while ((k_errno = tf_get_cred(&c)) == KSUCCESS) {
865 if (header) {
866 printf("%-18s %-18s %s\n",
867 " Issued", " Expires", " Principal");
868 header = 0;
869 }
870 printtime(c.issue_date);
871 fputs(" ", stdout);
872 printtime(krb_life_to_time(c.issue_date, c.lifetime));
873 printf(" %s%s%s%s%s\n",
874 c.service, (c.instance[0] ? "." : ""), c.instance,
875 (c.realm[0] ? "@" : ""), c.realm);
876 }
877 if (header && k_errno == EOF) {
878 printf("No tickets in file.\n");
879 }
880 }
881 #endif /* KRB4_KRB5_COMPAT */
882