s4-smbtorture: Make test names lowercase and dot-separated.
[Samba.git] / source4 / torture / auth / pac.c
blob13796bd3db9849a1c90d8812831d2630eeda4079
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"
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,
60 NULL,
61 tctx->lp_ctx,
62 &smb_krb5_context),
63 "smb_krb5_init_context");
65 generate_random_buffer(server_bytes, 16);
66 generate_random_buffer(krbtgt_bytes, 16);
68 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
69 ENCTYPE_ARCFOUR_HMAC,
70 server_bytes, sizeof(server_bytes),
71 &server_keyblock);
72 torture_assert(tctx, !ret, talloc_asprintf(tctx,
73 "(self test) Server Keyblock encoding failed: %s",
74 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
75 ret, mem_ctx)));
77 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
78 ENCTYPE_ARCFOUR_HMAC,
79 krbtgt_bytes, sizeof(krbtgt_bytes),
80 &krbtgt_keyblock);
81 if (ret) {
82 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
83 ret, mem_ctx);
85 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
86 &server_keyblock);
88 torture_fail(tctx, talloc_asprintf(tctx,
89 "(self test) KRBTGT Keyblock encoding failed: %s", err));
92 /* We need an input, and this one requires no underlying database */
93 nt_status = auth_anonymous_server_info(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &server_info);
95 if (!NT_STATUS_IS_OK(nt_status)) {
96 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
97 &server_keyblock);
98 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
99 &krbtgt_keyblock);
100 torture_fail(tctx, "auth_anonymous_server_info");
103 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
104 server_info->account_name,
105 KRB5_PRINCIPAL_PARSE_NO_REALM,
106 &client_principal);
107 if (ret) {
108 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
109 &server_keyblock);
110 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
111 &krbtgt_keyblock);
112 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
115 /* OK, go ahead and make a PAC */
116 ret = kerberos_create_pac(mem_ctx,
117 server_info,
118 smb_krb5_context->krb5_context,
119 &krbtgt_keyblock,
120 &server_keyblock,
121 client_principal,
122 logon_time,
123 &tmp_blob);
125 if (ret) {
126 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
127 &krbtgt_keyblock);
128 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
129 &server_keyblock);
130 krb5_free_principal(smb_krb5_context->krb5_context,
131 client_principal);
133 torture_fail(tctx, talloc_asprintf(tctx,
134 "(self test) PAC encoding failed: %s",
135 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
136 ret, mem_ctx)));
139 dump_data(10,tmp_blob.data,tmp_blob.length);
141 /* Now check that we can read it back (using full decode and validate) */
142 nt_status = kerberos_decode_pac(mem_ctx,
143 &pac_data,
144 tmp_blob,
145 smb_krb5_context->krb5_context,
146 &krbtgt_keyblock,
147 &server_keyblock,
148 client_principal,
149 logon_time, NULL);
151 if (!NT_STATUS_IS_OK(nt_status)) {
152 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
153 &krbtgt_keyblock);
154 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
155 &server_keyblock);
156 krb5_free_principal(smb_krb5_context->krb5_context,
157 client_principal);
159 torture_fail(tctx, talloc_asprintf(tctx,
160 "(self test) PAC decoding failed: %s",
161 nt_errstr(nt_status)));
164 /* Now check we can read it back (using Heimdal's pac parsing) */
165 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
166 tmp_blob,
167 smb_krb5_context->krb5_context,
168 &server_info_out);
170 if (!dom_sid_equal(server_info->account_sid,
171 server_info_out->account_sid)) {
172 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
173 &krbtgt_keyblock);
174 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
175 &server_keyblock);
176 krb5_free_principal(smb_krb5_context->krb5_context,
177 client_principal);
179 torture_fail(tctx,
180 talloc_asprintf(tctx,
181 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
182 dom_sid_string(mem_ctx, server_info->account_sid),
183 dom_sid_string(mem_ctx, server_info_out->account_sid)));
185 talloc_free(server_info_out);
187 /* Now check that we can read it back (yet again) */
188 nt_status = kerberos_pac_logon_info(mem_ctx,
189 &logon_info,
190 tmp_blob,
191 smb_krb5_context->krb5_context,
192 &krbtgt_keyblock,
193 &server_keyblock,
194 client_principal,
195 logon_time,
196 NULL);
198 if (!NT_STATUS_IS_OK(nt_status)) {
199 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
200 &krbtgt_keyblock);
201 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
202 &server_keyblock);
203 krb5_free_principal(smb_krb5_context->krb5_context,
204 client_principal);
206 torture_fail(tctx,
207 talloc_asprintf(tctx,
208 "(self test) PAC decoding (for logon info) failed: %s",
209 nt_errstr(nt_status)));
212 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
213 &krbtgt_keyblock);
214 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
215 &server_keyblock);
216 krb5_free_principal(smb_krb5_context->krb5_context,
217 client_principal);
219 /* And make a server info from the samba-parsed PAC */
220 validation.sam3 = &logon_info->info3;
221 nt_status = make_server_info_netlogon_validation(mem_ctx,
223 3, &validation,
224 &server_info_out);
225 if (!NT_STATUS_IS_OK(nt_status)) {
226 torture_fail(tctx,
227 talloc_asprintf(tctx,
228 "(self test) PAC decoding (make server info) failed: %s",
229 nt_errstr(nt_status)));
232 if (!dom_sid_equal(server_info->account_sid,
233 server_info_out->account_sid)) {
234 torture_fail(tctx,
235 talloc_asprintf(tctx,
236 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
237 dom_sid_string(mem_ctx, server_info->account_sid),
238 dom_sid_string(mem_ctx, server_info_out->account_sid)));
240 return true;
244 /* This is the PAC generated on my test network, by my test Win2k3 server.
245 -- abartlet 2005-07-04
248 static const uint8_t saved_pac[] = {
249 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
250 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
251 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
252 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
253 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
254 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
255 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
256 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
257 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
258 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
261 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
262 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
264 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
269 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
270 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
275 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
276 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
277 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
278 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
279 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
280 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
281 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
282 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
284 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
285 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
286 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
287 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
290 /* Check with a known 'well formed' PAC, from my test server */
291 static bool torture_pac_saved_check(struct torture_context *tctx)
293 NTSTATUS nt_status;
294 enum ndr_err_code ndr_err;
295 DATA_BLOB tmp_blob, validate_blob;
296 struct PAC_DATA *pac_data, pac_data2;
297 struct PAC_LOGON_INFO *logon_info;
298 union netr_Validation validation;
299 const char *pac_file, *pac_kdc_key, *pac_member_key;
300 struct auth_serversupplied_info *server_info_out;
302 krb5_keyblock server_keyblock;
303 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
304 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
306 krb5_error_code ret;
307 struct smb_krb5_context *smb_krb5_context;
309 const char *principal_string;
310 char *broken_principal_string;
311 krb5_principal client_principal;
312 const char *authtime_string;
313 time_t authtime;
314 TALLOC_CTX *mem_ctx = tctx;
316 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
317 tctx->lp_ctx,
318 &smb_krb5_context),
319 "smb_krb5_init_context");
321 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
322 "B286757148AF7FD252C53603A150B7E7");
324 pac_member_key = torture_setting_string(tctx, "pac_member_key",
325 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
327 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
328 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
330 /* The krbtgt key in use when the above PAC was generated.
331 * This is an arcfour-hmac-md5 key, extracted with our 'net
332 * samdump' tool. */
333 if (*pac_kdc_key == 0) {
334 krbtgt_bytes = NULL;
335 } else {
336 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
337 if (!krbtgt_bytes) {
338 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
342 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
343 if (!krbsrv_bytes) {
344 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
347 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
348 ENCTYPE_ARCFOUR_HMAC,
349 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
350 &server_keyblock);
351 torture_assert(tctx, !ret,
352 talloc_asprintf(tctx,
353 "(saved test) Server Keyblock encoding failed: %s",
354 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
355 ret, mem_ctx)));
357 if (krbtgt_bytes) {
358 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
359 ENCTYPE_ARCFOUR_HMAC,
360 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
361 &krbtgt_keyblock);
362 if (ret) {
363 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
364 &server_keyblock);
365 torture_fail(tctx,
366 talloc_asprintf(tctx,
367 "(saved test) Server Keyblock encoding failed: %s",
368 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
369 ret, mem_ctx)));
371 krbtgt_keyblock_p = &krbtgt_keyblock;
372 } else {
373 krbtgt_keyblock_p = NULL;
376 pac_file = torture_setting_string(tctx, "pac_file", NULL);
377 if (pac_file) {
378 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
379 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
380 } else {
381 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
384 dump_data(10,tmp_blob.data,tmp_blob.length);
386 principal_string = torture_setting_string(tctx, "pac_client_principal",
387 "w2003final$@WIN2K3.THINKER.LOCAL");
389 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
390 authtime = strtoull(authtime_string, NULL, 0);
392 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
393 &client_principal);
394 if (ret) {
395 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
396 krbtgt_keyblock_p);
397 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
398 &server_keyblock);
399 torture_fail(tctx,
400 talloc_asprintf(tctx,
401 "(saved test) parsing of client principal [%s] failed: %s",
402 principal_string,
403 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
406 /* Decode and verify the signaure on the PAC */
407 nt_status = kerberos_decode_pac(mem_ctx,
408 &pac_data,
409 tmp_blob,
410 smb_krb5_context->krb5_context,
411 krbtgt_keyblock_p,
412 &server_keyblock,
413 client_principal, authtime, NULL);
414 if (!NT_STATUS_IS_OK(nt_status)) {
415 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
416 krbtgt_keyblock_p);
417 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
418 &server_keyblock);
419 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
421 torture_fail(tctx, talloc_asprintf(tctx,
422 "(saved test) PAC decoding failed: %s",
423 nt_errstr(nt_status)));
426 /* Now check we can read it back (using Heimdal's pac parsing) */
427 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
428 tmp_blob,
429 smb_krb5_context->krb5_context,
430 &server_info_out);
432 if (!NT_STATUS_IS_OK(nt_status)) {
433 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
434 krbtgt_keyblock_p);
435 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
436 &server_keyblock);
437 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
439 torture_fail(tctx, talloc_asprintf(tctx,
440 "(saved test) Heimdal PAC decoding failed: %s",
441 nt_errstr(nt_status)));
444 if (!pac_file &&
445 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
446 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
447 server_info_out->account_sid)) {
448 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
449 krbtgt_keyblock_p);
450 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
451 &server_keyblock);
452 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
454 torture_fail(tctx,
455 talloc_asprintf(tctx,
456 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
457 "S-1-5-21-3048156945-3961193616-3706469200-1005",
458 dom_sid_string(mem_ctx, server_info_out->account_sid)));
461 talloc_free(server_info_out);
463 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
464 nt_status = kerberos_pac_logon_info(mem_ctx,
465 &logon_info,
466 tmp_blob,
467 smb_krb5_context->krb5_context,
468 krbtgt_keyblock_p,
469 &server_keyblock,
470 client_principal, authtime, NULL);
472 if (!NT_STATUS_IS_OK(nt_status)) {
473 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
474 krbtgt_keyblock_p);
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 torture_fail(tctx,
480 talloc_asprintf(tctx,
481 "(saved test) PAC decoding (for logon info) failed: %s",
482 nt_errstr(nt_status)));
485 validation.sam3 = &logon_info->info3;
486 nt_status = make_server_info_netlogon_validation(mem_ctx,
488 3, &validation,
489 &server_info_out);
490 if (!NT_STATUS_IS_OK(nt_status)) {
491 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
492 krbtgt_keyblock_p);
493 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
494 &server_keyblock);
495 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
497 torture_fail(tctx,
498 talloc_asprintf(tctx,
499 "(saved test) PAC decoding (make server info) failed: %s",
500 nt_errstr(nt_status)));
503 if (!pac_file &&
504 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
505 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
506 server_info_out->account_sid)) {
507 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
508 krbtgt_keyblock_p);
509 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
510 &server_keyblock);
511 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
513 torture_fail(tctx,
514 talloc_asprintf(tctx,
515 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
516 "S-1-5-21-3048156945-3961193616-3706469200-1005",
517 dom_sid_string(mem_ctx, server_info_out->account_sid)));
520 if (krbtgt_bytes == NULL) {
521 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
522 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
523 &server_keyblock);
524 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
525 return true;
528 ret = kerberos_encode_pac(mem_ctx,
529 pac_data,
530 smb_krb5_context->krb5_context,
531 krbtgt_keyblock_p,
532 &server_keyblock,
533 &validate_blob);
535 if (ret != 0) {
536 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
537 krbtgt_keyblock_p);
538 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
539 &server_keyblock);
540 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
542 torture_fail(tctx, "(saved test) PAC push failed");
545 dump_data(10, validate_blob.data, validate_blob.length);
547 /* compare both the length and the data bytes after a
548 * pull/push cycle. This ensures we use the exact same
549 * pointer, padding etc algorithms as win2k3.
551 if (tmp_blob.length != validate_blob.length) {
552 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
553 krbtgt_keyblock_p);
554 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
555 &server_keyblock);
556 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
558 torture_fail(tctx,
559 talloc_asprintf(tctx,
560 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
561 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
564 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
565 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
566 krbtgt_keyblock_p);
567 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
568 &server_keyblock);
569 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
571 DEBUG(0, ("tmp_data:\n"));
572 dump_data(0, tmp_blob.data, tmp_blob.length);
573 DEBUG(0, ("validate_blob:\n"));
574 dump_data(0, validate_blob.data, validate_blob.length);
576 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
579 ret = kerberos_create_pac(mem_ctx,
580 server_info_out,
581 smb_krb5_context->krb5_context,
582 krbtgt_keyblock_p,
583 &server_keyblock,
584 client_principal, authtime,
585 &validate_blob);
587 if (ret != 0) {
588 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
589 krbtgt_keyblock_p);
590 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
591 &server_keyblock);
592 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
594 torture_fail(tctx, "(saved test) regnerated PAC create failed");
597 dump_data(10,validate_blob.data,validate_blob.length);
599 /* compare both the length and the data bytes after a
600 * pull/push cycle. This ensures we use the exact same
601 * pointer, padding etc algorithms as win2k3.
603 if (tmp_blob.length != validate_blob.length) {
604 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
605 &pac_data2,
606 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
607 nt_status = ndr_map_error2ntstatus(ndr_err);
608 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
610 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
612 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
614 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
615 krbtgt_keyblock_p);
616 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
617 &server_keyblock);
618 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
620 torture_fail(tctx, talloc_asprintf(tctx,
621 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
622 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
625 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
626 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
627 &pac_data2,
628 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
629 nt_status = ndr_map_error2ntstatus(ndr_err);
630 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
632 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
634 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
636 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
637 krbtgt_keyblock_p);
638 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
639 &server_keyblock);
640 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
642 DEBUG(0, ("tmp_data:\n"));
643 dump_data(0, tmp_blob.data, tmp_blob.length);
644 DEBUG(0, ("validate_blob:\n"));
645 dump_data(0, validate_blob.data, validate_blob.length);
647 torture_fail(tctx, talloc_asprintf(tctx,
648 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
651 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
652 nt_status = kerberos_decode_pac(mem_ctx,
653 &pac_data,
654 tmp_blob,
655 smb_krb5_context->krb5_context,
656 krbtgt_keyblock_p,
657 &server_keyblock,
658 client_principal,
659 authtime + 1, NULL);
660 if (NT_STATUS_IS_OK(nt_status)) {
662 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
663 krbtgt_keyblock_p);
664 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
665 &server_keyblock);
666 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
667 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
670 /* Break the client principal */
671 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
673 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
674 broken_principal_string[0]++;
676 ret = krb5_parse_name(smb_krb5_context->krb5_context,
677 broken_principal_string, &client_principal);
678 if (ret) {
680 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
681 krbtgt_keyblock_p);
682 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
683 &server_keyblock);
684 torture_fail(tctx, talloc_asprintf(tctx,
685 "(saved test) parsing of broken client principal failed: %s",
686 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
689 nt_status = kerberos_decode_pac(mem_ctx,
690 &pac_data,
691 tmp_blob,
692 smb_krb5_context->krb5_context,
693 krbtgt_keyblock_p,
694 &server_keyblock,
695 client_principal,
696 authtime, NULL);
697 if (NT_STATUS_IS_OK(nt_status)) {
698 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
699 krbtgt_keyblock_p);
700 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
701 &server_keyblock);
702 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
705 /* Finally... Bugger up the signature, and check we fail the checksum */
706 tmp_blob.data[tmp_blob.length - 2]++;
708 nt_status = kerberos_decode_pac(mem_ctx,
709 &pac_data,
710 tmp_blob,
711 smb_krb5_context->krb5_context,
712 krbtgt_keyblock_p,
713 &server_keyblock,
714 client_principal,
715 authtime, NULL);
716 if (NT_STATUS_IS_OK(nt_status)) {
717 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
718 krbtgt_keyblock_p);
719 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
720 &server_keyblock);
721 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
724 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
725 krbtgt_keyblock_p);
726 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
727 &server_keyblock);
728 return true;
731 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
733 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
735 torture_suite_add_simple_test(suite, "self check",
736 torture_pac_self_check);
737 torture_suite_add_simple_test(suite, "saved check",
738 torture_pac_saved_check);
739 return suite;