xref: /freebsd/crypto/krb5/src/tests/gssapi/t_client_keytab.py (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1from k5test import *
2
3# Set up a basic realm and a client keytab containing two user principals.
4# Point HOME at realm.testdir for tests using .k5identity.
5realm = K5Realm(get_creds=False)
6bob = 'bob@' + realm.realm
7phost = 'p:' + realm.host_princ
8puser = 'p:' + realm.user_princ
9pbob = 'p:' + bob
10gssserver = 'h:host@' + hostname
11realm.env['HOME'] = realm.testdir
12realm.addprinc(bob, password('bob'))
13realm.extract_keytab(realm.user_princ, realm.client_keytab)
14realm.extract_keytab(bob, realm.client_keytab)
15
16# Test 1: no name/cache specified, pick first principal from client keytab
17realm.run(['./t_ccselect', phost], expected_msg=realm.user_princ)
18realm.run([kdestroy])
19
20# Test 2: no name/cache specified, pick principal from k5identity
21k5idname = os.path.join(realm.testdir, '.k5identity')
22k5id = open(k5idname, 'w')
23k5id.write('%s service=host host=%s\n' % (bob, hostname))
24k5id.close()
25realm.run(['./t_ccselect', gssserver], expected_msg=bob)
26os.remove(k5idname)
27realm.run([kdestroy])
28
29# Test 3: no name/cache specified, default ccache has name but no creds
30realm.run(['./ccinit', realm.ccache, bob])
31realm.run(['./t_ccselect', phost], expected_msg=bob)
32# Leave tickets for next test.
33
34# Test 4: name specified, non-collectable default cache doesn't match
35msg = 'Principal in credential cache does not match desired name'
36realm.run(['./t_ccselect', phost, puser], expected_code=1, expected_msg=msg)
37realm.run([kdestroy])
38
39# Test 5: name specified, nonexistent default cache
40realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
41# Leave tickets for next test.
42
43# Test 6: name specified, matches default cache, time to refresh
44realm.run(['./ccrefresh', realm.ccache, '1'])
45realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
46out = realm.run(['./ccrefresh', realm.ccache])
47if int(out) < 1000:
48    fail('Credentials apparently not refreshed')
49realm.run([kdestroy])
50
51# Test 7: empty ccache specified, pick first principal from client keytab
52realm.run(['./t_imp_cred', phost])
53realm.klist(realm.user_princ)
54realm.run([kdestroy])
55
56# Test 8: ccache specified with name but no creds; name not in client keytab
57realm.run(['./ccinit', realm.ccache, realm.host_princ])
58realm.run(['./t_imp_cred', phost], expected_code=1,
59          expected_msg='Credential cache is empty')
60realm.run([kdestroy])
61
62# Test 9: ccache specified with name but no creds; name in client keytab
63realm.run(['./ccinit', realm.ccache, bob])
64realm.run(['./t_imp_cred', phost])
65realm.klist(bob)
66# Leave tickets for next test.
67
68# Test 10: ccache specified with creds, time to refresh
69realm.run(['./ccrefresh', realm.ccache, '1'])
70realm.run(['./t_imp_cred', phost])
71realm.klist(bob)
72out = realm.run(['./ccrefresh', realm.ccache])
73if int(out) < 1000:
74    fail('Credentials apparently not refreshed')
75realm.run([kdestroy])
76
77# Test 11: gss_import_cred_from with client_keytab value
78store_keytab = os.path.join(realm.testdir, 'store_keytab')
79os.rename(realm.client_keytab, store_keytab)
80realm.run(['./t_credstore', '-i', 'p:' + realm.user_princ, 'client_keytab',
81           store_keytab])
82realm.klist(realm.user_princ)
83os.rename(store_keytab, realm.client_keytab)
84
85# Use a cache collection for the remaining tests.
86ccdir = os.path.join(realm.testdir, 'cc')
87ccname = 'DIR:' + ccdir
88os.mkdir(ccdir)
89realm.env['KRB5CCNAME'] = ccname
90
91# Test 12: name specified, matching cache in collection with no creds
92bobcache = os.path.join(ccdir, 'tktbob')
93realm.run(['./ccinit', bobcache, bob])
94realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
95# Leave tickets for next test.
96
97# Test 13: name specified, matching cache in collection, time to refresh
98realm.run(['./ccrefresh', bobcache, '1'])
99realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
100out = realm.run(['./ccrefresh', bobcache])
101if int(out) < 1000:
102    fail('Credentials apparently not refreshed')
103realm.run([kdestroy, '-A'])
104
105# Test 14: name specified, collection has default for different principal
106realm.kinit(realm.user_princ, password('user'))
107realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
108msg = 'Default principal: %s\n' % realm.user_princ
109realm.run([klist], expected_msg=msg)
110realm.run([kdestroy, '-A'])
111
112# Test 15: name specified, collection has no default cache
113realm.run(['./t_ccselect', phost, pbob], expected_msg=bob)
114# Make sure the tickets we acquired didn't become the default
115realm.run([klist], expected_code=1, expected_msg='No credentials cache found')
116realm.run([kdestroy, '-A'])
117
118# Test 16: default client keytab cannot be resolved, but valid
119# credentials exist in ccache.
120conf = {'libdefaults': {'default_client_keytab_name': '%{'}}
121bad_cktname = realm.special_env('bad_cktname', False, krb5_conf=conf)
122del bad_cktname['KRB5_CLIENT_KTNAME']
123realm.kinit(realm.user_princ, password('user'))
124realm.run(['./t_ccselect', phost], env=bad_cktname,
125          expected_msg=realm.user_princ)
126
127mark('refresh of manually acquired creds')
128
129# Test 17: no name/ccache specified, manually acquired creds which
130# will expire soon.  Verify that creds are refreshed using the current
131# client name, with refresh_time set in the refreshed ccache.
132realm.kinit('bob', password('bob'), ['-l', '15s'])
133realm.run(['./t_ccselect', phost], expected_msg='bob')
134realm.run([klist, '-C'], expected_msg='refresh_time = ')
135
136# Test 18: no name/ccache specified, manually acquired creds with a
137# client principal not present in the client keytab.  A refresh is
138# attempted but fails, and an expired ticket error results.
139realm.kinit(realm.admin_princ, password('admin'), ['-l', '-10s'])
140msgs = ('Getting initial credentials for user/admin@KRBTEST.COM',
141        '/Matching credential not found')
142realm.run(['./t_ccselect', phost], expected_code=1,
143          expected_msg='Ticket expired', expected_trace=msgs)
144realm.run([kdestroy, '-A'])
145
146# Test 19: host-based initiator name
147mark('host-based initiator name')
148hsvc = 'h:svc@' + hostname
149svcprinc = 'svc/%s@%s' % (hostname, realm.realm)
150realm.addprinc(svcprinc)
151realm.extract_keytab(svcprinc, realm.client_keytab)
152# On the first run we match against the keytab while getting tickets,
153# substituting the default realm.
154msgs = ('/Can\'t find client principal svc/%s@ in' % hostname,
155        'Getting initial credentials for svc/%s@' % hostname,
156        'Found entries for %s in keytab' % svcprinc,
157        'Retrieving %s from FILE:%s' % (svcprinc, realm.client_keytab),
158        'Storing %s -> %s in' % (svcprinc, realm.krbtgt_princ),
159        'Retrieving %s -> %s from' % (svcprinc, realm.krbtgt_princ),
160        'authenticator for %s -> %s' % (svcprinc, realm.host_princ))
161realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs)
162# On the second run we match against the collection.
163msgs = ('Matching svc/%s@ in collection with result: 0' % hostname,
164        'Getting credentials %s -> %s' % (svcprinc, realm.host_princ),
165        'authenticator for %s -> %s' % (svcprinc, realm.host_princ))
166realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs)
167realm.run([kdestroy, '-A'])
168
169# Test 20: host-based initiator name with fallback
170mark('host-based fallback initiator name')
171canonname = canonicalize_hostname(hostname)
172if canonname != hostname:
173    hfsvc = 'h:fsvc@' + hostname
174    canonprinc = 'fsvc/%s@%s' % (canonname, realm.realm)
175    realm.addprinc(canonprinc)
176    realm.extract_keytab(canonprinc, realm.client_keytab)
177    msgs = ('/Can\'t find client principal fsvc/%s@ in' % hostname,
178            'Found entries for %s in keytab' % canonprinc,
179            'authenticator for %s -> %s' % (canonprinc, realm.host_princ))
180    realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs)
181    msgs = ('Matching fsvc/%s@ in collection with result: 0' % hostname,
182            'Getting credentials %s -> %s' % (canonprinc, realm.host_princ))
183    realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs)
184    realm.run([kdestroy, '-A'])
185else:
186    skipped('GSS initiator name fallback test',
187            '%s does not canonicalize to a different name' % hostname)
188
189success('Client keytab tests')
190