From: bjaspan@aktis.com ("Barry Jaspan")
Subject: V5 kinit patch: "ksrvtgt" functionality
Organization: Internet-USENET Gateway at Stanford University
Date: Thu, 24 Dec 1992 21:31:58 GMT


The V4 program ksrvtgt always had the frustrating property of being
less flexible than kinit, even though it performed essentially the
same function (namely, obtaining a tgt for a specified principal,
using a key from a srvtab instead of a password provided by the user).

Since the current V5 distribution does not appear to contain a
ksrvtgt, I decided to prevent the problem from recurring by extending
kinit to provide "ksrvtgt functionality."  I have added two command
line options:

-k -- read the principal's key from the keytab instead of reading it
from the keyboard

-t keytab -- use the keytab <keytab> instead of the default keytab.

All other options operate normally.  If no principal name is
specified, the default host principal (host/canonical_host_name@REALM)
is used.

Barry Jaspan, bjaspan@aktis.com
Aktis, Inc.

===================================================================
RCS file: RCS/kinit.c,v
retrieving revision 5.23
diff -c -r5.23 kinit.c
*** 5.23	1992/09/30 14:09:54
--- kinit.c	1992/12/24 21:16:22
***************
*** 68,73 ****
--- 68,74 ----
  {
      krb5_ccache ccache = NULL;
      char *cache_name = NULL;		/* -f option */
+     char *keytab_name = NULL;		/* -t option */
      long lifetime = KRB5_DEFAULT_LIFE;	/* -l option */
      long rlife = 0;
      int options = KRB5_DEFAULT_OPTIONS;
***************
*** 79,84 ****
--- 80,88 ----
      krb5_principal server;
      krb5_creds my_creds;
      krb5_timestamp now;
+     int use_keytab = 0;			/* -k option */
+     krb5_keytab keytab = NULL;
+     krb5_keytab_entry kt_ent;
      struct passwd *pw = 0;
      int pwsize;
      char password[255], *client_name, prompt[255];
***************
*** 88,94 ****
      if (strrchr(argv[0], '/'))
  	argv[0] = strrchr(argv[0], '/')+1;
  
!     while ((option = getopt(argc, argv, "r:fpl:c:")) != EOF) {
  	switch (option) {
  	case 'r':
  	    options |= KDC_OPT_RENEWABLE;
--- 92,98 ----
      if (strrchr(argv[0], '/'))
  	argv[0] = strrchr(argv[0], '/')+1;
  
!     while ((option = getopt(argc, argv, "r:fpl:c:kt:")) != EOF) {
  	switch (option) {
  	case 'r':
  	    options |= KDC_OPT_RENEWABLE;
***************
*** 104,110 ****
  	case 'f':
  	    options |= KDC_OPT_FORWARDABLE;
  	    break;
! 	case 'l':
  	    code = krb5_parse_lifetime(optarg, &lifetime);
  	    if (code != 0 || lifetime == 0) {
  		fprintf(stderr, "Bad lifetime value (%s hours?)\n", optarg);
--- 108,132 ----
  	case 'f':
  	    options |= KDC_OPT_FORWARDABLE;
  	    break;
!        case 'k':
! 	    use_keytab = 1;
! 	    break;
!        case 't':
! 	    if (keytab == NULL) {
! 		 keytab_name = optarg;
! 
! 		 code = krb5_kt_resolve(keytab_name, &keytab);
! 		 if (code != 0) {
! 		      com_err(argv[0], code, "resolving keytab %s",
! 			      keytab_name);
! 		 errflg++;
! 		 }
! 	    } else {
! 		 fprintf(stderr, "Only one -t option allowed.\n");
! 		 errflg++;
! 	    }
! 	    break;
!        case 'l':
  	    code = krb5_parse_lifetime(optarg, &lifetime);
  	    if (code != 0 || lifetime == 0) {
  		fprintf(stderr, "Bad lifetime value (%s hours?)\n", optarg);
***************
*** 117,123 ****
  		
  		code = krb5_cc_resolve (cache_name, &ccache);
  		if (code != 0) {
! 		    com_err (argv[0], code, "resolving %s", cache_name);
  		    errflg++;
  		}
  	    } else {
--- 139,146 ----
  		
  		code = krb5_cc_resolve (cache_name, &ccache);
  		if (code != 0) {
! 		    com_err (argv[0], code, "resolving ccache %s",
! 			     cache_name);
  		    errflg++;
  		}
  	    } else {
***************
*** 133,173 ****
      }
  
      if (errflg) {
! 	fprintf(stderr, "Usage: %s [ -r time ] [ -puf ] [ -l lifetime ] [ -c cachename ] [principal]\n", argv[0]);
  	exit(2);
      }
  
      if (ccache == NULL) {
! 	if (code = krb5_cc_default(&ccache)) {
! 	    com_err(argv[0], code, "while getting default ccache");
! 	    exit(1);
! 	}
      }
!     
      if (optind != argc-1) {       /* No principal name specified */
! 	/* Get default principal from cache if one exists */
! 	code = krb5_cc_get_principal(ccache, &me);
! 	/* Else search passwd file for client */
! 	if (code) {
! 	    pw = getpwuid((int) getuid());
! 	    if (pw) {
! 		if (code = krb5_parse_name (pw->pw_name, &me)) {
! 		    com_err (argv[0], code, "when parsing name %s", pw->pw_name);
! 		    exit(1);
! 		}
! 	    } 
! 	    else {
! 		fprintf(stderr, 
  			"Unable to identify user from password file\n");
! 		exit(1);
! 	    }
! 	}
      }
-     else /* Use specified name */
-       if (code = krb5_parse_name (argv[optind], &me)) {
- 	  com_err (argv[0], code, "when parsing name %s",argv[optind]);
- 	  exit(1);
-       }
      
      if (code = krb5_unparse_name(me, &client_name)) {
  	com_err (argv[0], code, "when unparsing name");
--- 156,206 ----
      }
  
      if (errflg) {
! 	fprintf(stderr, "Usage: %s [-r time] [-puf] [-l lifetime] [-c cachename] [-k] [-t keytab] [principal]\n", argv[0]);
  	exit(2);
      }
  
      if (ccache == NULL) {
! 	 if (code = krb5_cc_default(&ccache)) {
! 	      com_err(argv[0], code, "while getting default ccache");
! 	      exit(1);
! 	 }
      }
! 
      if (optind != argc-1) {       /* No principal name specified */
! 	 if (use_keytab) {
! 	      /* Use the default host/service name */
! 	      code = krb5_sname_to_principal(NULL, NULL,
! 					     KRB5_NT_SRV_HST, &me);
! 	      if (code) {
! 		   com_err(argv[0], code,
! 			   "when creating default server principal name");
! 		   exit(1);
! 	      }
! 	 } else {
! 	      /* Get default principal from cache if one exists */
! 	      code = krb5_cc_get_principal(ccache, &me);
! 	      if (code) {
! 		   /* Else search passwd file for client */
! 		   pw = getpwuid((int) getuid());
! 		   if (pw) {
! 			if (code = krb5_parse_name (pw->pw_name, &me)) {
! 			     com_err (argv[0], code, "when parsing name %s",
! 				      pw->pw_name);
! 			     exit(1);
! 			}
! 		   } else {
! 			fprintf(stderr, 
  			"Unable to identify user from password file\n");
! 			exit(1);
! 		   }
! 	      }
! 	 }
!     } /* Use specified name */	 
!     else if (code = krb5_parse_name (argv[optind], &me)) {
! 	 com_err (argv[0], code, "when parsing name %s",argv[optind]);
! 	 exit(1);
      }
      
      if (code = krb5_unparse_name(me, &client_name)) {
  	com_err (argv[0], code, "when unparsing name");
***************
*** 215,241 ****
      } else
  	my_creds.times.renew_till = 0;
  
!     (void) sprintf(prompt,"Password for %s: ", (char *) client_name);
  
!     pwsize = sizeof(password);
  
!     code = krb5_read_password(prompt, 0, password, &pwsize);
!     if (code || pwsize == 0) {
! 	fprintf(stderr, "Error while reading password for '%s'\n",
! 		client_name);
! 	memset(password, 0, sizeof(password));
! 	krb5_free_addresses(my_addresses);
! 	exit(1);
      }
! 
!     code = krb5_get_in_tkt_with_password(options, my_addresses,
! 					 KRB5_PADATA_ENC_TIMESTAMP,
! 					 ETYPE_DES_CBC_CRC,
! 					 KEYTYPE_DES,
! 					 password,
! 					 ccache,
! 					 &my_creds, 0);
!     memset(password, 0, sizeof(password));
      krb5_free_principal(server);
      krb5_free_addresses(my_addresses);
      
--- 248,295 ----
      } else
  	my_creds.times.renew_till = 0;
  
!     if (!use_keytab) {
! 	 (void) sprintf(prompt,"Password for %s: ", (char *) client_name);
  
! 	 pwsize = sizeof(password);
  
! 	 code = krb5_read_password(prompt, 0, password, &pwsize);
! 	 if (code || pwsize == 0) {
! 	      fprintf(stderr, "Error while reading password for '%s'\n",
! 		      client_name);
! 	      memset(password, 0, sizeof(password));
! 	      krb5_free_addresses(my_addresses);
! 	      exit(1);
! 	 }
! 
! 	 code = krb5_get_in_tkt_with_password(options, my_addresses,
! 					      KRB5_PADATA_ENC_TIMESTAMP,
! 					      ETYPE_DES_CBC_CRC,
! 					      KEYTYPE_DES,
! 					      password,
! 					      ccache,
! 					      &my_creds, 0);
! 	 memset(password, 0, sizeof(password));
!     } else {
! 	 if (keytab != NULL) {
! 	      code = krb5_kt_get_entry(keytab, my_creds.client, 0,
! 				       &kt_ent);
! 	      if (code) {
! 		   com_err(argv[0], code, "reading keytab entry %s",
! 			   client_name);
! 		   exit(1);
! 	      }
! 	 }
! 		   
! 	 code = krb5_get_in_tkt_with_skey(options, my_addresses,
! 					  KRB5_PADATA_ENC_TIMESTAMP,
! 					  ETYPE_DES_CBC_CRC,
! 					  keytab ? &kt_ent.key : NULL,
! 					  ccache, &my_creds, 0);
! 	 if (keytab != NULL)
! 	      krb5_kt_free_entry(&kt_ent);
      }
!     
      krb5_free_principal(server);
      krb5_free_addresses(my_addresses);
      
Newsgroups: comp.protocols.kerberos