1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson * are met:
9c19800e8SDoug Rabson *
10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson *
13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson *
17c19800e8SDoug Rabson * 3. Neither the name of KTH nor the names of its contributors may be
18c19800e8SDoug Rabson * used to endorse or promote products derived from this software without
19c19800e8SDoug Rabson * specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22c19800e8SDoug Rabson * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24c19800e8SDoug Rabson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25c19800e8SDoug Rabson * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26c19800e8SDoug Rabson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27c19800e8SDoug Rabson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28c19800e8SDoug Rabson * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29c19800e8SDoug Rabson * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30c19800e8SDoug Rabson * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31c19800e8SDoug Rabson * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34c19800e8SDoug Rabson #include "config.h"
35c19800e8SDoug Rabson
36*ae771770SStanislav Sedov #include <roken.h>
37c19800e8SDoug Rabson #include <stdio.h>
38c19800e8SDoug Rabson #include <gssapi.h>
39c19800e8SDoug Rabson #include <err.h>
40c19800e8SDoug Rabson #include <getarg.h>
41c19800e8SDoug Rabson #include "test_common.h"
42c19800e8SDoug Rabson
43c19800e8SDoug Rabson #include <krb5.h>
44c19800e8SDoug Rabson #include <heimntlm.h>
45c19800e8SDoug Rabson
46c19800e8SDoug Rabson static int
test_libntlm_v1(int flags)47c19800e8SDoug Rabson test_libntlm_v1(int flags)
48c19800e8SDoug Rabson {
49c19800e8SDoug Rabson const char *user = "foo",
50c19800e8SDoug Rabson *domain = "mydomain",
51c19800e8SDoug Rabson *password = "digestpassword";
52c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
53c19800e8SDoug Rabson gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
54c19800e8SDoug Rabson gss_buffer_desc input, output;
55c19800e8SDoug Rabson struct ntlm_type1 type1;
56c19800e8SDoug Rabson struct ntlm_type2 type2;
57c19800e8SDoug Rabson struct ntlm_type3 type3;
58c19800e8SDoug Rabson struct ntlm_buf data;
59c19800e8SDoug Rabson krb5_error_code ret;
60c19800e8SDoug Rabson gss_name_t src_name = GSS_C_NO_NAME;
61c19800e8SDoug Rabson
62c19800e8SDoug Rabson memset(&type1, 0, sizeof(type1));
63c19800e8SDoug Rabson memset(&type2, 0, sizeof(type2));
64c19800e8SDoug Rabson memset(&type3, 0, sizeof(type3));
65c19800e8SDoug Rabson
66c19800e8SDoug Rabson type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags;
67c19800e8SDoug Rabson type1.domain = strdup(domain);
68c19800e8SDoug Rabson type1.hostname = NULL;
69c19800e8SDoug Rabson type1.os[0] = 0;
70c19800e8SDoug Rabson type1.os[1] = 0;
71c19800e8SDoug Rabson
72c19800e8SDoug Rabson ret = heim_ntlm_encode_type1(&type1, &data);
73c19800e8SDoug Rabson if (ret)
74c19800e8SDoug Rabson errx(1, "heim_ntlm_encode_type1");
75c19800e8SDoug Rabson
76c19800e8SDoug Rabson input.value = data.data;
77c19800e8SDoug Rabson input.length = data.length;
78c19800e8SDoug Rabson
79c19800e8SDoug Rabson output.length = 0;
80c19800e8SDoug Rabson output.value = NULL;
81c19800e8SDoug Rabson
82c19800e8SDoug Rabson maj_stat = gss_accept_sec_context(&min_stat,
83c19800e8SDoug Rabson &ctx,
84c19800e8SDoug Rabson GSS_C_NO_CREDENTIAL,
85c19800e8SDoug Rabson &input,
86c19800e8SDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
87c19800e8SDoug Rabson NULL,
88c19800e8SDoug Rabson NULL,
89c19800e8SDoug Rabson &output,
90c19800e8SDoug Rabson NULL,
91c19800e8SDoug Rabson NULL,
92c19800e8SDoug Rabson NULL);
93c19800e8SDoug Rabson free(data.data);
94c19800e8SDoug Rabson if (GSS_ERROR(maj_stat))
95c19800e8SDoug Rabson errx(1, "accept_sec_context v1: %s",
96c19800e8SDoug Rabson gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
97c19800e8SDoug Rabson
98c19800e8SDoug Rabson if (output.length == 0)
99c19800e8SDoug Rabson errx(1, "output.length == 0");
100c19800e8SDoug Rabson
101c19800e8SDoug Rabson data.data = output.value;
102c19800e8SDoug Rabson data.length = output.length;
103c19800e8SDoug Rabson
104c19800e8SDoug Rabson ret = heim_ntlm_decode_type2(&data, &type2);
105c19800e8SDoug Rabson if (ret)
106c19800e8SDoug Rabson errx(1, "heim_ntlm_decode_type2");
107c19800e8SDoug Rabson
108c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output);
109c19800e8SDoug Rabson
110c19800e8SDoug Rabson type3.flags = type2.flags;
111c19800e8SDoug Rabson type3.username = rk_UNCONST(user);
112c19800e8SDoug Rabson type3.targetname = type2.targetname;
113c19800e8SDoug Rabson type3.ws = rk_UNCONST("workstation");
114c19800e8SDoug Rabson
115c19800e8SDoug Rabson {
116c19800e8SDoug Rabson struct ntlm_buf key;
117c19800e8SDoug Rabson
118c19800e8SDoug Rabson heim_ntlm_nt_key(password, &key);
119c19800e8SDoug Rabson
120c19800e8SDoug Rabson heim_ntlm_calculate_ntlm1(key.data, key.length,
121*ae771770SStanislav Sedov type2.challenge,
122c19800e8SDoug Rabson &type3.ntlm);
123c19800e8SDoug Rabson
124c19800e8SDoug Rabson if (flags & NTLM_NEG_KEYEX) {
125c19800e8SDoug Rabson struct ntlm_buf sessionkey;
126c19800e8SDoug Rabson heim_ntlm_build_ntlm1_master(key.data, key.length,
127c19800e8SDoug Rabson &sessionkey,
128c19800e8SDoug Rabson &type3.sessionkey);
129c19800e8SDoug Rabson free(sessionkey.data);
130c19800e8SDoug Rabson }
131c19800e8SDoug Rabson free(key.data);
132c19800e8SDoug Rabson }
133c19800e8SDoug Rabson
134c19800e8SDoug Rabson ret = heim_ntlm_encode_type3(&type3, &data);
135c19800e8SDoug Rabson if (ret)
136c19800e8SDoug Rabson errx(1, "heim_ntlm_encode_type3");
137c19800e8SDoug Rabson
138c19800e8SDoug Rabson input.length = data.length;
139c19800e8SDoug Rabson input.value = data.data;
140c19800e8SDoug Rabson
141c19800e8SDoug Rabson maj_stat = gss_accept_sec_context(&min_stat,
142c19800e8SDoug Rabson &ctx,
143c19800e8SDoug Rabson GSS_C_NO_CREDENTIAL,
144c19800e8SDoug Rabson &input,
145c19800e8SDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
146c19800e8SDoug Rabson &src_name,
147c19800e8SDoug Rabson NULL,
148c19800e8SDoug Rabson &output,
149c19800e8SDoug Rabson NULL,
150c19800e8SDoug Rabson NULL,
151c19800e8SDoug Rabson NULL);
152c19800e8SDoug Rabson free(input.value);
153c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
154c19800e8SDoug Rabson errx(1, "accept_sec_context v1 2 %s",
155c19800e8SDoug Rabson gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
156c19800e8SDoug Rabson
157c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output);
158c19800e8SDoug Rabson gss_delete_sec_context(&min_stat, &ctx, NULL);
159c19800e8SDoug Rabson
160c19800e8SDoug Rabson if (src_name == GSS_C_NO_NAME)
161c19800e8SDoug Rabson errx(1, "no source name!");
162c19800e8SDoug Rabson
163c19800e8SDoug Rabson gss_display_name(&min_stat, src_name, &output, NULL);
164c19800e8SDoug Rabson
165c19800e8SDoug Rabson printf("src_name: %.*s\n", (int)output.length, (char*)output.value);
166c19800e8SDoug Rabson
167c19800e8SDoug Rabson gss_release_name(&min_stat, &src_name);
168c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output);
169c19800e8SDoug Rabson
170c19800e8SDoug Rabson return 0;
171c19800e8SDoug Rabson }
172c19800e8SDoug Rabson
173c19800e8SDoug Rabson static int
test_libntlm_v2(int flags)174c19800e8SDoug Rabson test_libntlm_v2(int flags)
175c19800e8SDoug Rabson {
176c19800e8SDoug Rabson const char *user = "foo",
177c19800e8SDoug Rabson *domain = "mydomain",
178c19800e8SDoug Rabson *password = "digestpassword";
179c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
180c19800e8SDoug Rabson gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
181c19800e8SDoug Rabson gss_buffer_desc input, output;
182c19800e8SDoug Rabson struct ntlm_type1 type1;
183c19800e8SDoug Rabson struct ntlm_type2 type2;
184c19800e8SDoug Rabson struct ntlm_type3 type3;
185c19800e8SDoug Rabson struct ntlm_buf data;
186c19800e8SDoug Rabson krb5_error_code ret;
187c19800e8SDoug Rabson
188c19800e8SDoug Rabson memset(&type1, 0, sizeof(type1));
189c19800e8SDoug Rabson memset(&type2, 0, sizeof(type2));
190c19800e8SDoug Rabson memset(&type3, 0, sizeof(type3));
191c19800e8SDoug Rabson
192c19800e8SDoug Rabson type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_NTLM|flags;
193c19800e8SDoug Rabson type1.domain = strdup(domain);
194c19800e8SDoug Rabson type1.hostname = NULL;
195c19800e8SDoug Rabson type1.os[0] = 0;
196c19800e8SDoug Rabson type1.os[1] = 0;
197c19800e8SDoug Rabson
198c19800e8SDoug Rabson ret = heim_ntlm_encode_type1(&type1, &data);
199c19800e8SDoug Rabson if (ret)
200c19800e8SDoug Rabson errx(1, "heim_ntlm_encode_type1");
201c19800e8SDoug Rabson
202c19800e8SDoug Rabson input.value = data.data;
203c19800e8SDoug Rabson input.length = data.length;
204c19800e8SDoug Rabson
205c19800e8SDoug Rabson output.length = 0;
206c19800e8SDoug Rabson output.value = NULL;
207c19800e8SDoug Rabson
208c19800e8SDoug Rabson maj_stat = gss_accept_sec_context(&min_stat,
209c19800e8SDoug Rabson &ctx,
210c19800e8SDoug Rabson GSS_C_NO_CREDENTIAL,
211c19800e8SDoug Rabson &input,
212c19800e8SDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
213c19800e8SDoug Rabson NULL,
214c19800e8SDoug Rabson NULL,
215c19800e8SDoug Rabson &output,
216c19800e8SDoug Rabson NULL,
217c19800e8SDoug Rabson NULL,
218c19800e8SDoug Rabson NULL);
219c19800e8SDoug Rabson free(data.data);
220c19800e8SDoug Rabson if (GSS_ERROR(maj_stat))
221c19800e8SDoug Rabson errx(1, "accept_sec_context v2 %s",
222c19800e8SDoug Rabson gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
223c19800e8SDoug Rabson
224c19800e8SDoug Rabson if (output.length == 0)
225c19800e8SDoug Rabson errx(1, "output.length == 0");
226c19800e8SDoug Rabson
227c19800e8SDoug Rabson data.data = output.value;
228c19800e8SDoug Rabson data.length = output.length;
229c19800e8SDoug Rabson
230c19800e8SDoug Rabson ret = heim_ntlm_decode_type2(&data, &type2);
231c19800e8SDoug Rabson if (ret)
232c19800e8SDoug Rabson errx(1, "heim_ntlm_decode_type2");
233c19800e8SDoug Rabson
234c19800e8SDoug Rabson type3.flags = type2.flags;
235c19800e8SDoug Rabson type3.username = rk_UNCONST(user);
236c19800e8SDoug Rabson type3.targetname = type2.targetname;
237c19800e8SDoug Rabson type3.ws = rk_UNCONST("workstation");
238c19800e8SDoug Rabson
239c19800e8SDoug Rabson {
240c19800e8SDoug Rabson struct ntlm_buf key;
241c19800e8SDoug Rabson unsigned char ntlmv2[16];
242c19800e8SDoug Rabson
243c19800e8SDoug Rabson heim_ntlm_nt_key(password, &key);
244c19800e8SDoug Rabson
245c19800e8SDoug Rabson heim_ntlm_calculate_ntlm2(key.data, key.length,
246c19800e8SDoug Rabson user,
247c19800e8SDoug Rabson type2.targetname,
248*ae771770SStanislav Sedov type2.challenge,
249c19800e8SDoug Rabson &type2.targetinfo,
250c19800e8SDoug Rabson ntlmv2,
251c19800e8SDoug Rabson &type3.ntlm);
252c19800e8SDoug Rabson free(key.data);
253c19800e8SDoug Rabson
254c19800e8SDoug Rabson if (flags & NTLM_NEG_KEYEX) {
255c19800e8SDoug Rabson struct ntlm_buf sessionkey;
256c19800e8SDoug Rabson heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2),
257c19800e8SDoug Rabson &sessionkey,
258c19800e8SDoug Rabson &type3.sessionkey);
259c19800e8SDoug Rabson free(sessionkey.data);
260c19800e8SDoug Rabson }
261c19800e8SDoug Rabson }
262c19800e8SDoug Rabson
263c19800e8SDoug Rabson ret = heim_ntlm_encode_type3(&type3, &data);
264c19800e8SDoug Rabson if (ret)
265c19800e8SDoug Rabson errx(1, "heim_ntlm_encode_type3");
266c19800e8SDoug Rabson
267c19800e8SDoug Rabson input.length = data.length;
268c19800e8SDoug Rabson input.value = data.data;
269c19800e8SDoug Rabson
270c19800e8SDoug Rabson maj_stat = gss_accept_sec_context(&min_stat,
271c19800e8SDoug Rabson &ctx,
272c19800e8SDoug Rabson GSS_C_NO_CREDENTIAL,
273c19800e8SDoug Rabson &input,
274c19800e8SDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
275c19800e8SDoug Rabson NULL,
276c19800e8SDoug Rabson NULL,
277c19800e8SDoug Rabson &output,
278c19800e8SDoug Rabson NULL,
279c19800e8SDoug Rabson NULL,
280c19800e8SDoug Rabson NULL);
281c19800e8SDoug Rabson free(input.value);
282c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
283c19800e8SDoug Rabson errx(1, "accept_sec_context v2 2 %s",
284c19800e8SDoug Rabson gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
285c19800e8SDoug Rabson
286c19800e8SDoug Rabson gss_delete_sec_context(&min_stat, &ctx, NULL);
287c19800e8SDoug Rabson
288c19800e8SDoug Rabson return 0;
289c19800e8SDoug Rabson }
290c19800e8SDoug Rabson
291c19800e8SDoug Rabson
292c19800e8SDoug Rabson
293c19800e8SDoug Rabson static int version_flag = 0;
294c19800e8SDoug Rabson static int help_flag = 0;
295c19800e8SDoug Rabson
296c19800e8SDoug Rabson static struct getargs args[] = {
297c19800e8SDoug Rabson {"version", 0, arg_flag, &version_flag, "print version", NULL },
298c19800e8SDoug Rabson {"help", 0, arg_flag, &help_flag, NULL, NULL }
299c19800e8SDoug Rabson };
300c19800e8SDoug Rabson
301c19800e8SDoug Rabson static void
usage(int ret)302c19800e8SDoug Rabson usage (int ret)
303c19800e8SDoug Rabson {
304c19800e8SDoug Rabson arg_printusage (args, sizeof(args)/sizeof(*args),
305c19800e8SDoug Rabson NULL, "");
306c19800e8SDoug Rabson exit (ret);
307c19800e8SDoug Rabson }
308c19800e8SDoug Rabson
309c19800e8SDoug Rabson int
main(int argc,char ** argv)310c19800e8SDoug Rabson main(int argc, char **argv)
311c19800e8SDoug Rabson {
312c19800e8SDoug Rabson int ret = 0, optind = 0;
313c19800e8SDoug Rabson
314c19800e8SDoug Rabson setprogname(argv[0]);
315c19800e8SDoug Rabson
316c19800e8SDoug Rabson if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
317c19800e8SDoug Rabson usage(1);
318c19800e8SDoug Rabson
319c19800e8SDoug Rabson if (help_flag)
320c19800e8SDoug Rabson usage (0);
321c19800e8SDoug Rabson
322c19800e8SDoug Rabson if(version_flag){
323c19800e8SDoug Rabson print_version(NULL);
324c19800e8SDoug Rabson exit(0);
325c19800e8SDoug Rabson }
326c19800e8SDoug Rabson
327c19800e8SDoug Rabson argc -= optind;
328c19800e8SDoug Rabson argv += optind;
329c19800e8SDoug Rabson
330c19800e8SDoug Rabson ret += test_libntlm_v1(0);
331c19800e8SDoug Rabson ret += test_libntlm_v1(NTLM_NEG_KEYEX);
332c19800e8SDoug Rabson
333c19800e8SDoug Rabson ret += test_libntlm_v2(0);
334c19800e8SDoug Rabson ret += test_libntlm_v2(NTLM_NEG_KEYEX);
335c19800e8SDoug Rabson
336c19800e8SDoug Rabson return 0;
337c19800e8SDoug Rabson }
338