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