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;
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 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
314 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
317 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
319 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
322 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
323 ENCTYPE_ARCFOUR_HMAC,
324 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
326 torture_assert(tctx, !ret,
327 talloc_asprintf(tctx,
328 "(saved test) Server Keyblock encoding failed: %s",
329 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
332 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
333 ENCTYPE_ARCFOUR_HMAC,
334 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
337 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
340 talloc_asprintf(tctx,
341 "(saved test) Server Keyblock encoding failed: %s",
342 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
346 pac_file = torture_setting_string(tctx, "pac_file", NULL);
348 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
349 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
351 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
354 dump_data(10,tmp_blob.data,tmp_blob.length);
356 principal_string = torture_setting_string(tctx, "pac_client_principal",
357 "w2003final$@WIN2K3.THINKER.LOCAL");
359 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
360 authtime = strtoull(authtime_string, NULL, 0);
362 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
365 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
367 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
370 talloc_asprintf(tctx,
371 "(saved test) parsing of client principal [%s] failed: %s",
373 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
376 /* Decode and verify the signaure on the PAC */
377 nt_status = kerberos_decode_pac(mem_ctx,
378 lp_iconv_convenience(tctx->lp_ctx),
381 smb_krb5_context->krb5_context,
384 client_principal, authtime, NULL);
385 if (!NT_STATUS_IS_OK(nt_status)) {
386 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
388 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
390 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
392 torture_fail(tctx, talloc_asprintf(tctx,
393 "(saved test) PAC decoding failed: %s",
394 nt_errstr(nt_status)));
397 /* Parse the PAC again, for the logon info this time */
398 nt_status = kerberos_pac_logon_info(mem_ctx,
399 lp_iconv_convenience(tctx->lp_ctx),
402 smb_krb5_context->krb5_context,
405 client_principal, authtime, NULL);
407 if (!NT_STATUS_IS_OK(nt_status)) {
408 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
410 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
412 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
415 talloc_asprintf(tctx,
416 "(saved test) PAC decoding (for logon info) failed: %s",
417 nt_errstr(nt_status)));
420 validation.sam3 = &logon_info->info3;
421 nt_status = make_server_info_netlogon_validation(mem_ctx,
425 if (!NT_STATUS_IS_OK(nt_status)) {
426 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
428 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
430 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
433 talloc_asprintf(tctx,
434 "(saved test) PAC decoding (make server info) failed: %s",
435 nt_errstr(nt_status)));
439 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
440 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
441 server_info_out->account_sid)) {
442 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
444 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
446 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
449 talloc_asprintf(tctx,
450 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
451 "S-1-5-21-3048156945-3961193616-3706469200-1005",
452 dom_sid_string(mem_ctx, server_info_out->account_sid)));
455 ret = kerberos_encode_pac(mem_ctx,
456 lp_iconv_convenience(tctx->lp_ctx),
458 smb_krb5_context->krb5_context,
464 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
466 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
468 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
470 torture_fail(tctx, "(saved test) PAC push failed");
473 dump_data(10, validate_blob.data, validate_blob.length);
475 /* compare both the length and the data bytes after a
476 * pull/push cycle. This ensures we use the exact same
477 * pointer, padding etc algorithms as win2k3.
479 if (tmp_blob.length != validate_blob.length) {
480 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
482 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
484 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
487 talloc_asprintf(tctx,
488 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
489 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
492 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
493 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
495 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
497 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
499 DEBUG(0, ("tmp_data:\n"));
500 dump_data(0, tmp_blob.data, tmp_blob.length);
501 DEBUG(0, ("validate_blob:\n"));
502 dump_data(0, validate_blob.data, validate_blob.length);
504 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
507 ret = kerberos_create_pac(mem_ctx,
508 lp_iconv_convenience(tctx->lp_ctx),
510 smb_krb5_context->krb5_context,
513 client_principal, authtime,
517 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
519 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
521 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
523 torture_fail(tctx, "(saved test) regnerated PAC create failed");
526 dump_data(10,validate_blob.data,validate_blob.length);
528 /* compare both the length and the data bytes after a
529 * pull/push cycle. This ensures we use the exact same
530 * pointer, padding etc algorithms as win2k3.
532 if (tmp_blob.length != validate_blob.length) {
533 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
534 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
535 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
536 nt_status = ndr_map_error2ntstatus(ndr_err);
537 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
539 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
541 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
543 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
545 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
547 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
549 torture_fail(tctx, talloc_asprintf(tctx,
550 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
551 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
554 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
555 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
556 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
557 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
558 nt_status = ndr_map_error2ntstatus(ndr_err);
559 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
561 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
563 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
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,
577 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
580 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
581 nt_status = kerberos_decode_pac(mem_ctx,
582 lp_iconv_convenience(tctx->lp_ctx),
585 smb_krb5_context->krb5_context,
590 if (NT_STATUS_IS_OK(nt_status)) {
592 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
594 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
596 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
597 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
600 /* Break the client principal */
601 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
603 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
604 broken_principal_string[0]++;
606 ret = krb5_parse_name(smb_krb5_context->krb5_context,
607 broken_principal_string, &client_principal);
610 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
612 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
614 torture_fail(tctx, talloc_asprintf(tctx,
615 "(saved test) parsing of broken client principal failed: %s",
616 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
619 nt_status = kerberos_decode_pac(mem_ctx,
620 lp_iconv_convenience(tctx->lp_ctx),
623 smb_krb5_context->krb5_context,
628 if (NT_STATUS_IS_OK(nt_status)) {
629 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
631 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
633 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
636 /* Finally... Bugger up the signature, and check we fail the checksum */
637 tmp_blob.data[tmp_blob.length - 2]++;
639 nt_status = kerberos_decode_pac(mem_ctx,
640 lp_iconv_convenience(tctx->lp_ctx),
643 smb_krb5_context->krb5_context,
648 if (NT_STATUS_IS_OK(nt_status)) {
649 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
651 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
653 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
656 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
658 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
663 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
665 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
667 torture_suite_add_simple_test(suite, "self check",
668 torture_pac_self_check);
670 torture_suite_add_simple_test(suite, "saved check",
671 torture_pac_saved_check);