context_stubs.c revision 178825
1178825Sdfr/*
2178825Sdfr * Copyright (c) 2004, PADL Software Pty Ltd.
3178825Sdfr * All rights reserved.
4178825Sdfr *
5178825Sdfr * Redistribution and use in source and binary forms, with or without
6178825Sdfr * modification, are permitted provided that the following conditions
7178825Sdfr * are met:
8178825Sdfr *
9178825Sdfr * 1. Redistributions of source code must retain the above copyright
10178825Sdfr *    notice, this list of conditions and the following disclaimer.
11178825Sdfr *
12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
13178825Sdfr *    notice, this list of conditions and the following disclaimer in the
14178825Sdfr *    documentation and/or other materials provided with the distribution.
15178825Sdfr *
16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors
17178825Sdfr *    may be used to endorse or promote products derived from this software
18178825Sdfr *    without specific prior written permission.
19178825Sdfr *
20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30178825Sdfr * SUCH DAMAGE.
31178825Sdfr */
32178825Sdfr
33178825Sdfr#include "spnego/spnego_locl.h"
34178825Sdfr
35178825SdfrRCSID("$Id: context_stubs.c 21035 2007-06-09 15:32:47Z lha $");
36178825Sdfr
37178825Sdfrstatic OM_uint32
38178825Sdfrspnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
39178825Sdfr{
40178825Sdfr    OM_uint32 ret, junk;
41178825Sdfr    gss_OID_set m;
42178825Sdfr    int i;
43178825Sdfr
44178825Sdfr    ret = gss_indicate_mechs(minor_status, &m);
45178825Sdfr    if (ret != GSS_S_COMPLETE)
46178825Sdfr	return ret;
47178825Sdfr
48178825Sdfr    ret = gss_create_empty_oid_set(minor_status, mechs);
49178825Sdfr    if (ret != GSS_S_COMPLETE) {
50178825Sdfr	gss_release_oid_set(&junk, &m);
51178825Sdfr	return ret;
52178825Sdfr    }
53178825Sdfr
54178825Sdfr    for (i = 0; i < m->count; i++) {
55178825Sdfr	if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM))
56178825Sdfr	    continue;
57178825Sdfr
58178825Sdfr	ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs);
59178825Sdfr	if (ret) {
60178825Sdfr	    gss_release_oid_set(&junk, &m);
61178825Sdfr	    gss_release_oid_set(&junk, mechs);
62178825Sdfr	    return ret;
63178825Sdfr	}
64178825Sdfr    }
65178825Sdfr    return ret;
66178825Sdfr}
67178825Sdfr
68178825Sdfr
69178825Sdfr
70178825SdfrOM_uint32 _gss_spnego_process_context_token
71178825Sdfr           (OM_uint32 *minor_status,
72178825Sdfr            const gss_ctx_id_t context_handle,
73178825Sdfr            const gss_buffer_t token_buffer
74178825Sdfr           )
75178825Sdfr{
76178825Sdfr    gss_ctx_id_t context ;
77178825Sdfr    gssspnego_ctx ctx;
78178825Sdfr    OM_uint32 ret;
79178825Sdfr
80178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT)
81178825Sdfr	return GSS_S_NO_CONTEXT;
82178825Sdfr
83178825Sdfr    context = context_handle;
84178825Sdfr    ctx = (gssspnego_ctx)context_handle;
85178825Sdfr
86178825Sdfr    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
87178825Sdfr
88178825Sdfr    ret = gss_process_context_token(minor_status,
89178825Sdfr				    ctx->negotiated_ctx_id,
90178825Sdfr				    token_buffer);
91178825Sdfr    if (ret != GSS_S_COMPLETE) {
92178825Sdfr	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
93178825Sdfr	return ret;
94178825Sdfr    }
95178825Sdfr
96178825Sdfr    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
97178825Sdfr
98178825Sdfr    return _gss_spnego_internal_delete_sec_context(minor_status,
99178825Sdfr					   &context,
100178825Sdfr					   GSS_C_NO_BUFFER);
101178825Sdfr}
102178825Sdfr
103178825SdfrOM_uint32 _gss_spnego_delete_sec_context
104178825Sdfr           (OM_uint32 *minor_status,
105178825Sdfr            gss_ctx_id_t *context_handle,
106178825Sdfr            gss_buffer_t output_token
107178825Sdfr           )
108178825Sdfr{
109178825Sdfr    gssspnego_ctx ctx;
110178825Sdfr
111178825Sdfr    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
112178825Sdfr	return GSS_S_NO_CONTEXT;
113178825Sdfr
114178825Sdfr    ctx = (gssspnego_ctx)*context_handle;
115178825Sdfr
116178825Sdfr    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
117178825Sdfr
118178825Sdfr    return _gss_spnego_internal_delete_sec_context(minor_status,
119178825Sdfr						   context_handle,
120178825Sdfr						   output_token);
121178825Sdfr}
122178825Sdfr
123178825SdfrOM_uint32 _gss_spnego_context_time
124178825Sdfr           (OM_uint32 *minor_status,
125178825Sdfr            const gss_ctx_id_t context_handle,
126178825Sdfr            OM_uint32 *time_rec
127178825Sdfr           )
128178825Sdfr{
129178825Sdfr    gssspnego_ctx ctx;
130178825Sdfr    *minor_status = 0;
131178825Sdfr
132178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
133178825Sdfr	return GSS_S_NO_CONTEXT;
134178825Sdfr    }
135178825Sdfr
136178825Sdfr    ctx = (gssspnego_ctx)context_handle;
137178825Sdfr
138178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
139178825Sdfr	return GSS_S_NO_CONTEXT;
140178825Sdfr    }
141178825Sdfr
142178825Sdfr    return gss_context_time(minor_status,
143178825Sdfr			    ctx->negotiated_ctx_id,
144178825Sdfr			    time_rec);
145178825Sdfr}
146178825Sdfr
147178825SdfrOM_uint32 _gss_spnego_get_mic
148178825Sdfr           (OM_uint32 *minor_status,
149178825Sdfr            const gss_ctx_id_t context_handle,
150178825Sdfr            gss_qop_t qop_req,
151178825Sdfr            const gss_buffer_t message_buffer,
152178825Sdfr            gss_buffer_t message_token
153178825Sdfr           )
154178825Sdfr{
155178825Sdfr    gssspnego_ctx ctx;
156178825Sdfr
157178825Sdfr    *minor_status = 0;
158178825Sdfr
159178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
160178825Sdfr	return GSS_S_NO_CONTEXT;
161178825Sdfr    }
162178825Sdfr
163178825Sdfr    ctx = (gssspnego_ctx)context_handle;
164178825Sdfr
165178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
166178825Sdfr	return GSS_S_NO_CONTEXT;
167178825Sdfr    }
168178825Sdfr
169178825Sdfr    return gss_get_mic(minor_status, ctx->negotiated_ctx_id,
170178825Sdfr		       qop_req, message_buffer, message_token);
171178825Sdfr}
172178825Sdfr
173178825SdfrOM_uint32 _gss_spnego_verify_mic
174178825Sdfr           (OM_uint32 * minor_status,
175178825Sdfr            const gss_ctx_id_t context_handle,
176178825Sdfr            const gss_buffer_t message_buffer,
177178825Sdfr            const gss_buffer_t token_buffer,
178178825Sdfr            gss_qop_t * qop_state
179178825Sdfr           )
180178825Sdfr{
181178825Sdfr    gssspnego_ctx ctx;
182178825Sdfr
183178825Sdfr    *minor_status = 0;
184178825Sdfr
185178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
186178825Sdfr	return GSS_S_NO_CONTEXT;
187178825Sdfr    }
188178825Sdfr
189178825Sdfr    ctx = (gssspnego_ctx)context_handle;
190178825Sdfr
191178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
192178825Sdfr	return GSS_S_NO_CONTEXT;
193178825Sdfr    }
194178825Sdfr
195178825Sdfr    return gss_verify_mic(minor_status,
196178825Sdfr			  ctx->negotiated_ctx_id,
197178825Sdfr			  message_buffer,
198178825Sdfr			  token_buffer,
199178825Sdfr			  qop_state);
200178825Sdfr}
201178825Sdfr
202178825SdfrOM_uint32 _gss_spnego_wrap
203178825Sdfr           (OM_uint32 * minor_status,
204178825Sdfr            const gss_ctx_id_t context_handle,
205178825Sdfr            int conf_req_flag,
206178825Sdfr            gss_qop_t qop_req,
207178825Sdfr            const gss_buffer_t input_message_buffer,
208178825Sdfr            int * conf_state,
209178825Sdfr            gss_buffer_t output_message_buffer
210178825Sdfr           )
211178825Sdfr{
212178825Sdfr    gssspnego_ctx ctx;
213178825Sdfr
214178825Sdfr    *minor_status = 0;
215178825Sdfr
216178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
217178825Sdfr	return GSS_S_NO_CONTEXT;
218178825Sdfr    }
219178825Sdfr
220178825Sdfr    ctx = (gssspnego_ctx)context_handle;
221178825Sdfr
222178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
223178825Sdfr	return GSS_S_NO_CONTEXT;
224178825Sdfr    }
225178825Sdfr
226178825Sdfr    return gss_wrap(minor_status,
227178825Sdfr		    ctx->negotiated_ctx_id,
228178825Sdfr		    conf_req_flag,
229178825Sdfr		    qop_req,
230178825Sdfr		    input_message_buffer,
231178825Sdfr		    conf_state,
232178825Sdfr		    output_message_buffer);
233178825Sdfr}
234178825Sdfr
235178825SdfrOM_uint32 _gss_spnego_unwrap
236178825Sdfr           (OM_uint32 * minor_status,
237178825Sdfr            const gss_ctx_id_t context_handle,
238178825Sdfr            const gss_buffer_t input_message_buffer,
239178825Sdfr            gss_buffer_t output_message_buffer,
240178825Sdfr            int * conf_state,
241178825Sdfr            gss_qop_t * qop_state
242178825Sdfr           )
243178825Sdfr{
244178825Sdfr    gssspnego_ctx ctx;
245178825Sdfr
246178825Sdfr    *minor_status = 0;
247178825Sdfr
248178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
249178825Sdfr	return GSS_S_NO_CONTEXT;
250178825Sdfr    }
251178825Sdfr
252178825Sdfr    ctx = (gssspnego_ctx)context_handle;
253178825Sdfr
254178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
255178825Sdfr	return GSS_S_NO_CONTEXT;
256178825Sdfr    }
257178825Sdfr
258178825Sdfr    return gss_unwrap(minor_status,
259178825Sdfr		      ctx->negotiated_ctx_id,
260178825Sdfr		      input_message_buffer,
261178825Sdfr		      output_message_buffer,
262178825Sdfr		      conf_state,
263178825Sdfr		      qop_state);
264178825Sdfr}
265178825Sdfr
266178825SdfrOM_uint32 _gss_spnego_display_status
267178825Sdfr           (OM_uint32 * minor_status,
268178825Sdfr            OM_uint32 status_value,
269178825Sdfr            int status_type,
270178825Sdfr            const gss_OID mech_type,
271178825Sdfr            OM_uint32 * message_context,
272178825Sdfr            gss_buffer_t status_string
273178825Sdfr           )
274178825Sdfr{
275178825Sdfr    return GSS_S_FAILURE;
276178825Sdfr}
277178825Sdfr
278178825SdfrOM_uint32 _gss_spnego_compare_name
279178825Sdfr           (OM_uint32 *minor_status,
280178825Sdfr            const gss_name_t name1,
281178825Sdfr            const gss_name_t name2,
282178825Sdfr            int * name_equal
283178825Sdfr           )
284178825Sdfr{
285178825Sdfr    spnego_name n1 = (spnego_name)name1;
286178825Sdfr    spnego_name n2 = (spnego_name)name2;
287178825Sdfr
288178825Sdfr    *name_equal = 0;
289178825Sdfr
290178825Sdfr    if (!gss_oid_equal(&n1->type, &n2->type))
291178825Sdfr	return GSS_S_COMPLETE;
292178825Sdfr    if (n1->value.length != n2->value.length)
293178825Sdfr	return GSS_S_COMPLETE;
294178825Sdfr    if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0)
295178825Sdfr	return GSS_S_COMPLETE;
296178825Sdfr
297178825Sdfr    *name_equal = 1;
298178825Sdfr
299178825Sdfr    return GSS_S_COMPLETE;
300178825Sdfr}
301178825Sdfr
302178825SdfrOM_uint32 _gss_spnego_display_name
303178825Sdfr           (OM_uint32 * minor_status,
304178825Sdfr            const gss_name_t input_name,
305178825Sdfr            gss_buffer_t output_name_buffer,
306178825Sdfr            gss_OID * output_name_type
307178825Sdfr           )
308178825Sdfr{
309178825Sdfr    spnego_name name = (spnego_name)input_name;
310178825Sdfr
311178825Sdfr    *minor_status = 0;
312178825Sdfr
313178825Sdfr    if (name == NULL || name->mech == GSS_C_NO_NAME)
314178825Sdfr	return GSS_S_FAILURE;
315178825Sdfr
316178825Sdfr    return gss_display_name(minor_status, name->mech,
317178825Sdfr			    output_name_buffer, output_name_type);
318178825Sdfr}
319178825Sdfr
320178825SdfrOM_uint32 _gss_spnego_import_name
321178825Sdfr           (OM_uint32 * minor_status,
322178825Sdfr            const gss_buffer_t name_buffer,
323178825Sdfr            const gss_OID name_type,
324178825Sdfr            gss_name_t * output_name
325178825Sdfr           )
326178825Sdfr{
327178825Sdfr    spnego_name name;
328178825Sdfr    OM_uint32 maj_stat;
329178825Sdfr
330178825Sdfr    *minor_status = 0;
331178825Sdfr
332178825Sdfr    name = calloc(1, sizeof(*name));
333178825Sdfr    if (name == NULL) {
334178825Sdfr	*minor_status = ENOMEM;
335178825Sdfr	return GSS_S_FAILURE;
336178825Sdfr    }
337178825Sdfr
338178825Sdfr    maj_stat = _gss_copy_oid(minor_status, name_type, &name->type);
339178825Sdfr    if (maj_stat) {
340178825Sdfr	free(name);
341178825Sdfr	return GSS_S_FAILURE;
342178825Sdfr    }
343178825Sdfr
344178825Sdfr    maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value);
345178825Sdfr    if (maj_stat) {
346178825Sdfr	gss_name_t rname = (gss_name_t)name;
347178825Sdfr	_gss_spnego_release_name(minor_status, &rname);
348178825Sdfr	return GSS_S_FAILURE;
349178825Sdfr    }
350178825Sdfr    name->mech = GSS_C_NO_NAME;
351178825Sdfr    *output_name = (gss_name_t)name;
352178825Sdfr
353178825Sdfr    return GSS_S_COMPLETE;
354178825Sdfr}
355178825Sdfr
356178825SdfrOM_uint32 _gss_spnego_export_name
357178825Sdfr           (OM_uint32  * minor_status,
358178825Sdfr            const gss_name_t input_name,
359178825Sdfr            gss_buffer_t exported_name
360178825Sdfr           )
361178825Sdfr{
362178825Sdfr    spnego_name name;
363178825Sdfr    *minor_status = 0;
364178825Sdfr
365178825Sdfr    if (input_name == GSS_C_NO_NAME)
366178825Sdfr	return GSS_S_BAD_NAME;
367178825Sdfr
368178825Sdfr    name = (spnego_name)input_name;
369178825Sdfr    if (name->mech == GSS_C_NO_NAME)
370178825Sdfr	return GSS_S_BAD_NAME;
371178825Sdfr
372178825Sdfr    return gss_export_name(minor_status, name->mech, exported_name);
373178825Sdfr}
374178825Sdfr
375178825SdfrOM_uint32 _gss_spnego_release_name
376178825Sdfr           (OM_uint32 * minor_status,
377178825Sdfr            gss_name_t * input_name
378178825Sdfr           )
379178825Sdfr{
380178825Sdfr    *minor_status = 0;
381178825Sdfr
382178825Sdfr    if (*input_name != GSS_C_NO_NAME) {
383178825Sdfr	OM_uint32 junk;
384178825Sdfr	spnego_name name = (spnego_name)*input_name;
385178825Sdfr	_gss_free_oid(&junk, &name->type);
386178825Sdfr	gss_release_buffer(&junk, &name->value);
387178825Sdfr	if (name->mech != GSS_C_NO_NAME)
388178825Sdfr	    gss_release_name(&junk, &name->mech);
389178825Sdfr	free(name);
390178825Sdfr
391178825Sdfr	*input_name = GSS_C_NO_NAME;
392178825Sdfr    }
393178825Sdfr    return GSS_S_COMPLETE;
394178825Sdfr}
395178825Sdfr
396178825SdfrOM_uint32 _gss_spnego_inquire_context (
397178825Sdfr            OM_uint32 * minor_status,
398178825Sdfr            const gss_ctx_id_t context_handle,
399178825Sdfr            gss_name_t * src_name,
400178825Sdfr            gss_name_t * targ_name,
401178825Sdfr            OM_uint32 * lifetime_rec,
402178825Sdfr            gss_OID * mech_type,
403178825Sdfr            OM_uint32 * ctx_flags,
404178825Sdfr            int * locally_initiated,
405178825Sdfr            int * open_context
406178825Sdfr           )
407178825Sdfr{
408178825Sdfr    gssspnego_ctx ctx;
409178825Sdfr
410178825Sdfr    *minor_status = 0;
411178825Sdfr
412178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
413178825Sdfr	return GSS_S_NO_CONTEXT;
414178825Sdfr    }
415178825Sdfr
416178825Sdfr    ctx = (gssspnego_ctx)context_handle;
417178825Sdfr
418178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
419178825Sdfr	return GSS_S_NO_CONTEXT;
420178825Sdfr    }
421178825Sdfr
422178825Sdfr    return gss_inquire_context(minor_status,
423178825Sdfr			       ctx->negotiated_ctx_id,
424178825Sdfr			       src_name,
425178825Sdfr			       targ_name,
426178825Sdfr			       lifetime_rec,
427178825Sdfr			       mech_type,
428178825Sdfr			       ctx_flags,
429178825Sdfr			       locally_initiated,
430178825Sdfr			       open_context);
431178825Sdfr}
432178825Sdfr
433178825SdfrOM_uint32 _gss_spnego_wrap_size_limit (
434178825Sdfr            OM_uint32 * minor_status,
435178825Sdfr            const gss_ctx_id_t context_handle,
436178825Sdfr            int conf_req_flag,
437178825Sdfr            gss_qop_t qop_req,
438178825Sdfr            OM_uint32 req_output_size,
439178825Sdfr            OM_uint32 * max_input_size
440178825Sdfr           )
441178825Sdfr{
442178825Sdfr    gssspnego_ctx ctx;
443178825Sdfr
444178825Sdfr    *minor_status = 0;
445178825Sdfr
446178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
447178825Sdfr	return GSS_S_NO_CONTEXT;
448178825Sdfr    }
449178825Sdfr
450178825Sdfr    ctx = (gssspnego_ctx)context_handle;
451178825Sdfr
452178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
453178825Sdfr	return GSS_S_NO_CONTEXT;
454178825Sdfr    }
455178825Sdfr
456178825Sdfr    return gss_wrap_size_limit(minor_status,
457178825Sdfr			       ctx->negotiated_ctx_id,
458178825Sdfr			       conf_req_flag,
459178825Sdfr			       qop_req,
460178825Sdfr			       req_output_size,
461178825Sdfr			       max_input_size);
462178825Sdfr}
463178825Sdfr
464178825SdfrOM_uint32 _gss_spnego_export_sec_context (
465178825Sdfr            OM_uint32 * minor_status,
466178825Sdfr            gss_ctx_id_t * context_handle,
467178825Sdfr            gss_buffer_t interprocess_token
468178825Sdfr           )
469178825Sdfr{
470178825Sdfr    gssspnego_ctx ctx;
471178825Sdfr    OM_uint32 ret;
472178825Sdfr
473178825Sdfr    *minor_status = 0;
474178825Sdfr
475178825Sdfr    if (context_handle == NULL) {
476178825Sdfr	return GSS_S_NO_CONTEXT;
477178825Sdfr    }
478178825Sdfr
479178825Sdfr    ctx = (gssspnego_ctx)*context_handle;
480178825Sdfr
481178825Sdfr    if (ctx == NULL)
482178825Sdfr	return GSS_S_NO_CONTEXT;
483178825Sdfr
484178825Sdfr    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
485178825Sdfr
486178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
487178825Sdfr	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
488178825Sdfr	return GSS_S_NO_CONTEXT;
489178825Sdfr    }
490178825Sdfr
491178825Sdfr    ret = gss_export_sec_context(minor_status,
492178825Sdfr				 &ctx->negotiated_ctx_id,
493178825Sdfr				 interprocess_token);
494178825Sdfr    if (ret == GSS_S_COMPLETE) {
495178825Sdfr	ret = _gss_spnego_internal_delete_sec_context(minor_status,
496178825Sdfr					     context_handle,
497178825Sdfr					     GSS_C_NO_BUFFER);
498178825Sdfr	if (ret == GSS_S_COMPLETE)
499178825Sdfr	    return GSS_S_COMPLETE;
500178825Sdfr    }
501178825Sdfr
502178825Sdfr    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
503178825Sdfr
504178825Sdfr    return ret;
505178825Sdfr}
506178825Sdfr
507178825SdfrOM_uint32 _gss_spnego_import_sec_context (
508178825Sdfr            OM_uint32 * minor_status,
509178825Sdfr            const gss_buffer_t interprocess_token,
510178825Sdfr            gss_ctx_id_t *context_handle
511178825Sdfr           )
512178825Sdfr{
513178825Sdfr    OM_uint32 ret, minor;
514178825Sdfr    gss_ctx_id_t context;
515178825Sdfr    gssspnego_ctx ctx;
516178825Sdfr
517178825Sdfr    ret = _gss_spnego_alloc_sec_context(minor_status, &context);
518178825Sdfr    if (ret != GSS_S_COMPLETE) {
519178825Sdfr	return ret;
520178825Sdfr    }
521178825Sdfr    ctx = (gssspnego_ctx)context;
522178825Sdfr
523178825Sdfr    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
524178825Sdfr
525178825Sdfr    ret = gss_import_sec_context(minor_status,
526178825Sdfr				 interprocess_token,
527178825Sdfr				 &ctx->negotiated_ctx_id);
528178825Sdfr    if (ret != GSS_S_COMPLETE) {
529178825Sdfr	_gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER);
530178825Sdfr	return ret;
531178825Sdfr    }
532178825Sdfr
533178825Sdfr    ctx->open = 1;
534178825Sdfr    /* don't bother filling in the rest of the fields */
535178825Sdfr
536178825Sdfr    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
537178825Sdfr
538178825Sdfr    *context_handle = (gss_ctx_id_t)ctx;
539178825Sdfr
540178825Sdfr    return GSS_S_COMPLETE;
541178825Sdfr}
542178825Sdfr
543178825SdfrOM_uint32 _gss_spnego_inquire_names_for_mech (
544178825Sdfr            OM_uint32 * minor_status,
545178825Sdfr            const gss_OID mechanism,
546178825Sdfr            gss_OID_set * name_types
547178825Sdfr           )
548178825Sdfr{
549178825Sdfr    gss_OID_set mechs, names, n;
550178825Sdfr    OM_uint32 ret, junk;
551178825Sdfr    int i, j;
552178825Sdfr
553178825Sdfr    *name_types = NULL;
554178825Sdfr
555178825Sdfr    ret = spnego_supported_mechs(minor_status, &mechs);
556178825Sdfr    if (ret != GSS_S_COMPLETE)
557178825Sdfr	return ret;
558178825Sdfr
559178825Sdfr    ret = gss_create_empty_oid_set(minor_status, &names);
560178825Sdfr    if (ret != GSS_S_COMPLETE)
561178825Sdfr	goto out;
562178825Sdfr
563178825Sdfr    for (i = 0; i < mechs->count; i++) {
564178825Sdfr	ret = gss_inquire_names_for_mech(minor_status,
565178825Sdfr					 &mechs->elements[i],
566178825Sdfr					 &n);
567178825Sdfr	if (ret)
568178825Sdfr	    continue;
569178825Sdfr
570178825Sdfr	for (j = 0; j < n->count; j++)
571178825Sdfr	    gss_add_oid_set_member(minor_status,
572178825Sdfr				   &n->elements[j],
573178825Sdfr				   &names);
574178825Sdfr	gss_release_oid_set(&junk, &n);
575178825Sdfr    }
576178825Sdfr
577178825Sdfr    ret = GSS_S_COMPLETE;
578178825Sdfr    *name_types = names;
579178825Sdfrout:
580178825Sdfr
581178825Sdfr    gss_release_oid_set(&junk, &mechs);
582178825Sdfr
583178825Sdfr    return GSS_S_COMPLETE;
584178825Sdfr}
585178825Sdfr
586178825SdfrOM_uint32 _gss_spnego_inquire_mechs_for_name (
587178825Sdfr            OM_uint32 * minor_status,
588178825Sdfr            const gss_name_t input_name,
589178825Sdfr            gss_OID_set * mech_types
590178825Sdfr           )
591178825Sdfr{
592178825Sdfr    OM_uint32 ret, junk;
593178825Sdfr
594178825Sdfr    ret = gss_create_empty_oid_set(minor_status, mech_types);
595178825Sdfr    if (ret)
596178825Sdfr	return ret;
597178825Sdfr
598178825Sdfr    ret = gss_add_oid_set_member(minor_status,
599178825Sdfr				 GSS_SPNEGO_MECHANISM,
600178825Sdfr				 mech_types);
601178825Sdfr    if (ret)
602178825Sdfr	gss_release_oid_set(&junk, mech_types);
603178825Sdfr
604178825Sdfr    return ret;
605178825Sdfr}
606178825Sdfr
607178825SdfrOM_uint32 _gss_spnego_canonicalize_name (
608178825Sdfr            OM_uint32 * minor_status,
609178825Sdfr            const gss_name_t input_name,
610178825Sdfr            const gss_OID mech_type,
611178825Sdfr            gss_name_t * output_name
612178825Sdfr           )
613178825Sdfr{
614178825Sdfr    /* XXX */
615178825Sdfr    return gss_duplicate_name(minor_status, input_name, output_name);
616178825Sdfr}
617178825Sdfr
618178825SdfrOM_uint32 _gss_spnego_duplicate_name (
619178825Sdfr            OM_uint32 * minor_status,
620178825Sdfr            const gss_name_t src_name,
621178825Sdfr            gss_name_t * dest_name
622178825Sdfr           )
623178825Sdfr{
624178825Sdfr    return gss_duplicate_name(minor_status, src_name, dest_name);
625178825Sdfr}
626178825Sdfr
627178825SdfrOM_uint32 _gss_spnego_sign
628178825Sdfr           (OM_uint32 * minor_status,
629178825Sdfr            gss_ctx_id_t context_handle,
630178825Sdfr            int qop_req,
631178825Sdfr            gss_buffer_t message_buffer,
632178825Sdfr            gss_buffer_t message_token
633178825Sdfr           )
634178825Sdfr{
635178825Sdfr    gssspnego_ctx ctx;
636178825Sdfr
637178825Sdfr    *minor_status = 0;
638178825Sdfr
639178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
640178825Sdfr	return GSS_S_NO_CONTEXT;
641178825Sdfr    }
642178825Sdfr
643178825Sdfr    ctx = (gssspnego_ctx)context_handle;
644178825Sdfr
645178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
646178825Sdfr	return GSS_S_NO_CONTEXT;
647178825Sdfr    }
648178825Sdfr
649178825Sdfr    return gss_sign(minor_status,
650178825Sdfr		    ctx->negotiated_ctx_id,
651178825Sdfr		    qop_req,
652178825Sdfr		    message_buffer,
653178825Sdfr		    message_token);
654178825Sdfr}
655178825Sdfr
656178825SdfrOM_uint32 _gss_spnego_verify
657178825Sdfr           (OM_uint32 * minor_status,
658178825Sdfr            gss_ctx_id_t context_handle,
659178825Sdfr            gss_buffer_t message_buffer,
660178825Sdfr            gss_buffer_t token_buffer,
661178825Sdfr            int * qop_state
662178825Sdfr           )
663178825Sdfr{
664178825Sdfr    gssspnego_ctx ctx;
665178825Sdfr
666178825Sdfr    *minor_status = 0;
667178825Sdfr
668178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
669178825Sdfr	return GSS_S_NO_CONTEXT;
670178825Sdfr    }
671178825Sdfr
672178825Sdfr    ctx = (gssspnego_ctx)context_handle;
673178825Sdfr
674178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
675178825Sdfr	return GSS_S_NO_CONTEXT;
676178825Sdfr    }
677178825Sdfr
678178825Sdfr    return gss_verify(minor_status,
679178825Sdfr		      ctx->negotiated_ctx_id,
680178825Sdfr		      message_buffer,
681178825Sdfr		      token_buffer,
682178825Sdfr		      qop_state);
683178825Sdfr}
684178825Sdfr
685178825SdfrOM_uint32 _gss_spnego_seal
686178825Sdfr           (OM_uint32 * minor_status,
687178825Sdfr            gss_ctx_id_t context_handle,
688178825Sdfr            int conf_req_flag,
689178825Sdfr            int qop_req,
690178825Sdfr            gss_buffer_t input_message_buffer,
691178825Sdfr            int * conf_state,
692178825Sdfr            gss_buffer_t output_message_buffer
693178825Sdfr           )
694178825Sdfr{
695178825Sdfr    gssspnego_ctx ctx;
696178825Sdfr
697178825Sdfr    *minor_status = 0;
698178825Sdfr
699178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
700178825Sdfr	return GSS_S_NO_CONTEXT;
701178825Sdfr    }
702178825Sdfr
703178825Sdfr    ctx = (gssspnego_ctx)context_handle;
704178825Sdfr
705178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
706178825Sdfr	return GSS_S_NO_CONTEXT;
707178825Sdfr    }
708178825Sdfr
709178825Sdfr    return gss_seal(minor_status,
710178825Sdfr		    ctx->negotiated_ctx_id,
711178825Sdfr		    conf_req_flag,
712178825Sdfr		    qop_req,
713178825Sdfr		    input_message_buffer,
714178825Sdfr		    conf_state,
715178825Sdfr		    output_message_buffer);
716178825Sdfr}
717178825Sdfr
718178825SdfrOM_uint32 _gss_spnego_unseal
719178825Sdfr           (OM_uint32 * minor_status,
720178825Sdfr            gss_ctx_id_t context_handle,
721178825Sdfr            gss_buffer_t input_message_buffer,
722178825Sdfr            gss_buffer_t output_message_buffer,
723178825Sdfr            int * conf_state,
724178825Sdfr            int * qop_state
725178825Sdfr           )
726178825Sdfr{
727178825Sdfr    gssspnego_ctx ctx;
728178825Sdfr
729178825Sdfr    *minor_status = 0;
730178825Sdfr
731178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
732178825Sdfr	return GSS_S_NO_CONTEXT;
733178825Sdfr    }
734178825Sdfr
735178825Sdfr    ctx = (gssspnego_ctx)context_handle;
736178825Sdfr
737178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
738178825Sdfr	return GSS_S_NO_CONTEXT;
739178825Sdfr    }
740178825Sdfr
741178825Sdfr    return gss_unseal(minor_status,
742178825Sdfr		      ctx->negotiated_ctx_id,
743178825Sdfr		      input_message_buffer,
744178825Sdfr		      output_message_buffer,
745178825Sdfr		      conf_state,
746178825Sdfr		      qop_state);
747178825Sdfr}
748178825Sdfr
749178825Sdfr#if 0
750178825SdfrOM_uint32 _gss_spnego_unwrap_ex
751178825Sdfr           (OM_uint32 * minor_status,
752178825Sdfr            const gss_ctx_id_t context_handle,
753178825Sdfr	    const gss_buffer_t token_header_buffer,
754178825Sdfr	    const gss_buffer_t associated_data_buffer,
755178825Sdfr	    const gss_buffer_t input_message_buffer,
756178825Sdfr	    gss_buffer_t output_message_buffer,
757178825Sdfr	    int * conf_state,
758178825Sdfr	    gss_qop_t * qop_state)
759178825Sdfr{
760178825Sdfr    gssspnego_ctx ctx;
761178825Sdfr
762178825Sdfr    *minor_status = 0;
763178825Sdfr
764178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
765178825Sdfr	return GSS_S_NO_CONTEXT;
766178825Sdfr    }
767178825Sdfr
768178825Sdfr    ctx = (gssspnego_ctx)context_handle;
769178825Sdfr
770178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
771178825Sdfr	return GSS_S_NO_CONTEXT;
772178825Sdfr    }
773178825Sdfr
774178825Sdfr    return gss_unwrap_ex(minor_status,
775178825Sdfr			 ctx->negotiated_ctx_id,
776178825Sdfr			 token_header_buffer,
777178825Sdfr			 associated_data_buffer,
778178825Sdfr			 input_message_buffer,
779178825Sdfr			 output_message_buffer,
780178825Sdfr			 conf_state,
781178825Sdfr			 qop_state);
782178825Sdfr}
783178825Sdfr
784178825SdfrOM_uint32 _gss_spnego_wrap_ex
785178825Sdfr           (OM_uint32 * minor_status,
786178825Sdfr            const gss_ctx_id_t context_handle,
787178825Sdfr            int conf_req_flag,
788178825Sdfr            gss_qop_t qop_req,
789178825Sdfr            const gss_buffer_t associated_data_buffer,
790178825Sdfr            const gss_buffer_t input_message_buffer,
791178825Sdfr            int * conf_state,
792178825Sdfr            gss_buffer_t output_token_buffer,
793178825Sdfr            gss_buffer_t output_message_buffer
794178825Sdfr	   )
795178825Sdfr{
796178825Sdfr    gssspnego_ctx ctx;
797178825Sdfr
798178825Sdfr    *minor_status = 0;
799178825Sdfr
800178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
801178825Sdfr	return GSS_S_NO_CONTEXT;
802178825Sdfr    }
803178825Sdfr
804178825Sdfr    ctx = (gssspnego_ctx)context_handle;
805178825Sdfr
806178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
807178825Sdfr	return GSS_S_NO_CONTEXT;
808178825Sdfr    }
809178825Sdfr
810178825Sdfr    if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 &&
811178825Sdfr	associated_data_buffer->length != input_message_buffer->length) {
812178825Sdfr	*minor_status = EINVAL;
813178825Sdfr	return GSS_S_BAD_QOP;
814178825Sdfr    }
815178825Sdfr
816178825Sdfr    return gss_wrap_ex(minor_status,
817178825Sdfr		       ctx->negotiated_ctx_id,
818178825Sdfr		       conf_req_flag,
819178825Sdfr		       qop_req,
820178825Sdfr		       associated_data_buffer,
821178825Sdfr		       input_message_buffer,
822178825Sdfr		       conf_state,
823178825Sdfr		       output_token_buffer,
824178825Sdfr		       output_message_buffer);
825178825Sdfr}
826178825Sdfr
827178825SdfrOM_uint32 _gss_spnego_complete_auth_token
828178825Sdfr           (OM_uint32 * minor_status,
829178825Sdfr            const gss_ctx_id_t context_handle,
830178825Sdfr	    gss_buffer_t input_message_buffer)
831178825Sdfr{
832178825Sdfr    gssspnego_ctx ctx;
833178825Sdfr
834178825Sdfr    *minor_status = 0;
835178825Sdfr
836178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
837178825Sdfr	return GSS_S_NO_CONTEXT;
838178825Sdfr    }
839178825Sdfr
840178825Sdfr    ctx = (gssspnego_ctx)context_handle;
841178825Sdfr
842178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
843178825Sdfr	return GSS_S_NO_CONTEXT;
844178825Sdfr    }
845178825Sdfr
846178825Sdfr    return gss_complete_auth_token(minor_status,
847178825Sdfr				   ctx->negotiated_ctx_id,
848178825Sdfr				   input_message_buffer);
849178825Sdfr}
850178825Sdfr#endif
851178825Sdfr
852178825SdfrOM_uint32 _gss_spnego_inquire_sec_context_by_oid
853178825Sdfr           (OM_uint32 * minor_status,
854178825Sdfr            const gss_ctx_id_t context_handle,
855178825Sdfr            const gss_OID desired_object,
856178825Sdfr            gss_buffer_set_t *data_set)
857178825Sdfr{
858178825Sdfr    gssspnego_ctx ctx;
859178825Sdfr
860178825Sdfr    *minor_status = 0;
861178825Sdfr
862178825Sdfr    if (context_handle == GSS_C_NO_CONTEXT) {
863178825Sdfr	return GSS_S_NO_CONTEXT;
864178825Sdfr    }
865178825Sdfr
866178825Sdfr    ctx = (gssspnego_ctx)context_handle;
867178825Sdfr
868178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
869178825Sdfr	return GSS_S_NO_CONTEXT;
870178825Sdfr    }
871178825Sdfr
872178825Sdfr    return gss_inquire_sec_context_by_oid(minor_status,
873178825Sdfr					  ctx->negotiated_ctx_id,
874178825Sdfr					  desired_object,
875178825Sdfr					  data_set);
876178825Sdfr}
877178825Sdfr
878178825SdfrOM_uint32 _gss_spnego_set_sec_context_option
879178825Sdfr           (OM_uint32 * minor_status,
880178825Sdfr            gss_ctx_id_t * context_handle,
881178825Sdfr            const gss_OID desired_object,
882178825Sdfr            const gss_buffer_t value)
883178825Sdfr{
884178825Sdfr    gssspnego_ctx ctx;
885178825Sdfr
886178825Sdfr    *minor_status = 0;
887178825Sdfr
888178825Sdfr    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) {
889178825Sdfr	return GSS_S_NO_CONTEXT;
890178825Sdfr    }
891178825Sdfr
892178825Sdfr    ctx = (gssspnego_ctx)context_handle;
893178825Sdfr
894178825Sdfr    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
895178825Sdfr	return GSS_S_NO_CONTEXT;
896178825Sdfr    }
897178825Sdfr
898178825Sdfr    return gss_set_sec_context_option(minor_status,
899178825Sdfr				      &ctx->negotiated_ctx_id,
900178825Sdfr				      desired_object,
901178825Sdfr				      value);
902178825Sdfr}
903178825Sdfr
904