}
if (ctx->referral_count == 1) {
- /* Cache the referral TGT only if it's from the local realm.
- * Make sure to note the associated authdata, if any. */
- code = krb5_copy_authdata(context, ctx->authdata,
- &ctx->reply_creds->authdata);
- if (code != 0)
- return code;
- (void) krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
-
/* The authdata in this TGT will be copied into subsequent TGTs or the
* final credentials, so we don't need to request it again. */
krb5_free_authdata(context, ctx->in_creds->authdata);
/* See where we wound up on the path (or off it). */
path_realm = find_realm_in_path(context, ctx, tgt_realm);
if (path_realm != NULL) {
- /* We got a realm on the expected path, so we can cache it. */
- (void) krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
+ /* Only cache the TGT if we asked for it, to avoid duplicates. */
+ if (path_realm == ctx->next_realm)
+ (void)krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
if (path_realm == ctx->last_realm) {
/* We received a TGT for the target realm. */
TRACE_TKT_CREDS_TARGET_TGT(context, ctx->cur_tgt->server);
r.stop()
+# Verify that the princs appear as the service principals in the klist
+# output for the realm r, in order.
+def check_klist(r, princs):
+ out = r.run([klist])
+ count = 0
+ seen_header = False
+ for l in out.split('\n'):
+ if l.startswith('Valid starting'):
+ seen_header = True
+ continue
+ if not seen_header or l == '':
+ continue
+ if count >= len(princs):
+ fail('too many entries in klist output')
+ svcprinc = l.split()[4]
+ if svcprinc != princs[count]:
+ fail('saw service princ %s in klist output, expected %s' %
+ (svcprinc, princs[count]))
+ count += 1
+ if count != len(princs):
+ fail('not enough entries in klist output')
+
+
+def tgt(r1, r2):
+ return 'krbtgt/%s@%s' % (r1.realm, r2.realm)
+
+
# Basic two-realm test with cross TGTs in both directions.
r1, r2 = cross_realms(2)
test_kvno(r1, r2.host_princ, 'basic r1->r2')
+check_klist(r1, (tgt(r1, r1), tgt(r2, r1), r2.host_princ))
test_kvno(r2, r1.host_princ, 'basic r2->r1')
+check_klist(r2, (tgt(r2, r2), tgt(r1, r2), r1.host_princ))
stop(r1, r2)
# Test the KDC domain walk for hierarchically arranged realms. The
args=({'realm': 'A.X'}, {'realm': 'X'},
{'realm': 'B.X'}))
test_kvno(r1, r3.host_princ, 'KDC domain walk')
+check_klist(r1, (tgt(r1, r1), r3.host_princ))
stop(r1, r2, r3)
# Test client capaths. The client in A will ask for a cross TGT to D,
{'realm': 'D', 'krb5_conf': capaths}))
r1client = r1.special_env('client', False, krb5_conf=capaths)
test_kvno(r1, r4.host_princ, 'client capaths', r1client)
+check_klist(r1, (tgt(r1, r1), tgt(r2, r1), tgt(r3, r2), tgt(r4, r3),
+ r4.host_princ))
stop(r1, r2, r3, r4)
# Test KDC capaths. The KDCs for A and B have appropriate capaths
{'realm': 'C', 'krb5_conf': capaths},
{'realm': 'D', 'krb5_conf': capaths}))
test_kvno(r1, r4.host_princ, 'KDC capaths')
+check_klist(r1, (tgt(r1, r1), tgt(r4, r3), r4.host_princ))
stop(r1, r2, r3, r4)
# Test transited error. The KDC for C does not recognize B as an
{'realm': 'B'}, {'realm': 'C'}))
r1.run([kvno, r3.host_princ], expected_code=1,
expected_msg='KDC policy rejects request')
+check_klist(r1, (tgt(r1, r1), tgt(r3, r2)))
stop(r1, r2, r3)
# Test a different kind of transited error. The KDC for D does not
{'realm': 'D'}))
r1.run([kvno, r4.host_princ], expected_code=1,
expected_msg='Illegal cross-realm ticket')
+check_klist(r1, (tgt(r1, r1), tgt(r4, r3)))
stop(r1, r2, r3, r4)
success('Cross-realm tests')
# Get credentials and check that we got a referral to REFREALM.
def testref(realm, nametype):
shutil.copyfile(savefile, realm.ccache)
- realm.run(['./gcred', nametype, 'a/x.d'])
- realm.klist(realm.user_princ, 'a/x.d@REFREALM')
+ realm.run(['./gcred', nametype, 'a/x.d@'])
+ out = realm.run([klist]).split('\n')
+ if len(out) != 8:
+ fail('unexpected number of lines in klist output')
+ if out[5].split()[4] != 'a/x.d@' or out[6].split()[4] != 'a/x.d@REFREALM':
+ fail('unexpected service principals in klist output')
+ exit(0)
# Get credentials and check that we get an error, not a referral.
def testfail(realm, nametype):
shutil.copyfile(savefile, realm.ccache)
- realm.run(['./gcred', nametype, 'a/x.d'], expected_code=1,
+ realm.run(['./gcred', nametype, 'a/x.d@'], expected_code=1,
expected_msg='not found in Kerberos database')
# Create a modified KDC environment and restart the KDC.