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