s3:vfs_gpfs: fix some compiler warnings
[Samba/gebeck_regimport.git] / source4 / torture / auth / pac.c
blob4840a79b7fd835c874d81013e90870e1f1c164c8
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 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/>.
23 #include "includes.h"
24 #include "system/kerberos.h"
25 #include "auth/auth.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "samba3/samba3.h"
28 #include "libcli/security/security.h"
29 #include "torture/torture.h"
30 #include "auth/auth_sam_reply.h"
31 #include "param/param.h"
32 #include "librpc/gen_ndr/ndr_krb5pac.h"
33 #include "torture/auth/proto.h"
35 static bool torture_pac_self_check(struct torture_context *tctx)
37 NTSTATUS nt_status;
38 DATA_BLOB tmp_blob;
39 struct PAC_DATA *pac_data;
40 struct PAC_LOGON_INFO *logon_info;
41 union netr_Validation validation;
43 /* Generate a nice, arbitary keyblock */
44 uint8_t server_bytes[16];
45 uint8_t krbtgt_bytes[16];
46 krb5_keyblock server_keyblock;
47 krb5_keyblock krbtgt_keyblock;
49 krb5_error_code ret;
51 struct smb_krb5_context *smb_krb5_context;
53 struct auth_user_info_dc *user_info_dc;
54 struct auth_user_info_dc *user_info_dc_out;
56 krb5_principal client_principal;
57 time_t logon_time = time(NULL);
59 TALLOC_CTX *mem_ctx = tctx;
61 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx,
62 NULL,
63 tctx->lp_ctx,
64 &smb_krb5_context),
65 "smb_krb5_init_context");
67 generate_random_buffer(server_bytes, 16);
68 generate_random_buffer(krbtgt_bytes, 16);
70 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
71 ENCTYPE_ARCFOUR_HMAC,
72 server_bytes, sizeof(server_bytes),
73 &server_keyblock);
74 torture_assert(tctx, !ret, talloc_asprintf(tctx,
75 "(self test) Server Keyblock encoding failed: %s",
76 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
77 ret, mem_ctx)));
79 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
80 ENCTYPE_ARCFOUR_HMAC,
81 krbtgt_bytes, sizeof(krbtgt_bytes),
82 &krbtgt_keyblock);
83 if (ret) {
84 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
85 ret, mem_ctx);
87 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
88 &server_keyblock);
90 torture_fail(tctx, talloc_asprintf(tctx,
91 "(self test) KRBTGT Keyblock encoding failed: %s", err));
94 /* We need an input, and this one requires no underlying database */
95 nt_status = auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &user_info_dc);
97 if (!NT_STATUS_IS_OK(nt_status)) {
98 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
99 &server_keyblock);
100 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
101 &krbtgt_keyblock);
102 torture_fail(tctx, "auth_anonymous_user_info_dc");
105 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
106 user_info_dc->info->account_name,
107 KRB5_PRINCIPAL_PARSE_NO_REALM,
108 &client_principal);
109 if (ret) {
110 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
111 &server_keyblock);
112 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
113 &krbtgt_keyblock);
114 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
117 /* OK, go ahead and make a PAC */
118 ret = kerberos_create_pac(mem_ctx,
119 user_info_dc,
120 smb_krb5_context->krb5_context,
121 &krbtgt_keyblock,
122 &server_keyblock,
123 client_principal,
124 logon_time,
125 &tmp_blob);
127 if (ret) {
128 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
129 &krbtgt_keyblock);
130 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
131 &server_keyblock);
132 krb5_free_principal(smb_krb5_context->krb5_context,
133 client_principal);
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,
138 ret, mem_ctx)));
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 tmp_blob,
146 smb_krb5_context->krb5_context,
147 &krbtgt_keyblock,
148 &server_keyblock,
149 client_principal,
150 logon_time,
151 &pac_data);
153 if (!NT_STATUS_IS_OK(nt_status)) {
154 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
155 &krbtgt_keyblock);
156 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
157 &server_keyblock);
158 krb5_free_principal(smb_krb5_context->krb5_context,
159 client_principal);
161 torture_fail(tctx, talloc_asprintf(tctx,
162 "(self test) PAC decoding failed: %s",
163 nt_errstr(nt_status)));
166 /* Now check we can read it back (using Heimdal's pac parsing) */
167 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
168 tmp_blob,
169 smb_krb5_context->krb5_context,
170 &user_info_dc_out, NULL, NULL);
172 /* The user's SID is the first element in the list */
173 if (!dom_sid_equal(user_info_dc->sids,
174 user_info_dc_out->sids)) {
175 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
176 &krbtgt_keyblock);
177 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
178 &server_keyblock);
179 krb5_free_principal(smb_krb5_context->krb5_context,
180 client_principal);
182 torture_fail(tctx,
183 talloc_asprintf(tctx,
184 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
185 dom_sid_string(mem_ctx, user_info_dc->sids),
186 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
188 talloc_free(user_info_dc_out);
190 /* Now check that we can read it back (yet again) */
191 nt_status = kerberos_pac_logon_info(mem_ctx,
192 tmp_blob,
193 smb_krb5_context->krb5_context,
194 &krbtgt_keyblock,
195 &server_keyblock,
196 client_principal,
197 logon_time,
198 &logon_info);
200 if (!NT_STATUS_IS_OK(nt_status)) {
201 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
202 &krbtgt_keyblock);
203 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
204 &server_keyblock);
205 krb5_free_principal(smb_krb5_context->krb5_context,
206 client_principal);
208 torture_fail(tctx,
209 talloc_asprintf(tctx,
210 "(self test) PAC decoding (for logon info) failed: %s",
211 nt_errstr(nt_status)));
214 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
215 &krbtgt_keyblock);
216 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
217 &server_keyblock);
218 krb5_free_principal(smb_krb5_context->krb5_context,
219 client_principal);
221 /* And make a server info from the samba-parsed PAC */
222 validation.sam3 = &logon_info->info3;
223 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
225 3, &validation,
226 true, /* This user was authenticated */
227 &user_info_dc_out);
228 if (!NT_STATUS_IS_OK(nt_status)) {
229 torture_fail(tctx,
230 talloc_asprintf(tctx,
231 "(self test) PAC decoding (make server info) failed: %s",
232 nt_errstr(nt_status)));
235 if (!dom_sid_equal(user_info_dc->sids,
236 user_info_dc_out->sids)) {
237 torture_fail(tctx,
238 talloc_asprintf(tctx,
239 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
240 dom_sid_string(mem_ctx, user_info_dc->sids),
241 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
243 return true;
247 /* This is the PAC generated on my test network, by my test Win2k3 server.
248 -- abartlet 2005-07-04
251 static const uint8_t saved_pac[] = {
252 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
253 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
254 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
255 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
256 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
257 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
258 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
259 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
260 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
261 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
264 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
265 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
267 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
272 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
273 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
278 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
279 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
280 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
281 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
282 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
283 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
284 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
285 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
287 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
288 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
289 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
290 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
293 /* Check with a known 'well formed' PAC, from my test server */
294 static bool torture_pac_saved_check(struct torture_context *tctx)
296 NTSTATUS nt_status;
297 enum ndr_err_code ndr_err;
298 DATA_BLOB tmp_blob, validate_blob;
299 struct PAC_DATA *pac_data, pac_data2;
300 struct PAC_LOGON_INFO *logon_info;
301 union netr_Validation validation;
302 const char *pac_file, *pac_kdc_key, *pac_member_key;
303 struct auth_user_info_dc *user_info_dc_out;
305 krb5_keyblock server_keyblock;
306 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
307 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
309 krb5_error_code ret;
310 struct smb_krb5_context *smb_krb5_context;
312 const char *principal_string;
313 char *broken_principal_string;
314 krb5_principal client_principal;
315 const char *authtime_string;
316 time_t authtime;
317 TALLOC_CTX *mem_ctx = tctx;
319 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
320 tctx->lp_ctx,
321 &smb_krb5_context),
322 "smb_krb5_init_context");
324 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
325 "B286757148AF7FD252C53603A150B7E7");
327 pac_member_key = torture_setting_string(tctx, "pac_member_key",
328 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
330 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
331 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
333 /* The krbtgt key in use when the above PAC was generated.
334 * This is an arcfour-hmac-md5 key, extracted with our 'net
335 * samdump' tool. */
336 if (*pac_kdc_key == 0) {
337 krbtgt_bytes = NULL;
338 } else {
339 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
340 if (!krbtgt_bytes) {
341 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
345 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
346 if (!krbsrv_bytes) {
347 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
350 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
351 ENCTYPE_ARCFOUR_HMAC,
352 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
353 &server_keyblock);
354 torture_assert(tctx, !ret,
355 talloc_asprintf(tctx,
356 "(saved test) Server Keyblock encoding failed: %s",
357 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
358 ret, mem_ctx)));
360 if (krbtgt_bytes) {
361 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
362 ENCTYPE_ARCFOUR_HMAC,
363 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
364 &krbtgt_keyblock);
365 if (ret) {
366 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
367 &server_keyblock);
368 torture_fail(tctx,
369 talloc_asprintf(tctx,
370 "(saved test) Server Keyblock encoding failed: %s",
371 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
372 ret, mem_ctx)));
374 krbtgt_keyblock_p = &krbtgt_keyblock;
375 } else {
376 krbtgt_keyblock_p = NULL;
379 pac_file = torture_setting_string(tctx, "pac_file", NULL);
380 if (pac_file) {
381 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
382 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
383 } else {
384 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
387 dump_data(10,tmp_blob.data,tmp_blob.length);
389 principal_string = torture_setting_string(tctx, "pac_client_principal",
390 "w2003final$@WIN2K3.THINKER.LOCAL");
392 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
393 authtime = strtoull(authtime_string, NULL, 0);
395 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
396 &client_principal);
397 if (ret) {
398 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
399 krbtgt_keyblock_p);
400 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
401 &server_keyblock);
402 torture_fail(tctx,
403 talloc_asprintf(tctx,
404 "(saved test) parsing of client principal [%s] failed: %s",
405 principal_string,
406 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
409 /* Decode and verify the signaure on the PAC */
410 nt_status = kerberos_decode_pac(mem_ctx,
411 tmp_blob,
412 smb_krb5_context->krb5_context,
413 krbtgt_keyblock_p,
414 &server_keyblock,
415 client_principal, authtime, &pac_data);
416 if (!NT_STATUS_IS_OK(nt_status)) {
417 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
418 krbtgt_keyblock_p);
419 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
420 &server_keyblock);
421 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
423 torture_fail(tctx, talloc_asprintf(tctx,
424 "(saved test) PAC decoding failed: %s",
425 nt_errstr(nt_status)));
428 /* Now check we can read it back (using Heimdal's pac parsing) */
429 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
430 tmp_blob,
431 smb_krb5_context->krb5_context,
432 &user_info_dc_out,
433 NULL, NULL);
435 if (!NT_STATUS_IS_OK(nt_status)) {
436 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
437 krbtgt_keyblock_p);
438 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
439 &server_keyblock);
440 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
442 torture_fail(tctx, talloc_asprintf(tctx,
443 "(saved test) Heimdal PAC decoding failed: %s",
444 nt_errstr(nt_status)));
447 if (!pac_file &&
448 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
449 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
450 user_info_dc_out->sids)) {
451 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
452 krbtgt_keyblock_p);
453 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
454 &server_keyblock);
455 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
457 torture_fail(tctx,
458 talloc_asprintf(tctx,
459 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
460 "S-1-5-21-3048156945-3961193616-3706469200-1005",
461 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
464 talloc_free(user_info_dc_out);
466 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
467 nt_status = kerberos_pac_logon_info(mem_ctx,
468 tmp_blob,
469 smb_krb5_context->krb5_context,
470 krbtgt_keyblock_p,
471 &server_keyblock,
472 client_principal, authtime, &logon_info);
474 if (!NT_STATUS_IS_OK(nt_status)) {
475 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
476 krbtgt_keyblock_p);
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 torture_fail(tctx,
482 talloc_asprintf(tctx,
483 "(saved test) PAC decoding (for logon info) failed: %s",
484 nt_errstr(nt_status)));
487 validation.sam3 = &logon_info->info3;
488 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
490 3, &validation,
491 true, /* This user was authenticated */
492 &user_info_dc_out);
493 if (!NT_STATUS_IS_OK(nt_status)) {
494 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
495 krbtgt_keyblock_p);
496 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
497 &server_keyblock);
498 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
500 torture_fail(tctx,
501 talloc_asprintf(tctx,
502 "(saved test) PAC decoding (make server info) failed: %s",
503 nt_errstr(nt_status)));
506 if (!pac_file &&
507 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
508 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
509 user_info_dc_out->sids)) {
510 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
511 krbtgt_keyblock_p);
512 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
513 &server_keyblock);
514 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
516 torture_fail(tctx,
517 talloc_asprintf(tctx,
518 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
519 "S-1-5-21-3048156945-3961193616-3706469200-1005",
520 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
523 if (krbtgt_bytes == NULL) {
524 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
525 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
526 &server_keyblock);
527 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
528 return true;
531 ret = kerberos_encode_pac(mem_ctx,
532 pac_data,
533 smb_krb5_context->krb5_context,
534 krbtgt_keyblock_p,
535 &server_keyblock,
536 &validate_blob);
538 if (ret != 0) {
539 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
540 krbtgt_keyblock_p);
541 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
542 &server_keyblock);
543 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
545 torture_fail(tctx, "(saved test) PAC push failed");
548 dump_data(10, validate_blob.data, validate_blob.length);
550 /* compare both the length and the data bytes after a
551 * pull/push cycle. This ensures we use the exact same
552 * pointer, padding etc algorithms as win2k3.
554 if (tmp_blob.length != validate_blob.length) {
555 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
556 krbtgt_keyblock_p);
557 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
558 &server_keyblock);
559 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
561 torture_fail(tctx,
562 talloc_asprintf(tctx,
563 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
564 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
567 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
568 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
569 krbtgt_keyblock_p);
570 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
571 &server_keyblock);
572 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
574 DEBUG(0, ("tmp_data:\n"));
575 dump_data(0, tmp_blob.data, tmp_blob.length);
576 DEBUG(0, ("validate_blob:\n"));
577 dump_data(0, validate_blob.data, validate_blob.length);
579 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
582 ret = kerberos_create_pac(mem_ctx,
583 user_info_dc_out,
584 smb_krb5_context->krb5_context,
585 krbtgt_keyblock_p,
586 &server_keyblock,
587 client_principal, authtime,
588 &validate_blob);
590 if (ret != 0) {
591 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
592 krbtgt_keyblock_p);
593 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
594 &server_keyblock);
595 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
597 torture_fail(tctx, "(saved test) regnerated PAC create failed");
600 dump_data(10,validate_blob.data,validate_blob.length);
602 /* compare both the length and the data bytes after a
603 * pull/push cycle. This ensures we use the exact same
604 * pointer, padding etc algorithms as win2k3.
606 if (tmp_blob.length != validate_blob.length) {
607 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
608 &pac_data2,
609 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
610 nt_status = ndr_map_error2ntstatus(ndr_err);
611 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
613 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
615 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
617 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
618 krbtgt_keyblock_p);
619 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
620 &server_keyblock);
621 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
623 torture_fail(tctx, talloc_asprintf(tctx,
624 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
625 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
628 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
629 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
630 &pac_data2,
631 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
632 nt_status = ndr_map_error2ntstatus(ndr_err);
633 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
635 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
637 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
639 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
640 krbtgt_keyblock_p);
641 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
642 &server_keyblock);
643 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
645 DEBUG(0, ("tmp_data:\n"));
646 dump_data(0, tmp_blob.data, tmp_blob.length);
647 DEBUG(0, ("validate_blob:\n"));
648 dump_data(0, validate_blob.data, validate_blob.length);
650 torture_fail(tctx, talloc_asprintf(tctx,
651 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
654 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
655 nt_status = kerberos_decode_pac(mem_ctx,
656 tmp_blob,
657 smb_krb5_context->krb5_context,
658 krbtgt_keyblock_p,
659 &server_keyblock,
660 client_principal,
661 authtime + 1, &pac_data);
662 if (NT_STATUS_IS_OK(nt_status)) {
664 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
665 krbtgt_keyblock_p);
666 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
667 &server_keyblock);
668 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
669 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
672 /* Break the client principal */
673 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
675 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
676 broken_principal_string[0]++;
678 ret = krb5_parse_name(smb_krb5_context->krb5_context,
679 broken_principal_string, &client_principal);
680 if (ret) {
682 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
683 krbtgt_keyblock_p);
684 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
685 &server_keyblock);
686 torture_fail(tctx, talloc_asprintf(tctx,
687 "(saved test) parsing of broken client principal failed: %s",
688 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
691 nt_status = kerberos_decode_pac(mem_ctx,
692 tmp_blob,
693 smb_krb5_context->krb5_context,
694 krbtgt_keyblock_p,
695 &server_keyblock,
696 client_principal,
697 authtime, &pac_data);
698 if (NT_STATUS_IS_OK(nt_status)) {
699 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
700 krbtgt_keyblock_p);
701 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
702 &server_keyblock);
703 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
706 /* Finally... Bugger up the signature, and check we fail the checksum */
707 tmp_blob.data[tmp_blob.length - 2]++;
709 nt_status = kerberos_decode_pac(mem_ctx,
710 tmp_blob,
711 smb_krb5_context->krb5_context,
712 krbtgt_keyblock_p,
713 &server_keyblock,
714 client_principal,
715 authtime,
716 &pac_data);
717 if (NT_STATUS_IS_OK(nt_status)) {
718 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
719 krbtgt_keyblock_p);
720 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
721 &server_keyblock);
722 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
725 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
726 krbtgt_keyblock_p);
727 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
728 &server_keyblock);
729 return true;
732 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
734 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
736 torture_suite_add_simple_test(suite, "self check",
737 torture_pac_self_check);
738 torture_suite_add_simple_test(suite, "saved check",
739 torture_pac_saved_check);
740 return suite;