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