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