xref: /onnv-gate/usr/src/cmd/krb5/klist/klist.c (revision 4922:fd833b1ab051)
10Sstevel@tonic-gate /*
2*4922Sps57422  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
60Sstevel@tonic-gate 
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate  * clients/klist/klist.c
90Sstevel@tonic-gate  *
100Sstevel@tonic-gate  * Copyright 1990 by the Massachusetts Institute of Technology.
110Sstevel@tonic-gate  * All Rights Reserved.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * Export of this software from the United States of America may
140Sstevel@tonic-gate  *   require a specific license from the United States Government.
150Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
160Sstevel@tonic-gate  *   export to obtain such a license before exporting.
170Sstevel@tonic-gate  *
180Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
190Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
200Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
210Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
220Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
230Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
240Sstevel@tonic-gate  * to distribution of the software without specific, written prior
250Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
260Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
270Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
280Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
290Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
300Sstevel@tonic-gate  * or implied warranty.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  * List out the contents of your credential cache or keytab.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <k5-int.h>
370Sstevel@tonic-gate #include "com_err.h"
380Sstevel@tonic-gate #include <krb5.h>
390Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
400Sstevel@tonic-gate #include <kerberosIV/krb.h>
410Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #include <stdlib.h>
440Sstevel@tonic-gate #include <string.h>
450Sstevel@tonic-gate #include <stdio.h>
460Sstevel@tonic-gate #include <time.h>
470Sstevel@tonic-gate #include <libintl.h>
480Sstevel@tonic-gate #include <locale.h>
490Sstevel@tonic-gate #include <netinet/in.h>
502881Smp153739 #if defined(HAVE_ARPA_INET_H)
510Sstevel@tonic-gate #include <arpa/inet.h>
522881Smp153739 #endif
530Sstevel@tonic-gate #include <inet/ip.h>
540Sstevel@tonic-gate #include <inet/ip6.h>
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #ifndef _WIN32
570Sstevel@tonic-gate #define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
580Sstevel@tonic-gate #else
590Sstevel@tonic-gate #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
600Sstevel@tonic-gate #endif /* _WIN32 */
610Sstevel@tonic-gate 
622881Smp153739 #ifndef _WIN32
630Sstevel@tonic-gate #include <sys/socket.h>
640Sstevel@tonic-gate #include <netdb.h>
652881Smp153739 #endif
660Sstevel@tonic-gate 
670Sstevel@tonic-gate extern int optind;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
700Sstevel@tonic-gate int show_etype = 0, show_addresses = 0, no_resolve = 0;
710Sstevel@tonic-gate char *defname;
720Sstevel@tonic-gate char *progname;
730Sstevel@tonic-gate krb5_int32 now;
740Sstevel@tonic-gate size_t timestamp_width;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate krb5_context kcontext;
770Sstevel@tonic-gate 
78781Sgtb char * etype_string (krb5_enctype );
792881Smp153739 void show_credential (krb5_creds *);
800Sstevel@tonic-gate 
81781Sgtb void do_ccache (char *);
82781Sgtb void do_keytab (char *);
83781Sgtb void printtime (time_t);
84781Sgtb void one_addr (krb5_address *);
852881Smp153739 void fillit (FILE *, unsigned int, int);
860Sstevel@tonic-gate void show_addr(krb5_address *a);
870Sstevel@tonic-gate 
880Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
89781Sgtb void do_v4_ccache (char *);
900Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
910Sstevel@tonic-gate 
920Sstevel@tonic-gate #define DEFAULT 0
930Sstevel@tonic-gate #define CCACHE 1
940Sstevel@tonic-gate #define KEYTAB 2
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  * The reason we start out with got_k4 and got_k5 as zero (false) is
980Sstevel@tonic-gate  * so that we can easily add dynamic loading support for determining
990Sstevel@tonic-gate  * whether Kerberos 4 and Keberos 5 libraries are available
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate static int got_k5 = 0;
1030Sstevel@tonic-gate static int got_k4 = 0;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate static int default_k5 = 1;
1060Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1070Sstevel@tonic-gate static int default_k4 = 1;
1080Sstevel@tonic-gate #else  /* KRB5_KRB4_COMPAT */
1090Sstevel@tonic-gate static int default_k4 = 0;
1100Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
1110Sstevel@tonic-gate 
usage()1122881Smp153739 static void usage()
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate #define KRB_AVAIL_STRING(x) ((x)?gettext("available"):gettext("not available"))
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate     fprintf(stderr, gettext("Usage: %s [-5] [-4] [-e]"
1170Sstevel@tonic-gate                     " [[-c] [-f] [-s] [-a [-n]]] "
1180Sstevel@tonic-gate 	            "[-k [-t] [-K]] [name]\n"), progname);
1190Sstevel@tonic-gate     fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
1200Sstevel@tonic-gate     fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
1210Sstevel@tonic-gate     fprintf(stderr, gettext("\t   (Default is %s%s%s%s)\n"),
1220Sstevel@tonic-gate 	    default_k5?"Kerberos 5":"",
1230Sstevel@tonic-gate 	    (default_k5 && default_k4)?gettext(" and "):"",
1240Sstevel@tonic-gate 	    default_k4?"Kerberos 4":"",
1250Sstevel@tonic-gate 	    (!default_k5 && !default_k4)?gettext("neither"):"");
1260Sstevel@tonic-gate     fprintf(stderr, gettext("\t-c specifies credentials cache\n"));
1270Sstevel@tonic-gate     fprintf(stderr, gettext("\t-k specifies keytab\n"));
1280Sstevel@tonic-gate     fprintf(stderr, gettext("\t   (Default is credentials cache)\n"));
1290Sstevel@tonic-gate     fprintf(stderr, gettext("\t-e shows the encryption type\n"));
1300Sstevel@tonic-gate     fprintf(stderr, gettext("\toptions for credential caches:\n"));
1310Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-f shows credentials flags\n"));
1320Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-s sets exit status based on valid tgt existence\n"));
1330Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-a displays the address list\n"));
1340Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-n do not reverse-resolve\n"));
1350Sstevel@tonic-gate     fprintf(stderr, gettext("\toptions for keytabs:\n"));
1360Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-t shows keytab entry timestamps\n"));
1370Sstevel@tonic-gate     fprintf(stderr, gettext("\t\t-K shows keytab entry DES keys\n"));
1380Sstevel@tonic-gate     exit(1);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate int
main(argc,argv)1432881Smp153739 main(argc, argv)
1442881Smp153739     int argc;
1452881Smp153739     char **argv;
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate     int c;
1480Sstevel@tonic-gate     char *name;
1490Sstevel@tonic-gate     int mode;
1500Sstevel@tonic-gate     int use_k5 = 0, use_k4 = 0;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate     got_k5 = 1;
1530Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1540Sstevel@tonic-gate     got_k4 = 1;
1550Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1600Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
1610Sstevel@tonic-gate #endif /* !TEXT_DOMAIN */
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate     progname = GET_PROGNAME(argv[0]);
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate     name = NULL;
1680Sstevel@tonic-gate     mode = DEFAULT;
1690Sstevel@tonic-gate     while ((c = getopt(argc, argv, "fetKsnack45")) != -1) {
1700Sstevel@tonic-gate 	switch (c) {
1710Sstevel@tonic-gate 	case 'f':
1720Sstevel@tonic-gate 	    show_flags = 1;
1730Sstevel@tonic-gate 	    break;
1740Sstevel@tonic-gate 	case 'e':
1750Sstevel@tonic-gate 	    show_etype = 1;
1760Sstevel@tonic-gate 	    break;
1770Sstevel@tonic-gate 	case 't':
1780Sstevel@tonic-gate 	    show_time = 1;
1790Sstevel@tonic-gate 	    break;
1800Sstevel@tonic-gate 	case 'K':
1810Sstevel@tonic-gate 	    show_keys = 1;
1820Sstevel@tonic-gate 	    break;
1830Sstevel@tonic-gate 	case 's':
1840Sstevel@tonic-gate 	    status_only = 1;
1850Sstevel@tonic-gate 	    break;
1860Sstevel@tonic-gate 	case 'n':
1870Sstevel@tonic-gate 	    no_resolve = 1;
1880Sstevel@tonic-gate 	    break;
1890Sstevel@tonic-gate 	case 'a':
1900Sstevel@tonic-gate 	    show_addresses = 1;
1910Sstevel@tonic-gate 	    break;
1920Sstevel@tonic-gate 	case 'c':
1930Sstevel@tonic-gate 	    if (mode != DEFAULT) usage();
1940Sstevel@tonic-gate 	    mode = CCACHE;
1950Sstevel@tonic-gate 	    break;
1960Sstevel@tonic-gate 	case 'k':
1970Sstevel@tonic-gate 	    if (mode != DEFAULT) usage();
1980Sstevel@tonic-gate 	    mode = KEYTAB;
1990Sstevel@tonic-gate 	    break;
2000Sstevel@tonic-gate 	case '4':
2010Sstevel@tonic-gate 	    if (!got_k4)
2020Sstevel@tonic-gate 	    {
2030Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
2040Sstevel@tonic-gate 		fprintf(stderr, "Kerberos 4 support could not be loaded\n");
2050Sstevel@tonic-gate #else  /* KRB5_KRB4_COMPAT */
2060Sstevel@tonic-gate 		fprintf(stderr, gettext("This was not built with Kerberos 4 support\n"));
2070Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
2080Sstevel@tonic-gate 		exit(3);
2090Sstevel@tonic-gate 	    }
2100Sstevel@tonic-gate 	    use_k4 = 1;
2110Sstevel@tonic-gate 	    break;
2120Sstevel@tonic-gate 	case '5':
2130Sstevel@tonic-gate 	    if (!got_k5)
2140Sstevel@tonic-gate 	    {
2150Sstevel@tonic-gate 		fprintf(stderr, gettext("Kerberos 5 support could not be loaded\n"));
2160Sstevel@tonic-gate 		exit(3);
2170Sstevel@tonic-gate 	    }
2180Sstevel@tonic-gate 	    use_k5 = 1;
2190Sstevel@tonic-gate 	    break;
2200Sstevel@tonic-gate 	default:
2210Sstevel@tonic-gate 	    usage();
2220Sstevel@tonic-gate 	    break;
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate     }
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate     if (no_resolve && !show_addresses) {
2270Sstevel@tonic-gate 	usage();
2280Sstevel@tonic-gate     }
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate     if (mode == DEFAULT || mode == CCACHE) {
2310Sstevel@tonic-gate 	if (show_time || show_keys)
2320Sstevel@tonic-gate 	    usage();
2330Sstevel@tonic-gate     } else {
2340Sstevel@tonic-gate 	if (show_flags || status_only || show_addresses)
2350Sstevel@tonic-gate 	    usage();
2360Sstevel@tonic-gate     }
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate     if (argc - optind > 1) {
2390Sstevel@tonic-gate 		fprintf(stderr,
2400Sstevel@tonic-gate 			gettext("Extra arguments (starting with \"%s\").\n"),
2410Sstevel@tonic-gate 		argv[optind+1]);
2420Sstevel@tonic-gate 	usage();
2430Sstevel@tonic-gate     }
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate     name = (optind == argc-1) ? argv[optind] : 0;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate     if (!use_k5 && !use_k4)
2480Sstevel@tonic-gate     {
2490Sstevel@tonic-gate 	use_k5 = default_k5;
2500Sstevel@tonic-gate 	use_k4 = default_k4;
2510Sstevel@tonic-gate     }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate     if (!use_k5)
2540Sstevel@tonic-gate 	got_k5 = 0;
2550Sstevel@tonic-gate     if (!use_k4)
2560Sstevel@tonic-gate 	got_k4 = 0;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate     now = time(0);
2590Sstevel@tonic-gate     {
2600Sstevel@tonic-gate 	char tmp[BUFSIZ];
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
2630Sstevel@tonic-gate 	    !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp),
2640Sstevel@tonic-gate 					(char *) NULL))
2652881Smp153739 	    timestamp_width = (int) strlen(tmp);
2660Sstevel@tonic-gate 	else
2670Sstevel@tonic-gate 	    timestamp_width = 15;
2680Sstevel@tonic-gate     }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate     if (got_k5)
2710Sstevel@tonic-gate     {
2720Sstevel@tonic-gate 	krb5_error_code retval;
2730Sstevel@tonic-gate 	retval = krb5_init_context(&kcontext);
2740Sstevel@tonic-gate 	if (retval) {
2750Sstevel@tonic-gate 	    com_err(progname, retval, gettext("while initializing krb5"));
2760Sstevel@tonic-gate 	    exit(1);
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	if (mode == DEFAULT || mode == CCACHE)
2800Sstevel@tonic-gate 	    do_ccache(name);
2810Sstevel@tonic-gate 	else
2820Sstevel@tonic-gate 	    do_keytab(name);
2830Sstevel@tonic-gate     } else {
2840Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
2850Sstevel@tonic-gate 	if (mode == DEFAULT || mode == CCACHE)
2860Sstevel@tonic-gate 	    do_v4_ccache(name);
2870Sstevel@tonic-gate 	else {
2880Sstevel@tonic-gate 	    /* We may want to add v4 srvtab support */
2890Sstevel@tonic-gate 	    fprintf(stderr,
2900Sstevel@tonic-gate 		    "%s: srvtab option not supported for Kerberos 4\n",
2910Sstevel@tonic-gate 		    progname);
2920Sstevel@tonic-gate 	    exit(1);
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate #endif /* KRB4_KRB5_COMPAT */
2950Sstevel@tonic-gate     }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate     return 0;
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
do_keytab(name)3000Sstevel@tonic-gate void do_keytab(name)
3010Sstevel@tonic-gate    char *name;
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate      krb5_keytab kt;
3040Sstevel@tonic-gate      krb5_keytab_entry entry;
3050Sstevel@tonic-gate      krb5_kt_cursor cursor;
3060Sstevel@tonic-gate      char buf[BUFSIZ]; /* hopefully large enough for any type */
3070Sstevel@tonic-gate      char *pname;
3080Sstevel@tonic-gate      int code;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate      if (name == NULL) {
3110Sstevel@tonic-gate 	  if ((code = krb5_kt_default(kcontext, &kt))) {
3120Sstevel@tonic-gate 			com_err(progname, code,
3130Sstevel@tonic-gate 				gettext("while getting default keytab"));
3140Sstevel@tonic-gate 	       exit(1);
3150Sstevel@tonic-gate 	  }
3160Sstevel@tonic-gate      } else {
3170Sstevel@tonic-gate 	  if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
3180Sstevel@tonic-gate 			com_err(progname, code,
3190Sstevel@tonic-gate 				gettext("while resolving keytab %s"),
3200Sstevel@tonic-gate 		       name);
3210Sstevel@tonic-gate 	       exit(1);
3220Sstevel@tonic-gate 	  }
3230Sstevel@tonic-gate      }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate      if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
3262881Smp153739 	  com_err(progname, code,
3270Sstevel@tonic-gate 			gettext("while getting keytab name"));
3280Sstevel@tonic-gate 	  exit(1);
3290Sstevel@tonic-gate      }
3300Sstevel@tonic-gate 
3312881Smp153739      printf(gettext("Keytab name: %s\n"), buf);
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
3342881Smp153739 	  com_err(progname, code,
3350Sstevel@tonic-gate 			gettext("while starting keytab scan"));
3360Sstevel@tonic-gate 	  exit(1);
3370Sstevel@tonic-gate      }
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate      if (show_time) {
3402881Smp153739 	  printf(gettext("KVNO Timestamp"));
3412881Smp153739 	  fillit(stdout, timestamp_width -
3422881Smp153739 	    sizeof (gettext("Timestamp")) + 2, (int)' ');
3432881Smp153739 	  printf(gettext("Principal\n"));
3442881Smp153739 	  printf("---- ");
3450Sstevel@tonic-gate 	  fillit(stdout, timestamp_width, (int) '-');
3460Sstevel@tonic-gate 	  printf(" ");
3472881Smp153739 	  fillit(stdout, 78 - timestamp_width -
3480Sstevel@tonic-gate 		    sizeof (gettext("KVNO")), (int)'-');
3490Sstevel@tonic-gate 	  printf("\n");
3500Sstevel@tonic-gate      } else {
3512881Smp153739 	  printf(gettext("KVNO Principal\n"));
3522881Smp153739 	  printf("---- ------------------------------"
3530Sstevel@tonic-gate 			    "--------------------------------------"
3540Sstevel@tonic-gate 			    "------\n");
3550Sstevel@tonic-gate      }
3560Sstevel@tonic-gate 
3572881Smp153739      while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
3582881Smp153739 	  if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
3592881Smp153739 	       com_err(progname, code,
3600Sstevel@tonic-gate 				gettext("while unparsing principal name"));
3610Sstevel@tonic-gate 	       exit(1);
3620Sstevel@tonic-gate 	  }
3630Sstevel@tonic-gate 	  printf("%4d ", entry.vno);
3640Sstevel@tonic-gate 	  if (show_time) {
3650Sstevel@tonic-gate 	       printtime(entry.timestamp);
3660Sstevel@tonic-gate 	       printf(" ");
3670Sstevel@tonic-gate 	  }
3680Sstevel@tonic-gate 	  printf("%s", pname);
3690Sstevel@tonic-gate 	  if (show_etype)
3700Sstevel@tonic-gate 	      printf(" (%s) " , etype_string(entry.key.enctype));
3710Sstevel@tonic-gate 	  if (show_keys) {
3720Sstevel@tonic-gate 	       printf(" (0x");
3730Sstevel@tonic-gate 	       {
3740Sstevel@tonic-gate 		    int i;
3750Sstevel@tonic-gate 		    for (i = 0; i < entry.key.length; i++)
3760Sstevel@tonic-gate 			 printf("%02x", entry.key.contents[i]);
3770Sstevel@tonic-gate 	       }
3780Sstevel@tonic-gate 	       printf(")");
3790Sstevel@tonic-gate 	  }
3800Sstevel@tonic-gate 	  printf("\n");
3810Sstevel@tonic-gate 	  krb5_free_unparsed_name(kcontext, pname);
3820Sstevel@tonic-gate      }
3830Sstevel@tonic-gate      if (code && code != KRB5_KT_END) {
3840Sstevel@tonic-gate 		com_err(progname, code,
3850Sstevel@tonic-gate 			gettext("while scanning keytab"));
3860Sstevel@tonic-gate 	  exit(1);
3870Sstevel@tonic-gate      }
3880Sstevel@tonic-gate      if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
3890Sstevel@tonic-gate 		com_err(progname, code,
3900Sstevel@tonic-gate 			gettext("while ending keytab scan"));
3910Sstevel@tonic-gate 	  exit(1);
3920Sstevel@tonic-gate      }
3930Sstevel@tonic-gate      exit(0);
3940Sstevel@tonic-gate }
do_ccache(name)3950Sstevel@tonic-gate void do_ccache(name)
3960Sstevel@tonic-gate    char *name;
3970Sstevel@tonic-gate {
3980Sstevel@tonic-gate     krb5_ccache cache = NULL;
3990Sstevel@tonic-gate     krb5_cc_cursor cur;
4000Sstevel@tonic-gate     krb5_creds creds;
4010Sstevel@tonic-gate     krb5_principal princ;
4020Sstevel@tonic-gate     krb5_flags flags;
4030Sstevel@tonic-gate     krb5_error_code code;
4040Sstevel@tonic-gate     int	exit_status = 0;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate     if (status_only)
4070Sstevel@tonic-gate 	/* exit_status is set back to 0 if a valid tgt is found */
4080Sstevel@tonic-gate 	exit_status = 1;
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate     if (name == NULL) {
4110Sstevel@tonic-gate 	if ((code = krb5_cc_default(kcontext, &cache))) {
4120Sstevel@tonic-gate 	    if (!status_only)
4130Sstevel@tonic-gate 				com_err(progname, code,
4140Sstevel@tonic-gate 					gettext("while getting default "
4150Sstevel@tonic-gate 						"ccache"));
4160Sstevel@tonic-gate 	    exit(1);
4170Sstevel@tonic-gate 	    }
4180Sstevel@tonic-gate     } else {
4190Sstevel@tonic-gate 	if ((code = krb5_cc_resolve(kcontext, name, &cache))) {
4200Sstevel@tonic-gate 	    if (!status_only)
4210Sstevel@tonic-gate 				com_err(progname, code,
4220Sstevel@tonic-gate 					gettext("while resolving ccache %s"),
4230Sstevel@tonic-gate 			name);
4240Sstevel@tonic-gate 	    exit(1);
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate     }
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate     flags = 0;				/* turns off OPENCLOSE mode */
4290Sstevel@tonic-gate     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
4300Sstevel@tonic-gate 	if (code == KRB5_FCC_NOFILE) {
4310Sstevel@tonic-gate 	    if (!status_only) {
4320Sstevel@tonic-gate 		com_err(progname, code, gettext("(ticket cache %s:%s)"),
4330Sstevel@tonic-gate 			krb5_cc_get_type(kcontext, cache),
4340Sstevel@tonic-gate 			krb5_cc_get_name(kcontext, cache));
4350Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
4360Sstevel@tonic-gate 		if (name == NULL)
4370Sstevel@tonic-gate 		    do_v4_ccache(0);
4380Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
4390Sstevel@tonic-gate 	    }
4400Sstevel@tonic-gate 	} else {
4410Sstevel@tonic-gate 	    if (!status_only)
4420Sstevel@tonic-gate 		com_err(progname, code,
4430Sstevel@tonic-gate 			gettext("while setting cache "
4440Sstevel@tonic-gate 				"flags(ticket cache %s:%s)"),
4450Sstevel@tonic-gate 			krb5_cc_get_type(kcontext, cache),
4462881Smp153739 			krb5_cc_get_name(kcontext, cache));
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate 	exit(1);
4490Sstevel@tonic-gate     }
4500Sstevel@tonic-gate     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
4510Sstevel@tonic-gate 	if (!status_only)
4520Sstevel@tonic-gate 			com_err(progname, code,
4530Sstevel@tonic-gate 				gettext("while retrieving principal name"));
4540Sstevel@tonic-gate 	exit(1);
4550Sstevel@tonic-gate     }
4560Sstevel@tonic-gate     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
4570Sstevel@tonic-gate 	if (!status_only)
4580Sstevel@tonic-gate 			com_err(progname, code,
4590Sstevel@tonic-gate 				gettext("while unparsing principal name"));
4600Sstevel@tonic-gate 	exit(1);
4610Sstevel@tonic-gate     }
4620Sstevel@tonic-gate     if (!status_only) {
4630Sstevel@tonic-gate 		printf(gettext("Ticket cache: %s:%s\nDefault principal: "
4640Sstevel@tonic-gate 			    "%s\n\n"),
4650Sstevel@tonic-gate 	       krb5_cc_get_type(kcontext, cache),
4662881Smp153739 	       krb5_cc_get_name(kcontext, cache), defname);
4670Sstevel@tonic-gate 		fputs(gettext("Valid starting"), stdout);
4680Sstevel@tonic-gate 		fillit(stdout, timestamp_width -
4690Sstevel@tonic-gate 		    sizeof (gettext("Valid starting")) + 3, (int)' ');
4700Sstevel@tonic-gate 		fputs(gettext("Expires"), stdout);
4710Sstevel@tonic-gate 		fillit(stdout, timestamp_width -
4720Sstevel@tonic-gate 		    sizeof (gettext("Expires")) + 3, (int)' ');
4730Sstevel@tonic-gate 		fputs(gettext("Service principal\n"), stdout);
4740Sstevel@tonic-gate     }
4750Sstevel@tonic-gate     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
4760Sstevel@tonic-gate 	if (!status_only)
4770Sstevel@tonic-gate 			com_err(progname, code,
4780Sstevel@tonic-gate 				gettext("while starting to retrieve tickets"));
4790Sstevel@tonic-gate 	exit(1);
4800Sstevel@tonic-gate     }
4810Sstevel@tonic-gate     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
4820Sstevel@tonic-gate 	if (status_only) {
4830Sstevel@tonic-gate 	    if (exit_status && creds.server->length == 2 &&
4840Sstevel@tonic-gate 			    strcmp(creds.server->realm.data,
4850Sstevel@tonic-gate 				princ->realm.data) == 0 &&
4860Sstevel@tonic-gate 			    strcmp((char *)creds.server->data[0].data,
4870Sstevel@tonic-gate 				"krbtgt") == 0 &&
4880Sstevel@tonic-gate 		strcmp((char *)creds.server->data[1].data,
4890Sstevel@tonic-gate 		       princ->realm.data) == 0 &&
4900Sstevel@tonic-gate 		creds.times.endtime > now)
4910Sstevel@tonic-gate 		exit_status = 0;
4920Sstevel@tonic-gate 	} else {
4932881Smp153739 	    show_credential(&creds);
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 	krb5_free_cred_contents(kcontext, &creds);
4960Sstevel@tonic-gate     }
4970Sstevel@tonic-gate     if (code == KRB5_CC_END) {
4980Sstevel@tonic-gate 	if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
4990Sstevel@tonic-gate 	    if (!status_only)
5000Sstevel@tonic-gate 				com_err(progname, code,
5010Sstevel@tonic-gate 					gettext("while finishing ticket "
5020Sstevel@tonic-gate 						"retrieval"));
5030Sstevel@tonic-gate 	    exit(1);
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 	flags = KRB5_TC_OPENCLOSE;	/* turns on OPENCLOSE mode */
5060Sstevel@tonic-gate 	if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
5070Sstevel@tonic-gate 	    if (!status_only)
5080Sstevel@tonic-gate 				com_err(progname, code,
5090Sstevel@tonic-gate 					gettext("while closing ccache"));
5100Sstevel@tonic-gate 	    exit(1);
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
5130Sstevel@tonic-gate 	if (name == NULL && !status_only)
5140Sstevel@tonic-gate 	    do_v4_ccache(0);
5150Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
5160Sstevel@tonic-gate 	exit(exit_status);
5170Sstevel@tonic-gate     } else {
5180Sstevel@tonic-gate 	if (!status_only)
5190Sstevel@tonic-gate 			com_err(progname, code,
5200Sstevel@tonic-gate 				gettext("while retrieving a ticket"));
5210Sstevel@tonic-gate 	exit(1);
5220Sstevel@tonic-gate     }
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate char *
etype_string(enctype)5260Sstevel@tonic-gate etype_string(enctype)
5270Sstevel@tonic-gate     krb5_enctype enctype;
5280Sstevel@tonic-gate {
529*4922Sps57422     static char buf[256];
5300Sstevel@tonic-gate     krb5_error_code retval;
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate     if ((retval = krb5_enctype_to_string(enctype, buf, sizeof(buf)))) {
5330Sstevel@tonic-gate 	/* XXX if there's an error != EINVAL, I should probably report it */
534*4922Sps57422 	snprintf(buf, sizeof(buf), gettext("unsupported encryption type %d"), enctype);
5350Sstevel@tonic-gate     }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate     return buf;
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate 
5402881Smp153739 static char *
flags_string(cred)5410Sstevel@tonic-gate flags_string(cred)
5420Sstevel@tonic-gate     register krb5_creds *cred;
5430Sstevel@tonic-gate {
5440Sstevel@tonic-gate     static char buf[32];
5450Sstevel@tonic-gate     int i = 0;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
5480Sstevel@tonic-gate 	buf[i++] = 'F';
5490Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_FORWARDED)
5500Sstevel@tonic-gate 	buf[i++] = 'f';
5510Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
5520Sstevel@tonic-gate 	buf[i++] = 'P';
5530Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_PROXY)
5540Sstevel@tonic-gate 	buf[i++] = 'p';
5550Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
5560Sstevel@tonic-gate 	buf[i++] = 'D';
5570Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_POSTDATED)
5580Sstevel@tonic-gate 	buf[i++] = 'd';
5590Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_INVALID)
5600Sstevel@tonic-gate 	buf[i++] = 'i';
5610Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
5620Sstevel@tonic-gate 	buf[i++] = 'R';
5630Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_INITIAL)
5640Sstevel@tonic-gate 	buf[i++] = 'I';
5650Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
5660Sstevel@tonic-gate 	buf[i++] = 'H';
5670Sstevel@tonic-gate     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
5680Sstevel@tonic-gate 	buf[i++] = 'A';
5692881Smp153739     if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED)
5702881Smp153739 	buf[i++] = 'T';
5712881Smp153739     if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)
5722881Smp153739 	buf[i++] = 'O';		/* D/d are taken.  Use short strings?  */
5732881Smp153739     if (cred->ticket_flags & TKT_FLG_ANONYMOUS)
5742881Smp153739 	buf[i++] = 'a';
5750Sstevel@tonic-gate     buf[i] = '\0';
5760Sstevel@tonic-gate     return(buf);
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate void
printtime(tv)5800Sstevel@tonic-gate printtime(tv)
5810Sstevel@tonic-gate     time_t tv;
5820Sstevel@tonic-gate {
5830Sstevel@tonic-gate     char timestring[BUFSIZ];
5840Sstevel@tonic-gate     char fill;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate     fill = ' ';
5870Sstevel@tonic-gate 	if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv, timestring,
5880Sstevel@tonic-gate 					timestamp_width+1, &fill)) {
5890Sstevel@tonic-gate 	printf(timestring);
5900Sstevel@tonic-gate     }
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate void
show_credential(cred)5942881Smp153739 show_credential(cred)
5950Sstevel@tonic-gate     register krb5_creds * cred;
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate     krb5_error_code retval;
5980Sstevel@tonic-gate     krb5_ticket *tkt;
5990Sstevel@tonic-gate     char *name, *sname, *flags;
6000Sstevel@tonic-gate     int	extra_field = 0;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate     retval = krb5_unparse_name(kcontext, cred->client, &name);
6030Sstevel@tonic-gate     if (retval) {
6040Sstevel@tonic-gate 		com_err(progname, retval,
6050Sstevel@tonic-gate 			gettext("while unparsing client name"));
6060Sstevel@tonic-gate 	return;
6070Sstevel@tonic-gate     }
6080Sstevel@tonic-gate     retval = krb5_unparse_name(kcontext, cred->server, &sname);
6090Sstevel@tonic-gate     if (retval) {
6100Sstevel@tonic-gate 		com_err(progname, retval,
6110Sstevel@tonic-gate 			gettext("while unparsing server name"));
6120Sstevel@tonic-gate 		krb5_free_unparsed_name(kcontext, name);
6130Sstevel@tonic-gate 	return;
6140Sstevel@tonic-gate     }
6150Sstevel@tonic-gate     if (!cred->times.starttime)
6160Sstevel@tonic-gate 	cred->times.starttime = cred->times.authtime;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate     printtime(cred->times.starttime);
6190Sstevel@tonic-gate     putchar(' '); putchar(' ');
6200Sstevel@tonic-gate     printtime(cred->times.endtime);
6210Sstevel@tonic-gate     putchar(' '); putchar(' ');
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate     printf("%s\n", sname);
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate     if (strcmp(name, defname)) {
6260Sstevel@tonic-gate 		printf(gettext("\tfor client %s"), name);
6270Sstevel@tonic-gate 	    extra_field++;
6280Sstevel@tonic-gate     }
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate     if (cred->times.renew_till) {
6310Sstevel@tonic-gate 	if (!extra_field)
6320Sstevel@tonic-gate 		fputs("\t",stdout);
6330Sstevel@tonic-gate 	else
6340Sstevel@tonic-gate 		fputs(", ",stdout);
6350Sstevel@tonic-gate 		fputs(gettext("renew until "), stdout);
6360Sstevel@tonic-gate 	printtime(cred->times.renew_till);
6370Sstevel@tonic-gate 	extra_field += 2;
6380Sstevel@tonic-gate     }
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate     if (extra_field > 3) {
6410Sstevel@tonic-gate 	fputs("\n", stdout);
6420Sstevel@tonic-gate 	extra_field = 0;
6430Sstevel@tonic-gate     }
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate     if (show_flags) {
6460Sstevel@tonic-gate 	flags = flags_string(cred);
6470Sstevel@tonic-gate 	if (flags && *flags) {
6480Sstevel@tonic-gate 	    if (!extra_field)
6490Sstevel@tonic-gate 		fputs("\t",stdout);
6500Sstevel@tonic-gate 	    else
6510Sstevel@tonic-gate 		fputs(", ",stdout);
6520Sstevel@tonic-gate 			printf(gettext("Flags: %s"), flags);
6530Sstevel@tonic-gate 	    extra_field++;
6540Sstevel@tonic-gate 	}
6550Sstevel@tonic-gate     }
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate     if (extra_field > 2) {
6580Sstevel@tonic-gate 	fputs("\n", stdout);
6590Sstevel@tonic-gate 	extra_field = 0;
6600Sstevel@tonic-gate     }
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate     if (show_etype) {
6630Sstevel@tonic-gate 	retval = decode_krb5_ticket(&cred->ticket, &tkt);
6642881Smp153739 	if (retval)
6652881Smp153739 	    goto err_tkt;
6662881Smp153739 
6672881Smp153739 	if (!extra_field)
6682881Smp153739 	    fputs("\t",stdout);
6692881Smp153739 	else
6702881Smp153739 	    fputs(", ",stdout);
6712881Smp153739 	printf(gettext("Etype(skey, tkt): %s, "),
6722881Smp153739 	       etype_string(cred->keyblock.enctype));
6732881Smp153739 	printf("%s ",
6742881Smp153739 	       etype_string(tkt->enc_part.enctype));
6752881Smp153739 	extra_field++;
6762881Smp153739 
6772881Smp153739     err_tkt:
6782881Smp153739 	if (tkt != NULL)
6790Sstevel@tonic-gate 	    krb5_free_ticket(kcontext, tkt);
6800Sstevel@tonic-gate     }
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate     /* if any additional info was printed, extra_field is non-zero */
6830Sstevel@tonic-gate     if (extra_field)
6840Sstevel@tonic-gate 	putchar('\n');
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate     if (show_addresses) {
6880Sstevel@tonic-gate 	if (!cred->addresses || !cred->addresses[0]) {
6890Sstevel@tonic-gate 	    printf(gettext("\tAddresses: (none)\n"));
6900Sstevel@tonic-gate 	} else {
6910Sstevel@tonic-gate 	    int i;
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	    printf(gettext("\tAddresses: "));
6940Sstevel@tonic-gate 	    one_addr(cred->addresses[0]);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	    for (i=1; cred->addresses[i]; i++) {
6970Sstevel@tonic-gate 		printf(", ");
6980Sstevel@tonic-gate 		one_addr(cred->addresses[i]);
6990Sstevel@tonic-gate 	    }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	    printf("\n");
7020Sstevel@tonic-gate 	}
7030Sstevel@tonic-gate     }
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate     krb5_free_unparsed_name(kcontext, name);
7060Sstevel@tonic-gate     krb5_free_unparsed_name(kcontext, sname);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate #include "port-sockets.h"
7100Sstevel@tonic-gate #include "socket-utils.h" /* for ss2sin etc */
7110Sstevel@tonic-gate #include <fake-addrinfo.h>
7120Sstevel@tonic-gate 
one_addr(a)7130Sstevel@tonic-gate void one_addr(a)
7140Sstevel@tonic-gate     krb5_address *a;
7150Sstevel@tonic-gate {
7160Sstevel@tonic-gate     struct sockaddr_storage ss;
7170Sstevel@tonic-gate     int err;
7180Sstevel@tonic-gate     char namebuf[NI_MAXHOST];
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate     memset (&ss, 0, sizeof (ss));
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate     switch (a->addrtype) {
7230Sstevel@tonic-gate     case ADDRTYPE_INET:
7240Sstevel@tonic-gate 	if (a->length != IPV4_ADDR_LEN) {
7250Sstevel@tonic-gate 	broken:
7260Sstevel@tonic-gate 	    printf ("broken address (type %d length %d)",
7270Sstevel@tonic-gate 		    a->addrtype, a->length);
7280Sstevel@tonic-gate 	    return;
7290Sstevel@tonic-gate 	}
7300Sstevel@tonic-gate 	{
7310Sstevel@tonic-gate 	    struct sockaddr_in *sinp = ss2sin (&ss);
7320Sstevel@tonic-gate 	    sinp->sin_family = AF_INET;
7330Sstevel@tonic-gate #ifdef HAVE_SA_LEN
7340Sstevel@tonic-gate 	    sinp->sin_len = sizeof (struct sockaddr_in);
7350Sstevel@tonic-gate #endif
7360Sstevel@tonic-gate 	    memcpy (&sinp->sin_addr, a->contents, IPV4_ADDR_LEN);
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 	break;
7390Sstevel@tonic-gate #ifdef KRB5_USE_INET6
7400Sstevel@tonic-gate     case ADDRTYPE_INET6:
7410Sstevel@tonic-gate 	if (a->length != IPV6_ADDR_LEN)
7420Sstevel@tonic-gate 	    goto broken;
7430Sstevel@tonic-gate 	{
7440Sstevel@tonic-gate 	    struct sockaddr_in6 *sin6p = ss2sin6 (&ss);
7450Sstevel@tonic-gate 	    sin6p->sin6_family = AF_INET6;
7460Sstevel@tonic-gate #ifdef HAVE_SA_LEN
7470Sstevel@tonic-gate 	    sin6p->sin6_len = sizeof (struct sockaddr_in6);
7480Sstevel@tonic-gate #endif
7490Sstevel@tonic-gate 	    memcpy (&sin6p->sin6_addr, a->contents, IPV6_ADDR_LEN);
7500Sstevel@tonic-gate 	}
7510Sstevel@tonic-gate 	break;
7520Sstevel@tonic-gate #endif
7530Sstevel@tonic-gate     default:
7540Sstevel@tonic-gate 	printf(gettext("unknown addr type %d"), a->addrtype);
7550Sstevel@tonic-gate 	return;
7560Sstevel@tonic-gate     }
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate     namebuf[0] = 0;
7590Sstevel@tonic-gate     err = getnameinfo (ss2sa (&ss), socklen (ss2sa (&ss)),
7600Sstevel@tonic-gate 		       namebuf, sizeof (namebuf), 0, 0,
7610Sstevel@tonic-gate 		       no_resolve ? NI_NUMERICHOST : 0U);
7620Sstevel@tonic-gate     if (err) {
7630Sstevel@tonic-gate 	printf (gettext("unprintable address (type %d, error %d %s)"), a->addrtype, err,
7640Sstevel@tonic-gate 		gai_strerror (err));
7650Sstevel@tonic-gate 	return;
7660Sstevel@tonic-gate     }
7670Sstevel@tonic-gate     printf ("%s", namebuf);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate void
fillit(f,num,c)7710Sstevel@tonic-gate fillit(f, num, c)
7720Sstevel@tonic-gate     FILE		*f;
7732881Smp153739     unsigned int	num;
7740Sstevel@tonic-gate     int			c;
7750Sstevel@tonic-gate {
7760Sstevel@tonic-gate     int i;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate     for (i=0; i<num; i++)
7790Sstevel@tonic-gate 	fputc(c, f);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7830Sstevel@tonic-gate void
do_v4_ccache(name)7840Sstevel@tonic-gate do_v4_ccache(name)
7850Sstevel@tonic-gate     char * name;
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate     char    pname[ANAME_SZ];
7880Sstevel@tonic-gate     char    pinst[INST_SZ];
7890Sstevel@tonic-gate     char    prealm[REALM_SZ];
7900Sstevel@tonic-gate     char    *file;
7910Sstevel@tonic-gate     int     k_errno;
7920Sstevel@tonic-gate     CREDENTIALS c;
7930Sstevel@tonic-gate     int     header = 1;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate     if (!got_k4)
7960Sstevel@tonic-gate 	return;
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate     file = name?name:tkt_string();
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate     if (status_only) {
8010Sstevel@tonic-gate 	fprintf(stderr,
8020Sstevel@tonic-gate 		"%s: exit status option not supported for Kerberos 4\n",
8030Sstevel@tonic-gate 		progname);
8040Sstevel@tonic-gate 	exit(1);
8050Sstevel@tonic-gate     }
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate     if (got_k5)
8080Sstevel@tonic-gate 	printf("\n\n");
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate     printf("Kerberos 4 ticket cache: %s\n", file);
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate     /*
8130Sstevel@tonic-gate      * Since krb_get_tf_realm will return a ticket_file error,
8140Sstevel@tonic-gate      * we will call tf_init and tf_close first to filter out
8150Sstevel@tonic-gate      * things like no ticket file.  Otherwise, the error that
8160Sstevel@tonic-gate      * the user would see would be
8170Sstevel@tonic-gate      * klist: can't find realm of ticket file: No ticket file (tf_util)
8180Sstevel@tonic-gate      * instead of
8190Sstevel@tonic-gate      * klist: No ticket file (tf_util)
8200Sstevel@tonic-gate      */
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate     /* Open ticket file */
8232881Smp153739     k_errno = tf_init(file, R_TKT_FIL);
8242881Smp153739     if (k_errno) {
8250Sstevel@tonic-gate 	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
8260Sstevel@tonic-gate 	exit(1);
8270Sstevel@tonic-gate     }
8280Sstevel@tonic-gate     /* Close ticket file */
8290Sstevel@tonic-gate     (void) tf_close();
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate     /*
8320Sstevel@tonic-gate      * We must find the realm of the ticket file here before calling
8330Sstevel@tonic-gate      * tf_init because since the realm of the ticket file is not
8340Sstevel@tonic-gate      * really stored in the principal section of the file, the
8350Sstevel@tonic-gate      * routine we use must itself call tf_init and tf_close.
8360Sstevel@tonic-gate      */
8370Sstevel@tonic-gate     if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) {
8380Sstevel@tonic-gate 	fprintf(stderr, "%s: can't find realm of ticket file: %s\n",
8390Sstevel@tonic-gate 		progname, krb_get_err_text (k_errno));
8400Sstevel@tonic-gate 	exit(1);
8410Sstevel@tonic-gate     }
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate     /* Open ticket file */
8442881Smp153739     if ((k_errno = tf_init(file, R_TKT_FIL))) {
8450Sstevel@tonic-gate 	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
8460Sstevel@tonic-gate 	exit(1);
8470Sstevel@tonic-gate     }
8480Sstevel@tonic-gate     /* Get principal name and instance */
8490Sstevel@tonic-gate     if ((k_errno = tf_get_pname(pname)) ||
8500Sstevel@tonic-gate 	(k_errno = tf_get_pinst(pinst))) {
8510Sstevel@tonic-gate 	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
8520Sstevel@tonic-gate 	exit(1);
8530Sstevel@tonic-gate     }
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate     /*
8560Sstevel@tonic-gate      * You may think that this is the obvious place to get the
8570Sstevel@tonic-gate      * realm of the ticket file, but it can't be done here as the
8580Sstevel@tonic-gate      * routine to do this must open the ticket file.  This is why
8590Sstevel@tonic-gate      * it was done before tf_init.
8600Sstevel@tonic-gate      */
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate     printf("Principal: %s%s%s%s%s\n\n", pname,
8630Sstevel@tonic-gate 	   (pinst[0] ? "." : ""), pinst,
8640Sstevel@tonic-gate 	   (prealm[0] ? "@" : ""), prealm);
8650Sstevel@tonic-gate     while ((k_errno = tf_get_cred(&c)) == KSUCCESS) {
8660Sstevel@tonic-gate 	if (header) {
8670Sstevel@tonic-gate 	    printf("%-18s  %-18s  %s\n",
8680Sstevel@tonic-gate 		   "  Issued", "  Expires", "  Principal");
8690Sstevel@tonic-gate 	    header = 0;
8700Sstevel@tonic-gate 	}
8710Sstevel@tonic-gate 	printtime(c.issue_date);
8720Sstevel@tonic-gate 	fputs("  ", stdout);
8732881Smp153739 	printtime(krb_life_to_time(c.issue_date, c.lifetime));
8740Sstevel@tonic-gate 	printf("  %s%s%s%s%s\n",
8750Sstevel@tonic-gate 	       c.service, (c.instance[0] ? "." : ""), c.instance,
8760Sstevel@tonic-gate 	       (c.realm[0] ? "@" : ""), c.realm);
8770Sstevel@tonic-gate     }
8780Sstevel@tonic-gate     if (header && k_errno == EOF) {
8790Sstevel@tonic-gate 	printf("No tickets in file.\n");
8800Sstevel@tonic-gate     }
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate #endif /* KRB4_KRB5_COMPAT */
883