1/*	$NetBSD: context_stubs.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2
3/*
4 * Copyright (c) 2004, PADL Software Pty Ltd.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * 3. Neither the name of PADL Software nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include "spnego_locl.h"
36
37static OM_uint32
38spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
39{
40    OM_uint32 ret, junk;
41    gss_OID_set m;
42    size_t i;
43
44    ret = gss_indicate_mechs(minor_status, &m);
45    if (ret != GSS_S_COMPLETE)
46	return ret;
47
48    ret = gss_create_empty_oid_set(minor_status, mechs);
49    if (ret != GSS_S_COMPLETE) {
50	gss_release_oid_set(&junk, &m);
51	return ret;
52    }
53
54    for (i = 0; i < m->count; i++) {
55	if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM))
56	    continue;
57
58	ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs);
59	if (ret) {
60	    gss_release_oid_set(&junk, &m);
61	    gss_release_oid_set(&junk, mechs);
62	    return ret;
63	}
64    }
65    gss_release_oid_set(&junk, &m);
66    return ret;
67}
68
69
70
71OM_uint32 GSSAPI_CALLCONV _gss_spnego_process_context_token
72           (OM_uint32 *minor_status,
73            gss_const_ctx_id_t context_handle,
74            const gss_buffer_t token_buffer
75           )
76{
77    gss_ctx_id_t context;
78    gssspnego_ctx ctx;
79    OM_uint32 ret;
80
81    if (context_handle == GSS_C_NO_CONTEXT)
82	return GSS_S_NO_CONTEXT;
83
84    context = (gss_ctx_id_t)context_handle;
85    ctx = (gssspnego_ctx)context_handle;
86
87    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
88
89    ret = gss_process_context_token(minor_status,
90				    ctx->negotiated_ctx_id,
91				    token_buffer);
92    if (ret != GSS_S_COMPLETE) {
93	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
94	return ret;
95    }
96
97    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
98
99    return _gss_spnego_internal_delete_sec_context(minor_status,
100					   &context,
101					   GSS_C_NO_BUFFER);
102}
103
104OM_uint32 GSSAPI_CALLCONV _gss_spnego_delete_sec_context
105           (OM_uint32 *minor_status,
106            gss_ctx_id_t *context_handle,
107            gss_buffer_t output_token
108           )
109{
110    gssspnego_ctx ctx;
111
112    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
113	return GSS_S_NO_CONTEXT;
114
115    ctx = (gssspnego_ctx)*context_handle;
116
117    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
118
119    return _gss_spnego_internal_delete_sec_context(minor_status,
120						   context_handle,
121						   output_token);
122}
123
124OM_uint32 GSSAPI_CALLCONV _gss_spnego_context_time
125           (OM_uint32 *minor_status,
126            gss_const_ctx_id_t context_handle,
127            OM_uint32 *time_rec
128           )
129{
130    gssspnego_ctx ctx;
131    *minor_status = 0;
132
133    if (context_handle == GSS_C_NO_CONTEXT) {
134	return GSS_S_NO_CONTEXT;
135    }
136
137    ctx = (gssspnego_ctx)context_handle;
138
139    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
140	return GSS_S_NO_CONTEXT;
141    }
142
143    return gss_context_time(minor_status,
144			    ctx->negotiated_ctx_id,
145			    time_rec);
146}
147
148OM_uint32 GSSAPI_CALLCONV _gss_spnego_get_mic
149           (OM_uint32 *minor_status,
150            gss_const_ctx_id_t context_handle,
151            gss_qop_t qop_req,
152            const gss_buffer_t message_buffer,
153            gss_buffer_t message_token
154           )
155{
156    gssspnego_ctx ctx;
157
158    *minor_status = 0;
159
160    if (context_handle == GSS_C_NO_CONTEXT) {
161	return GSS_S_NO_CONTEXT;
162    }
163
164    ctx = (gssspnego_ctx)context_handle;
165
166    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
167	return GSS_S_NO_CONTEXT;
168    }
169
170    return gss_get_mic(minor_status, ctx->negotiated_ctx_id,
171		       qop_req, message_buffer, message_token);
172}
173
174OM_uint32 GSSAPI_CALLCONV _gss_spnego_verify_mic
175           (OM_uint32 * minor_status,
176            gss_const_ctx_id_t context_handle,
177            const gss_buffer_t message_buffer,
178            const gss_buffer_t token_buffer,
179            gss_qop_t * qop_state
180           )
181{
182    gssspnego_ctx ctx;
183
184    *minor_status = 0;
185
186    if (context_handle == GSS_C_NO_CONTEXT) {
187	return GSS_S_NO_CONTEXT;
188    }
189
190    ctx = (gssspnego_ctx)context_handle;
191
192    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
193	return GSS_S_NO_CONTEXT;
194    }
195
196    return gss_verify_mic(minor_status,
197			  ctx->negotiated_ctx_id,
198			  message_buffer,
199			  token_buffer,
200			  qop_state);
201}
202
203OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap
204           (OM_uint32 * minor_status,
205            gss_const_ctx_id_t context_handle,
206            int conf_req_flag,
207            gss_qop_t qop_req,
208            const gss_buffer_t input_message_buffer,
209            int * conf_state,
210            gss_buffer_t output_message_buffer
211           )
212{
213    gssspnego_ctx ctx;
214
215    *minor_status = 0;
216
217    if (context_handle == GSS_C_NO_CONTEXT) {
218	return GSS_S_NO_CONTEXT;
219    }
220
221    ctx = (gssspnego_ctx)context_handle;
222
223    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
224	return GSS_S_NO_CONTEXT;
225    }
226
227    return gss_wrap(minor_status,
228		    ctx->negotiated_ctx_id,
229		    conf_req_flag,
230		    qop_req,
231		    input_message_buffer,
232		    conf_state,
233		    output_message_buffer);
234}
235
236OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap
237           (OM_uint32 * minor_status,
238            gss_const_ctx_id_t context_handle,
239            const gss_buffer_t input_message_buffer,
240            gss_buffer_t output_message_buffer,
241            int * conf_state,
242            gss_qop_t * qop_state
243           )
244{
245    gssspnego_ctx ctx;
246
247    *minor_status = 0;
248
249    if (context_handle == GSS_C_NO_CONTEXT) {
250	return GSS_S_NO_CONTEXT;
251    }
252
253    ctx = (gssspnego_ctx)context_handle;
254
255    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
256	return GSS_S_NO_CONTEXT;
257    }
258
259    return gss_unwrap(minor_status,
260		      ctx->negotiated_ctx_id,
261		      input_message_buffer,
262		      output_message_buffer,
263		      conf_state,
264		      qop_state);
265}
266
267OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
268           (OM_uint32 *minor_status,
269            gss_const_name_t name1,
270            gss_const_name_t name2,
271            int * name_equal
272           )
273{
274    spnego_name n1 = (spnego_name)name1;
275    spnego_name n2 = (spnego_name)name2;
276
277    *name_equal = 0;
278
279    if (!gss_oid_equal(&n1->type, &n2->type))
280	return GSS_S_COMPLETE;
281    if (n1->value.length != n2->value.length)
282	return GSS_S_COMPLETE;
283    if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0)
284	return GSS_S_COMPLETE;
285
286    *name_equal = 1;
287
288    return GSS_S_COMPLETE;
289}
290
291OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name
292           (OM_uint32 * minor_status,
293            gss_const_name_t input_name,
294            gss_buffer_t output_name_buffer,
295            gss_OID * output_name_type
296           )
297{
298    spnego_name name = (spnego_name)input_name;
299
300    *minor_status = 0;
301
302    if (name == NULL || name->mech == GSS_C_NO_NAME)
303	return GSS_S_FAILURE;
304
305    return gss_display_name(minor_status, name->mech,
306			    output_name_buffer, output_name_type);
307}
308
309OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name
310           (OM_uint32 * minor_status,
311            const gss_buffer_t name_buffer,
312            const gss_OID name_type,
313            gss_name_t * output_name
314           )
315{
316    spnego_name name;
317    OM_uint32 maj_stat;
318
319    *minor_status = 0;
320
321    name = calloc(1, sizeof(*name));
322    if (name == NULL) {
323	*minor_status = ENOMEM;
324	return GSS_S_FAILURE;
325    }
326
327    maj_stat = _gss_copy_oid(minor_status, name_type, &name->type);
328    if (maj_stat) {
329	free(name);
330	return GSS_S_FAILURE;
331    }
332
333    maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value);
334    if (maj_stat) {
335	gss_name_t rname = (gss_name_t)name;
336	_gss_spnego_release_name(minor_status, &rname);
337	return GSS_S_FAILURE;
338    }
339    name->mech = GSS_C_NO_NAME;
340    *output_name = (gss_name_t)name;
341
342    return GSS_S_COMPLETE;
343}
344
345OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
346           (OM_uint32  * minor_status,
347            gss_const_name_t input_name,
348            gss_buffer_t exported_name
349           )
350{
351    spnego_name name;
352    *minor_status = 0;
353
354    if (input_name == GSS_C_NO_NAME)
355	return GSS_S_BAD_NAME;
356
357    name = (spnego_name)input_name;
358    if (name->mech == GSS_C_NO_NAME)
359	return GSS_S_BAD_NAME;
360
361    return gss_export_name(minor_status, name->mech, exported_name);
362}
363
364OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
365           (OM_uint32 * minor_status,
366            gss_name_t * input_name
367           )
368{
369    *minor_status = 0;
370
371    if (*input_name != GSS_C_NO_NAME) {
372	OM_uint32 junk;
373	spnego_name name = (spnego_name)*input_name;
374	_gss_free_oid(&junk, &name->type);
375	gss_release_buffer(&junk, &name->value);
376	if (name->mech != GSS_C_NO_NAME)
377	    gss_release_name(&junk, &name->mech);
378	free(name);
379
380	*input_name = GSS_C_NO_NAME;
381    }
382    return GSS_S_COMPLETE;
383}
384
385OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context (
386            OM_uint32 * minor_status,
387            gss_const_ctx_id_t context_handle,
388            gss_name_t * src_name,
389            gss_name_t * targ_name,
390            OM_uint32 * lifetime_rec,
391            gss_OID * mech_type,
392            OM_uint32 * ctx_flags,
393            int * locally_initiated,
394            int * open_context
395           )
396{
397    gssspnego_ctx ctx;
398    OM_uint32 maj_stat, junk;
399    gss_name_t src_mn, targ_mn;
400
401    *minor_status = 0;
402
403    if (context_handle == GSS_C_NO_CONTEXT)
404	return GSS_S_NO_CONTEXT;
405
406    ctx = (gssspnego_ctx)context_handle;
407
408    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
409	return GSS_S_NO_CONTEXT;
410
411    maj_stat = gss_inquire_context(minor_status,
412				   ctx->negotiated_ctx_id,
413				   &src_mn,
414				   &targ_mn,
415				   lifetime_rec,
416				   mech_type,
417				   ctx_flags,
418				   locally_initiated,
419				   open_context);
420    if (maj_stat != GSS_S_COMPLETE)
421	return maj_stat;
422
423    if (src_name) {
424	spnego_name name = calloc(1, sizeof(*name));
425	if (name == NULL)
426	    goto enomem;
427	name->mech = src_mn;
428	*src_name = (gss_name_t)name;
429    } else
430	gss_release_name(&junk, &src_mn);
431
432    if (targ_name) {
433	spnego_name name = calloc(1, sizeof(*name));
434	if (name == NULL) {
435	    gss_release_name(minor_status, src_name);
436	    goto enomem;
437	}
438	name->mech = targ_mn;
439	*targ_name = (gss_name_t)name;
440    } else
441	gss_release_name(&junk, &targ_mn);
442
443    return GSS_S_COMPLETE;
444
445enomem:
446    gss_release_name(&junk, &targ_mn);
447    gss_release_name(&junk, &src_mn);
448    *minor_status = ENOMEM;
449    return GSS_S_FAILURE;
450}
451
452OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap_size_limit (
453            OM_uint32 * minor_status,
454            gss_const_ctx_id_t context_handle,
455            int conf_req_flag,
456            gss_qop_t qop_req,
457            OM_uint32 req_output_size,
458            OM_uint32 * max_input_size
459           )
460{
461    gssspnego_ctx ctx;
462
463    *minor_status = 0;
464
465    if (context_handle == GSS_C_NO_CONTEXT) {
466	return GSS_S_NO_CONTEXT;
467    }
468
469    ctx = (gssspnego_ctx)context_handle;
470
471    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
472	return GSS_S_NO_CONTEXT;
473    }
474
475    return gss_wrap_size_limit(minor_status,
476			       ctx->negotiated_ctx_id,
477			       conf_req_flag,
478			       qop_req,
479			       req_output_size,
480			       max_input_size);
481}
482
483OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_sec_context (
484            OM_uint32 * minor_status,
485            gss_ctx_id_t * context_handle,
486            gss_buffer_t interprocess_token
487           )
488{
489    gssspnego_ctx ctx;
490    OM_uint32 ret;
491
492    *minor_status = 0;
493
494    if (context_handle == NULL) {
495	return GSS_S_NO_CONTEXT;
496    }
497
498    ctx = (gssspnego_ctx)*context_handle;
499
500    if (ctx == NULL)
501	return GSS_S_NO_CONTEXT;
502
503    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
504
505    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
506	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
507	return GSS_S_NO_CONTEXT;
508    }
509
510    ret = gss_export_sec_context(minor_status,
511				 &ctx->negotiated_ctx_id,
512				 interprocess_token);
513    if (ret == GSS_S_COMPLETE) {
514	ret = _gss_spnego_internal_delete_sec_context(minor_status,
515					     context_handle,
516					     GSS_C_NO_BUFFER);
517	if (ret == GSS_S_COMPLETE)
518	    return GSS_S_COMPLETE;
519    }
520
521    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
522
523    return ret;
524}
525
526OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_sec_context (
527            OM_uint32 * minor_status,
528            const gss_buffer_t interprocess_token,
529            gss_ctx_id_t *context_handle
530           )
531{
532    OM_uint32 ret, minor;
533    gss_ctx_id_t context;
534    gssspnego_ctx ctx;
535
536    *context_handle = GSS_C_NO_CONTEXT;
537    ret = _gss_spnego_alloc_sec_context(minor_status, &context);
538    if (ret != GSS_S_COMPLETE) {
539	return ret;
540    }
541    ctx = (gssspnego_ctx)context;
542
543    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
544
545    ret = gss_import_sec_context(minor_status,
546				 interprocess_token,
547				 &ctx->negotiated_ctx_id);
548    if (ret != GSS_S_COMPLETE) {
549	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
550	return ret;
551    }
552
553    ctx->open = 1;
554    /* don't bother filling in the rest of the fields */
555
556    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
557
558    *context_handle = (gss_ctx_id_t)ctx;
559
560    return GSS_S_COMPLETE;
561}
562
563OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_names_for_mech (
564            OM_uint32 * minor_status,
565            const gss_OID mechanism,
566            gss_OID_set * name_types
567           )
568{
569    gss_OID_set mechs, names, n;
570    OM_uint32 ret, junk;
571    size_t i, j;
572
573    *name_types = NULL;
574
575    ret = spnego_supported_mechs(minor_status, &mechs);
576    if (ret != GSS_S_COMPLETE)
577	return ret;
578
579    ret = gss_create_empty_oid_set(minor_status, &names);
580    if (ret != GSS_S_COMPLETE)
581	goto out;
582
583    for (i = 0; i < mechs->count; i++) {
584	ret = gss_inquire_names_for_mech(minor_status,
585					 &mechs->elements[i],
586					 &n);
587	if (ret)
588	    continue;
589
590	for (j = 0; j < n->count; j++)
591	    gss_add_oid_set_member(minor_status,
592				   &n->elements[j],
593				   &names);
594	gss_release_oid_set(&junk, &n);
595    }
596
597    ret = GSS_S_COMPLETE;
598    *name_types = names;
599out:
600
601    gss_release_oid_set(&junk, &mechs);
602
603    return ret;
604}
605
606OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name (
607            OM_uint32 * minor_status,
608            gss_const_name_t input_name,
609            gss_OID_set * mech_types
610           )
611{
612    OM_uint32 ret, junk;
613
614    ret = gss_create_empty_oid_set(minor_status, mech_types);
615    if (ret)
616	return ret;
617
618    ret = gss_add_oid_set_member(minor_status,
619				 GSS_SPNEGO_MECHANISM,
620				 mech_types);
621    if (ret)
622	gss_release_oid_set(&junk, mech_types);
623
624    return ret;
625}
626
627OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name (
628            OM_uint32 * minor_status,
629            gss_const_name_t input_name,
630            const gss_OID mech_type,
631            gss_name_t * output_name
632           )
633{
634    /* XXX */
635    return gss_duplicate_name(minor_status, input_name, output_name);
636}
637
638OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name (
639            OM_uint32 * minor_status,
640            gss_const_name_t src_name,
641            gss_name_t * dest_name
642           )
643{
644    return gss_duplicate_name(minor_status, src_name, dest_name);
645}
646
647OM_uint32 GSSAPI_CALLCONV
648_gss_spnego_wrap_iov(OM_uint32 * minor_status,
649		     gss_ctx_id_t  context_handle,
650		     int conf_req_flag,
651		     gss_qop_t qop_req,
652		     int * conf_state,
653		     gss_iov_buffer_desc *iov,
654		     int iov_count)
655{
656    gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
657
658    *minor_status = 0;
659
660    if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
661	return GSS_S_NO_CONTEXT;
662
663    return gss_wrap_iov(minor_status, ctx->negotiated_ctx_id,
664			conf_req_flag, qop_req, conf_state,
665			iov, iov_count);
666}
667
668OM_uint32 GSSAPI_CALLCONV
669_gss_spnego_unwrap_iov(OM_uint32 *minor_status,
670		       gss_ctx_id_t context_handle,
671		       int *conf_state,
672		       gss_qop_t *qop_state,
673		       gss_iov_buffer_desc *iov,
674		       int iov_count)
675{
676    gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
677
678    *minor_status = 0;
679
680    if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
681	return GSS_S_NO_CONTEXT;
682
683    return gss_unwrap_iov(minor_status,
684			  ctx->negotiated_ctx_id,
685			  conf_state, qop_state,
686			  iov, iov_count);
687}
688
689OM_uint32 GSSAPI_CALLCONV
690_gss_spnego_wrap_iov_length(OM_uint32 * minor_status,
691			    gss_ctx_id_t context_handle,
692			    int conf_req_flag,
693			    gss_qop_t qop_req,
694			    int *conf_state,
695			    gss_iov_buffer_desc *iov,
696			    int iov_count)
697{
698    gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
699
700    *minor_status = 0;
701
702    if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
703	return GSS_S_NO_CONTEXT;
704
705    return gss_wrap_iov_length(minor_status, ctx->negotiated_ctx_id,
706			       conf_req_flag, qop_req, conf_state,
707			       iov, iov_count);
708}
709
710#if 0
711OM_uint32 GSSAPI_CALLCONV _gss_spnego_complete_auth_token
712           (OM_uint32 * minor_status,
713            gss_const_ctx_id_t context_handle,
714	    gss_buffer_t input_message_buffer)
715{
716    gssspnego_ctx ctx;
717
718    *minor_status = 0;
719
720    if (context_handle == GSS_C_NO_CONTEXT) {
721	return GSS_S_NO_CONTEXT;
722    }
723
724    ctx = (gssspnego_ctx)context_handle;
725
726    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
727	return GSS_S_NO_CONTEXT;
728    }
729
730    return gss_complete_auth_token(minor_status,
731				   ctx->negotiated_ctx_id,
732				   input_message_buffer);
733}
734#endif
735
736OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_sec_context_by_oid
737           (OM_uint32 * minor_status,
738            gss_const_ctx_id_t context_handle,
739            const gss_OID desired_object,
740            gss_buffer_set_t *data_set)
741{
742    gssspnego_ctx ctx;
743
744    *minor_status = 0;
745
746    if (context_handle == GSS_C_NO_CONTEXT) {
747	return GSS_S_NO_CONTEXT;
748    }
749
750    ctx = (gssspnego_ctx)context_handle;
751
752    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
753	return GSS_S_NO_CONTEXT;
754    }
755
756    return gss_inquire_sec_context_by_oid(minor_status,
757					  ctx->negotiated_ctx_id,
758					  desired_object,
759					  data_set);
760}
761
762OM_uint32 GSSAPI_CALLCONV _gss_spnego_set_sec_context_option
763           (OM_uint32 * minor_status,
764            gss_ctx_id_t * context_handle,
765            const gss_OID desired_object,
766            const gss_buffer_t value)
767{
768    gssspnego_ctx ctx;
769
770    *minor_status = 0;
771
772    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) {
773	return GSS_S_NO_CONTEXT;
774    }
775
776    ctx = (gssspnego_ctx)*context_handle;
777
778    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
779	return GSS_S_NO_CONTEXT;
780    }
781
782    return gss_set_sec_context_option(minor_status,
783				      &ctx->negotiated_ctx_id,
784				      desired_object,
785				      value);
786}
787
788
789OM_uint32 GSSAPI_CALLCONV
790_gss_spnego_pseudo_random(OM_uint32 *minor_status,
791			  gss_ctx_id_t context_handle,
792			  int prf_key,
793			  const gss_buffer_t prf_in,
794			  ssize_t desired_output_len,
795			  gss_buffer_t prf_out)
796{
797    gssspnego_ctx ctx;
798
799    *minor_status = 0;
800
801    if (context_handle == GSS_C_NO_CONTEXT)
802	return GSS_S_NO_CONTEXT;
803
804    ctx = (gssspnego_ctx)context_handle;
805
806    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
807	return GSS_S_NO_CONTEXT;
808
809    return gss_pseudo_random(minor_status,
810			     ctx->negotiated_ctx_id,
811			     prf_key,
812			     prf_in,
813			     desired_output_len,
814			     prf_out);
815}
816