s3 swat: Allow getting the user's HTTP auth password
[Samba.git] / source4 / torture / auth / pac.c
blobfd54863686ca323d4b774e6d9e74bfe7d30aac0e
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 "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "samba3/samba3.h"
29 #include "libcli/security/security.h"
30 #include "torture/torture.h"
31 #include "auth/auth_sam_reply.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, lp_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 lp_iconv_convenience(tctx->lp_ctx),
118 server_info,
119 smb_krb5_context->krb5_context,
120 &krbtgt_keyblock,
121 &server_keyblock,
122 client_principal,
123 logon_time,
124 &tmp_blob);
126 if (ret) {
127 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
128 &krbtgt_keyblock);
129 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
130 &server_keyblock);
131 krb5_free_principal(smb_krb5_context->krb5_context,
132 client_principal);
134 torture_fail(tctx, talloc_asprintf(tctx,
135 "(self test) PAC encoding failed: %s",
136 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
137 ret, mem_ctx)));
140 dump_data(10,tmp_blob.data,tmp_blob.length);
142 /* Now check that we can read it back (using full decode and validate) */
143 nt_status = kerberos_decode_pac(mem_ctx,
144 lp_iconv_convenience(tctx->lp_ctx),
145 &pac_data,
146 tmp_blob,
147 smb_krb5_context->krb5_context,
148 &krbtgt_keyblock,
149 &server_keyblock,
150 client_principal,
151 logon_time, NULL);
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_server_info(mem_ctx,
168 lp_iconv_convenience(tctx->lp_ctx),
169 tmp_blob,
170 smb_krb5_context->krb5_context,
171 &server_info_out);
173 if (!dom_sid_equal(server_info->account_sid,
174 server_info_out->account_sid)) {
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, server_info->account_sid),
186 dom_sid_string(mem_ctx, server_info_out->account_sid)));
188 talloc_free(server_info_out);
190 /* Now check that we can read it back (yet again) */
191 nt_status = kerberos_pac_logon_info(mem_ctx,
192 lp_iconv_convenience(tctx->lp_ctx),
193 &logon_info,
194 tmp_blob,
195 smb_krb5_context->krb5_context,
196 &krbtgt_keyblock,
197 &server_keyblock,
198 client_principal,
199 logon_time,
200 NULL);
202 if (!NT_STATUS_IS_OK(nt_status)) {
203 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
204 &krbtgt_keyblock);
205 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
206 &server_keyblock);
207 krb5_free_principal(smb_krb5_context->krb5_context,
208 client_principal);
210 torture_fail(tctx,
211 talloc_asprintf(tctx,
212 "(self test) PAC decoding (for logon info) failed: %s",
213 nt_errstr(nt_status)));
216 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
217 &krbtgt_keyblock);
218 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
219 &server_keyblock);
220 krb5_free_principal(smb_krb5_context->krb5_context,
221 client_principal);
223 /* And make a server info from the samba-parsed PAC */
224 validation.sam3 = &logon_info->info3;
225 nt_status = make_server_info_netlogon_validation(mem_ctx,
227 3, &validation,
228 &server_info_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(server_info->account_sid,
237 server_info_out->account_sid)) {
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, server_info->account_sid),
242 dom_sid_string(mem_ctx, server_info_out->account_sid)));
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_serversupplied_info *server_info_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 = krb5_keyblock_init(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 = krb5_keyblock_init(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 lp_iconv_convenience(tctx->lp_ctx),
413 &pac_data,
414 tmp_blob,
415 smb_krb5_context->krb5_context,
416 krbtgt_keyblock_p,
417 &server_keyblock,
418 client_principal, authtime, NULL);
419 if (!NT_STATUS_IS_OK(nt_status)) {
420 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
421 krbtgt_keyblock_p);
422 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
423 &server_keyblock);
424 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
426 torture_fail(tctx, talloc_asprintf(tctx,
427 "(saved test) PAC decoding failed: %s",
428 nt_errstr(nt_status)));
431 /* Now check we can read it back (using Heimdal's pac parsing) */
432 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
433 lp_iconv_convenience(tctx->lp_ctx),
434 tmp_blob,
435 smb_krb5_context->krb5_context,
436 &server_info_out);
438 if (!NT_STATUS_IS_OK(nt_status)) {
439 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
440 krbtgt_keyblock_p);
441 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
442 &server_keyblock);
443 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
445 torture_fail(tctx, talloc_asprintf(tctx,
446 "(saved test) Heimdal PAC decoding failed: %s",
447 nt_errstr(nt_status)));
450 if (!pac_file &&
451 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
452 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
453 server_info_out->account_sid)) {
454 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
455 krbtgt_keyblock_p);
456 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
457 &server_keyblock);
458 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
460 torture_fail(tctx,
461 talloc_asprintf(tctx,
462 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
463 "S-1-5-21-3048156945-3961193616-3706469200-1005",
464 dom_sid_string(mem_ctx, server_info_out->account_sid)));
467 talloc_free(server_info_out);
469 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
470 nt_status = kerberos_pac_logon_info(mem_ctx,
471 lp_iconv_convenience(tctx->lp_ctx),
472 &logon_info,
473 tmp_blob,
474 smb_krb5_context->krb5_context,
475 krbtgt_keyblock_p,
476 &server_keyblock,
477 client_principal, authtime, NULL);
479 if (!NT_STATUS_IS_OK(nt_status)) {
480 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
481 krbtgt_keyblock_p);
482 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
483 &server_keyblock);
484 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
486 torture_fail(tctx,
487 talloc_asprintf(tctx,
488 "(saved test) PAC decoding (for logon info) failed: %s",
489 nt_errstr(nt_status)));
492 validation.sam3 = &logon_info->info3;
493 nt_status = make_server_info_netlogon_validation(mem_ctx,
495 3, &validation,
496 &server_info_out);
497 if (!NT_STATUS_IS_OK(nt_status)) {
498 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
499 krbtgt_keyblock_p);
500 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
501 &server_keyblock);
502 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
504 torture_fail(tctx,
505 talloc_asprintf(tctx,
506 "(saved test) PAC decoding (make server info) failed: %s",
507 nt_errstr(nt_status)));
510 if (!pac_file &&
511 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
512 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
513 server_info_out->account_sid)) {
514 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
515 krbtgt_keyblock_p);
516 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
517 &server_keyblock);
518 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
520 torture_fail(tctx,
521 talloc_asprintf(tctx,
522 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
523 "S-1-5-21-3048156945-3961193616-3706469200-1005",
524 dom_sid_string(mem_ctx, server_info_out->account_sid)));
527 if (krbtgt_bytes == NULL) {
528 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
529 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
530 &server_keyblock);
531 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
532 return true;
535 ret = kerberos_encode_pac(mem_ctx,
536 lp_iconv_convenience(tctx->lp_ctx),
537 pac_data,
538 smb_krb5_context->krb5_context,
539 krbtgt_keyblock_p,
540 &server_keyblock,
541 &validate_blob);
543 if (ret != 0) {
544 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
545 krbtgt_keyblock_p);
546 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
547 &server_keyblock);
548 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
550 torture_fail(tctx, "(saved test) PAC push failed");
553 dump_data(10, validate_blob.data, validate_blob.length);
555 /* compare both the length and the data bytes after a
556 * pull/push cycle. This ensures we use the exact same
557 * pointer, padding etc algorithms as win2k3.
559 if (tmp_blob.length != validate_blob.length) {
560 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
561 krbtgt_keyblock_p);
562 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
563 &server_keyblock);
564 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
566 torture_fail(tctx,
567 talloc_asprintf(tctx,
568 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
569 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
572 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
573 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
574 krbtgt_keyblock_p);
575 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
576 &server_keyblock);
577 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
579 DEBUG(0, ("tmp_data:\n"));
580 dump_data(0, tmp_blob.data, tmp_blob.length);
581 DEBUG(0, ("validate_blob:\n"));
582 dump_data(0, validate_blob.data, validate_blob.length);
584 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
587 ret = kerberos_create_pac(mem_ctx,
588 lp_iconv_convenience(tctx->lp_ctx),
589 server_info_out,
590 smb_krb5_context->krb5_context,
591 krbtgt_keyblock_p,
592 &server_keyblock,
593 client_principal, authtime,
594 &validate_blob);
596 if (ret != 0) {
597 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
598 krbtgt_keyblock_p);
599 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
600 &server_keyblock);
601 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
603 torture_fail(tctx, "(saved test) regnerated PAC create failed");
606 dump_data(10,validate_blob.data,validate_blob.length);
608 /* compare both the length and the data bytes after a
609 * pull/push cycle. This ensures we use the exact same
610 * pointer, padding etc algorithms as win2k3.
612 if (tmp_blob.length != validate_blob.length) {
613 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
614 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
615 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
616 nt_status = ndr_map_error2ntstatus(ndr_err);
617 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
619 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
621 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
623 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
624 krbtgt_keyblock_p);
625 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
626 &server_keyblock);
627 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
629 torture_fail(tctx, talloc_asprintf(tctx,
630 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
631 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
634 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
635 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
636 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
637 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
638 nt_status = ndr_map_error2ntstatus(ndr_err);
639 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
641 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
643 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
645 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
646 krbtgt_keyblock_p);
647 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
648 &server_keyblock);
649 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
651 DEBUG(0, ("tmp_data:\n"));
652 dump_data(0, tmp_blob.data, tmp_blob.length);
653 DEBUG(0, ("validate_blob:\n"));
654 dump_data(0, validate_blob.data, validate_blob.length);
656 torture_fail(tctx, talloc_asprintf(tctx,
657 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
660 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
661 nt_status = kerberos_decode_pac(mem_ctx,
662 lp_iconv_convenience(tctx->lp_ctx),
663 &pac_data,
664 tmp_blob,
665 smb_krb5_context->krb5_context,
666 krbtgt_keyblock_p,
667 &server_keyblock,
668 client_principal,
669 authtime + 1, NULL);
670 if (NT_STATUS_IS_OK(nt_status)) {
672 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
673 krbtgt_keyblock_p);
674 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
675 &server_keyblock);
676 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
677 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
680 /* Break the client principal */
681 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
683 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
684 broken_principal_string[0]++;
686 ret = krb5_parse_name(smb_krb5_context->krb5_context,
687 broken_principal_string, &client_principal);
688 if (ret) {
690 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
691 krbtgt_keyblock_p);
692 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
693 &server_keyblock);
694 torture_fail(tctx, talloc_asprintf(tctx,
695 "(saved test) parsing of broken client principal failed: %s",
696 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
699 nt_status = kerberos_decode_pac(mem_ctx,
700 lp_iconv_convenience(tctx->lp_ctx),
701 &pac_data,
702 tmp_blob,
703 smb_krb5_context->krb5_context,
704 krbtgt_keyblock_p,
705 &server_keyblock,
706 client_principal,
707 authtime, NULL);
708 if (NT_STATUS_IS_OK(nt_status)) {
709 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
710 krbtgt_keyblock_p);
711 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
712 &server_keyblock);
713 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
716 /* Finally... Bugger up the signature, and check we fail the checksum */
717 tmp_blob.data[tmp_blob.length - 2]++;
719 nt_status = kerberos_decode_pac(mem_ctx,
720 lp_iconv_convenience(tctx->lp_ctx),
721 &pac_data,
722 tmp_blob,
723 smb_krb5_context->krb5_context,
724 krbtgt_keyblock_p,
725 &server_keyblock,
726 client_principal,
727 authtime, NULL);
728 if (NT_STATUS_IS_OK(nt_status)) {
729 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
730 krbtgt_keyblock_p);
731 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
732 &server_keyblock);
733 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
736 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
737 krbtgt_keyblock_p);
738 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
739 &server_keyblock);
740 return true;
743 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
745 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
747 torture_suite_add_simple_test(suite, "self check",
748 torture_pac_self_check);
749 torture_suite_add_simple_test(suite, "saved check",
750 torture_pac_saved_check);
751 return suite;