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"
32 #include "librpc/gen_ndr/ndr_krb5pac.h"
33 #include "torture/auth/proto.h"
35 static bool torture_pac_self_check(struct torture_context *tctx)
39 struct PAC_DATA *pac_data;
40 struct PAC_LOGON_INFO *logon_info;
41 union netr_Validation validation;
43 /* Generate a nice, arbitary keyblock */
44 uint8_t server_bytes[16];
45 uint8_t krbtgt_bytes[16];
46 krb5_keyblock server_keyblock;
47 krb5_keyblock krbtgt_keyblock;
51 struct smb_krb5_context *smb_krb5_context;
53 struct auth_user_info_dc *user_info_dc;
54 struct auth_user_info_dc *user_info_dc_out;
56 krb5_principal client_principal;
57 time_t logon_time = time(NULL);
59 TALLOC_CTX *mem_ctx = tctx;
61 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx,
65 "smb_krb5_init_context");
67 generate_random_buffer(server_bytes, 16);
68 generate_random_buffer(krbtgt_bytes, 16);
70 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
72 server_bytes, sizeof(server_bytes),
74 torture_assert(tctx, !ret, talloc_asprintf(tctx,
75 "(self test) Server Keyblock encoding failed: %s",
76 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
79 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
81 krbtgt_bytes, sizeof(krbtgt_bytes),
84 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
87 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
90 torture_fail(tctx, talloc_asprintf(tctx,
91 "(self test) KRBTGT Keyblock encoding failed: %s", err));
94 /* We need an input, and this one requires no underlying database */
95 nt_status = auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &user_info_dc);
97 if (!NT_STATUS_IS_OK(nt_status)) {
98 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
100 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
102 torture_fail(tctx, "auth_anonymous_user_info_dc");
105 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
106 user_info_dc->info->account_name,
107 KRB5_PRINCIPAL_PARSE_NO_REALM,
110 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
112 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
114 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
117 /* OK, go ahead and make a PAC */
118 ret = kerberos_create_pac(mem_ctx,
120 smb_krb5_context->krb5_context,
128 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
130 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
132 krb5_free_principal(smb_krb5_context->krb5_context,
135 torture_fail(tctx, talloc_asprintf(tctx,
136 "(self test) PAC encoding failed: %s",
137 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
141 dump_data(10,tmp_blob.data,tmp_blob.length);
143 /* Now check that we can read it back (using full decode and validate) */
144 nt_status = kerberos_decode_pac(mem_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 we can read it back (using Heimdal's pac parsing) */
167 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
169 smb_krb5_context->krb5_context,
170 &user_info_dc_out, NULL, NULL);
172 /* The user's SID is the first element in the list */
173 if (!dom_sid_equal(user_info_dc->sids,
174 user_info_dc_out->sids)) {
175 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
177 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
179 krb5_free_principal(smb_krb5_context->krb5_context,
183 talloc_asprintf(tctx,
184 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
185 dom_sid_string(mem_ctx, user_info_dc->sids),
186 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
188 talloc_free(user_info_dc_out);
190 /* Now check that we can read it back (yet again) */
191 nt_status = kerberos_pac_logon_info(mem_ctx,
194 smb_krb5_context->krb5_context,
201 if (!NT_STATUS_IS_OK(nt_status)) {
202 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
204 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
206 krb5_free_principal(smb_krb5_context->krb5_context,
210 talloc_asprintf(tctx,
211 "(self test) PAC decoding (for logon info) failed: %s",
212 nt_errstr(nt_status)));
215 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
217 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
219 krb5_free_principal(smb_krb5_context->krb5_context,
222 /* And make a server info from the samba-parsed PAC */
223 validation.sam3 = &logon_info->info3;
224 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
228 if (!NT_STATUS_IS_OK(nt_status)) {
230 talloc_asprintf(tctx,
231 "(self test) PAC decoding (make server info) failed: %s",
232 nt_errstr(nt_status)));
235 if (!dom_sid_equal(user_info_dc->sids,
236 user_info_dc_out->sids)) {
238 talloc_asprintf(tctx,
239 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
240 dom_sid_string(mem_ctx, user_info_dc->sids),
241 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
247 /* This is the PAC generated on my test network, by my test Win2k3 server.
248 -- abartlet 2005-07-04
251 static const uint8_t saved_pac[] = {
252 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
253 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
254 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
255 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
256 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
257 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
258 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
259 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
260 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
261 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
264 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
265 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
267 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
272 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
273 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
278 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
279 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
280 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
281 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
282 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
283 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
284 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
285 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
287 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
288 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
289 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
290 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
293 /* Check with a known 'well formed' PAC, from my test server */
294 static bool torture_pac_saved_check(struct torture_context *tctx)
297 enum ndr_err_code ndr_err;
298 DATA_BLOB tmp_blob, validate_blob;
299 struct PAC_DATA *pac_data, pac_data2;
300 struct PAC_LOGON_INFO *logon_info;
301 union netr_Validation validation;
302 const char *pac_file, *pac_kdc_key, *pac_member_key;
303 struct auth_user_info_dc *user_info_dc_out;
305 krb5_keyblock server_keyblock;
306 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
307 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
310 struct smb_krb5_context *smb_krb5_context;
312 const char *principal_string;
313 char *broken_principal_string;
314 krb5_principal client_principal;
315 const char *authtime_string;
317 TALLOC_CTX *mem_ctx = tctx;
319 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
322 "smb_krb5_init_context");
324 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
325 "B286757148AF7FD252C53603A150B7E7");
327 pac_member_key = torture_setting_string(tctx, "pac_member_key",
328 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
330 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
331 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
333 /* The krbtgt key in use when the above PAC was generated.
334 * This is an arcfour-hmac-md5 key, extracted with our 'net
336 if (*pac_kdc_key == 0) {
339 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
341 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
345 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
347 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
350 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
351 ENCTYPE_ARCFOUR_HMAC,
352 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
354 torture_assert(tctx, !ret,
355 talloc_asprintf(tctx,
356 "(saved test) Server Keyblock encoding failed: %s",
357 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
361 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
362 ENCTYPE_ARCFOUR_HMAC,
363 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
366 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
369 talloc_asprintf(tctx,
370 "(saved test) Server Keyblock encoding failed: %s",
371 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
374 krbtgt_keyblock_p = &krbtgt_keyblock;
376 krbtgt_keyblock_p = NULL;
379 pac_file = torture_setting_string(tctx, "pac_file", NULL);
381 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
382 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
384 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
387 dump_data(10,tmp_blob.data,tmp_blob.length);
389 principal_string = torture_setting_string(tctx, "pac_client_principal",
390 "w2003final$@WIN2K3.THINKER.LOCAL");
392 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
393 authtime = strtoull(authtime_string, NULL, 0);
395 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
398 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
400 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
403 talloc_asprintf(tctx,
404 "(saved test) parsing of client principal [%s] failed: %s",
406 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
409 /* Decode and verify the signaure on the PAC */
410 nt_status = kerberos_decode_pac(mem_ctx,
413 smb_krb5_context->krb5_context,
416 client_principal, authtime, NULL);
417 if (!NT_STATUS_IS_OK(nt_status)) {
418 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
420 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
422 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
424 torture_fail(tctx, talloc_asprintf(tctx,
425 "(saved test) PAC decoding failed: %s",
426 nt_errstr(nt_status)));
429 /* Now check we can read it back (using Heimdal's pac parsing) */
430 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
432 smb_krb5_context->krb5_context,
436 if (!NT_STATUS_IS_OK(nt_status)) {
437 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
439 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
441 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
443 torture_fail(tctx, talloc_asprintf(tctx,
444 "(saved test) Heimdal PAC decoding failed: %s",
445 nt_errstr(nt_status)));
449 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
450 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
451 user_info_dc_out->sids)) {
452 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
454 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
456 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
459 talloc_asprintf(tctx,
460 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
461 "S-1-5-21-3048156945-3961193616-3706469200-1005",
462 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
465 talloc_free(user_info_dc_out);
467 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
468 nt_status = kerberos_pac_logon_info(mem_ctx,
471 smb_krb5_context->krb5_context,
474 client_principal, authtime, NULL);
476 if (!NT_STATUS_IS_OK(nt_status)) {
477 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
479 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
481 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
484 talloc_asprintf(tctx,
485 "(saved test) PAC decoding (for logon info) failed: %s",
486 nt_errstr(nt_status)));
489 validation.sam3 = &logon_info->info3;
490 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
494 if (!NT_STATUS_IS_OK(nt_status)) {
495 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
497 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
499 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
502 talloc_asprintf(tctx,
503 "(saved test) PAC decoding (make server info) failed: %s",
504 nt_errstr(nt_status)));
508 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
509 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
510 user_info_dc_out->sids)) {
511 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
513 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
515 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
518 talloc_asprintf(tctx,
519 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
520 "S-1-5-21-3048156945-3961193616-3706469200-1005",
521 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
524 if (krbtgt_bytes == NULL) {
525 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
526 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
528 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
532 ret = kerberos_encode_pac(mem_ctx,
534 smb_krb5_context->krb5_context,
540 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
542 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
544 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
546 torture_fail(tctx, "(saved test) PAC push failed");
549 dump_data(10, validate_blob.data, validate_blob.length);
551 /* compare both the length and the data bytes after a
552 * pull/push cycle. This ensures we use the exact same
553 * pointer, padding etc algorithms as win2k3.
555 if (tmp_blob.length != validate_blob.length) {
556 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
558 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
560 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
563 talloc_asprintf(tctx,
564 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
565 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
568 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
569 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
571 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
573 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
575 DEBUG(0, ("tmp_data:\n"));
576 dump_data(0, tmp_blob.data, tmp_blob.length);
577 DEBUG(0, ("validate_blob:\n"));
578 dump_data(0, validate_blob.data, validate_blob.length);
580 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
583 ret = kerberos_create_pac(mem_ctx,
585 smb_krb5_context->krb5_context,
588 client_principal, authtime,
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);
598 torture_fail(tctx, "(saved test) regnerated PAC create failed");
601 dump_data(10,validate_blob.data,validate_blob.length);
603 /* compare both the length and the data bytes after a
604 * pull/push cycle. This ensures we use the exact same
605 * pointer, padding etc algorithms as win2k3.
607 if (tmp_blob.length != validate_blob.length) {
608 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
610 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
611 nt_status = ndr_map_error2ntstatus(ndr_err);
612 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
614 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
616 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
618 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
620 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
622 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
624 torture_fail(tctx, talloc_asprintf(tctx,
625 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
626 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
629 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
630 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
632 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
633 nt_status = ndr_map_error2ntstatus(ndr_err);
634 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
636 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
638 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
640 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
642 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
644 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
646 DEBUG(0, ("tmp_data:\n"));
647 dump_data(0, tmp_blob.data, tmp_blob.length);
648 DEBUG(0, ("validate_blob:\n"));
649 dump_data(0, validate_blob.data, validate_blob.length);
651 torture_fail(tctx, talloc_asprintf(tctx,
652 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
655 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
656 nt_status = kerberos_decode_pac(mem_ctx,
659 smb_krb5_context->krb5_context,
664 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 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
671 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
674 /* Break the client principal */
675 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
677 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
678 broken_principal_string[0]++;
680 ret = krb5_parse_name(smb_krb5_context->krb5_context,
681 broken_principal_string, &client_principal);
684 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
686 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
688 torture_fail(tctx, talloc_asprintf(tctx,
689 "(saved test) parsing of broken client principal failed: %s",
690 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
693 nt_status = kerberos_decode_pac(mem_ctx,
696 smb_krb5_context->krb5_context,
701 if (NT_STATUS_IS_OK(nt_status)) {
702 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
704 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
706 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
709 /* Finally... Bugger up the signature, and check we fail the checksum */
710 tmp_blob.data[tmp_blob.length - 2]++;
712 nt_status = kerberos_decode_pac(mem_ctx,
715 smb_krb5_context->krb5_context,
720 if (NT_STATUS_IS_OK(nt_status)) {
721 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
723 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
725 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
728 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
730 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
735 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
737 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
739 torture_suite_add_simple_test(suite, "self check",
740 torture_pac_self_check);
741 torture_suite_add_simple_test(suite, "saved check",
742 torture_pac_saved_check);