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