[1169] in Kerberos-V5-bugs
krb5b4pl3: clients/klist/klist.c: many improvements
daemon@ATHENA.MIT.EDU (Jonathan I. Kamens)
Tue Mar 14 14:17:09 1995
From: "Jonathan I. Kamens" <jik@cam.ov.com>
Date: Tue, 14 Mar 1995 14:19:17 -0500
To: krb5-bugs@MIT.EDU
The patch below provides numerous improvements to klist, including:
* Update usage message.
* Enforce usage message (e.g., don't allow conflicting options).
* Display keytabs as well as credential caches ("-k" option).
* Add "-s" option, to exit with status indicating whether or not a
valid TGT is present, without printing anything else.
* Print DES key contents with "-K".
--- clients/klist/klist.c 1995/03/09 17:07:37 1.1.1.1
+++ clients/klist/klist.c 1995/03/09 17:13:41 1.5
@@ -21,7 +21,7 @@
* or implied warranty.
*
*
- * List out the contents of your credential cache.
+ * List out the contents of your credential cache or keytab.
*/
#include <stdio.h>
@@ -33,123 +33,280 @@
extern int optind;
extern char *optarg;
-int show_flags = 0;
+int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
char *progname;
char *defname;
time_t now;
-void
-show_credential PROTOTYPE((krb5_creds *));
+void show_credential PROTOTYPE((krb5_creds *)),
+ do_ccache PROTOTYPE((char *)),
+ do_keytab PROTOTYPE((char *)),
+ printtime PROTOTYPE((time_t));
+
+#define DEFAULT 0
+#define CCACHE 1
+#define KEYTAB 2
+
+void usage()
+{
+ fprintf(stderr, "Usage: %s [[-c] [-f] [-s]] [-k [-t] [-K]] [name]\n",
+ progname);
+ fprintf(stderr, "\t-c specifies credentials cache, -k specifies keytab");
+ fprintf(stderr, ", -c is default\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, "\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);
+}
void
main(argc, argv)
int argc;
char **argv;
{
- int c;
- int errflg = 0;
- int code;
+ int mode, code;
+ char *name;
+
+ krb5_init_ets();
+
+ progname = (strrchr(*argv, '/') ? strrchr(*argv, '/')+1 : argv[0]);
+
+ argv++;
+ name = NULL;
+ mode = DEFAULT;
+ while (*argv) {
+ if ((*argv)[0] != '-') {
+ if (name) usage();
+ name = *argv;
+ } else switch ((*argv)[1]) {
+ case 'f':
+ show_flags = 1;
+ break;
+ case 't':
+ show_time = 1;
+ break;
+ case 'K':
+ show_keys = 1;
+ break;
+ case 's':
+ status_only = 1;
+ break;
+ case 'c':
+ if (mode != DEFAULT) usage();
+ mode = CCACHE;
+ break;
+ case 'k':
+ if (mode != DEFAULT) usage();
+ mode = KEYTAB;
+ break;
+ default:
+ usage();
+ break;
+ }
+
+ argv++;
+ }
+
+ if (mode == DEFAULT || mode == CCACHE) {
+ if (show_time || show_keys)
+ usage();
+ } else {
+ if (show_flags || status_only)
+ usage();
+ }
+
+ if (code = krb5_timeofday(&now)) {
+ if (!status_only)
+ com_err(progname, code, "while getting time of day.");
+ exit(1);
+ }
+
+ if (mode == DEFAULT || mode == CCACHE)
+ do_ccache(name);
+ else
+ do_keytab(name);
+}
+
+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, *tstring;
+ int code;
+
+ if (name == NULL) {
+ if (code = krb5_kt_default(&kt)) {
+ com_err(progname, code, "while getting default keytab");
+ exit(1);
+ }
+ } else {
+ if (code = krb5_kt_resolve(name, &kt)) {
+ com_err(progname, code, "while resolving keytab %s",
+ name);
+ exit(1);
+ }
+ }
+
+ if (code = krb5_kt_get_name(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(kt, &cursor)) {
+ com_err(progname, code, "while starting keytab scan");
+ exit(1);
+ }
+
+ if (show_time) {
+ printf("KVNO Timestamp Principal\n");
+ printf("---- ------------------ -------------------------------------------------------\n");
+ } else {
+ printf("KVNO Principal\n");
+ printf("---- --------------------------------------------------------------------------\n");
+ }
+
+ while ((code = krb5_kt_next_entry(kt, &entry, &cursor)) == 0) {
+ if (code = krb5_unparse_name(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_keys) {
+ printf(" (0x");
+ {
+ int i;
+ for (i = 0; i < entry.key.length; i++)
+ printf("%02x", entry.key.contents[i]);
+ }
+ printf(")");
+ }
+ printf("\n");
+ free(pname);
+ }
+ if (code && code != KRB5_KT_END) {
+ com_err(progname, code, "while scanning keytab");
+ exit(1);
+ }
+ if (code = krb5_kt_end_seq_get(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;
- char *cache_name;
krb5_principal princ;
krb5_flags flags;
+ int code, exit_status;
- krb5_init_ets();
-
- time(&now);
-
- if (strrchr(argv[0], '/'))
- progname = strrchr(argv[0], '/')+1;
+ if (status_only)
+ /* exit_status is set back to 0 if a valid tgt is found */
+ exit_status = 1;
else
- progname = argv[0];
-
- while ((c = getopt(argc, argv, "fc:")) != EOF) {
- switch (c) {
- case 'f':
- show_flags = 1;
- break;
- case 'c':
- if (cache == NULL) {
- cache_name = optarg;
-
- code = krb5_cc_resolve (cache_name, &cache);
- if (code != 0) {
- com_err(progname, code, "while resolving %s", cache_name);
- errflg++;
- }
- } else {
- fprintf(stderr, "Only one -c option allowed\n");
- errflg++;
- }
- break;
- case '?':
- default:
- errflg++;
- break;
- }
- }
-
- if (optind != argc)
- errflg++;
+ exit_status = 0;
- if (errflg) {
- fprintf(stderr, "Usage: %s [ -c cache ]\n", progname);
- exit(2);
- }
- if (cache == NULL) {
- if (code = krb5_cc_default(&cache)) {
- com_err(progname, code, "while getting default ccache");
- exit(1);
- }
+ if (name == NULL) {
+ if (code = krb5_cc_default(&cache)) {
+ if (!status_only)
+ com_err(progname, code, "while getting default ccache");
+ exit(1);
+ }
+ } else {
+ if (code = krb5_cc_resolve(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(cache, flags)) {
if (code == ENOENT) {
- com_err(progname, code, "(ticket cache %s)",
- krb5_cc_get_name(cache));
+ if (!status_only)
+ com_err(progname, code, "(ticket cache %s)",
+ krb5_cc_get_name(cache));
} else
- com_err(progname, code,
- "while setting cache flags (ticket cache %s)",
- krb5_cc_get_name(cache));
+ if (!status_only)
+ com_err(progname, code,
+ "while setting cache flags (ticket cache %s)",
+ krb5_cc_get_name(cache));
exit(1);
}
if (code = krb5_cc_get_principal(cache, &princ)) {
- com_err(progname, code, "while retrieving principal name");
- exit(1);
+ if (!status_only)
+ com_err(progname, code, "while retrieving principal name");
+ exit(1);
}
if (code = krb5_unparse_name(princ, &defname)) {
- com_err(progname, code, "while unparsing principal name");
- exit(1);
+ if (!status_only)
+ com_err(progname, code, "while unparsing principal name");
+ exit(1);
}
- printf("Ticket cache: %s\nDefault principal: %s\n\n",
- krb5_cc_get_name(cache), defname);
+
+ if (!status_only) {
+ printf("Ticket cache: %s\nDefault principal: %s\n\n",
+ krb5_cc_get_name(cache), defname);
+ fputs(" Valid starting Expires Service principal\n",
+ stdout);
+ }
+
if (code = krb5_cc_start_seq_get(cache, &cur)) {
- com_err(progname, code, "while starting to retrieve tickets");
- exit(1);
+ if (!status_only)
+ com_err(progname, code, "while starting to retrieve tickets");
+ exit(1);
}
- fputs(" Valid starting Expires Service principal\n",
- stdout);
+
while (!(code = krb5_cc_next_cred(cache, &cur, &creds))) {
- show_credential(&creds);
- krb5_free_cred_contents(&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(&creds);
}
+
if (code == KRB5_CC_END) {
if (code = krb5_cc_end_seq_get(cache, &cur)) {
- com_err(progname, code, "while finishing ticket retrieval");
- exit(1);
+ 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(cache, flags)) {
- com_err(progname, code, "while closing ccache");
- exit(1);
+ if (!status_only)
+ com_err(progname, code, "while closing ccache");
+ exit(1);
}
- exit(0);
+ exit(exit_status);
} else {
- com_err(progname, code, "while retrieving a ticket");
- exit(1);
+ if (!status_only)
+ com_err(progname, code, "while retrieving a ticket");
+ exit(1);
}
}
@@ -244,6 +401,7 @@
fputs(", ",stdout);
fputs("renew until ", stdout);
printtime(cred->times.renew_till);
+ first = 0;
}
if (show_flags) {
flags = flags_string(cred);
@@ -256,7 +414,9 @@
first = 0;
}
}
- putchar('\n');
+ /* if any additional info was printed, first is zero */
+ if (!first)
+ putchar('\n');
free(name);
free(sname);
}