[1169] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

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);
 }

home help back first fref pref prev next nref lref last post