diff options
Diffstat (limited to 'src/mac/klist.c')
-rw-r--r-- | src/mac/klist.c | 912 |
1 files changed, 912 insertions, 0 deletions
diff --git a/src/mac/klist.c b/src/mac/klist.c new file mode 100644 index 0000000..8aa2e48 --- /dev/null +++ b/src/mac/klist.c @@ -0,0 +1,912 @@ +/* + * clients/klist/klist.c + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * List out the contents of your credential cache or keytab. + */ + +#if TARGET_HEADER_FRAMEWORK + #include <Kerberos/Kerberos.h> +#else + #include <krb5.h> + #ifdef KRB5_KRB4_COMPAT + #include <kerberosIV/krb.h> + #endif + #include <com_err.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <time.h> +#if defined(HAVE_ARPA_INET_H) +#include <arpa/inet.h> +#endif + +#ifndef _WIN32 +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) +#else +#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) +#endif + +#if (defined(_MSDOS) || defined(_WIN32)) +#include <winsock.h> +#else +#include <sys/socket.h> +#include <netdb.h> +#endif + +extern int optind; + +int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0; +int show_etype = 0, show_addresses = 0, no_resolve = 0; +char *defname; +char *progname; +krb5_int32 now; +unsigned int timestamp_width; + +krb5_context kcontext; + +char * etype_string KRB5_PROTOTYPE((krb5_enctype )); +void show_credential KRB5_PROTOTYPE((krb5_creds *)); + +void do_ccache KRB5_PROTOTYPE((char *)); +void do_keytab KRB5_PROTOTYPE((char *)); +void printtime KRB5_PROTOTYPE((time_t)); +void one_addr KRB5_PROTOTYPE((krb5_address *)); +void fillit KRB5_PROTOTYPE((FILE *, unsigned int, int)); + +#ifdef KRB5_KRB4_COMPAT +void do_v4_ccache KRB5_PROTOTYPE((char *)); +#endif /* KRB5_KRB4_COMPAT */ + +#define DEFAULT 0 +#define CCACHE 1 +#define KEYTAB 2 + +/* + * The reason we start out with got_k4 and got_k5 as zero (false) is + * so that we can easily add dynamic loading support for determining + * whether Kerberos 4 and Keberos 5 libraries are available + */ + +static int got_k5 = 0; +static int got_k4 = 0; + +static int default_k5 = 1; +#ifdef KRB5_KRB4_COMPAT +static int default_k4 = 1; +#else +static int default_k4 = 0; +#endif + +static void usage() +{ +#define KRB_AVAIL_STRING(x) ((x)?"available":"not available") + + fprintf(stderr, "Usage: %s [-5] [-4] [-e] [[-c] [-f] [-s] [-a [-n]]] %s", + progname, "[-k [-t] [-K]] [name]\n"); + fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5)); + fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4)); + fprintf(stderr, "\t (Default is %s%s%s%s)\n", + default_k5?"Kerberos 5":"", + (default_k5 && default_k4)?" and ":"", + default_k4?"Kerberos 4":"", + (!default_k5 && !default_k4)?"neither":""); + fprintf(stderr, "\t-c specifies credentials cache\n"); + fprintf(stderr, "\t-k specifies keytab\n"); + fprintf(stderr, "\t (Default is credentials cache)\n"); + fprintf(stderr, "\t-e shows the encryption type\n"); + fprintf(stderr, "\toptions for credential caches:\n"); + fprintf(stderr, "\t\t-f shows credentials flags\n"); + fprintf(stderr, "\t\t-s sets exit status based on valid tgt existence\n"); + fprintf(stderr, "\t\t-a displays the address list\n"); + fprintf(stderr, "\t\t\t-n do not reverse-resolve\n"); + fprintf(stderr, "\toptions for keytabs:\n"); + fprintf(stderr, "\t\t-t shows keytab entry timestamps\n"); + fprintf(stderr, "\t\t-K shows keytab entry DES keys\n"); + exit(1); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + char *name; + int mode; + int use_k5 = 0, use_k4 = 0; + + got_k5 = 1; +#ifdef KRB5_KRB4_COMPAT + got_k4 = 1; +#endif + + progname = GET_PROGNAME(argv[0]); + + name = NULL; + mode = DEFAULT; + while ((c = getopt(argc, argv, "fetKsnack45")) != -1) { + switch (c) { + case 'f': + show_flags = 1; + break; + case 'e': + show_etype = 1; + break; + case 't': + show_time = 1; + break; + case 'K': + show_keys = 1; + break; + case 's': + status_only = 1; + break; + case 'n': + no_resolve = 1; + break; + case 'a': + show_addresses = 1; + break; + case 'c': + if (mode != DEFAULT) usage(); + mode = CCACHE; + break; + case 'k': + if (mode != DEFAULT) usage(); + mode = KEYTAB; + break; + case '4': + if (!got_k4) + { +#ifdef KRB5_KRB4_COMPAT + fprintf(stderr, "Kerberos 4 support could not be loaded\n"); +#else + fprintf(stderr, "This was not built with Kerberos 4 support\n"); +#endif + exit(3); + } + use_k4 = 1; + break; + case '5': + if (!got_k5) + { + fprintf(stderr, "Kerberos 5 support could not be loaded\n"); + exit(3); + } + use_k5 = 1; + break; + default: + usage(); + break; + } + } + + if (no_resolve && !show_addresses) { + usage(); + } + + if (mode == DEFAULT || mode == CCACHE) { + if (show_time || show_keys) + usage(); + } else { + if (show_flags || status_only || show_addresses) + usage(); + } + + if (argc - optind > 1) { + fprintf(stderr, "Extra arguments (starting with \"%s\").\n", + argv[optind+1]); + usage(); + } + + name = (optind == argc-1) ? argv[optind] : 0; + + if (!use_k5 && !use_k4) + { + use_k5 = default_k5; + use_k4 = default_k4; + } + + if (!use_k5) + got_k5 = 0; + if (!use_k4) + got_k4 = 0; + + now = time(0); + { + char tmp[BUFSIZ]; + + if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) || + !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), + (char *) NULL)) + timestamp_width = (int) strlen(tmp); + else + timestamp_width = 15; + } + + if (got_k5) + { + krb5_error_code retval; + retval = krb5_init_context(&kcontext); + if (retval) { + com_err(progname, retval, "while initializing krb5"); + exit(1); + } + + if (mode == DEFAULT || mode == CCACHE) + do_ccache(name); + else + do_keytab(name); + } else { +#ifdef KRB5_KRB4_COMPAT + if (mode == DEFAULT || mode == CCACHE) + do_v4_ccache(name); + else { + /* We may want to add v4 srvtab support */ + fprintf(stderr, + "%s: srvtab option not supported for Kerberos 4\n", + progname); + exit(1); + } +#endif /* KRB4_KRB5_COMPAT */ + } + + return 0; +} + +void do_keytab(name) + char *name; +{ + krb5_keytab kt; + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + char buf[BUFSIZ]; /* hopefully large enough for any type */ + char *pname; + int code; + + if (name == NULL) { + if ((code = krb5_kt_default(kcontext, &kt))) { + com_err(progname, code, "while getting default keytab"); + exit(1); + } + } else { + if ((code = krb5_kt_resolve(kcontext, name, &kt))) { + com_err(progname, code, "while resolving keytab %s", + name); + exit(1); + } + } + + if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) { + com_err(progname, code, "while getting keytab name"); + exit(1); + } + + printf("Keytab name: %s\n", buf); + + if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) { + com_err(progname, code, "while starting keytab scan"); + exit(1); + } + + if (show_time) { + printf("KVNO Timestamp"); + fillit(stdout, timestamp_width - sizeof("Timestamp") + 2, (int) ' '); + printf("Principal\n"); + printf("---- "); + fillit(stdout, timestamp_width, (int) '-'); + printf(" "); + fillit(stdout, 78 - timestamp_width - sizeof("KVNO"), (int) '-'); + printf("\n"); + } else { + printf("KVNO Principal\n"); + printf("---- --------------------------------------------------------------------------\n"); + } + + while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) { + if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) { + com_err(progname, code, "while unparsing principal name"); + exit(1); + } + printf("%4d ", entry.vno); + if (show_time) { + printtime(entry.timestamp); + printf(" "); + } + printf("%s", pname); + if (show_etype) + printf(" (%s) " , etype_string(entry.key.enctype)); + if (show_keys) { + printf(" (0x"); + { + int i; + for (i = 0; i < entry.key.length; i++) + printf("%02x", entry.key.contents[i]); + } + printf(")"); + } + printf("\n"); + krb5_free_unparsed_name(kcontext, pname); + } + if (code && code != KRB5_KT_END) { + com_err(progname, code, "while scanning keytab"); + exit(1); + } + if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) { + com_err(progname, code, "while ending keytab scan"); + exit(1); + } + exit(0); +} +void do_ccache(name) + char *name; +{ + krb5_ccache cache = NULL; + krb5_cc_cursor cur; + krb5_creds creds; + krb5_principal princ; + krb5_flags flags; + krb5_error_code code; + int exit_status = 0; + + if (status_only) + /* exit_status is set back to 0 if a valid tgt is found */ + exit_status = 1; + + if (name == NULL) { + if ((code = krb5_cc_default(kcontext, &cache))) { + if (!status_only) + com_err(progname, code, "while getting default ccache"); + exit(1); + } + } else { + if ((code = krb5_cc_resolve(kcontext, name, &cache))) { + if (!status_only) + com_err(progname, code, "while resolving ccache %s", + name); + exit(1); + } + } + + flags = 0; /* turns off OPENCLOSE mode */ + if ((code = krb5_cc_set_flags(kcontext, cache, flags))) { + if (code == KRB5_FCC_NOFILE) { + if (!status_only) { + com_err(progname, code, "(ticket cache %s:%s)", + krb5_cc_get_type(kcontext, cache), + krb5_cc_get_name(kcontext, cache)); +#ifdef KRB5_KRB4_COMPAT + if (name == NULL) + do_v4_ccache(0); +#endif + } + } else { + if (!status_only) + com_err(progname, code, + "while setting cache flags (ticket cache %s:%s)", + krb5_cc_get_type(kcontext, cache), + krb5_cc_get_name(kcontext, cache)); + } + exit(1); + } + if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) { + if (!status_only) + com_err(progname, code, "while retrieving principal name"); + exit(1); + } + if ((code = krb5_unparse_name(kcontext, princ, &defname))) { + if (!status_only) + com_err(progname, code, "while unparsing principal name"); + exit(1); + } + if (!status_only) { + printf("Ticket cache: %s:%s\nDefault principal: %s\n\n", + krb5_cc_get_type(kcontext, cache), + krb5_cc_get_name(kcontext, cache), defname); + fputs("Valid starting", stdout); + fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, + (int) ' '); + fputs("Expires", stdout); + fillit(stdout, timestamp_width - sizeof("Expires") + 3, + (int) ' '); + fputs("Service principal\n", stdout); + } + if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) { + if (!status_only) + com_err(progname, code, "while starting to retrieve tickets"); + exit(1); + } + while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) { + if (status_only) { + if (exit_status && creds.server->length == 2 && + strcmp(creds.server->realm.data, princ->realm.data) == 0 && + strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 && + strcmp((char *)creds.server->data[1].data, + princ->realm.data) == 0 && + creds.times.endtime > now) + exit_status = 0; + } else { + show_credential(&creds); + } + krb5_free_cred_contents(kcontext, &creds); + } + if (code == KRB5_CC_END) { + if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) { + if (!status_only) + com_err(progname, code, "while finishing ticket retrieval"); + exit(1); + } + flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */ + if ((code = krb5_cc_set_flags(kcontext, cache, flags))) { + if (!status_only) + com_err(progname, code, "while closing ccache"); + exit(1); + } +#ifdef KRB5_KRB4_COMPAT + if (name == NULL && !status_only) + do_v4_ccache(0); +#endif + exit(exit_status); + } else { + if (!status_only) + com_err(progname, code, "while retrieving a ticket"); + exit(1); + } +} + +char * +etype_string(enctype) + krb5_enctype enctype; +{ + static char buf[100]; + krb5_error_code retval; + + if ((retval = krb5_enctype_to_string(enctype, buf, sizeof(buf)))) { + /* XXX if there's an error != EINVAL, I should probably report it */ + sprintf(buf, "etype %d", enctype); + } + + return buf; +} + +static char * +flags_string(cred) + register krb5_creds *cred; +{ + static char buf[32]; + int i = 0; + + if (cred->ticket_flags & TKT_FLG_FORWARDABLE) + buf[i++] = 'F'; + if (cred->ticket_flags & TKT_FLG_FORWARDED) + buf[i++] = 'f'; + if (cred->ticket_flags & TKT_FLG_PROXIABLE) + buf[i++] = 'P'; + if (cred->ticket_flags & TKT_FLG_PROXY) + buf[i++] = 'p'; + if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE) + buf[i++] = 'D'; + if (cred->ticket_flags & TKT_FLG_POSTDATED) + buf[i++] = 'd'; + if (cred->ticket_flags & TKT_FLG_INVALID) + buf[i++] = 'i'; + if (cred->ticket_flags & TKT_FLG_RENEWABLE) + buf[i++] = 'R'; + if (cred->ticket_flags & TKT_FLG_INITIAL) + buf[i++] = 'I'; + if (cred->ticket_flags & TKT_FLG_HW_AUTH) + buf[i++] = 'H'; + if (cred->ticket_flags & TKT_FLG_PRE_AUTH) + buf[i++] = 'A'; + buf[i] = '\0'; + return(buf); +} + +void +printtime(tv) + time_t tv; +{ + char timestring[BUFSIZ]; + char fill; + + fill = ' '; + if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv, + timestring, + timestamp_width+1, + &fill)) { + printf(timestring); + } +} + +void +show_credential(cred) + register krb5_creds * cred; +{ + krb5_error_code retval; + krb5_ticket *tkt; + char *name, *sname, *flags; + int extra_field = 0; + + retval = krb5_unparse_name(kcontext, cred->client, &name); + if (retval) { + com_err(progname, retval, "while unparsing client name"); + return; + } + retval = krb5_unparse_name(kcontext, cred->server, &sname); + if (retval) { + com_err(progname, retval, "while unparsing server name"); + krb5_free_unparsed_name(kcontext, name); + return; + } + if (!cred->times.starttime) + cred->times.starttime = cred->times.authtime; + + printtime(cred->times.starttime); + putchar(' '); putchar(' '); + printtime(cred->times.endtime); + putchar(' '); putchar(' '); + + printf("%s\n", sname); + + if (strcmp(name, defname)) { + printf("\tfor client %s", name); + extra_field++; + } + + if (cred->ticket_flags & TKT_FLG_RENEWABLE) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + fputs("renew until ", stdout); + printtime(cred->times.renew_till); + extra_field += 2; + } + + if (extra_field > 3) { + fputs("\n", stdout); + extra_field = 0; + } + + if (show_flags) { + flags = flags_string(cred); + if (flags && *flags) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf("Flags: %s", flags); + extra_field++; + } + } + + if (extra_field > 2) { + fputs("\n", stdout); + extra_field = 0; + } + + if (show_etype) { + retval = krb5_decode_ticket(&cred->ticket, &tkt); + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf("Etype (skey, tkt): %s, ", + etype_string(cred->keyblock.enctype)); + printf("%s ", + etype_string(tkt->enc_part.enctype)); + krb5_free_ticket(kcontext, tkt); + extra_field++; + } + + /* if any additional info was printed, extra_field is non-zero */ + if (extra_field) + putchar('\n'); + + + if (show_addresses) { + if (!cred->addresses || !cred->addresses[0]) { + printf("\tAddresses: (none)\n"); + } else { + int i; + + printf("\tAddresses: "); + one_addr(cred->addresses[0]); + + for (i=1; cred->addresses[i]; i++) { + printf(", "); + one_addr(cred->addresses[i]); + } + + printf("\n"); + } + } + + krb5_free_unparsed_name(kcontext, name); + krb5_free_unparsed_name(kcontext, sname); +} + +void one_addr(a) + krb5_address *a; +{ + struct hostent *h; + + if ((a->addrtype == ADDRTYPE_INET && a->length == 4) +#ifdef AF_INET6 + || (a->addrtype == ADDRTYPE_INET6 && a->length == 16) +#endif + ) { + int af = AF_INET; +#ifdef AF_INET6 + if (a->addrtype == ADDRTYPE_INET6) + af = AF_INET6; +#endif + if (!no_resolve) { +#ifdef HAVE_GETIPNODEBYADDR + int err; + h = getipnodebyaddr(a->contents, a->length, af, &err); + if (h) { + printf("%s", h->h_name); + freehostent(h); + } +#else + h = gethostbyaddr(a->contents, (int) a->length, af); + if (h) { + printf("%s", h->h_name); + } +#endif + if (h) + return; + } + if (no_resolve || !h) { +#ifdef HAVE_INET_NTOP + char buf[46]; + const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf)); + if (name) { + printf ("%s", name); + return; + } +#else + if (a->addrtype == ADDRTYPE_INET) { + printf("%d.%d.%d.%d", a->contents[0], a->contents[1], + a->contents[2], a->contents[3]); + return; + } +#endif + } + } + printf("unknown addr type %d", a->addrtype); +} + +void +fillit(f, num, c) + FILE *f; + unsigned int num; + int c; +{ + int i; + + for (i=0; i<num; i++) + fputc(c, f); +} + +#ifdef KRB5_KRB4_COMPAT +void +do_v4_ccache(name) + char * name; +{ +#if USE_CCAPI + cc_context_t context = nil; + cc_ccache_t cache = nil; + cc_credentials_iterator_t credsIterator = nil; + cc_credentials_t creds = nil; + cc_string_t cacheName = nil, principalName = nil; + cc_int32 err; +#else + char pname[ANAME_SZ]; + char pinst[INST_SZ]; + char prealm[REALM_SZ]; + int k_errno; + CREDENTIALS c; +#endif + char *file; + int header = 1; + + if (!got_k4) + return; + + file = name?name:tkt_string(); + + if (status_only) { + fprintf(stderr, "%s: exit status option not supported for Kerberos 4\n", progname); + exit(1); + } + + if (got_k5) + printf("\n\n"); + + printf("Kerberos 4 ticket cache: %s\n", file); + +#if USE_CCAPI + /* Initialize the CCache library */ + err = cc_initialize (&context, ccapi_version_4, nil, nil); + if (err != ccNoError) { + fprintf(stderr, "%s: cc_initialize returned error = %ld\n", progname, err); + exit(1); + } + + /* Get the default cache */ + err = cc_context_get_default_ccache_name (context, &cacheName); + if (err != ccNoError) { + fprintf(stderr, "%s: cc_context_get_default_ccache_name returned error = %ld\n", progname, err); + exit(1); + } + + /* Open the default cache */ + err = cc_context_open_default_ccache (context, &cache); + if ((err != ccNoError) && (err != ccErrCCacheNotFound)) { + fprintf(stderr, "%s: cc_context_open_default_ccache returned error = %ld\n", progname, err); + exit(1); + } else if (err == ccErrCCacheNotFound) { + printf("%s: No tickets in Credentials Cache\n", progname); + exit(0); + } + + /* get the v4 principal of the ccache */ + err = cc_ccache_get_principal (cache, cc_credentials_v4, &principalName); + if ((err != ccNoError) && (err != ccErrBadCredentialsVersion)) { + fprintf(stderr, "%s: cc_ccache_get_principal returned error = %ld\n", progname, err); + exit(1); + } else if (err == ccErrBadCredentialsVersion) { + printf("%s: No v4 tickets in Credentials Cache\n", progname); + exit(0); + } + + /* display the principal */ + printf("Default Principal: %s\n\n", principalName -> data); + + /* Loop over the credentials and display them */ + err = cc_ccache_new_credentials_iterator (cache, &credsIterator); + if (err != ccNoError) { + fprintf(stderr, "%s: cc_ccache_new_credentials_iterator returned error = %ld\n", progname, err); + exit(1); + } + + for (;;) { + err = cc_credentials_iterator_next (credsIterator, &creds); + if ((err != ccNoError) && (err != ccIteratorEnd)) { + fprintf(stderr, "%s: cc_credentials_iterator_next returned error = %ld\n", progname, err); + exit(1); + } else if (err == ccIteratorEnd) { + err = ccNoError; // this is an error we can deal with, so reset so we continue to dump data + break; + } + + + /* print out any v4 credentials */ + if (creds -> data -> version == cc_credentials_v4) { + cc_credentials_v4_t *creds4 = creds -> data -> credentials.credentials_v4; + + if (header) { + printf("%-18s %-18s %s\n", " Issued", " Expires", " Principal"); + header = 0; + } + printtime(creds4 -> issue_date); + fputs(" ", stdout); + + /* ccapi_version_4 compensates for long lifetimes so we just add here: */ + printtime(creds4 -> issue_date + creds4 -> lifetime); + + printf(" %s%s%s%s%s\n", creds4 -> service, (creds4 -> service_instance[0] ? "." : ""), + creds4 -> service_instance, (creds4 -> realm[0] ? "@" : ""), creds4 -> realm); + } + + cc_credentials_release (creds); + creds = nil; + } + + cc_credentials_iterator_release (credsIterator); + credsIterator = nil; + + cc_ccache_release (cache); + cache = nil; + +#else + + /* + * Since krb_get_tf_realm will return a ticket_file error, + * we will call tf_init and tf_close first to filter out + * things like no ticket file. Otherwise, the error that + * the user would see would be + * klist: can't find realm of ticket file: No ticket file (tf_util) + * instead of + * klist: No ticket file (tf_util) + */ + + /* Open ticket file */ + k_errno = tf_init(file, R_TKT_FIL); + if (k_errno) { + fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno)); + exit(1); + } + /* Close ticket file */ + (void) tf_close(); + + /* + * We must find the realm of the ticket file here before calling + * tf_init because since the realm of the ticket file is not + * really stored in the principal section of the file, the + * routine we use must itself call tf_init and tf_close. + */ + if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) { + fprintf(stderr, "%s: can't find realm of ticket file: %s\n", + progname, krb_get_err_text (k_errno)); + exit(1); + } + + /* Open ticket file */ + if ((k_errno = tf_init(file, R_TKT_FIL))) { + fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno)); + exit(1); + } + /* Get principal name and instance */ + if ((k_errno = tf_get_pname(pname)) || + (k_errno = tf_get_pinst(pinst))) { + fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno)); + exit(1); + } + + /* + * You may think that this is the obvious place to get the + * realm of the ticket file, but it can't be done here as the + * routine to do this must open the ticket file. This is why + * it was done before tf_init. + */ + + printf("Principal: %s%s%s%s%s\n\n", pname, + (pinst[0] ? "." : ""), pinst, + (prealm[0] ? "@" : ""), prealm); + while ((k_errno = tf_get_cred(&c)) == KSUCCESS) { + if (header) { + printf("%-18s %-18s %s\n", + " Issued", " Expires", " Principal"); + header = 0; + } + printtime(c.issue_date); + fputs(" ", stdout); + printtime(krb_life_to_time(c.issue_date, c.lifetime)); + printf(" %s%s%s%s%s\n", + c.service, (c.instance[0] ? "." : ""), c.instance, + (c.realm[0] ? "@" : ""), c.realm); + } + if (header && k_errno == EOF) { + printf("No tickets in file.\n"); + } +#endif +} +#endif /* KRB4_KRB5_COMPAT */ |