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