1 /* $NetBSD: context_stubs.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
4 * Copyright (c) 2004, PADL Software Pty Ltd.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
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.
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.
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
35 #include "spnego_locl.h"
38 spnego_supported_mechs(OM_uint32
*minor_status
, gss_OID_set
*mechs
)
44 ret
= gss_indicate_mechs(minor_status
, &m
);
45 if (ret
!= GSS_S_COMPLETE
)
48 ret
= gss_create_empty_oid_set(minor_status
, mechs
);
49 if (ret
!= GSS_S_COMPLETE
) {
50 gss_release_oid_set(&junk
, &m
);
54 for (i
= 0; i
< m
->count
; i
++) {
55 if (gss_oid_equal(&m
->elements
[i
], GSS_SPNEGO_MECHANISM
))
58 ret
= gss_add_oid_set_member(minor_status
, &m
->elements
[i
], mechs
);
60 gss_release_oid_set(&junk
, &m
);
61 gss_release_oid_set(&junk
, mechs
);
65 gss_release_oid_set(&junk
, &m
);
71 OM_uint32 GSSAPI_CALLCONV _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
77 gss_ctx_id_t context
;
81 if (context_handle
== GSS_C_NO_CONTEXT
)
82 return GSS_S_NO_CONTEXT
;
84 context
= context_handle
;
85 ctx
= (gssspnego_ctx
)context_handle
;
87 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
89 ret
= gss_process_context_token(minor_status
,
90 ctx
->negotiated_ctx_id
,
92 if (ret
!= GSS_S_COMPLETE
) {
93 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
97 ctx
->negotiated_ctx_id
= GSS_C_NO_CONTEXT
;
99 return _gss_spnego_internal_delete_sec_context(minor_status
,
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
112 if (context_handle
== NULL
|| *context_handle
== GSS_C_NO_CONTEXT
)
113 return GSS_S_NO_CONTEXT
;
115 ctx
= (gssspnego_ctx
)*context_handle
;
117 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
119 return _gss_spnego_internal_delete_sec_context(minor_status
,
124 OM_uint32 GSSAPI_CALLCONV _gss_spnego_context_time
125 (OM_uint32
*minor_status
,
126 const gss_ctx_id_t context_handle
,
133 if (context_handle
== GSS_C_NO_CONTEXT
) {
134 return GSS_S_NO_CONTEXT
;
137 ctx
= (gssspnego_ctx
)context_handle
;
139 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
140 return GSS_S_NO_CONTEXT
;
143 return gss_context_time(minor_status
,
144 ctx
->negotiated_ctx_id
,
148 OM_uint32 GSSAPI_CALLCONV _gss_spnego_get_mic
149 (OM_uint32
*minor_status
,
150 const gss_ctx_id_t context_handle
,
152 const gss_buffer_t message_buffer
,
153 gss_buffer_t message_token
160 if (context_handle
== GSS_C_NO_CONTEXT
) {
161 return GSS_S_NO_CONTEXT
;
164 ctx
= (gssspnego_ctx
)context_handle
;
166 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
167 return GSS_S_NO_CONTEXT
;
170 return gss_get_mic(minor_status
, ctx
->negotiated_ctx_id
,
171 qop_req
, message_buffer
, message_token
);
174 OM_uint32 GSSAPI_CALLCONV _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
186 if (context_handle
== GSS_C_NO_CONTEXT
) {
187 return GSS_S_NO_CONTEXT
;
190 ctx
= (gssspnego_ctx
)context_handle
;
192 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
193 return GSS_S_NO_CONTEXT
;
196 return gss_verify_mic(minor_status
,
197 ctx
->negotiated_ctx_id
,
203 OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap
204 (OM_uint32
* minor_status
,
205 const gss_ctx_id_t context_handle
,
208 const gss_buffer_t input_message_buffer
,
210 gss_buffer_t output_message_buffer
217 if (context_handle
== GSS_C_NO_CONTEXT
) {
218 return GSS_S_NO_CONTEXT
;
221 ctx
= (gssspnego_ctx
)context_handle
;
223 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
224 return GSS_S_NO_CONTEXT
;
227 return gss_wrap(minor_status
,
228 ctx
->negotiated_ctx_id
,
231 input_message_buffer
,
233 output_message_buffer
);
236 OM_uint32 GSSAPI_CALLCONV _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
,
242 gss_qop_t
* qop_state
249 if (context_handle
== GSS_C_NO_CONTEXT
) {
250 return GSS_S_NO_CONTEXT
;
253 ctx
= (gssspnego_ctx
)context_handle
;
255 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
256 return GSS_S_NO_CONTEXT
;
259 return gss_unwrap(minor_status
,
260 ctx
->negotiated_ctx_id
,
261 input_message_buffer
,
262 output_message_buffer
,
267 OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
268 (OM_uint32
*minor_status
,
269 const gss_name_t name1
,
270 const gss_name_t name2
,
274 spnego_name n1
= (spnego_name
)name1
;
275 spnego_name n2
= (spnego_name
)name2
;
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
;
288 return GSS_S_COMPLETE
;
291 OM_uint32 GSSAPI_CALLCONV _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
298 spnego_name name
= (spnego_name
)input_name
;
302 if (name
== NULL
|| name
->mech
== GSS_C_NO_NAME
)
303 return GSS_S_FAILURE
;
305 return gss_display_name(minor_status
, name
->mech
,
306 output_name_buffer
, output_name_type
);
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
321 name
= calloc(1, sizeof(*name
));
323 *minor_status
= ENOMEM
;
324 return GSS_S_FAILURE
;
327 maj_stat
= _gss_copy_oid(minor_status
, name_type
, &name
->type
);
330 return GSS_S_FAILURE
;
333 maj_stat
= _gss_copy_buffer(minor_status
, name_buffer
, &name
->value
);
335 gss_name_t rname
= (gss_name_t
)name
;
336 _gss_spnego_release_name(minor_status
, &rname
);
337 return GSS_S_FAILURE
;
339 name
->mech
= GSS_C_NO_NAME
;
340 *output_name
= (gss_name_t
)name
;
342 return GSS_S_COMPLETE
;
345 OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
346 (OM_uint32
* minor_status
,
347 const gss_name_t input_name
,
348 gss_buffer_t exported_name
354 if (input_name
== GSS_C_NO_NAME
)
355 return GSS_S_BAD_NAME
;
357 name
= (spnego_name
)input_name
;
358 if (name
->mech
== GSS_C_NO_NAME
)
359 return GSS_S_BAD_NAME
;
361 return gss_export_name(minor_status
, name
->mech
, exported_name
);
364 OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
365 (OM_uint32
* minor_status
,
366 gss_name_t
* input_name
371 if (*input_name
!= GSS_C_NO_NAME
) {
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
);
380 *input_name
= GSS_C_NO_NAME
;
382 return GSS_S_COMPLETE
;
385 OM_uint32 GSSAPI_CALLCONV
_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
,
392 OM_uint32
* ctx_flags
,
393 int * locally_initiated
,
398 OM_uint32 maj_stat
, junk
;
399 gss_name_t src_mn
, targ_mn
;
403 if (context_handle
== GSS_C_NO_CONTEXT
)
404 return GSS_S_NO_CONTEXT
;
406 ctx
= (gssspnego_ctx
)context_handle
;
408 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
)
409 return GSS_S_NO_CONTEXT
;
411 maj_stat
= gss_inquire_context(minor_status
,
412 ctx
->negotiated_ctx_id
,
420 if (maj_stat
!= GSS_S_COMPLETE
)
424 spnego_name name
= calloc(1, sizeof(*name
));
428 *src_name
= (gss_name_t
)name
;
430 gss_release_name(&junk
, &src_mn
);
433 spnego_name name
= calloc(1, sizeof(*name
));
435 gss_release_name(minor_status
, src_name
);
438 name
->mech
= targ_mn
;
439 *targ_name
= (gss_name_t
)name
;
441 gss_release_name(&junk
, &targ_mn
);
443 return GSS_S_COMPLETE
;
446 gss_release_name(&junk
, &targ_mn
);
447 gss_release_name(&junk
, &src_mn
);
448 *minor_status
= ENOMEM
;
449 return GSS_S_FAILURE
;
452 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_wrap_size_limit (
453 OM_uint32
* minor_status
,
454 const gss_ctx_id_t context_handle
,
457 OM_uint32 req_output_size
,
458 OM_uint32
* max_input_size
465 if (context_handle
== GSS_C_NO_CONTEXT
) {
466 return GSS_S_NO_CONTEXT
;
469 ctx
= (gssspnego_ctx
)context_handle
;
471 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
472 return GSS_S_NO_CONTEXT
;
475 return gss_wrap_size_limit(minor_status
,
476 ctx
->negotiated_ctx_id
,
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
494 if (context_handle
== NULL
) {
495 return GSS_S_NO_CONTEXT
;
498 ctx
= (gssspnego_ctx
)*context_handle
;
501 return GSS_S_NO_CONTEXT
;
503 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
505 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
506 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
507 return GSS_S_NO_CONTEXT
;
510 ret
= gss_export_sec_context(minor_status
,
511 &ctx
->negotiated_ctx_id
,
513 if (ret
== GSS_S_COMPLETE
) {
514 ret
= _gss_spnego_internal_delete_sec_context(minor_status
,
517 if (ret
== GSS_S_COMPLETE
)
518 return GSS_S_COMPLETE
;
521 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
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
532 OM_uint32 ret
, minor
;
533 gss_ctx_id_t context
;
536 ret
= _gss_spnego_alloc_sec_context(minor_status
, &context
);
537 if (ret
!= GSS_S_COMPLETE
) {
540 ctx
= (gssspnego_ctx
)context
;
542 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
544 ret
= gss_import_sec_context(minor_status
,
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
);
553 /* don't bother filling in the rest of the fields */
555 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
557 *context_handle
= (gss_ctx_id_t
)ctx
;
559 return GSS_S_COMPLETE
;
562 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_inquire_names_for_mech (
563 OM_uint32
* minor_status
,
564 const gss_OID mechanism
,
565 gss_OID_set
* name_types
568 gss_OID_set mechs
, names
, n
;
574 ret
= spnego_supported_mechs(minor_status
, &mechs
);
575 if (ret
!= GSS_S_COMPLETE
)
578 ret
= gss_create_empty_oid_set(minor_status
, &names
);
579 if (ret
!= GSS_S_COMPLETE
)
582 for (i
= 0; i
< mechs
->count
; i
++) {
583 ret
= gss_inquire_names_for_mech(minor_status
,
589 for (j
= 0; j
< n
->count
; j
++)
590 gss_add_oid_set_member(minor_status
,
593 gss_release_oid_set(&junk
, &n
);
596 ret
= GSS_S_COMPLETE
;
600 gss_release_oid_set(&junk
, &mechs
);
605 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_inquire_mechs_for_name (
606 OM_uint32
* minor_status
,
607 const gss_name_t input_name
,
608 gss_OID_set
* mech_types
613 ret
= gss_create_empty_oid_set(minor_status
, mech_types
);
617 ret
= gss_add_oid_set_member(minor_status
,
618 GSS_SPNEGO_MECHANISM
,
621 gss_release_oid_set(&junk
, mech_types
);
626 OM_uint32 GSSAPI_CALLCONV
_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
634 return gss_duplicate_name(minor_status
, input_name
, output_name
);
637 OM_uint32 GSSAPI_CALLCONV
_gss_spnego_duplicate_name (
638 OM_uint32
* minor_status
,
639 const gss_name_t src_name
,
640 gss_name_t
* dest_name
643 return gss_duplicate_name(minor_status
, src_name
, dest_name
);
646 OM_uint32 GSSAPI_CALLCONV
647 _gss_spnego_wrap_iov(OM_uint32
* minor_status
,
648 gss_ctx_id_t context_handle
,
652 gss_iov_buffer_desc
*iov
,
655 gssspnego_ctx ctx
= (gssspnego_ctx
)context_handle
;
659 if (ctx
== NULL
|| ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
)
660 return GSS_S_NO_CONTEXT
;
662 return gss_wrap_iov(minor_status
, ctx
->negotiated_ctx_id
,
663 conf_req_flag
, qop_req
, conf_state
,
667 OM_uint32 GSSAPI_CALLCONV
668 _gss_spnego_unwrap_iov(OM_uint32
*minor_status
,
669 gss_ctx_id_t context_handle
,
671 gss_qop_t
*qop_state
,
672 gss_iov_buffer_desc
*iov
,
675 gssspnego_ctx ctx
= (gssspnego_ctx
)context_handle
;
679 if (ctx
== NULL
|| ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
)
680 return GSS_S_NO_CONTEXT
;
682 return gss_unwrap_iov(minor_status
,
683 ctx
->negotiated_ctx_id
,
684 conf_state
, qop_state
,
688 OM_uint32 GSSAPI_CALLCONV
689 _gss_spnego_wrap_iov_length(OM_uint32
* minor_status
,
690 gss_ctx_id_t context_handle
,
694 gss_iov_buffer_desc
*iov
,
697 gssspnego_ctx ctx
= (gssspnego_ctx
)context_handle
;
701 if (ctx
== NULL
|| ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
)
702 return GSS_S_NO_CONTEXT
;
704 return gss_wrap_iov_length(minor_status
, ctx
->negotiated_ctx_id
,
705 conf_req_flag
, qop_req
, conf_state
,
710 OM_uint32 GSSAPI_CALLCONV _gss_spnego_complete_auth_token
711 (OM_uint32
* minor_status
,
712 const gss_ctx_id_t context_handle
,
713 gss_buffer_t input_message_buffer
)
719 if (context_handle
== GSS_C_NO_CONTEXT
) {
720 return GSS_S_NO_CONTEXT
;
723 ctx
= (gssspnego_ctx
)context_handle
;
725 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
726 return GSS_S_NO_CONTEXT
;
729 return gss_complete_auth_token(minor_status
,
730 ctx
->negotiated_ctx_id
,
731 input_message_buffer
);
735 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_sec_context_by_oid
736 (OM_uint32
* minor_status
,
737 const gss_ctx_id_t context_handle
,
738 const gss_OID desired_object
,
739 gss_buffer_set_t
*data_set
)
745 if (context_handle
== GSS_C_NO_CONTEXT
) {
746 return GSS_S_NO_CONTEXT
;
749 ctx
= (gssspnego_ctx
)context_handle
;
751 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
752 return GSS_S_NO_CONTEXT
;
755 return gss_inquire_sec_context_by_oid(minor_status
,
756 ctx
->negotiated_ctx_id
,
761 OM_uint32 GSSAPI_CALLCONV _gss_spnego_set_sec_context_option
762 (OM_uint32
* minor_status
,
763 gss_ctx_id_t
* context_handle
,
764 const gss_OID desired_object
,
765 const gss_buffer_t value
)
771 if (context_handle
== NULL
|| *context_handle
== GSS_C_NO_CONTEXT
) {
772 return GSS_S_NO_CONTEXT
;
775 ctx
= (gssspnego_ctx
)*context_handle
;
777 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
) {
778 return GSS_S_NO_CONTEXT
;
781 return gss_set_sec_context_option(minor_status
,
782 &ctx
->negotiated_ctx_id
,
788 OM_uint32 GSSAPI_CALLCONV
789 _gss_spnego_pseudo_random(OM_uint32
*minor_status
,
790 gss_ctx_id_t context_handle
,
792 const gss_buffer_t prf_in
,
793 ssize_t desired_output_len
,
794 gss_buffer_t prf_out
)
800 if (context_handle
== GSS_C_NO_CONTEXT
)
801 return GSS_S_NO_CONTEXT
;
803 ctx
= (gssspnego_ctx
)context_handle
;
805 if (ctx
->negotiated_ctx_id
== GSS_C_NO_CONTEXT
)
806 return GSS_S_NO_CONTEXT
;
808 return gss_pseudo_random(minor_status
,
809 ctx
->negotiated_ctx_id
,