[8056] in Kerberos

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

Re: Can't forward credentials with beta7

daemon@ATHENA.MIT.EDU (Sam Hartman)
Thu Sep 19 15:26:44 1996

To: mbeattie@sable.ox.ac.uk (Malcolm Beattie)
Cc: kerberos@MIT.EDU
From: Sam Hartman <hartmans@MIT.EDU>
Date: 19 Sep 1996 15:07:20 -0400
In-Reply-To: mbeattie@sable.ox.ac.uk's message of 19 Sep 1996 15:11:14 GMT


	The inability to forward credentials was introduced by a
last-minute (well, last-hour at least) patch to fix a political bug.
Basically, there was a potential security problem if /tmp didn't have
the sticky bit set and you run login.krb5.  This isn't really a
problem because many other products and other parts of Kerberos assume
that/tmp has the sticky bit set.  

	This is fairly substantially my fault as I had an opportunity
to audit the patch and missed the fairly obvious fact that it
completely broke forwarding tickets.  I don't think someone has worked
out a correct patch yet and they certainly haven't committed it to our
tree.  However, since the problem it fixes is not a problem on
correctly configured systems, you can just unapply the patch with
patch -R.

From bjaspan@MIT.EDU Wed Sep 11 15:49:00 1996
Received: from SOUTH-STATION-ANNEX.MIT.EDU by po10.MIT.EDU (5.61/4.7) id AA24620; Wed, 11 Sep 96 15:32:23 EDT
Received: from DUN-DUN-NOODLES.MIT.EDU by MIT.EDU with SMTP
	id AA26766; Wed, 11 Sep 96 15:32:17 EDT
Received: by DUN-DUN-NOODLES.MIT.EDU (5.x/4.7) id AA16374; Wed, 11 Sep 1996 15:32:14 -0400
Date: Wed, 11 Sep 1996 15:32:14 -0400
Message-Id: <9609111932.AA16374@DUN-DUN-NOODLES.MIT.EDU>
From: "Barry Jaspan" <bjaspan@MIT.EDU>
To: hartmans@MIT.EDU
Lines: 212
Xref: tertius.mit.edu mail.misc:5258

Index: login.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/bsd/login.c,v
retrieving revision 5.49
diff -c -r5.49 login.c
*** login.c	1996/06/24 04:05:09	5.49
--- login.c	1996/09/10 17:53:23
***************
*** 612,618 ****
  	/* get_name pulls out just the name not the
  	   type */
  	strcpy(ccfile, krb5_cc_get_name(kcontext, ccache));
- 	(void) chown(ccfile, pwd->pw_uid, pwd->pw_gid);
  	krbflag = got_v5_tickets = 1;
  	return 1;
      }
--- 612,617 ----
***************
*** 704,710 ****
      }
      got_v4_tickets = 1;
      strcpy(tkfile, tkt_string());
-     (void) chown(tkfile, pwd->pw_uid, pwd->pw_gid);
      return 1;
  }
  #endif
--- 703,708 ----
***************
*** 726,732 ****
  	kpass_ok = 1;
  	krbflag = 1;
  	strcpy(tkfile, tkt_string());
- 	(void) chown(tkfile, pwd->pw_uid, pwd->pw_gid);
  	break;	
  	/* These errors should be silent */
  	/* So the Kerberos database can't be probed */
--- 724,729 ----
***************
*** 877,884 ****
      krb5_ticket *ticket = NULL;
  
      /* XXX This is to work around a library bug.  I'm not sure if it's
!        been fixed for beta-6, so leave this in for now.  Remove it (and
!        fix the bug if necessary) after beta-6 ships.  */
      sleep(2);
  
      /* get the server principal for the local host */
--- 874,886 ----
      krb5_ticket *ticket = NULL;
  
      /* XXX This is to work around a library bug.  I'm not sure if it's
!        been fixed for beta-7, so leave this in for now.  Remove it (and
!        fix the bug if necessary) after beta-7 ships.
! 
!        Whoever wrote that comment didn't mention what the bug is!  Ted
!        says it is something about the starttime of the ticket and
!        "now" being equal.  He thinks it is fixed, but isn't sure.
!        */
      sleep(2);
  
      /* get the server principal for the local host */
***************
*** 1157,1163 ****
  	int retval;
  #ifdef KRB5_GET_TICKETS
  	krb5_principal me;
! #endif /* KRB5_GET_TICKETS */
  	char *ccname = 0;   /* name of forwarded cache */
  	char *tz = 0;
  
--- 1159,1169 ----
  	int retval;
  #ifdef KRB5_GET_TICKETS
  	krb5_principal me;
! 	krb5_creds save_v5creds;
! #endif
! #ifdef KRB4_GET_TICKETS
! 	CREDENTIALS save_v4creds;
! #endif
  	char *ccname = 0;   /* name of forwarded cache */
  	char *tz = 0;
  
***************
*** 1639,1644 ****
--- 1645,1714 ----
  	(void)setgid((gid_t) pwd->pw_gid);
  	(void) initgroups(username, pwd->pw_gid);
  
+ 	/*
+ 	 * The V5 ccache and V4 ticket file are both created as root.
+ 	 * They need to be owned by the user, and chown (a) assumes
+ 	 * they are stored in a file and (b) allows a race condition
+ 	 * in which a user can delete the file (if the directory
+ 	 * sticky bit is not set) and make it a symlink to somewhere
+ 	 * else; on some platforms, chown() on a symlink actually
+ 	 * changes the owner of the pointed-to file.  This is Bad.
+ 	 *
+ 	 * So, we suck the V5 and V4 krbtgts into memory here, destroy
+ 	 * the ccache/ticket file, and recreate them later after the
+ 	 * setuid.
+ 	 */
+ #ifdef KRB5_GET_TICKETS
+ 	if (got_v5_tickets) {
+ 	     krb5_creds mcreds;
+ 
+ 	     memset(&mcreds, 0, sizeof(mcreds));
+ 	     memset(&save_v5creds, 0, sizeof(save_v5creds));
+ 
+ 	     mcreds.client = me;
+ 	     retval = krb5_build_principal_ext(kcontext, &mcreds.server,
+ 				    krb5_princ_realm(kcontext, me)->length,
+ 				    krb5_princ_realm(kcontext, me)->data,
+ 				    tgtname.length, tgtname.data,
+ 				    krb5_princ_realm(kcontext, me)->length,
+ 				    krb5_princ_realm(kcontext, me)->data,
+ 				    0);
+ 	     if (retval) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while creating V5 krbtgt principal",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	     mcreds.ticket_flags = TKT_FLG_INITIAL;
+ 	     
+ 	     if (retval = krb5_cc_retrieve_cred(kcontext, ccache,
+ 					   KRB5_TC_MATCH_FLAGS,
+ 					   &mcreds, &save_v5creds)) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while retrieiving V5 initial ticket for copy",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	     krb5_free_principal(kcontext, mcreds.server);
+ 	}
+ #endif /* KRB5_GET_TICKETS */
+ #ifdef KRB4_GET_TICKETS
+ 	if (got_v4_tickets) {
+ 	     memset(&save_v4creds, 0, sizeof(save_v4creds));
+ 	     
+ 	     retval = krb_get_cred("krbtgt", realm, realm, &save_v4creds);
+ 	     if (retval != KSUCCESS) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while retrieving V4 initial ticket for copy",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	}
+ #endif /* KRB4_GET_TICKETS */
+ #if defined(KRB5_GET_TICKETS) || defined(KRB4_GET_TICKETS)
+ 	destroy_tickets();
+ #endif
+ 
  #ifdef OQUOTA
  	quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
  #endif
***************
*** 1665,1670 ****
--- 1735,1788 ----
  	     perror("setuid");
  	     sleepexit(1);
  	}
+ 
+ 	/*
+ 	 * We are the user now.  Re-create the destroyed ccache and
+ 	 * ticket file.
+ 	 */
+ #ifdef KRB5_GET_TICKETS
+ 	if (got_v5_tickets) {
+ 	     retval = krb5_cc_initialize (kcontext, ccache, me);
+ 	     if (retval) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while re-initializing V5 ccache as user",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	     if (retval = krb5_cc_store_cred(kcontext, ccache, &save_v5creds)) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while re-storing V5 credentials as user",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	     krb5_free_cred_contents(kcontext, &save_v5creds);
+ 	}
+ #endif /* KRB5_GET_TICKETS */
+ #ifdef KRB4_GET_TICKETS
+ 	if (got_v4_tickets) {
+ 	     retval = in_tkt(save_v4creds.pname, save_v4creds.pinst);
+ 	     if (retval != KSUCCESS) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while re-initializing V4 ticket cache as user",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	     retval = krb_save_credentials(save_v4creds.service,
+ 					   save_v4creds.instance,
+ 					   save_v4creds.realm, 
+ 					   save_v4creds.session,
+ 					   save_v4creds.lifetime,
+ 					   save_v4creds.kvno,
+ 					   &(save_v4creds.ticket_st), 
+ 					   save_v4creds.issue_date);
+ 	     if (retval != KSUCCESS) {
+ 		  syslog(LOG_ERR,
+ 			 "%s while re-storing V4 tickets as user",
+ 			 error_message(retval));
+ 		  sleepexit(1);
+ 	     }
+ 	}
+ #endif /* KRB4_GET_TICKETS */
  
  	if (*pwd->pw_shell == '\0')
  		pwd->pw_shell = BSHELL;



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