5218d73d8f21c49a797cfccd4e67c05822a127f9
[ira/wip.git] / source4 / torture / auth / pac.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Validate the krb5 pac generation routines
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 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         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
54
55         if (ret) {
56                 talloc_free(mem_ctx);
57                 return False;
58         }
59
60         generate_random_buffer(server_bytes, 16);
61         generate_random_buffer(krbtgt_bytes, 16);
62
63         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
64                                  ENCTYPE_ARCFOUR_HMAC,
65                                  server_bytes, sizeof(server_bytes),
66                                  &server_keyblock);
67         if (ret) {
68                 printf("Server Keyblock encoding failed: %s\n", 
69                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
70                                                   ret, mem_ctx));
71                 
72                 talloc_free(mem_ctx);
73                 return False;
74         }
75
76         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
77                                  ENCTYPE_ARCFOUR_HMAC,
78                                  krbtgt_bytes, sizeof(krbtgt_bytes),
79                                  &krbtgt_keyblock);
80         if (ret) {
81                 printf("KRBTGT Keyblock encoding failed: %s\n", 
82                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
83                                                   ret, mem_ctx));
84         
85                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
86                                             &server_keyblock);
87                 talloc_free(mem_ctx);
88                 return False;
89         }
90
91         /* We need an input, and this one requires no underlying database */
92         nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
93
94         if (!NT_STATUS_IS_OK(nt_status)) {
95                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
96                                             &server_keyblock);
97                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
98                                             &krbtgt_keyblock);
99                 talloc_free(mem_ctx);
100                 return False;
101         }
102         
103         /* OK, go ahead and make a PAC */
104         ret = kerberos_create_pac(mem_ctx, server_info, 
105                                   smb_krb5_context->krb5_context,  
106                                   &krbtgt_keyblock,
107                                   &server_keyblock,
108                                   &tmp_blob);
109         
110         if (ret) {
111                 printf("PAC encoding failed: %s\n", 
112                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
113                                                   ret, mem_ctx));
114
115                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
116                                             &krbtgt_keyblock);
117                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
118                                             &server_keyblock);
119                 talloc_free(mem_ctx);
120                 return False;
121         }
122
123         dump_data(10,tmp_blob.data,tmp_blob.length);
124
125         /* Now check that we can read it back */
126         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
127                                         tmp_blob,
128                                         smb_krb5_context,
129                                         &krbtgt_keyblock,
130                                         &server_keyblock);
131
132         if (!NT_STATUS_IS_OK(nt_status)) {
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                 DEBUG(1, ("PAC decoding failed: %s\n", 
138                           nt_errstr(nt_status)));
139
140                 talloc_free(mem_ctx);
141                 return False;
142         }
143
144         /* Now check that we can read it back */
145         nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
146                                             tmp_blob,
147                                             smb_krb5_context,
148                                             &krbtgt_keyblock,
149                                             &server_keyblock);
150         
151         if (!NT_STATUS_IS_OK(nt_status)) {
152                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
153                                             &krbtgt_keyblock);
154                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
155                                             &server_keyblock);
156                 printf("PAC decoding (for logon info) failed: %s\n", 
157                        nt_errstr(nt_status));
158                 
159                 talloc_free(mem_ctx);
160                 return False;
161         }
162         
163         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
164                                     &krbtgt_keyblock);
165         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
166                                     &server_keyblock);
167
168         validation.sam3 = &logon_info->info3;
169         nt_status = make_server_info_netlogon_validation(mem_ctx,
170                                                          "",
171                                                          3, &validation,
172                                                          &server_info_out); 
173         if (!NT_STATUS_IS_OK(nt_status)) {
174                 printf("PAC decoding (make server info) failed: %s\n", 
175                        nt_errstr(nt_status));
176                 
177                 talloc_free(mem_ctx);
178                 return False;
179         }
180         
181         if (!dom_sid_equal(server_info->account_sid, 
182                            server_info_out->account_sid)) {
183                 printf("PAC Decode resulted in *different* domain SID: %s != %s\n",
184                        dom_sid_string(mem_ctx, server_info->account_sid), 
185                        dom_sid_string(mem_ctx, server_info_out->account_sid));
186                 talloc_free(mem_ctx);
187                 return False;
188         }
189         
190         talloc_free(mem_ctx);
191         return True;
192 }
193
194
195 /* This is the PAC generated on my test network, by my test Win2k3 server.
196    -- abartlet 2005-07-04
197  */
198
199 static const uint8_t saved_pac[] = {
200         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
201         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
202         0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
203         0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
204         0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
205         0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
206         0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
207         0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
208         0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
209         0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
210         0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
211         0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
212         0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
213         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214         0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
215         0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216         0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218         0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
220         0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
221         0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225         0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
226         0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
227         0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
228         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
229         0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
230         0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
231         0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
232         0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
233         0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234         0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
235         0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
236         0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
237         0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
238         0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
239 };
240
241 /* Check with a known 'well formed' PAC, from my test server */
242 static BOOL torture_pac_saved_check(void) 
243 {
244         NTSTATUS nt_status;
245         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
246         DATA_BLOB tmp_blob, validate_blob;
247         struct PAC_DATA *pac_data;
248         struct PAC_LOGON_INFO *logon_info;
249         union netr_Validation validation;
250         const char *pac_file, *pac_kdc_key, *pac_member_key;
251
252         struct auth_serversupplied_info *server_info_out;
253
254         krb5_keyblock server_keyblock;
255         krb5_keyblock krbtgt_keyblock;
256         struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
257         
258         krb5_error_code ret;
259
260         struct smb_krb5_context *smb_krb5_context;
261
262         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
263
264         if (ret) {
265                 talloc_free(mem_ctx);
266                 return False;
267         }
268
269         pac_kdc_key = lp_parm_string(-1,"torture","pac_kdc_key");
270         if (pac_kdc_key == NULL) {
271                 pac_kdc_key = "B286757148AF7FD252C53603A150B7E7";
272         }
273
274         pac_member_key = lp_parm_string(-1,"torture","pac_member_key");
275         if (pac_member_key == NULL) {
276                 pac_member_key = "D217FAEAE5E6B5F95CCC94077AB8A5FC";
277         }
278
279         printf("Using pac_kdc_key '%s'\n", pac_kdc_key);
280         printf("Using pac_member_key '%s'\n", pac_member_key);
281
282         /* The krbtgt key in use when the above PAC was generated.
283          * This is an arcfour-hmac-md5 key, extracted with our 'net
284          * samdump' tool. */
285         krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
286         if (!krbtgt_bytes) {
287                 DEBUG(0, ("Could not interpret krbtgt key"));
288                 talloc_free(mem_ctx);
289                 return False;
290         }
291
292         krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
293         if (!krbsrv_bytes) {
294                 DEBUG(0, ("Could not interpret krbsrv key"));
295                 talloc_free(mem_ctx);
296                 return False;
297         }
298
299         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
300                                  ENCTYPE_ARCFOUR_HMAC,
301                                  krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
302                                  &server_keyblock);
303         if (ret) {
304                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
305                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
306                                                      ret, mem_ctx)));
307
308                 talloc_free(mem_ctx);
309                 return False;
310         }
311
312         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
313                                  ENCTYPE_ARCFOUR_HMAC,
314                                  krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
315                                  &krbtgt_keyblock);
316         if (ret) {
317                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
318                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
319                                                      ret, mem_ctx)));
320
321                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
322                                             &server_keyblock);
323                 talloc_free(mem_ctx);
324                 return False;
325         }
326
327         pac_file = lp_parm_string(-1,"torture","pac_file");
328         if (pac_file) {
329                 tmp_blob.data = file_load(pac_file, &tmp_blob.length, mem_ctx);
330                 printf("Loaded pac of size %d from %s\n", tmp_blob.length, pac_file);
331         } else {
332                 tmp_blob = data_blob(saved_pac, sizeof(saved_pac));
333                 file_save("x.dat", tmp_blob.data, tmp_blob.length);
334         }
335         
336         dump_data(10,tmp_blob.data,tmp_blob.length);
337
338         /* Decode and verify the signaure on the PAC */
339         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
340                                         tmp_blob,
341                                         smb_krb5_context,
342                                         &krbtgt_keyblock,
343                                         &server_keyblock);
344         if (!NT_STATUS_IS_OK(nt_status)) {
345                 DEBUG(1, ("PAC decoding failed: %s\n", 
346                           nt_errstr(nt_status)));
347
348                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
349                                             &krbtgt_keyblock);
350                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
351                                             &server_keyblock);
352                 talloc_free(mem_ctx);
353                 return False;
354         }
355
356         /* Parse the PAC again, for the logon info this time */
357         nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
358                                             tmp_blob,
359                                             smb_krb5_context,
360                                             &krbtgt_keyblock,
361                                             &server_keyblock);
362
363         if (!NT_STATUS_IS_OK(nt_status)) {
364                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
365                                             &krbtgt_keyblock);
366                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
367                                             &server_keyblock);
368                 printf("PAC decoding (for logon info) failed: %s\n", 
369                           nt_errstr(nt_status));
370
371                 talloc_free(mem_ctx);
372                 return False;
373         }
374
375         validation.sam3 = &logon_info->info3;
376         nt_status = make_server_info_netlogon_validation(mem_ctx,
377                                                          "",
378                                                          3, &validation,
379                                                          &server_info_out); 
380         if (!NT_STATUS_IS_OK(nt_status)) {
381                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
382                                             &krbtgt_keyblock);
383                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
384                                     &server_keyblock);
385
386                 printf("PAC decoding (make server info) failed: %s\n", 
387                        nt_errstr(nt_status));
388                 
389                 talloc_free(mem_ctx);
390                 return False;
391         }
392
393         if (!pac_file &&
394             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
395                            server_info_out->account_sid)) {
396                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
397                                             &krbtgt_keyblock);
398                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
399                                             &server_keyblock);
400
401                 printf("PAC Decode resulted in *different* domain SID: %s != %s\n",
402                        "S-1-5-21-3048156945-3961193616-3706469200-1005", 
403                        dom_sid_string(mem_ctx, server_info_out->account_sid));
404                 talloc_free(mem_ctx);
405                 return False;
406         }
407
408         ret = kerberos_encode_pac(mem_ctx, 
409                                   pac_data,
410                                   smb_krb5_context->krb5_context,
411                                   &krbtgt_keyblock,
412                                   &server_keyblock,
413                                   &validate_blob);
414
415         if (ret != 0) {
416                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
417                                             &krbtgt_keyblock);
418                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
419                                             &server_keyblock);
420
421                 DEBUG(0, ("PAC push failed\n"));
422                 talloc_free(mem_ctx);
423                 return False;
424         }
425
426         dump_data(10,validate_blob.data,validate_blob.length);
427
428         /* compare both the length and the data bytes after a
429          * pull/push cycle.  This ensures we use the exact same
430          * pointer, padding etc algorithms as win2k3.
431          */
432         if (tmp_blob.length != validate_blob.length) {
433                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
434                                             &krbtgt_keyblock);
435                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
436                                             &server_keyblock);
437
438                 DEBUG(0, ("PAC push failed: original buffer length[%u] != created buffer length[%u]\n",
439                                 (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
440                 talloc_free(mem_ctx);
441                 return False;
442         }
443
444         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
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
450                 DEBUG(0, ("PAC push failed: length[%u] matches, but data does not\n",
451                           (unsigned)tmp_blob.length));
452                 talloc_free(mem_ctx);
453                 return False;
454         }
455
456         /* Finally...  Bugger up the signature, and check we fail the checksum */
457         tmp_blob.data[tmp_blob.length - 2]++;
458
459         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
460                                         tmp_blob,
461                                         smb_krb5_context,
462                                         &krbtgt_keyblock,
463                                         &server_keyblock);
464         if (NT_STATUS_IS_OK(nt_status)) {
465                 DEBUG(1, ("PAC decoding DID NOT fail on broken checksum\n"));
466
467                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
468                                             &krbtgt_keyblock);
469                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
470                                             &server_keyblock);
471                 talloc_free(mem_ctx);
472                 return False;
473         }
474
475         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
476                                     &krbtgt_keyblock);
477         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
478                                     &server_keyblock);
479
480         talloc_free(mem_ctx);
481         return True;
482 }
483
484 BOOL torture_pac(void) 
485 {
486         BOOL ret = True;
487         ret &= torture_pac_self_check();
488         ret &= torture_pac_saved_check();
489         return ret;
490 }