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