s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[metze/samba/wip.git] / source4 / torture / auth / pac.c
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
33 static bool torture_pac_self_check(struct torture_context *tctx)
34 {
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;
40
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;
46         
47         krb5_error_code ret;
48
49         struct smb_krb5_context *smb_krb5_context;
50
51         struct auth_serversupplied_info *server_info;
52         struct auth_serversupplied_info *server_info_out;
53
54         krb5_principal client_principal;
55         time_t logon_time = time(NULL);
56
57         TALLOC_CTX *mem_ctx = tctx;
58
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");
64
65         generate_random_buffer(server_bytes, 16);
66         generate_random_buffer(krbtgt_bytes, 16);
67
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)));
76
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);
84         
85                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
86                                             &server_keyblock);
87
88                 torture_fail(tctx, talloc_asprintf(tctx, 
89                                                    "(self test) KRBTGT Keyblock encoding failed: %s", err));
90         }
91
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);
94
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");
101         }
102
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)");
113         }
114
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);
124         
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);
132
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)));
137         }
138
139         dump_data(10,tmp_blob.data,tmp_blob.length);
140
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);
150
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);
158
159                 torture_fail(tctx, talloc_asprintf(tctx,
160                                                    "(self test) PAC decoding failed: %s", 
161                                                    nt_errstr(nt_status)));
162         }
163
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);
169
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);
178
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)));
184         }
185         talloc_free(server_info_out);
186
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);
197         
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);
205                 
206                 torture_fail(tctx,  
207                              talloc_asprintf(tctx, 
208                                              "(self test) PAC decoding (for logon info) failed: %s", 
209                                              nt_errstr(nt_status)));
210         }
211         
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);
218
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,
222                                                          "",
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)));
230         }
231         
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)));
239         }
240         return true;
241 }
242
243
244 /* This is the PAC generated on my test network, by my test Win2k3 server.
245    -- abartlet 2005-07-04
246 */
247
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
288 };
289
290 /* Check with a known 'well formed' PAC, from my test server */
291 static bool torture_pac_saved_check(struct torture_context *tctx)
292 {
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;
301
302         krb5_keyblock server_keyblock;
303         krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
304         struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
305         
306         krb5_error_code ret;
307         struct smb_krb5_context *smb_krb5_context;
308
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;
315
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");
320
321         pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key", 
322                                              "B286757148AF7FD252C53603A150B7E7");
323
324         pac_member_key = torture_setting_string(tctx, "pac_member_key", 
325                                                 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
326
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);
329
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");
339                 }
340         }
341
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");
345         }
346
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)));
356
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)));
370                 }
371                 krbtgt_keyblock_p = &krbtgt_keyblock;
372         } else {
373                 krbtgt_keyblock_p = NULL;
374         }
375
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));
382         }
383         
384         dump_data(10,tmp_blob.data,tmp_blob.length);
385
386         principal_string = torture_setting_string(tctx, "pac_client_principal", 
387                                                   "w2003final$@WIN2K3.THINKER.LOCAL");
388
389         authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
390         authtime = strtoull(authtime_string, NULL, 0);
391
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)));
404         }
405
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);
420                 
421                 torture_fail(tctx, talloc_asprintf(tctx, 
422                                                    "(saved test) PAC decoding failed: %s", 
423                                                    nt_errstr(nt_status)));
424         }
425
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);
431
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);
438                 
439                 torture_fail(tctx, talloc_asprintf(tctx, 
440                                                    "(saved test) Heimdal PAC decoding failed: %s", 
441                                                    nt_errstr(nt_status)));
442         }
443
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);
453
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)));
459         }
460
461         talloc_free(server_info_out);
462
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);
471
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);
478         
479                 torture_fail(tctx,  
480                              talloc_asprintf(tctx, 
481                                              "(saved test) PAC decoding (for logon info) failed: %s", 
482                                              nt_errstr(nt_status)));
483         }
484
485         validation.sam3 = &logon_info->info3;
486         nt_status = make_server_info_netlogon_validation(mem_ctx,
487                                                          "",
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);
496
497                 torture_fail(tctx,  
498                              talloc_asprintf(tctx, 
499                                              "(saved test) PAC decoding (make server info) failed: %s", 
500                                              nt_errstr(nt_status)));
501         }
502
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);
512
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)));
518         }
519
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;
526         }
527
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);
534
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);
541
542                 torture_fail(tctx, "(saved test) PAC push failed");
543         }
544
545         dump_data(10, validate_blob.data, validate_blob.length);
546
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.
550          */
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);
557
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));
562         }
563
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);
570
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);
575
576                 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
577         }
578
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);
586
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);
593
594                 torture_fail(tctx, "(saved test) regnerated PAC create failed");
595         }
596
597         dump_data(10,validate_blob.data,validate_blob.length);
598
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.
602          */
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");
609                 
610                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
611
612                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
613
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);
619
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));
623         }
624
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");
631                 
632                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
633
634                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
635
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);
641
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);
646
647                 torture_fail(tctx, talloc_asprintf(tctx, 
648                                                    "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
649         }
650
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)) {
661
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)");
668         }
669
670         /* Break the client principal */
671         krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
672
673         broken_principal_string = talloc_strdup(mem_ctx, principal_string);
674         broken_principal_string[0]++;
675
676         ret = krb5_parse_name(smb_krb5_context->krb5_context,
677                               broken_principal_string, &client_principal);
678         if (ret) {
679
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)));
687         }
688
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");
703         }
704
705         /* Finally...  Bugger up the signature, and check we fail the checksum */
706         tmp_blob.data[tmp_blob.length - 2]++;
707
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");
722         }
723
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;
729 }
730
731 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
732 {
733         struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
734
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;
740 }