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