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