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"
32 #include "param/param.h"
34 static bool torture_pac_self_check(struct torture_context
*tctx
)
38 struct PAC_DATA
*pac_data
;
39 struct PAC_LOGON_INFO
*logon_info
;
40 union netr_Validation validation
;
42 /* Generate a nice, arbitary keyblock */
43 uint8_t server_bytes
[16];
44 uint8_t krbtgt_bytes
[16];
45 krb5_keyblock server_keyblock
;
46 krb5_keyblock krbtgt_keyblock
;
50 struct smb_krb5_context
*smb_krb5_context
;
52 struct auth_serversupplied_info
*server_info
;
53 struct auth_serversupplied_info
*server_info_out
;
55 krb5_principal client_principal
;
56 time_t logon_time
= time(NULL
);
58 TALLOC_CTX
*mem_ctx
= tctx
;
60 torture_assert(tctx
, 0 == smb_krb5_init_context(mem_ctx
,
64 "smb_krb5_init_context");
66 generate_random_buffer(server_bytes
, 16);
67 generate_random_buffer(krbtgt_bytes
, 16);
69 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
71 server_bytes
, sizeof(server_bytes
),
73 torture_assert(tctx
, !ret
, talloc_asprintf(tctx
,
74 "(self test) Server Keyblock encoding failed: %s",
75 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
78 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
80 krbtgt_bytes
, sizeof(krbtgt_bytes
),
83 char *err
= smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
86 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
89 torture_fail(tctx
, talloc_asprintf(tctx
,
90 "(self test) KRBTGT Keyblock encoding failed: %s", err
));
93 /* We need an input, and this one requires no underlying database */
94 nt_status
= auth_anonymous_server_info(mem_ctx
, lp_netbios_name(tctx
->lp_ctx
), &server_info
);
96 if (!NT_STATUS_IS_OK(nt_status
)) {
97 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
99 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
101 torture_fail(tctx
, "auth_anonymous_server_info");
104 ret
= krb5_parse_name_flags(smb_krb5_context
->krb5_context
,
105 server_info
->account_name
,
106 KRB5_PRINCIPAL_PARSE_NO_REALM
,
109 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
111 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
113 torture_fail(tctx
, "krb5_parse_name_flags(norealm)");
116 /* OK, go ahead and make a PAC */
117 ret
= kerberos_create_pac(mem_ctx
,
118 lp_iconv_convenience(tctx
->lp_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
,
145 lp_iconv_convenience(tctx
->lp_ctx
),
148 smb_krb5_context
->krb5_context
,
154 if (!NT_STATUS_IS_OK(nt_status
)) {
155 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
157 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
159 krb5_free_principal(smb_krb5_context
->krb5_context
,
162 torture_fail(tctx
, talloc_asprintf(tctx
,
163 "(self test) PAC decoding failed: %s",
164 nt_errstr(nt_status
)));
167 /* Now check we can read it back (using Heimdal's pac parsing) */
168 nt_status
= kerberos_pac_blob_to_server_info(mem_ctx
,
169 lp_iconv_convenience(tctx
->lp_ctx
),
171 smb_krb5_context
->krb5_context
,
174 if (!dom_sid_equal(server_info
->account_sid
,
175 server_info_out
->account_sid
)) {
176 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
178 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
180 krb5_free_principal(smb_krb5_context
->krb5_context
,
184 talloc_asprintf(tctx
,
185 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
186 dom_sid_string(mem_ctx
, server_info
->account_sid
),
187 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
189 talloc_free(server_info_out
);
191 /* Now check that we can read it back (yet again) */
192 nt_status
= kerberos_pac_logon_info(mem_ctx
,
193 lp_iconv_convenience(tctx
->lp_ctx
),
196 smb_krb5_context
->krb5_context
,
203 if (!NT_STATUS_IS_OK(nt_status
)) {
204 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
206 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
208 krb5_free_principal(smb_krb5_context
->krb5_context
,
212 talloc_asprintf(tctx
,
213 "(self test) PAC decoding (for logon info) failed: %s",
214 nt_errstr(nt_status
)));
217 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
219 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
221 krb5_free_principal(smb_krb5_context
->krb5_context
,
224 /* And make a server info from the samba-parsed PAC */
225 validation
.sam3
= &logon_info
->info3
;
226 nt_status
= make_server_info_netlogon_validation(mem_ctx
,
230 if (!NT_STATUS_IS_OK(nt_status
)) {
232 talloc_asprintf(tctx
,
233 "(self test) PAC decoding (make server info) failed: %s",
234 nt_errstr(nt_status
)));
237 if (!dom_sid_equal(server_info
->account_sid
,
238 server_info_out
->account_sid
)) {
240 talloc_asprintf(tctx
,
241 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
242 dom_sid_string(mem_ctx
, server_info
->account_sid
),
243 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
249 /* This is the PAC generated on my test network, by my test Win2k3 server.
250 -- abartlet 2005-07-04
253 static const uint8_t saved_pac
[] = {
254 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
255 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
256 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
257 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
258 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
259 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
260 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
261 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
262 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
263 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
266 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
267 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
269 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
274 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
275 0x41, 0x00, 0x4c, 0x00, 0x24, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
280 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
281 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
282 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
283 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
284 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
285 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
286 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
287 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
289 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
290 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
291 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
292 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
295 /* Check with a known 'well formed' PAC, from my test server */
296 static bool torture_pac_saved_check(struct torture_context
*tctx
)
299 enum ndr_err_code ndr_err
;
300 DATA_BLOB tmp_blob
, validate_blob
;
301 struct PAC_DATA
*pac_data
, pac_data2
;
302 struct PAC_LOGON_INFO
*logon_info
;
303 union netr_Validation validation
;
304 const char *pac_file
, *pac_kdc_key
, *pac_member_key
;
305 struct auth_serversupplied_info
*server_info_out
;
307 krb5_keyblock server_keyblock
;
308 krb5_keyblock krbtgt_keyblock
, *krbtgt_keyblock_p
;
309 struct samr_Password
*krbtgt_bytes
, *krbsrv_bytes
;
312 struct smb_krb5_context
*smb_krb5_context
;
314 const char *principal_string
;
315 char *broken_principal_string
;
316 krb5_principal client_principal
;
317 const char *authtime_string
;
319 TALLOC_CTX
*mem_ctx
= tctx
;
321 torture_assert(tctx
, 0 == smb_krb5_init_context(mem_ctx
, NULL
,
324 "smb_krb5_init_context");
326 pac_kdc_key
= torture_setting_string(tctx
, "pac_kdc_key",
327 "B286757148AF7FD252C53603A150B7E7");
329 pac_member_key
= torture_setting_string(tctx
, "pac_member_key",
330 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
332 torture_comment(tctx
, "Using pac_kdc_key '%s'\n", pac_kdc_key
);
333 torture_comment(tctx
, "Using pac_member_key '%s'\n", pac_member_key
);
335 /* The krbtgt key in use when the above PAC was generated.
336 * This is an arcfour-hmac-md5 key, extracted with our 'net
338 if (*pac_kdc_key
== 0) {
341 krbtgt_bytes
= smbpasswd_gethexpwd(mem_ctx
, pac_kdc_key
);
343 torture_fail(tctx
, "(saved test) Could not interpret krbtgt key");
347 krbsrv_bytes
= smbpasswd_gethexpwd(mem_ctx
, pac_member_key
);
349 torture_fail(tctx
, "(saved test) Could not interpret krbsrv key");
352 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
353 ENCTYPE_ARCFOUR_HMAC
,
354 krbsrv_bytes
->hash
, sizeof(krbsrv_bytes
->hash
),
356 torture_assert(tctx
, !ret
,
357 talloc_asprintf(tctx
,
358 "(saved test) Server Keyblock encoding failed: %s",
359 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
363 ret
= krb5_keyblock_init(smb_krb5_context
->krb5_context
,
364 ENCTYPE_ARCFOUR_HMAC
,
365 krbtgt_bytes
->hash
, sizeof(krbtgt_bytes
->hash
),
368 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
371 talloc_asprintf(tctx
,
372 "(saved test) Server Keyblock encoding failed: %s",
373 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
,
376 krbtgt_keyblock_p
= &krbtgt_keyblock
;
378 krbtgt_keyblock_p
= NULL
;
381 pac_file
= torture_setting_string(tctx
, "pac_file", NULL
);
383 tmp_blob
.data
= (uint8_t *)file_load(pac_file
, &tmp_blob
.length
, 0, mem_ctx
);
384 torture_comment(tctx
, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob
.length
, pac_file
);
386 tmp_blob
= data_blob_talloc(mem_ctx
, saved_pac
, sizeof(saved_pac
));
389 dump_data(10,tmp_blob
.data
,tmp_blob
.length
);
391 principal_string
= torture_setting_string(tctx
, "pac_client_principal",
392 "w2003final$@WIN2K3.THINKER.LOCAL");
394 authtime_string
= torture_setting_string(tctx
, "pac_authtime", "1120440609");
395 authtime
= strtoull(authtime_string
, NULL
, 0);
397 ret
= krb5_parse_name(smb_krb5_context
->krb5_context
, principal_string
,
400 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
402 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
405 talloc_asprintf(tctx
,
406 "(saved test) parsing of client principal [%s] failed: %s",
408 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
, ret
, mem_ctx
)));
411 /* Decode and verify the signaure on the PAC */
412 nt_status
= kerberos_decode_pac(mem_ctx
,
413 lp_iconv_convenience(tctx
->lp_ctx
),
416 smb_krb5_context
->krb5_context
,
419 client_principal
, authtime
, NULL
);
420 if (!NT_STATUS_IS_OK(nt_status
)) {
421 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
423 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
425 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
427 torture_fail(tctx
, talloc_asprintf(tctx
,
428 "(saved test) PAC decoding failed: %s",
429 nt_errstr(nt_status
)));
432 /* Now check we can read it back (using Heimdal's pac parsing) */
433 nt_status
= kerberos_pac_blob_to_server_info(mem_ctx
,
434 lp_iconv_convenience(tctx
->lp_ctx
),
436 smb_krb5_context
->krb5_context
,
439 if (!NT_STATUS_IS_OK(nt_status
)) {
440 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
442 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
444 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
446 torture_fail(tctx
, talloc_asprintf(tctx
,
447 "(saved test) Heimdal PAC decoding failed: %s",
448 nt_errstr(nt_status
)));
452 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx
,
453 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
454 server_info_out
->account_sid
)) {
455 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
457 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
459 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
462 talloc_asprintf(tctx
,
463 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
464 "S-1-5-21-3048156945-3961193616-3706469200-1005",
465 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
468 talloc_free(server_info_out
);
470 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
471 nt_status
= kerberos_pac_logon_info(mem_ctx
,
472 lp_iconv_convenience(tctx
->lp_ctx
),
475 smb_krb5_context
->krb5_context
,
478 client_principal
, authtime
, NULL
);
480 if (!NT_STATUS_IS_OK(nt_status
)) {
481 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
483 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
485 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
488 talloc_asprintf(tctx
,
489 "(saved test) PAC decoding (for logon info) failed: %s",
490 nt_errstr(nt_status
)));
493 validation
.sam3
= &logon_info
->info3
;
494 nt_status
= make_server_info_netlogon_validation(mem_ctx
,
498 if (!NT_STATUS_IS_OK(nt_status
)) {
499 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
501 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
503 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
506 talloc_asprintf(tctx
,
507 "(saved test) PAC decoding (make server info) failed: %s",
508 nt_errstr(nt_status
)));
512 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx
,
513 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
514 server_info_out
->account_sid
)) {
515 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
517 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
519 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
522 talloc_asprintf(tctx
,
523 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
524 "S-1-5-21-3048156945-3961193616-3706469200-1005",
525 dom_sid_string(mem_ctx
, server_info_out
->account_sid
)));
528 if (krbtgt_bytes
== NULL
) {
529 torture_comment(tctx
, "skipping PAC encoding tests as non kdc key\n");
530 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
532 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
536 ret
= kerberos_encode_pac(mem_ctx
,
537 lp_iconv_convenience(tctx
->lp_ctx
),
539 smb_krb5_context
->krb5_context
,
545 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
547 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
549 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
551 torture_fail(tctx
, "(saved test) PAC push failed");
554 dump_data(10, validate_blob
.data
, validate_blob
.length
);
556 /* compare both the length and the data bytes after a
557 * pull/push cycle. This ensures we use the exact same
558 * pointer, padding etc algorithms as win2k3.
560 if (tmp_blob
.length
!= validate_blob
.length
) {
561 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
563 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
565 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
568 talloc_asprintf(tctx
,
569 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
570 (unsigned)tmp_blob
.length
, (unsigned)validate_blob
.length
));
573 if (memcmp(tmp_blob
.data
, validate_blob
.data
, tmp_blob
.length
) != 0) {
574 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
576 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
578 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
580 DEBUG(0, ("tmp_data:\n"));
581 dump_data(0, tmp_blob
.data
, tmp_blob
.length
);
582 DEBUG(0, ("validate_blob:\n"));
583 dump_data(0, validate_blob
.data
, validate_blob
.length
);
585 torture_fail(tctx
, talloc_asprintf(tctx
, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob
.length
));
588 ret
= kerberos_create_pac(mem_ctx
,
589 lp_iconv_convenience(tctx
->lp_ctx
),
591 smb_krb5_context
->krb5_context
,
594 client_principal
, authtime
,
598 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
600 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
602 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
604 torture_fail(tctx
, "(saved test) regnerated PAC create failed");
607 dump_data(10,validate_blob
.data
,validate_blob
.length
);
609 /* compare both the length and the data bytes after a
610 * pull/push cycle. This ensures we use the exact same
611 * pointer, padding etc algorithms as win2k3.
613 if (tmp_blob
.length
!= validate_blob
.length
) {
614 ndr_err
= ndr_pull_struct_blob(&validate_blob
, mem_ctx
,
615 lp_iconv_convenience(tctx
->lp_ctx
), &pac_data2
,
616 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
617 nt_status
= ndr_map_error2ntstatus(ndr_err
);
618 torture_assert_ntstatus_ok(tctx
, nt_status
, "can't parse the PAC");
620 NDR_PRINT_DEBUG(PAC_DATA
, pac_data
);
622 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data2
);
624 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
626 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
628 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
630 torture_fail(tctx
, talloc_asprintf(tctx
,
631 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
632 (unsigned)tmp_blob
.length
, (unsigned)validate_blob
.length
));
635 if (memcmp(tmp_blob
.data
, validate_blob
.data
, tmp_blob
.length
) != 0) {
636 ndr_err
= ndr_pull_struct_blob(&validate_blob
, mem_ctx
,
637 lp_iconv_convenience(tctx
->lp_ctx
), &pac_data2
,
638 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
639 nt_status
= ndr_map_error2ntstatus(ndr_err
);
640 torture_assert_ntstatus_ok(tctx
, nt_status
, "can't parse the PAC");
642 NDR_PRINT_DEBUG(PAC_DATA
, pac_data
);
644 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data2
);
646 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
648 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
650 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
652 DEBUG(0, ("tmp_data:\n"));
653 dump_data(0, tmp_blob
.data
, tmp_blob
.length
);
654 DEBUG(0, ("validate_blob:\n"));
655 dump_data(0, validate_blob
.data
, validate_blob
.length
);
657 torture_fail(tctx
, talloc_asprintf(tctx
,
658 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob
.length
));
661 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
662 nt_status
= kerberos_decode_pac(mem_ctx
,
663 lp_iconv_convenience(tctx
->lp_ctx
),
666 smb_krb5_context
->krb5_context
,
671 if (NT_STATUS_IS_OK(nt_status
)) {
673 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
675 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
677 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
678 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
681 /* Break the client principal */
682 krb5_free_principal(smb_krb5_context
->krb5_context
, client_principal
);
684 broken_principal_string
= talloc_strdup(mem_ctx
, principal_string
);
685 broken_principal_string
[0]++;
687 ret
= krb5_parse_name(smb_krb5_context
->krb5_context
,
688 broken_principal_string
, &client_principal
);
691 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
693 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
695 torture_fail(tctx
, talloc_asprintf(tctx
,
696 "(saved test) parsing of broken client principal failed: %s",
697 smb_get_krb5_error_message(smb_krb5_context
->krb5_context
, ret
, mem_ctx
)));
700 nt_status
= kerberos_decode_pac(mem_ctx
,
701 lp_iconv_convenience(tctx
->lp_ctx
),
704 smb_krb5_context
->krb5_context
,
709 if (NT_STATUS_IS_OK(nt_status
)) {
710 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
712 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
714 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on modified principal");
717 /* Finally... Bugger up the signature, and check we fail the checksum */
718 tmp_blob
.data
[tmp_blob
.length
- 2]++;
720 nt_status
= kerberos_decode_pac(mem_ctx
,
721 lp_iconv_convenience(tctx
->lp_ctx
),
724 smb_krb5_context
->krb5_context
,
729 if (NT_STATUS_IS_OK(nt_status
)) {
730 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
732 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
734 torture_fail(tctx
, "(saved test) PAC decoding DID NOT fail on broken checksum");
737 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
739 krb5_free_keyblock_contents(smb_krb5_context
->krb5_context
,
744 struct torture_suite
*torture_pac(TALLOC_CTX
*mem_ctx
)
746 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "PAC");
748 torture_suite_add_simple_test(suite
, "self check",
749 torture_pac_self_check
);
750 torture_suite_add_simple_test(suite
, "saved check",
751 torture_pac_saved_check
);