[412] in Kerberos-V5-bugs

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

Re: Some bugs, some questions, and a Next.cf

daemon@ATHENA.MIT.EDU (Andrew Gross)
Wed Jan 26 02:56:48 1994

Date: Tue, 25 Jan 94 23:56:29 -0800
From: Andrew Gross <drew@drew.extern.ucsd.edu>
To: drew@drew.extern.ucsd.edu, tytso@MIT.EDU
Cc: krb5-bugs@athena.mit.edu.

>    Date: Mon, 24 Jan 94 23:11:45 -0800
>    From: Andrew Gross <drew@drew.extern.ucsd.edu>
> 
>       Are you all interested in mods to make multihomed hosts possible
>    under K5?  I can make kadmind listen on all interfaces, krshd/krlogind
>    choose the right pricipal based on the interface being used, and
>    kdb5_edit extract several principals to the v5srvtab (one per
>    interface).  I understand that you do not have any use for this
>    functionality but could it be added (#defined) to show others who want
>    to use it how it can be done?
> 
> Yes, I'm interested; send me diffs, and I'll see about getting them
> integrated in.  Please try to make the changes as clean as possible.
> While the Kerberos V5 distributions haven't been exactly clean
> themselves, I've been trying make the code cleaner, and I'd rather not
> add any dirty code in.

Hello,

   Don't you violate a law of thermodynamics if you only add cleaner
code???

   Here are the patches I have for multihomed hosts.  They are
reasonably clean except for I don't like how the buffer overflow for
the hostname being too long is handled in the krshd/krlogind patches.
It should be a fatal error but the syslog/exit does not appeal to me.

Thank you,
Andrew Gross
=========================================================================

%%% To make kadmind listen on multiple interfaces, it just needs to
%%% in adm_network.c(line 223) put INADDR_ANY into
%%% client_server_info.server_name.sin_addr[.s_addr] in the "#ifdef unicos61"
%%% construct.



%%% This is a patch for kdb5_edit.  It adds the nxst command which can
%%% be used to extract multiple principals into the v5srvtab.  I got
%%% this from the kerberos mailing list and all credit for it goes
%%% to Jonathan Kamens (jik@MIT.Edu).

diff -r -c edit/kdb5_ed_ct.ct edit.x/kdb5_ed_ct.ct
*** edit/kdb5_ed_ct.ct	Thu Jan 13 12:10:55 1994
--- edit.x/kdb5_ed_ct.ct	Fri Jan 21 07:43:11 1994
***************
*** 54,59 ****
--- 54,62 ----
  request extract_srvtab, "Extract service key table",
  	extract_srvtab, xst, ex_st;
  
+ request new_extract_srvtab, "Extract service key table",
+         new_extract_srvtab, nxst, n_ex_st;
+ 
  request extract_v4_srvtab, "Extract service key table",
  	extract_v4_srvtab, xst4;
  
diff -r -c edit/kdb5_edit.c edit.x/kdb5_edit.c
*** edit/kdb5_edit.c	Thu Jan 13 12:11:41 1994
--- edit.x/kdb5_edit.c	Fri Jan 21 07:46:50 1994
***************
*** 673,678 ****
--- 673,815 ----
  }
  
  void
+ new_extract_srvtab(argc, argv)
+ int argc;
+ char *argv[];
+ {
+     char ktname[MAXPATHLEN+sizeof("WRFILE:")+1], *ktnameptr = 0;
+     krb5_keytab ktid;
+     krb5_error_code retval;
+     krb5_principal princ;
+     krb5_db_entry dbentry;
+     char *pname;
+     register int i;
+     int nentries;
+     krb5_boolean more;
+     krb5_keytab_entry newentry;
+     char *subsysname = argv[0];
+     static int srvtab_number = 0;
+ 
+     argv++, argc--;
+ 
+     while (argc && **argv == '-') {
+ 	 if (! strcmp(&argv[0][1], "file")) {
+ 	      argv++, argc--;
+ 	      if (! argc) {
+ 		   com_err(subsysname, 0, "Missing argument after '-file'");
+ 		   goto usage;
+ 	      }
+ 	      ktnameptr = argv[0];
+ 	      argv++, argc--;
+ 	 }
+ 	 else {
+ 	      goto usage;
+ 	 }
+     }
+ 
+     if (! argc) {
+ 	 goto usage;
+     }
+ 
+     if (!dbactive) {
+ 	    com_err(subsysname, 0, Err_no_database);
+ 	    return;
+     }
+     if (!valid_master_key) {
+ 	    com_err(subsysname, 0, Err_no_master_msg);
+ 	    return;
+     }
+ 
+     memset(ktname, 0, sizeof(ktname));
+     strcpy(ktname, "WRFILE:");
+     if (ktnameptr) {
+ 	 if (strlen(ktnameptr) + strlen(ktname) + 1 > sizeof(ktname)) {
+ 	      com_err(subsysname, 0, "File name '%s' is too long",
+ 		      ktnameptr);
+ 	      return;
+ 	 }
+ 	 strcat(ktname, ktnameptr);
+     }
+     else {
+ 	 (void) sprintf(&ktname[strlen(ktname)], "new-srvtab-%d",
+ 			srvtab_number++);
+     }
+ 
+     if (retval = krb5_kt_resolve(ktname, &ktid)) {
+ 	com_err(subsysname, retval, "while resolving keytab name '%s'",
+ 		ktname);
+ 	return;
+     }
+ 
+     for (; argc; argc--, argv++) {
+ 	/* iterate over the names */
+ 	pname = malloc(strlen(*argv) + strlen(cur_realm)+2);
+ 	if (!pname) {
+ 	    com_err(subsysname, ENOMEM,
+ 		    "while preparing to extract key for %s", *argv);
+ 	    continue;
+ 	}
+ 	strcpy(pname, *argv);
+ 	if (!strchr(*argv, REALM_SEP)) {
+ 	    strcat(pname, REALM_SEP_STR);
+ 	    strcat(pname, cur_realm);
+ 	}
+ 
+ 	if (retval = krb5_parse_name(pname, &princ)) {
+ 	    com_err(subsysname, retval, "while parsing '%s'", pname);
+ 	    free(pname);
+ 	    continue;
+ 	}
+ 	nentries = 1;
+ 	if (retval = krb5_db_get_principal(princ, &dbentry, &nentries,
+ 					   &more)) {
+ 	    com_err(subsysname, retval, "while retrieving '%s'", pname);
+ 	    goto cleanmost;
+ 	} else if (more) {
+ 	    com_err(subsysname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
+ 		    "while retrieving '%s'", pname);
+ 	    if (nentries)
+ 		krb5_db_free_principal(&dbentry, nentries);
+ 	    goto cleanmost;
+ 	} else if (!nentries) {
+ 	    com_err(subsysname, KRB5_KDB_NOENTRY, "while retrieving '%s'",
+ 		    pname);
+ 	    goto cleanmost;
+ 	}
+ 	if (retval = krb5_kdb_decrypt_key(&master_encblock,
+ 					  &dbentry.key,
+ 					  &newentry.key)) {
+ 	    com_err(subsysname, retval, "while decrypting key for '%s'",
+ 		    pname);
+ 	    goto cleanall;
+ 	}
+ 	newentry.principal = princ;
+ 	newentry.vno = dbentry.kvno;
+ 	if (retval = krb5_kt_add_entry(ktid, &newentry)) {
+ 	    com_err(subsysname, retval, "while adding key to keytab '%s'",
+ 		    ktname);
+ 	} else
+ 	    printf("'%s' added to keytab '%s'\n",
+ 		   pname, ktname);
+ 	memset((char *)newentry.key.contents, 0, newentry.key.length);
+ 	krb5_xfree(newentry.key.contents);
+     cleanall:
+ 	    krb5_db_free_principal(&dbentry, nentries);
+     cleanmost:
+ 	    free(pname);
+ 	    krb5_free_principal(princ);
+     }
+     if (retval = krb5_kt_close(ktid))
+ 	com_err(subsysname, retval, "while closing keytab");
+     return;
+ 
+ usage:
+     com_err(subsysname, 0, "Usage: %s [ -file srvtab-file ] principal ...",
+ 	    subsysname);
+     return;
+ }
+ 
+ void
  extract_v4_srvtab(argc, argv)
  int argc;
  char *argv[];



%%% These are the patches for krshd and krlogind.  Basically I
%%% do a gethostbyname on the data returned from getsockname and
%%% use that hostname in the krb5_sname_to_principal call.
%%% I don't like how I handled the buffer overflow error in the
%%% first branch of the "if (hp)" statement but I'm not sure what
%%% would be better.

diff -r -c bsd/krlogind.c bsd.x/krlogind.c
*** bsd/krlogind.c	Fri Jan 14 12:42:19 1994
--- bsd.x/krlogind.c	Tue Jan 25 23:25:44 1994
***************
*** 106,111 ****
--- 106,112 ----
   * #define KERBEROS
   */
  #define LOG_REMOTE_REALM
+ #define LOG_ALL_LOGINS
  #define CRYPT
  #ifdef KRB5_KRB4_COMPAT
  #define SERVE_V4
***************
*** 1393,1398 ****
--- 1394,1401 ----
      krb5_data inbuf;
      char v4_instance[INST_SZ];	/* V4 Instance */
      char v4_version[9];
+     char hostname[100];
+     struct hostent *hp;
  
      len = sizeof(laddr);
      if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
***************
*** 1399,1404 ****
--- 1402,1420 ----
  	    exit(1);
      }
  	
+     hp = gethostbyaddr((char *)&laddr.sin_addr, sizeof (struct in_addr),
+                      laddr.sin_family);
+     if (hp){
+         if ( 100 < strlen(hp->h_name) + 1) {
+           syslog(LOG_ERR,"gethostbyaddr returned name > 100 chars\n");
+           exit(244);
+         }
+         strcpy(hostname,hp->h_name);
+     } else {
+ 	/* assume inet dot form is no more than 100 chars */
+         strcpy(hostname,(char *)inet_ntoa(laddr.sin_addr));
+     }
+ 
      len = sizeof(peersin);
      if (getpeername(netf, (struct sockaddr *)&peersin, &len)) {
  	syslog(LOG_ERR, "get peer name failed %d", netf);
***************
*** 1415,1422 ****
--- 1431,1442 ----
      peeraddr.length = SIZEOF_INADDR;
      peeraddr.contents = (krb5_octet *)&peersin.sin_addr;
  	
+     if (status = krb5_sname_to_principal(hostname, "host", KRB5_NT_SRV_HST,
+ 					 &server)) {
+ /*DREW
      if (status = krb5_sname_to_principal(NULL, "host", KRB5_NT_SRV_HST,
  					 &server)) {
+ */
  	    syslog(LOG_ERR, "parse server name %s: %s", "host",
  		   error_message(status));
  	    exit(1);
diff -r -c bsd/krshd.c bsd.x/krshd.c
*** bsd/krshd.c	Fri Jan 14 12:42:26 1994
--- bsd.x/krshd.c	Tue Jan 25 23:26:20 1994
***************
*** 1383,1394 ****
      char v4_instance[INST_SZ];	/* V4 Instance */
      char v4_version[9];
      krb5_ticket        *ticket;
  
      len = sizeof(laddr);
      if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
  	    exit(1);
      }
! 	
  #ifdef unicos61
  #define SIZEOF_INADDR  SIZEOF_in_addr
  #else
--- 1383,1409 ----
      char v4_instance[INST_SZ];	/* V4 Instance */
      char v4_version[9];
      krb5_ticket        *ticket;
+     char hostname[100];
+     struct hostent *hp;
  
      len = sizeof(laddr);
      if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
  	    exit(1);
      }
! 
!     hp = gethostbyaddr((char *)&laddr.sin_addr, sizeof (struct in_addr),
!                      laddr.sin_family);
!     if (hp){
!         if ( 100 < strlen(hp->h_name) + 1) {
!           syslog(LOG_ERR,"gethostbyaddr returned name > 100 chars\n");
!          exit(244);
!         }
!         strcpy(hostname,hp->h_name);
!     } else {
!         /* assume inet dot form is no more than 100 chars */
!         strcpy(hostname,(char *)inet_ntoa(laddr.sin_addr));
!     }
! 
  #ifdef unicos61
  #define SIZEOF_INADDR  SIZEOF_in_addr
  #else
***************
*** 1395,1402 ****
--- 1410,1421 ----
  #define SIZEOF_INADDR sizeof(struct in_addr)
  #endif
  
+     if (status = krb5_sname_to_principal(hostname, "host", KRB5_NT_SRV_HST,
+ 					 &server)) {
+ /*DREW
      if (status = krb5_sname_to_principal(NULL, "host", KRB5_NT_SRV_HST,
  					 &server)) {
+ */
  	    syslog(LOG_ERR, "parse server name %s: %s", "host",
  		   error_message(status));
  	    exit(1);

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