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