[8056] in Kerberos
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;