Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/tests/gssapi/t_s4u.py
34889 views
1
from k5test import *
2
from base64 import b64encode
3
import shutil
4
5
realm = K5Realm(create_host=False, get_creds=False)
6
usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache')
7
storagecache = 'FILE:' + os.path.join(realm.testdir, 'save')
8
9
# Create two service principals with keys in the default keytab.
10
service1 = 'service/1@%s' % realm.realm
11
realm.addprinc(service1)
12
realm.extract_keytab(service1, realm.keytab)
13
service2 = 'service/2@%s' % realm.realm
14
realm.addprinc(service2)
15
realm.extract_keytab(service2, realm.keytab)
16
17
puser = 'p:' + realm.user_princ
18
pservice1 = 'p:' + service1
19
pservice2 = 'p:' + service2
20
21
# Get forwardable creds for service1 in the default cache.
22
realm.kinit(service1, None, ['-f', '-k'])
23
24
# Try S4U2Self for user with a restricted password.
25
realm.run([kadminl, 'modprinc', '+needchange', realm.user_princ])
26
realm.run(['./t_s4u', 'e:user', '-'])
27
realm.run([kadminl, 'modprinc', '-needchange',
28
'-pwexpire', '1/1/2000', realm.user_princ])
29
realm.run(['./t_s4u', 'e:user', '-'])
30
realm.run([kadminl, 'modprinc', '-pwexpire', 'never', realm.user_princ])
31
32
# Try krb5 -> S4U2Proxy with forwardable user creds. This should fail
33
# at the S4U2Proxy step since the DB2 back end currently has no
34
# support for allowing it.
35
realm.kinit(realm.user_princ, password('user'), ['-f', '-c', usercache])
36
output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-',
37
pservice1, pservice2], expected_code=1)
38
if ('auth1: ' + realm.user_princ not in output or
39
'KDC can\'t fulfill requested option' not in output):
40
fail('krb5 -> s4u2proxy')
41
42
# Again with SPNEGO.
43
output = realm.run(['./t_s4u2proxy_krb5', '--spnego', usercache, storagecache,
44
'-', pservice1, pservice2],
45
expected_code=1)
46
if ('auth1: ' + realm.user_princ not in output or
47
'KDC can\'t fulfill requested option' not in output):
48
fail('krb5 -> s4u2proxy (SPNEGO)')
49
50
# Try krb5 -> S4U2Proxy without forwardable user creds.
51
realm.kinit(realm.user_princ, password('user'), ['-c', usercache])
52
output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1,
53
pservice1, pservice2], expected_code=1)
54
if ('auth1: ' + realm.user_princ not in output or
55
'KDC can\'t fulfill requested option' not in output):
56
fail('krb5 -> s4u2proxy not-forwardable')
57
58
# Try S4U2Self. Ask for an S4U2Proxy step; this won't succeed because
59
# service/1 isn't allowed to get a forwardable S4U2Self ticket.
60
realm.run(['./t_s4u', puser, pservice2], expected_code=1,
61
expected_msg='KDC can\'t fulfill requested option')
62
realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1,
63
expected_msg='KDC can\'t fulfill requested option')
64
65
# Correct that problem and try again. As above, the S4U2Proxy step
66
# won't actually succeed since we don't support that in DB2.
67
realm.run([kadminl, 'modprinc', '+ok_to_auth_as_delegate', service1])
68
realm.run(['./t_s4u', puser, pservice2], expected_code=1,
69
expected_msg='KDC can\'t fulfill requested option')
70
71
# Again with SPNEGO. This uses SPNEGO for the initial authentication,
72
# but still uses krb5 for S4U2Proxy--the delegated cred is returned as
73
# a krb5 cred, not a SPNEGO cred, and t_s4u uses the delegated cred
74
# directly rather than saving and reacquiring it.
75
realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1,
76
expected_msg='KDC can\'t fulfill requested option')
77
78
realm.stop()
79
80
# Set up a realm using the test KDB module so that we can do
81
# successful S4U2Proxy delegations.
82
testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},
83
'user': {'keys': 'aes128-cts'},
84
'service/1': {'flags': '+ok-to-auth-as-delegate',
85
'keys': 'aes128-cts'},
86
'service/2': {'keys': 'aes128-cts'}}
87
conf = {'realms': {'$realm': {'database_module': 'test'}},
88
'dbmodules': {'test': {'db_library': 'test',
89
'princs': testprincs,
90
'delegation': {'service/1': 'service/2'}}}}
91
realm = K5Realm(create_kdb=False, kdc_conf=conf)
92
userkeytab = 'FILE:' + os.path.join(realm.testdir, 'userkeytab')
93
realm.extract_keytab(realm.user_princ, userkeytab)
94
realm.extract_keytab(service1, realm.keytab)
95
realm.extract_keytab(service2, realm.keytab)
96
realm.start_kdc()
97
98
# Get forwardable creds for service1 in the default cache.
99
realm.kinit(service1, None, ['-f', '-k'])
100
101
# Successful krb5 -> S4U2Proxy, with krb5 and SPNEGO mechs.
102
realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache,
103
'-t', userkeytab])
104
out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-',
105
pservice1, pservice2])
106
if 'auth1: user@' not in out or 'auth2: user@' not in out:
107
fail('krb5 -> s4u2proxy')
108
out = realm.run(['./t_s4u2proxy_krb5', '--spnego', usercache, storagecache,
109
'-', pservice1, pservice2])
110
if 'auth1: user@' not in out or 'auth2: user@' not in out:
111
fail('krb5 -> s4u2proxy')
112
113
# Successful S4U2Self -> S4U2Proxy.
114
out = realm.run(['./t_s4u', puser, pservice2])
115
116
# Regression test for #8139: get a user ticket directly for service1 and
117
# try krb5 -> S4U2Proxy.
118
realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache,
119
'-t', userkeytab, '-S', service1])
120
out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-',
121
pservice1, pservice2])
122
if 'auth1: user@' not in out or 'auth2: user@' not in out:
123
fail('krb5 -> s4u2proxy')
124
125
# Simulate a krbtgt rollover and verify that the user ticket can still
126
# be validated.
127
realm.stop_kdc()
128
newtgt_keys = ['2 aes128-cts', '1 aes128-cts']
129
newtgt_princs = {'krbtgt/KRBTEST.COM': {'keys': newtgt_keys}}
130
newtgt_conf = {'dbmodules': {'test': {'princs': newtgt_princs}}}
131
newtgt_env = realm.special_env('newtgt', True, kdc_conf=newtgt_conf)
132
realm.start_kdc(env=newtgt_env)
133
out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-',
134
pservice1, pservice2])
135
if 'auth1: user@' not in out or 'auth2: user@' not in out:
136
fail('krb5 -> s4u2proxy')
137
138
# Get a user ticket after the krbtgt rollover and verify that
139
# S4U2Proxy delegation works (also a #8139 regression test).
140
realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache,
141
'-t', userkeytab])
142
out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-',
143
pservice1, pservice2])
144
if 'auth1: user@' not in out or 'auth2: user@' not in out:
145
fail('krb5 -> s4u2proxy')
146
147
realm.stop()
148
149
mark('S4U2Self with various enctypes')
150
for realm in multipass_realms(create_host=False, get_creds=False):
151
service1 = 'service/1@%s' % realm.realm
152
realm.addprinc(service1)
153
realm.extract_keytab(service1, realm.keytab)
154
realm.kinit(service1, None, ['-k'])
155
realm.run(['./t_s4u', 'e:user', '-'])
156
157
# Test cross realm S4U2Self using server referrals.
158
mark('cross-realm S4U2Self')
159
testprincs = {'krbtgt/SREALM': {'keys': 'aes128-cts'},
160
'krbtgt/UREALM': {'keys': 'aes128-cts'},
161
'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
162
'other': {'keys': 'aes128-cts'}}
163
kdcconf1 = {'realms': {'$realm': {'database_module': 'test'}},
164
'dbmodules': {'test': {'db_library': 'test',
165
'princs': testprincs,
166
'alias': {'enterprise@abc': '@UREALM',
167
'user@UREALM': '@UREALM'}}}}
168
kdcconf2 = {'realms': {'$realm': {'database_module': 'test'}},
169
'dbmodules': {'test': {'db_library': 'test',
170
'princs': testprincs,
171
'alias': {'user@SREALM': '@SREALM',
172
'user@UREALM': 'user',
173
'enterprise@abc': 'user'}}}}
174
r1, r2 = cross_realms(2, xtgts=(),
175
args=({'realm': 'SREALM', 'kdc_conf': kdcconf1},
176
{'realm': 'UREALM', 'kdc_conf': kdcconf2}),
177
create_kdb=False)
178
179
r1.start_kdc()
180
r2.start_kdc()
181
r1.extract_keytab(r1.user_princ, r1.keytab)
182
r1.kinit(r1.user_princ, None, ['-k', '-t', r1.keytab])
183
savefile = r1.ccache + '.save'
184
shutil.copyfile(r1.ccache, savefile)
185
186
# Include a regression test for #8741 by unsetting the default realm.
187
remove_default = {'libdefaults': {'default_realm': None}}
188
no_default = r1.special_env('no_default', False, krb5_conf=remove_default)
189
msgs = ('Getting credentials user@UREALM -> user@SREALM',
190
'/Matching credential not found',
191
'Getting credentials user@SREALM -> krbtgt/UREALM@SREALM',
192
'Received creds for desired service krbtgt/UREALM@SREALM',
193
'via TGT krbtgt/UREALM@SREALM after requesting user\\@SREALM@UREALM',
194
'krbtgt/SREALM@UREALM differs from requested user\\@SREALM@UREALM',
195
'via TGT krbtgt/SREALM@UREALM after requesting user@SREALM',
196
'TGS reply is for user@UREALM -> user@SREALM')
197
r1.run(['./t_s4u', 'p:' + r2.user_princ, '-', r1.keytab], env=no_default,
198
expected_trace=msgs)
199
200
# Test realm identification of enterprise principal names ([MS-SFU]
201
# 3.1.5.1.1.1). Attach a bogus realm to the enterprise name to verify
202
# that we start at the server realm.
203
mark('cross-realm S4U2Self with enterprise name')
204
msgs = ('Getting initial credentials for enterprise\\@abc@SREALM',
205
'Sending unauthenticated request',
206
'/Realm not local to KDC',
207
'Following referral to realm UREALM',
208
'Sending unauthenticated request',
209
'/Additional pre-authentication required',
210
'Identified realm of client principal as UREALM',
211
'Getting credentials enterprise\\@abc@UREALM -> user@SREALM',
212
'TGS reply is for enterprise\\@abc@UREALM -> user@SREALM')
213
r1.run(['./t_s4u', 'e:enterprise@abc@NOREALM', '-', r1.keytab],
214
expected_trace=msgs)
215
216
mark('S4U2Self using X509 certificate')
217
218
# Encode name as a PEM certificate file (sort of) for use by kvno.
219
def princ_cert(name):
220
enc = b64encode(name.encode('ascii')).decode('ascii')
221
return '-----BEGIN CERTIFICATE-----\n%s\n-----END y\n' % enc
222
223
cert_path = os.path.join(r1.testdir, 'fake_cert')
224
with open(cert_path, "w") as cert_file:
225
cert_file.write(princ_cert('other'))
226
227
shutil.copyfile(savefile, r1.ccache)
228
msgs = ('Getting initial credentials for @SREALM',
229
'Identified realm of client principal as SREALM',
230
'TGS reply is for other@SREALM',
231
'Getting credentials other@SREALM',
232
'Storing other@SREALM')
233
r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs)
234
235
shutil.copyfile(savefile, r1.ccache)
236
msgs = ('Getting credentials other@SREALM',
237
'TGS reply is for other@SREALM',
238
'Storing other@SREALM')
239
r1.run([kvno, '-I', 'other', '-F', cert_path, r1.user_princ],
240
expected_trace=msgs)
241
242
shutil.copyfile(savefile, r1.ccache)
243
msgs = ('Getting initial credentials for other@SREALM',
244
'Identified realm of client principal as SREALM',
245
'Getting credentials other@SREALM',
246
'TGS reply is for other@SREALM',
247
'Storing other@SREALM')
248
r1.run([kvno, '-U', 'other', '-F', cert_path, r1.user_princ],
249
expected_trace=msgs)
250
251
mark('cross-realm S4U2Self using X509 certificate')
252
253
with open(cert_path, "w") as cert_file:
254
cert_file.write(princ_cert('user@UREALM'))
255
256
shutil.copyfile(savefile, r1.ccache)
257
msgs = ('Getting initial credentials for @SREALM',
258
'Identified realm of client principal as UREALM',
259
'TGS reply is for user@UREALM',
260
'Getting credentials user@UREALM',
261
'Storing user@UREALM')
262
r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs)
263
264
shutil.copyfile(savefile, r1.ccache)
265
msgs = ('Getting credentials user@UREALM',
266
'TGS reply is for user@UREALM',
267
'Storing user@UREALM')
268
r1.run([kvno, '-I', 'user@UREALM', '-F', cert_path, r1.user_princ],
269
expected_trace=msgs)
270
271
shutil.copyfile(savefile, r1.ccache)
272
msgs = ('Getting initial credentials for enterprise\\@abc@SREALM',
273
'Identified realm of client principal as UREALM',
274
'Getting credentials enterprise\\@abc@UREALM',
275
'TGS reply is for enterprise\\@abc@UREALM',
276
'Storing enterprise\\@abc@UREALM')
277
r1.run([kvno, '-U', 'enterprise@abc', '-F', cert_path, r1.user_princ],
278
expected_trace=msgs)
279
280
shutil.copyfile(savefile, r1.ccache)
281
282
mark('S4U2Self using X509 certificate (GSSAPI)')
283
284
r1.run(['./t_s4u', 'c:other', '-', r1.keytab])
285
r1.run(['./t_s4u', 'c:user@UREALM', '-', r1.keytab])
286
287
r1.run(['./t_s4u', '--spnego', 'c:other', '-', r1.keytab])
288
r1.run(['./t_s4u', '--spnego', 'c:user@UREALM', '-', r1.keytab])
289
290
r1.stop()
291
r2.stop()
292
293
mark('Resource-based constrained delegation')
294
295
a_princs = {'krbtgt/A': {'keys': 'aes128-cts'},
296
'krbtgt/B': {'keys': 'aes128-cts'},
297
'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
298
'sensitive': {'keys': 'aes128-cts',
299
'flags': '+disallow_forwardable'},
300
'impersonator': {'keys': 'aes128-cts'},
301
'service1': {'keys': 'aes128-cts'},
302
'rb2': {'keys': 'aes128-cts'},
303
'rb': {'keys': 'aes128-cts'}}
304
a_kconf = {'realms': {'$realm': {'database_module': 'test'}},
305
'dbmodules': {'test': {'db_library': 'test',
306
'princs': a_princs,
307
'rbcd': {'rb@A': 'impersonator@A',
308
'rb2@A': 'service1@A'},
309
'delegation': {'service1': 'rb2'},
310
'alias': {'rb@A': 'rb',
311
'rb@B': '@B',
312
'rb@C': '@B',
313
'service/rb.a': 'rb',
314
'service/rb.b': '@B',
315
'service/rb.c': '@B' }}}}
316
317
b_princs = {'krbtgt/B': {'keys': 'aes128-cts'},
318
'krbtgt/A': {'keys': 'aes128-cts'},
319
'krbtgt/C': {'keys': 'aes128-cts'},
320
'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
321
'rb': {'keys': 'aes128-cts'}}
322
b_kconf = {'realms': {'$realm': {'database_module': 'test'}},
323
'dbmodules': {'test': {'db_library': 'test',
324
'princs': b_princs,
325
'rbcd': {'rb@B': 'impersonator@A'},
326
'alias': {'rb@B': 'rb',
327
'service/rb.b': 'rb',
328
'rb@C': '@C',
329
'impersonator@A': '@A',
330
'service/rb.c': '@C'}}}}
331
332
c_princs = {'krbtgt/C': {'keys': 'aes128-cts'},
333
'krbtgt/B': {'keys': 'aes128-cts'},
334
'rb': {'keys': 'aes128-cts'}}
335
c_kconf = {'realms': {'$realm': {'database_module': 'test'}},
336
'capaths': { 'A' : { 'C' : 'B' }},
337
'dbmodules': {'test': {'db_library': 'test',
338
'princs': c_princs,
339
'rbcd': {'rb@C': ['impersonator@A',
340
'service1@A']},
341
'alias': {'rb@C': 'rb',
342
'service/rb.c': 'rb' }}}}
343
344
ra, rb, rc = cross_realms(3, xtgts=(),
345
args=({'realm': 'A', 'kdc_conf': a_kconf},
346
{'realm': 'B', 'kdc_conf': b_kconf},
347
{'realm': 'C', 'kdc_conf': c_kconf}),
348
create_kdb=False)
349
350
ra.start_kdc()
351
rb.start_kdc()
352
rc.start_kdc()
353
354
domain_realm = {'domain_realm': {'.a':'A', '.b':'B', '.c':'C'}}
355
domain_conf = ra.special_env('domain_conf', False, krb5_conf=domain_realm)
356
357
ra.extract_keytab('impersonator@A', ra.keytab)
358
ra.kinit('impersonator@A', None, ['-f', '-k', '-t', ra.keytab])
359
360
mark('Local-realm RBCD')
361
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'p:rb'])
362
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb'])
363
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'p:rb@A'])
364
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A'])
365
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A@'])
366
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A@A'])
367
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'])
368
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'], env=domain_conf)
369
ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:[email protected]'], expected_code=1)
370
ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:[email protected]'])
371
372
mark('Cross-realm RBCD')
373
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B'])
374
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B@'])
375
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B@A'])
376
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'])
377
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'], env=domain_conf)
378
ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:[email protected]'], expected_code=1)
379
ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:[email protected]'])
380
381
mark('RBCD transitive trust')
382
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C'])
383
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C@'])
384
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C@A'])
385
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'])
386
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:[email protected]'], env=domain_conf)
387
ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:[email protected]'], expected_code=1)
388
ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:[email protected]'])
389
390
# Although service1 has RBCD delegation privileges to rb2@A, it does
391
# not have ok-to-auth-as-delegate and does have traditional delegation
392
# privileges, so it cannot get a forwardable S4U2Self ticket.
393
mark('RBCD forwardable blocked by forward delegation privileges')
394
ra.extract_keytab('service1@A', ra.keytab)
395
ra.kinit('service1@A', None, ['-f', '-k', '-t', ra.keytab])
396
ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb2@A'], expected_code=1,
397
expected_msg='KDC can\'t fulfill requested option')
398
399
ra.stop()
400
rb.stop()
401
rc.stop()
402
403
success('S4U test cases')
404
405