r26233: Pass loadparm context when creating krb5 contexts.
[jelmer/samba4-debian.git] / source / 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 3 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, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/kerberos.h"
25 #include "auth/auth.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "samba3/samba3.h"
29 #include "libcli/security/security.h"
30 #include "torture/torture.h"
31
32 static bool torture_pac_self_check(struct torture_context *tctx)
33 {
34         NTSTATUS nt_status;
35         DATA_BLOB tmp_blob;
36         struct PAC_DATA *pac_data;
37         struct PAC_LOGON_INFO *logon_info;
38         union netr_Validation validation;
39
40         /* Generate a nice, arbitary keyblock */
41         uint8_t server_bytes[16];
42         uint8_t krbtgt_bytes[16];
43         krb5_keyblock server_keyblock;
44         krb5_keyblock krbtgt_keyblock;
45         
46         krb5_error_code ret;
47
48         struct smb_krb5_context *smb_krb5_context;
49
50         struct auth_serversupplied_info *server_info;
51         struct auth_serversupplied_info *server_info_out;
52
53         krb5_principal client_principal;
54         time_t logon_time = time(NULL);
55
56         TALLOC_CTX *mem_ctx = tctx;
57
58         torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, 
59                                                         NULL,
60                                                         global_loadparm,
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         enum ndr_err_code ndr_err;
267         DATA_BLOB tmp_blob, validate_blob;
268         struct PAC_DATA *pac_data, pac_data2;
269         struct PAC_LOGON_INFO *logon_info;
270         union netr_Validation validation;
271         const char *pac_file, *pac_kdc_key, *pac_member_key;
272         struct auth_serversupplied_info *server_info_out;
273
274         krb5_keyblock server_keyblock;
275         krb5_keyblock krbtgt_keyblock;
276         struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
277         
278         krb5_error_code ret;
279         struct smb_krb5_context *smb_krb5_context;
280
281         const char *principal_string;
282         char *broken_principal_string;
283         krb5_principal client_principal;
284         const char *authtime_string;
285         time_t authtime;
286         TALLOC_CTX *mem_ctx = tctx;
287
288         torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, NULL,
289                                                         global_loadparm,
290                                                         &smb_krb5_context),
291                        "smb_krb5_init_context");
292
293         pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key", 
294                                              "B286757148AF7FD252C53603A150B7E7");
295
296         pac_member_key = torture_setting_string(tctx, "pac_member_key", 
297                                                 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
298
299         torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
300         torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
301
302         /* The krbtgt key in use when the above PAC was generated.
303          * This is an arcfour-hmac-md5 key, extracted with our 'net
304          * samdump' tool. */
305         krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
306         if (!krbtgt_bytes) {
307                 torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
308         }
309
310         krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
311         if (!krbsrv_bytes) {
312                 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
313         }
314
315         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
316                                  ENCTYPE_ARCFOUR_HMAC,
317                                  krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
318                                  &server_keyblock);
319         torture_assert(tctx, !ret,
320                        talloc_asprintf(tctx,
321                                        "(saved test) Server Keyblock encoding failed: %s", 
322                                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
323                                                                   ret, mem_ctx)));
324
325         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
326                                  ENCTYPE_ARCFOUR_HMAC,
327                                  krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
328                                  &krbtgt_keyblock);
329         if (ret) {
330                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
331                                             &server_keyblock);
332                 torture_fail(tctx, 
333                              talloc_asprintf(tctx, 
334                                              "(saved test) Server Keyblock encoding failed: %s", 
335                                              smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
336                                                                         ret, mem_ctx)));
337         }
338
339         pac_file = torture_setting_string(tctx, "pac_file", NULL);
340         if (pac_file) {
341                 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
342                 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
343         } else {
344                 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
345         }
346         
347         dump_data(10,tmp_blob.data,tmp_blob.length);
348
349         principal_string = torture_setting_string(tctx, "pac_client_principal", 
350                                                   "w2003final$@WIN2K3.THINKER.LOCAL");
351
352         authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
353         authtime = strtoull(authtime_string, NULL, 0);
354
355         ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
356                               &client_principal);
357         if (ret) {
358                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
359                                             &krbtgt_keyblock);
360                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
361                                             &server_keyblock);
362                 torture_fail(tctx,  
363                              talloc_asprintf(tctx, 
364                                              "(saved test) parsing of client principal [%s] failed: %s", 
365                                              principal_string, 
366                                              smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
367         }
368
369         /* Decode and verify the signaure on the PAC */
370         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
371                                         tmp_blob,
372                                         smb_krb5_context->krb5_context,
373                                         &krbtgt_keyblock,
374                                         &server_keyblock, 
375                                         client_principal, authtime, NULL);
376         if (!NT_STATUS_IS_OK(nt_status)) {
377                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
378                                             &krbtgt_keyblock);
379                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
380                                             &server_keyblock);
381                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
382                 
383                 torture_fail(tctx, talloc_asprintf(tctx, 
384                                                    "(saved test) PAC decoding failed: %s", 
385                                                    nt_errstr(nt_status)));
386         }
387
388         /* Parse the PAC again, for the logon info this time */
389         nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
390                                             tmp_blob,
391                                             smb_krb5_context->krb5_context,
392                                             &krbtgt_keyblock,
393                                             &server_keyblock,
394                                             client_principal, authtime, NULL);
395
396         if (!NT_STATUS_IS_OK(nt_status)) {
397                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
398                                             &krbtgt_keyblock);
399                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
400                                             &server_keyblock);
401                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
402         
403                 torture_fail(tctx,  
404                              talloc_asprintf(tctx, 
405                                              "(saved test) PAC decoding (for logon info) failed: %s", 
406                                              nt_errstr(nt_status)));
407         }
408
409         validation.sam3 = &logon_info->info3;
410         nt_status = make_server_info_netlogon_validation(mem_ctx,
411                                                          "",
412                                                          3, &validation,
413                                                          &server_info_out); 
414         if (!NT_STATUS_IS_OK(nt_status)) {
415                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
416                                             &krbtgt_keyblock);
417                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
418                                             &server_keyblock);
419                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
420
421                 torture_fail(tctx,  
422                              talloc_asprintf(tctx, 
423                                              "(saved test) PAC decoding (make server info) failed: %s", 
424                                              nt_errstr(nt_status)));
425         }
426
427         if (!pac_file &&
428             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
429                                                 "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
430                            server_info_out->account_sid)) {
431                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
432                                             &krbtgt_keyblock);
433                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
434                                             &server_keyblock);
435                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
436
437                 torture_fail(tctx,  
438                              talloc_asprintf(tctx, 
439                                              "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
440                                              "S-1-5-21-3048156945-3961193616-3706469200-1005", 
441                                              dom_sid_string(mem_ctx, server_info_out->account_sid)));
442         }
443
444         ret = kerberos_encode_pac(mem_ctx, 
445                                   pac_data,
446                                   smb_krb5_context->krb5_context,
447                                   &krbtgt_keyblock,
448                                   &server_keyblock,
449                                   &validate_blob);
450
451         if (ret != 0) {
452                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
453                                             &krbtgt_keyblock);
454                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
455                                             &server_keyblock);
456                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
457
458                 torture_fail(tctx, "(saved test) PAC push failed");
459         }
460
461         dump_data(10, validate_blob.data, validate_blob.length);
462
463         /* compare both the length and the data bytes after a
464          * pull/push cycle.  This ensures we use the exact same
465          * pointer, padding etc algorithms as win2k3.
466          */
467         if (tmp_blob.length != validate_blob.length) {
468                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
469                                             &krbtgt_keyblock);
470                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
471                                             &server_keyblock);
472                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
473
474                 torture_fail(tctx, 
475                              talloc_asprintf(tctx, 
476                                              "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
477                                              (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
478         }
479
480         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
481                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
482                                             &krbtgt_keyblock);
483                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
484                                             &server_keyblock);
485                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
486
487                 DEBUG(0, ("tmp_data:\n"));
488                 dump_data(0, tmp_blob.data, tmp_blob.length);
489                 DEBUG(0, ("validate_blob:\n"));
490                 dump_data(0, validate_blob.data, validate_blob.length);
491
492                 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
493         }
494
495         ret = kerberos_create_pac(mem_ctx, 
496                                   server_info_out,
497                                   smb_krb5_context->krb5_context,
498                                   &krbtgt_keyblock,
499                                   &server_keyblock,
500                                   client_principal, authtime,
501                                   &validate_blob);
502
503         if (ret != 0) {
504                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
505                                             &krbtgt_keyblock);
506                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
507                                             &server_keyblock);
508                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
509
510                 torture_fail(tctx, "(saved test) regnerated PAC create failed");
511         }
512
513         dump_data(10,validate_blob.data,validate_blob.length);
514
515         /* compare both the length and the data bytes after a
516          * pull/push cycle.  This ensures we use the exact same
517          * pointer, padding etc algorithms as win2k3.
518          */
519         if (tmp_blob.length != validate_blob.length) {
520                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
521                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
522                 nt_status = ndr_map_error2ntstatus(ndr_err);
523                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
524                 
525                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
526
527                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
528
529                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
530                                             &krbtgt_keyblock);
531                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
532                                             &server_keyblock);
533                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
534
535                 torture_fail(tctx, talloc_asprintf(tctx, 
536                                                    "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
537                                                    (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
538         }
539
540         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
541                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
542                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
543                 nt_status = ndr_map_error2ntstatus(ndr_err);
544                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
545                 
546                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
547
548                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
549
550                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
551                                             &krbtgt_keyblock);
552                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
553                                             &server_keyblock);
554                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
555
556                 DEBUG(0, ("tmp_data:\n"));
557                 dump_data(0, tmp_blob.data, tmp_blob.length);
558                 DEBUG(0, ("validate_blob:\n"));
559                 dump_data(0, validate_blob.data, validate_blob.length);
560
561                 torture_fail(tctx, talloc_asprintf(tctx, 
562                                                    "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
563         }
564
565         /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
566         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
567                                         tmp_blob,
568                                         smb_krb5_context->krb5_context,
569                                         &krbtgt_keyblock,
570                                         &server_keyblock,
571                                         client_principal, 
572                                         authtime + 1, NULL);
573         if (NT_STATUS_IS_OK(nt_status)) {
574
575                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
576                                             &krbtgt_keyblock);
577                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
578                                             &server_keyblock);
579                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
580                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
581         }
582
583         /* Break the client principal */
584         krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
585
586         broken_principal_string = talloc_strdup(mem_ctx, principal_string);
587         broken_principal_string[0]++;
588
589         ret = krb5_parse_name(smb_krb5_context->krb5_context,
590                               broken_principal_string, &client_principal);
591         if (ret) {
592
593                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
594                                             &krbtgt_keyblock);
595                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
596                                             &server_keyblock);
597                 torture_fail(tctx, talloc_asprintf(tctx, 
598                                                    "(saved test) parsing of broken client principal failed: %s", 
599                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
600         }
601
602         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
603                                         tmp_blob,
604                                         smb_krb5_context->krb5_context,
605                                         &krbtgt_keyblock,
606                                         &server_keyblock,
607                                         client_principal, 
608                                         authtime, NULL);
609         if (NT_STATUS_IS_OK(nt_status)) {
610                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
611                                             &krbtgt_keyblock);
612                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
613                                             &server_keyblock);
614                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
615         }
616
617         /* Finally...  Bugger up the signature, and check we fail the checksum */
618         tmp_blob.data[tmp_blob.length - 2]++;
619
620         nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
621                                         tmp_blob,
622                                         smb_krb5_context->krb5_context,
623                                         &krbtgt_keyblock,
624                                         &server_keyblock,
625                                         client_principal, 
626                                         authtime, NULL);
627         if (NT_STATUS_IS_OK(nt_status)) {
628                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
629                                             &krbtgt_keyblock);
630                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
631                                             &server_keyblock);
632                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
633         }
634
635         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
636                                     &krbtgt_keyblock);
637         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
638                                     &server_keyblock);
639         return true;
640 }
641
642 _PUBLIC_ struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
643 {
644         struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
645
646         torture_suite_add_simple_test(suite, "self check", 
647                                       torture_pac_self_check);
648
649         torture_suite_add_simple_test(suite, "saved check",
650                                       torture_pac_saved_check);
651
652         return suite;
653 }