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