r8110: More PAC work. I still can't get WinXP to accept the PAC, but we are
[jelmer/samba4-debian.git] / source / torture / auth / pac.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Validate the krb5 pac generation routines
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 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 "system/time.h"
27 #include "system/network.h"
28 #include "auth/auth.h"
29 #include "auth/kerberos/kerberos.h"
30 #include "librpc/gen_ndr/ndr_krb5pac.h"
31 #include "auth/auth.h"
32
33 static BOOL torture_pac_self_check(void) 
34 {
35         NTSTATUS nt_status;
36         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
37         DATA_BLOB tmp_blob;
38         struct PAC_LOGON_INFO *pac_info;
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
52         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
53
54         if (ret) {
55                 talloc_free(mem_ctx);
56                 return False;
57         }
58
59         generate_random_buffer(server_bytes, 16);
60         generate_random_buffer(krbtgt_bytes, 16);
61
62         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
63                                  ENCTYPE_ARCFOUR_HMAC,
64                                  server_bytes, sizeof(server_bytes),
65                                  &server_keyblock);
66         if (ret) {
67                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
68                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
69                                                      ret, mem_ctx)));
70
71                 talloc_free(mem_ctx);
72                 return False;
73         }
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                 DEBUG(1, ("KRBTGT Keyblock encoding failed: %s\n", 
81                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
82                                                      ret, mem_ctx)));
83
84                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
85                                             &server_keyblock);
86                 talloc_free(mem_ctx);
87                 return False;
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                 talloc_free(mem_ctx);
99                 return False;
100         }
101         
102         /* OK, go ahead and make a PAC */
103         ret = kerberos_encode_pac(mem_ctx, server_info, 
104                                   smb_krb5_context->krb5_context,  
105                                   &krbtgt_keyblock,
106                                   &server_keyblock,
107                                   &tmp_blob);
108         
109         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
110                                     &krbtgt_keyblock);
111
112         if (ret) {
113                 DEBUG(1, ("PAC encoding failed: %s\n", 
114                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
115                                                      ret, mem_ctx)));
116
117                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
118                                             &server_keyblock);
119                 talloc_free(mem_ctx);
120                 return False;
121         }
122         
123         /* Now check that we can read it back */
124         nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
125                                         tmp_blob,
126                                         smb_krb5_context,
127                                         &server_keyblock);
128         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
129                                     &server_keyblock);
130         if (ret) {
131                 DEBUG(1, ("PAC decoding failed: %s\n", 
132                           nt_errstr(nt_status)));
133
134                 talloc_free(mem_ctx);
135                 return False;
136         }
137
138         talloc_free(mem_ctx);
139         return True;
140 }
141
142
143 /* This is the PAC generated on my test network, by my test Win2k3 server.
144    -- abartlet 2005-07-04
145  */
146
147 static const char saved_pac[] = {
148         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
149         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
150         0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
151         0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
152         0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
153         0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
154         0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
155         0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
156         0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
157         0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
158         0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
159         0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
160         0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
161         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162         0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
163         0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164         0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166         0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
168         0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
169         0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170         0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
174         0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
175         0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
176         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
177         0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
178         0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
179         0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
180         0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
181         0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182         0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
183         0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
184         0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
185         0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
186         0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
187 };
188
189 /* Check with a known 'well formed' PAC, from my test server */
190 static BOOL torture_pac_saved_check(void) 
191 {
192         NTSTATUS nt_status;
193         TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
194         DATA_BLOB tmp_blob;
195         struct PAC_LOGON_INFO *pac_info;
196         krb5_keyblock server_keyblock;
197         uint8_t server_bytes[16];
198         
199         krb5_error_code ret;
200
201         struct smb_krb5_context *smb_krb5_context;
202
203         ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
204
205         if (ret) {
206                 talloc_free(mem_ctx);
207                 return False;
208         }
209
210         /* The machine trust account in use when the above PAC 
211            was generated.  It used arcfour-hmac-md5, so this is easy */
212         E_md4hash("iqvwmii8CuEkyY", server_bytes);
213
214         ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
215                                  ENCTYPE_ARCFOUR_HMAC,
216                                  server_bytes, sizeof(server_bytes),
217                                  &server_keyblock);
218         if (ret) {
219                 DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
220                           smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
221                                                      ret, mem_ctx)));
222
223                 talloc_free(mem_ctx);
224                 return False;
225         }
226
227         tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
228
229         /* Decode and verify the signaure on the PAC */
230         nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
231                                         tmp_blob,
232                                         smb_krb5_context,
233                                         &server_keyblock);
234         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
235                                     &server_keyblock);
236         if (ret) {
237                 DEBUG(1, ("PAC decoding failed: %s\n", 
238                           nt_errstr(nt_status)));
239
240                 talloc_free(mem_ctx);
241                 return False;
242         }
243         talloc_free(mem_ctx);
244         return True;
245 }
246
247 BOOL torture_pac(void) 
248 {
249         BOOL ret = True;
250         ret &= torture_pac_self_check();
251         ret &= torture_pac_saved_check();
252         return ret;
253 }