2 Unix SMB/CIFS implementation.
4 Validate the krb5 pac generation routines
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/kerberos.h"
25 #include "auth/auth.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "samba3/samba3.h"
28 #include "libcli/security/security.h"
29 #include "torture/torture.h"
30 #include "auth/auth_sam_reply.h"
31 #include "param/param.h"
33 static bool torture_pac_self_check(struct torture_context
*tctx
)
37 struct PAC_DATA
*pac_data
;
38 struct PAC_LOGON_INFO
*logon_info
;
39 union netr_Validation validation
;
41 /* Generate a nice, arbitary keyblock */
42 uint8_t server_bytes
[16];
43 uint8_t krbtgt_bytes
[16];
44 krb5_keyblock server_keyblock
;
45 krb5_keyblock krbtgt_keyblock
;
49 struct smb_krb5_context
*smb_krb5_context
;
51 struct auth_serversupplied_info
*server_info
;
52 struct auth_serversupplied_info
*server_info_out
;
54 krb5_principal client_principal
;
55 time_t logon_time
= time(NULL
);
57 TALLOC_CTX
*mem_ctx
= tctx
;
59 torture_assert(tctx
, 0 == smb_krb5_init_context(mem_ctx
,
63 "smb_krb5_init_context");
65 generate_random_buffer(server_bytes
, 16);
66 generate_random_buffer(krbtgt_bytes
, 16);
68 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
70 server_bytes
, sizeof(server_bytes
),
72 torture_assert(tctx
, !ret
, talloc_asprintf(tctx
,
73 "(self test) Server Keyblock encoding failed: %s",
74 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
77 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
79 krbtgt_bytes
, sizeof(krbtgt_bytes
),
82 char *err
= smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
85 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
88 torture_fail(tctx
, talloc_asprintf(tctx
,
89 "(self test) KRBTGT Keyblock encoding failed: %s", err
));
92 /* We need an input, and this one requires no underlying database */
93 nt_status
= auth_anonymous_server_info(mem_ctx
, lpcfg_netbios_name(tctx
->lp_ctx
), &server_info
);
95 if (!NT_STATUS_IS_OK(nt_status
)) {
96 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
98 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
100 torture_fail(tctx
, "auth_anonymous_server_info");
103 ret
= krb5_parse_name_flags(smb_krb5_context
->krb5_context
,
104 server_info
->account_name
,
105 KRB5_PRINCIPAL_PARSE_NO_REALM
,
108 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
110 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
112 torture_fail(tctx
, "krb5_parse_name_flags(norealm)");
115 /* OK, go ahead and make a PAC */
116 ret
= kerberos_create_pac(mem_ctx
,
118 smb_krb5_context
->krb5_context
,
126 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
128 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
130 krb5_free_principal(smb_krb5_context
->krb5_context
,
133 torture_fail(tctx
, talloc_asprintf(tctx
,
134 "(self test) PAC encoding failed: %s",
135 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
139 dump_data(10,tmp_blob
.data
,tmp_blob
.length
);
141 /* Now check that we can read it back (using full decode and validate) */
142 nt_status
= kerberos_decode_pac(mem_ctx
,
145 smb_krb5_context
->krb5_context
,
151 if (!NT_STATUS_IS_OK(nt_status
)) {
152 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
154 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
156 krb5_free_principal(smb_krb5_context
->krb5_context
,
159 torture_fail(tctx
, talloc_asprintf(tctx
,
160 "(self test) PAC decoding failed: %s",
161 nt_errstr(nt_status
)));
164 /* Now check we can read it back (using Heimdal's pac parsing) */
165 nt_status
= kerberos_pac_blob_to_server_info(mem_ctx
,
167 smb_krb5_context
->krb5_context
,
170 if (!dom_sid_equal(server_info
->account_sid
,
171 server_info_out
->account_sid
)) {
172 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
174 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
176 krb5_free_principal(smb_krb5_context
->krb5_context
,
180 talloc_asprintf(tctx
,
181 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
182 dom_sid_string(mem_ctx
, server_info
->account_sid
),
183 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
185 talloc_free(server_info_out
);
187 /* Now check that we can read it back (yet again) */
188 nt_status
= kerberos_pac_logon_info(mem_ctx
,
191 smb_krb5_context
->krb5_context
,
198 if (!NT_STATUS_IS_OK(nt_status
)) {
199 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
201 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
203 krb5_free_principal(smb_krb5_context
->krb5_context
,
207 talloc_asprintf(tctx
,
208 "(self test) PAC decoding (for logon info) failed: %s",
209 nt_errstr(nt_status
)));
212 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
214 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
216 krb5_free_principal(smb_krb5_context
->krb5_context
,
219 /* And make a server info from the samba-parsed PAC */
220 validation
.sam3
= &logon_info
->info3
;
221 nt_status
= make_server_info_netlogon_validation(mem_ctx
,
225 if (!NT_STATUS_IS_OK(nt_status
)) {
227 talloc_asprintf(tctx
,
228 "(self test) PAC decoding (make server info) failed: %s",
229 nt_errstr(nt_status
)));
232 if (!dom_sid_equal(server_info
->account_sid
,
233 server_info_out
->account_sid
)) {
235 talloc_asprintf(tctx
,
236 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
237 dom_sid_string(mem_ctx
, server_info
->account_sid
),
238 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
244 /* This is the PAC generated on my test network, by my test Win2k3 server.
245 -- abartlet 2005-07-04
248 static const uint8_t saved_pac
[] = {
249 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
250 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
251 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
252 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
253 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
254 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
255 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
256 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
257 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
258 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
261 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
262 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
264 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
269 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
270 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
275 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
276 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
277 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
278 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
279 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
280 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
281 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
282 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
284 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
285 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
286 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
287 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
290 /* Check with a known 'well formed' PAC, from my test server */
291 static bool torture_pac_saved_check(struct torture_context
*tctx
)
294 enum ndr_err_code ndr_err
;
295 DATA_BLOB tmp_blob
, validate_blob
;
296 struct PAC_DATA
*pac_data
, pac_data2
;
297 struct PAC_LOGON_INFO
*logon_info
;
298 union netr_Validation validation
;
299 const char *pac_file
, *pac_kdc_key
, *pac_member_key
;
300 struct auth_serversupplied_info
*server_info_out
;
302 krb5_keyblock server_keyblock
;
303 krb5_keyblock krbtgt_keyblock
, *krbtgt_keyblock_p
;
304 struct samr_Password
*krbtgt_bytes
, *krbsrv_bytes
;
307 struct smb_krb5_context
*smb_krb5_context
;
309 const char *principal_string
;
310 char *broken_principal_string
;
311 krb5_principal client_principal
;
312 const char *authtime_string
;
314 TALLOC_CTX
*mem_ctx
= tctx
;
316 torture_assert(tctx
, 0 == smb_krb5_init_context(mem_ctx
, NULL
,
319 "smb_krb5_init_context");
321 pac_kdc_key
= torture_setting_string(tctx
, "pac_kdc_key",
322 "B286757148AF7FD252C53603A150B7E7");
324 pac_member_key
= torture_setting_string(tctx
, "pac_member_key",
325 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
327 torture_comment(tctx
, "Using pac_kdc_key '%s'\n", pac_kdc_key
);
328 torture_comment(tctx
, "Using pac_member_key '%s'\n", pac_member_key
);
330 /* The krbtgt key in use when the above PAC was generated.
331 * This is an arcfour-hmac-md5 key, extracted with our 'net
333 if (*pac_kdc_key
== 0) {
336 krbtgt_bytes
= smbpasswd_gethexpwd(mem_ctx
, pac_kdc_key
);
338 torture_fail(tctx
, "(saved test) Could not interpret krbtgt key");
342 krbsrv_bytes
= smbpasswd_gethexpwd(mem_ctx
, pac_member_key
);
344 torture_fail(tctx
, "(saved test) Could not interpret krbsrv key");
347 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
348 ENCTYPE_ARCFOUR_HMAC
,
349 krbsrv_bytes
->hash
, sizeof(krbsrv_bytes
->hash
),
351 torture_assert(tctx
, !ret
,
352 talloc_asprintf(tctx
,
353 "(saved test) Server Keyblock encoding failed: %s",
354 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
358 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
359 ENCTYPE_ARCFOUR_HMAC
,
360 krbtgt_bytes
->hash
, sizeof(krbtgt_bytes
->hash
),
363 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
366 talloc_asprintf(tctx
,
367 "(saved test) Server Keyblock encoding failed: %s",
368 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
371 krbtgt_keyblock_p
= &krbtgt_keyblock
;
373 krbtgt_keyblock_p
= NULL
;
376 pac_file
= torture_setting_string(tctx
, "pac_file", NULL
);
378 tmp_blob
.data
= (uint8_t *)file_load(pac_file
, &tmp_blob
.length
, 0, mem_ctx
);
379 torture_comment(tctx
, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob
.length
, pac_file
);
381 tmp_blob
= data_blob_talloc(mem_ctx
, saved_pac
, sizeof(saved_pac
));
384 dump_data(10,tmp_blob
.data
,tmp_blob
.length
);
386 principal_string
= torture_setting_string(tctx
, "pac_client_principal",
387 "w2003final$@WIN2K3.THINKER.LOCAL");
389 authtime_string
= torture_setting_string(tctx
, "pac_authtime", "1120440609");
390 authtime
= strtoull(authtime_string
, NULL
, 0);
392 ret
= krb5_parse_name(smb_krb5_context
->krb5_context
, principal_string
,
395 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
397 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
400 talloc_asprintf(tctx
,
401 "(saved test) parsing of client principal [%s] failed: %s",
403 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
, ret
, mem_ctx
)));
406 /* Decode and verify the signaure on the PAC */
407 nt_status
= kerberos_decode_pac(mem_ctx
,
410 smb_krb5_context
->krb5_context
,
413 client_principal
, authtime
, NULL
);
414 if (!NT_STATUS_IS_OK(nt_status
)) {
415 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
417 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
419 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
421 torture_fail(tctx
, talloc_asprintf(tctx
,
422 "(saved test) PAC decoding failed: %s",
423 nt_errstr(nt_status
)));
426 /* Now check we can read it back (using Heimdal's pac parsing) */
427 nt_status
= kerberos_pac_blob_to_server_info(mem_ctx
,
429 smb_krb5_context
->krb5_context
,
432 if (!NT_STATUS_IS_OK(nt_status
)) {
433 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
435 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
437 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
439 torture_fail(tctx
, talloc_asprintf(tctx
,
440 "(saved test) Heimdal PAC decoding failed: %s",
441 nt_errstr(nt_status
)));
445 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx
,
446 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
447 server_info_out
->account_sid
)) {
448 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
450 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
452 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
455 talloc_asprintf(tctx
,
456 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
457 "S-1-5-21-3048156945-3961193616-3706469200-1005",
458 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
461 talloc_free(server_info_out
);
463 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
464 nt_status
= kerberos_pac_logon_info(mem_ctx
,
467 smb_krb5_context
->krb5_context
,
470 client_principal
, authtime
, NULL
);
472 if (!NT_STATUS_IS_OK(nt_status
)) {
473 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
475 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
477 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
480 talloc_asprintf(tctx
,
481 "(saved test) PAC decoding (for logon info) failed: %s",
482 nt_errstr(nt_status
)));
485 validation
.sam3
= &logon_info
->info3
;
486 nt_status
= make_server_info_netlogon_validation(mem_ctx
,
490 if (!NT_STATUS_IS_OK(nt_status
)) {
491 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
493 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
495 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
498 talloc_asprintf(tctx
,
499 "(saved test) PAC decoding (make server info) failed: %s",
500 nt_errstr(nt_status
)));
504 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx
,
505 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
506 server_info_out
->account_sid
)) {
507 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
509 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
511 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
514 talloc_asprintf(tctx
,
515 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
516 "S-1-5-21-3048156945-3961193616-3706469200-1005",
517 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
520 if (krbtgt_bytes
== NULL
) {
521 torture_comment(tctx
, "skipping PAC encoding tests as non kdc key\n");
522 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
524 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
528 ret
= kerberos_encode_pac(mem_ctx
,
530 smb_krb5_context
->krb5_context
,
536 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
538 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
540 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
542 torture_fail(tctx
, "(saved test) PAC push failed");
545 dump_data(10, validate_blob
.data
, validate_blob
.length
);
547 /* compare both the length and the data bytes after a
548 * pull/push cycle. This ensures we use the exact same
549 * pointer, padding etc algorithms as win2k3.
551 if (tmp_blob
.length
!= validate_blob
.length
) {
552 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
554 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
556 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
559 talloc_asprintf(tctx
,
560 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
561 (unsigned)tmp_blob
.length
, (unsigned)validate_blob
.length
));
564 if (memcmp(tmp_blob
.data
, validate_blob
.data
, tmp_blob
.length
) != 0) {
565 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
567 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
569 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
571 DEBUG(0, ("tmp_data:\n"));
572 dump_data(0, tmp_blob
.data
, tmp_blob
.length
);
573 DEBUG(0, ("validate_blob:\n"));
574 dump_data(0, validate_blob
.data
, validate_blob
.length
);
576 torture_fail(tctx
, talloc_asprintf(tctx
, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob
.length
));
579 ret
= kerberos_create_pac(mem_ctx
,
581 smb_krb5_context
->krb5_context
,
584 client_principal
, authtime
,
588 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
590 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
592 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
594 torture_fail(tctx
, "(saved test) regnerated PAC create failed");
597 dump_data(10,validate_blob
.data
,validate_blob
.length
);
599 /* compare both the length and the data bytes after a
600 * pull/push cycle. This ensures we use the exact same
601 * pointer, padding etc algorithms as win2k3.
603 if (tmp_blob
.length
!= validate_blob
.length
) {
604 ndr_err
= ndr_pull_struct_blob(&validate_blob
, mem_ctx
,
606 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
607 nt_status
= ndr_map_error2ntstatus(ndr_err
);
608 torture_assert_ntstatus_ok(tctx
, nt_status
, "can't parse the PAC");
610 NDR_PRINT_DEBUG(PAC_DATA
, pac_data
);
612 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data2
);
614 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
616 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
618 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
620 torture_fail(tctx
, talloc_asprintf(tctx
,
621 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
622 (unsigned)tmp_blob
.length
, (unsigned)validate_blob
.length
));
625 if (memcmp(tmp_blob
.data
, validate_blob
.data
, tmp_blob
.length
) != 0) {
626 ndr_err
= ndr_pull_struct_blob(&validate_blob
, mem_ctx
,
628 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
629 nt_status
= ndr_map_error2ntstatus(ndr_err
);
630 torture_assert_ntstatus_ok(tctx
, nt_status
, "can't parse the PAC");
632 NDR_PRINT_DEBUG(PAC_DATA
, pac_data
);
634 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data2
);
636 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
638 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
640 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
642 DEBUG(0, ("tmp_data:\n"));
643 dump_data(0, tmp_blob
.data
, tmp_blob
.length
);
644 DEBUG(0, ("validate_blob:\n"));
645 dump_data(0, validate_blob
.data
, validate_blob
.length
);
647 torture_fail(tctx
, talloc_asprintf(tctx
,
648 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob
.length
));
651 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
652 nt_status
= kerberos_decode_pac(mem_ctx
,
655 smb_krb5_context
->krb5_context
,
660 if (NT_STATUS_IS_OK(nt_status
)) {
662 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
664 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
666 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
667 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
670 /* Break the client principal */
671 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
673 broken_principal_string
= talloc_strdup(mem_ctx
, principal_string
);
674 broken_principal_string
[0]++;
676 ret
= krb5_parse_name(smb_krb5_context
->krb5_context
,
677 broken_principal_string
, &client_principal
);
680 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
682 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
684 torture_fail(tctx
, talloc_asprintf(tctx
,
685 "(saved test) parsing of broken client principal failed: %s",
686 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
, ret
, mem_ctx
)));
689 nt_status
= kerberos_decode_pac(mem_ctx
,
692 smb_krb5_context
->krb5_context
,
697 if (NT_STATUS_IS_OK(nt_status
)) {
698 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
700 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
702 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on modified principal");
705 /* Finally... Bugger up the signature, and check we fail the checksum */
706 tmp_blob
.data
[tmp_blob
.length
- 2]++;
708 nt_status
= kerberos_decode_pac(mem_ctx
,
711 smb_krb5_context
->krb5_context
,
716 if (NT_STATUS_IS_OK(nt_status
)) {
717 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
719 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
721 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on broken checksum");
724 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
726 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
731 struct torture_suite
*torture_pac(TALLOC_CTX
*mem_ctx
)
733 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "PAC");
735 torture_suite_add_simple_test(suite
, "self check",
736 torture_pac_self_check
);
737 torture_suite_add_simple_test(suite
, "saved check",
738 torture_pac_saved_check
);