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,
146 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,
193 smb_krb5_context->krb5_context,
200 if (!NT_STATUS_IS_OK(nt_status)) {
201 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
203 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
205 krb5_free_principal(smb_krb5_context->krb5_context,
209 talloc_asprintf(tctx,
210 "(self test) PAC decoding (for logon info) failed: %s",
211 nt_errstr(nt_status)));
214 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
216 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
218 krb5_free_principal(smb_krb5_context->krb5_context,
221 /* And make a server info from the samba-parsed PAC */
222 validation.sam3 = &logon_info->info3;
223 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
227 if (!NT_STATUS_IS_OK(nt_status)) {
229 talloc_asprintf(tctx,
230 "(self test) PAC decoding (make server info) failed: %s",
231 nt_errstr(nt_status)));
234 if (!dom_sid_equal(user_info_dc->sids,
235 user_info_dc_out->sids)) {
237 talloc_asprintf(tctx,
238 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
239 dom_sid_string(mem_ctx, user_info_dc->sids),
240 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
246 /* This is the PAC generated on my test network, by my test Win2k3 server.
247 -- abartlet 2005-07-04
250 static const uint8_t saved_pac[] = {
251 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
252 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
253 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
254 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
255 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
256 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
257 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
258 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
259 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
260 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
263 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
264 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
266 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
271 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
272 0x41, 0x00, 0x4c, 0x00, 0x24, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
277 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
278 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
279 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
280 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
281 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
282 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
283 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
284 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
286 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
287 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
288 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
289 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
292 /* Check with a known 'well formed' PAC, from my test server */
293 static bool torture_pac_saved_check(struct torture_context *tctx)
296 enum ndr_err_code ndr_err;
297 DATA_BLOB tmp_blob, validate_blob;
298 struct PAC_DATA *pac_data, pac_data2;
299 struct PAC_LOGON_INFO *logon_info;
300 union netr_Validation validation;
301 const char *pac_file, *pac_kdc_key, *pac_member_key;
302 struct auth_user_info_dc *user_info_dc_out;
304 krb5_keyblock server_keyblock;
305 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
306 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
309 struct smb_krb5_context *smb_krb5_context;
311 const char *principal_string;
312 char *broken_principal_string;
313 krb5_principal client_principal;
314 const char *authtime_string;
316 TALLOC_CTX *mem_ctx = tctx;
318 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
321 "smb_krb5_init_context");
323 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
324 "B286757148AF7FD252C53603A150B7E7");
326 pac_member_key = torture_setting_string(tctx, "pac_member_key",
327 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
329 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
330 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
332 /* The krbtgt key in use when the above PAC was generated.
333 * This is an arcfour-hmac-md5 key, extracted with our 'net
335 if (*pac_kdc_key == 0) {
338 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
340 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
344 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
346 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
349 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
350 ENCTYPE_ARCFOUR_HMAC,
351 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
353 torture_assert(tctx, !ret,
354 talloc_asprintf(tctx,
355 "(saved test) Server Keyblock encoding failed: %s",
356 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
360 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
361 ENCTYPE_ARCFOUR_HMAC,
362 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
365 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
368 talloc_asprintf(tctx,
369 "(saved test) Server Keyblock encoding failed: %s",
370 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
373 krbtgt_keyblock_p = &krbtgt_keyblock;
375 krbtgt_keyblock_p = NULL;
378 pac_file = torture_setting_string(tctx, "pac_file", NULL);
380 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
381 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
383 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
386 dump_data(10,tmp_blob.data,tmp_blob.length);
388 principal_string = torture_setting_string(tctx, "pac_client_principal",
389 "w2003final$@WIN2K3.THINKER.LOCAL");
391 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
392 authtime = strtoull(authtime_string, NULL, 0);
394 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
397 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
399 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
402 talloc_asprintf(tctx,
403 "(saved test) parsing of client principal [%s] failed: %s",
405 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
408 /* Decode and verify the signaure on the PAC */
409 nt_status = kerberos_decode_pac(mem_ctx,
411 smb_krb5_context->krb5_context,
414 client_principal, authtime, &pac_data);
415 if (!NT_STATUS_IS_OK(nt_status)) {
416 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
418 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
420 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
422 torture_fail(tctx, talloc_asprintf(tctx,
423 "(saved test) PAC decoding failed: %s",
424 nt_errstr(nt_status)));
427 /* Now check we can read it back (using Heimdal's pac parsing) */
428 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
430 smb_krb5_context->krb5_context,
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);
441 torture_fail(tctx, talloc_asprintf(tctx,
442 "(saved test) Heimdal PAC decoding failed: %s",
443 nt_errstr(nt_status)));
447 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
448 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
449 user_info_dc_out->sids)) {
450 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
452 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
454 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
457 talloc_asprintf(tctx,
458 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
459 "S-1-5-21-3048156945-3961193616-3706469200-1005",
460 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
463 talloc_free(user_info_dc_out);
465 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
466 nt_status = kerberos_pac_logon_info(mem_ctx,
468 smb_krb5_context->krb5_context,
471 client_principal, authtime, &logon_info);
473 if (!NT_STATUS_IS_OK(nt_status)) {
474 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
476 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
478 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
481 talloc_asprintf(tctx,
482 "(saved test) PAC decoding (for logon info) failed: %s",
483 nt_errstr(nt_status)));
486 validation.sam3 = &logon_info->info3;
487 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
491 if (!NT_STATUS_IS_OK(nt_status)) {
492 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
494 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
496 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
499 talloc_asprintf(tctx,
500 "(saved test) PAC decoding (make server info) failed: %s",
501 nt_errstr(nt_status)));
505 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
506 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
507 user_info_dc_out->sids)) {
508 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
510 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
512 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
515 talloc_asprintf(tctx,
516 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
517 "S-1-5-21-3048156945-3961193616-3706469200-1005",
518 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
521 if (krbtgt_bytes == NULL) {
522 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
523 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
525 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
529 ret = kerberos_encode_pac(mem_ctx,
531 smb_krb5_context->krb5_context,
537 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
539 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
541 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
543 torture_fail(tctx, "(saved test) PAC push failed");
546 dump_data(10, validate_blob.data, validate_blob.length);
548 /* compare both the length and the data bytes after a
549 * pull/push cycle. This ensures we use the exact same
550 * pointer, padding etc algorithms as win2k3.
552 if (tmp_blob.length != validate_blob.length) {
553 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
555 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
557 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
560 talloc_asprintf(tctx,
561 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
562 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
565 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
566 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
568 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
570 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
572 DEBUG(0, ("tmp_data:\n"));
573 dump_data(0, tmp_blob.data, tmp_blob.length);
574 DEBUG(0, ("validate_blob:\n"));
575 dump_data(0, validate_blob.data, validate_blob.length);
577 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
580 ret = kerberos_create_pac(mem_ctx,
582 smb_krb5_context->krb5_context,
585 client_principal, authtime,
589 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
591 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
593 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
595 torture_fail(tctx, "(saved test) regnerated PAC create failed");
598 dump_data(10,validate_blob.data,validate_blob.length);
600 /* compare both the length and the data bytes after a
601 * pull/push cycle. This ensures we use the exact same
602 * pointer, padding etc algorithms as win2k3.
604 if (tmp_blob.length != validate_blob.length) {
605 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
607 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
608 nt_status = ndr_map_error2ntstatus(ndr_err);
609 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
611 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
613 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
615 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
617 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
619 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
621 torture_fail(tctx, talloc_asprintf(tctx,
622 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
623 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
626 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
627 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
629 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
630 nt_status = ndr_map_error2ntstatus(ndr_err);
631 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
633 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
635 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
637 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
639 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
641 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
643 DEBUG(0, ("tmp_data:\n"));
644 dump_data(0, tmp_blob.data, tmp_blob.length);
645 DEBUG(0, ("validate_blob:\n"));
646 dump_data(0, validate_blob.data, validate_blob.length);
648 torture_fail(tctx, talloc_asprintf(tctx,
649 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
652 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
653 nt_status = kerberos_decode_pac(mem_ctx,
655 smb_krb5_context->krb5_context,
659 authtime + 1, &pac_data);
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,
691 smb_krb5_context->krb5_context,
695 authtime, &pac_data);
696 if (NT_STATUS_IS_OK(nt_status)) {
697 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
699 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
701 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
704 /* Finally... Bugger up the signature, and check we fail the checksum */
705 tmp_blob.data[tmp_blob.length - 2]++;
707 nt_status = kerberos_decode_pac(mem_ctx,
709 smb_krb5_context->krb5_context,
715 if (NT_STATUS_IS_OK(nt_status)) {
716 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
718 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
720 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
723 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
725 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
730 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
732 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
734 torture_suite_add_simple_test(suite, "self check",
735 torture_pac_self_check);
736 torture_suite_add_simple_test(suite, "saved check",
737 torture_pac_saved_check);