1*ae771770SStanislav Sedov /*
2*ae771770SStanislav Sedov * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3*ae771770SStanislav Sedov * (Royal Institute of Technology, Stockholm, Sweden).
4*ae771770SStanislav Sedov * All rights reserved.
5*ae771770SStanislav Sedov *
6*ae771770SStanislav Sedov * Redistribution and use in source and binary forms, with or without
7*ae771770SStanislav Sedov * modification, are permitted provided that the following conditions
8*ae771770SStanislav Sedov * are met:
9*ae771770SStanislav Sedov *
10*ae771770SStanislav Sedov * 1. Redistributions of source code must retain the above copyright
11*ae771770SStanislav Sedov * notice, this list of conditions and the following disclaimer.
12*ae771770SStanislav Sedov *
13*ae771770SStanislav Sedov * 2. Redistributions in binary form must reproduce the above copyright
14*ae771770SStanislav Sedov * notice, this list of conditions and the following disclaimer in the
15*ae771770SStanislav Sedov * documentation and/or other materials provided with the distribution.
16*ae771770SStanislav Sedov *
17*ae771770SStanislav Sedov * 3. Neither the name of the Institute nor the names of its contributors
18*ae771770SStanislav Sedov * may be used to endorse or promote products derived from this software
19*ae771770SStanislav Sedov * without specific prior written permission.
20*ae771770SStanislav Sedov *
21*ae771770SStanislav Sedov * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22*ae771770SStanislav Sedov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*ae771770SStanislav Sedov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*ae771770SStanislav Sedov * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25*ae771770SStanislav Sedov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*ae771770SStanislav Sedov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*ae771770SStanislav Sedov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*ae771770SStanislav Sedov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*ae771770SStanislav Sedov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*ae771770SStanislav Sedov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*ae771770SStanislav Sedov * SUCH DAMAGE.
32*ae771770SStanislav Sedov */
33*ae771770SStanislav Sedov
34*ae771770SStanislav Sedov #include "ntlm.h"
35*ae771770SStanislav Sedov
36*ae771770SStanislav Sedov #ifdef DIGEST
37*ae771770SStanislav Sedov
38*ae771770SStanislav Sedov /*
39*ae771770SStanislav Sedov *
40*ae771770SStanislav Sedov */
41*ae771770SStanislav Sedov
42*ae771770SStanislav Sedov struct ntlmkrb5 {
43*ae771770SStanislav Sedov krb5_context context;
44*ae771770SStanislav Sedov krb5_ntlm ntlm;
45*ae771770SStanislav Sedov krb5_realm kerberos_realm;
46*ae771770SStanislav Sedov krb5_ccache id;
47*ae771770SStanislav Sedov krb5_data opaque;
48*ae771770SStanislav Sedov int destroy;
49*ae771770SStanislav Sedov OM_uint32 flags;
50*ae771770SStanislav Sedov struct ntlm_buf key;
51*ae771770SStanislav Sedov krb5_data sessionkey;
52*ae771770SStanislav Sedov };
53*ae771770SStanislav Sedov
54*ae771770SStanislav Sedov static OM_uint32 kdc_destroy(OM_uint32 *, void *);
55*ae771770SStanislav Sedov
56*ae771770SStanislav Sedov /*
57*ae771770SStanislav Sedov * Get credential cache that the ntlm code can use to talk to the KDC
58*ae771770SStanislav Sedov * using the digest API.
59*ae771770SStanislav Sedov */
60*ae771770SStanislav Sedov
61*ae771770SStanislav Sedov static krb5_error_code
get_ccache(krb5_context context,int * destroy,krb5_ccache * id)62*ae771770SStanislav Sedov get_ccache(krb5_context context, int *destroy, krb5_ccache *id)
63*ae771770SStanislav Sedov {
64*ae771770SStanislav Sedov krb5_principal principal = NULL;
65*ae771770SStanislav Sedov krb5_error_code ret;
66*ae771770SStanislav Sedov krb5_keytab kt = NULL;
67*ae771770SStanislav Sedov
68*ae771770SStanislav Sedov *id = NULL;
69*ae771770SStanislav Sedov
70*ae771770SStanislav Sedov if (!issuid()) {
71*ae771770SStanislav Sedov const char *cache;
72*ae771770SStanislav Sedov
73*ae771770SStanislav Sedov cache = getenv("NTLM_ACCEPTOR_CCACHE");
74*ae771770SStanislav Sedov if (cache) {
75*ae771770SStanislav Sedov ret = krb5_cc_resolve(context, cache, id);
76*ae771770SStanislav Sedov if (ret)
77*ae771770SStanislav Sedov goto out;
78*ae771770SStanislav Sedov return 0;
79*ae771770SStanislav Sedov }
80*ae771770SStanislav Sedov }
81*ae771770SStanislav Sedov
82*ae771770SStanislav Sedov ret = krb5_sname_to_principal(context, NULL, "host",
83*ae771770SStanislav Sedov KRB5_NT_SRV_HST, &principal);
84*ae771770SStanislav Sedov if (ret)
85*ae771770SStanislav Sedov goto out;
86*ae771770SStanislav Sedov
87*ae771770SStanislav Sedov ret = krb5_cc_cache_match(context, principal, id);
88*ae771770SStanislav Sedov if (ret == 0)
89*ae771770SStanislav Sedov return 0;
90*ae771770SStanislav Sedov
91*ae771770SStanislav Sedov /* did not find in default credcache, lets try default keytab */
92*ae771770SStanislav Sedov ret = krb5_kt_default(context, &kt);
93*ae771770SStanislav Sedov if (ret)
94*ae771770SStanislav Sedov goto out;
95*ae771770SStanislav Sedov
96*ae771770SStanislav Sedov /* XXX check in keytab */
97*ae771770SStanislav Sedov {
98*ae771770SStanislav Sedov krb5_get_init_creds_opt *opt;
99*ae771770SStanislav Sedov krb5_creds cred;
100*ae771770SStanislav Sedov
101*ae771770SStanislav Sedov memset(&cred, 0, sizeof(cred));
102*ae771770SStanislav Sedov
103*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, "MEMORY", NULL, id);
104*ae771770SStanislav Sedov if (ret)
105*ae771770SStanislav Sedov goto out;
106*ae771770SStanislav Sedov *destroy = 1;
107*ae771770SStanislav Sedov ret = krb5_get_init_creds_opt_alloc(context, &opt);
108*ae771770SStanislav Sedov if (ret)
109*ae771770SStanislav Sedov goto out;
110*ae771770SStanislav Sedov ret = krb5_get_init_creds_keytab (context,
111*ae771770SStanislav Sedov &cred,
112*ae771770SStanislav Sedov principal,
113*ae771770SStanislav Sedov kt,
114*ae771770SStanislav Sedov 0,
115*ae771770SStanislav Sedov NULL,
116*ae771770SStanislav Sedov opt);
117*ae771770SStanislav Sedov krb5_get_init_creds_opt_free(context, opt);
118*ae771770SStanislav Sedov if (ret)
119*ae771770SStanislav Sedov goto out;
120*ae771770SStanislav Sedov ret = krb5_cc_initialize (context, *id, cred.client);
121*ae771770SStanislav Sedov if (ret) {
122*ae771770SStanislav Sedov krb5_free_cred_contents (context, &cred);
123*ae771770SStanislav Sedov goto out;
124*ae771770SStanislav Sedov }
125*ae771770SStanislav Sedov ret = krb5_cc_store_cred (context, *id, &cred);
126*ae771770SStanislav Sedov krb5_free_cred_contents (context, &cred);
127*ae771770SStanislav Sedov if (ret)
128*ae771770SStanislav Sedov goto out;
129*ae771770SStanislav Sedov }
130*ae771770SStanislav Sedov
131*ae771770SStanislav Sedov krb5_kt_close(context, kt);
132*ae771770SStanislav Sedov
133*ae771770SStanislav Sedov return 0;
134*ae771770SStanislav Sedov
135*ae771770SStanislav Sedov out:
136*ae771770SStanislav Sedov if (*id) {
137*ae771770SStanislav Sedov if (*destroy)
138*ae771770SStanislav Sedov krb5_cc_destroy(context, *id);
139*ae771770SStanislav Sedov else
140*ae771770SStanislav Sedov krb5_cc_close(context, *id);
141*ae771770SStanislav Sedov *id = NULL;
142*ae771770SStanislav Sedov }
143*ae771770SStanislav Sedov
144*ae771770SStanislav Sedov if (kt)
145*ae771770SStanislav Sedov krb5_kt_close(context, kt);
146*ae771770SStanislav Sedov
147*ae771770SStanislav Sedov if (principal)
148*ae771770SStanislav Sedov krb5_free_principal(context, principal);
149*ae771770SStanislav Sedov return ret;
150*ae771770SStanislav Sedov }
151*ae771770SStanislav Sedov
152*ae771770SStanislav Sedov /*
153*ae771770SStanislav Sedov *
154*ae771770SStanislav Sedov */
155*ae771770SStanislav Sedov
156*ae771770SStanislav Sedov static OM_uint32
kdc_alloc(OM_uint32 * minor,void ** ctx)157*ae771770SStanislav Sedov kdc_alloc(OM_uint32 *minor, void **ctx)
158*ae771770SStanislav Sedov {
159*ae771770SStanislav Sedov krb5_error_code ret;
160*ae771770SStanislav Sedov struct ntlmkrb5 *c;
161*ae771770SStanislav Sedov OM_uint32 junk;
162*ae771770SStanislav Sedov
163*ae771770SStanislav Sedov c = calloc(1, sizeof(*c));
164*ae771770SStanislav Sedov if (c == NULL) {
165*ae771770SStanislav Sedov *minor = ENOMEM;
166*ae771770SStanislav Sedov return GSS_S_FAILURE;
167*ae771770SStanislav Sedov }
168*ae771770SStanislav Sedov
169*ae771770SStanislav Sedov ret = krb5_init_context(&c->context);
170*ae771770SStanislav Sedov if (ret) {
171*ae771770SStanislav Sedov kdc_destroy(&junk, c);
172*ae771770SStanislav Sedov *minor = ret;
173*ae771770SStanislav Sedov return GSS_S_FAILURE;
174*ae771770SStanislav Sedov }
175*ae771770SStanislav Sedov
176*ae771770SStanislav Sedov ret = get_ccache(c->context, &c->destroy, &c->id);
177*ae771770SStanislav Sedov if (ret) {
178*ae771770SStanislav Sedov kdc_destroy(&junk, c);
179*ae771770SStanislav Sedov *minor = ret;
180*ae771770SStanislav Sedov return GSS_S_FAILURE;
181*ae771770SStanislav Sedov }
182*ae771770SStanislav Sedov
183*ae771770SStanislav Sedov ret = krb5_ntlm_alloc(c->context, &c->ntlm);
184*ae771770SStanislav Sedov if (ret) {
185*ae771770SStanislav Sedov kdc_destroy(&junk, c);
186*ae771770SStanislav Sedov *minor = ret;
187*ae771770SStanislav Sedov return GSS_S_FAILURE;
188*ae771770SStanislav Sedov }
189*ae771770SStanislav Sedov
190*ae771770SStanislav Sedov *ctx = c;
191*ae771770SStanislav Sedov
192*ae771770SStanislav Sedov return GSS_S_COMPLETE;
193*ae771770SStanislav Sedov }
194*ae771770SStanislav Sedov
195*ae771770SStanislav Sedov static int
kdc_probe(OM_uint32 * minor,void * ctx,const char * realm)196*ae771770SStanislav Sedov kdc_probe(OM_uint32 *minor, void *ctx, const char *realm)
197*ae771770SStanislav Sedov {
198*ae771770SStanislav Sedov struct ntlmkrb5 *c = ctx;
199*ae771770SStanislav Sedov krb5_error_code ret;
200*ae771770SStanislav Sedov unsigned flags;
201*ae771770SStanislav Sedov
202*ae771770SStanislav Sedov ret = krb5_digest_probe(c->context, rk_UNCONST(realm), c->id, &flags);
203*ae771770SStanislav Sedov if (ret)
204*ae771770SStanislav Sedov return ret;
205*ae771770SStanislav Sedov
206*ae771770SStanislav Sedov if ((flags & (1|2|4)) == 0)
207*ae771770SStanislav Sedov return EINVAL;
208*ae771770SStanislav Sedov
209*ae771770SStanislav Sedov return 0;
210*ae771770SStanislav Sedov }
211*ae771770SStanislav Sedov
212*ae771770SStanislav Sedov /*
213*ae771770SStanislav Sedov *
214*ae771770SStanislav Sedov */
215*ae771770SStanislav Sedov
216*ae771770SStanislav Sedov static OM_uint32
kdc_destroy(OM_uint32 * minor,void * ctx)217*ae771770SStanislav Sedov kdc_destroy(OM_uint32 *minor, void *ctx)
218*ae771770SStanislav Sedov {
219*ae771770SStanislav Sedov struct ntlmkrb5 *c = ctx;
220*ae771770SStanislav Sedov krb5_data_free(&c->opaque);
221*ae771770SStanislav Sedov krb5_data_free(&c->sessionkey);
222*ae771770SStanislav Sedov if (c->ntlm)
223*ae771770SStanislav Sedov krb5_ntlm_free(c->context, c->ntlm);
224*ae771770SStanislav Sedov if (c->id) {
225*ae771770SStanislav Sedov if (c->destroy)
226*ae771770SStanislav Sedov krb5_cc_destroy(c->context, c->id);
227*ae771770SStanislav Sedov else
228*ae771770SStanislav Sedov krb5_cc_close(c->context, c->id);
229*ae771770SStanislav Sedov }
230*ae771770SStanislav Sedov if (c->context)
231*ae771770SStanislav Sedov krb5_free_context(c->context);
232*ae771770SStanislav Sedov memset(c, 0, sizeof(*c));
233*ae771770SStanislav Sedov free(c);
234*ae771770SStanislav Sedov
235*ae771770SStanislav Sedov return GSS_S_COMPLETE;
236*ae771770SStanislav Sedov }
237*ae771770SStanislav Sedov
238*ae771770SStanislav Sedov /*
239*ae771770SStanislav Sedov *
240*ae771770SStanislav Sedov */
241*ae771770SStanislav Sedov
242*ae771770SStanislav Sedov static OM_uint32
kdc_type2(OM_uint32 * minor_status,void * ctx,uint32_t flags,const char * hostname,const char * domain,uint32_t * ret_flags,struct ntlm_buf * out)243*ae771770SStanislav Sedov kdc_type2(OM_uint32 *minor_status,
244*ae771770SStanislav Sedov void *ctx,
245*ae771770SStanislav Sedov uint32_t flags,
246*ae771770SStanislav Sedov const char *hostname,
247*ae771770SStanislav Sedov const char *domain,
248*ae771770SStanislav Sedov uint32_t *ret_flags,
249*ae771770SStanislav Sedov struct ntlm_buf *out)
250*ae771770SStanislav Sedov {
251*ae771770SStanislav Sedov struct ntlmkrb5 *c = ctx;
252*ae771770SStanislav Sedov krb5_error_code ret;
253*ae771770SStanislav Sedov struct ntlm_type2 type2;
254*ae771770SStanislav Sedov krb5_data challange;
255*ae771770SStanislav Sedov struct ntlm_buf data;
256*ae771770SStanislav Sedov krb5_data ti;
257*ae771770SStanislav Sedov
258*ae771770SStanislav Sedov memset(&type2, 0, sizeof(type2));
259*ae771770SStanislav Sedov
260*ae771770SStanislav Sedov /*
261*ae771770SStanislav Sedov * Request data for type 2 packet from the KDC.
262*ae771770SStanislav Sedov */
263*ae771770SStanislav Sedov ret = krb5_ntlm_init_request(c->context,
264*ae771770SStanislav Sedov c->ntlm,
265*ae771770SStanislav Sedov NULL,
266*ae771770SStanislav Sedov c->id,
267*ae771770SStanislav Sedov flags,
268*ae771770SStanislav Sedov hostname,
269*ae771770SStanislav Sedov domain);
270*ae771770SStanislav Sedov if (ret) {
271*ae771770SStanislav Sedov *minor_status = ret;
272*ae771770SStanislav Sedov return GSS_S_FAILURE;
273*ae771770SStanislav Sedov }
274*ae771770SStanislav Sedov
275*ae771770SStanislav Sedov /*
276*ae771770SStanislav Sedov *
277*ae771770SStanislav Sedov */
278*ae771770SStanislav Sedov
279*ae771770SStanislav Sedov ret = krb5_ntlm_init_get_opaque(c->context, c->ntlm, &c->opaque);
280*ae771770SStanislav Sedov if (ret) {
281*ae771770SStanislav Sedov *minor_status = ret;
282*ae771770SStanislav Sedov return GSS_S_FAILURE;
283*ae771770SStanislav Sedov }
284*ae771770SStanislav Sedov
285*ae771770SStanislav Sedov /*
286*ae771770SStanislav Sedov *
287*ae771770SStanislav Sedov */
288*ae771770SStanislav Sedov
289*ae771770SStanislav Sedov ret = krb5_ntlm_init_get_flags(c->context, c->ntlm, &type2.flags);
290*ae771770SStanislav Sedov if (ret) {
291*ae771770SStanislav Sedov *minor_status = ret;
292*ae771770SStanislav Sedov return GSS_S_FAILURE;
293*ae771770SStanislav Sedov }
294*ae771770SStanislav Sedov *ret_flags = type2.flags;
295*ae771770SStanislav Sedov
296*ae771770SStanislav Sedov ret = krb5_ntlm_init_get_challange(c->context, c->ntlm, &challange);
297*ae771770SStanislav Sedov if (ret) {
298*ae771770SStanislav Sedov *minor_status = ret;
299*ae771770SStanislav Sedov return GSS_S_FAILURE;
300*ae771770SStanislav Sedov }
301*ae771770SStanislav Sedov
302*ae771770SStanislav Sedov if (challange.length != sizeof(type2.challenge)) {
303*ae771770SStanislav Sedov *minor_status = EINVAL;
304*ae771770SStanislav Sedov return GSS_S_FAILURE;
305*ae771770SStanislav Sedov }
306*ae771770SStanislav Sedov memcpy(type2.challenge, challange.data, sizeof(type2.challenge));
307*ae771770SStanislav Sedov krb5_data_free(&challange);
308*ae771770SStanislav Sedov
309*ae771770SStanislav Sedov ret = krb5_ntlm_init_get_targetname(c->context, c->ntlm,
310*ae771770SStanislav Sedov &type2.targetname);
311*ae771770SStanislav Sedov if (ret) {
312*ae771770SStanislav Sedov *minor_status = ret;
313*ae771770SStanislav Sedov return GSS_S_FAILURE;
314*ae771770SStanislav Sedov }
315*ae771770SStanislav Sedov
316*ae771770SStanislav Sedov ret = krb5_ntlm_init_get_targetinfo(c->context, c->ntlm, &ti);
317*ae771770SStanislav Sedov if (ret) {
318*ae771770SStanislav Sedov free(type2.targetname);
319*ae771770SStanislav Sedov *minor_status = ret;
320*ae771770SStanislav Sedov return GSS_S_FAILURE;
321*ae771770SStanislav Sedov }
322*ae771770SStanislav Sedov
323*ae771770SStanislav Sedov type2.targetinfo.data = ti.data;
324*ae771770SStanislav Sedov type2.targetinfo.length = ti.length;
325*ae771770SStanislav Sedov
326*ae771770SStanislav Sedov ret = heim_ntlm_encode_type2(&type2, &data);
327*ae771770SStanislav Sedov free(type2.targetname);
328*ae771770SStanislav Sedov krb5_data_free(&ti);
329*ae771770SStanislav Sedov if (ret) {
330*ae771770SStanislav Sedov *minor_status = ret;
331*ae771770SStanislav Sedov return GSS_S_FAILURE;
332*ae771770SStanislav Sedov }
333*ae771770SStanislav Sedov
334*ae771770SStanislav Sedov out->data = data.data;
335*ae771770SStanislav Sedov out->length = data.length;
336*ae771770SStanislav Sedov
337*ae771770SStanislav Sedov return GSS_S_COMPLETE;
338*ae771770SStanislav Sedov }
339*ae771770SStanislav Sedov
340*ae771770SStanislav Sedov /*
341*ae771770SStanislav Sedov *
342*ae771770SStanislav Sedov */
343*ae771770SStanislav Sedov
344*ae771770SStanislav Sedov static OM_uint32
kdc_type3(OM_uint32 * minor_status,void * ctx,const struct ntlm_type3 * type3,struct ntlm_buf * sessionkey)345*ae771770SStanislav Sedov kdc_type3(OM_uint32 *minor_status,
346*ae771770SStanislav Sedov void *ctx,
347*ae771770SStanislav Sedov const struct ntlm_type3 *type3,
348*ae771770SStanislav Sedov struct ntlm_buf *sessionkey)
349*ae771770SStanislav Sedov {
350*ae771770SStanislav Sedov struct ntlmkrb5 *c = ctx;
351*ae771770SStanislav Sedov krb5_error_code ret;
352*ae771770SStanislav Sedov
353*ae771770SStanislav Sedov sessionkey->data = NULL;
354*ae771770SStanislav Sedov sessionkey->length = 0;
355*ae771770SStanislav Sedov
356*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_flags(c->context, c->ntlm, type3->flags);
357*ae771770SStanislav Sedov if (ret) goto out;
358*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_username(c->context, c->ntlm, type3->username);
359*ae771770SStanislav Sedov if (ret) goto out;
360*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_targetname(c->context, c->ntlm,
361*ae771770SStanislav Sedov type3->targetname);
362*ae771770SStanislav Sedov if (ret) goto out;
363*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_lm(c->context, c->ntlm,
364*ae771770SStanislav Sedov type3->lm.data, type3->lm.length);
365*ae771770SStanislav Sedov if (ret) goto out;
366*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_ntlm(c->context, c->ntlm,
367*ae771770SStanislav Sedov type3->ntlm.data, type3->ntlm.length);
368*ae771770SStanislav Sedov if (ret) goto out;
369*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_opaque(c->context, c->ntlm, &c->opaque);
370*ae771770SStanislav Sedov if (ret) goto out;
371*ae771770SStanislav Sedov
372*ae771770SStanislav Sedov if (type3->sessionkey.length) {
373*ae771770SStanislav Sedov ret = krb5_ntlm_req_set_session(c->context, c->ntlm,
374*ae771770SStanislav Sedov type3->sessionkey.data,
375*ae771770SStanislav Sedov type3->sessionkey.length);
376*ae771770SStanislav Sedov if (ret) goto out;
377*ae771770SStanislav Sedov }
378*ae771770SStanislav Sedov
379*ae771770SStanislav Sedov /*
380*ae771770SStanislav Sedov * Verify with the KDC the type3 packet is ok
381*ae771770SStanislav Sedov */
382*ae771770SStanislav Sedov ret = krb5_ntlm_request(c->context,
383*ae771770SStanislav Sedov c->ntlm,
384*ae771770SStanislav Sedov NULL,
385*ae771770SStanislav Sedov c->id);
386*ae771770SStanislav Sedov if (ret)
387*ae771770SStanislav Sedov goto out;
388*ae771770SStanislav Sedov
389*ae771770SStanislav Sedov if (krb5_ntlm_rep_get_status(c->context, c->ntlm) != TRUE) {
390*ae771770SStanislav Sedov ret = EINVAL;
391*ae771770SStanislav Sedov goto out;
392*ae771770SStanislav Sedov }
393*ae771770SStanislav Sedov
394*ae771770SStanislav Sedov if (type3->sessionkey.length) {
395*ae771770SStanislav Sedov ret = krb5_ntlm_rep_get_sessionkey(c->context,
396*ae771770SStanislav Sedov c->ntlm,
397*ae771770SStanislav Sedov &c->sessionkey);
398*ae771770SStanislav Sedov if (ret)
399*ae771770SStanislav Sedov goto out;
400*ae771770SStanislav Sedov
401*ae771770SStanislav Sedov sessionkey->data = c->sessionkey.data;
402*ae771770SStanislav Sedov sessionkey->length = c->sessionkey.length;
403*ae771770SStanislav Sedov }
404*ae771770SStanislav Sedov
405*ae771770SStanislav Sedov return 0;
406*ae771770SStanislav Sedov
407*ae771770SStanislav Sedov out:
408*ae771770SStanislav Sedov *minor_status = ret;
409*ae771770SStanislav Sedov return GSS_S_FAILURE;
410*ae771770SStanislav Sedov }
411*ae771770SStanislav Sedov
412*ae771770SStanislav Sedov /*
413*ae771770SStanislav Sedov *
414*ae771770SStanislav Sedov */
415*ae771770SStanislav Sedov
416*ae771770SStanislav Sedov static void
kdc_free_buffer(struct ntlm_buf * sessionkey)417*ae771770SStanislav Sedov kdc_free_buffer(struct ntlm_buf *sessionkey)
418*ae771770SStanislav Sedov {
419*ae771770SStanislav Sedov if (sessionkey->data)
420*ae771770SStanislav Sedov free(sessionkey->data);
421*ae771770SStanislav Sedov sessionkey->data = NULL;
422*ae771770SStanislav Sedov sessionkey->length = 0;
423*ae771770SStanislav Sedov }
424*ae771770SStanislav Sedov
425*ae771770SStanislav Sedov /*
426*ae771770SStanislav Sedov *
427*ae771770SStanislav Sedov */
428*ae771770SStanislav Sedov
429*ae771770SStanislav Sedov struct ntlm_server_interface ntlmsspi_kdc_digest = {
430*ae771770SStanislav Sedov kdc_alloc,
431*ae771770SStanislav Sedov kdc_destroy,
432*ae771770SStanislav Sedov kdc_probe,
433*ae771770SStanislav Sedov kdc_type2,
434*ae771770SStanislav Sedov kdc_type3,
435*ae771770SStanislav Sedov kdc_free_buffer
436*ae771770SStanislav Sedov };
437*ae771770SStanislav Sedov
438*ae771770SStanislav Sedov #endif /* DIGEST */
439