From 6b2929e54b9d0da84338cc5f23ac31b95ffcfe2e Mon Sep 17 00:00:00 2001
From: Theodore Tso <tytso@mit.edu>
Date: Thu, 8 Jun 1995 21:47:51 +0000
Subject: Integrated patch from OpenVision which allows klist to list keytabs
 as well as ccache's.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5984 dc483132-0cff-0310-8789-dd5450dbe970
---
 src/clients/klist/ChangeLog |   5 +
 src/clients/klist/klist.c   | 313 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 242 insertions(+), 76 deletions(-)

(limited to 'src')

diff --git a/src/clients/klist/ChangeLog b/src/clients/klist/ChangeLog
index 924bbd32f2..a5c82ea3b4 100644
--- a/src/clients/klist/ChangeLog
+++ b/src/clients/klist/ChangeLog
@@ -1,3 +1,8 @@
+Thu Jun  8 17:46:51 1995    <tytso@rsx-11.mit.edu>
+
+	* klist.c: Integrated patch from OpenVision which allows klist to
+		list keytabs as well as ccache's.
+
 Thu May 11 07:31:42 1995  Ezra Peisach  <epeisach@kangaroo.mit.edu>
 
 	* klist.c (main): Update usage message to include -e and -f.
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index ecd398d880..4030ca94b0 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -21,139 +21,297 @@
  * or implied warranty.
  * 
  *
- * List out the contents of your credential cache.
+ * List out the contents of your credential cache or keytab.
  */
 
 #include "krb5.h"
 #include "com_err.h"
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
 
 extern int optind;
 extern char *optarg;
+int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
 int show_etype = 0;
-int show_flags = 0;
 char *defname;
-time_t now;
+char *progname;
+krb5_int32 now;
 
-void
-show_credential 
-	PROTOTYPE((char *,
-		   krb5_context,
-		   krb5_creds *));
+krb5_context kcontext;
+
+void show_credential PROTOTYPE((char *,
+				krb5_context,
+				krb5_creds *));
+	
+void do_ccache PROTOTYPE((char *));
+void do_keytab PROTOTYPE((char *));
+void 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;
-    krb5_ccache cache = NULL;
-    krb5_cc_cursor cur;
-    krb5_creds creds;
-    char *cache_name;
-    krb5_principal princ;
-    krb5_flags flags;
-    krb5_context kcontext;
+    char *name;
+    int mode;
 
     krb5_init_context(&kcontext);
     krb5_init_ets(kcontext);
 
-    time(&now);
-    
-    if (strrchr(argv[0], '/'))
-	argv[0] = strrchr(argv[0], '/')+1;
+    progname = (strrchr(*argv, '/') ? strrchr(*argv, '/')+1 : argv[0]);
 
-    while ((c = getopt(argc, argv, "efc:")) != EOF) {
-	switch (c) {
+    argv++;
+    name = NULL;
+    mode = DEFAULT;
+    while (*argv) {
+	if ((*argv)[0] != '-') {
+	    if (name) usage();
+	    name = *argv;
+	} else switch ((*argv)[1]) {
 	case 'e':
-	     show_etype = 1;
-	     break;
+	    show_etype = 1;
+	    break;
 	case 'f':
-	     show_flags = 1;
-	     break;
+	    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 (cache == NULL) {
-		cache_name = optarg;
-		
-		code = krb5_cc_resolve (kcontext, cache_name, &cache);
-		if (code != 0) {
-		    com_err(argv[0], code, "while resolving %s", cache_name);
-		    errflg++;
-		}
-	    } else {
-		fprintf(stderr, "Only one -c option allowed\n");
-		errflg++;
-	    }
+	    if (mode != DEFAULT) usage();
+	    mode = CCACHE;
+	    break;
+	case 'k':
+	    if (mode != DEFAULT) usage();
+	    mode = KEYTAB;
 	    break;
-	case '?':
 	default:
-	    errflg++;
+	    usage();
 	    break;
 	}
+	argv++;
     }
 
-    if (optind != argc)
-	errflg++;
-    
-    if (errflg) {
-	fprintf(stderr, "Usage: %s [ -c cache ] [-e] [-f]\n", argv[0]);
-	exit(2);
+    if (mode == DEFAULT || mode == CCACHE) {
+	 if (show_time || show_keys)
+	      usage();
+    } else {
+	 if (show_flags || status_only)
+	      usage();
+    }
+
+    if ((code = krb5_timeofday(kcontext, &now))) {
+	 if (!status_only)
+	      com_err(progname, code, "while getting time of day.");
+	 exit(1);
     }
-    if (cache == NULL) {
-	if (code = krb5_cc_default(kcontext, &cache)) {
-	    com_err(argv[0], code, "while getting default ccache");
+
+    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;
+     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          Principal\n");
+	  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_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(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_cc_set_flags(kcontext, cache, flags))) {
 	if (code == ENOENT) {
-	    com_err(argv[0], code, "(ticket cache %s)",
-		    krb5_cc_get_name(kcontext, cache));
-	} else
-	    com_err(argv[0], code,
-		    "while setting cache flags (ticket cache %s)",
-		    krb5_cc_get_name(kcontext, cache));
+	    if (!status_only)
+		com_err(progname, code, "(ticket cache %s)",
+			krb5_cc_get_name(kcontext, cache));
+	} else {
+	    if (!status_only)
+		com_err(progname, code,
+			"while setting cache flags (ticket cache %s)",
+			krb5_cc_get_name(kcontext, cache));
+	}
 	exit(1);
     }
-    if (code = krb5_cc_get_principal(kcontext, cache, &princ)) {
-	com_err(argv[0], code, "while retrieving principal name");
+    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)) {
-	com_err(argv[0], code, "while unparsing principal name");
+    if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
+	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(kcontext, cache), defname);
-    if (code = krb5_cc_start_seq_get(kcontext, cache, &cur)) {
-	com_err(argv[0], code, "while starting to retrieve tickets");
+    if (!status_only) {
+	printf("Ticket cache: %s\nDefault principal: %s\n\n",
+	       krb5_cc_get_name(kcontext, cache), defname);
+	fputs("  Valid starting       Expires          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);
     }
-    fputs("  Valid starting       Expires          Service principal\n",
-	  stdout);
     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
-	show_credential(argv[0], kcontext, &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(progname, kcontext, &creds);
+	}
 	krb5_free_cred_contents(kcontext, &creds);
     }
     if (code == KRB5_CC_END) {
-	if (code = krb5_cc_end_seq_get(kcontext, cache, &cur)) {
-	    com_err(argv[0], code, "while finishing ticket retrieval");
+	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)) {
-	    com_err(argv[0], code, "while closing ccache");
+	if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
+	    if (!status_only)
+		com_err(progname, code, "while closing ccache");
 	    exit(1);
 	}
-	exit(0);
+	exit(exit_status);
     } else {
-	com_err(argv[0], code, "while retrieving a ticket");
+	if (!status_only)
+	    com_err(progname, code, "while retrieving a ticket");
 	exit(1);
     }	
 }
@@ -263,6 +421,7 @@ show_credential(progname, kcontext, cred)
 		fputs(", ",stdout);
 	fputs("renew until ", stdout);
         printtime(cred->times.renew_till);
+	first = 0;
     }
 
     if (show_etype) {
@@ -295,7 +454,9 @@ show_credential(progname, kcontext, cred)
         }
     }
 
-    putchar('\n');
+    /* if any additional info was printed, first is zero */
+    if (!first)
+	putchar('\n');
     free(name);
     free(sname);
 }
-- 
cgit