source: trunk/server/source4/torture/auth/pac.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 27.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Validate the krb5 pac generation routines
5
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7
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.
12
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.
17
18
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/>.
21*/
22
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
34static bool torture_pac_self_check(struct torture_context *tctx)
35{
36 NTSTATUS nt_status;
37 DATA_BLOB tmp_blob;
38 struct PAC_DATA *pac_data;
39 struct PAC_LOGON_INFO *logon_info;
40 union netr_Validation validation;
41
42 /* Generate a nice, arbitary keyblock */
43 uint8_t server_bytes[16];
44 uint8_t krbtgt_bytes[16];
45 krb5_keyblock server_keyblock;
46 krb5_keyblock krbtgt_keyblock;
47
48 krb5_error_code ret;
49
50 struct smb_krb5_context *smb_krb5_context;
51
52 struct auth_user_info_dc *user_info_dc;
53 struct auth_user_info_dc *user_info_dc_out;
54
55 krb5_principal client_principal;
56 time_t logon_time = time(NULL);
57
58 TALLOC_CTX *mem_ctx = tctx;
59
60 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx,
61 NULL,
62 tctx->lp_ctx,
63 &smb_krb5_context),
64 "smb_krb5_init_context");
65
66 generate_random_buffer(server_bytes, 16);
67 generate_random_buffer(krbtgt_bytes, 16);
68
69 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
70 ENCTYPE_ARCFOUR_HMAC,
71 server_bytes, sizeof(server_bytes),
72 &server_keyblock);
73 torture_assert(tctx, !ret, talloc_asprintf(tctx,
74 "(self test) Server Keyblock encoding failed: %s",
75 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
76 ret, mem_ctx)));
77
78 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
79 ENCTYPE_ARCFOUR_HMAC,
80 krbtgt_bytes, sizeof(krbtgt_bytes),
81 &krbtgt_keyblock);
82 if (ret) {
83 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context,
84 ret, mem_ctx);
85
86 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
87 &server_keyblock);
88
89 torture_fail(tctx, talloc_asprintf(tctx,
90 "(self test) KRBTGT Keyblock encoding failed: %s", err));
91 }
92
93 /* We need an input, and this one requires no underlying database */
94 nt_status = auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &user_info_dc);
95
96 if (!NT_STATUS_IS_OK(nt_status)) {
97 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
98 &server_keyblock);
99 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
100 &krbtgt_keyblock);
101 torture_fail(tctx, "auth_anonymous_user_info_dc");
102 }
103
104 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
105 user_info_dc->info->account_name,
106 KRB5_PRINCIPAL_PARSE_NO_REALM,
107 &client_principal);
108 if (ret) {
109 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
110 &server_keyblock);
111 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
112 &krbtgt_keyblock);
113 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
114 }
115
116 /* OK, go ahead and make a PAC */
117 ret = kerberos_create_pac(mem_ctx,
118 user_info_dc,
119 smb_krb5_context->krb5_context,
120 &krbtgt_keyblock,
121 &server_keyblock,
122 client_principal,
123 logon_time,
124 &tmp_blob);
125
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);
133
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)));
138 }
139
140 dump_data(10,tmp_blob.data,tmp_blob.length);
141
142 /* Now check that we can read it back (using full decode and validate) */
143 nt_status = kerberos_decode_pac(mem_ctx,
144 &pac_data,
145 tmp_blob,
146 smb_krb5_context->krb5_context,
147 &krbtgt_keyblock,
148 &server_keyblock,
149 client_principal,
150 logon_time, NULL);
151
152 if (!NT_STATUS_IS_OK(nt_status)) {
153 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
154 &krbtgt_keyblock);
155 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
156 &server_keyblock);
157 krb5_free_principal(smb_krb5_context->krb5_context,
158 client_principal);
159
160 torture_fail(tctx, talloc_asprintf(tctx,
161 "(self test) PAC decoding failed: %s",
162 nt_errstr(nt_status)));
163 }
164
165 /* Now check we can read it back (using Heimdal's pac parsing) */
166 nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
167 tmp_blob,
168 smb_krb5_context->krb5_context,
169 &user_info_dc_out, NULL, NULL);
170
171 /* The user's SID is the first element in the list */
172 if (!dom_sid_equal(user_info_dc->sids,
173 user_info_dc_out->sids)) {
174 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
175 &krbtgt_keyblock);
176 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
177 &server_keyblock);
178 krb5_free_principal(smb_krb5_context->krb5_context,
179 client_principal);
180
181 torture_fail(tctx,
182 talloc_asprintf(tctx,
183 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
184 dom_sid_string(mem_ctx, user_info_dc->sids),
185 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
186 }
187 talloc_free(user_info_dc_out);
188
189 /* Now check that we can read it back (yet again) */
190 nt_status = kerberos_pac_logon_info(mem_ctx,
191 &logon_info,
192 tmp_blob,
193 smb_krb5_context->krb5_context,
194 &krbtgt_keyblock,
195 &server_keyblock,
196 client_principal,
197 logon_time,
198 NULL);
199
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);
207
208 torture_fail(tctx,
209 talloc_asprintf(tctx,
210 "(self test) PAC decoding (for logon info) failed: %s",
211 nt_errstr(nt_status)));
212 }
213
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);
220
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,
224 "",
225 3, &validation,
226 &user_info_dc_out);
227 if (!NT_STATUS_IS_OK(nt_status)) {
228 torture_fail(tctx,
229 talloc_asprintf(tctx,
230 "(self test) PAC decoding (make server info) failed: %s",
231 nt_errstr(nt_status)));
232 }
233
234 if (!dom_sid_equal(user_info_dc->sids,
235 user_info_dc_out->sids)) {
236 torture_fail(tctx,
237 talloc_asprintf(tctx,
238 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
239 dom_sid_string(mem_ctx, user_info_dc->sids),
240 dom_sid_string(mem_ctx, user_info_dc_out->sids)));
241 }
242 return true;
243}
244
245
246/* This is the PAC generated on my test network, by my test Win2k3 server.
247 -- abartlet 2005-07-04
248*/
249
250static const uint8_t saved_pac[] = {
251 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
252 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
253 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
254 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
255 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
256 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
257 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
258 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
259 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
260 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
263 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
264 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
266 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
271 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
272 0x41, 0x00, 0x4c, 0x00, 0x24, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
277 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
278 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
279 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
280 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
281 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
282 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
283 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
284 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
286 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
287 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
288 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
289 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
290};
291
292/* Check with a known 'well formed' PAC, from my test server */
293static bool torture_pac_saved_check(struct torture_context *tctx)
294{
295 NTSTATUS nt_status;
296 enum ndr_err_code ndr_err;
297 DATA_BLOB tmp_blob, validate_blob;
298 struct PAC_DATA *pac_data, pac_data2;
299 struct PAC_LOGON_INFO *logon_info;
300 union netr_Validation validation;
301 const char *pac_file, *pac_kdc_key, *pac_member_key;
302 struct auth_user_info_dc *user_info_dc_out;
303
304 krb5_keyblock server_keyblock;
305 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
306 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
307
308 krb5_error_code ret;
309 struct smb_krb5_context *smb_krb5_context;
310
311 const char *principal_string;
312 char *broken_principal_string;
313 krb5_principal client_principal;
314 const char *authtime_string;
315 time_t authtime;
316 TALLOC_CTX *mem_ctx = tctx;
317
318 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
319 tctx->lp_ctx,
320 &smb_krb5_context),
321 "smb_krb5_init_context");
322
323 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
324 "B286757148AF7FD252C53603A150B7E7");
325
326 pac_member_key = torture_setting_string(tctx, "pac_member_key",
327 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
328
329 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
330 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
331
332 /* The krbtgt key in use when the above PAC was generated.
333 * This is an arcfour-hmac-md5 key, extracted with our 'net
334 * samdump' tool. */
335 if (*pac_kdc_key == 0) {
336 krbtgt_bytes = NULL;
337 } else {
338 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
339 if (!krbtgt_bytes) {
340 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
341 }
342 }
343
344 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
345 if (!krbsrv_bytes) {
346 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
347 }
348
349 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
350 ENCTYPE_ARCFOUR_HMAC,
351 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
352 &server_keyblock);
353 torture_assert(tctx, !ret,
354 talloc_asprintf(tctx,
355 "(saved test) Server Keyblock encoding failed: %s",
356 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
357 ret, mem_ctx)));
358
359 if (krbtgt_bytes) {
360 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
361 ENCTYPE_ARCFOUR_HMAC,
362 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
363 &krbtgt_keyblock);
364 if (ret) {
365 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
366 &server_keyblock);
367 torture_fail(tctx,
368 talloc_asprintf(tctx,
369 "(saved test) Server Keyblock encoding failed: %s",
370 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
371 ret, mem_ctx)));
372 }
373 krbtgt_keyblock_p = &krbtgt_keyblock;
374 } else {
375 krbtgt_keyblock_p = NULL;
376 }
377
378 pac_file = torture_setting_string(tctx, "pac_file", NULL);
379 if (pac_file) {
380 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
381 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
382 } else {
383 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
384 }
385
386 dump_data(10,tmp_blob.data,tmp_blob.length);
387
388 principal_string = torture_setting_string(tctx, "pac_client_principal",
389 "w2003final$@WIN2K3.THINKER.LOCAL");
390
391 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
392 authtime = strtoull(authtime_string, NULL, 0);
393
394 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
395 &client_principal);
396 if (ret) {
397 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
398 krbtgt_keyblock_p);
399 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
400 &server_keyblock);
401 torture_fail(tctx,
402 talloc_asprintf(tctx,
403 "(saved test) parsing of client principal [%s] failed: %s",
404 principal_string,
405 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
406 }
407
408 /* Decode and verify the signaure on the PAC */
409 nt_status = kerberos_decode_pac(mem_ctx,
410 &pac_data,
411 tmp_blob,
412 smb_krb5_context->krb5_context,
413 krbtgt_keyblock_p,
414 &server_keyblock,
415 client_principal, authtime, NULL);
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);
422
423 torture_fail(tctx, talloc_asprintf(tctx,
424 "(saved test) PAC decoding failed: %s",
425 nt_errstr(nt_status)));
426 }
427
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);
434
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);
441
442 torture_fail(tctx, talloc_asprintf(tctx,
443 "(saved test) Heimdal PAC decoding failed: %s",
444 nt_errstr(nt_status)));
445 }
446
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);
456
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)));
462 }
463
464 talloc_free(user_info_dc_out);
465
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 &logon_info,
469 tmp_blob,
470 smb_krb5_context->krb5_context,
471 krbtgt_keyblock_p,
472 &server_keyblock,
473 client_principal, authtime, NULL);
474
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);
481
482 torture_fail(tctx,
483 talloc_asprintf(tctx,
484 "(saved test) PAC decoding (for logon info) failed: %s",
485 nt_errstr(nt_status)));
486 }
487
488 validation.sam3 = &logon_info->info3;
489 nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
490 "",
491 3, &validation,
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);
499
500 torture_fail(tctx,
501 talloc_asprintf(tctx,
502 "(saved test) PAC decoding (make server info) failed: %s",
503 nt_errstr(nt_status)));
504 }
505
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);
515
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)));
521 }
522
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;
529 }
530
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);
537
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);
544
545 torture_fail(tctx, "(saved test) PAC push failed");
546 }
547
548 dump_data(10, validate_blob.data, validate_blob.length);
549
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.
553 */
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);
560
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));
565 }
566
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);
573
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);
578
579 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
580 }
581
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);
589
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);
596
597 torture_fail(tctx, "(saved test) regnerated PAC create failed");
598 }
599
600 dump_data(10,validate_blob.data,validate_blob.length);
601
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.
605 */
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");
612
613 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
614
615 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
616
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);
622
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));
626 }
627
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");
634
635 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
636
637 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
638
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);
644
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);
649
650 torture_fail(tctx, talloc_asprintf(tctx,
651 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
652 }
653
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 &pac_data,
657 tmp_blob,
658 smb_krb5_context->krb5_context,
659 krbtgt_keyblock_p,
660 &server_keyblock,
661 client_principal,
662 authtime + 1, NULL);
663 if (NT_STATUS_IS_OK(nt_status)) {
664
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)");
671 }
672
673 /* Break the client principal */
674 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
675
676 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
677 broken_principal_string[0]++;
678
679 ret = krb5_parse_name(smb_krb5_context->krb5_context,
680 broken_principal_string, &client_principal);
681 if (ret) {
682
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)));
690 }
691
692 nt_status = kerberos_decode_pac(mem_ctx,
693 &pac_data,
694 tmp_blob,
695 smb_krb5_context->krb5_context,
696 krbtgt_keyblock_p,
697 &server_keyblock,
698 client_principal,
699 authtime, NULL);
700 if (NT_STATUS_IS_OK(nt_status)) {
701 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
702 krbtgt_keyblock_p);
703 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
704 &server_keyblock);
705 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
706 }
707
708 /* Finally... Bugger up the signature, and check we fail the checksum */
709 tmp_blob.data[tmp_blob.length - 2]++;
710
711 nt_status = kerberos_decode_pac(mem_ctx,
712 &pac_data,
713 tmp_blob,
714 smb_krb5_context->krb5_context,
715 krbtgt_keyblock_p,
716 &server_keyblock,
717 client_principal,
718 authtime, NULL);
719 if (NT_STATUS_IS_OK(nt_status)) {
720 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
721 krbtgt_keyblock_p);
722 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
723 &server_keyblock);
724 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
725 }
726
727 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
728 krbtgt_keyblock_p);
729 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
730 &server_keyblock);
731 return true;
732}
733
734struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
735{
736 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
737
738 torture_suite_add_simple_test(suite, "self check",
739 torture_pac_self_check);
740 torture_suite_add_simple_test(suite, "saved check",
741 torture_pac_saved_check);
742 return suite;
743}
Note: See TracBrowser for help on using the repository browser.