Skip to content

Commit

Permalink
krb5: Don't cache/reuse referral TGTs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nicowilliams authored and jaltman committed Mar 14, 2015
1 parent d9e3e37 commit c37f1b3
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions lib/krb5/get_cred.c
Expand Up @@ -919,21 +919,29 @@ 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,
krb5_ccache ccache,
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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit c37f1b3

Please sign in to comment.