Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
[kai/samba.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 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, *krbtgt_keyblock_p;
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         if (*pac_kdc_key == 0) {
313                 krbtgt_bytes = NULL;
314         } else {
315                 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
316                 if (!krbtgt_bytes) {
317                         torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
318                 }
319         }
320
321         krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
322         if (!krbsrv_bytes) {
323                 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
324         }
325
326         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
327                                  ENCTYPE_ARCFOUR_HMAC,
328                                  krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
329                                  &server_keyblock);
330         torture_assert(tctx, !ret,
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         if (krbtgt_bytes) {
337                 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
338                                          ENCTYPE_ARCFOUR_HMAC,
339                                          krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
340                                          &krbtgt_keyblock);
341                 if (ret) {
342                         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
343                                                     &server_keyblock);
344                         torture_fail(tctx, 
345                                      talloc_asprintf(tctx, 
346                                                      "(saved test) Server Keyblock encoding failed: %s", 
347                                                      smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
348                                                                                 ret, mem_ctx)));
349                 }
350                 krbtgt_keyblock_p = &krbtgt_keyblock;
351         } else {
352                 krbtgt_keyblock_p = NULL;
353         }
354
355         pac_file = torture_setting_string(tctx, "pac_file", NULL);
356         if (pac_file) {
357                 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
358                 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
359         } else {
360                 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
361         }
362         
363         dump_data(10,tmp_blob.data,tmp_blob.length);
364
365         principal_string = torture_setting_string(tctx, "pac_client_principal", 
366                                                   "w2003final$@WIN2K3.THINKER.LOCAL");
367
368         authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
369         authtime = strtoull(authtime_string, NULL, 0);
370
371         ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
372                               &client_principal);
373         if (ret) {
374                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
375                                             krbtgt_keyblock_p);
376                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
377                                             &server_keyblock);
378                 torture_fail(tctx,  
379                              talloc_asprintf(tctx, 
380                                              "(saved test) parsing of client principal [%s] failed: %s", 
381                                              principal_string, 
382                                              smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
383         }
384
385         /* Decode and verify the signaure on the PAC */
386         nt_status = kerberos_decode_pac(mem_ctx, 
387                                         lp_iconv_convenience(tctx->lp_ctx),
388                                         &pac_data,
389                                         tmp_blob,
390                                         smb_krb5_context->krb5_context,
391                                         krbtgt_keyblock_p,
392                                         &server_keyblock, 
393                                         client_principal, authtime, NULL);
394         if (!NT_STATUS_IS_OK(nt_status)) {
395                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
396                                             krbtgt_keyblock_p);
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, talloc_asprintf(tctx, 
402                                                    "(saved test) PAC decoding failed: %s", 
403                                                    nt_errstr(nt_status)));
404         }
405
406         /* Parse the PAC again, for the logon info this time */
407         nt_status = kerberos_pac_logon_info(mem_ctx, 
408                                             lp_iconv_convenience(tctx->lp_ctx),
409                                             &logon_info,
410                                             tmp_blob,
411                                             smb_krb5_context->krb5_context,
412                                             krbtgt_keyblock_p,
413                                             &server_keyblock,
414                                             client_principal, authtime, NULL);
415
416         if (!NT_STATUS_IS_OK(nt_status)) {
417                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
418                                             krbtgt_keyblock_p);
419                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
420                                             &server_keyblock);
421                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
422         
423                 torture_fail(tctx,  
424                              talloc_asprintf(tctx, 
425                                              "(saved test) PAC decoding (for logon info) failed: %s", 
426                                              nt_errstr(nt_status)));
427         }
428
429         validation.sam3 = &logon_info->info3;
430         nt_status = make_server_info_netlogon_validation(mem_ctx,
431                                                          "",
432                                                          3, &validation,
433                                                          &server_info_out); 
434         if (!NT_STATUS_IS_OK(nt_status)) {
435                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
436                                             krbtgt_keyblock_p);
437                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
438                                             &server_keyblock);
439                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
440
441                 torture_fail(tctx,  
442                              talloc_asprintf(tctx, 
443                                              "(saved test) PAC decoding (make server info) failed: %s", 
444                                              nt_errstr(nt_status)));
445         }
446
447         if (!pac_file &&
448             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
449                                                 "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
450                            server_info_out->account_sid)) {
451                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
452                                             krbtgt_keyblock_p);
453                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
454                                             &server_keyblock);
455                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
456
457                 torture_fail(tctx,  
458                              talloc_asprintf(tctx, 
459                                              "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
460                                              "S-1-5-21-3048156945-3961193616-3706469200-1005", 
461                                              dom_sid_string(mem_ctx, server_info_out->account_sid)));
462         }
463
464         if (krbtgt_bytes == NULL) {
465                 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
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                 return true;
470         }
471
472         ret = kerberos_encode_pac(mem_ctx, 
473                                   lp_iconv_convenience(tctx->lp_ctx),
474                                   pac_data,
475                                   smb_krb5_context->krb5_context,
476                                   krbtgt_keyblock_p,
477                                   &server_keyblock,
478                                   &validate_blob);
479
480         if (ret != 0) {
481                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
482                                             krbtgt_keyblock_p);
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                 torture_fail(tctx, "(saved test) PAC push failed");
488         }
489
490         dump_data(10, validate_blob.data, validate_blob.length);
491
492         /* compare both the length and the data bytes after a
493          * pull/push cycle.  This ensures we use the exact same
494          * pointer, padding etc algorithms as win2k3.
495          */
496         if (tmp_blob.length != validate_blob.length) {
497                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
498                                             krbtgt_keyblock_p);
499                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
500                                             &server_keyblock);
501                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
502
503                 torture_fail(tctx, 
504                              talloc_asprintf(tctx, 
505                                              "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
506                                              (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
507         }
508
509         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
510                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
511                                             krbtgt_keyblock_p);
512                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
513                                             &server_keyblock);
514                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
515
516                 DEBUG(0, ("tmp_data:\n"));
517                 dump_data(0, tmp_blob.data, tmp_blob.length);
518                 DEBUG(0, ("validate_blob:\n"));
519                 dump_data(0, validate_blob.data, validate_blob.length);
520
521                 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
522         }
523
524         ret = kerberos_create_pac(mem_ctx, 
525                                   lp_iconv_convenience(tctx->lp_ctx),
526                                   server_info_out,
527                                   smb_krb5_context->krb5_context,
528                                   krbtgt_keyblock_p,
529                                   &server_keyblock,
530                                   client_principal, authtime,
531                                   &validate_blob);
532
533         if (ret != 0) {
534                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
535                                             krbtgt_keyblock_p);
536                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
537                                             &server_keyblock);
538                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
539
540                 torture_fail(tctx, "(saved test) regnerated PAC create failed");
541         }
542
543         dump_data(10,validate_blob.data,validate_blob.length);
544
545         /* compare both the length and the data bytes after a
546          * pull/push cycle.  This ensures we use the exact same
547          * pointer, padding etc algorithms as win2k3.
548          */
549         if (tmp_blob.length != validate_blob.length) {
550                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
551                                                lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
552                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
553                 nt_status = ndr_map_error2ntstatus(ndr_err);
554                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
555                 
556                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
557
558                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
559
560                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
561                                             krbtgt_keyblock_p);
562                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
563                                             &server_keyblock);
564                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
565
566                 torture_fail(tctx, talloc_asprintf(tctx, 
567                                                    "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
568                                                    (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
569         }
570
571         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
572                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
573                                                lp_iconv_convenience(tctx->lp_ctx), &pac_data2,
574                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
575                 nt_status = ndr_map_error2ntstatus(ndr_err);
576                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
577                 
578                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
579
580                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
581
582                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
583                                             krbtgt_keyblock_p);
584                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
585                                             &server_keyblock);
586                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
587
588                 DEBUG(0, ("tmp_data:\n"));
589                 dump_data(0, tmp_blob.data, tmp_blob.length);
590                 DEBUG(0, ("validate_blob:\n"));
591                 dump_data(0, validate_blob.data, validate_blob.length);
592
593                 torture_fail(tctx, talloc_asprintf(tctx, 
594                                                    "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
595         }
596
597         /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
598         nt_status = kerberos_decode_pac(mem_ctx, 
599                                         lp_iconv_convenience(tctx->lp_ctx),
600                                         &pac_data,
601                                         tmp_blob,
602                                         smb_krb5_context->krb5_context,
603                                         krbtgt_keyblock_p,
604                                         &server_keyblock,
605                                         client_principal, 
606                                         authtime + 1, NULL);
607         if (NT_STATUS_IS_OK(nt_status)) {
608
609                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
610                                             krbtgt_keyblock_p);
611                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
612                                             &server_keyblock);
613                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
614                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
615         }
616
617         /* Break the client principal */
618         krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
619
620         broken_principal_string = talloc_strdup(mem_ctx, principal_string);
621         broken_principal_string[0]++;
622
623         ret = krb5_parse_name(smb_krb5_context->krb5_context,
624                               broken_principal_string, &client_principal);
625         if (ret) {
626
627                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
628                                             krbtgt_keyblock_p);
629                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
630                                             &server_keyblock);
631                 torture_fail(tctx, talloc_asprintf(tctx, 
632                                                    "(saved test) parsing of broken client principal failed: %s", 
633                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
634         }
635
636         nt_status = kerberos_decode_pac(mem_ctx, 
637                                         lp_iconv_convenience(tctx->lp_ctx),
638                                         &pac_data,
639                                         tmp_blob,
640                                         smb_krb5_context->krb5_context,
641                                         krbtgt_keyblock_p,
642                                         &server_keyblock,
643                                         client_principal, 
644                                         authtime, NULL);
645         if (NT_STATUS_IS_OK(nt_status)) {
646                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
647                                             krbtgt_keyblock_p);
648                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
649                                             &server_keyblock);
650                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
651         }
652
653         /* Finally...  Bugger up the signature, and check we fail the checksum */
654         tmp_blob.data[tmp_blob.length - 2]++;
655
656         nt_status = kerberos_decode_pac(mem_ctx, 
657                                         lp_iconv_convenience(tctx->lp_ctx),
658                                         &pac_data,
659                                         tmp_blob,
660                                         smb_krb5_context->krb5_context,
661                                         krbtgt_keyblock_p,
662                                         &server_keyblock,
663                                         client_principal, 
664                                         authtime, NULL);
665         if (NT_STATUS_IS_OK(nt_status)) {
666                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
667                                             krbtgt_keyblock_p);
668                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
669                                             &server_keyblock);
670                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
671         }
672
673         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
674                                     krbtgt_keyblock_p);
675         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
676                                     &server_keyblock);
677         return true;
678 }
679
680 struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
681 {
682         struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
683
684         torture_suite_add_simple_test(suite, "self check", 
685                                       torture_pac_self_check);
686         torture_suite_add_simple_test(suite, "saved check",
687                                       torture_pac_saved_check);
688         return suite;
689 }