]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - crypto/heimdal/lib/gssapi/spnego/context_stubs.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / crypto / heimdal / lib / gssapi / spnego / context_stubs.c
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
35 static OM_uint32
36 spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
37 {
38     OM_uint32 ret, junk;
39     gss_OID_set m;
40     size_t i;
41
42     ret = gss_indicate_mechs(minor_status, &m);
43     if (ret != GSS_S_COMPLETE)
44         return ret;
45
46     ret = gss_create_empty_oid_set(minor_status, mechs);
47     if (ret != GSS_S_COMPLETE) {
48         gss_release_oid_set(&junk, &m);
49         return ret;
50     }
51
52     for (i = 0; i < m->count; i++) {
53         if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM))
54             continue;
55
56         ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs);
57         if (ret) {
58             gss_release_oid_set(&junk, &m);
59             gss_release_oid_set(&junk, mechs);
60             return ret;
61         }
62     }
63     gss_release_oid_set(&junk, &m);
64     return ret;
65 }
66
67
68
69 OM_uint32 GSSAPI_CALLCONV _gss_spnego_process_context_token
70            (OM_uint32 *minor_status,
71             const gss_ctx_id_t context_handle,
72             const gss_buffer_t token_buffer
73            )
74 {
75     gss_ctx_id_t context ;
76     gssspnego_ctx ctx;
77     OM_uint32 ret;
78
79     if (context_handle == GSS_C_NO_CONTEXT)
80         return GSS_S_NO_CONTEXT;
81
82     context = context_handle;
83     ctx = (gssspnego_ctx)context_handle;
84
85     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
86
87     ret = gss_process_context_token(minor_status,
88                                     ctx->negotiated_ctx_id,
89                                     token_buffer);
90     if (ret != GSS_S_COMPLETE) {
91         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
92         return ret;
93     }
94
95     ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
96
97     return _gss_spnego_internal_delete_sec_context(minor_status,
98                                            &context,
99                                            GSS_C_NO_BUFFER);
100 }
101
102 OM_uint32 GSSAPI_CALLCONV _gss_spnego_delete_sec_context
103            (OM_uint32 *minor_status,
104             gss_ctx_id_t *context_handle,
105             gss_buffer_t output_token
106            )
107 {
108     gssspnego_ctx ctx;
109
110     if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
111         return GSS_S_NO_CONTEXT;
112
113     ctx = (gssspnego_ctx)*context_handle;
114
115     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
116
117     return _gss_spnego_internal_delete_sec_context(minor_status,
118                                                    context_handle,
119                                                    output_token);
120 }
121
122 OM_uint32 GSSAPI_CALLCONV _gss_spnego_context_time
123            (OM_uint32 *minor_status,
124             const gss_ctx_id_t context_handle,
125             OM_uint32 *time_rec
126            )
127 {
128     gssspnego_ctx ctx;
129     *minor_status = 0;
130
131     if (context_handle == GSS_C_NO_CONTEXT) {
132         return GSS_S_NO_CONTEXT;
133     }
134
135     ctx = (gssspnego_ctx)context_handle;
136
137     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
138         return GSS_S_NO_CONTEXT;
139     }
140
141     return gss_context_time(minor_status,
142                             ctx->negotiated_ctx_id,
143                             time_rec);
144 }
145
146 OM_uint32 GSSAPI_CALLCONV _gss_spnego_get_mic
147            (OM_uint32 *minor_status,
148             const gss_ctx_id_t context_handle,
149             gss_qop_t qop_req,
150             const gss_buffer_t message_buffer,
151             gss_buffer_t message_token
152            )
153 {
154     gssspnego_ctx ctx;
155
156     *minor_status = 0;
157
158     if (context_handle == GSS_C_NO_CONTEXT) {
159         return GSS_S_NO_CONTEXT;
160     }
161
162     ctx = (gssspnego_ctx)context_handle;
163
164     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
165         return GSS_S_NO_CONTEXT;
166     }
167
168     return gss_get_mic(minor_status, ctx->negotiated_ctx_id,
169                        qop_req, message_buffer, message_token);
170 }
171
172 OM_uint32 GSSAPI_CALLCONV _gss_spnego_verify_mic
173            (OM_uint32 * minor_status,
174             const gss_ctx_id_t context_handle,
175             const gss_buffer_t message_buffer,
176             const gss_buffer_t token_buffer,
177             gss_qop_t * qop_state
178            )
179 {
180     gssspnego_ctx ctx;
181
182     *minor_status = 0;
183
184     if (context_handle == GSS_C_NO_CONTEXT) {
185         return GSS_S_NO_CONTEXT;
186     }
187
188     ctx = (gssspnego_ctx)context_handle;
189
190     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
191         return GSS_S_NO_CONTEXT;
192     }
193
194     return gss_verify_mic(minor_status,
195                           ctx->negotiated_ctx_id,
196                           message_buffer,
197                           token_buffer,
198                           qop_state);
199 }
200
201 OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap
202            (OM_uint32 * minor_status,
203             const gss_ctx_id_t context_handle,
204             int conf_req_flag,
205             gss_qop_t qop_req,
206             const gss_buffer_t input_message_buffer,
207             int * conf_state,
208             gss_buffer_t output_message_buffer
209            )
210 {
211     gssspnego_ctx ctx;
212
213     *minor_status = 0;
214
215     if (context_handle == GSS_C_NO_CONTEXT) {
216         return GSS_S_NO_CONTEXT;
217     }
218
219     ctx = (gssspnego_ctx)context_handle;
220
221     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
222         return GSS_S_NO_CONTEXT;
223     }
224
225     return gss_wrap(minor_status,
226                     ctx->negotiated_ctx_id,
227                     conf_req_flag,
228                     qop_req,
229                     input_message_buffer,
230                     conf_state,
231                     output_message_buffer);
232 }
233
234 OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap
235            (OM_uint32 * minor_status,
236             const gss_ctx_id_t context_handle,
237             const gss_buffer_t input_message_buffer,
238             gss_buffer_t output_message_buffer,
239             int * conf_state,
240             gss_qop_t * qop_state
241            )
242 {
243     gssspnego_ctx ctx;
244
245     *minor_status = 0;
246
247     if (context_handle == GSS_C_NO_CONTEXT) {
248         return GSS_S_NO_CONTEXT;
249     }
250
251     ctx = (gssspnego_ctx)context_handle;
252
253     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
254         return GSS_S_NO_CONTEXT;
255     }
256
257     return gss_unwrap(minor_status,
258                       ctx->negotiated_ctx_id,
259                       input_message_buffer,
260                       output_message_buffer,
261                       conf_state,
262                       qop_state);
263 }
264
265 OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
266            (OM_uint32 *minor_status,
267             const gss_name_t name1,
268             const gss_name_t name2,
269             int * name_equal
270            )
271 {
272     spnego_name n1 = (spnego_name)name1;
273     spnego_name n2 = (spnego_name)name2;
274
275     *name_equal = 0;
276
277     if (!gss_oid_equal(&n1->type, &n2->type))
278         return GSS_S_COMPLETE;
279     if (n1->value.length != n2->value.length)
280         return GSS_S_COMPLETE;
281     if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0)
282         return GSS_S_COMPLETE;
283
284     *name_equal = 1;
285
286     return GSS_S_COMPLETE;
287 }
288
289 OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name
290            (OM_uint32 * minor_status,
291             const gss_name_t input_name,
292             gss_buffer_t output_name_buffer,
293             gss_OID * output_name_type
294            )
295 {
296     spnego_name name = (spnego_name)input_name;
297
298     *minor_status = 0;
299
300     if (name == NULL || name->mech == GSS_C_NO_NAME)
301         return GSS_S_FAILURE;
302
303     return gss_display_name(minor_status, name->mech,
304                             output_name_buffer, output_name_type);
305 }
306
307 OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name
308            (OM_uint32 * minor_status,
309             const gss_buffer_t name_buffer,
310             const gss_OID name_type,
311             gss_name_t * output_name
312            )
313 {
314     spnego_name name;
315     OM_uint32 maj_stat;
316
317     *minor_status = 0;
318
319     name = calloc(1, sizeof(*name));
320     if (name == NULL) {
321         *minor_status = ENOMEM;
322         return GSS_S_FAILURE;
323     }
324
325     maj_stat = _gss_copy_oid(minor_status, name_type, &name->type);
326     if (maj_stat) {
327         free(name);
328         return GSS_S_FAILURE;
329     }
330
331     maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value);
332     if (maj_stat) {
333         gss_name_t rname = (gss_name_t)name;
334         _gss_spnego_release_name(minor_status, &rname);
335         return GSS_S_FAILURE;
336     }
337     name->mech = GSS_C_NO_NAME;
338     *output_name = (gss_name_t)name;
339
340     return GSS_S_COMPLETE;
341 }
342
343 OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
344            (OM_uint32  * minor_status,
345             const gss_name_t input_name,
346             gss_buffer_t exported_name
347            )
348 {
349     spnego_name name;
350     *minor_status = 0;
351
352     if (input_name == GSS_C_NO_NAME)
353         return GSS_S_BAD_NAME;
354
355     name = (spnego_name)input_name;
356     if (name->mech == GSS_C_NO_NAME)
357         return GSS_S_BAD_NAME;
358
359     return gss_export_name(minor_status, name->mech, exported_name);
360 }
361
362 OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
363            (OM_uint32 * minor_status,
364             gss_name_t * input_name
365            )
366 {
367     *minor_status = 0;
368
369     if (*input_name != GSS_C_NO_NAME) {
370         OM_uint32 junk;
371         spnego_name name = (spnego_name)*input_name;
372         _gss_free_oid(&junk, &name->type);
373         gss_release_buffer(&junk, &name->value);
374         if (name->mech != GSS_C_NO_NAME)
375             gss_release_name(&junk, &name->mech);
376         free(name);
377
378         *input_name = GSS_C_NO_NAME;
379     }
380     return GSS_S_COMPLETE;
381 }
382
383 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context (
384             OM_uint32 * minor_status,
385             const gss_ctx_id_t context_handle,
386             gss_name_t * src_name,
387             gss_name_t * targ_name,
388             OM_uint32 * lifetime_rec,
389             gss_OID * mech_type,
390             OM_uint32 * ctx_flags,
391             int * locally_initiated,
392             int * open_context
393            )
394 {
395     gssspnego_ctx ctx;
396     OM_uint32 maj_stat, junk;
397     gss_name_t src_mn, targ_mn;
398
399     *minor_status = 0;
400
401     if (context_handle == GSS_C_NO_CONTEXT)
402         return GSS_S_NO_CONTEXT;
403
404     ctx = (gssspnego_ctx)context_handle;
405
406     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
407         return GSS_S_NO_CONTEXT;
408
409     maj_stat = gss_inquire_context(minor_status,
410                                    ctx->negotiated_ctx_id,
411                                    &src_mn,
412                                    &targ_mn,
413                                    lifetime_rec,
414                                    mech_type,
415                                    ctx_flags,
416                                    locally_initiated,
417                                    open_context);
418     if (maj_stat != GSS_S_COMPLETE)
419         return maj_stat;
420
421     if (src_name) {
422         spnego_name name = calloc(1, sizeof(*name));
423         if (name == NULL)
424             goto enomem;
425         name->mech = src_mn;
426         *src_name = (gss_name_t)name;
427     } else
428         gss_release_name(&junk, &src_mn);
429
430     if (targ_name) {
431         spnego_name name = calloc(1, sizeof(*name));
432         if (name == NULL) {
433             gss_release_name(minor_status, src_name);
434             goto enomem;
435         }
436         name->mech = targ_mn;
437         *targ_name = (gss_name_t)name;
438     } else
439         gss_release_name(&junk, &targ_mn);
440
441     return GSS_S_COMPLETE;
442
443 enomem:
444     gss_release_name(&junk, &targ_mn);
445     gss_release_name(&junk, &src_mn);
446     *minor_status = ENOMEM;
447     return GSS_S_FAILURE;
448 }
449
450 OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap_size_limit (
451             OM_uint32 * minor_status,
452             const gss_ctx_id_t context_handle,
453             int conf_req_flag,
454             gss_qop_t qop_req,
455             OM_uint32 req_output_size,
456             OM_uint32 * max_input_size
457            )
458 {
459     gssspnego_ctx ctx;
460
461     *minor_status = 0;
462
463     if (context_handle == GSS_C_NO_CONTEXT) {
464         return GSS_S_NO_CONTEXT;
465     }
466
467     ctx = (gssspnego_ctx)context_handle;
468
469     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
470         return GSS_S_NO_CONTEXT;
471     }
472
473     return gss_wrap_size_limit(minor_status,
474                                ctx->negotiated_ctx_id,
475                                conf_req_flag,
476                                qop_req,
477                                req_output_size,
478                                max_input_size);
479 }
480
481 OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_sec_context (
482             OM_uint32 * minor_status,
483             gss_ctx_id_t * context_handle,
484             gss_buffer_t interprocess_token
485            )
486 {
487     gssspnego_ctx ctx;
488     OM_uint32 ret;
489
490     *minor_status = 0;
491
492     if (context_handle == NULL) {
493         return GSS_S_NO_CONTEXT;
494     }
495
496     ctx = (gssspnego_ctx)*context_handle;
497
498     if (ctx == NULL)
499         return GSS_S_NO_CONTEXT;
500
501     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
502
503     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
504         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
505         return GSS_S_NO_CONTEXT;
506     }
507
508     ret = gss_export_sec_context(minor_status,
509                                  &ctx->negotiated_ctx_id,
510                                  interprocess_token);
511     if (ret == GSS_S_COMPLETE) {
512         ret = _gss_spnego_internal_delete_sec_context(minor_status,
513                                              context_handle,
514                                              GSS_C_NO_BUFFER);
515         if (ret == GSS_S_COMPLETE)
516             return GSS_S_COMPLETE;
517     }
518
519     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
520
521     return ret;
522 }
523
524 OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_sec_context (
525             OM_uint32 * minor_status,
526             const gss_buffer_t interprocess_token,
527             gss_ctx_id_t *context_handle
528            )
529 {
530     OM_uint32 ret, minor;
531     gss_ctx_id_t context;
532     gssspnego_ctx ctx;
533
534     ret = _gss_spnego_alloc_sec_context(minor_status, &context);
535     if (ret != GSS_S_COMPLETE) {
536         return ret;
537     }
538     ctx = (gssspnego_ctx)context;
539
540     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
541
542     ret = gss_import_sec_context(minor_status,
543                                  interprocess_token,
544                                  &ctx->negotiated_ctx_id);
545     if (ret != GSS_S_COMPLETE) {
546         _gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER);
547         return ret;
548     }
549
550     ctx->open = 1;
551     /* don't bother filling in the rest of the fields */
552
553     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
554
555     *context_handle = (gss_ctx_id_t)ctx;
556
557     return GSS_S_COMPLETE;
558 }
559
560 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_names_for_mech (
561             OM_uint32 * minor_status,
562             const gss_OID mechanism,
563             gss_OID_set * name_types
564            )
565 {
566     gss_OID_set mechs, names, n;
567     OM_uint32 ret, junk;
568     size_t i, j;
569
570     *name_types = NULL;
571
572     ret = spnego_supported_mechs(minor_status, &mechs);
573     if (ret != GSS_S_COMPLETE)
574         return ret;
575
576     ret = gss_create_empty_oid_set(minor_status, &names);
577     if (ret != GSS_S_COMPLETE)
578         goto out;
579
580     for (i = 0; i < mechs->count; i++) {
581         ret = gss_inquire_names_for_mech(minor_status,
582                                          &mechs->elements[i],
583                                          &n);
584         if (ret)
585             continue;
586
587         for (j = 0; j < n->count; j++)
588             gss_add_oid_set_member(minor_status,
589                                    &n->elements[j],
590                                    &names);
591         gss_release_oid_set(&junk, &n);
592     }
593
594     ret = GSS_S_COMPLETE;
595     *name_types = names;
596 out:
597
598     gss_release_oid_set(&junk, &mechs);
599
600     return ret;
601 }
602
603 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name (
604             OM_uint32 * minor_status,
605             const gss_name_t input_name,
606             gss_OID_set * mech_types
607            )
608 {
609     OM_uint32 ret, junk;
610
611     ret = gss_create_empty_oid_set(minor_status, mech_types);
612     if (ret)
613         return ret;
614
615     ret = gss_add_oid_set_member(minor_status,
616                                  GSS_SPNEGO_MECHANISM,
617                                  mech_types);
618     if (ret)
619         gss_release_oid_set(&junk, mech_types);
620
621     return ret;
622 }
623
624 OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name (
625             OM_uint32 * minor_status,
626             const gss_name_t input_name,
627             const gss_OID mech_type,
628             gss_name_t * output_name
629            )
630 {
631     /* XXX */
632     return gss_duplicate_name(minor_status, input_name, output_name);
633 }
634
635 OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name (
636             OM_uint32 * minor_status,
637             const gss_name_t src_name,
638             gss_name_t * dest_name
639            )
640 {
641     return gss_duplicate_name(minor_status, src_name, dest_name);
642 }
643
644 #if 0
645 OM_uint32 GSSAPI_CALLCONV
646 _gss_spnego_wrap_iov(OM_uint32 * minor_status,
647                      gss_ctx_id_t  context_handle,
648                      int conf_req_flag,
649                      gss_qop_t qop_req,
650                      int * conf_state,
651                      gss_iov_buffer_desc *iov,
652                      int iov_count)
653 {
654     gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
655
656     *minor_status = 0;
657
658     if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
659         return GSS_S_NO_CONTEXT;
660
661     return gss_wrap_iov(minor_status, ctx->negotiated_ctx_id,
662                         conf_req_flag, qop_req, conf_state,
663                         iov, iov_count);
664 }
665
666 OM_uint32 GSSAPI_CALLCONV
667 _gss_spnego_unwrap_iov(OM_uint32 *minor_status,
668                        gss_ctx_id_t context_handle,
669                        int *conf_state,
670                        gss_qop_t *qop_state,
671                        gss_iov_buffer_desc *iov,
672                        int iov_count)
673 {
674     gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
675
676     *minor_status = 0;
677
678     if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
679         return GSS_S_NO_CONTEXT;
680
681     return gss_unwrap_iov(minor_status,
682                           ctx->negotiated_ctx_id,
683                           conf_state, qop_state,
684                           iov, iov_count);
685 }
686
687 OM_uint32 GSSAPI_CALLCONV
688 _gss_spnego_wrap_iov_length(OM_uint32 * minor_status,
689                             gss_ctx_id_t context_handle,
690                             int conf_req_flag,
691                             gss_qop_t qop_req,
692                             int *conf_state,
693                             gss_iov_buffer_desc *iov,
694                             int iov_count)
695 {
696     gssspnego_ctx ctx = (gssspnego_ctx)context_handle;
697
698     *minor_status = 0;
699
700     if (ctx == NULL || ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
701         return GSS_S_NO_CONTEXT;
702
703     return gss_wrap_iov_length(minor_status, ctx->negotiated_ctx_id,
704                                conf_req_flag, qop_req, conf_state,
705                                iov, iov_count);
706 }
707
708 #endif
709
710 #if 0
711 OM_uint32 GSSAPI_CALLCONV _gss_spnego_complete_auth_token
712            (OM_uint32 * minor_status,
713             const gss_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
736 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_sec_context_by_oid
737            (OM_uint32 * minor_status,
738             const gss_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
762 OM_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
789 OM_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 }