6f1c3eb4b6f493e4050c46e0ff5b3b007a5f82a6
[metze/samba/wip.git] / source / 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/spnego_locl.h"
34
35 RCSID("$Id: context_stubs.c 22688 2008-03-16 11:33:58Z lha $");
36
37 static OM_uint32
38 spnego_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     return ret;
66 }
67
68
69
70 OM_uint32 _gss_spnego_process_context_token
71            (OM_uint32 *minor_status,
72             const gss_ctx_id_t context_handle,
73             const gss_buffer_t token_buffer
74            )
75 {
76     gss_ctx_id_t context ;
77     gssspnego_ctx ctx;
78     OM_uint32 ret;
79
80     if (context_handle == GSS_C_NO_CONTEXT)
81         return GSS_S_NO_CONTEXT;
82
83     context = context_handle;
84     ctx = (gssspnego_ctx)context_handle;
85
86     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
87
88     ret = gss_process_context_token(minor_status,
89                                     ctx->negotiated_ctx_id,
90                                     token_buffer);
91     if (ret != GSS_S_COMPLETE) {
92         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
93         return ret;
94     }
95
96     ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
97
98     return _gss_spnego_internal_delete_sec_context(minor_status,
99                                            &context,
100                                            GSS_C_NO_BUFFER);
101 }
102
103 OM_uint32 _gss_spnego_delete_sec_context
104            (OM_uint32 *minor_status,
105             gss_ctx_id_t *context_handle,
106             gss_buffer_t output_token
107            )
108 {
109     gssspnego_ctx ctx;
110
111     if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
112         return GSS_S_NO_CONTEXT;
113
114     ctx = (gssspnego_ctx)*context_handle;
115
116     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
117
118     return _gss_spnego_internal_delete_sec_context(minor_status,
119                                                    context_handle,
120                                                    output_token);
121 }
122
123 OM_uint32 _gss_spnego_context_time
124            (OM_uint32 *minor_status,
125             const gss_ctx_id_t context_handle,
126             OM_uint32 *time_rec
127            )
128 {
129     gssspnego_ctx ctx;
130     *minor_status = 0;
131
132     if (context_handle == GSS_C_NO_CONTEXT) {
133         return GSS_S_NO_CONTEXT;
134     }
135
136     ctx = (gssspnego_ctx)context_handle;
137
138     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
139         return GSS_S_NO_CONTEXT;
140     }
141
142     return gss_context_time(minor_status,
143                             ctx->negotiated_ctx_id,
144                             time_rec);
145 }
146
147 OM_uint32 _gss_spnego_get_mic
148            (OM_uint32 *minor_status,
149             const gss_ctx_id_t context_handle,
150             gss_qop_t qop_req,
151             const gss_buffer_t message_buffer,
152             gss_buffer_t message_token
153            )
154 {
155     gssspnego_ctx ctx;
156
157     *minor_status = 0;
158
159     if (context_handle == GSS_C_NO_CONTEXT) {
160         return GSS_S_NO_CONTEXT;
161     }
162
163     ctx = (gssspnego_ctx)context_handle;
164
165     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
166         return GSS_S_NO_CONTEXT;
167     }
168
169     return gss_get_mic(minor_status, ctx->negotiated_ctx_id,
170                        qop_req, message_buffer, message_token);
171 }
172
173 OM_uint32 _gss_spnego_verify_mic
174            (OM_uint32 * minor_status,
175             const gss_ctx_id_t context_handle,
176             const gss_buffer_t message_buffer,
177             const gss_buffer_t token_buffer,
178             gss_qop_t * qop_state
179            )
180 {
181     gssspnego_ctx ctx;
182
183     *minor_status = 0;
184
185     if (context_handle == GSS_C_NO_CONTEXT) {
186         return GSS_S_NO_CONTEXT;
187     }
188
189     ctx = (gssspnego_ctx)context_handle;
190
191     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
192         return GSS_S_NO_CONTEXT;
193     }
194
195     return gss_verify_mic(minor_status,
196                           ctx->negotiated_ctx_id,
197                           message_buffer,
198                           token_buffer,
199                           qop_state);
200 }
201
202 OM_uint32 _gss_spnego_wrap
203            (OM_uint32 * minor_status,
204             const gss_ctx_id_t context_handle,
205             int conf_req_flag,
206             gss_qop_t qop_req,
207             const gss_buffer_t input_message_buffer,
208             int * conf_state,
209             gss_buffer_t output_message_buffer
210            )
211 {
212     gssspnego_ctx ctx;
213
214     *minor_status = 0;
215
216     if (context_handle == GSS_C_NO_CONTEXT) {
217         return GSS_S_NO_CONTEXT;
218     }
219
220     ctx = (gssspnego_ctx)context_handle;
221
222     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
223         return GSS_S_NO_CONTEXT;
224     }
225
226     return gss_wrap(minor_status,
227                     ctx->negotiated_ctx_id,
228                     conf_req_flag,
229                     qop_req,
230                     input_message_buffer,
231                     conf_state,
232                     output_message_buffer);
233 }
234
235 OM_uint32 _gss_spnego_unwrap
236            (OM_uint32 * minor_status,
237             const gss_ctx_id_t context_handle,
238             const gss_buffer_t input_message_buffer,
239             gss_buffer_t output_message_buffer,
240             int * conf_state,
241             gss_qop_t * qop_state
242            )
243 {
244     gssspnego_ctx ctx;
245
246     *minor_status = 0;
247
248     if (context_handle == GSS_C_NO_CONTEXT) {
249         return GSS_S_NO_CONTEXT;
250     }
251
252     ctx = (gssspnego_ctx)context_handle;
253
254     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
255         return GSS_S_NO_CONTEXT;
256     }
257
258     return gss_unwrap(minor_status,
259                       ctx->negotiated_ctx_id,
260                       input_message_buffer,
261                       output_message_buffer,
262                       conf_state,
263                       qop_state);
264 }
265
266 OM_uint32 _gss_spnego_compare_name
267            (OM_uint32 *minor_status,
268             const gss_name_t name1,
269             const gss_name_t name2,
270             int * name_equal
271            )
272 {
273     spnego_name n1 = (spnego_name)name1;
274     spnego_name n2 = (spnego_name)name2;
275
276     *name_equal = 0;
277
278     if (!gss_oid_equal(&n1->type, &n2->type))
279         return GSS_S_COMPLETE;
280     if (n1->value.length != n2->value.length)
281         return GSS_S_COMPLETE;
282     if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0)
283         return GSS_S_COMPLETE;
284
285     *name_equal = 1;
286
287     return GSS_S_COMPLETE;
288 }
289
290 OM_uint32 _gss_spnego_display_name
291            (OM_uint32 * minor_status,
292             const gss_name_t input_name,
293             gss_buffer_t output_name_buffer,
294             gss_OID * output_name_type
295            )
296 {
297     spnego_name name = (spnego_name)input_name;
298
299     *minor_status = 0;
300
301     if (name == NULL || name->mech == GSS_C_NO_NAME)
302         return GSS_S_FAILURE;
303
304     return gss_display_name(minor_status, name->mech,
305                             output_name_buffer, output_name_type);
306 }
307
308 OM_uint32 _gss_spnego_import_name
309            (OM_uint32 * minor_status,
310             const gss_buffer_t name_buffer,
311             const gss_OID name_type,
312             gss_name_t * output_name
313            )
314 {
315     spnego_name name;
316     OM_uint32 maj_stat;
317
318     *minor_status = 0;
319
320     name = calloc(1, sizeof(*name));
321     if (name == NULL) {
322         *minor_status = ENOMEM;
323         return GSS_S_FAILURE;
324     }
325     
326     maj_stat = _gss_copy_oid(minor_status, name_type, &name->type);
327     if (maj_stat) {
328         free(name);
329         return GSS_S_FAILURE;
330     }
331     
332     maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value);
333     if (maj_stat) {
334         gss_name_t rname = (gss_name_t)name;
335         _gss_spnego_release_name(minor_status, &rname);
336         return GSS_S_FAILURE;
337     }
338     name->mech = GSS_C_NO_NAME;
339     *output_name = (gss_name_t)name;
340
341     return GSS_S_COMPLETE;
342 }
343
344 OM_uint32 _gss_spnego_export_name
345            (OM_uint32  * minor_status,
346             const gss_name_t input_name,
347             gss_buffer_t exported_name
348            )
349 {
350     spnego_name name;
351     *minor_status = 0;
352
353     if (input_name == GSS_C_NO_NAME)
354         return GSS_S_BAD_NAME;
355
356     name = (spnego_name)input_name;
357     if (name->mech == GSS_C_NO_NAME)
358         return GSS_S_BAD_NAME;
359
360     return gss_export_name(minor_status, name->mech, exported_name);
361 }
362
363 OM_uint32 _gss_spnego_release_name
364            (OM_uint32 * minor_status,
365             gss_name_t * input_name
366            )
367 {
368     *minor_status = 0;
369
370     if (*input_name != GSS_C_NO_NAME) {
371         OM_uint32 junk;
372         spnego_name name = (spnego_name)*input_name;
373         _gss_free_oid(&junk, &name->type);
374         gss_release_buffer(&junk, &name->value);
375         if (name->mech != GSS_C_NO_NAME)
376             gss_release_name(&junk, &name->mech);
377         free(name);
378
379         *input_name = GSS_C_NO_NAME;
380     }
381     return GSS_S_COMPLETE;
382 }
383
384 OM_uint32 _gss_spnego_inquire_context (
385             OM_uint32 * minor_status,
386             const gss_ctx_id_t context_handle,
387             gss_name_t * src_name,
388             gss_name_t * targ_name,
389             OM_uint32 * lifetime_rec,
390             gss_OID * mech_type,
391             OM_uint32 * ctx_flags,
392             int * locally_initiated,
393             int * open_context
394            )
395 {
396     gssspnego_ctx ctx;
397     OM_uint32 maj_stat, junk;
398     gss_name_t src_mn, targ_mn;
399
400     *minor_status = 0;
401
402     if (context_handle == GSS_C_NO_CONTEXT)
403         return GSS_S_NO_CONTEXT;
404
405     ctx = (gssspnego_ctx)context_handle;
406
407     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
408         return GSS_S_NO_CONTEXT;
409
410     maj_stat = gss_inquire_context(minor_status,
411                                    ctx->negotiated_ctx_id,
412                                    &src_mn,
413                                    &targ_mn,
414                                    lifetime_rec,
415                                    mech_type,
416                                    ctx_flags,
417                                    locally_initiated,
418                                    open_context);
419     if (maj_stat != GSS_S_COMPLETE)
420         return maj_stat;
421
422     if (src_name) {
423         spnego_name name = calloc(1, sizeof(*name));
424         if (name == NULL)
425             goto enomem;
426         name->mech = src_mn;
427         *src_name = (gss_name_t)name;
428     } else
429         gss_release_name(&junk, &src_mn);
430     
431     if (targ_name) {
432         spnego_name name = calloc(1, sizeof(*name));
433         if (name == NULL) {
434             gss_release_name(minor_status, src_name);
435             goto enomem;
436         }
437         name->mech = targ_mn;
438         *targ_name = (gss_name_t)name;
439     } else
440         gss_release_name(&junk, &targ_mn);
441
442     return GSS_S_COMPLETE;
443
444 enomem:
445     gss_release_name(&junk, &targ_mn);
446     gss_release_name(&junk, &src_mn);
447     *minor_status = ENOMEM;
448     return GSS_S_FAILURE;
449 }
450
451 OM_uint32 _gss_spnego_wrap_size_limit (
452             OM_uint32 * minor_status,
453             const gss_ctx_id_t context_handle,
454             int conf_req_flag,
455             gss_qop_t qop_req,
456             OM_uint32 req_output_size,
457             OM_uint32 * max_input_size
458            )
459 {
460     gssspnego_ctx ctx;
461
462     *minor_status = 0;
463
464     if (context_handle == GSS_C_NO_CONTEXT) {
465         return GSS_S_NO_CONTEXT;
466     }
467
468     ctx = (gssspnego_ctx)context_handle;
469
470     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
471         return GSS_S_NO_CONTEXT;
472     }
473
474     return gss_wrap_size_limit(minor_status,
475                                ctx->negotiated_ctx_id,
476                                conf_req_flag,
477                                qop_req,
478                                req_output_size,
479                                max_input_size);
480 }
481
482 OM_uint32 _gss_spnego_export_sec_context (
483             OM_uint32 * minor_status,
484             gss_ctx_id_t * context_handle,
485             gss_buffer_t interprocess_token
486            )
487 {
488     gssspnego_ctx ctx;
489     OM_uint32 ret;
490
491     *minor_status = 0;
492
493     if (context_handle == NULL) {
494         return GSS_S_NO_CONTEXT;
495     }
496
497     ctx = (gssspnego_ctx)*context_handle;
498
499     if (ctx == NULL)
500         return GSS_S_NO_CONTEXT;
501
502     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
503
504     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
505         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
506         return GSS_S_NO_CONTEXT;
507     }
508
509     ret = gss_export_sec_context(minor_status,
510                                  &ctx->negotiated_ctx_id,
511                                  interprocess_token);
512     if (ret == GSS_S_COMPLETE) {
513         ret = _gss_spnego_internal_delete_sec_context(minor_status,
514                                              context_handle,
515                                              GSS_C_NO_BUFFER);
516         if (ret == GSS_S_COMPLETE)
517             return GSS_S_COMPLETE;
518     }
519
520     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
521
522     return ret;
523 }
524
525 OM_uint32 _gss_spnego_import_sec_context (
526             OM_uint32 * minor_status,
527             const gss_buffer_t interprocess_token,
528             gss_ctx_id_t *context_handle
529            )
530 {
531     OM_uint32 ret, minor;
532     gss_ctx_id_t context;
533     gssspnego_ctx ctx;
534
535     ret = _gss_spnego_alloc_sec_context(minor_status, &context);
536     if (ret != GSS_S_COMPLETE) {
537         return ret;
538     }
539     ctx = (gssspnego_ctx)context;
540
541     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
542
543     ret = gss_import_sec_context(minor_status,
544                                  interprocess_token,
545                                  &ctx->negotiated_ctx_id);
546     if (ret != GSS_S_COMPLETE) {
547         _gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER);
548         return ret;
549     }
550
551     ctx->open = 1;
552     /* don't bother filling in the rest of the fields */
553
554     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
555
556     *context_handle = (gss_ctx_id_t)ctx;
557
558     return GSS_S_COMPLETE;
559 }
560
561 OM_uint32 _gss_spnego_inquire_names_for_mech (
562             OM_uint32 * minor_status,
563             const gss_OID mechanism,
564             gss_OID_set * name_types
565            )
566 {
567     gss_OID_set mechs, names, n;
568     OM_uint32 ret, junk;
569     int i, j;
570
571     *name_types = NULL;
572
573     ret = spnego_supported_mechs(minor_status, &mechs);
574     if (ret != GSS_S_COMPLETE)
575         return ret;
576
577     ret = gss_create_empty_oid_set(minor_status, &names);
578     if (ret != GSS_S_COMPLETE)
579         goto out;
580
581     for (i = 0; i < mechs->count; i++) {
582         ret = gss_inquire_names_for_mech(minor_status,
583                                          &mechs->elements[i],
584                                          &n);
585         if (ret)
586             continue;
587
588         for (j = 0; j < n->count; j++)
589             gss_add_oid_set_member(minor_status,
590                                    &n->elements[j],
591                                    &names);
592         gss_release_oid_set(&junk, &n);
593     }
594
595     ret = GSS_S_COMPLETE;
596     *name_types = names;
597 out:
598
599     gss_release_oid_set(&junk, &mechs);
600
601     return GSS_S_COMPLETE;
602 }
603
604 OM_uint32 _gss_spnego_inquire_mechs_for_name (
605             OM_uint32 * minor_status,
606             const gss_name_t input_name,
607             gss_OID_set * mech_types
608            )
609 {
610     OM_uint32 ret, junk;
611
612     ret = gss_create_empty_oid_set(minor_status, mech_types);
613     if (ret)
614         return ret;
615
616     ret = gss_add_oid_set_member(minor_status,
617                                  GSS_SPNEGO_MECHANISM,
618                                  mech_types);
619     if (ret)
620         gss_release_oid_set(&junk, mech_types);
621
622     return ret;
623 }
624
625 OM_uint32 _gss_spnego_canonicalize_name (
626             OM_uint32 * minor_status,
627             const gss_name_t input_name,
628             const gss_OID mech_type,
629             gss_name_t * output_name
630            )
631 {
632     /* XXX */
633     return gss_duplicate_name(minor_status, input_name, output_name);
634 }
635
636 OM_uint32 _gss_spnego_duplicate_name (
637             OM_uint32 * minor_status,
638             const gss_name_t src_name,
639             gss_name_t * dest_name
640            )
641 {
642     return gss_duplicate_name(minor_status, src_name, dest_name);
643 }
644
645 OM_uint32 _gss_spnego_sign
646            (OM_uint32 * minor_status,
647             gss_ctx_id_t context_handle,
648             int qop_req,
649             gss_buffer_t message_buffer,
650             gss_buffer_t message_token
651            )
652 {
653     gssspnego_ctx ctx;
654
655     *minor_status = 0;
656
657     if (context_handle == GSS_C_NO_CONTEXT) {
658         return GSS_S_NO_CONTEXT;
659     }
660
661     ctx = (gssspnego_ctx)context_handle;
662
663     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
664         return GSS_S_NO_CONTEXT;
665     }
666
667     return gss_sign(minor_status,
668                     ctx->negotiated_ctx_id,
669                     qop_req,
670                     message_buffer,
671                     message_token);
672 }
673
674 OM_uint32 _gss_spnego_verify
675            (OM_uint32 * minor_status,
676             gss_ctx_id_t context_handle,
677             gss_buffer_t message_buffer,
678             gss_buffer_t token_buffer,
679             int * qop_state
680            )
681 {
682     gssspnego_ctx ctx;
683
684     *minor_status = 0;
685
686     if (context_handle == GSS_C_NO_CONTEXT) {
687         return GSS_S_NO_CONTEXT;
688     }
689
690     ctx = (gssspnego_ctx)context_handle;
691
692     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
693         return GSS_S_NO_CONTEXT;
694     }
695
696     return gss_verify(minor_status,
697                       ctx->negotiated_ctx_id,
698                       message_buffer,
699                       token_buffer,
700                       qop_state);
701 }
702
703 OM_uint32 _gss_spnego_seal
704            (OM_uint32 * minor_status,
705             gss_ctx_id_t context_handle,
706             int conf_req_flag,
707             int qop_req,
708             gss_buffer_t input_message_buffer,
709             int * conf_state,
710             gss_buffer_t output_message_buffer
711            )
712 {
713     gssspnego_ctx ctx;
714
715     *minor_status = 0;
716
717     if (context_handle == GSS_C_NO_CONTEXT) {
718         return GSS_S_NO_CONTEXT;
719     }
720
721     ctx = (gssspnego_ctx)context_handle;
722
723     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
724         return GSS_S_NO_CONTEXT;
725     }
726
727     return gss_seal(minor_status,
728                     ctx->negotiated_ctx_id,
729                     conf_req_flag,
730                     qop_req,
731                     input_message_buffer,
732                     conf_state,
733                     output_message_buffer);
734 }
735
736 OM_uint32 _gss_spnego_unseal
737            (OM_uint32 * minor_status,
738             gss_ctx_id_t context_handle,
739             gss_buffer_t input_message_buffer,
740             gss_buffer_t output_message_buffer,
741             int * conf_state,
742             int * qop_state
743            )
744 {
745     gssspnego_ctx ctx;
746
747     *minor_status = 0;
748
749     if (context_handle == GSS_C_NO_CONTEXT) {
750         return GSS_S_NO_CONTEXT;
751     }
752
753     ctx = (gssspnego_ctx)context_handle;
754
755     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
756         return GSS_S_NO_CONTEXT;
757     }
758
759     return gss_unseal(minor_status,
760                       ctx->negotiated_ctx_id,
761                       input_message_buffer,
762                       output_message_buffer,
763                       conf_state,
764                       qop_state);
765 }
766
767 #if 0
768 OM_uint32 _gss_spnego_unwrap_ex
769            (OM_uint32 * minor_status,
770             const gss_ctx_id_t context_handle,
771             const gss_buffer_t token_header_buffer,
772             const gss_buffer_t associated_data_buffer,
773             const gss_buffer_t input_message_buffer,
774             gss_buffer_t output_message_buffer,
775             int * conf_state,
776             gss_qop_t * qop_state)
777 {
778     gssspnego_ctx ctx;
779
780     *minor_status = 0;
781
782     if (context_handle == GSS_C_NO_CONTEXT) {
783         return GSS_S_NO_CONTEXT;
784     }
785
786     ctx = (gssspnego_ctx)context_handle;
787
788     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
789         return GSS_S_NO_CONTEXT;
790     }
791
792     return gss_unwrap_ex(minor_status,
793                          ctx->negotiated_ctx_id,
794                          token_header_buffer,
795                          associated_data_buffer,
796                          input_message_buffer,
797                          output_message_buffer,
798                          conf_state,
799                          qop_state);
800 }
801
802 OM_uint32 _gss_spnego_wrap_ex
803            (OM_uint32 * minor_status,
804             const gss_ctx_id_t context_handle,
805             int conf_req_flag,
806             gss_qop_t qop_req,
807             const gss_buffer_t associated_data_buffer,
808             const gss_buffer_t input_message_buffer,
809             int * conf_state,
810             gss_buffer_t output_token_buffer,
811             gss_buffer_t output_message_buffer
812            )
813 {
814     gssspnego_ctx ctx;
815
816     *minor_status = 0;
817
818     if (context_handle == GSS_C_NO_CONTEXT) {
819         return GSS_S_NO_CONTEXT;
820     }
821
822     ctx = (gssspnego_ctx)context_handle;
823
824     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
825         return GSS_S_NO_CONTEXT;
826     }
827
828     if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 &&
829         associated_data_buffer->length != input_message_buffer->length) {
830         *minor_status = EINVAL;
831         return GSS_S_BAD_QOP;
832     }
833
834     return gss_wrap_ex(minor_status,
835                        ctx->negotiated_ctx_id,
836                        conf_req_flag,
837                        qop_req,
838                        associated_data_buffer,
839                        input_message_buffer,
840                        conf_state,
841                        output_token_buffer,
842                        output_message_buffer);
843 }
844
845 OM_uint32 _gss_spnego_complete_auth_token
846            (OM_uint32 * minor_status,
847             const gss_ctx_id_t context_handle,
848             gss_buffer_t input_message_buffer)
849 {
850     gssspnego_ctx ctx;
851
852     *minor_status = 0;
853
854     if (context_handle == GSS_C_NO_CONTEXT) {
855         return GSS_S_NO_CONTEXT;
856     }
857
858     ctx = (gssspnego_ctx)context_handle;
859
860     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
861         return GSS_S_NO_CONTEXT;
862     }
863
864     return gss_complete_auth_token(minor_status,
865                                    ctx->negotiated_ctx_id,
866                                    input_message_buffer);
867 }
868 #endif
869
870 OM_uint32 _gss_spnego_inquire_sec_context_by_oid
871            (OM_uint32 * minor_status,
872             const gss_ctx_id_t context_handle,
873             const gss_OID desired_object,
874             gss_buffer_set_t *data_set)
875 {
876     gssspnego_ctx ctx;
877
878     *minor_status = 0;
879
880     if (context_handle == GSS_C_NO_CONTEXT) {
881         return GSS_S_NO_CONTEXT;
882     }
883
884     ctx = (gssspnego_ctx)context_handle;
885
886     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
887         return GSS_S_NO_CONTEXT;
888     }
889
890     return gss_inquire_sec_context_by_oid(minor_status,
891                                           ctx->negotiated_ctx_id,
892                                           desired_object,
893                                           data_set);
894 }
895
896 OM_uint32 _gss_spnego_set_sec_context_option
897            (OM_uint32 * minor_status,
898             gss_ctx_id_t * context_handle,
899             const gss_OID desired_object,
900             const gss_buffer_t value)
901 {
902     gssspnego_ctx ctx;
903
904     *minor_status = 0;
905
906     if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) {
907         return GSS_S_NO_CONTEXT;
908     }
909
910     ctx = (gssspnego_ctx)*context_handle;
911
912     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
913         return GSS_S_NO_CONTEXT;
914     }
915
916     return gss_set_sec_context_option(minor_status,
917                                       &ctx->negotiated_ctx_id,
918                                       desired_object,
919                                       value);
920 }
921
922
923 OM_uint32
924 _gss_spnego_pseudo_random(OM_uint32 *minor_status,
925                           gss_ctx_id_t context_handle,
926                           int prf_key,
927                           const gss_buffer_t prf_in,
928                           ssize_t desired_output_len,
929                           gss_buffer_t prf_out)
930 {
931     gssspnego_ctx ctx;
932
933     *minor_status = 0;
934
935     if (context_handle == GSS_C_NO_CONTEXT)
936         return GSS_S_NO_CONTEXT;
937
938     ctx = (gssspnego_ctx)context_handle;
939
940     if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT)
941         return GSS_S_NO_CONTEXT;
942
943     return gss_pseudo_random(minor_status,
944                              ctx->negotiated_ctx_id,
945                              prf_key,
946                              prf_in,
947                              desired_output_len,
948                              prf_out);
949 }