• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/heimdal/lib/gssapi/spnego/
1/*
2 * Copyright (c) 2004, PADL Software Pty Ltd.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "spnego_locl.h"
34
35RCSID("$Id: context_stubs.c,v 1.1.1.1 2011/06/10 09:34:41 andrew Exp $");
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    int 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 _gss_spnego_process_context_token
72           (OM_uint32 *minor_status,
73            const gss_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 = 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 _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 _gss_spnego_context_time
125           (OM_uint32 *minor_status,
126            const gss_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 _gss_spnego_get_mic
149           (OM_uint32 *minor_status,
150            const gss_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 _gss_spnego_verify_mic
175           (OM_uint32 * minor_status,
176            const gss_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 _gss_spnego_wrap
204           (OM_uint32 * minor_status,
205            const gss_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 _gss_spnego_unwrap
237           (OM_uint32 * minor_status,
238            const gss_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 _gss_spnego_compare_name
268           (OM_uint32 *minor_status,
269            const gss_name_t name1,
270            const gss_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 _gss_spnego_display_name
292           (OM_uint32 * minor_status,
293            const gss_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 _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 _gss_spnego_export_name
346           (OM_uint32  * minor_status,
347            const gss_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 _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 _gss_spnego_inquire_context (
386            OM_uint32 * minor_status,
387            const gss_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 _gss_spnego_wrap_size_limit (
453            OM_uint32 * minor_status,
454            const gss_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 _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 _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    ret = _gss_spnego_alloc_sec_context(minor_status, &context);
537    if (ret != GSS_S_COMPLETE) {
538	return ret;
539    }
540    ctx = (gssspnego_ctx)context;
541
542    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
543
544    ret = gss_import_sec_context(minor_status,
545				 interprocess_token,
546				 &ctx->negotiated_ctx_id);
547    if (ret != GSS_S_COMPLETE) {
548	_gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER);
549	return ret;
550    }
551
552    ctx->open = 1;
553    /* don't bother filling in the rest of the fields */
554
555    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
556
557    *context_handle = (gss_ctx_id_t)ctx;
558
559    return GSS_S_COMPLETE;
560}
561
562OM_uint32 _gss_spnego_inquire_names_for_mech (
563            OM_uint32 * minor_status,
564            const gss_OID mechanism,
565            gss_OID_set * name_types
566           )
567{
568    gss_OID_set mechs, names, n;
569    OM_uint32 ret, junk;
570    int i, j;
571
572    *name_types = NULL;
573
574    ret = spnego_supported_mechs(minor_status, &mechs);
575    if (ret != GSS_S_COMPLETE)
576	return ret;
577
578    ret = gss_create_empty_oid_set(minor_status, &names);
579    if (ret != GSS_S_COMPLETE)
580	goto out;
581
582    for (i = 0; i < mechs->count; i++) {
583	ret = gss_inquire_names_for_mech(minor_status,
584					 &mechs->elements[i],
585					 &n);
586	if (ret)
587	    continue;
588
589	for (j = 0; j < n->count; j++)
590	    gss_add_oid_set_member(minor_status,
591				   &n->elements[j],
592				   &names);
593	gss_release_oid_set(&junk, &n);
594    }
595
596    ret = GSS_S_COMPLETE;
597    *name_types = names;
598out:
599
600    gss_release_oid_set(&junk, &mechs);
601
602    return ret;
603}
604
605OM_uint32 _gss_spnego_inquire_mechs_for_name (
606            OM_uint32 * minor_status,
607            const gss_name_t input_name,
608            gss_OID_set * mech_types
609           )
610{
611    OM_uint32 ret, junk;
612
613    ret = gss_create_empty_oid_set(minor_status, mech_types);
614    if (ret)
615	return ret;
616
617    ret = gss_add_oid_set_member(minor_status,
618				 GSS_SPNEGO_MECHANISM,
619				 mech_types);
620    if (ret)
621	gss_release_oid_set(&junk, mech_types);
622
623    return ret;
624}
625
626OM_uint32 _gss_spnego_canonicalize_name (
627            OM_uint32 * minor_status,
628            const gss_name_t input_name,
629            const gss_OID mech_type,
630            gss_name_t * output_name
631           )
632{
633    /* XXX */
634    return gss_duplicate_name(minor_status, input_name, output_name);
635}
636
637OM_uint32 _gss_spnego_duplicate_name (
638            OM_uint32 * minor_status,
639            const gss_name_t src_name,
640            gss_name_t * dest_name
641           )
642{
643    return gss_duplicate_name(minor_status, src_name, dest_name);
644}
645
646#if 0
647OM_uint32 _gss_spnego_unwrap_ex
648           (OM_uint32 * minor_status,
649            const gss_ctx_id_t context_handle,
650	    const gss_buffer_t token_header_buffer,
651	    const gss_buffer_t associated_data_buffer,
652	    const gss_buffer_t input_message_buffer,
653	    gss_buffer_t output_message_buffer,
654	    int * conf_state,
655	    gss_qop_t * qop_state)
656{
657    gssspnego_ctx ctx;
658
659    *minor_status = 0;
660
661    if (context_handle == GSS_C_NO_CONTEXT) {
662	return GSS_S_NO_CONTEXT;
663    }
664
665    ctx = (gssspnego_ctx)context_handle;
666
667    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
668	return GSS_S_NO_CONTEXT;
669    }
670
671    return gss_unwrap_ex(minor_status,
672			 ctx->negotiated_ctx_id,
673			 token_header_buffer,
674			 associated_data_buffer,
675			 input_message_buffer,
676			 output_message_buffer,
677			 conf_state,
678			 qop_state);
679}
680
681OM_uint32 _gss_spnego_wrap_ex
682           (OM_uint32 * minor_status,
683            const gss_ctx_id_t context_handle,
684            int conf_req_flag,
685            gss_qop_t qop_req,
686            const gss_buffer_t associated_data_buffer,
687            const gss_buffer_t input_message_buffer,
688            int * conf_state,
689            gss_buffer_t output_token_buffer,
690            gss_buffer_t output_message_buffer
691	   )
692{
693    gssspnego_ctx ctx;
694
695    *minor_status = 0;
696
697    if (context_handle == GSS_C_NO_CONTEXT) {
698	return GSS_S_NO_CONTEXT;
699    }
700
701    ctx = (gssspnego_ctx)context_handle;
702
703    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
704	return GSS_S_NO_CONTEXT;
705    }
706
707    if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 &&
708	associated_data_buffer->length != input_message_buffer->length) {
709	*minor_status = EINVAL;
710	return GSS_S_BAD_QOP;
711    }
712
713    return gss_wrap_ex(minor_status,
714		       ctx->negotiated_ctx_id,
715		       conf_req_flag,
716		       qop_req,
717		       associated_data_buffer,
718		       input_message_buffer,
719		       conf_state,
720		       output_token_buffer,
721		       output_message_buffer);
722}
723
724OM_uint32 _gss_spnego_complete_auth_token
725           (OM_uint32 * minor_status,
726            const gss_ctx_id_t context_handle,
727	    gss_buffer_t input_message_buffer)
728{
729    gssspnego_ctx ctx;
730
731    *minor_status = 0;
732
733    if (context_handle == GSS_C_NO_CONTEXT) {
734	return GSS_S_NO_CONTEXT;
735    }
736
737    ctx = (gssspnego_ctx)context_handle;
738
739    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
740	return GSS_S_NO_CONTEXT;
741    }
742
743    return gss_complete_auth_token(minor_status,
744				   ctx->negotiated_ctx_id,
745				   input_message_buffer);
746}
747#endif
748
749OM_uint32 _gss_spnego_inquire_sec_context_by_oid
750           (OM_uint32 * minor_status,
751            const gss_ctx_id_t context_handle,
752            const gss_OID desired_object,
753            gss_buffer_set_t *data_set)
754{
755    gssspnego_ctx ctx;
756
757    *minor_status = 0;
758
759    if (context_handle == GSS_C_NO_CONTEXT) {
760	return GSS_S_NO_CONTEXT;
761    }
762
763    ctx = (gssspnego_ctx)context_handle;
764
765    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
766	return GSS_S_NO_CONTEXT;
767    }
768
769    return gss_inquire_sec_context_by_oid(minor_status,
770					  ctx->negotiated_ctx_id,
771					  desired_object,
772					  data_set);
773}
774
775OM_uint32 _gss_spnego_set_sec_context_option
776           (OM_uint32 * minor_status,
777            gss_ctx_id_t * context_handle,
778            const gss_OID desired_object,
779            const gss_buffer_t value)
780{
781    gssspnego_ctx ctx;
782
783    *minor_status = 0;
784
785    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) {
786	return GSS_S_NO_CONTEXT;
787    }
788
789    ctx = (gssspnego_ctx)*context_handle;
790
791    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
792	return GSS_S_NO_CONTEXT;
793    }
794
795    return gss_set_sec_context_option(minor_status,
796				      &ctx->negotiated_ctx_id,
797				      desired_object,
798				      value);
799}
800
801
802OM_uint32
803_gss_spnego_pseudo_random(OM_uint32 *minor_status,
804			  gss_ctx_id_t context_handle,
805			  int prf_key,
806			  const gss_buffer_t prf_in,
807			  ssize_t desired_output_len,
808			  gss_buffer_t prf_out)
809{
810    gssspnego_ctx ctx;
811
812    *minor_status = 0;
813
814    if (context_handle == GSS_C_NO_CONTEXT)
815	return GSS_S_NO_CONTEXT;
816
817    ctx = (gssspnego_ctx)context_handle;
818
819    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
820	return GSS_S_NO_CONTEXT;
821
822    return gss_pseudo_random(minor_status,
823			     ctx->negotiated_ctx_id,
824			     prf_key,
825			     prf_in,
826			     desired_output_len,
827			     prf_out);
828}
829