1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
from k5test import *
# Test that the kdcpreauth client_keyblock() callback matches the key
# indicated by the etype info, and returns NULL if no key was selected.
testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so')
conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth},
'clpreauth': {'module': 'test:' + testpreauth}}}
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ])
realm.run([kadminl, 'setstr', realm.user_princ, 'teststring', 'testval'])
realm.run([kadminl, 'addprinc', '-nokey', '+requires_preauth', 'nokeyuser'])
realm.kinit(realm.user_princ, password('user'), expected_msg='testval')
realm.kinit('nokeyuser', password('user'), expected_code=1,
expected_msg='no key')
# Preauth type -123 is the test preauth module type; 133 is FAST
# PA-FX-COOKIE; 2 is encrypted timestamp.
# Test normal preauth flow.
mark('normal')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'Decrypted AS reply')
realm.run(['./icred', realm.user_princ, password('user')],
expected_msg='testval', expected_trace=msgs)
# Test successful optimistic preauth.
mark('optimistic')
expected_trace = ('Attempting optimistic preauth',
'Processing preauth types: -123',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: -123',
'Decrypted AS reply')
realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
expected_trace=expected_trace)
# Test optimistic preauth failing on client, falling back to encrypted
# timestamp.
mark('optimistic (client failure)')
msgs = ('Attempting optimistic preauth',
'Processing preauth types: -123',
'/induced optimistic fail',
'Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Encrypted timestamp (for ',
'module encrypted_timestamp (2) (real) returned: 0/Success',
'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
'Decrypted AS reply')
realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ,
password('user')], expected_trace=msgs)
# Test optimistic preauth failing on KDC, falling back to encrypted
# timestamp.
mark('optimistic (KDC failure)')
realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes'])
msgs = ('Attempting optimistic preauth',
'Processing preauth types: -123',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: -123',
'/Preauthentication failed',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Encrypted timestamp (for ',
'module encrypted_timestamp (2) (real) returned: 0/Success',
'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
'Decrypted AS reply')
realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
expected_trace=msgs)
# Leave failopt set for the next test.
# Test optimistic preauth failing on KDC, stopping because the test
# module disabled fallback.
mark('optimistic (KDC failure, no fallback)')
msgs = ('Attempting optimistic preauth',
'Processing preauth types: -123',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: -123',
'/Preauthentication failed')
realm.run(['./icred', '-X', 'disable_fallback', '-o', '-123', realm.user_princ,
password('user')], expected_code=1,
expected_msg='Preauthentication failed', expected_trace=msgs)
realm.run([kadminl, 'delstr', realm.user_princ, 'failopt'])
# Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
mark('second round-trip')
realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip'])
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/More preauthentication data is required',
'Continuing preauth mech -123',
'Processing preauth types: -123, PA-FX-COOKIE (133)',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'Decrypted AS reply')
realm.run(['./icred', realm.user_princ, password('user')],
expected_msg='2rt: secondtrip', expected_trace=msgs)
# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
# falling back to encrypted timestamp.
mark('second round-trip (client failure)')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/More preauthentication data is required',
'Continuing preauth mech -123',
'Processing preauth types: -123, PA-FX-COOKIE (133)',
'/induced 2rt fail',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Encrypted timestamp (for ',
'module encrypted_timestamp (2) (real) returned: 0/Success',
'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
'Decrypted AS reply')
realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')],
expected_msg='2rt: secondtrip', expected_trace=msgs)
# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
# stopping because the test module disabled fallback.
mark('second round-trip (client failure, no fallback)')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/More preauthentication data is required',
'Continuing preauth mech -123',
'Processing preauth types: -123, PA-FX-COOKIE (133)',
'/induced 2rt fail')
realm.run(['./icred', '-X', 'fail_2rt', '-X', 'disable_fallback',
realm.user_princ, password('user')], expected_code=1,
expected_msg='Pre-authentication failed: induced 2rt fail',
expected_trace=msgs)
# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
# falling back to encrypted timestamp.
mark('second round-trip (KDC failure)')
realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes'])
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/More preauthentication data is required',
'Continuing preauth mech -123',
'Processing preauth types: -123, PA-FX-COOKIE (133)',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/Preauthentication failed',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Encrypted timestamp (for ',
'module encrypted_timestamp (2) (real) returned: 0/Success',
'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
'Decrypted AS reply')
realm.run(['./icred', realm.user_princ, password('user')],
expected_msg='2rt: secondtrip', expected_trace=msgs)
# Leave fail2rt set for the next test.
# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
# stopping because the test module disabled fallback.
mark('second round-trip (KDC failure, no fallback)')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/More preauthentication data is required',
'Continuing preauth mech -123',
'Processing preauth types: -123, PA-FX-COOKIE (133)',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/Preauthentication failed')
realm.run(['./icred', '-X', 'disable_fallback',
realm.user_princ, password('user')], expected_code=1,
expected_msg='Preauthentication failed', expected_trace=msgs)
realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt'])
# Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC.
mark('tryagain')
realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain'])
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/KDC has no support for encryption type',
'Recovering from KDC error 14 using preauth mech -123',
'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
'Preauth module test (-123) tryagain returned: 0/Success',
'Followup preauth for next request: -123, PA-FX-COOKIE (133)',
'Decrypted AS reply')
realm.run(['./icred', realm.user_princ, password('user')],
expected_msg='tryagain: testagain', expected_trace=msgs)
# Test a client-side tryagain failure, falling back to encrypted
# timestamp.
mark('tryagain (client failure)')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/KDC has no support for encryption type',
'Recovering from KDC error 14 using preauth mech -123',
'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
'/induced tryagain fail',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Encrypted timestamp (for ',
'module encrypted_timestamp (2) (real) returned: 0/Success',
'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
'Decrypted AS reply')
realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ,
password('user')], expected_trace=msgs)
# Test a client-side tryagain failure, stopping because the test
# module disabled fallback.
mark('tryagain (client failure, no fallback)')
msgs = ('Sending unauthenticated request',
'/Additional pre-authentication required',
'Preauthenticating using KDC method data',
'Processing preauth types:',
'Preauth module test (-123) (real) returned: 0/Success',
'Produced preauth for next request: PA-FX-COOKIE (133), -123',
'/KDC has no support for encryption type',
'Recovering from KDC error 14 using preauth mech -123',
'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
'/induced tryagain fail')
realm.run(['./icred', '-X', 'fail_tryagain', '-X', 'disable_fallback',
realm.user_princ, password('user')], expected_code=1,
expected_msg='KDC has no support for encryption type',
expected_trace=msgs)
# Test that multiple stepwise initial creds operations can be
# performed with the same krb5_context, with proper tracking of
# clpreauth module request handles.
mark('interleaved')
realm.run([kadminl, 'addprinc', '-pw', 'pw', 'u1'])
realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u2'])
realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u3'])
realm.run([kadminl, 'setstr', 'u2', '2rt', 'extra'])
out = realm.run(['./icinterleave', 'pw', 'u1', 'u2', 'u3'])
if out != ('step 1\nstep 2\nstep 3\nstep 1\nfinish 1\nstep 2\nno attr\n'
'step 3\nno attr\nstep 2\n2rt: extra\nstep 3\nfinish 3\nstep 2\n'
'finish 2\n'):
fail('unexpected output from icinterleave')
success('Pre-authentication framework tests')
|