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 "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "samba3/samba3.h"
29 #include "libcli/security/security.h"
30 #include "torture/torture.h"
31 #include "auth/session_proto.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, lp_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,
117 lp_iconv_convenience(tctx->lp_ctx),
119 smb_krb5_context->krb5_context,
127 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
129 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
131 krb5_free_principal(smb_krb5_context->krb5_context,
134 torture_fail(tctx, talloc_asprintf(tctx,
135 "(self test) PAC encoding failed: %s",
136 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
140 dump_data(10,tmp_blob.data,tmp_blob.length);
142 /* Now check that we can read it back */
143 nt_status = kerberos_decode_pac(mem_ctx,
144 lp_iconv_convenience(tctx->lp_ctx),
147 smb_krb5_context->krb5_context,
153 if (!NT_STATUS_IS_OK(nt_status)) {
154 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
156 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
158 krb5_free_principal(smb_krb5_context->krb5_context,
161 torture_fail(tctx, talloc_asprintf(tctx,
162 "(self test) PAC decoding failed: %s",
163 nt_errstr(nt_status)));
166 /* Now check that we can read it back */
167 nt_status = kerberos_pac_logon_info(mem_ctx,
168 lp_iconv_convenience(tctx->lp_ctx),
171 smb_krb5_context->krb5_context,
178 if (!NT_STATUS_IS_OK(nt_status)) {
179 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
181 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
183 krb5_free_principal(smb_krb5_context->krb5_context,
187 talloc_asprintf(tctx,
188 "(self test) PAC decoding (for logon info) failed: %s",
189 nt_errstr(nt_status)));
192 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
194 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
196 krb5_free_principal(smb_krb5_context->krb5_context,
199 validation.sam3 = &logon_info->info3;
200 nt_status = make_server_info_netlogon_validation(mem_ctx,
204 if (!NT_STATUS_IS_OK(nt_status)) {
206 talloc_asprintf(tctx,
207 "(self test) PAC decoding (make server info) failed: %s",
208 nt_errstr(nt_status)));
211 if (!dom_sid_equal(server_info->account_sid,
212 server_info_out->account_sid)) {
214 talloc_asprintf(tctx,
215 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
216 dom_sid_string(mem_ctx, server_info->account_sid),
217 dom_sid_string(mem_ctx, server_info_out->account_sid)));
223 /* This is the PAC generated on my test network, by my test Win2k3 server.
224 -- abartlet 2005-07-04
227 static const uint8_t saved_pac[] = {
228 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
229 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
230 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
231 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
232 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
233 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
234 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
235 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
236 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
237 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
240 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
241 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
243 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
248 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
249 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
254 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
255 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
256 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
257 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
258 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
259 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
260 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
261 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
263 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
264 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
265 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
266 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
269 /* Check with a known 'well formed' PAC, from my test server */
270 static bool torture_pac_saved_check(struct torture_context *tctx)
273 enum ndr_err_code ndr_err;
274 DATA_BLOB tmp_blob, validate_blob;
275 struct PAC_DATA *pac_data, pac_data2;
276 struct PAC_LOGON_INFO *logon_info;
277 union netr_Validation validation;
278 const char *pac_file, *pac_kdc_key, *pac_member_key;
279 struct auth_serversupplied_info *server_info_out;
281 krb5_keyblock server_keyblock;
282 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
283 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
286 struct smb_krb5_context *smb_krb5_context;
288 const char *principal_string;
289 char *broken_principal_string;
290 krb5_principal client_principal;
291 const char *authtime_string;
293 TALLOC_CTX *mem_ctx = tctx;
295 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
298 "smb_krb5_init_context");
300 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
301 "B286757148AF7FD252C53603A150B7E7");
303 pac_member_key = torture_setting_string(tctx, "pac_member_key",
304 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
306 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
307 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
309 /* The krbtgt key in use when the above PAC was generated.
310 * This is an arcfour-hmac-md5 key, extracted with our 'net
312 if (*pac_kdc_key == 0) {
315 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
317 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
321 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
323 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
326 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
327 ENCTYPE_ARCFOUR_HMAC,
328 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
330 torture_assert(tctx, !ret,
331 talloc_asprintf(tctx,
332 "(saved test) Server Keyblock encoding failed: %s",
333 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
337 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
338 ENCTYPE_ARCFOUR_HMAC,
339 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
342 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
345 talloc_asprintf(tctx,
346 "(saved test) Server Keyblock encoding failed: %s",
347 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
350 krbtgt_keyblock_p = &krbtgt_keyblock;
352 krbtgt_keyblock_p = NULL;
355 pac_file = torture_setting_string(tctx, "pac_file", NULL);
357 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
358 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
360 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
363 dump_data(10,tmp_blob.data,tmp_blob.length);
365 principal_string = torture_setting_string(tctx, "pac_client_principal",
366 "w2003final$@WIN2K3.THINKER.LOCAL");
368 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
369 authtime = strtoull(authtime_string, NULL, 0);
371 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
374 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
376 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
379 talloc_asprintf(tctx,
380 "(saved test) parsing of client principal [%s] failed: %s",
382 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
385 /* Decode and verify the signaure on the PAC */
386 nt_status = kerberos_decode_pac(mem_ctx,
387 lp_iconv_convenience(tctx->lp_ctx),
390 smb_krb5_context->krb5_context,
393 client_principal, authtime, NULL);
394 if (!NT_STATUS_IS_OK(nt_status)) {
395 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
397 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
399 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
401 torture_fail(tctx, talloc_asprintf(tctx,
402 "(saved test) PAC decoding failed: %s",
403 nt_errstr(nt_status)));
406 /* Parse the PAC again, for the logon info this time */
407 nt_status = kerberos_pac_logon_info(mem_ctx,
408 lp_iconv_convenience(tctx->lp_ctx),
411 smb_krb5_context->krb5_context,
414 client_principal, authtime, NULL);
416 if (!NT_STATUS_IS_OK(nt_status)) {
417 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
419 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
421 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
424 talloc_asprintf(tctx,
425 "(saved test) PAC decoding (for logon info) failed: %s",
426 nt_errstr(nt_status)));
429 validation.sam3 = &logon_info->info3;
430 nt_status = make_server_info_netlogon_validation(mem_ctx,
434 if (!NT_STATUS_IS_OK(nt_status)) {
435 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
437 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
439 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
442 talloc_asprintf(tctx,
443 "(saved test) PAC decoding (make server info) failed: %s",
444 nt_errstr(nt_status)));
448 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
449 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
450 server_info_out->account_sid)) {
451 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
453 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
455 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
458 talloc_asprintf(tctx,
459 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
460 "S-1-5-21-3048156945-3961193616-3706469200-1005",
461 dom_sid_string(mem_ctx, server_info_out->account_sid)));
464 if (krbtgt_bytes == NULL) {
465 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
466 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
468 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
472 ret = kerberos_encode_pac(mem_ctx,
473 lp_iconv_convenience(tctx->lp_ctx),
475 smb_krb5_context->krb5_context,
481 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
483 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
485 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
487 torture_fail(tctx, "(saved test) PAC push failed");
490 dump_data(10, validate_blob.data, validate_blob.length);
492 /* compare both the length and the data bytes after a
493 * pull/push cycle. This ensures we use the exact same
494 * pointer, padding etc algorithms as win2k3.
496 if (tmp_blob.length != validate_blob.length) {
497 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
499 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
501 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
504 talloc_asprintf(tctx,
505 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
506 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
509 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
510 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
512 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
514 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
516 DEBUG(0, ("tmp_data:\n"));
517 dump_data(0, tmp_blob.data, tmp_blob.length);
518 DEBUG(0, ("validate_blob:\n"));
519 dump_data(0, validate_blob.data, validate_blob.length);
521 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
524 ret = kerberos_create_pac(mem_ctx,
525 lp_iconv_convenience(tctx->lp_ctx),
527 smb_krb5_context->krb5_context,
530 client_principal, authtime,
534 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
536 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
538 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
540 torture_fail(tctx, "(saved test) regnerated PAC create failed");
543 dump_data(10,validate_blob.data,validate_blob.length);
545 /* compare both the length and the data bytes after a
546 * pull/push cycle. This ensures we use the exact same
547 * pointer, padding etc algorithms as win2k3.
549 if (tmp_blob.length != validate_blob.length) {
550 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
551 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
552 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
553 nt_status = ndr_map_error2ntstatus(ndr_err);
554 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
556 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
558 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
560 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
562 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
564 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
566 torture_fail(tctx, talloc_asprintf(tctx,
567 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
568 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
571 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
572 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
573 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
574 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
575 nt_status = ndr_map_error2ntstatus(ndr_err);
576 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
578 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
580 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
582 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
584 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
586 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
588 DEBUG(0, ("tmp_data:\n"));
589 dump_data(0, tmp_blob.data, tmp_blob.length);
590 DEBUG(0, ("validate_blob:\n"));
591 dump_data(0, validate_blob.data, validate_blob.length);
593 torture_fail(tctx, talloc_asprintf(tctx,
594 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
597 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
598 nt_status = kerberos_decode_pac(mem_ctx,
599 lp_iconv_convenience(tctx->lp_ctx),
602 smb_krb5_context->krb5_context,
607 if (NT_STATUS_IS_OK(nt_status)) {
609 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
611 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
613 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
614 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
617 /* Break the client principal */
618 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
620 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
621 broken_principal_string[0]++;
623 ret = krb5_parse_name(smb_krb5_context->krb5_context,
624 broken_principal_string, &client_principal);
627 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
629 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
631 torture_fail(tctx, talloc_asprintf(tctx,
632 "(saved test) parsing of broken client principal failed: %s",
633 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
636 nt_status = kerberos_decode_pac(mem_ctx,
637 lp_iconv_convenience(tctx->lp_ctx),
640 smb_krb5_context->krb5_context,
645 if (NT_STATUS_IS_OK(nt_status)) {
646 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
648 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
650 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
653 /* Finally... Bugger up the signature, and check we fail the checksum */
654 tmp_blob.data[tmp_blob.length - 2]++;
656 nt_status = kerberos_decode_pac(mem_ctx,
657 lp_iconv_convenience(tctx->lp_ctx),
660 smb_krb5_context->krb5_context,
665 if (NT_STATUS_IS_OK(nt_status)) {
666 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
668 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
670 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
673 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
675 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
680 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
682 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
684 torture_suite_add_simple_test(suite, "self check",
685 torture_pac_self_check);
686 torture_suite_add_simple_test(suite, "saved check",
687 torture_pac_saved_check);