Skip Menu |
 

Subject: Cred cache can contain multiple similar tickets during x-realm auth
CC: Mark.Phalan@Sun.COM

In a cross-realm scenario the cred-cache can become populated with
multiple similar tickets. This happens when a KDC returns a "closer" tgt
which is different to the requested ticket.
The attached patch resolves this issue.
Download gc_frm_kdc-1.patch
text/x-patch 2.6KiB
Index: src/lib/krb5/krb/gc_frm_kdc.c
===================================================================
--- src/lib/krb5/krb/gc_frm_kdc.c (revision 19813)
+++ src/lib/krb5/krb/gc_frm_kdc.c (working copy)
@@ -434,7 +434,7 @@
krb5_principal *kdcptr;

TR_DBG(ts, "find_nxt_kdc");
- assert(ts->nxt_tgt == ts->kdc_tgts[ts->ntgts-1]);
+
if (krb5_princ_size(ts->ctx, ts->nxt_tgt->server) != 2)
return KRB5_KDCREP_MODIFIED;

@@ -454,7 +454,11 @@
* Don't touch NXT_KDC, thus allowing next_closest_tgt() to
* continue looping backwards.
*/
- if (ts->ntgts > 0) {
+ /*
+ * Only free the allocated creds if they are in kdc_tgts. If they
+ * are in cc_tgts no freeing is necessary.
+ */
+ if (ts->ntgts > 0 && ts->nxt_tgt == ts->kdc_tgts[ts->ntgts-1]) {
/* Punt NXT_TGT from KDC_TGTS if bogus. */
krb5_free_creds(ts->ctx, ts->kdc_tgts[--ts->ntgts]);
ts->kdc_tgts[ts->ntgts] = NULL;
@@ -478,6 +482,7 @@
{
krb5_error_code retval;
krb5_creds ltgtq;
+ krb5_creds *tmp_out_cred;

TR_DBG(ts, "try_kdc");
/* This check should probably be in gc_via_tkt. */
@@ -487,16 +492,38 @@
ltgtq = *tgtq;
ltgtq.is_skey = FALSE;
ltgtq.ticket_flags = ts->cur_tgt->ticket_flags;
+ /*
+ * Store credential in a temporary ticket as we may not
+ * want to add it to ts->kdc_tgts if it is already in
+ * the cache.
+ */
retval = krb5_get_cred_via_tkt(ts->ctx, ts->cur_tgt,
FLAGS2OPTS(ltgtq.ticket_flags),
ts->cur_tgt->addresses,
- &ltgtq, &ts->kdc_tgts[ts->ntgts++]);
+ &ltgtq, &tmp_out_cred);
if (retval) {
ts->ntgts--;
ts->nxt_tgt = ts->cur_tgt;
TR_DBG_RET(ts, "try_kdc", retval);
return retval;
}
+
+ /*
+ * See if the returned creds are different to the requested creds.
+ * This can happen when the server returns a TGT "closer" to the
+ * desired realm.
+ */
+ if (!(krb5_principal_compare(ts->ctx, tgtq->server, tmp_out_cred->server))) {
+ /* Not equal, ticket may already be in the cache */
+ retval = try_ccache(ts, tmp_out_cred);
+ if (!retval) {
+ krb5_free_creds(ts->ctx, tmp_out_cred);
+ retval = find_nxt_kdc(ts);
+ return retval;
+ }
+ }
+
+ ts->kdc_tgts[ts->ntgts++] = tmp_out_cred;
ts->nxt_tgt = ts->kdc_tgts[ts->ntgts-1];
retval = find_nxt_kdc(ts);
TR_DBG_RET(ts, "try_kdc", retval);