s4-ldb: ldap attribute names can contain a '.'
[Samba/aatanasov.git] / source4 / torture / auth / pac.c
blob076120bfeeea839a4c7b613acddb384729a70e8f
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"
32 #include "param/param.h"
34 static bool torture_pac_self_check(struct torture_context *tctx)
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;
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;
48 krb5_error_code ret;
50 struct smb_krb5_context *smb_krb5_context;
52 struct auth_serversupplied_info *server_info;
53 struct auth_serversupplied_info *server_info_out;
55 krb5_principal client_principal;
56 time_t logon_time = time(NULL);
58 TALLOC_CTX *mem_ctx = tctx;
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");
66 generate_random_buffer(server_bytes, 16);
67 generate_random_buffer(krbtgt_bytes, 16);
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)));
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);
86 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
87 &server_keyblock);
89 torture_fail(tctx, talloc_asprintf(tctx,
90 "(self test) KRBTGT Keyblock encoding failed: %s", err));
93 /* We need an input, and this one requires no underlying database */
94 nt_status = auth_anonymous_server_info(mem_ctx, lp_netbios_name(tctx->lp_ctx), &server_info);
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_server_info");
104 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
105 server_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)");
116 /* OK, go ahead and make a PAC */
117 ret = kerberos_create_pac(mem_ctx,
118 lp_iconv_convenience(tctx->lp_ctx),
119 server_info,
120 smb_krb5_context->krb5_context,
121 &krbtgt_keyblock,
122 &server_keyblock,
123 client_principal,
124 logon_time,
125 &tmp_blob);
127 if (ret) {
128 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
129 &krbtgt_keyblock);
130 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
131 &server_keyblock);
132 krb5_free_principal(smb_krb5_context->krb5_context,
133 client_principal);
135 torture_fail(tctx, talloc_asprintf(tctx,
136 "(self test) PAC encoding failed: %s",
137 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
138 ret, mem_ctx)));
141 dump_data(10,tmp_blob.data,tmp_blob.length);
143 /* Now check that we can read it back (using full decode and validate) */
144 nt_status = kerberos_decode_pac(mem_ctx,
145 lp_iconv_convenience(tctx->lp_ctx),
146 &pac_data,
147 tmp_blob,
148 smb_krb5_context->krb5_context,
149 &krbtgt_keyblock,
150 &server_keyblock,
151 client_principal,
152 logon_time, NULL);
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_server_info(mem_ctx,
169 lp_iconv_convenience(tctx->lp_ctx),
170 tmp_blob,
171 smb_krb5_context->krb5_context,
172 &server_info_out);
174 if (!dom_sid_equal(server_info->account_sid,
175 server_info_out->account_sid)) {
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, server_info->account_sid),
187 dom_sid_string(mem_ctx, server_info_out->account_sid)));
189 talloc_free(server_info_out);
191 /* Now check that we can read it back (yet again) */
192 nt_status = kerberos_pac_logon_info(mem_ctx,
193 lp_iconv_convenience(tctx->lp_ctx),
194 &logon_info,
195 tmp_blob,
196 smb_krb5_context->krb5_context,
197 &krbtgt_keyblock,
198 &server_keyblock,
199 client_principal,
200 logon_time,
201 NULL);
203 if (!NT_STATUS_IS_OK(nt_status)) {
204 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
205 &krbtgt_keyblock);
206 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
207 &server_keyblock);
208 krb5_free_principal(smb_krb5_context->krb5_context,
209 client_principal);
211 torture_fail(tctx,
212 talloc_asprintf(tctx,
213 "(self test) PAC decoding (for logon info) failed: %s",
214 nt_errstr(nt_status)));
217 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
218 &krbtgt_keyblock);
219 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
220 &server_keyblock);
221 krb5_free_principal(smb_krb5_context->krb5_context,
222 client_principal);
224 /* And make a server info from the samba-parsed PAC */
225 validation.sam3 = &logon_info->info3;
226 nt_status = make_server_info_netlogon_validation(mem_ctx,
228 3, &validation,
229 &server_info_out);
230 if (!NT_STATUS_IS_OK(nt_status)) {
231 torture_fail(tctx,
232 talloc_asprintf(tctx,
233 "(self test) PAC decoding (make server info) failed: %s",
234 nt_errstr(nt_status)));
237 if (!dom_sid_equal(server_info->account_sid,
238 server_info_out->account_sid)) {
239 torture_fail(tctx,
240 talloc_asprintf(tctx,
241 "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
242 dom_sid_string(mem_ctx, server_info->account_sid),
243 dom_sid_string(mem_ctx, server_info_out->account_sid)));
245 return true;
249 /* This is the PAC generated on my test network, by my test Win2k3 server.
250 -- abartlet 2005-07-04
253 static const uint8_t saved_pac[] = {
254 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
255 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
256 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
257 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
258 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
259 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
260 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
261 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
262 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
263 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
266 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
267 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
269 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x21, 0x00, 0x00, 0x00, 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 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
274 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
275 0x41, 0x00, 0x4c, 0x00, 0x24, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
280 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
281 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
282 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
283 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
284 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
285 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
286 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
287 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
289 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
290 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
291 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
292 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
295 /* Check with a known 'well formed' PAC, from my test server */
296 static bool torture_pac_saved_check(struct torture_context *tctx)
298 NTSTATUS nt_status;
299 enum ndr_err_code ndr_err;
300 DATA_BLOB tmp_blob, validate_blob;
301 struct PAC_DATA *pac_data, pac_data2;
302 struct PAC_LOGON_INFO *logon_info;
303 union netr_Validation validation;
304 const char *pac_file, *pac_kdc_key, *pac_member_key;
305 struct auth_serversupplied_info *server_info_out;
307 krb5_keyblock server_keyblock;
308 krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
309 struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
311 krb5_error_code ret;
312 struct smb_krb5_context *smb_krb5_context;
314 const char *principal_string;
315 char *broken_principal_string;
316 krb5_principal client_principal;
317 const char *authtime_string;
318 time_t authtime;
319 TALLOC_CTX *mem_ctx = tctx;
321 torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
322 tctx->lp_ctx,
323 &smb_krb5_context),
324 "smb_krb5_init_context");
326 pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key",
327 "B286757148AF7FD252C53603A150B7E7");
329 pac_member_key = torture_setting_string(tctx, "pac_member_key",
330 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
332 torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
333 torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
335 /* The krbtgt key in use when the above PAC was generated.
336 * This is an arcfour-hmac-md5 key, extracted with our 'net
337 * samdump' tool. */
338 if (*pac_kdc_key == 0) {
339 krbtgt_bytes = NULL;
340 } else {
341 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
342 if (!krbtgt_bytes) {
343 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
347 krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
348 if (!krbsrv_bytes) {
349 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
352 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
353 ENCTYPE_ARCFOUR_HMAC,
354 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
355 &server_keyblock);
356 torture_assert(tctx, !ret,
357 talloc_asprintf(tctx,
358 "(saved test) Server Keyblock encoding failed: %s",
359 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
360 ret, mem_ctx)));
362 if (krbtgt_bytes) {
363 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
364 ENCTYPE_ARCFOUR_HMAC,
365 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
366 &krbtgt_keyblock);
367 if (ret) {
368 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
369 &server_keyblock);
370 torture_fail(tctx,
371 talloc_asprintf(tctx,
372 "(saved test) Server Keyblock encoding failed: %s",
373 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
374 ret, mem_ctx)));
376 krbtgt_keyblock_p = &krbtgt_keyblock;
377 } else {
378 krbtgt_keyblock_p = NULL;
381 pac_file = torture_setting_string(tctx, "pac_file", NULL);
382 if (pac_file) {
383 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
384 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
385 } else {
386 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
389 dump_data(10,tmp_blob.data,tmp_blob.length);
391 principal_string = torture_setting_string(tctx, "pac_client_principal",
392 "w2003final$@WIN2K3.THINKER.LOCAL");
394 authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
395 authtime = strtoull(authtime_string, NULL, 0);
397 ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string,
398 &client_principal);
399 if (ret) {
400 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
401 krbtgt_keyblock_p);
402 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
403 &server_keyblock);
404 torture_fail(tctx,
405 talloc_asprintf(tctx,
406 "(saved test) parsing of client principal [%s] failed: %s",
407 principal_string,
408 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
411 /* Decode and verify the signaure on the PAC */
412 nt_status = kerberos_decode_pac(mem_ctx,
413 lp_iconv_convenience(tctx->lp_ctx),
414 &pac_data,
415 tmp_blob,
416 smb_krb5_context->krb5_context,
417 krbtgt_keyblock_p,
418 &server_keyblock,
419 client_principal, authtime, NULL);
420 if (!NT_STATUS_IS_OK(nt_status)) {
421 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
422 krbtgt_keyblock_p);
423 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
424 &server_keyblock);
425 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
427 torture_fail(tctx, talloc_asprintf(tctx,
428 "(saved test) PAC decoding failed: %s",
429 nt_errstr(nt_status)));
432 /* Now check we can read it back (using Heimdal's pac parsing) */
433 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
434 lp_iconv_convenience(tctx->lp_ctx),
435 tmp_blob,
436 smb_krb5_context->krb5_context,
437 &server_info_out);
439 if (!NT_STATUS_IS_OK(nt_status)) {
440 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
441 krbtgt_keyblock_p);
442 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
443 &server_keyblock);
444 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
446 torture_fail(tctx, talloc_asprintf(tctx,
447 "(saved test) Heimdal PAC decoding failed: %s",
448 nt_errstr(nt_status)));
451 if (!pac_file &&
452 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
453 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
454 server_info_out->account_sid)) {
455 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
456 krbtgt_keyblock_p);
457 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
458 &server_keyblock);
459 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
461 torture_fail(tctx,
462 talloc_asprintf(tctx,
463 "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
464 "S-1-5-21-3048156945-3961193616-3706469200-1005",
465 dom_sid_string(mem_ctx, server_info_out->account_sid)));
468 talloc_free(server_info_out);
470 /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
471 nt_status = kerberos_pac_logon_info(mem_ctx,
472 lp_iconv_convenience(tctx->lp_ctx),
473 &logon_info,
474 tmp_blob,
475 smb_krb5_context->krb5_context,
476 krbtgt_keyblock_p,
477 &server_keyblock,
478 client_principal, authtime, NULL);
480 if (!NT_STATUS_IS_OK(nt_status)) {
481 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
482 krbtgt_keyblock_p);
483 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
484 &server_keyblock);
485 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
487 torture_fail(tctx,
488 talloc_asprintf(tctx,
489 "(saved test) PAC decoding (for logon info) failed: %s",
490 nt_errstr(nt_status)));
493 validation.sam3 = &logon_info->info3;
494 nt_status = make_server_info_netlogon_validation(mem_ctx,
496 3, &validation,
497 &server_info_out);
498 if (!NT_STATUS_IS_OK(nt_status)) {
499 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
500 krbtgt_keyblock_p);
501 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
502 &server_keyblock);
503 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
505 torture_fail(tctx,
506 talloc_asprintf(tctx,
507 "(saved test) PAC decoding (make server info) failed: %s",
508 nt_errstr(nt_status)));
511 if (!pac_file &&
512 !dom_sid_equal(dom_sid_parse_talloc(mem_ctx,
513 "S-1-5-21-3048156945-3961193616-3706469200-1005"),
514 server_info_out->account_sid)) {
515 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
516 krbtgt_keyblock_p);
517 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
518 &server_keyblock);
519 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
521 torture_fail(tctx,
522 talloc_asprintf(tctx,
523 "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
524 "S-1-5-21-3048156945-3961193616-3706469200-1005",
525 dom_sid_string(mem_ctx, server_info_out->account_sid)));
528 if (krbtgt_bytes == NULL) {
529 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
530 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
531 &server_keyblock);
532 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
533 return true;
536 ret = kerberos_encode_pac(mem_ctx,
537 lp_iconv_convenience(tctx->lp_ctx),
538 pac_data,
539 smb_krb5_context->krb5_context,
540 krbtgt_keyblock_p,
541 &server_keyblock,
542 &validate_blob);
544 if (ret != 0) {
545 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
546 krbtgt_keyblock_p);
547 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
548 &server_keyblock);
549 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
551 torture_fail(tctx, "(saved test) PAC push failed");
554 dump_data(10, validate_blob.data, validate_blob.length);
556 /* compare both the length and the data bytes after a
557 * pull/push cycle. This ensures we use the exact same
558 * pointer, padding etc algorithms as win2k3.
560 if (tmp_blob.length != validate_blob.length) {
561 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
562 krbtgt_keyblock_p);
563 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
564 &server_keyblock);
565 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
567 torture_fail(tctx,
568 talloc_asprintf(tctx,
569 "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
570 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
573 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
574 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
575 krbtgt_keyblock_p);
576 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
577 &server_keyblock);
578 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
580 DEBUG(0, ("tmp_data:\n"));
581 dump_data(0, tmp_blob.data, tmp_blob.length);
582 DEBUG(0, ("validate_blob:\n"));
583 dump_data(0, validate_blob.data, validate_blob.length);
585 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
588 ret = kerberos_create_pac(mem_ctx,
589 lp_iconv_convenience(tctx->lp_ctx),
590 server_info_out,
591 smb_krb5_context->krb5_context,
592 krbtgt_keyblock_p,
593 &server_keyblock,
594 client_principal, authtime,
595 &validate_blob);
597 if (ret != 0) {
598 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
599 krbtgt_keyblock_p);
600 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
601 &server_keyblock);
602 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
604 torture_fail(tctx, "(saved test) regnerated PAC create failed");
607 dump_data(10,validate_blob.data,validate_blob.length);
609 /* compare both the length and the data bytes after a
610 * pull/push cycle. This ensures we use the exact same
611 * pointer, padding etc algorithms as win2k3.
613 if (tmp_blob.length != validate_blob.length) {
614 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
615 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
616 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
617 nt_status = ndr_map_error2ntstatus(ndr_err);
618 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
620 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
622 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
624 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
625 krbtgt_keyblock_p);
626 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
627 &server_keyblock);
628 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
630 torture_fail(tctx, talloc_asprintf(tctx,
631 "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
632 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
635 if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
636 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx,
637 lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
638 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
639 nt_status = ndr_map_error2ntstatus(ndr_err);
640 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
642 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
644 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
646 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
647 krbtgt_keyblock_p);
648 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
649 &server_keyblock);
650 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
652 DEBUG(0, ("tmp_data:\n"));
653 dump_data(0, tmp_blob.data, tmp_blob.length);
654 DEBUG(0, ("validate_blob:\n"));
655 dump_data(0, validate_blob.data, validate_blob.length);
657 torture_fail(tctx, talloc_asprintf(tctx,
658 "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
661 /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
662 nt_status = kerberos_decode_pac(mem_ctx,
663 lp_iconv_convenience(tctx->lp_ctx),
664 &pac_data,
665 tmp_blob,
666 smb_krb5_context->krb5_context,
667 krbtgt_keyblock_p,
668 &server_keyblock,
669 client_principal,
670 authtime + 1, NULL);
671 if (NT_STATUS_IS_OK(nt_status)) {
673 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
674 krbtgt_keyblock_p);
675 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
676 &server_keyblock);
677 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
678 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
681 /* Break the client principal */
682 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
684 broken_principal_string = talloc_strdup(mem_ctx, principal_string);
685 broken_principal_string[0]++;
687 ret = krb5_parse_name(smb_krb5_context->krb5_context,
688 broken_principal_string, &client_principal);
689 if (ret) {
691 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
692 krbtgt_keyblock_p);
693 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
694 &server_keyblock);
695 torture_fail(tctx, talloc_asprintf(tctx,
696 "(saved test) parsing of broken client principal failed: %s",
697 smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
700 nt_status = kerberos_decode_pac(mem_ctx,
701 lp_iconv_convenience(tctx->lp_ctx),
702 &pac_data,
703 tmp_blob,
704 smb_krb5_context->krb5_context,
705 krbtgt_keyblock_p,
706 &server_keyblock,
707 client_principal,
708 authtime, NULL);
709 if (NT_STATUS_IS_OK(nt_status)) {
710 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
711 krbtgt_keyblock_p);
712 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
713 &server_keyblock);
714 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
717 /* Finally... Bugger up the signature, and check we fail the checksum */
718 tmp_blob.data[tmp_blob.length - 2]++;
720 nt_status = kerberos_decode_pac(mem_ctx,
721 lp_iconv_convenience(tctx->lp_ctx),
722 &pac_data,
723 tmp_blob,
724 smb_krb5_context->krb5_context,
725 krbtgt_keyblock_p,
726 &server_keyblock,
727 client_principal,
728 authtime, NULL);
729 if (NT_STATUS_IS_OK(nt_status)) {
730 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
731 krbtgt_keyblock_p);
732 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
733 &server_keyblock);
734 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
737 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
738 krbtgt_keyblock_p);
739 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
740 &server_keyblock);
741 return true;
744 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
746 struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
748 torture_suite_add_simple_test(suite, "self check",
749 torture_pac_self_check);
750 torture_suite_add_simple_test(suite, "saved check",
751 torture_pac_saved_check);
752 return suite;