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:

committed by
Jeffrey Altman

parent
d9e3e376a3
commit
c37f1b3e4f
@@ -919,6 +919,13 @@ get_cred_kdc_capath(krb5_context context,
|
|||||||
return ret;
|
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
|
static krb5_error_code
|
||||||
get_cred_kdc_referral(krb5_context context,
|
get_cred_kdc_referral(krb5_context context,
|
||||||
krb5_kdc_flags flags,
|
krb5_kdc_flags flags,
|
||||||
@@ -926,14 +933,15 @@ get_cred_kdc_referral(krb5_context context,
|
|||||||
krb5_creds *in_creds,
|
krb5_creds *in_creds,
|
||||||
krb5_principal impersonate_principal,
|
krb5_principal impersonate_principal,
|
||||||
Ticket *second_ticket,
|
Ticket *second_ticket,
|
||||||
krb5_creds **out_creds,
|
krb5_creds **out_creds)
|
||||||
krb5_creds ***ret_tgts)
|
|
||||||
{
|
{
|
||||||
krb5_const_realm client_realm;
|
krb5_const_realm client_realm;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_creds tgt, referral, ticket;
|
krb5_creds tgt, referral, ticket;
|
||||||
|
krb5_creds **referral_tgts = NULL; /* used for loop detection */
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
int ok_as_delegate = 1;
|
int ok_as_delegate = 1;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
|
if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
|
||||||
krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
|
krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
|
||||||
@@ -962,7 +970,7 @@ get_cred_kdc_referral(krb5_context context,
|
|||||||
if(ret)
|
if(ret)
|
||||||
return 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);
|
krb5_free_principal(context, tgtname);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1021,7 +1029,7 @@ get_cred_kdc_referral(krb5_context context,
|
|||||||
referral_realm = ticket.server->name.name_string.val[1];
|
referral_realm = ticket.server->name.name_string.val[1];
|
||||||
|
|
||||||
/* check that there are no referrals loops */
|
/* check that there are no referrals loops */
|
||||||
tickets = *ret_tgts;
|
tickets = referral_tgts;
|
||||||
|
|
||||||
krb5_cc_clear_mcred(&mcreds);
|
krb5_cc_clear_mcred(&mcreds);
|
||||||
mcreds.server = ticket.server;
|
mcreds.server = ticket.server;
|
||||||
@@ -1053,7 +1061,7 @@ get_cred_kdc_referral(krb5_context context,
|
|||||||
ticket.flags.b.ok_as_delegate = 0;
|
ticket.flags.b.ok_as_delegate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = add_cred(context, &ticket, ret_tgts);
|
ret = add_cred(context, &ticket, &referral_tgts);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -1071,6 +1079,9 @@ get_cred_kdc_referral(krb5_context context,
|
|||||||
ret = krb5_copy_creds(context, &ticket, out_creds);
|
ret = krb5_copy_creds(context, &ticket, out_creds);
|
||||||
|
|
||||||
out:
|
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_principal(context, referral.server);
|
||||||
krb5_free_cred_contents(context, &tgt);
|
krb5_free_cred_contents(context, &tgt);
|
||||||
krb5_free_cred_contents(context, &ticket);
|
krb5_free_cred_contents(context, &ticket);
|
||||||
@@ -1102,16 +1113,19 @@ _krb5_get_cred_kdc_any(krb5_context context,
|
|||||||
context->kdc_usec_offset = 0;
|
context->kdc_usec_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try referrals */
|
||||||
ret = get_cred_kdc_referral(context,
|
ret = get_cred_kdc_referral(context,
|
||||||
flags,
|
flags,
|
||||||
ccache,
|
ccache,
|
||||||
in_creds,
|
in_creds,
|
||||||
impersonate_principal,
|
impersonate_principal,
|
||||||
second_ticket,
|
second_ticket,
|
||||||
out_creds,
|
out_creds);
|
||||||
ret_tgts);
|
|
||||||
if (ret == 0 || flags.b.canonicalize)
|
if (ret == 0 || flags.b.canonicalize)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Try capaths */
|
||||||
return get_cred_kdc_capath(context,
|
return get_cred_kdc_capath(context,
|
||||||
flags,
|
flags,
|
||||||
ccache,
|
ccache,
|
||||||
|
Reference in New Issue
Block a user