From aec6e0f51bfc20be67b70a7d81808b4add22838a Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sat, 13 Oct 2018 16:27:02 +0300 Subject: [PATCH] Add test for cross realm S4U2Self using referrals [ghudson@mit.edu: factored out tgtname() in kdb_test.c; added trace messages to tests and removed old redundant test] ticket: 8747 --- src/plugins/kdb/test/kdb_test.c | 37 ++++++++++++++++++++++++--- src/tests/gssapi/t_s4u.py | 44 ++++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c index 776dda388c..bc65bfb1bc 100644 --- a/src/plugins/kdb/test/kdb_test.c +++ b/src/plugins/kdb/test/kdb_test.c @@ -64,6 +64,9 @@ * Key values are generated using a hash of the kvno, enctype, salt type, and * principal name. This module does not use master key encryption, so it * serves as a partial test of the DAL's ability to avoid that. + * + * For cross realm, just add outbound 'krbtgt/OTHER_REALM' principal to each + * kdc configuration, while for inbound trust the local krbtgt will be used. */ #include "k5-int.h" @@ -297,12 +300,27 @@ test_close(krb5_context context) return 0; } +/* Return the principal name krbtgt/tgs_realm@our_realm. */ +static krb5_principal +tgtname(krb5_context context, const krb5_data *tgs_realm, + const krb5_data *our_realm) +{ + krb5_principal princ; + + check(krb5_build_principal_ext(context, &princ, + our_realm->length, our_realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + tgs_realm->length, tgs_realm->data, 0)); + princ->type = KRB5_NT_SRV_INST; + return princ; +} + static krb5_error_code test_get_principal(krb5_context context, krb5_const_principal search_for, unsigned int flags, krb5_db_entry **entry) { krb5_error_code ret; - krb5_principal princ = NULL; + krb5_principal princ = NULL, tgtprinc; krb5_principal_data empty_princ = { KV5M_PRINCIPAL }; testhandle h = context->dal_handle->db_context; char *search_name = NULL, *canon = NULL, *flagstr, **names, **key_strings; @@ -330,14 +348,25 @@ test_get_principal(krb5_context context, krb5_const_principal search_for, princ = NULL; ret = 0; goto cleanup; + } else if (flags & KRB5_KDB_FLAG_CANONICALIZE) { + /* Generate a server referral by looking up the TGT for the + * canonical name's realm. */ + tgtprinc = tgtname(context, &princ->realm, &search_for->realm); + krb5_free_principal(context, princ); + princ = tgtprinc; + + krb5_free_unparsed_name(context, search_name); + check(krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &search_name)); + ename = search_name; } else { - /* We could look up a cross-realm TGS entry, but we don't need - * that behavior yet. */ ret = KRB5_KDB_NOENTRY; goto cleanup; } + } else { + ename = canon; } - ename = canon; } else { check(krb5_copy_principal(context, search_for, &princ)); ename = search_name; diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py index 35bc9e436c..eb9545ddfb 100755 --- a/src/tests/gssapi/t_s4u.py +++ b/src/tests/gssapi/t_s4u.py @@ -139,21 +139,43 @@ if 'auth1: user@' not in out or 'auth2: user@' not in out: realm.stop() -# Exercise cross-realm S4U2Self. The query in the foreign realm will -# fail, but we can check that the right server principal was used. +# Test cross realm S4U2Self using server referrals. +mark('cross-realm S4U2Self') +testprincs = {'krbtgt/SREALM': {'keys': 'aes128-cts'}, + 'krbtgt/UREALM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts'}} +kdcconf1 = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs }}} +kdcconf2 = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'alias': {'user@SREALM': '@SREALM'}}}} +r1, r2 = cross_realms(2, xtgts=(), + args=({'realm': 'SREALM', 'kdc_conf': kdcconf1}, + {'realm': 'UREALM', 'kdc_conf': kdcconf2}), + create_kdb=False) + +r1.start_kdc() +r2.start_kdc() +r1.extract_keytab(r1.user_princ, r1.keytab) +r1.kinit(r1.user_princ, None, ['-k', '-t', r1.keytab]) + # Include a regression test for #8741 by unsetting the default realm. -r1, r2 = cross_realms(2, create_user=False) -r1.run([kinit, '-k', r1.host_princ]) remove_default = {'libdefaults': {'default_realm': None}} no_default = r1.special_env('no_default', False, krb5_conf=remove_default) -r1.run(['./t_s4u', 'p:' + r2.host_princ], env=no_default, expected_code=1, - expected_msg='Server not found in Kerberos database') +msgs = ('Getting credentials user@UREALM -> user@SREALM', + '/Matching credential not found', + 'Getting credentials user@SREALM -> krbtgt/UREALM@SREALM', + 'Received creds for desired service krbtgt/UREALM@SREALM', + 'via TGT krbtgt/UREALM@SREALM after requesting user\\@SREALM@UREALM', + 'krbtgt/SREALM@UREALM differs from requested user\\@SREALM@UREALM', + 'via TGT krbtgt/SREALM@UREALM after requesting user@SREALM', + 'TGS reply is for user@UREALM -> user@SREALM') +r1.run(['./t_s4u', 'p:' + r2.user_princ, '-', r1.keytab], env=no_default, + expected_trace=msgs) + r1.stop() r2.stop() -with open(os.path.join(r2.testdir, 'kdc.log')) as f: - kdclog = f.read() -exp_princ = r1.host_princ.replace('/', '\\/').replace('@', '\\@') -if ('for %s@%s, Server not found' % (exp_princ, r2.realm)) not in kdclog: - fail('cross-realm s4u2self (kdc log)') success('S4U test cases') -- 2.47.2