r15328: Move some functions around, remove dependencies.
[kai/samba.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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "system/kerberos.h"
26 #include "auth/auth.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
29 #include "samba3/samba3.h"
30 #include "libcli/security/security.h"
31 #include "torture/torture.h"
32
33 static BOOL torture_pac_self_check(void) 
34 {
35         NTSTATUS nt_status;
36         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
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_serversupplied_info *server_info;
53         struct auth_serversupplied_info *server_info_out;
54
55         krb5_principal client_principal;
56         time_t logon_time = time(NULL);
57
58         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
59
60         if (ret) {
61                 talloc_free(mem_ctx);
62                 return False;
63         }
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         if (ret) {
73                 printf("(self test) Server Keyblock encoding failed: %s\n", 
74                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
75                                                   ret, mem_ctx));
76                 
77                 talloc_free(mem_ctx);
78                 return False;
79         }
80
81         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
82                                  ENCTYPE_ARCFOUR_HMAC,
83                                  krbtgt_bytes, sizeof(krbtgt_bytes),
84                                  &krbtgt_keyblock);
85         if (ret) {
86                 printf("(self test) KRBTGT Keyblock encoding failed: %s\n", 
87                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
88                                                   ret, mem_ctx));
89         
90                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
91                                             &server_keyblock);
92                 talloc_free(mem_ctx);
93                 return False;
94         }
95
96         /* We need an input, and this one requires no underlying database */
97         nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
98
99         if (!NT_STATUS_IS_OK(nt_status)) {
100                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
101                                             &server_keyblock);
102                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
103                                             &krbtgt_keyblock);
104                 talloc_free(mem_ctx);
105                 return False;
106         }
107
108         ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, 
109                                       server_info->account_name, &client_principal);
110         if (ret) {
111                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
112                                             &server_keyblock);
113                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
114                                             &krbtgt_keyblock);
115                 talloc_free(mem_ctx);
116                 return False;
117         }
118
119         /* OK, go ahead and make a PAC */
120         ret = kerberos_create_pac(mem_ctx, server_info, 
121                                   smb_krb5_context->krb5_context,  
122                                   &krbtgt_keyblock,
123                                   &server_keyblock,
124                                   client_principal,
125                                   logon_time,
126                                   &tmp_blob);
127         
128         if (ret) {
129                 printf("(self test) PAC encoding failed: %s\n", 
130                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
131                                                   ret, mem_ctx));
132
133                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
134                                             &krbtgt_keyblock);
135                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
136                                             &server_keyblock);
137                 krb5_free_principal(smb_krb5_context->krb5_context, 
138                                     client_principal);
139                 talloc_free(mem_ctx);
140                 return False;
141         }
142
143         dump_data(10,tmp_blob.data,tmp_blob.length);
144
145         /* Now check that we can read it back */
146         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
147                                         tmp_blob,
148                                         smb_krb5_context->krb5_context,
149                                         &krbtgt_keyblock,
150                                         &server_keyblock,
151                                         client_principal, 
152                                         logon_time, NULL);
153
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);
161                 DEBUG(1, ("(self test) PAC decoding failed: %s\n", 
162                           nt_errstr(nt_status)));
163
164                 talloc_free(mem_ctx);
165                 return False;
166         }
167
168         /* Now check that we can read it back */
169         nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
170                                             tmp_blob,
171                                             smb_krb5_context->krb5_context,
172                                             &krbtgt_keyblock,
173                                             &server_keyblock,
174                                             client_principal, 
175                                             logon_time, 
176                                             NULL);
177         
178         if (!NT_STATUS_IS_OK(nt_status)) {
179                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
180                                             &krbtgt_keyblock);
181                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
182                                             &server_keyblock);
183                 krb5_free_principal(smb_krb5_context->krb5_context, 
184                                     client_principal);
185                 printf("(self test) PAC decoding (for logon info) failed: %s\n", 
186                        nt_errstr(nt_status));
187                 
188                 talloc_free(mem_ctx);
189                 return False;
190         }
191         
192         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
193                                     &krbtgt_keyblock);
194         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
195                                     &server_keyblock);
196         krb5_free_principal(smb_krb5_context->krb5_context, 
197                             client_principal);
198
199         validation.sam3 = &logon_info->info3;
200         nt_status = make_server_info_netlogon_validation(mem_ctx,
201                                                          "",
202                                                          3, &validation,
203                                                          &server_info_out); 
204         if (!NT_STATUS_IS_OK(nt_status)) {
205                 printf("(self test) PAC decoding (make server info) failed: %s\n", 
206                        nt_errstr(nt_status));
207                 
208                 talloc_free(mem_ctx);
209                 return False;
210         }
211         
212         if (!dom_sid_equal(server_info->account_sid, 
213                            server_info_out->account_sid)) {
214                 printf("(self test) PAC Decode resulted in *different* domain SID: %s != %s\n",
215                        dom_sid_string(mem_ctx, server_info->account_sid), 
216                        dom_sid_string(mem_ctx, server_info_out->account_sid));
217                 talloc_free(mem_ctx);
218                 return False;
219         }
220         
221         talloc_free(mem_ctx);
222         return True;
223 }
224
225
226 /* This is the PAC generated on my test network, by my test Win2k3 server.
227    -- abartlet 2005-07-04
228  */
229
230 static const uint8_t saved_pac[] = {
231         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
232         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
233         0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
234         0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
235         0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
236         0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
237         0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
238         0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
239         0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
240         0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
241         0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
242         0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
243         0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
244         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245         0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
246         0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247         0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249         0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
251         0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
252         0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256         0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
257         0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
258         0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
259         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
260         0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
261         0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
262         0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
263         0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
264         0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265         0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
266         0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
267         0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
268         0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
269         0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
270 };
271
272 /* Check with a known 'well formed' PAC, from my test server */
273 static BOOL torture_pac_saved_check(void) 
274 {
275         NTSTATUS nt_status;
276         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
277         DATA_BLOB tmp_blob, validate_blob;
278         struct PAC_DATA *pac_data, pac_data2;
279         struct PAC_LOGON_INFO *logon_info;
280         union netr_Validation validation;
281         const char *pac_file, *pac_kdc_key, *pac_member_key;
282         struct auth_serversupplied_info *server_info_out;
283
284         krb5_keyblock server_keyblock;
285         krb5_keyblock krbtgt_keyblock;
286         struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
287         
288         krb5_error_code ret;
289         struct smb_krb5_context *smb_krb5_context;
290
291         const char *principal_string;
292         krb5_principal client_principal;
293         const char *authtime_string;
294         time_t authtime;
295
296         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
297
298         if (ret) {
299                 talloc_free(mem_ctx);
300                 return False;
301         }
302
303         pac_kdc_key = lp_parm_string(-1,"torture","pac_kdc_key");
304         if (pac_kdc_key == NULL) {
305                 pac_kdc_key = "B286757148AF7FD252C53603A150B7E7";
306         }
307
308         pac_member_key = lp_parm_string(-1,"torture","pac_member_key");
309         if (pac_member_key == NULL) {
310                 pac_member_key = "D217FAEAE5E6B5F95CCC94077AB8A5FC";
311         }
312
313         printf("Using pac_kdc_key '%s'\n", pac_kdc_key);
314         printf("Using pac_member_key '%s'\n", pac_member_key);
315
316         /* The krbtgt key in use when the above PAC was generated.
317          * This is an arcfour-hmac-md5 key, extracted with our 'net
318          * samdump' tool. */
319         krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
320         if (!krbtgt_bytes) {
321                 DEBUG(0, ("(saved test) Could not interpret krbtgt key"));
322                 talloc_free(mem_ctx);
323                 return False;
324         }
325
326         krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
327         if (!krbsrv_bytes) {
328                 DEBUG(0, ("(saved test) Could not interpret krbsrv key"));
329                 talloc_free(mem_ctx);
330                 return False;
331         }
332
333         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
334                                  ENCTYPE_ARCFOUR_HMAC,
335                                  krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
336                                  &server_keyblock);
337         if (ret) {
338                 DEBUG(1, ("(saved test) Server Keyblock encoding failed: %s\n", 
339                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
340                                                      ret, mem_ctx)));
341
342                 talloc_free(mem_ctx);
343                 return False;
344         }
345
346         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
347                                  ENCTYPE_ARCFOUR_HMAC,
348                                  krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
349                                  &krbtgt_keyblock);
350         if (ret) {
351                 DEBUG(1, ("(saved test) Server Keyblock encoding failed: %s\n", 
352                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
353                                                      ret, mem_ctx)));
354
355                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
356                                             &server_keyblock);
357                 talloc_free(mem_ctx);
358                 return False;
359         }
360
361         pac_file = lp_parm_string(-1,"torture","pac_file");
362         if (pac_file) {
363                 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
364                 printf("(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
365         } else {
366                 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
367         }
368         
369         dump_data(10,tmp_blob.data,tmp_blob.length);
370
371         principal_string = lp_parm_string(-1,"torture","pac_client_principal");
372         if (!principal_string) {
373                 principal_string = "w2003final$@WIN2K3.THINKER.LOCAL";
374         }
375
376         authtime_string = lp_parm_string(-1,"torture","pac_authtime");
377         if (!authtime_string) {
378                 authtime = 1120440609;
379         } else {
380                 authtime = strtoull(authtime_string, NULL, 0);
381         }
382
383         ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
384                               &client_principal);
385         if (ret) {
386                 DEBUG(1, ("(saved test) parsing of client principal [%s] failed: %s\n", 
387                           principal_string, 
388                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
389
390                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
391                                             &krbtgt_keyblock);
392                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
393                                             &server_keyblock);
394                 talloc_free(mem_ctx);
395                 return False;
396         }
397
398         /* Decode and verify the signaure on the PAC */
399         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
400                                         tmp_blob,
401                                         smb_krb5_context->krb5_context,
402                                         &krbtgt_keyblock,
403                                         &server_keyblock, 
404                                         client_principal, authtime, NULL);
405         if (!NT_STATUS_IS_OK(nt_status)) {
406                 DEBUG(1, ("(saved test) PAC decoding failed: %s\n", 
407                           nt_errstr(nt_status)));
408
409                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
410                                             &krbtgt_keyblock);
411                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
412                                             &server_keyblock);
413                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
414                 
415                 talloc_free(mem_ctx);
416                 return False;
417         }
418
419         /* Parse the PAC again, for the logon info this time */
420         nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
421                                             tmp_blob,
422                                             smb_krb5_context->krb5_context,
423                                             &krbtgt_keyblock,
424                                             &server_keyblock,
425                                             client_principal, authtime, NULL);
426
427         if (!NT_STATUS_IS_OK(nt_status)) {
428                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
429                                             &krbtgt_keyblock);
430                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
431                                             &server_keyblock);
432                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
433         
434                 printf("(saved test) PAC decoding (for logon info) failed: %s\n", 
435                           nt_errstr(nt_status));
436
437                 talloc_free(mem_ctx);
438                 return False;
439         }
440
441         validation.sam3 = &logon_info->info3;
442         nt_status = make_server_info_netlogon_validation(mem_ctx,
443                                                          "",
444                                                          3, &validation,
445                                                          &server_info_out); 
446         if (!NT_STATUS_IS_OK(nt_status)) {
447                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
448                                             &krbtgt_keyblock);
449                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
450                                     &server_keyblock);
451                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
452
453                 printf("(saved test) PAC decoding (make server info) failed: %s\n", 
454                        nt_errstr(nt_status));
455                 
456                 talloc_free(mem_ctx);
457                 return False;
458         }
459
460         if (!pac_file &&
461             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
462                            server_info_out->account_sid)) {
463                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
464                                             &krbtgt_keyblock);
465                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
466                                             &server_keyblock);
467                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
468
469                 printf("(saved test) PAC Decode resulted in *different* domain SID: %s != %s\n",
470                        "S-1-5-21-3048156945-3961193616-3706469200-1005", 
471                        dom_sid_string(mem_ctx, server_info_out->account_sid));
472                 talloc_free(mem_ctx);
473                 return False;
474         }
475
476         ret = kerberos_encode_pac(mem_ctx, 
477                                   pac_data,
478                                   smb_krb5_context->krb5_context,
479                                   &krbtgt_keyblock,
480                                   &server_keyblock,
481                                   &validate_blob);
482
483         if (ret != 0) {
484                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
485                                             &krbtgt_keyblock);
486                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
487                                             &server_keyblock);
488                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
489
490                 DEBUG(0, ("(saved test) PAC push failed\n"));
491                 talloc_free(mem_ctx);
492                 return False;
493         }
494
495         dump_data(10,validate_blob.data,validate_blob.length);
496
497         /* compare both the length and the data bytes after a
498          * pull/push cycle.  This ensures we use the exact same
499          * pointer, padding etc algorithms as win2k3.
500          */
501         if (tmp_blob.length != validate_blob.length) {
502                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
503                                             &krbtgt_keyblock);
504                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
505                                             &server_keyblock);
506                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
507
508                 DEBUG(0, ("(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]\n",
509                                 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
510                 talloc_free(mem_ctx);
511                 return False;
512         }
513
514         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
515                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
516                                             &krbtgt_keyblock);
517                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
518                                             &server_keyblock);
519                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
520
521                 DEBUG(0, ("(saved test) PAC push failed: length[%u] matches, but data does not\n",
522                           (unsigned)tmp_blob.length));
523                 DEBUG(0, ("tmp_data:\n"));
524                 dump_data(0, tmp_blob.data, tmp_blob.length);
525                 DEBUG(0, ("validate_blob:\n"));
526                 dump_data(0, validate_blob.data, validate_blob.length);
527
528                 talloc_free(mem_ctx);
529                 return False;
530         }
531
532         ret = kerberos_create_pac(mem_ctx, 
533                                   server_info_out,
534                                   smb_krb5_context->krb5_context,
535                                   &krbtgt_keyblock,
536                                   &server_keyblock,
537                                   client_principal, authtime,
538                                   &validate_blob);
539
540         if (ret != 0) {
541                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
542                                             &krbtgt_keyblock);
543                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
544                                             &server_keyblock);
545                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
546
547                 DEBUG(0, ("(saved test) regnerated PAC create failed\n"));
548                 talloc_free(mem_ctx);
549                 return False;
550         }
551
552         dump_data(10,validate_blob.data,validate_blob.length);
553
554         /* compare both the length and the data bytes after a
555          * pull/push cycle.  This ensures we use the exact same
556          * pointer, padding etc algorithms as win2k3.
557          */
558         if (tmp_blob.length != validate_blob.length) {
559                 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
560                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
561                 if (!NT_STATUS_IS_OK(nt_status)) {
562                         DEBUG(0,("can't parse the PAC\n"));
563                         return False;
564                 }
565                 
566                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
567
568                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
569
570                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
571                                             &krbtgt_keyblock);
572                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
573                                             &server_keyblock);
574                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
575
576                 DEBUG(0, ("(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]\n",
577                                 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
578                 talloc_free(mem_ctx);
579                 return False;
580         }
581
582         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
583                 nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
584                                               (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
585                 if (!NT_STATUS_IS_OK(nt_status)) {
586                         DEBUG(0,("can't parse the PAC\n"));
587                         return False;
588                 }
589                 
590                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
591
592                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
593
594                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
595                                             &krbtgt_keyblock);
596                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
597                                             &server_keyblock);
598                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
599
600                 DEBUG(0, ("(saved test) PAC regenerate failed: length[%u] matches, but data does not\n",
601                           (unsigned)tmp_blob.length));
602                 DEBUG(0, ("tmp_data:\n"));
603                 dump_data(0, tmp_blob.data, tmp_blob.length);
604                 DEBUG(0, ("validate_blob:\n"));
605                 dump_data(0, validate_blob.data, validate_blob.length);
606
607                 talloc_free(mem_ctx);
608                 return False;
609         }
610
611         /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
612         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
613                                         tmp_blob,
614                                         smb_krb5_context->krb5_context,
615                                         &krbtgt_keyblock,
616                                         &server_keyblock,
617                                         client_principal, 
618                                         authtime + 1, NULL);
619         if (NT_STATUS_IS_OK(nt_status)) {
620                 DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)\n"));
621
622                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
623                                             &krbtgt_keyblock);
624                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
625                                             &server_keyblock);
626                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
627                 talloc_free(mem_ctx);
628                 return False;
629         }
630
631         /* Break the client principal */
632         krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
633
634         ret = krb5_parse_name(smb_krb5_context->krb5_context,
635                              "not the right principal", &client_principal);
636         if (ret) {
637                 DEBUG(1, ("(saved test) parsing of bogus client principal failed: %s\n", 
638                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
639
640                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
641                                             &krbtgt_keyblock);
642                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
643                                             &server_keyblock);
644                 talloc_free(mem_ctx);
645                 return False;
646         }
647
648         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
649                                         tmp_blob,
650                                         smb_krb5_context->krb5_context,
651                                         &krbtgt_keyblock,
652                                         &server_keyblock,
653                                         client_principal, 
654                                         authtime, NULL);
655         if (NT_STATUS_IS_OK(nt_status)) {
656                 DEBUG(1, ("(saved test) PAC decoding DID NOT fail on modified principal\n"));
657
658                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
659                                             &krbtgt_keyblock);
660                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
661                                             &server_keyblock);
662                 talloc_free(mem_ctx);
663                 return False;
664         }
665
666         /* Finally...  Bugger up the signature, and check we fail the checksum */
667         tmp_blob.data[tmp_blob.length - 2]++;
668
669         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
670                                         tmp_blob,
671                                         smb_krb5_context->krb5_context,
672                                         &krbtgt_keyblock,
673                                         &server_keyblock,
674                                         client_principal, 
675                                         authtime, NULL);
676         if (NT_STATUS_IS_OK(nt_status)) {
677                 DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken checksum\n"));
678
679                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
680                                             &krbtgt_keyblock);
681                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
682                                             &server_keyblock);
683                 talloc_free(mem_ctx);
684                 return False;
685         }
686
687         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
688                                     &krbtgt_keyblock);
689         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
690                                     &server_keyblock);
691
692         talloc_free(mem_ctx);
693         return True;
694 }
695
696 BOOL torture_pac(struct torture_context *torture) 
697 {
698         BOOL ret = True;
699         ret &= torture_pac_self_check();
700         ret &= torture_pac_saved_check();
701         return ret;
702 }