r19339: Merge my 4.0-unittest branch. This adds an API for more fine-grained
[Samba.git] / source / torture / auth / pac.c
blobfffec86c0d1696a04f722daeddb22905ad267b43
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_norealm(smb_krb5_context->krb5_context,
101 server_info->account_name, &client_principal);
102 if (ret) {
103 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
104 &server_keyblock);
105 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
106 &krbtgt_keyblock);
107 torture_fail(tctx, "krb5_parse_name_norealm");
110 /* OK, go ahead and make a PAC */
111 ret = kerberos_create_pac(mem_ctx, server_info,
112 smb_krb5_context->krb5_context,
113 &krbtgt_keyblock,
114 &server_keyblock,
115 client_principal,
116 logon_time,
117 &tmp_blob);
119 if (ret) {
120 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
121 &krbtgt_keyblock);
122 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
123 &server_keyblock);
124 krb5_free_principal(smb_krb5_context->krb5_context,
125 client_principal);
127 torture_fail(tctx, talloc_asprintf(tctx,
128 "(self test) PAC encoding failed: %s",
129 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
130 ret, mem_ctx)));
133 dump_data(10,tmp_blob.data,tmp_blob.length);
135 /* Now check that we can read it back */
136 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
137 tmp_blob,
138 smb_krb5_context->krb5_context,
139 &krbtgt_keyblock,
140 &server_keyblock,
141 client_principal,
142 logon_time, NULL);
144 if (!NT_STATUS_IS_OK(nt_status)) {
145 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
146 &krbtgt_keyblock);
147 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
148 &server_keyblock);
149 krb5_free_principal(smb_krb5_context->krb5_context,
150 client_principal);
152 torture_fail(tctx, talloc_asprintf(tctx,
153 "(self test) PAC decoding failed: %s",
154 nt_errstr(nt_status)));
157 /* Now check that we can read it back */
158 nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
159 tmp_blob,
160 smb_krb5_context->krb5_context,
161 &krbtgt_keyblock,
162 &server_keyblock,
163 client_principal,
164 logon_time,
165 NULL);
167 if (!NT_STATUS_IS_OK(nt_status)) {
168 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
169 &krbtgt_keyblock);
170 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
171 &server_keyblock);
172 krb5_free_principal(smb_krb5_context->krb5_context,
173 client_principal);
175 torture_fail(tctx,
176 talloc_asprintf(tctx,
177 "(self test) PAC decoding (for logon info) failed: %s",
178 nt_errstr(nt_status)));
181 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
182 &krbtgt_keyblock);
183 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
184 &server_keyblock);
185 krb5_free_principal(smb_krb5_context->krb5_context,
186 client_principal);
188 validation.sam3 = &logon_info->info3;
189 nt_status = make_server_info_netlogon_validation(mem_ctx,
191 3, &validation,
192 &server_info_out);
193 if (!NT_STATUS_IS_OK(nt_status)) {
194 torture_fail(tctx,
195 talloc_asprintf(tctx,
196 "(self test) PAC decoding (make server info) failed: %s",
197 nt_errstr(nt_status)));
200 if (!dom_sid_equal(server_info->account_sid,
201 server_info_out->account_sid)) {
202 torture_fail(tctx,
203 talloc_asprintf(tctx,
204 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
205 dom_sid_string(mem_ctx, server_info->account_sid),
206 dom_sid_string(mem_ctx, server_info_out->account_sid)));
208 return true;
212 /* This is the PAC generated on my test network, by my test Win2k3 server.
213 -- abartlet 2005-07-04
216 static const uint8_t saved_pac[] = {
217 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
218 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
219 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
220 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
221 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
222 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
223 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
224 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
225 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
226 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
229 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
230 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
232 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
237 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
238 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
243 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
244 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
245 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
246 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
247 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
248 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
249 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
250 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
252 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
253 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
254 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
255 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
258 /* Check with a known 'well formed' PAC, from my test server */
259 static bool torture_pac_saved_check(struct torture_context *tctx)
261 NTSTATUS nt_status;
262 DATA_BLOB tmp_blob, validate_blob;
263 struct PAC_DATA *pac_data, pac_data2;
264 struct PAC_LOGON_INFO *logon_info;
265 union netr_Validation validation;
266 const char *pac_file, *pac_kdc_key, *pac_member_key;
267 struct auth_serversupplied_info *server_info_out;
269 krb5_keyblock server_keyblock;
270 krb5_keyblock krbtgt_keyblock;
271 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
273 krb5_error_code ret;
274 struct smb_krb5_context *smb_krb5_context;
276 const char *principal_string;
277 krb5_principal client_principal;
278 const char *authtime_string;
279 time_t authtime;
280 TALLOC_CTX *mem_ctx = tctx;
282 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, &smb_krb5_context),
283 "smb_krb5_init_context");
285 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
286 "B286757148AF7FD252C53603A150B7E7");
288 pac_member_key = torture_setting_string(tctx, "pac_member_key",
289 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
291 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
292 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
294 /* The krbtgt key in use when the above PAC was generated.
295 * This is an arcfour-hmac-md5 key, extracted with our 'net
296 * samdump' tool. */
297 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
298 if (!krbtgt_bytes) {
299 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
302 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
303 if (!krbsrv_bytes) {
304 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
307 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
308 ENCTYPE_ARCFOUR_HMAC,
309 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
310 &server_keyblock);
311 torture_assert(tctx, !ret,
312 talloc_asprintf(tctx,
313 "(saved test) Server Keyblock encoding failed: %s",
314 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
315 ret, mem_ctx)));
317 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
318 ENCTYPE_ARCFOUR_HMAC,
319 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
320 &krbtgt_keyblock);
321 if (ret) {
322 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
323 &server_keyblock);
324 torture_fail(tctx,
325 talloc_asprintf(tctx,
326 "(saved test) Server Keyblock encoding failed: %s",
327 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
328 ret, mem_ctx)));
331 pac_file = torture_setting_string(tctx, "pac_file", NULL);
332 if (pac_file) {
333 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
334 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
335 } else {
336 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
339 dump_data(10,tmp_blob.data,tmp_blob.length);
341 principal_string = torture_setting_string(tctx, "pac_client_principal",
342 "w2003final$@WIN2K3.THINKER.LOCAL");
344 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
345 authtime = strtoull(authtime_string, NULL, 0);
347 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
348 &client_principal);
349 if (ret) {
350 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
351 &krbtgt_keyblock);
352 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
353 &server_keyblock);
354 torture_fail(tctx,
355 talloc_asprintf(tctx,
356 "(saved test) parsing of client principal [%s] failed: %s",
357 principal_string,
358 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
361 /* Decode and verify the signaure on the PAC */
362 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
363 tmp_blob,
364 smb_krb5_context->krb5_context,
365 &krbtgt_keyblock,
366 &server_keyblock,
367 client_principal, authtime, NULL);
368 if (!NT_STATUS_IS_OK(nt_status)) {
369 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
370 &krbtgt_keyblock);
371 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
372 &server_keyblock);
373 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
375 torture_fail(tctx, talloc_asprintf(tctx,
376 "(saved test) PAC decoding failed: %s",
377 nt_errstr(nt_status)));
380 /* Parse the PAC again, for the logon info this time */
381 nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
382 tmp_blob,
383 smb_krb5_context->krb5_context,
384 &krbtgt_keyblock,
385 &server_keyblock,
386 client_principal, authtime, NULL);
388 if (!NT_STATUS_IS_OK(nt_status)) {
389 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
390 &krbtgt_keyblock);
391 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
392 &server_keyblock);
393 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
395 torture_fail(tctx,
396 talloc_asprintf(tctx,
397 "(saved test) PAC decoding (for logon info) failed: %s",
398 nt_errstr(nt_status)));
401 validation.sam3 = &logon_info->info3;
402 nt_status = make_server_info_netlogon_validation(mem_ctx,
404 3, &validation,
405 &server_info_out);
406 if (!NT_STATUS_IS_OK(nt_status)) {
407 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
408 &krbtgt_keyblock);
409 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
410 &server_keyblock);
411 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
413 torture_fail(tctx,
414 talloc_asprintf(tctx,
415 "(saved test) PAC decoding (make server info) failed: %s",
416 nt_errstr(nt_status)));
419 if (!pac_file &&
420 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
421 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
422 server_info_out->account_sid)) {
423 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
424 &krbtgt_keyblock);
425 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
426 &server_keyblock);
427 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
429 torture_fail(tctx,
430 talloc_asprintf(tctx,
431 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
432 "S-1-5-21-3048156945-3961193616-3706469200-1005",
433 dom_sid_string(mem_ctx, server_info_out->account_sid)));
436 ret = kerberos_encode_pac(mem_ctx,
437 pac_data,
438 smb_krb5_context->krb5_context,
439 &krbtgt_keyblock,
440 &server_keyblock,
441 &validate_blob);
443 if (ret != 0) {
444 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
445 &krbtgt_keyblock);
446 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
447 &server_keyblock);
448 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
450 torture_fail(tctx, "(saved test) PAC push failed");
453 dump_data(10, validate_blob.data, validate_blob.length);
455 /* compare both the length and the data bytes after a
456 * pull/push cycle. This ensures we use the exact same
457 * pointer, padding etc algorithms as win2k3.
459 if (tmp_blob.length != validate_blob.length) {
460 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
461 &krbtgt_keyblock);
462 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
463 &server_keyblock);
464 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
466 torture_fail(tctx,
467 talloc_asprintf(tctx,
468 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
469 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
472 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
473 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
474 &krbtgt_keyblock);
475 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
476 &server_keyblock);
477 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
479 DEBUG(0, ("tmp_data:\n"));
480 dump_data(0, tmp_blob.data, tmp_blob.length);
481 DEBUG(0, ("validate_blob:\n"));
482 dump_data(0, validate_blob.data, validate_blob.length);
484 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
487 ret = kerberos_create_pac(mem_ctx,
488 server_info_out,
489 smb_krb5_context->krb5_context,
490 &krbtgt_keyblock,
491 &server_keyblock,
492 client_principal, authtime,
493 &validate_blob);
495 if (ret != 0) {
496 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
497 &krbtgt_keyblock);
498 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
499 &server_keyblock);
500 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
502 torture_fail(tctx, "(saved test) regnerated PAC create failed");
505 dump_data(10,validate_blob.data,validate_blob.length);
507 /* compare both the length and the data bytes after a
508 * pull/push cycle. This ensures we use the exact same
509 * pointer, padding etc algorithms as win2k3.
511 if (tmp_blob.length != validate_blob.length) {
512 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
513 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
514 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
516 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
518 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
520 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
521 &krbtgt_keyblock);
522 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
523 &server_keyblock);
524 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
526 torture_fail(tctx, talloc_asprintf(tctx,
527 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
528 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
531 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
532 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
533 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
534 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
536 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
538 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
540 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
541 &krbtgt_keyblock);
542 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
543 &server_keyblock);
544 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
546 DEBUG(0, ("tmp_data:\n"));
547 dump_data(0, tmp_blob.data, tmp_blob.length);
548 DEBUG(0, ("validate_blob:\n"));
549 dump_data(0, validate_blob.data, validate_blob.length);
551 torture_fail(tctx, talloc_asprintf(tctx,
552 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
555 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
556 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
557 tmp_blob,
558 smb_krb5_context->krb5_context,
559 &krbtgt_keyblock,
560 &server_keyblock,
561 client_principal,
562 authtime + 1, NULL);
563 if (NT_STATUS_IS_OK(nt_status)) {
565 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
566 &krbtgt_keyblock);
567 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
568 &server_keyblock);
569 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
570 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
573 /* Break the client principal */
574 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
576 ret = krb5_parse_name(smb_krb5_context->krb5_context,
577 "not the right principal", &client_principal);
578 if (ret) {
580 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
581 &krbtgt_keyblock);
582 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
583 &server_keyblock);
584 torture_fail(tctx, talloc_asprintf(tctx,
585 "(saved test) parsing of bogus client principal failed: %s",
586 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
589 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
590 tmp_blob,
591 smb_krb5_context->krb5_context,
592 &krbtgt_keyblock,
593 &server_keyblock,
594 client_principal,
595 authtime, NULL);
596 if (NT_STATUS_IS_OK(nt_status)) {
597 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
598 &krbtgt_keyblock);
599 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
600 &server_keyblock);
601 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
604 /* Finally... Bugger up the signature, and check we fail the checksum */
605 tmp_blob.data[tmp_blob.length - 2]++;
607 nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
608 tmp_blob,
609 smb_krb5_context->krb5_context,
610 &krbtgt_keyblock,
611 &server_keyblock,
612 client_principal,
613 authtime, NULL);
614 if (NT_STATUS_IS_OK(nt_status)) {
615 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
616 &krbtgt_keyblock);
617 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
618 &server_keyblock);
619 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
622 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
623 &krbtgt_keyblock);
624 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
625 &server_keyblock);
626 return true;
629 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
631 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
633 torture_suite_add_simple_test(suite, "self check",
634 torture_pac_self_check);
636 torture_suite_add_simple_test(suite, "saved check",
637 torture_pac_saved_check);
639 return suite;