r8156: I found out that the unknown[2] field of the unknown[4] array is a length...
[kai/samba-autobuild/.git] / source4 / torture / auth / pac.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Validate the krb5 pac generation routines
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "system/kerberos.h"
26 #include "auth/auth.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
29
30 #ifdef HAVE_KRB5
31
32 static BOOL torture_pac_self_check(void) 
33 {
34         NTSTATUS nt_status;
35         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
36         DATA_BLOB tmp_blob;
37         struct PAC_LOGON_INFO *pac_info;
38
39         /* Generate a nice, arbitary keyblock */
40         uint8_t server_bytes[16];
41         uint8_t krbtgt_bytes[16];
42         krb5_keyblock server_keyblock;
43         krb5_keyblock krbtgt_keyblock;
44         
45         krb5_error_code ret;
46
47         struct smb_krb5_context *smb_krb5_context;
48
49         struct auth_serversupplied_info *server_info;
50
51         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
52
53         if (ret) {
54                 talloc_free(mem_ctx);
55                 return False;
56         }
57
58         generate_random_buffer(server_bytes, 16);
59         generate_random_buffer(krbtgt_bytes, 16);
60
61         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
62                                  ENCTYPE_ARCFOUR_HMAC,
63                                  server_bytes, sizeof(server_bytes),
64                                  &server_keyblock);
65         if (ret) {
66                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
67                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
68                                                      ret, mem_ctx)));
69
70                 talloc_free(mem_ctx);
71                 return False;
72         }
73
74         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
75                                  ENCTYPE_ARCFOUR_HMAC,
76                                  krbtgt_bytes, sizeof(krbtgt_bytes),
77                                  &krbtgt_keyblock);
78         if (ret) {
79                 DEBUG(1, ("KRBTGT Keyblock encoding failed: %s\n", 
80                           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                 talloc_free(mem_ctx);
86                 return False;
87         }
88
89         /* We need an input, and this one requires no underlying database */
90         nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
91
92         if (!NT_STATUS_IS_OK(nt_status)) {
93                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
94                                             &server_keyblock);
95                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
96                                             &krbtgt_keyblock);
97                 talloc_free(mem_ctx);
98                 return False;
99         }
100         
101         /* OK, go ahead and make a PAC */
102         ret = kerberos_encode_pac(mem_ctx, server_info, 
103                                   smb_krb5_context->krb5_context,  
104                                   &krbtgt_keyblock,
105                                   &server_keyblock,
106                                   &tmp_blob);
107         
108         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
109                                     &krbtgt_keyblock);
110
111         if (ret) {
112                 DEBUG(1, ("PAC encoding failed: %s\n", 
113                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
114                                                      ret, mem_ctx)));
115
116                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
117                                             &server_keyblock);
118                 talloc_free(mem_ctx);
119                 return False;
120         }
121
122         dump_data(10,tmp_blob.data,tmp_blob.length);
123
124         /* Now check that we can read it back */
125         nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
126                                         tmp_blob,
127                                         smb_krb5_context,
128                                         &server_keyblock);
129         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
130                                     &server_keyblock);
131         if (ret) {
132                 DEBUG(1, ("PAC decoding failed: %s\n", 
133                           nt_errstr(nt_status)));
134
135                 talloc_free(mem_ctx);
136                 return False;
137         }
138
139         talloc_free(mem_ctx);
140         return True;
141 }
142
143
144 /* This is the PAC generated on my test network, by my test Win2k3 server.
145    -- abartlet 2005-07-04
146  */
147
148 static const char saved_pac[] = {
149         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
150         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
151         0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
152         0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
153         0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
154         0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
155         0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
156         0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
157         0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
158         0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
159         0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
160         0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
161         0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
162         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163         0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
164         0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165         0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167         0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
169         0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
170         0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
175         0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
176         0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
177         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
178         0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
179         0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
180         0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
181         0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
182         0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183         0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
184         0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
185         0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
186         0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
187         0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
188 };
189
190 /* Check with a known 'well formed' PAC, from my test server */
191 static BOOL torture_pac_saved_check(void) 
192 {
193         NTSTATUS nt_status;
194         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
195         DATA_BLOB tmp_blob, validate_blob;
196         struct PAC_LOGON_INFO *pac_info;
197         struct PAC_DATA pac_data;
198         krb5_keyblock server_keyblock;
199         uint8_t server_bytes[16];
200         
201         krb5_error_code ret;
202
203         struct smb_krb5_context *smb_krb5_context;
204
205         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
206
207         if (ret) {
208                 talloc_free(mem_ctx);
209                 return False;
210         }
211
212         /* The machine trust account in use when the above PAC 
213            was generated.  It used arcfour-hmac-md5, so this is easy */
214         E_md4hash("iqvwmii8CuEkyY", server_bytes);
215
216         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
217                                  ENCTYPE_ARCFOUR_HMAC,
218                                  server_bytes, sizeof(server_bytes),
219                                  &server_keyblock);
220         if (ret) {
221                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
222                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
223                                                      ret, mem_ctx)));
224
225                 talloc_free(mem_ctx);
226                 return False;
227         }
228
229         tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
230
231         /*tmp_blob.data = file_load(lp_parm_string(-1,"torture","pac_file"), &tmp_blob.length);*/
232
233         dump_data(10,tmp_blob.data,tmp_blob.length);
234
235         /* Decode and verify the signaure on the PAC */
236         nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
237                                         tmp_blob,
238                                         smb_krb5_context,
239                                         &server_keyblock);
240         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
241                                     &server_keyblock);
242         if (ret) {
243                 DEBUG(1, ("PAC decoding failed: %s\n", 
244                           nt_errstr(nt_status)));
245
246                 talloc_free(mem_ctx);
247                 return False;
248         }
249
250         nt_status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
251                                          (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
252         if (!NT_STATUS_IS_OK(nt_status)) {
253                 DEBUG(0,("can't parse the PAC\n"));
254                 talloc_free(mem_ctx);
255                 return False;
256         }
257
258         nt_status = ndr_push_struct_blob(&validate_blob, mem_ctx, &pac_data,
259                                          (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
260         if (!NT_STATUS_IS_OK(nt_status)) {
261                 DEBUG(0, ("PAC push failed: %s\n", nt_errstr(nt_status)));
262                 talloc_free(mem_ctx);
263                 return False;
264         }
265
266         dump_data(10,validate_blob.data,validate_blob.length);
267
268         /* all we can check is the length of the buffers,
269          * to check that the alignment and padding is ok,
270          * we can't compare the bytes, because we use a different algorithm
271          * to create the pointer values
272          */
273         if (tmp_blob.length != validate_blob.length) {
274                 DEBUG(0, ("PAC push failed orignial buffer length[%u] != created buffer length[%u]\n",
275                                 tmp_blob.length, validate_blob.length));
276                 talloc_free(mem_ctx);
277                 return False;
278         }
279
280         talloc_free(mem_ctx);
281         return True;
282 }
283
284 BOOL torture_pac(void) 
285 {
286         BOOL ret = True;
287         ret &= torture_pac_self_check();
288         ret &= torture_pac_saved_check();
289         return ret;
290 }
291
292 #else 
293
294 BOOL torture_pac(void) 
295 {
296         printf("Cannot do PAC test without Krb5\n");
297         return False;
298 }
299
300 #endif
301