xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/gssapi/spnego/context_stubs.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
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 
37 static OM_uint32
spnego_supported_mechs(OM_uint32 * minor_status,gss_OID_set * mechs)38 spnego_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 
_gss_spnego_process_context_token(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,const gss_buffer_t token_buffer)71 OM_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 
_gss_spnego_delete_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t output_token)104 OM_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 
_gss_spnego_context_time(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,OM_uint32 * time_rec)124 OM_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 
_gss_spnego_get_mic(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,gss_qop_t qop_req,const gss_buffer_t message_buffer,gss_buffer_t message_token)148 OM_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 
_gss_spnego_verify_mic(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,const gss_buffer_t message_buffer,const gss_buffer_t token_buffer,gss_qop_t * qop_state)174 OM_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 
_gss_spnego_wrap(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,int conf_req_flag,gss_qop_t qop_req,const gss_buffer_t input_message_buffer,int * conf_state,gss_buffer_t output_message_buffer)203 OM_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 
_gss_spnego_unwrap(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state)236 OM_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 
_gss_spnego_compare_name(OM_uint32 * minor_status,gss_const_name_t name1,gss_const_name_t name2,int * name_equal)267 OM_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 
_gss_spnego_display_name(OM_uint32 * minor_status,gss_const_name_t input_name,gss_buffer_t output_name_buffer,gss_OID * output_name_type)291 OM_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 
_gss_spnego_import_name(OM_uint32 * minor_status,const gss_buffer_t name_buffer,const gss_OID name_type,gss_name_t * output_name)309 OM_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 
_gss_spnego_export_name(OM_uint32 * minor_status,gss_const_name_t input_name,gss_buffer_t exported_name)345 OM_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 
_gss_spnego_release_name(OM_uint32 * minor_status,gss_name_t * input_name)364 OM_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 
_gss_spnego_inquire_context(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,gss_name_t * src_name,gss_name_t * targ_name,OM_uint32 * lifetime_rec,gss_OID * mech_type,OM_uint32 * ctx_flags,int * locally_initiated,int * open_context)385 OM_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 
445 enomem:
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 
_gss_spnego_wrap_size_limit(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,int conf_req_flag,gss_qop_t qop_req,OM_uint32 req_output_size,OM_uint32 * max_input_size)452 OM_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 
_gss_spnego_export_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t interprocess_token)483 OM_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 
_gss_spnego_import_sec_context(OM_uint32 * minor_status,const gss_buffer_t interprocess_token,gss_ctx_id_t * context_handle)526 OM_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 
_gss_spnego_inquire_names_for_mech(OM_uint32 * minor_status,const gss_OID mechanism,gss_OID_set * name_types)563 OM_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;
599 out:
600 
601     gss_release_oid_set(&junk, &mechs);
602 
603     return ret;
604 }
605 
_gss_spnego_inquire_mechs_for_name(OM_uint32 * minor_status,gss_const_name_t input_name,gss_OID_set * mech_types)606 OM_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 
_gss_spnego_canonicalize_name(OM_uint32 * minor_status,gss_const_name_t input_name,const gss_OID mech_type,gss_name_t * output_name)627 OM_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 
_gss_spnego_duplicate_name(OM_uint32 * minor_status,gss_const_name_t src_name,gss_name_t * dest_name)638 OM_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 
647 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_wrap_iov(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int conf_req_flag,gss_qop_t qop_req,int * conf_state,gss_iov_buffer_desc * iov,int iov_count)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 
668 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_unwrap_iov(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int * conf_state,gss_qop_t * qop_state,gss_iov_buffer_desc * iov,int iov_count)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 
689 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_wrap_iov_length(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int conf_req_flag,gss_qop_t qop_req,int * conf_state,gss_iov_buffer_desc * iov,int iov_count)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
711 OM_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 
_gss_spnego_inquire_sec_context_by_oid(OM_uint32 * minor_status,gss_const_ctx_id_t context_handle,const gss_OID desired_object,gss_buffer_set_t * data_set)736 OM_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 
_gss_spnego_set_sec_context_option(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,const gss_OID desired_object,const gss_buffer_t value)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
_gss_spnego_pseudo_random(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int prf_key,const gss_buffer_t prf_in,ssize_t desired_output_len,gss_buffer_t prf_out)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