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