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/auth_sam_reply.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 (using full decode and validate) */
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 we can read it back (using Heimdal's pac parsing) */
167 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
168 lp_iconv_convenience(tctx->lp_ctx),
170 smb_krb5_context->krb5_context,
173 if (!dom_sid_equal(server_info->account_sid,
174 server_info_out->account_sid)) {
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, server_info->account_sid),
186 dom_sid_string(mem_ctx, server_info_out->account_sid)));
188 talloc_free(server_info_out);
190 /* Now check that we can read it back (yet again) */
191 nt_status = kerberos_pac_logon_info(mem_ctx,
192 lp_iconv_convenience(tctx->lp_ctx),
195 smb_krb5_context->krb5_context,
202 if (!NT_STATUS_IS_OK(nt_status)) {
203 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
205 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
207 krb5_free_principal(smb_krb5_context->krb5_context,
211 talloc_asprintf(tctx,
212 "(self test) PAC decoding (for logon info) failed: %s",
213 nt_errstr(nt_status)));
216 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
218 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
220 krb5_free_principal(smb_krb5_context->krb5_context,
223 /* And make a server info from the samba-parsed PAC */
224 validation.sam3 = &logon_info->info3;
225 nt_status = make_server_info_netlogon_validation(mem_ctx,
229 if (!NT_STATUS_IS_OK(nt_status)) {
231 talloc_asprintf(tctx,
232 "(self test) PAC decoding (make server info) failed: %s",
233 nt_errstr(nt_status)));
236 if (!dom_sid_equal(server_info->account_sid,
237 server_info_out->account_sid)) {
239 talloc_asprintf(tctx,
240 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
241 dom_sid_string(mem_ctx, server_info->account_sid),
242 dom_sid_string(mem_ctx, server_info_out->account_sid)));
248 /* This is the PAC generated on my test network, by my test Win2k3 server.
249 -- abartlet 2005-07-04
252 static const uint8_t saved_pac[] = {
253 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
254 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
255 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
256 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
257 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
258 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
259 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
260 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
261 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
262 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
265 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
266 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
268 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
273 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
274 0x41, 0x00, 0x4c, 0x00, 0x24, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
279 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
280 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
281 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
282 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
283 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
284 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
285 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
286 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
288 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
289 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
290 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
291 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
294 /* Check with a known 'well formed' PAC, from my test server */
295 static bool torture_pac_saved_check(struct torture_context *tctx)
298 enum ndr_err_code ndr_err;
299 DATA_BLOB tmp_blob, validate_blob;
300 struct PAC_DATA *pac_data, pac_data2;
301 struct PAC_LOGON_INFO *logon_info;
302 union netr_Validation validation;
303 const char *pac_file, *pac_kdc_key, *pac_member_key;
304 struct auth_serversupplied_info *server_info_out;
306 krb5_keyblock server_keyblock;
307 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
308 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
311 struct smb_krb5_context *smb_krb5_context;
313 const char *principal_string;
314 char *broken_principal_string;
315 krb5_principal client_principal;
316 const char *authtime_string;
318 TALLOC_CTX *mem_ctx = tctx;
320 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
323 "smb_krb5_init_context");
325 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
326 "B286757148AF7FD252C53603A150B7E7");
328 pac_member_key = torture_setting_string(tctx, "pac_member_key",
329 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
331 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
332 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
334 /* The krbtgt key in use when the above PAC was generated.
335 * This is an arcfour-hmac-md5 key, extracted with our 'net
337 if (*pac_kdc_key == 0) {
340 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
342 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
346 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
348 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
351 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
352 ENCTYPE_ARCFOUR_HMAC,
353 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
355 torture_assert(tctx, !ret,
356 talloc_asprintf(tctx,
357 "(saved test) Server Keyblock encoding failed: %s",
358 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
362 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
363 ENCTYPE_ARCFOUR_HMAC,
364 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
367 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
370 talloc_asprintf(tctx,
371 "(saved test) Server Keyblock encoding failed: %s",
372 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
375 krbtgt_keyblock_p = &krbtgt_keyblock;
377 krbtgt_keyblock_p = NULL;
380 pac_file = torture_setting_string(tctx, "pac_file", NULL);
382 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
383 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
385 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
388 dump_data(10,tmp_blob.data,tmp_blob.length);
390 principal_string = torture_setting_string(tctx, "pac_client_principal",
391 "w2003final$@WIN2K3.THINKER.LOCAL");
393 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
394 authtime = strtoull(authtime_string, NULL, 0);
396 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
399 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
401 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
404 talloc_asprintf(tctx,
405 "(saved test) parsing of client principal [%s] failed: %s",
407 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
410 /* Decode and verify the signaure on the PAC */
411 nt_status = kerberos_decode_pac(mem_ctx,
412 lp_iconv_convenience(tctx->lp_ctx),
415 smb_krb5_context->krb5_context,
418 client_principal, authtime, NULL);
419 if (!NT_STATUS_IS_OK(nt_status)) {
420 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
422 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
424 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
426 torture_fail(tctx, talloc_asprintf(tctx,
427 "(saved test) PAC decoding failed: %s",
428 nt_errstr(nt_status)));
431 /* Now check we can read it back (using Heimdal's pac parsing) */
432 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
433 lp_iconv_convenience(tctx->lp_ctx),
435 smb_krb5_context->krb5_context,
438 if (!NT_STATUS_IS_OK(nt_status)) {
439 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
441 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
443 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
445 torture_fail(tctx, talloc_asprintf(tctx,
446 "(saved test) Heimdal PAC decoding failed: %s",
447 nt_errstr(nt_status)));
451 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
452 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
453 server_info_out->account_sid)) {
454 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
456 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
458 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
461 talloc_asprintf(tctx,
462 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
463 "S-1-5-21-3048156945-3961193616-3706469200-1005",
464 dom_sid_string(mem_ctx, server_info_out->account_sid)));
467 talloc_free(server_info_out);
469 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
470 nt_status = kerberos_pac_logon_info(mem_ctx,
471 lp_iconv_convenience(tctx->lp_ctx),
474 smb_krb5_context->krb5_context,
477 client_principal, authtime, NULL);
479 if (!NT_STATUS_IS_OK(nt_status)) {
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 decoding (for logon info) failed: %s",
489 nt_errstr(nt_status)));
492 validation.sam3 = &logon_info->info3;
493 nt_status = make_server_info_netlogon_validation(mem_ctx,
497 if (!NT_STATUS_IS_OK(nt_status)) {
498 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
500 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
502 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
505 talloc_asprintf(tctx,
506 "(saved test) PAC decoding (make server info) failed: %s",
507 nt_errstr(nt_status)));
511 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
512 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
513 server_info_out->account_sid)) {
514 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
516 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
518 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
521 talloc_asprintf(tctx,
522 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
523 "S-1-5-21-3048156945-3961193616-3706469200-1005",
524 dom_sid_string(mem_ctx, server_info_out->account_sid)));
527 if (krbtgt_bytes == NULL) {
528 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
529 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
531 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
535 ret = kerberos_encode_pac(mem_ctx,
536 lp_iconv_convenience(tctx->lp_ctx),
538 smb_krb5_context->krb5_context,
544 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
546 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
548 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
550 torture_fail(tctx, "(saved test) PAC push failed");
553 dump_data(10, validate_blob.data, validate_blob.length);
555 /* compare both the length and the data bytes after a
556 * pull/push cycle. This ensures we use the exact same
557 * pointer, padding etc algorithms as win2k3.
559 if (tmp_blob.length != validate_blob.length) {
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);
567 talloc_asprintf(tctx,
568 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
569 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
572 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
573 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
575 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
577 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
579 DEBUG(0, ("tmp_data:\n"));
580 dump_data(0, tmp_blob.data, tmp_blob.length);
581 DEBUG(0, ("validate_blob:\n"));
582 dump_data(0, validate_blob.data, validate_blob.length);
584 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
587 ret = kerberos_create_pac(mem_ctx,
588 lp_iconv_convenience(tctx->lp_ctx),
590 smb_krb5_context->krb5_context,
593 client_principal, authtime,
597 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
599 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
601 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
603 torture_fail(tctx, "(saved test) regnerated PAC create failed");
606 dump_data(10,validate_blob.data,validate_blob.length);
608 /* compare both the length and the data bytes after a
609 * pull/push cycle. This ensures we use the exact same
610 * pointer, padding etc algorithms as win2k3.
612 if (tmp_blob.length != validate_blob.length) {
613 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
614 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
615 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
616 nt_status = ndr_map_error2ntstatus(ndr_err);
617 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
619 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
621 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
623 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
625 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
627 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
629 torture_fail(tctx, talloc_asprintf(tctx,
630 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
631 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
634 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
635 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
636 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
637 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
638 nt_status = ndr_map_error2ntstatus(ndr_err);
639 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
641 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
643 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
645 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
647 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
649 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
651 DEBUG(0, ("tmp_data:\n"));
652 dump_data(0, tmp_blob.data, tmp_blob.length);
653 DEBUG(0, ("validate_blob:\n"));
654 dump_data(0, validate_blob.data, validate_blob.length);
656 torture_fail(tctx, talloc_asprintf(tctx,
657 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
660 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
661 nt_status = kerberos_decode_pac(mem_ctx,
662 lp_iconv_convenience(tctx->lp_ctx),
665 smb_krb5_context->krb5_context,
670 if (NT_STATUS_IS_OK(nt_status)) {
672 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
674 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
676 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
677 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
680 /* Break the client principal */
681 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
683 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
684 broken_principal_string[0]++;
686 ret = krb5_parse_name(smb_krb5_context->krb5_context,
687 broken_principal_string, &client_principal);
690 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
692 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
694 torture_fail(tctx, talloc_asprintf(tctx,
695 "(saved test) parsing of broken client principal failed: %s",
696 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
699 nt_status = kerberos_decode_pac(mem_ctx,
700 lp_iconv_convenience(tctx->lp_ctx),
703 smb_krb5_context->krb5_context,
708 if (NT_STATUS_IS_OK(nt_status)) {
709 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
711 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
713 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
716 /* Finally... Bugger up the signature, and check we fail the checksum */
717 tmp_blob.data[tmp_blob.length - 2]++;
719 nt_status = kerberos_decode_pac(mem_ctx,
720 lp_iconv_convenience(tctx->lp_ctx),
723 smb_krb5_context->krb5_context,
728 if (NT_STATUS_IS_OK(nt_status)) {
729 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
731 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
733 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
736 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
738 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
743 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
745 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
747 torture_suite_add_simple_test(suite, "self check",
748 torture_pac_self_check);
749 torture_suite_add_simple_test(suite, "saved check",
750 torture_pac_saved_check);