1c19800e8SDoug Rabson /*
2ae771770SStanislav 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 the Institute nor the names of its contributors
18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson * without specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson * SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34ae771770SStanislav Sedov #include "ntlm.h"
35c19800e8SDoug Rabson
36c19800e8SDoug Rabson static int
from_file(const char * fn,const char * target_domain,char ** username,struct ntlm_buf * key)37c19800e8SDoug Rabson from_file(const char *fn, const char *target_domain,
38c19800e8SDoug Rabson char **username, struct ntlm_buf *key)
39c19800e8SDoug Rabson {
40c19800e8SDoug Rabson char *str, buf[1024];
41c19800e8SDoug Rabson FILE *f;
42c19800e8SDoug Rabson
43c19800e8SDoug Rabson f = fopen(fn, "r");
44c19800e8SDoug Rabson if (f == NULL)
45c19800e8SDoug Rabson return ENOENT;
46ae771770SStanislav Sedov rk_cloexec_file(f);
47c19800e8SDoug Rabson
48c19800e8SDoug Rabson while (fgets(buf, sizeof(buf), f) != NULL) {
49c19800e8SDoug Rabson char *d, *u, *p;
50c19800e8SDoug Rabson buf[strcspn(buf, "\r\n")] = '\0';
51c19800e8SDoug Rabson if (buf[0] == '#')
52c19800e8SDoug Rabson continue;
53c19800e8SDoug Rabson str = NULL;
54c19800e8SDoug Rabson d = strtok_r(buf, ":", &str);
55*ed549cb0SCy Schubert if (!d)
56*ed549cb0SCy Schubert continue;
57c19800e8SDoug Rabson if (d && strcasecmp(target_domain, d) != 0)
58c19800e8SDoug Rabson continue;
59c19800e8SDoug Rabson u = strtok_r(NULL, ":", &str);
60c19800e8SDoug Rabson p = strtok_r(NULL, ":", &str);
61c19800e8SDoug Rabson if (u == NULL || p == NULL)
62c19800e8SDoug Rabson continue;
63c19800e8SDoug Rabson
64c19800e8SDoug Rabson *username = strdup(u);
65c19800e8SDoug Rabson
66c19800e8SDoug Rabson heim_ntlm_nt_key(p, key);
67c19800e8SDoug Rabson
68c19800e8SDoug Rabson memset(buf, 0, sizeof(buf));
69c19800e8SDoug Rabson fclose(f);
70c19800e8SDoug Rabson return 0;
71c19800e8SDoug Rabson }
72c19800e8SDoug Rabson memset(buf, 0, sizeof(buf));
73c19800e8SDoug Rabson fclose(f);
74c19800e8SDoug Rabson return ENOENT;
75c19800e8SDoug Rabson }
76c19800e8SDoug Rabson
77c19800e8SDoug Rabson static int
get_user_file(const ntlm_name target_name,char ** username,struct ntlm_buf * key)78c19800e8SDoug Rabson get_user_file(const ntlm_name target_name,
79c19800e8SDoug Rabson char **username, struct ntlm_buf *key)
80c19800e8SDoug Rabson {
81c19800e8SDoug Rabson const char *fn;
82c19800e8SDoug Rabson
83c19800e8SDoug Rabson if (issuid())
84c19800e8SDoug Rabson return ENOENT;
85c19800e8SDoug Rabson
86c19800e8SDoug Rabson fn = getenv("NTLM_USER_FILE");
87c19800e8SDoug Rabson if (fn == NULL)
88c19800e8SDoug Rabson return ENOENT;
89c19800e8SDoug Rabson if (from_file(fn, target_name->domain, username, key) == 0)
90c19800e8SDoug Rabson return 0;
91c19800e8SDoug Rabson
92c19800e8SDoug Rabson return ENOENT;
93c19800e8SDoug Rabson }
94c19800e8SDoug Rabson
95c19800e8SDoug Rabson /*
96c19800e8SDoug Rabson * Pick up the ntlm cred from the default krb5 credential cache.
97c19800e8SDoug Rabson */
98c19800e8SDoug Rabson
99c19800e8SDoug Rabson static int
get_user_ccache(const ntlm_name name,char ** username,struct ntlm_buf * key)100c19800e8SDoug Rabson get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key)
101c19800e8SDoug Rabson {
102c19800e8SDoug Rabson krb5_context context = NULL;
103ae771770SStanislav Sedov krb5_principal client;
104c19800e8SDoug Rabson krb5_ccache id = NULL;
105ae771770SStanislav Sedov krb5_error_code ret;
106ae771770SStanislav Sedov char *confname;
107ae771770SStanislav Sedov krb5_data data;
108c19800e8SDoug Rabson
109c19800e8SDoug Rabson *username = NULL;
110ae771770SStanislav Sedov krb5_data_zero(&data);
111c19800e8SDoug Rabson key->length = 0;
112c19800e8SDoug Rabson key->data = NULL;
113c19800e8SDoug Rabson
114c19800e8SDoug Rabson ret = krb5_init_context(&context);
115c19800e8SDoug Rabson if (ret)
116c19800e8SDoug Rabson return ret;
117c19800e8SDoug Rabson
118c19800e8SDoug Rabson ret = krb5_cc_default(context, &id);
119c19800e8SDoug Rabson if (ret)
120c19800e8SDoug Rabson goto out;
121c19800e8SDoug Rabson
122c19800e8SDoug Rabson ret = krb5_cc_get_principal(context, id, &client);
123c19800e8SDoug Rabson if (ret)
124c19800e8SDoug Rabson goto out;
125c19800e8SDoug Rabson
126c19800e8SDoug Rabson ret = krb5_unparse_name_flags(context, client,
127c19800e8SDoug Rabson KRB5_PRINCIPAL_UNPARSE_NO_REALM,
128c19800e8SDoug Rabson username);
129c19800e8SDoug Rabson krb5_free_principal(context, client);
130c19800e8SDoug Rabson if (ret)
131c19800e8SDoug Rabson goto out;
132c19800e8SDoug Rabson
133ae771770SStanislav Sedov asprintf(&confname, "ntlm-key-%s", name->domain);
134ae771770SStanislav Sedov if (confname == NULL) {
135ae771770SStanislav Sedov krb5_clear_error_message(context);
136ae771770SStanislav Sedov ret = ENOMEM;
137c19800e8SDoug Rabson goto out;
138c19800e8SDoug Rabson }
139c19800e8SDoug Rabson
140ae771770SStanislav Sedov ret = krb5_cc_get_config(context, id, NULL,
141ae771770SStanislav Sedov confname, &data);
142ae771770SStanislav Sedov if (ret)
143c19800e8SDoug Rabson goto out;
144c19800e8SDoug Rabson
145ae771770SStanislav Sedov key->data = malloc(data.length);
146ae771770SStanislav Sedov if (key->data == NULL) {
147ae771770SStanislav Sedov ret = ENOMEM;
148ae771770SStanislav Sedov goto out;
149ae771770SStanislav Sedov }
150ae771770SStanislav Sedov key->length = data.length;
151ae771770SStanislav Sedov memcpy(key->data, data.data, data.length);
152c19800e8SDoug Rabson
153c19800e8SDoug Rabson out:
154ae771770SStanislav Sedov krb5_data_free(&data);
155c19800e8SDoug Rabson if (id)
156c19800e8SDoug Rabson krb5_cc_close(context, id);
157ae771770SStanislav Sedov
158c19800e8SDoug Rabson krb5_free_context(context);
159c19800e8SDoug Rabson
160c19800e8SDoug Rabson return ret;
161c19800e8SDoug Rabson }
162c19800e8SDoug Rabson
163c19800e8SDoug Rabson int
_gss_ntlm_get_user_cred(const ntlm_name target_name,ntlm_cred * rcred)164c19800e8SDoug Rabson _gss_ntlm_get_user_cred(const ntlm_name target_name,
165c19800e8SDoug Rabson ntlm_cred *rcred)
166c19800e8SDoug Rabson {
167c19800e8SDoug Rabson ntlm_cred cred;
168c19800e8SDoug Rabson int ret;
169c19800e8SDoug Rabson
170c19800e8SDoug Rabson cred = calloc(1, sizeof(*cred));
171c19800e8SDoug Rabson if (cred == NULL)
172c19800e8SDoug Rabson return ENOMEM;
173c19800e8SDoug Rabson
174c19800e8SDoug Rabson ret = get_user_file(target_name, &cred->username, &cred->key);
175c19800e8SDoug Rabson if (ret)
176c19800e8SDoug Rabson ret = get_user_ccache(target_name, &cred->username, &cred->key);
177c19800e8SDoug Rabson if (ret) {
178c19800e8SDoug Rabson free(cred);
179c19800e8SDoug Rabson return ret;
180c19800e8SDoug Rabson }
181c19800e8SDoug Rabson
182c19800e8SDoug Rabson cred->domain = strdup(target_name->domain);
183c19800e8SDoug Rabson *rcred = cred;
184c19800e8SDoug Rabson
185c19800e8SDoug Rabson return ret;
186c19800e8SDoug Rabson }
187c19800e8SDoug Rabson
188c19800e8SDoug Rabson static int
_gss_copy_cred(ntlm_cred from,ntlm_cred * to)189c19800e8SDoug Rabson _gss_copy_cred(ntlm_cred from, ntlm_cred *to)
190c19800e8SDoug Rabson {
191ae771770SStanislav Sedov *to = calloc(1, sizeof(**to));
192c19800e8SDoug Rabson if (*to == NULL)
193c19800e8SDoug Rabson return ENOMEM;
194c19800e8SDoug Rabson (*to)->username = strdup(from->username);
195c19800e8SDoug Rabson if ((*to)->username == NULL) {
196c19800e8SDoug Rabson free(*to);
197c19800e8SDoug Rabson return ENOMEM;
198c19800e8SDoug Rabson }
199c19800e8SDoug Rabson (*to)->domain = strdup(from->domain);
200c19800e8SDoug Rabson if ((*to)->domain == NULL) {
201c19800e8SDoug Rabson free((*to)->username);
202c19800e8SDoug Rabson free(*to);
203c19800e8SDoug Rabson return ENOMEM;
204c19800e8SDoug Rabson }
205c19800e8SDoug Rabson (*to)->key.data = malloc(from->key.length);
206c19800e8SDoug Rabson if ((*to)->key.data == NULL) {
207c19800e8SDoug Rabson free((*to)->domain);
208c19800e8SDoug Rabson free((*to)->username);
209c19800e8SDoug Rabson free(*to);
210c19800e8SDoug Rabson return ENOMEM;
211c19800e8SDoug Rabson }
212c19800e8SDoug Rabson memcpy((*to)->key.data, from->key.data, from->key.length);
213c19800e8SDoug Rabson (*to)->key.length = from->key.length;
214c19800e8SDoug Rabson
215c19800e8SDoug Rabson return 0;
216c19800e8SDoug Rabson }
217c19800e8SDoug Rabson
218ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV
_gss_ntlm_init_sec_context(OM_uint32 * minor_status,const gss_cred_id_t initiator_cred_handle,gss_ctx_id_t * context_handle,const gss_name_t target_name,const gss_OID mech_type,OM_uint32 req_flags,OM_uint32 time_req,const gss_channel_bindings_t input_chan_bindings,const gss_buffer_t input_token,gss_OID * actual_mech_type,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec)219c19800e8SDoug Rabson _gss_ntlm_init_sec_context
220c19800e8SDoug Rabson (OM_uint32 * minor_status,
221c19800e8SDoug Rabson const gss_cred_id_t initiator_cred_handle,
222c19800e8SDoug Rabson gss_ctx_id_t * context_handle,
223c19800e8SDoug Rabson const gss_name_t target_name,
224c19800e8SDoug Rabson const gss_OID mech_type,
225c19800e8SDoug Rabson OM_uint32 req_flags,
226c19800e8SDoug Rabson OM_uint32 time_req,
227c19800e8SDoug Rabson const gss_channel_bindings_t input_chan_bindings,
228c19800e8SDoug Rabson const gss_buffer_t input_token,
229c19800e8SDoug Rabson gss_OID * actual_mech_type,
230c19800e8SDoug Rabson gss_buffer_t output_token,
231c19800e8SDoug Rabson OM_uint32 * ret_flags,
232c19800e8SDoug Rabson OM_uint32 * time_rec
233c19800e8SDoug Rabson )
234c19800e8SDoug Rabson {
235c19800e8SDoug Rabson ntlm_ctx ctx;
236c19800e8SDoug Rabson ntlm_name name = (ntlm_name)target_name;
237c19800e8SDoug Rabson
238c19800e8SDoug Rabson *minor_status = 0;
239c19800e8SDoug Rabson
240c19800e8SDoug Rabson if (ret_flags)
241c19800e8SDoug Rabson *ret_flags = 0;
242c19800e8SDoug Rabson if (time_rec)
243c19800e8SDoug Rabson *time_rec = 0;
244c19800e8SDoug Rabson if (actual_mech_type)
245c19800e8SDoug Rabson *actual_mech_type = GSS_C_NO_OID;
246c19800e8SDoug Rabson
247c19800e8SDoug Rabson if (*context_handle == GSS_C_NO_CONTEXT) {
248c19800e8SDoug Rabson struct ntlm_type1 type1;
249c19800e8SDoug Rabson struct ntlm_buf data;
250c19800e8SDoug Rabson uint32_t flags = 0;
251c19800e8SDoug Rabson int ret;
252c19800e8SDoug Rabson
253c19800e8SDoug Rabson ctx = calloc(1, sizeof(*ctx));
254c19800e8SDoug Rabson if (ctx == NULL) {
255c19800e8SDoug Rabson *minor_status = EINVAL;
256c19800e8SDoug Rabson return GSS_S_FAILURE;
257c19800e8SDoug Rabson }
258c19800e8SDoug Rabson *context_handle = (gss_ctx_id_t)ctx;
259c19800e8SDoug Rabson
260c19800e8SDoug Rabson if (initiator_cred_handle != GSS_C_NO_CREDENTIAL) {
261c19800e8SDoug Rabson ntlm_cred cred = (ntlm_cred)initiator_cred_handle;
262c19800e8SDoug Rabson ret = _gss_copy_cred(cred, &ctx->client);
263c19800e8SDoug Rabson } else
264c19800e8SDoug Rabson ret = _gss_ntlm_get_user_cred(name, &ctx->client);
265c19800e8SDoug Rabson
266c19800e8SDoug Rabson if (ret) {
267c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
268c19800e8SDoug Rabson *minor_status = ret;
269c19800e8SDoug Rabson return GSS_S_FAILURE;
270c19800e8SDoug Rabson }
271c19800e8SDoug Rabson
272c19800e8SDoug Rabson if (req_flags & GSS_C_CONF_FLAG)
273c19800e8SDoug Rabson flags |= NTLM_NEG_SEAL;
274c19800e8SDoug Rabson if (req_flags & GSS_C_INTEG_FLAG)
275c19800e8SDoug Rabson flags |= NTLM_NEG_SIGN;
276c19800e8SDoug Rabson else
277c19800e8SDoug Rabson flags |= NTLM_NEG_ALWAYS_SIGN;
278c19800e8SDoug Rabson
279c19800e8SDoug Rabson flags |= NTLM_NEG_UNICODE;
280c19800e8SDoug Rabson flags |= NTLM_NEG_NTLM;
281c19800e8SDoug Rabson flags |= NTLM_NEG_NTLM2_SESSION;
282c19800e8SDoug Rabson flags |= NTLM_NEG_KEYEX;
283c19800e8SDoug Rabson
284c19800e8SDoug Rabson memset(&type1, 0, sizeof(type1));
285c19800e8SDoug Rabson
286c19800e8SDoug Rabson type1.flags = flags;
287c19800e8SDoug Rabson type1.domain = name->domain;
288c19800e8SDoug Rabson type1.hostname = NULL;
289c19800e8SDoug Rabson type1.os[0] = 0;
290c19800e8SDoug Rabson type1.os[1] = 0;
291c19800e8SDoug Rabson
292c19800e8SDoug Rabson ret = heim_ntlm_encode_type1(&type1, &data);
293c19800e8SDoug Rabson if (ret) {
294c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
295c19800e8SDoug Rabson *minor_status = ret;
296c19800e8SDoug Rabson return GSS_S_FAILURE;
297c19800e8SDoug Rabson }
298c19800e8SDoug Rabson
299c19800e8SDoug Rabson output_token->value = data.data;
300c19800e8SDoug Rabson output_token->length = data.length;
301c19800e8SDoug Rabson
302c19800e8SDoug Rabson return GSS_S_CONTINUE_NEEDED;
303c19800e8SDoug Rabson } else {
304c19800e8SDoug Rabson krb5_error_code ret;
305c19800e8SDoug Rabson struct ntlm_type2 type2;
306c19800e8SDoug Rabson struct ntlm_type3 type3;
307c19800e8SDoug Rabson struct ntlm_buf data;
308c19800e8SDoug Rabson
309c19800e8SDoug Rabson ctx = (ntlm_ctx)*context_handle;
310c19800e8SDoug Rabson
311c19800e8SDoug Rabson data.data = input_token->value;
312c19800e8SDoug Rabson data.length = input_token->length;
313c19800e8SDoug Rabson
314c19800e8SDoug Rabson ret = heim_ntlm_decode_type2(&data, &type2);
315c19800e8SDoug Rabson if (ret) {
316c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
317c19800e8SDoug Rabson *minor_status = ret;
318c19800e8SDoug Rabson return GSS_S_FAILURE;
319c19800e8SDoug Rabson }
320c19800e8SDoug Rabson
321c19800e8SDoug Rabson ctx->flags = type2.flags;
322c19800e8SDoug Rabson
323ae771770SStanislav Sedov /* XXX check that type2.targetinfo matches `target_name´ */
324c19800e8SDoug Rabson /* XXX check verify targetinfo buffer */
325c19800e8SDoug Rabson
326c19800e8SDoug Rabson memset(&type3, 0, sizeof(type3));
327c19800e8SDoug Rabson
328c19800e8SDoug Rabson type3.username = ctx->client->username;
329c19800e8SDoug Rabson type3.flags = type2.flags;
330c19800e8SDoug Rabson type3.targetname = type2.targetname;
331c19800e8SDoug Rabson type3.ws = rk_UNCONST("workstation");
332c19800e8SDoug Rabson
333c19800e8SDoug Rabson /*
334c19800e8SDoug Rabson * NTLM Version 1 if no targetinfo buffer.
335c19800e8SDoug Rabson */
336c19800e8SDoug Rabson
337c19800e8SDoug Rabson if (1 || type2.targetinfo.length == 0) {
338c19800e8SDoug Rabson struct ntlm_buf sessionkey;
339c19800e8SDoug Rabson
340c19800e8SDoug Rabson if (type2.flags & NTLM_NEG_NTLM2_SESSION) {
341c19800e8SDoug Rabson unsigned char nonce[8];
342c19800e8SDoug Rabson
343c19800e8SDoug Rabson if (RAND_bytes(nonce, sizeof(nonce)) != 1) {
344c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,
345c19800e8SDoug Rabson context_handle, NULL);
346c19800e8SDoug Rabson *minor_status = EINVAL;
347c19800e8SDoug Rabson return GSS_S_FAILURE;
348c19800e8SDoug Rabson }
349c19800e8SDoug Rabson
350c19800e8SDoug Rabson ret = heim_ntlm_calculate_ntlm2_sess(nonce,
351ae771770SStanislav Sedov type2.challenge,
352c19800e8SDoug Rabson ctx->client->key.data,
353c19800e8SDoug Rabson &type3.lm,
354c19800e8SDoug Rabson &type3.ntlm);
355c19800e8SDoug Rabson } else {
356c19800e8SDoug Rabson ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data,
357c19800e8SDoug Rabson ctx->client->key.length,
358ae771770SStanislav Sedov type2.challenge,
359c19800e8SDoug Rabson &type3.ntlm);
360c19800e8SDoug Rabson
361c19800e8SDoug Rabson }
362c19800e8SDoug Rabson if (ret) {
363c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
364c19800e8SDoug Rabson *minor_status = ret;
365c19800e8SDoug Rabson return GSS_S_FAILURE;
366c19800e8SDoug Rabson }
367c19800e8SDoug Rabson
368c19800e8SDoug Rabson ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data,
369c19800e8SDoug Rabson ctx->client->key.length,
370c19800e8SDoug Rabson &sessionkey,
371c19800e8SDoug Rabson &type3.sessionkey);
372c19800e8SDoug Rabson if (ret) {
373c19800e8SDoug Rabson if (type3.lm.data)
374c19800e8SDoug Rabson free(type3.lm.data);
375c19800e8SDoug Rabson if (type3.ntlm.data)
376c19800e8SDoug Rabson free(type3.ntlm.data);
377c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
378c19800e8SDoug Rabson *minor_status = ret;
379c19800e8SDoug Rabson return GSS_S_FAILURE;
380c19800e8SDoug Rabson }
381c19800e8SDoug Rabson
382c19800e8SDoug Rabson ret = krb5_data_copy(&ctx->sessionkey,
383c19800e8SDoug Rabson sessionkey.data, sessionkey.length);
384c19800e8SDoug Rabson free(sessionkey.data);
385c19800e8SDoug Rabson if (ret) {
386c19800e8SDoug Rabson if (type3.lm.data)
387c19800e8SDoug Rabson free(type3.lm.data);
388c19800e8SDoug Rabson if (type3.ntlm.data)
389c19800e8SDoug Rabson free(type3.ntlm.data);
390c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
391c19800e8SDoug Rabson *minor_status = ret;
392c19800e8SDoug Rabson return GSS_S_FAILURE;
393c19800e8SDoug Rabson }
394c19800e8SDoug Rabson ctx->status |= STATUS_SESSIONKEY;
395c19800e8SDoug Rabson
396c19800e8SDoug Rabson } else {
397c19800e8SDoug Rabson struct ntlm_buf sessionkey;
398c19800e8SDoug Rabson unsigned char ntlmv2[16];
399c19800e8SDoug Rabson struct ntlm_targetinfo ti;
400c19800e8SDoug Rabson
401c19800e8SDoug Rabson /* verify infotarget */
402c19800e8SDoug Rabson
403c19800e8SDoug Rabson ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti);
404c19800e8SDoug Rabson if(ret) {
405c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,
406c19800e8SDoug Rabson context_handle, NULL);
407c19800e8SDoug Rabson *minor_status = ret;
408c19800e8SDoug Rabson return GSS_S_FAILURE;
409c19800e8SDoug Rabson }
410c19800e8SDoug Rabson
411c19800e8SDoug Rabson if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) {
412c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,
413c19800e8SDoug Rabson context_handle, NULL);
414c19800e8SDoug Rabson *minor_status = EINVAL;
415c19800e8SDoug Rabson return GSS_S_FAILURE;
416c19800e8SDoug Rabson }
417c19800e8SDoug Rabson
418c19800e8SDoug Rabson ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data,
419c19800e8SDoug Rabson ctx->client->key.length,
420c19800e8SDoug Rabson ctx->client->username,
421c19800e8SDoug Rabson name->domain,
422ae771770SStanislav Sedov type2.challenge,
423c19800e8SDoug Rabson &type2.targetinfo,
424c19800e8SDoug Rabson ntlmv2,
425c19800e8SDoug Rabson &type3.ntlm);
426c19800e8SDoug Rabson if (ret) {
427c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,
428c19800e8SDoug Rabson context_handle, NULL);
429c19800e8SDoug Rabson *minor_status = ret;
430c19800e8SDoug Rabson return GSS_S_FAILURE;
431c19800e8SDoug Rabson }
432c19800e8SDoug Rabson
433c19800e8SDoug Rabson ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2),
434c19800e8SDoug Rabson &sessionkey,
435c19800e8SDoug Rabson &type3.sessionkey);
436c19800e8SDoug Rabson memset(ntlmv2, 0, sizeof(ntlmv2));
437c19800e8SDoug Rabson if (ret) {
438c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status,
439c19800e8SDoug Rabson context_handle, NULL);
440c19800e8SDoug Rabson *minor_status = ret;
441c19800e8SDoug Rabson return GSS_S_FAILURE;
442c19800e8SDoug Rabson }
443c19800e8SDoug Rabson
444c19800e8SDoug Rabson ctx->flags |= NTLM_NEG_NTLM2_SESSION;
445c19800e8SDoug Rabson
446c19800e8SDoug Rabson ret = krb5_data_copy(&ctx->sessionkey,
447c19800e8SDoug Rabson sessionkey.data, sessionkey.length);
448c19800e8SDoug Rabson free(sessionkey.data);
449ae771770SStanislav Sedov if (ret) {
450ae771770SStanislav Sedov _gss_ntlm_delete_sec_context(minor_status,
451ae771770SStanislav Sedov context_handle, NULL);
452ae771770SStanislav Sedov *minor_status = ret;
453ae771770SStanislav Sedov return GSS_S_FAILURE;
454ae771770SStanislav Sedov }
455c19800e8SDoug Rabson }
456c19800e8SDoug Rabson
457c19800e8SDoug Rabson if (ctx->flags & NTLM_NEG_NTLM2_SESSION) {
458c19800e8SDoug Rabson ctx->status |= STATUS_SESSIONKEY;
459c19800e8SDoug Rabson _gss_ntlm_set_key(&ctx->u.v2.send, 0, (ctx->flags & NTLM_NEG_KEYEX),
460c19800e8SDoug Rabson ctx->sessionkey.data,
461c19800e8SDoug Rabson ctx->sessionkey.length);
462c19800e8SDoug Rabson _gss_ntlm_set_key(&ctx->u.v2.recv, 1, (ctx->flags & NTLM_NEG_KEYEX),
463c19800e8SDoug Rabson ctx->sessionkey.data,
464c19800e8SDoug Rabson ctx->sessionkey.length);
465c19800e8SDoug Rabson } else {
466c19800e8SDoug Rabson ctx->status |= STATUS_SESSIONKEY;
467c19800e8SDoug Rabson RC4_set_key(&ctx->u.v1.crypto_recv.key,
468c19800e8SDoug Rabson ctx->sessionkey.length,
469c19800e8SDoug Rabson ctx->sessionkey.data);
470c19800e8SDoug Rabson RC4_set_key(&ctx->u.v1.crypto_send.key,
471c19800e8SDoug Rabson ctx->sessionkey.length,
472c19800e8SDoug Rabson ctx->sessionkey.data);
473c19800e8SDoug Rabson }
474c19800e8SDoug Rabson
475c19800e8SDoug Rabson
476c19800e8SDoug Rabson
477c19800e8SDoug Rabson ret = heim_ntlm_encode_type3(&type3, &data);
478c19800e8SDoug Rabson free(type3.sessionkey.data);
479c19800e8SDoug Rabson if (type3.lm.data)
480c19800e8SDoug Rabson free(type3.lm.data);
481c19800e8SDoug Rabson if (type3.ntlm.data)
482c19800e8SDoug Rabson free(type3.ntlm.data);
483c19800e8SDoug Rabson if (ret) {
484c19800e8SDoug Rabson _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
485c19800e8SDoug Rabson *minor_status = ret;
486c19800e8SDoug Rabson return GSS_S_FAILURE;
487c19800e8SDoug Rabson }
488c19800e8SDoug Rabson
489c19800e8SDoug Rabson output_token->length = data.length;
490c19800e8SDoug Rabson output_token->value = data.data;
491c19800e8SDoug Rabson
492c19800e8SDoug Rabson if (actual_mech_type)
493c19800e8SDoug Rabson *actual_mech_type = GSS_NTLM_MECHANISM;
494c19800e8SDoug Rabson if (ret_flags)
495c19800e8SDoug Rabson *ret_flags = 0;
496c19800e8SDoug Rabson if (time_rec)
497c19800e8SDoug Rabson *time_rec = GSS_C_INDEFINITE;
498c19800e8SDoug Rabson
499c19800e8SDoug Rabson ctx->status |= STATUS_OPEN;
500c19800e8SDoug Rabson
501c19800e8SDoug Rabson return GSS_S_COMPLETE;
502c19800e8SDoug Rabson }
503c19800e8SDoug Rabson }
504