2 Unix SMB/CIFS implementation.
4 Validate the krb5 pac generation routines
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
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.
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.
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.
25 #include "system/kerberos.h"
26 #include "auth/auth.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
32 static BOOL torture_pac_self_check(void)
35 TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
37 struct PAC_LOGON_INFO *pac_info;
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;
47 struct smb_krb5_context *smb_krb5_context;
49 struct auth_serversupplied_info *server_info;
51 ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
58 generate_random_buffer(server_bytes, 16);
59 generate_random_buffer(krbtgt_bytes, 16);
61 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
63 server_bytes, sizeof(server_bytes),
66 DEBUG(1, ("Server Keyblock encoding failed: %s\n",
67 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
74 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
76 krbtgt_bytes, sizeof(krbtgt_bytes),
79 DEBUG(1, ("KRBTGT Keyblock encoding failed: %s\n",
80 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
83 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
89 /* We need an input, and this one requires no underlying database */
90 nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
92 if (!NT_STATUS_IS_OK(nt_status)) {
93 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
95 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
101 /* OK, go ahead and make a PAC */
102 ret = kerberos_encode_pac(mem_ctx, server_info,
103 smb_krb5_context->krb5_context,
108 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
112 DEBUG(1, ("PAC encoding failed: %s\n",
113 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
116 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
118 talloc_free(mem_ctx);
122 /* dump_data(0,tmp_blob.data,tmp_blob.length); */
124 /* Now check that we can read it back */
125 nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
129 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
132 DEBUG(1, ("PAC decoding failed: %s\n",
133 nt_errstr(nt_status)));
135 talloc_free(mem_ctx);
139 talloc_free(mem_ctx);
144 /* This is the PAC generated on my test network, by my test Win2k3 server.
145 -- abartlet 2005-07-04
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
190 /* Check with a known 'well formed' PAC, from my test server */
191 static BOOL torture_pac_saved_check(void)
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];
203 struct smb_krb5_context *smb_krb5_context;
205 ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
208 talloc_free(mem_ctx);
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);
216 ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
217 ENCTYPE_ARCFOUR_HMAC,
218 server_bytes, sizeof(server_bytes),
221 DEBUG(1, ("Server Keyblock encoding failed: %s\n",
222 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
225 talloc_free(mem_ctx);
229 tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
231 /*tmp_blob.data = file_load(lp_parm_string(-1,"torture","pac_file"), &tmp_blob.length);*/
233 /*dump_data(0,tmp_blob.data,tmp_blob.length);*/
235 /* Decode and verify the signaure on the PAC */
236 nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
240 krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
243 DEBUG(1, ("PAC decoding failed: %s\n",
244 nt_errstr(nt_status)));
246 talloc_free(mem_ctx);
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);
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);
266 /* dump_data(0,validate_blob.data,validate_blob.length); */
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
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);
280 talloc_free(mem_ctx);
284 BOOL torture_pac(void)
287 ret &= torture_pac_self_check();
288 ret &= torture_pac_saved_check();
294 BOOL torture_pac(void)
296 printf("Cannot do PAC test without Krb5\n");