krb5: Don't cache/reuse referral TGTs

Prior to this change _krb5_get_cred_kdc_any() would include TGTs obtained
via KDC referrals in the "*ret_tgts" array returned to the caller.  The
caller typically stores these TGTs in the active credential cache.

However, referrals TGTs must not be cached or reused for any request
beyond the one it was issued for.  The referral is for a specific service
principal and the resulting TGT could include service specific AuthData.
The referral might also direct the client along a transitive path that
is specific to this service and not applicable in the general case.

This change removes the *ret_tgts parameter from get_cred_kdc_referral()
so that the obtained TGTs are never returned to its caller.   This also
prevents these TGTs from being used by any subsequent call to
get_cred_kdc_capath().

Change-Id: Iacc76c5b1639af3cf6bf277966cfd1535dd1e84d
This commit is contained in:
Nicolas Williams
2015-03-11 15:32:05 -05:00
committed by Jeffrey Altman
parent d9e3e376a3
commit c37f1b3e4f

View File

@@ -919,6 +919,13 @@ get_cred_kdc_capath(krb5_context context,
return ret;
}
/*
* Get a service ticket from a KDC by chasing referrals from a start realm.
*
* All referral TGTs produced in the process are thrown away when we're done.
* We don't store them, and we don't allow other search mechanisms (capaths) to
* use referral TGTs produced here.
*/
static krb5_error_code
get_cred_kdc_referral(krb5_context context,
krb5_kdc_flags flags,
@@ -926,14 +933,15 @@ get_cred_kdc_referral(krb5_context context,
krb5_creds *in_creds,
krb5_principal impersonate_principal,
Ticket *second_ticket,
krb5_creds **out_creds,
krb5_creds ***ret_tgts)
krb5_creds **out_creds)
{
krb5_const_realm client_realm;
krb5_error_code ret;
krb5_creds tgt, referral, ticket;
krb5_creds **referral_tgts = NULL; /* used for loop detection */
int loop = 0;
int ok_as_delegate = 1;
size_t i;
if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
@@ -962,7 +970,7 @@ get_cred_kdc_referral(krb5_context context,
if(ret)
return ret;
ret = find_cred(context, ccache, tgtname, *ret_tgts, &tgt);
ret = find_cred(context, ccache, tgtname, NULL, &tgt);
krb5_free_principal(context, tgtname);
if (ret)
return ret;
@@ -1021,7 +1029,7 @@ get_cred_kdc_referral(krb5_context context,
referral_realm = ticket.server->name.name_string.val[1];
/* check that there are no referrals loops */
tickets = *ret_tgts;
tickets = referral_tgts;
krb5_cc_clear_mcred(&mcreds);
mcreds.server = ticket.server;
@@ -1053,7 +1061,7 @@ get_cred_kdc_referral(krb5_context context,
ticket.flags.b.ok_as_delegate = 0;
}
ret = add_cred(context, &ticket, ret_tgts);
ret = add_cred(context, &ticket, &referral_tgts);
if (ret)
goto out;
@@ -1071,6 +1079,9 @@ get_cred_kdc_referral(krb5_context context,
ret = krb5_copy_creds(context, &ticket, out_creds);
out:
for (i = 0; referral_tgts && referral_tgts[i]; i++)
krb5_free_creds(context, referral_tgts[i]);
free(referral_tgts);
krb5_free_principal(context, referral.server);
krb5_free_cred_contents(context, &tgt);
krb5_free_cred_contents(context, &ticket);
@@ -1102,16 +1113,19 @@ _krb5_get_cred_kdc_any(krb5_context context,
context->kdc_usec_offset = 0;
}
/* Try referrals */
ret = get_cred_kdc_referral(context,
flags,
ccache,
in_creds,
impersonate_principal,
second_ticket,
out_creds,
ret_tgts);
out_creds);
if (ret == 0 || flags.b.canonicalize)
return ret;
/* Try capaths */
return get_cred_kdc_capath(context,
flags,
ccache,