r19649: Fix indentation.
[Samba/ekacnet.git] / source / torture / auth / pac.c
blobd3d6dcbe4d5e05e607802a6807f8188d62683229
1 /*
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
25 #include "system/kerberos.h"
26 #include "auth/auth.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
29 #include "samba3/samba3.h"
30 #include "libcli/security/security.h"
31 #include "torture/torture.h"
33 static bool torture_pac_self_check(struct torture_context *tctx)
35 NTSTATUS nt_status;
36 DATA_BLOB tmp_blob;
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;
47 krb5_error_code ret;
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, &smb_krb5_context),
60 "smb_krb5_init_context");
62 generate_random_buffer(server_bytes, 16);
63 generate_random_buffer(krbtgt_bytes, 16);
65 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
66 ENCTYPE_ARCFOUR_HMAC,
67 server_bytes, sizeof(server_bytes),
68 &server_keyblock);
69 torture_assert(tctx, !ret, talloc_asprintf(tctx,
70 "(self test) Server Keyblock encoding failed: %s",
71 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
72 ret, mem_ctx)));
74 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
75 ENCTYPE_ARCFOUR_HMAC,
76 krbtgt_bytes, sizeof(krbtgt_bytes),
77 &krbtgt_keyblock);
78 if (ret) {
79 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
80 ret, mem_ctx);
82 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
83 &server_keyblock);
85 torture_fail(tctx, talloc_asprintf(tctx,
86 "(self test) KRBTGT Keyblock encoding failed: %s", err));
89 /* We need an input, and this one requires no underlying database */
90 nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
92 if (!NT_STATUS_IS_OK(nt_status)) {
93 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
94 &server_keyblock);
95 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
96 &krbtgt_keyblock);
97 torture_fail(tctx, "auth_anonymous_server_info");
100 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
101 server_info->account_name,
102 KRB5_PRINCIPAL_PARSE_NO_REALM,
103 &client_principal);
104 if (ret) {
105 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
106 &server_keyblock);
107 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
108 &krbtgt_keyblock);
109 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
112 /* OK, go ahead and make a PAC */
113 ret = kerberos_create_pac(mem_ctx, server_info,
114 smb_krb5_context->krb5_context,
115 &krbtgt_keyblock,
116 &server_keyblock,
117 client_principal,
118 logon_time,
119 &tmp_blob);
121 if (ret) {
122 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
123 &krbtgt_keyblock);
124 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
125 &server_keyblock);
126 krb5_free_principal(smb_krb5_context->krb5_context,
127 client_principal);
129 torture_fail(tctx, talloc_asprintf(tctx,
130 "(self test) PAC encoding failed: %s",
131 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
132 ret, mem_ctx)));
135 dump_data(10,tmp_blob.data,tmp_blob.length);
137 /* Now check that we can read it back */
138 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
139 tmp_blob,
140 smb_krb5_context->krb5_context,
141 &krbtgt_keyblock,
142 &server_keyblock,
143 client_principal,
144 logon_time, NULL);
146 if (!NT_STATUS_IS_OK(nt_status)) {
147 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
148 &krbtgt_keyblock);
149 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
150 &server_keyblock);
151 krb5_free_principal(smb_krb5_context->krb5_context,
152 client_principal);
154 torture_fail(tctx, talloc_asprintf(tctx,
155 "(self test) PAC decoding failed: %s",
156 nt_errstr(nt_status)));
159 /* Now check that we can read it back */
160 nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
161 tmp_blob,
162 smb_krb5_context->krb5_context,
163 &krbtgt_keyblock,
164 &server_keyblock,
165 client_principal,
166 logon_time,
167 NULL);
169 if (!NT_STATUS_IS_OK(nt_status)) {
170 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
171 &krbtgt_keyblock);
172 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
173 &server_keyblock);
174 krb5_free_principal(smb_krb5_context->krb5_context,
175 client_principal);
177 torture_fail(tctx,
178 talloc_asprintf(tctx,
179 "(self test) PAC decoding (for logon info) failed: %s",
180 nt_errstr(nt_status)));
183 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
184 &krbtgt_keyblock);
185 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
186 &server_keyblock);
187 krb5_free_principal(smb_krb5_context->krb5_context,
188 client_principal);
190 validation.sam3 = &logon_info->info3;
191 nt_status = make_server_info_netlogon_validation(mem_ctx,
193 3, &validation,
194 &server_info_out);
195 if (!NT_STATUS_IS_OK(nt_status)) {
196 torture_fail(tctx,
197 talloc_asprintf(tctx,
198 "(self test) PAC decoding (make server info) failed: %s",
199 nt_errstr(nt_status)));
202 if (!dom_sid_equal(server_info->account_sid,
203 server_info_out->account_sid)) {
204 torture_fail(tctx,
205 talloc_asprintf(tctx,
206 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
207 dom_sid_string(mem_ctx, server_info->account_sid),
208 dom_sid_string(mem_ctx, server_info_out->account_sid)));
210 return true;
214 /* This is the PAC generated on my test network, by my test Win2k3 server.
215 -- abartlet 2005-07-04
218 static const uint8_t saved_pac[] = {
219 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
220 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
221 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
222 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
223 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
224 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
225 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
226 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
227 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
228 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
231 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
232 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
234 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
239 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
240 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
245 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
246 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
247 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
248 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
249 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
250 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
251 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
252 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
254 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
255 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
256 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
257 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
260 /* Check with a known 'well formed' PAC, from my test server */
261 static bool torture_pac_saved_check(struct torture_context *tctx)
263 NTSTATUS nt_status;
264 DATA_BLOB tmp_blob, validate_blob;
265 struct PAC_DATA *pac_data, pac_data2;
266 struct PAC_LOGON_INFO *logon_info;
267 union netr_Validation validation;
268 const char *pac_file, *pac_kdc_key, *pac_member_key;
269 struct auth_serversupplied_info *server_info_out;
271 krb5_keyblock server_keyblock;
272 krb5_keyblock krbtgt_keyblock;
273 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
275 krb5_error_code ret;
276 struct smb_krb5_context *smb_krb5_context;
278 const char *principal_string;
279 krb5_principal client_principal;
280 const char *authtime_string;
281 time_t authtime;
282 TALLOC_CTX *mem_ctx = tctx;
284 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, &smb_krb5_context),
285 "smb_krb5_init_context");
287 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
288 "B286757148AF7FD252C53603A150B7E7");
290 pac_member_key = torture_setting_string(tctx, "pac_member_key",
291 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
293 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
294 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
296 /* The krbtgt key in use when the above PAC was generated.
297 * This is an arcfour-hmac-md5 key, extracted with our 'net
298 * samdump' tool. */
299 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
300 if (!krbtgt_bytes) {
301 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
304 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
305 if (!krbsrv_bytes) {
306 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
309 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
310 ENCTYPE_ARCFOUR_HMAC,
311 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
312 &server_keyblock);
313 torture_assert(tctx, !ret,
314 talloc_asprintf(tctx,
315 "(saved test) Server Keyblock encoding failed: %s",
316 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
317 ret, mem_ctx)));
319 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
320 ENCTYPE_ARCFOUR_HMAC,
321 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
322 &krbtgt_keyblock);
323 if (ret) {
324 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
325 &server_keyblock);
326 torture_fail(tctx,
327 talloc_asprintf(tctx,
328 "(saved test) Server Keyblock encoding failed: %s",
329 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
330 ret, mem_ctx)));
333 pac_file = torture_setting_string(tctx, "pac_file", NULL);
334 if (pac_file) {
335 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
336 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
337 } else {
338 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
341 dump_data(10,tmp_blob.data,tmp_blob.length);
343 principal_string = torture_setting_string(tctx, "pac_client_principal",
344 "w2003final$@WIN2K3.THINKER.LOCAL");
346 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
347 authtime = strtoull(authtime_string, NULL, 0);
349 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
350 &client_principal);
351 if (ret) {
352 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
353 &krbtgt_keyblock);
354 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
355 &server_keyblock);
356 torture_fail(tctx,
357 talloc_asprintf(tctx,
358 "(saved test) parsing of client principal [%s] failed: %s",
359 principal_string,
360 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
363 /* Decode and verify the signaure on the PAC */
364 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
365 tmp_blob,
366 smb_krb5_context->krb5_context,
367 &krbtgt_keyblock,
368 &server_keyblock,
369 client_principal, authtime, NULL);
370 if (!NT_STATUS_IS_OK(nt_status)) {
371 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
372 &krbtgt_keyblock);
373 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
374 &server_keyblock);
375 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
377 torture_fail(tctx, talloc_asprintf(tctx,
378 "(saved test) PAC decoding failed: %s",
379 nt_errstr(nt_status)));
382 /* Parse the PAC again, for the logon info this time */
383 nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
384 tmp_blob,
385 smb_krb5_context->krb5_context,
386 &krbtgt_keyblock,
387 &server_keyblock,
388 client_principal, authtime, NULL);
390 if (!NT_STATUS_IS_OK(nt_status)) {
391 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
392 &krbtgt_keyblock);
393 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
394 &server_keyblock);
395 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
397 torture_fail(tctx,
398 talloc_asprintf(tctx,
399 "(saved test) PAC decoding (for logon info) failed: %s",
400 nt_errstr(nt_status)));
403 validation.sam3 = &logon_info->info3;
404 nt_status = make_server_info_netlogon_validation(mem_ctx,
406 3, &validation,
407 &server_info_out);
408 if (!NT_STATUS_IS_OK(nt_status)) {
409 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
410 &krbtgt_keyblock);
411 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
412 &server_keyblock);
413 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
415 torture_fail(tctx,
416 talloc_asprintf(tctx,
417 "(saved test) PAC decoding (make server info) failed: %s",
418 nt_errstr(nt_status)));
421 if (!pac_file &&
422 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
423 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
424 server_info_out->account_sid)) {
425 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
426 &krbtgt_keyblock);
427 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
428 &server_keyblock);
429 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
431 torture_fail(tctx,
432 talloc_asprintf(tctx,
433 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
434 "S-1-5-21-3048156945-3961193616-3706469200-1005",
435 dom_sid_string(mem_ctx, server_info_out->account_sid)));
438 ret = kerberos_encode_pac(mem_ctx,
439 pac_data,
440 smb_krb5_context->krb5_context,
441 &krbtgt_keyblock,
442 &server_keyblock,
443 &validate_blob);
445 if (ret != 0) {
446 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
447 &krbtgt_keyblock);
448 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
449 &server_keyblock);
450 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
452 torture_fail(tctx, "(saved test) PAC push failed");
455 dump_data(10, validate_blob.data, validate_blob.length);
457 /* compare both the length and the data bytes after a
458 * pull/push cycle. This ensures we use the exact same
459 * pointer, padding etc algorithms as win2k3.
461 if (tmp_blob.length != validate_blob.length) {
462 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
463 &krbtgt_keyblock);
464 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
465 &server_keyblock);
466 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
468 torture_fail(tctx,
469 talloc_asprintf(tctx,
470 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
471 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
474 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
475 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
476 &krbtgt_keyblock);
477 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
478 &server_keyblock);
479 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
481 DEBUG(0, ("tmp_data:\n"));
482 dump_data(0, tmp_blob.data, tmp_blob.length);
483 DEBUG(0, ("validate_blob:\n"));
484 dump_data(0, validate_blob.data, validate_blob.length);
486 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
489 ret = kerberos_create_pac(mem_ctx,
490 server_info_out,
491 smb_krb5_context->krb5_context,
492 &krbtgt_keyblock,
493 &server_keyblock,
494 client_principal, authtime,
495 &validate_blob);
497 if (ret != 0) {
498 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
499 &krbtgt_keyblock);
500 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
501 &server_keyblock);
502 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
504 torture_fail(tctx, "(saved test) regnerated PAC create failed");
507 dump_data(10,validate_blob.data,validate_blob.length);
509 /* compare both the length and the data bytes after a
510 * pull/push cycle. This ensures we use the exact same
511 * pointer, padding etc algorithms as win2k3.
513 if (tmp_blob.length != validate_blob.length) {
514 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
515 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
516 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
518 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
520 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
522 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
523 &krbtgt_keyblock);
524 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
525 &server_keyblock);
526 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
528 torture_fail(tctx, talloc_asprintf(tctx,
529 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
530 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
533 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
534 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
535 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
536 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
538 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
540 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
542 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
543 &krbtgt_keyblock);
544 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
545 &server_keyblock);
546 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
548 DEBUG(0, ("tmp_data:\n"));
549 dump_data(0, tmp_blob.data, tmp_blob.length);
550 DEBUG(0, ("validate_blob:\n"));
551 dump_data(0, validate_blob.data, validate_blob.length);
553 torture_fail(tctx, talloc_asprintf(tctx,
554 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
557 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
558 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
559 tmp_blob,
560 smb_krb5_context->krb5_context,
561 &krbtgt_keyblock,
562 &server_keyblock,
563 client_principal,
564 authtime + 1, NULL);
565 if (NT_STATUS_IS_OK(nt_status)) {
567 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
568 &krbtgt_keyblock);
569 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
570 &server_keyblock);
571 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
572 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
575 /* Break the client principal */
576 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
578 ret = krb5_parse_name(smb_krb5_context->krb5_context,
579 "not the right principal", &client_principal);
580 if (ret) {
582 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
583 &krbtgt_keyblock);
584 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
585 &server_keyblock);
586 torture_fail(tctx, talloc_asprintf(tctx,
587 "(saved test) parsing of bogus client principal failed: %s",
588 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
591 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
592 tmp_blob,
593 smb_krb5_context->krb5_context,
594 &krbtgt_keyblock,
595 &server_keyblock,
596 client_principal,
597 authtime, NULL);
598 if (NT_STATUS_IS_OK(nt_status)) {
599 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
600 &krbtgt_keyblock);
601 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
602 &server_keyblock);
603 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
606 /* Finally... Bugger up the signature, and check we fail the checksum */
607 tmp_blob.data[tmp_blob.length - 2]++;
609 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
610 tmp_blob,
611 smb_krb5_context->krb5_context,
612 &krbtgt_keyblock,
613 &server_keyblock,
614 client_principal,
615 authtime, NULL);
616 if (NT_STATUS_IS_OK(nt_status)) {
617 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
618 &krbtgt_keyblock);
619 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
620 &server_keyblock);
621 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
624 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
625 &krbtgt_keyblock);
626 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
627 &server_keyblock);
628 return true;
631 _PUBLIC_ struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
633 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
635 torture_suite_add_simple_test(suite, "self check",
636 torture_pac_self_check);
638 torture_suite_add_simple_test(suite, "saved check",
639 torture_pac_saved_check);
641 return suite;