diff options
Diffstat (limited to 'src/tests/gssapi')
| -rw-r--r-- | src/tests/gssapi/Makefile.in | 27 | ||||
| -rw-r--r-- | src/tests/gssapi/deps | 7 | ||||
| -rw-r--r-- | src/tests/gssapi/t_authind.py | 20 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_ccselect.py | 67 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_client_keytab.py | 60 | ||||
| -rw-r--r-- | src/tests/gssapi/t_enctypes.c | 14 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_enctypes.py | 4 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_export_cred.py | 4 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_gssapi.py | 130 | ||||
| -rw-r--r-- | src/tests/gssapi/t_invalid.c | 57 | ||||
| -rw-r--r-- | src/tests/gssapi/t_lifetime.c | 140 | ||||
| -rw-r--r-- | src/tests/gssapi/t_s4u.c | 20 | ||||
| -rwxr-xr-x | src/tests/gssapi/t_s4u.py | 21 |
13 files changed, 408 insertions, 163 deletions
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in index 6c146429793d3..604f926dec457 100644 --- a/src/tests/gssapi/Makefile.in +++ b/src/tests/gssapi/Makefile.in @@ -15,15 +15,16 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ $(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \ - $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c $(srcdir)/t_pcontok.c \ - $(srcdir)/t_prf.c $(srcdir)/t_s4u.c $(srcdir)/t_s4u2proxy_krb5.c \ - $(srcdir)/t_saslname.c $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c + $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \ + $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \ + $(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \ + $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_ciflags.o \ t_credstore.o t_enctypes.o t_err.o t_export_cred.o t_export_name.o \ t_gssexts.o t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o \ - t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_namingexts.o t_oid.o \ - t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \ + t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o \ + t_oid.o t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \ t_spnego.o t_srcattrs.o COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) @@ -31,9 +32,9 @@ COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS) all: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore t_enctypes \ t_err t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name \ - t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_namingexts \ - t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego \ - t_srcattrs + t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \ + t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname \ + t_spnego t_srcattrs check-unix: t_oid $(RUN_TEST) ./t_invalid @@ -42,8 +43,8 @@ check-unix: t_oid check-pytests: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore \ t_enctypes t_err t_export_cred t_export_name t_imp_cred t_inq_cred \ - t_inq_ctx t_inq_mechs_name t_iov t_pcontok t_s4u t_s4u2proxy_krb5 \ - t_spnego t_srcattrs + t_inq_ctx t_inq_mechs_name t_iov t_lifetime t_pcontok t_s4u \ + t_s4u2proxy_krb5 t_spnego t_srcattrs $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) @@ -88,6 +89,8 @@ t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS) t_iov: t_iov.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_iov.o $(COMMON_LIBS) +t_lifetime: t_lifetime.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_lifetime.o $(COMMON_LIBS) t_namingexts: t_namingexts.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_namingexts.o $(COMMON_LIBS) t_pcontok: t_pcontok.o $(COMMON_DEPS) @@ -111,5 +114,5 @@ clean: $(RM) ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore $(RM) t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred $(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov - $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 - $(RM) t_saslname t_spnego t_srcattrs + $(RM) t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u + $(RM) t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps index be3cefbb456b9..b784deb638d06 100644 --- a/src/tests/gssapi/deps +++ b/src/tests/gssapi/deps @@ -45,7 +45,8 @@ $(OUTPRE)t_enctypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(COM_ERR_DEPS) $(srcdir)/../../lib/gssapi/generic/gssapi_ext.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ @@ -113,6 +114,10 @@ $(OUTPRE)t_iov.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ common.h t_iov.c +$(OUTPRE)t_lifetime.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_lifetime.c $(OUTPRE)t_namingexts.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ diff --git a/src/tests/gssapi/t_authind.py b/src/tests/gssapi/t_authind.py index 316bc40938015..84793beb623f7 100644 --- a/src/tests/gssapi/t_authind.py +++ b/src/tests/gssapi/t_authind.py @@ -24,9 +24,8 @@ if ('Attribute auth-indicators Authenticated Complete') not in out: if '73757065727374726f6e67' not in out: fail('Expected auth indicator not seen in name attributes') -out = realm.run(['./t_srcattrs', 'p:service/2'], expected_code=1) -if 'gss_init_sec_context: KDC policy rejects request' not in out: - fail('Expected error message not seen for indicator mismatch') +msg = 'gss_init_sec_context: KDC policy rejects request' +realm.run(['./t_srcattrs', 'p:service/2'], expected_code=1, expected_msg=msg) realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=one two']) out = realm.run(['./t_srcattrs', 'p:service/2']) @@ -35,4 +34,19 @@ if '6f6e65' not in out or '74776f' not in out: fail('Expected auth indicator not seen in name attributes') realm.stop() + +# Test the FAST encrypted challenge auth indicator. +kdcconf = {'realms': {'$realm': {'encrypted_challenge_indicator': 'fast'}}} +realm = K5Realm(kdc_conf=kdcconf) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +realm.run([kadminl, 'xst', realm.host_princ]) +realm.kinit(realm.user_princ, password('user')) +realm.kinit(realm.user_princ, password('user'), ['-T', realm.ccache]) +out = realm.run(['./t_srcattrs', 'p:' + realm.host_princ]) +if ('Attribute auth-indicators Authenticated Complete') not in out: + fail('Expected attribute type not seen') +if '66617374' not in out: + fail('Expected auth indicator not seen in name attributes') + +realm.stop() success('GSSAPI auth indicator tests') diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py index 6be6b4ec06c16..3503f92699b11 100755 --- a/src/tests/gssapi/t_ccselect.py +++ b/src/tests/gssapi/t_ccselect.py @@ -31,12 +31,20 @@ r2 = K5Realm(create_user=False, realm='KRBTEST2.COM', portbase=62000, host1 = 'p:' + r1.host_princ host2 = 'p:' + r2.host_princ +foo = 'foo.krbtest.com' +foo2 = 'foo.krbtest2.com' +foobar = "foo.bar.krbtest.com" -# gsserver specifies the target as a GSS name. The resulting -# principal will have the host-based type, but the realm won't be -# known before the client cache is selected (since k5test realms have -# no domain-realm mapping by default). -gssserver = 'h:host@' + hostname +# These strings specify the target as a GSS name. The resulting +# principal will have the host-based type, with the referral realm +# (since k5test realms have no domain-realm mapping by default). +# krb5_cc_select() will use the fallback realm, which is either the +# uppercased parent domain, or the default realm if the hostname is a +# single component. +gssserver = 'h:host@' + foo +gssserver2 = 'h:host@' + foo2 +gssserver_bar = 'h:host@' + foobar +gsslocal = 'h:host@localhost' # refserver specifies the target as a principal in the referral realm. # The principal won't be treated as a host principal by the @@ -45,9 +53,8 @@ refserver = 'p:host/' + hostname + '@' # Verify that we can't get initiator creds with no credentials in the # collection. -output = r1.run(['./t_ccselect', host1, '-'], expected_code=1) -if 'No Kerberos credentials available' not in output: - fail('Expected error not seen in output when no credentials available') +r1.run(['./t_ccselect', host1, '-'], expected_code=1, + expected_msg='No Kerberos credentials available') # Make a directory collection and use it for client commands in both realms. ccdir = os.path.join(r1.testdir, 'cc') @@ -67,6 +74,18 @@ r1.addprinc(alice, password('alice')) r1.addprinc(bob, password('bob')) r2.addprinc(zaphod, password('zaphod')) +# Create host principals and keytabs for fallback realm tests. +r1.addprinc('host/localhost') +r2.addprinc('host/localhost') +r1.addprinc('host/' + foo) +r2.addprinc('host/' + foo2) +r1.addprinc('host/' + foobar) +r1.extract_keytab('host/localhost', r1.keytab) +r2.extract_keytab('host/localhost', r2.keytab) +r1.extract_keytab('host/' + foo, r1.keytab) +r2.extract_keytab('host/' + foo2, r2.keytab) +r1.extract_keytab('host/' + foobar, r1.keytab) + # Get tickets for one user in each realm (zaphod will be primary). r1.kinit(alice, password('alice')) r2.kinit(zaphod, password('zaphod')) @@ -94,10 +113,29 @@ if output != (zaphod + '\n'): fail('zaphod not chosen as default initiator name for server in r1') # Check that primary cache is used if server realm is unknown. -output = r2.run(['./t_ccselect', gssserver]) +output = r2.run(['./t_ccselect', refserver]) if output != (zaphod + '\n'): fail('zaphod not chosen via primary cache for unknown server realm') -r1.run(['./t_ccselect', gssserver], expected_code=1) +r1.run(['./t_ccselect', gssserver2], expected_code=1) +# Check ccache selection using a fallback realm. +output = r1.run(['./t_ccselect', gssserver]) +if output != (alice + '\n'): + fail('alice not chosen via parent domain fallback') +output = r2.run(['./t_ccselect', gssserver2]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via parent domain fallback') +# Check ccache selection using a fallback realm (default realm). +output = r1.run(['./t_ccselect', gsslocal]) +if output != (alice + '\n'): + fail('alice not chosen via default realm fallback') +output = r2.run(['./t_ccselect', gsslocal]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via default realm fallback') + +# Check that realm ccselect fallback works correctly +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) +r2.kinit(zaphod, password('zaphod')) +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) # Get a second cred in r1 (bob will be primary). r1.kinit(bob, password('bob')) @@ -105,20 +143,19 @@ r1.kinit(bob, password('bob')) # Try some cache selections using .k5identity. k5id = open(os.path.join(r1.testdir, '.k5identity'), 'w') k5id.write('%s realm=%s\n' % (alice, r1.realm)) -k5id.write('%s service=ho*t host=%s\n' % (zaphod, hostname)) +k5id.write('%s service=ho*t host=localhost\n' % zaphod) k5id.write('noprinc service=bogus') k5id.close() output = r1.run(['./t_ccselect', host1]) if output != (alice + '\n'): fail('alice not chosen via .k5identity realm line.') -output = r2.run(['./t_ccselect', gssserver]) +output = r2.run(['./t_ccselect', gsslocal]) if output != (zaphod + '\n'): fail('zaphod not chosen via .k5identity service/host line.') output = r1.run(['./t_ccselect', refserver]) if output != (bob + '\n'): fail('bob not chosen via primary cache when no .k5identity line matches.') -output = r1.run(['./t_ccselect', 'h:bogus@' + hostname], expected_code=1) -if 'Can\'t find client principal noprinc' not in output: - fail('Expected error not seen when k5identity selects bad principal.') +r1.run(['./t_ccselect', 'h:bogus@' + foo2], expected_code=1, + expected_msg="Can't find client principal noprinc") success('GSSAPI credential selection tests') diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py index 4c8747a506c16..2da87f45b5b2f 100755 --- a/src/tests/gssapi/t_client_keytab.py +++ b/src/tests/gssapi/t_client_keytab.py @@ -15,9 +15,7 @@ realm.extract_keytab(realm.user_princ, realm.client_keytab) realm.extract_keytab(bob, realm.client_keytab) # Test 1: no name/cache specified, pick first principal from client keytab -out = realm.run(['./t_ccselect', phost]) -if realm.user_princ not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost], expected_msg=realm.user_princ) realm.run([kdestroy]) # Test 2: no name/cache specified, pick principal from k5identity @@ -25,36 +23,27 @@ k5idname = os.path.join(realm.testdir, '.k5identity') k5id = open(k5idname, 'w') k5id.write('%s service=host host=%s\n' % (bob, hostname)) k5id.close() -out = realm.run(['./t_ccselect', gssserver]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', gssserver], expected_msg=bob) os.remove(k5idname) realm.run([kdestroy]) # Test 3: no name/cache specified, default ccache has name but no creds realm.run(['./ccinit', realm.ccache, bob]) -out = realm.run(['./t_ccselect', phost]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost], expected_msg=bob) # Leave tickets for next test. # Test 4: name specified, non-collectable default cache doesn't match -out = realm.run(['./t_ccselect', phost, puser], expected_code=1) -if 'Principal in credential cache does not match desired name' not in out: - fail('Expected error not seen') +msg = 'Principal in credential cache does not match desired name' +realm.run(['./t_ccselect', phost, puser], expected_code=1, expected_msg=msg) realm.run([kdestroy]) # Test 5: name specified, nonexistent default cache -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Leave tickets for next test. # Test 6: name specified, matches default cache, time to refresh realm.run(['./ccrefresh', realm.ccache, '1']) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) out = realm.run(['./ccrefresh', realm.ccache]) if int(out) < 1000: fail('Credentials apparently not refreshed') @@ -67,9 +56,8 @@ realm.run([kdestroy]) # Test 8: ccache specified with name but no creds; name not in client keytab realm.run(['./ccinit', realm.ccache, realm.host_princ]) -out = realm.run(['./t_imp_cred', phost], expected_code=1) -if 'Credential cache is empty' not in out: - fail('Expected error not seen') +realm.run(['./t_imp_cred', phost], expected_code=1, + expected_msg='Credential cache is empty') realm.run([kdestroy]) # Test 9: ccache specified with name but no creds; name in client keytab @@ -104,16 +92,12 @@ realm.env['KRB5CCNAME'] = ccname # Test 12: name specified, matching cache in collection with no creds bobcache = os.path.join(ccdir, 'tktbob') realm.run(['./ccinit', bobcache, bob]) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Leave tickets for next test. # Test 13: name specified, matching cache in collection, time to refresh realm.run(['./ccrefresh', bobcache, '1']) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) out = realm.run(['./ccrefresh', bobcache]) if int(out) < 1000: fail('Credentials apparently not refreshed') @@ -121,22 +105,15 @@ realm.run([kdestroy, '-A']) # Test 14: name specified, collection has default for different principal realm.kinit(realm.user_princ, password('user')) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') -out = realm.run([klist]) -if 'Default principal: %s\n' % realm.user_princ not in out: - fail('Default cache overwritten by acquire_cred') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +msg = 'Default principal: %s\n' % realm.user_princ +realm.run([klist], expected_msg=msg) realm.run([kdestroy, '-A']) # Test 15: name specified, collection has no default cache -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Make sure the tickets we acquired didn't become the default -out = realm.run([klist], expected_code=1) -if 'No credentials cache found' not in out: - fail('Expected error not seen') +realm.run([klist], expected_code=1, expected_msg='No credentials cache found') realm.run([kdestroy, '-A']) # Test 16: default client keytab cannot be resolved, but valid @@ -145,8 +122,7 @@ conf = {'libdefaults': {'default_client_keytab_name': '%{'}} bad_cktname = realm.special_env('bad_cktname', False, krb5_conf=conf) del bad_cktname['KRB5_CLIENT_KTNAME'] realm.kinit(realm.user_princ, password('user')) -out = realm.run(['./t_ccselect', phost], env=bad_cktname) -if realm.user_princ not in out: - fail('Expected principal not seen for bad client keytab name') +realm.run(['./t_ccselect', phost], env=bad_cktname, + expected_msg=realm.user_princ) success('Client keytab tests') diff --git a/src/tests/gssapi/t_enctypes.c b/src/tests/gssapi/t_enctypes.c index a2ad18f47aba5..3fd31e2f8cd50 100644 --- a/src/tests/gssapi/t_enctypes.c +++ b/src/tests/gssapi/t_enctypes.c @@ -32,6 +32,7 @@ #include "k5-int.h" #include "common.h" +#include "gssapi_ext.h" /* * This test program establishes contexts with the krb5 mech, the default @@ -86,6 +87,9 @@ main(int argc, char *argv[]) gss_krb5_lucid_context_v1_t *ilucid, *alucid; gss_krb5_rfc1964_keydata_t *i1964, *a1964; gss_krb5_cfx_keydata_t *icfx, *acfx; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; + gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF; + unsigned int ssf; size_t count; void *lptr; int c; @@ -139,6 +143,16 @@ main(int argc, char *argv[]) establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx, NULL, NULL, NULL); + /* Query the SSF value and range-check the result. */ + major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset); + check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor); + if (bufset->elements[0].length != 4) + errout("SSF buffer has unexpected length"); + ssf = load_32_be(bufset->elements[0].value); + if (ssf < 56 || ssf > 256) + errout("SSF value not within acceptable range (56-256)"); + (void)gss_release_buffer_set(&minor, &bufset); + /* Export to lucid contexts. */ major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr); check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor); diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py index 862f229895b2e..f513db2b55cf7 100755 --- a/src/tests/gssapi/t_enctypes.py +++ b/src/tests/gssapi/t_enctypes.py @@ -58,9 +58,7 @@ def test(msg, ienc, aenc, tktenc='', tktsession='', proto='', isubkey='', # and check that it fails with the expected error message. def test_err(msg, ienc, aenc, expected_err): shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache) - out = realm.run(cmdline(ienc, aenc), expected_code=1) - if expected_err not in out: - fail(msg) + realm.run(cmdline(ienc, aenc), expected_code=1, expected_msg=expected_err) # By default, all of the key enctypes should be aes256. diff --git a/src/tests/gssapi/t_export_cred.py b/src/tests/gssapi/t_export_cred.py index 6988359289010..b98962788b586 100755 --- a/src/tests/gssapi/t_export_cred.py +++ b/src/tests/gssapi/t_export_cred.py @@ -23,9 +23,7 @@ def ccache_restore(realm): def check(realm, args): ccache_restore(realm) realm.run(['./t_export_cred'] + args) - output = realm.run([klist, '-f']) - if 'Flags: Ff' not in output: - fail('Forwarded tickets not found in ccache after t_export_cred') + realm.run([klist, '-f'], expected_msg='Flags: Ff') # Check a given set of arguments with no specified mech and with krb5 # and SPNEGO as the specified mech. diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py index e23c936d7f44e..6da5fceff3be8 100755 --- a/src/tests/gssapi/t_gssapi.py +++ b/src/tests/gssapi/t_gssapi.py @@ -28,57 +28,40 @@ realm.run([kadminl, 'renprinc', 'service1/abraham', 'service1/andrew']) # Test with no acceptor name, including client/keytab principal # mismatch (non-fatal) and missing keytab entry (fatal). -output = realm.run(['./t_accname', 'p:service1/andrew']) -if 'service1/abraham' not in output: - fail('Expected service1/abraham in t_accname output') -output = realm.run(['./t_accname', 'p:service1/barack']) -if 'service1/barack' not in output: - fail('Expected service1/barack in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin']) -if 'service2/calvin' not in output: - fail('Expected service1/barack in t_accname output') -output = realm.run(['./t_accname', 'p:service2/dwight'], expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:service1/andrew'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/barack'], expected_msg='service1/barack') +realm.run(['./t_accname', 'p:service2/calvin'], expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') # Test with acceptor name containing service only, including # client/keytab hostname mismatch (non-fatal) and service name # mismatch (fatal). -output = realm.run(['./t_accname', 'p:service1/andrew', 'h:service1']) -if 'service1/abraham' not in output: - fail('Expected service1/abraham in t_accname output') -output = realm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], - expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin', 'h:service2']) -if 'service2/calvin' not in output: - fail('Expected service2/calvin in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], - expected_code=1) -if ' found in keytab but does not match server principal' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:service1/andrew', 'h:service1'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], expected_code=1, + expected_msg=' not found in keytab') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service2'], + expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1, + expected_msg=' found in keytab but does not match server principal') # Test with acceptor name containing service and host. Use the # client's un-canonicalized hostname as acceptor input to mirror what # many servers do. -output = realm.run(['./t_accname', 'p:' + realm.host_princ, - 'h:host@%s' % socket.gethostname()]) -if realm.host_princ not in output: - fail('Expected %s in t_accname output' % realm.host_princ) -output = realm.run(['./t_accname', 'p:host/-nomatch-', - 'h:host@%s' % socket.gethostname()], - expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:' + realm.host_princ, + 'h:host@%s' % socket.gethostname()], expected_msg=realm.host_princ) +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_code=1, + expected_msg=' not found in keytab') # Test krb5_gss_import_cred. realm.run(['./t_imp_cred', 'p:service1/barack']) realm.run(['./t_imp_cred', 'p:service1/barack', 'service1/barack']) realm.run(['./t_imp_cred', 'p:service1/andrew', 'service1/abraham']) -output = realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_imp_cred output') +realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') # Test credential store extension. tmpccname = 'FILE:' + os.path.join(realm.testdir, 'def_cache') @@ -116,10 +99,8 @@ ignore_conf = {'libdefaults': {'ignore_acceptor_hostname': 'true'}} realm = K5Realm(krb5_conf=ignore_conf) realm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-']) realm.run([kadminl, 'xst', 'host/-nomatch-']) -output = realm.run(['./t_accname', 'p:host/-nomatch-', - 'h:host@%s' % socket.gethostname()]) -if 'host/-nomatch-' not in output: - fail('Expected host/-nomatch- in t_accname output') +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_msg='host/-nomatch-') realm.stop() @@ -141,41 +122,25 @@ r3.stop() realm = K5Realm() # Test deferred resolution of the default ccache for initiator creds. -output = realm.run(['./t_inq_cred']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) -output = realm.run(['./t_inq_cred', '-k']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) -output = realm.run(['./t_inq_cred', '-s']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) +realm.run(['./t_inq_cred'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-s'], expected_msg=realm.user_princ) # Test picking a name from the keytab for acceptor creds. -output = realm.run(['./t_inq_cred', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) -output = realm.run(['./t_inq_cred', '-k', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) -output = realm.run(['./t_inq_cred', '-s', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) +realm.run(['./t_inq_cred', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-k', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-s', '-a'], expected_msg=realm.host_princ) # Test client keytab initiation (non-deferred) with a specified name. realm.extract_keytab(realm.user_princ, realm.client_keytab) os.remove(realm.ccache) -output = realm.run(['./t_inq_cred', '-k']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) # Test deferred client keytab initiation and GSS_C_BOTH cred usage. os.remove(realm.client_keytab) os.remove(realm.ccache) shutil.copyfile(realm.keytab, realm.client_keytab) -output = realm.run(['./t_inq_cred', '-k', '-b']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) +realm.run(['./t_inq_cred', '-k', '-b'], expected_msg=realm.host_princ) # Test gss_export_name behavior. out = realm.run(['./t_export_name', 'u:x']) @@ -220,4 +185,37 @@ realm.run(['./t_ciflags', 'p:' + realm.host_princ]) # contexts. realm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ]) +if runenv.sizeof_time_t <= 4: + skip_rest('y2038 GSSAPI tests', 'platform has 32-bit time_t') + +# Test lifetime results, using a realm with a large maximum lifetime +# so that we can test ticket end dates after y2038. +realm.stop() +conf = {'realms': {'$realm': {'max_life': '9000d'}}} +realm = K5Realm(kdc_conf=conf, get_creds=False) + +# Check a lifetime string result against an expected number value (or None). +# Allow some variance due to time elapsed during the tests. +def check_lifetime(msg, val, expected): + if expected is None and val != 'indefinite': + fail('%s: expected indefinite, got %s' % (msg, val)) + if expected is not None and val == 'indefinite': + fail('%s: expected %d, got indefinite' % (msg, expected)) + if expected is not None and abs(int(val) - expected) > 100: + fail('%s: expected %d, got %s' % (msg, expected, val)) + +realm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d']) +out = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)]) +ln = out.split('\n') +check_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400) +check_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400) +check_lifetime('acred gss_acquire_cred', ln[2], None) +check_lifetime('acred gss_inquire_cred', ln[3], None) +check_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400) +check_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400) +check_lifetime('ictx gss_context_time', ln[6], 8000 * 86400) +check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300) +check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300) +check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300) + success('GSSAPI tests') diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c index 5c8ddac8dc846..2a332a8ae0485 100644 --- a/src/tests/gssapi/t_invalid.c +++ b/src/tests/gssapi/t_invalid.c @@ -31,8 +31,8 @@ */ /* - * This file contains regression tests for some GSSAPI krb5 invalid per-message - * token vulnerabilities. + * This file contains regression tests for some GSSAPI invalid token + * vulnerabilities. * * 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a * null pointer dereference. (The token must use SEAL_ALG_NONE or it will @@ -54,10 +54,13 @@ * causes an integer underflow when computing the original message length, * leading to an allocation error. * + * 5. In the mechglue, truncated encapsulation in the initial context token can + * cause input buffer overruns in gss_accept_sec_context(). + * * Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with - * fewer than 16 bytes after the ASN.1 header will be rejected. Vulnerability - * #2 can only be robustly detected using a memory-checking environment such as - * valgrind. + * fewer than 16 bytes after the ASN.1 header will be rejected. + * Vulnerabilities #2 and #5 can only be robustly detected using a + * memory-checking environment such as valgrind. */ #include "k5-int.h" @@ -406,6 +409,48 @@ test_bad_pad(gss_ctx_id_t ctx, const struct test *test) (void)gss_release_buffer(&minor, &out); } +static void +try_accept(void *value, size_t len) +{ + OM_uint32 minor; + gss_buffer_desc in, out; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + + /* Copy the provided value to make input overruns more obvious. */ + in.value = malloc(len); + if (in.value == NULL) + abort(); + memcpy(in.value, value, len); + in.length = len; + (void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &out, NULL, NULL, NULL); + gss_release_buffer(&minor, &out); + gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER); + free(in.value); +} + +/* Accept contexts using superficially valid but truncated encapsulations. */ +static void +test_short_encapsulation() +{ + /* Include just the initial application tag, to see if we overrun reading + * the sequence length. */ + try_accept("\x60", 1); + + /* Indicate four additional sequence length bytes, to see if we overrun + * reading them (or skipping them and reading the next byte). */ + try_accept("\x60\x84", 2); + + /* Include an object identifier tag but no length, to see if we overrun + * reading the length. */ + try_accept("\x60\x40\x06", 3); + + /* Include an object identifier tag with a length matching the krb5 mech, + * but no OID bytes, to see if we overrun comparing against mechs. */ + try_accept("\x60\x40\x06\x09", 4); +} + int main(int argc, char **argv) { @@ -425,5 +470,7 @@ main(int argc, char **argv) free_fake_context(ctx); } + test_short_encapsulation(); + return 0; } diff --git a/src/tests/gssapi/t_lifetime.c b/src/tests/gssapi/t_lifetime.c new file mode 100644 index 0000000000000..8dcf18621bbf8 --- /dev/null +++ b/src/tests/gssapi/t_lifetime.c @@ -0,0 +1,140 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_lifetime.c - display cred and context lifetimes */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "common.h" + +/* + * Using the default credential, exercise the GSS functions which accept or + * produce lifetimes. Display the following results, one per line, as ASCII + * integers or the string "indefinite": + * + * initiator cred lifetime according to gss_acquire_cred() + * initiator cred lifetime according to gss_inquire_cred() + * acceptor cred lifetime according to gss_acquire_cred() + * acceptor cred lifetime according to gss_inquire_cred() + * initiator context lifetime according to gss_init_sec_context() + * initiator context lifetime according to gss_inquire_context() + * initiator context lifetime according to gss_context_time() + * acceptor context lifetime according to gss_init_sec_context() + * acceptor context lifetime according to gss_inquire_context() + * acceptor context lifetime according to gss_context_time() + */ + +static void +display_time(OM_uint32 tval) +{ + if (tval == GSS_C_INDEFINITE) + puts("indefinite"); + else + printf("%u\n", (unsigned int)tval); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t icred, acred; + gss_name_t tname; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER; + OM_uint32 time_req = GSS_C_INDEFINITE, time_rec; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [time_req]\n", argv[0]); + return 1; + } + tname = import_name(argv[1]); + if (argc >= 3) + time_req = atoll(argv[2]); + + /* Get initiator cred and display its lifetime according to + * gss_acquire_cred and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_INITIATE, &icred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(initiate)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, icred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(initiate)", major, minor); + display_time(time_rec); + + /* Get acceptor cred and display its lifetime according to gss_acquire_cred + * and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_ACCEPT, &acred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(accept)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, acred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(accept)", major, minor); + display_time(time_rec); + + /* Make an initiator context and display its lifetime according to + * gss_init_sec_context, gss_inquire_context, and gss_context_time. */ + major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5, 0, + time_req, GSS_C_NO_CHANNEL_BINDINGS, &atok, + NULL, &itok, NULL, &time_rec); + check_gsserr("gss_init_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, ictx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(initiate)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, ictx, &time_rec); + check_gsserr("gss_context_time(initiate)", major, minor); + display_time(time_rec); + + major = gss_accept_sec_context(&minor, &actx, acred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, &time_rec, NULL); + check_gsserr("gss_accept_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, actx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(accept)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, actx, &time_rec); + check_gsserr("gss_context_time(accept)", major, minor); + display_time(time_rec); + + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_release_name(&minor, &tname); + (void)gss_release_cred(&minor, &icred); + (void)gss_release_cred(&minor, &acred); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/src/tests/gssapi/t_s4u.c b/src/tests/gssapi/t_s4u.c index 5bc1e4470bdcf..0400f8f61f414 100644 --- a/src/tests/gssapi/t_s4u.c +++ b/src/tests/gssapi/t_s4u.c @@ -242,6 +242,7 @@ main(int argc, char *argv[]) gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; gss_name_t user = GSS_C_NO_NAME, target = GSS_C_NO_NAME; gss_OID_set mechs; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; if (argc < 2 || argc > 5) { fprintf(stderr, "Usage: %s [--spnego] [user] " @@ -305,6 +306,25 @@ main(int argc, char *argv[]) fprintf(stderr, "\n"); } + if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + /* Inquire impersonator status. */ + major = gss_inquire_cred_by_oid(&minor, user_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count == 0) + errout("gss_inquire_cred_by_oid(user) returned NO impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + + major = gss_inquire_cred_by_oid(&minor, impersonator_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count != 0) + errout("gss_inquire_cred_by_oid(svc) returned an impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + } + (void)gss_release_name(&minor, &user); (void)gss_release_name(&minor, &target); (void)gss_release_cred(&minor, &delegated_cred_handle); diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py index 7366e3915ee35..e4cd684693000 100755 --- a/src/tests/gssapi/t_s4u.py +++ b/src/tests/gssapi/t_s4u.py @@ -42,10 +42,8 @@ if ('auth1: ' + realm.user_princ not in output or # result in no delegated credential being created by # accept_sec_context. realm.kinit(realm.user_princ, password('user'), ['-c', usercache]) -output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1, - pservice1, pservice2]) -if 'no credential delegated' not in output: - fail('krb5 -> no delegated cred') +realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1, + pservice1, pservice2], expected_msg='no credential delegated') # Try S4U2Self. Ask for an S4U2Proxy step; this won't happen because # service/1 isn't allowed to get a forwardable S4U2Self ticket. @@ -61,17 +59,15 @@ if ('Warning: no delegated cred handle' not in output or # Correct that problem and try again. As above, the S4U2Proxy step # won't actually succeed since we don't support that in DB2. realm.run([kadminl, 'modprinc', '+ok_to_auth_as_delegate', service1]) -output = realm.run(['./t_s4u', puser, pservice2], expected_code=1) -if 'NOT_ALLOWED_TO_DELEGATE' not in output: - fail('s4u2self') +realm.run(['./t_s4u', puser, pservice2], expected_code=1, + expected_msg='NOT_ALLOWED_TO_DELEGATE') # Again with SPNEGO. This uses SPNEGO for the initial authentication, # but still uses krb5 for S4U2Proxy--the delegated cred is returned as # a krb5 cred, not a SPNEGO cred, and t_s4u uses the delegated cred # directly rather than saving and reacquiring it. -output = realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1) -if 'NOT_ALLOWED_TO_DELEGATE' not in output: - fail('s4u2self') +realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1, + expected_msg='NOT_ALLOWED_TO_DELEGATE') realm.stop() @@ -148,9 +144,8 @@ realm.stop() # fail, but we can check that the right server principal was used. r1, r2 = cross_realms(2, create_user=False) r1.run([kinit, '-k', r1.host_princ]) -out = r1.run(['./t_s4u', 'p:' + r2.host_princ], expected_code=1) -if 'Server not found in Kerberos database' not in out: - fail('cross-realm s4u2self (t_s4u output)') +r1.run(['./t_s4u', 'p:' + r2.host_princ], expected_code=1, + expected_msg='Server not found in Kerberos database') r1.stop() r2.stop() with open(os.path.join(r2.testdir, 'kdc.log')) as f: |
