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