smbd: Fix an ancient oplock bug
[Samba.git] / source4 / torture / auth / pac.c
blob64a843c07fcf53aa89e65e1c066ab9e4f6d7cfb0
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"
34 #include "auth/kerberos/pac_utils.h"
36 static bool torture_pac_self_check(struct torture_context *tctx)
38 NTSTATUS nt_status;
39 DATA_BLOB tmp_blob;
40 struct PAC_DATA *pac_data;
41 struct PAC_LOGON_INFO *logon_info;
42 union netr_Validation validation;
44 /* Generate a nice, arbitary keyblock */
45 uint8_t server_bytes[16];
46 uint8_t krbtgt_bytes[16];
47 krb5_keyblock server_keyblock;
48 krb5_keyblock krbtgt_keyblock;
50 krb5_error_code ret;
52 struct smb_krb5_context *smb_krb5_context;
54 struct auth_user_info_dc *user_info_dc;
55 struct auth_user_info_dc *user_info_dc_out;
57 krb5_principal client_principal;
58 time_t logon_time = time(NULL);
60 TALLOC_CTX *mem_ctx = tctx;
62 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx,
63 NULL,
64 tctx->lp_ctx,
65 &smb_krb5_context),
66 "smb_krb5_init_context");
68 generate_random_buffer(server_bytes, 16);
69 generate_random_buffer(krbtgt_bytes, 16);
71 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
72 ENCTYPE_ARCFOUR_HMAC,
73 server_bytes, sizeof(server_bytes),
74 &server_keyblock);
75 torture_assert(tctx, !ret, talloc_asprintf(tctx,
76 "(self test) Server Keyblock encoding failed: %s",
77 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
78 ret, mem_ctx)));
80 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
81 ENCTYPE_ARCFOUR_HMAC,
82 krbtgt_bytes, sizeof(krbtgt_bytes),
83 &krbtgt_keyblock);
84 if (ret) {
85 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
86 ret, mem_ctx);
88 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
89 &server_keyblock);
91 torture_fail(tctx, talloc_asprintf(tctx,
92 "(self test) KRBTGT Keyblock encoding failed: %s", err));
95 /* We need an input, and this one requires no underlying database */
96 nt_status = auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &user_info_dc);
98 if (!NT_STATUS_IS_OK(nt_status)) {
99 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
100 &server_keyblock);
101 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
102 &krbtgt_keyblock);
103 torture_fail(tctx, "auth_anonymous_user_info_dc");
106 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
107 user_info_dc->info->account_name,
108 KRB5_PRINCIPAL_PARSE_NO_REALM,
109 &client_principal);
110 if (ret) {
111 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
112 &server_keyblock);
113 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
114 &krbtgt_keyblock);
115 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
118 /* OK, go ahead and make a PAC */
119 ret = kerberos_create_pac(mem_ctx,
120 user_info_dc,
121 smb_krb5_context->krb5_context,
122 &krbtgt_keyblock,
123 &server_keyblock,
124 client_principal,
125 logon_time,
126 &tmp_blob);
128 if (ret) {
129 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
130 &krbtgt_keyblock);
131 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
132 &server_keyblock);
133 krb5_free_principal(smb_krb5_context->krb5_context,
134 client_principal);
136 torture_fail(tctx, talloc_asprintf(tctx,
137 "(self test) PAC encoding failed: %s",
138 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
139 ret, mem_ctx)));
142 dump_data(10,tmp_blob.data,tmp_blob.length);
144 /* Now check that we can read it back (using full decode and validate) */
145 nt_status = kerberos_decode_pac(mem_ctx,
146 tmp_blob,
147 smb_krb5_context->krb5_context,
148 &krbtgt_keyblock,
149 &server_keyblock,
150 client_principal,
151 logon_time,
152 &pac_data);
154 if (!NT_STATUS_IS_OK(nt_status)) {
155 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
156 &krbtgt_keyblock);
157 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
158 &server_keyblock);
159 krb5_free_principal(smb_krb5_context->krb5_context,
160 client_principal);
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_user_info_dc(mem_ctx,
169 tmp_blob,
170 smb_krb5_context->krb5_context,
171 &user_info_dc_out, NULL, NULL);
173 /* The user's SID is the first element in the list */
174 if (!dom_sid_equal(user_info_dc->sids,
175 user_info_dc_out->sids)) {
176 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
177 &krbtgt_keyblock);
178 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
179 &server_keyblock);
180 krb5_free_principal(smb_krb5_context->krb5_context,
181 client_principal);
183 torture_fail(tctx,
184 talloc_asprintf(tctx,
185 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
186 dom_sid_string(mem_ctx, user_info_dc->sids),
187 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
189 talloc_free(user_info_dc_out);
191 /* Now check that we can read it back (yet again) */
192 nt_status = kerberos_pac_logon_info(mem_ctx,
193 tmp_blob,
194 smb_krb5_context->krb5_context,
195 &krbtgt_keyblock,
196 &server_keyblock,
197 client_principal,
198 logon_time,
199 &logon_info);
201 if (!NT_STATUS_IS_OK(nt_status)) {
202 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
203 &krbtgt_keyblock);
204 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
205 &server_keyblock);
206 krb5_free_principal(smb_krb5_context->krb5_context,
207 client_principal);
209 torture_fail(tctx,
210 talloc_asprintf(tctx,
211 "(self test) PAC decoding (for logon info) failed: %s",
212 nt_errstr(nt_status)));
215 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
216 &krbtgt_keyblock);
217 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
218 &server_keyblock);
219 krb5_free_principal(smb_krb5_context->krb5_context,
220 client_principal);
222 /* And make a server info from the samba-parsed PAC */
223 validation.sam3 = &logon_info->info3;
224 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
226 3, &validation,
227 true, /* This user was authenticated */
228 &user_info_dc_out);
229 if (!NT_STATUS_IS_OK(nt_status)) {
230 torture_fail(tctx,
231 talloc_asprintf(tctx,
232 "(self test) PAC decoding (make server info) failed: %s",
233 nt_errstr(nt_status)));
236 if (!dom_sid_equal(user_info_dc->sids,
237 user_info_dc_out->sids)) {
238 torture_fail(tctx,
239 talloc_asprintf(tctx,
240 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
241 dom_sid_string(mem_ctx, user_info_dc->sids),
242 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
244 return true;
248 /* This is the PAC generated on my test network, by my test Win2k3 server.
249 -- abartlet 2005-07-04
252 static const uint8_t saved_pac[] = {
253 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
254 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
255 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
256 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
257 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
258 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
259 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
260 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
261 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
262 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
265 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
266 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
268 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
273 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
274 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
279 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
280 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
281 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
282 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
283 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
284 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
285 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
286 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
288 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
289 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
290 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
291 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
294 /* Check with a known 'well formed' PAC, from my test server */
295 static bool torture_pac_saved_check(struct torture_context *tctx)
297 NTSTATUS nt_status;
298 enum ndr_err_code ndr_err;
299 DATA_BLOB tmp_blob, validate_blob;
300 struct PAC_DATA *pac_data, pac_data2;
301 struct PAC_LOGON_INFO *logon_info;
302 union netr_Validation validation;
303 const char *pac_file, *pac_kdc_key, *pac_member_key;
304 struct auth_user_info_dc *user_info_dc_out;
306 krb5_keyblock server_keyblock;
307 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
308 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
310 krb5_error_code ret;
311 struct smb_krb5_context *smb_krb5_context;
313 const char *principal_string;
314 char *broken_principal_string;
315 krb5_principal client_principal;
316 const char *authtime_string;
317 time_t authtime;
318 TALLOC_CTX *mem_ctx = tctx;
320 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
321 tctx->lp_ctx,
322 &smb_krb5_context),
323 "smb_krb5_init_context");
325 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
326 "B286757148AF7FD252C53603A150B7E7");
328 pac_member_key = torture_setting_string(tctx, "pac_member_key",
329 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
331 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
332 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
334 /* The krbtgt key in use when the above PAC was generated.
335 * This is an arcfour-hmac-md5 key, extracted with our 'net
336 * samdump' tool. */
337 if (*pac_kdc_key == 0) {
338 krbtgt_bytes = NULL;
339 } else {
340 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
341 if (!krbtgt_bytes) {
342 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
346 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
347 if (!krbsrv_bytes) {
348 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
351 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
352 ENCTYPE_ARCFOUR_HMAC,
353 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
354 &server_keyblock);
355 torture_assert(tctx, !ret,
356 talloc_asprintf(tctx,
357 "(saved test) Server Keyblock encoding failed: %s",
358 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
359 ret, mem_ctx)));
361 if (krbtgt_bytes) {
362 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
363 ENCTYPE_ARCFOUR_HMAC,
364 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
365 &krbtgt_keyblock);
366 if (ret) {
367 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
368 &server_keyblock);
369 torture_fail(tctx,
370 talloc_asprintf(tctx,
371 "(saved test) Server Keyblock encoding failed: %s",
372 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
373 ret, mem_ctx)));
375 krbtgt_keyblock_p = &krbtgt_keyblock;
376 } else {
377 krbtgt_keyblock_p = NULL;
380 pac_file = torture_setting_string(tctx, "pac_file", NULL);
381 if (pac_file) {
382 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
383 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
384 } else {
385 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
388 dump_data(10,tmp_blob.data,tmp_blob.length);
390 principal_string = torture_setting_string(tctx, "pac_client_principal",
391 "w2003final$@WIN2K3.THINKER.LOCAL");
393 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
394 authtime = strtoull(authtime_string, NULL, 0);
396 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
397 &client_principal);
398 if (ret) {
399 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
400 krbtgt_keyblock_p);
401 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
402 &server_keyblock);
403 torture_fail(tctx,
404 talloc_asprintf(tctx,
405 "(saved test) parsing of client principal [%s] failed: %s",
406 principal_string,
407 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
410 /* Decode and verify the signaure on the PAC */
411 nt_status = kerberos_decode_pac(mem_ctx,
412 tmp_blob,
413 smb_krb5_context->krb5_context,
414 krbtgt_keyblock_p,
415 &server_keyblock,
416 client_principal, authtime, &pac_data);
417 if (!NT_STATUS_IS_OK(nt_status)) {
418 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
419 krbtgt_keyblock_p);
420 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
421 &server_keyblock);
422 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
424 torture_fail(tctx, talloc_asprintf(tctx,
425 "(saved test) PAC decoding failed: %s",
426 nt_errstr(nt_status)));
429 /* Now check we can read it back (using Heimdal's pac parsing) */
430 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
431 tmp_blob,
432 smb_krb5_context->krb5_context,
433 &user_info_dc_out,
434 NULL, NULL);
436 if (!NT_STATUS_IS_OK(nt_status)) {
437 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
438 krbtgt_keyblock_p);
439 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
440 &server_keyblock);
441 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
443 torture_fail(tctx, talloc_asprintf(tctx,
444 "(saved test) Heimdal PAC decoding failed: %s",
445 nt_errstr(nt_status)));
448 if (!pac_file &&
449 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
450 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
451 user_info_dc_out->sids)) {
452 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
453 krbtgt_keyblock_p);
454 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
455 &server_keyblock);
456 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
458 torture_fail(tctx,
459 talloc_asprintf(tctx,
460 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
461 "S-1-5-21-3048156945-3961193616-3706469200-1005",
462 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
465 talloc_free(user_info_dc_out);
467 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
468 nt_status = kerberos_pac_logon_info(mem_ctx,
469 tmp_blob,
470 smb_krb5_context->krb5_context,
471 krbtgt_keyblock_p,
472 &server_keyblock,
473 client_principal, authtime, &logon_info);
475 if (!NT_STATUS_IS_OK(nt_status)) {
476 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
477 krbtgt_keyblock_p);
478 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
479 &server_keyblock);
480 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
482 torture_fail(tctx,
483 talloc_asprintf(tctx,
484 "(saved test) PAC decoding (for logon info) failed: %s",
485 nt_errstr(nt_status)));
488 validation.sam3 = &logon_info->info3;
489 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
491 3, &validation,
492 true, /* This user was authenticated */
493 &user_info_dc_out);
494 if (!NT_STATUS_IS_OK(nt_status)) {
495 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
496 krbtgt_keyblock_p);
497 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
498 &server_keyblock);
499 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
501 torture_fail(tctx,
502 talloc_asprintf(tctx,
503 "(saved test) PAC decoding (make server info) failed: %s",
504 nt_errstr(nt_status)));
507 if (!pac_file &&
508 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
509 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
510 user_info_dc_out->sids)) {
511 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
512 krbtgt_keyblock_p);
513 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
514 &server_keyblock);
515 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
517 torture_fail(tctx,
518 talloc_asprintf(tctx,
519 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
520 "S-1-5-21-3048156945-3961193616-3706469200-1005",
521 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
524 if (krbtgt_bytes == NULL) {
525 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
526 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
527 &server_keyblock);
528 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
529 return true;
532 ret = kerberos_encode_pac(mem_ctx,
533 pac_data,
534 smb_krb5_context->krb5_context,
535 krbtgt_keyblock_p,
536 &server_keyblock,
537 &validate_blob);
539 if (ret != 0) {
540 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
541 krbtgt_keyblock_p);
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 torture_fail(tctx, "(saved test) PAC push failed");
549 dump_data(10, validate_blob.data, validate_blob.length);
551 /* compare both the length and the data bytes after a
552 * pull/push cycle. This ensures we use the exact same
553 * pointer, padding etc algorithms as win2k3.
555 if (tmp_blob.length != validate_blob.length) {
556 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
557 krbtgt_keyblock_p);
558 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
559 &server_keyblock);
560 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
562 torture_fail(tctx,
563 talloc_asprintf(tctx,
564 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
565 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
568 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
569 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
570 krbtgt_keyblock_p);
571 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
572 &server_keyblock);
573 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
575 DEBUG(0, ("tmp_data:\n"));
576 dump_data(0, tmp_blob.data, tmp_blob.length);
577 DEBUG(0, ("validate_blob:\n"));
578 dump_data(0, validate_blob.data, validate_blob.length);
580 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
583 ret = kerberos_create_pac(mem_ctx,
584 user_info_dc_out,
585 smb_krb5_context->krb5_context,
586 krbtgt_keyblock_p,
587 &server_keyblock,
588 client_principal, authtime,
589 &validate_blob);
591 if (ret != 0) {
592 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
593 krbtgt_keyblock_p);
594 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
595 &server_keyblock);
596 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
598 torture_fail(tctx, "(saved test) regnerated PAC create failed");
601 dump_data(10,validate_blob.data,validate_blob.length);
603 /* compare both the length and the data bytes after a
604 * pull/push cycle. This ensures we use the exact same
605 * pointer, padding etc algorithms as win2k3.
607 if (tmp_blob.length != validate_blob.length) {
608 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
609 &pac_data2,
610 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
611 nt_status = ndr_map_error2ntstatus(ndr_err);
612 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
614 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
616 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
618 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
619 krbtgt_keyblock_p);
620 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
621 &server_keyblock);
622 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
624 torture_fail(tctx, talloc_asprintf(tctx,
625 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
626 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
629 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
630 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
631 &pac_data2,
632 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
633 nt_status = ndr_map_error2ntstatus(ndr_err);
634 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
636 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
638 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
640 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
641 krbtgt_keyblock_p);
642 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
643 &server_keyblock);
644 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
646 DEBUG(0, ("tmp_data:\n"));
647 dump_data(0, tmp_blob.data, tmp_blob.length);
648 DEBUG(0, ("validate_blob:\n"));
649 dump_data(0, validate_blob.data, validate_blob.length);
651 torture_fail(tctx, talloc_asprintf(tctx,
652 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
655 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
656 nt_status = kerberos_decode_pac(mem_ctx,
657 tmp_blob,
658 smb_krb5_context->krb5_context,
659 krbtgt_keyblock_p,
660 &server_keyblock,
661 client_principal,
662 authtime + 1, &pac_data);
663 if (NT_STATUS_IS_OK(nt_status)) {
665 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
666 krbtgt_keyblock_p);
667 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
668 &server_keyblock);
669 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
670 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
673 /* Break the client principal */
674 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
676 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
677 broken_principal_string[0]++;
679 ret = krb5_parse_name(smb_krb5_context->krb5_context,
680 broken_principal_string, &client_principal);
681 if (ret) {
683 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
684 krbtgt_keyblock_p);
685 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
686 &server_keyblock);
687 torture_fail(tctx, talloc_asprintf(tctx,
688 "(saved test) parsing of broken client principal failed: %s",
689 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
692 nt_status = kerberos_decode_pac(mem_ctx,
693 tmp_blob,
694 smb_krb5_context->krb5_context,
695 krbtgt_keyblock_p,
696 &server_keyblock,
697 client_principal,
698 authtime, &pac_data);
699 if (NT_STATUS_IS_OK(nt_status)) {
700 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
701 krbtgt_keyblock_p);
702 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
703 &server_keyblock);
704 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
707 /* Finally... Bugger up the signature, and check we fail the checksum */
708 tmp_blob.data[tmp_blob.length - 2]++;
710 nt_status = kerberos_decode_pac(mem_ctx,
711 tmp_blob,
712 smb_krb5_context->krb5_context,
713 krbtgt_keyblock_p,
714 &server_keyblock,
715 client_principal,
716 authtime,
717 &pac_data);
718 if (NT_STATUS_IS_OK(nt_status)) {
719 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
720 krbtgt_keyblock_p);
721 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
722 &server_keyblock);
723 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
726 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
727 krbtgt_keyblock_p);
728 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
729 &server_keyblock);
730 return true;
733 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
735 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
737 torture_suite_add_simple_test(suite, "self check",
738 torture_pac_self_check);
739 torture_suite_add_simple_test(suite, "saved check",
740 torture_pac_saved_check);
741 return suite;