summaryrefslogtreecommitdiff
path: root/src/tests/gssapi
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/gssapi')
-rw-r--r--src/tests/gssapi/Makefile.in27
-rw-r--r--src/tests/gssapi/deps7
-rw-r--r--src/tests/gssapi/t_authind.py20
-rwxr-xr-xsrc/tests/gssapi/t_ccselect.py67
-rwxr-xr-xsrc/tests/gssapi/t_client_keytab.py60
-rw-r--r--src/tests/gssapi/t_enctypes.c14
-rwxr-xr-xsrc/tests/gssapi/t_enctypes.py4
-rwxr-xr-xsrc/tests/gssapi/t_export_cred.py4
-rwxr-xr-xsrc/tests/gssapi/t_gssapi.py130
-rw-r--r--src/tests/gssapi/t_invalid.c57
-rw-r--r--src/tests/gssapi/t_lifetime.c140
-rw-r--r--src/tests/gssapi/t_s4u.c20
-rwxr-xr-xsrc/tests/gssapi/t_s4u.py21
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: