2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "gssapi_locl.h"
38 HEIMDAL_MUTEX gssapi_keytab_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
39 krb5_keytab gssapi_krb5_keytab
;
42 gsskrb5_register_acceptor_identity (const char *identity
)
46 ret
= gssapi_krb5_init();
50 HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex
);
52 if(gssapi_krb5_keytab
!= NULL
) {
53 krb5_kt_close(gssapi_krb5_context
, gssapi_krb5_keytab
);
54 gssapi_krb5_keytab
= NULL
;
56 if (identity
== NULL
) {
57 ret
= krb5_kt_default(gssapi_krb5_context
, &gssapi_krb5_keytab
);
61 asprintf(&p
, "FILE:%s", identity
);
63 HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex
);
66 ret
= krb5_kt_resolve(gssapi_krb5_context
, p
, &gssapi_krb5_keytab
);
69 HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex
);
72 return GSS_S_COMPLETE
;
76 gsskrb5_is_cfx(gss_ctx_id_t context_handle
, int *is_cfx
)
79 int acceptor
= (context_handle
->more_flags
& LOCAL
) == 0;
82 if (context_handle
->auth_context
->local_subkey
)
83 key
= context_handle
->auth_context
->local_subkey
;
85 key
= context_handle
->auth_context
->remote_subkey
;
87 if (context_handle
->auth_context
->remote_subkey
)
88 key
= context_handle
->auth_context
->remote_subkey
;
90 key
= context_handle
->auth_context
->local_subkey
;
93 key
= context_handle
->auth_context
->keyblock
;
98 switch (key
->keytype
) {
99 case ETYPE_DES_CBC_CRC
:
100 case ETYPE_DES_CBC_MD4
:
101 case ETYPE_DES_CBC_MD5
:
102 case ETYPE_DES3_CBC_MD5
:
103 case ETYPE_DES3_CBC_SHA1
:
104 case ETYPE_ARCFOUR_HMAC_MD5
:
105 case ETYPE_ARCFOUR_HMAC_MD5_56
:
109 if ((acceptor
&& context_handle
->auth_context
->local_subkey
) ||
110 (!acceptor
&& context_handle
->auth_context
->remote_subkey
))
111 context_handle
->more_flags
|= ACCEPTOR_SUBKEY
;
118 gsskrb5_accept_delegated_token
119 (OM_uint32
* minor_status
,
120 gss_ctx_id_t
* context_handle
,
123 krb5_principal principal
,
124 gss_cred_id_t
* delegated_cred_handle
127 krb5_ccache ccache
= NULL
;
128 krb5_error_code kret
;
129 int32_t ac_flags
, ret
;
130 gss_cred_id_t handle
= NULL
;
132 if (delegated_cred_handle
== NULL
) {
133 /* XXX Create a new delegated_cred_handle? */
137 kret
= krb5_cc_default (gssapi_krb5_context
, &ccache
);
139 *flags
&= ~GSS_C_DELEG_FLAG
;
144 *delegated_cred_handle
= NULL
;
146 handle
= calloc(1, sizeof(*handle
));
147 if (handle
== NULL
) {
149 *minor_status
= ENOMEM
;
150 krb5_set_error_string(gssapi_krb5_context
, "out of memory");
151 gssapi_krb5_set_error_string();
152 *flags
&= ~GSS_C_DELEG_FLAG
;
155 if ((ret
= gss_duplicate_name(minor_status
, principal
,
156 &handle
->principal
)) != 0) {
157 *flags
&= ~GSS_C_DELEG_FLAG
;
161 kret
= krb5_cc_gen_new (gssapi_krb5_context
,
165 *flags
&= ~GSS_C_DELEG_FLAG
;
169 ccache
= handle
->ccache
;
171 ret
= gss_create_empty_oid_set(minor_status
, &handle
->mechanisms
);
173 *flags
&= ~GSS_C_DELEG_FLAG
;
176 ret
= gss_add_oid_set_member(minor_status
, GSS_KRB5_MECHANISM
,
177 &handle
->mechanisms
);
179 *flags
&= ~GSS_C_DELEG_FLAG
;
184 kret
= krb5_cc_initialize(gssapi_krb5_context
, ccache
, principal
);
186 *flags
&= ~GSS_C_DELEG_FLAG
;
191 krb5_auth_con_removeflags(gssapi_krb5_context
,
192 (*context_handle
)->auth_context
,
193 KRB5_AUTH_CONTEXT_DO_TIME
,
195 kret
= krb5_rd_cred2(gssapi_krb5_context
,
196 (*context_handle
)->auth_context
,
200 gssapi_krb5_set_error_string();
201 krb5_auth_con_setflags(gssapi_krb5_context
,
202 (*context_handle
)->auth_context
,
205 *flags
&= ~GSS_C_DELEG_FLAG
;
207 *minor_status
= kret
;
211 /* if there was some kind of failure, clean up internal structures */
212 if ((*flags
& GSS_C_DELEG_FLAG
) == 0) {
214 if (handle
->principal
)
215 gss_release_name(minor_status
, &handle
->principal
);
216 if (handle
->mechanisms
)
217 gss_release_oid_set(NULL
, &handle
->mechanisms
);
219 krb5_cc_destroy(gssapi_krb5_context
, handle
->ccache
);
224 if (delegated_cred_handle
== NULL
) {
226 krb5_cc_close(gssapi_krb5_context
, ccache
);
229 *delegated_cred_handle
= handle
;
236 gsskrb5_accept_sec_context
237 (OM_uint32
* minor_status
,
238 gss_ctx_id_t
* context_handle
,
239 const gss_cred_id_t acceptor_cred_handle
,
240 const gss_buffer_t input_token_buffer
,
241 const gss_channel_bindings_t input_chan_bindings
,
242 gss_name_t
* src_name
,
244 gss_buffer_t output_token
,
245 OM_uint32
* ret_flags
,
246 OM_uint32
* time_rec
,
247 gss_cred_id_t
* delegated_cred_handle
250 krb5_error_code kret
;
251 OM_uint32 ret
= GSS_S_COMPLETE
;
253 krb5_flags ap_options
;
255 krb5_ticket
*ticket
= NULL
;
256 krb5_keytab keytab
= NULL
;
263 krb5_data_zero (&fwd_data
);
264 output_token
->length
= 0;
265 output_token
->value
= NULL
;
267 if (src_name
!= NULL
)
270 *mech_type
= GSS_KRB5_MECHANISM
;
272 if (*context_handle
== GSS_C_NO_CONTEXT
) {
273 *context_handle
= malloc(sizeof(**context_handle
));
274 if (*context_handle
== GSS_C_NO_CONTEXT
) {
275 *minor_status
= ENOMEM
;
276 return GSS_S_FAILURE
;
280 HEIMDAL_MUTEX_init(&(*context_handle
)->ctx_id_mutex
);
281 (*context_handle
)->auth_context
= NULL
;
282 (*context_handle
)->source
= NULL
;
283 (*context_handle
)->target
= NULL
;
284 (*context_handle
)->flags
= 0;
285 (*context_handle
)->more_flags
= 0;
286 (*context_handle
)->ticket
= NULL
;
287 (*context_handle
)->lifetime
= GSS_C_INDEFINITE
;
288 (*context_handle
)->order
= NULL
;
290 kret
= krb5_auth_con_init (gssapi_krb5_context
,
291 &(*context_handle
)->auth_context
);
294 *minor_status
= kret
;
295 gssapi_krb5_set_error_string ();
299 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
300 && input_chan_bindings
->application_data
.length
==
301 2 * sizeof((*context_handle
)->auth_context
->local_port
)
304 /* Port numbers are expected to be in application_data.value,
305 * initator's port first */
307 krb5_address initiator_addr
, acceptor_addr
;
309 memset(&initiator_addr
, 0, sizeof(initiator_addr
));
310 memset(&acceptor_addr
, 0, sizeof(acceptor_addr
));
312 (*context_handle
)->auth_context
->remote_port
=
313 *(int16_t *) input_chan_bindings
->application_data
.value
;
315 (*context_handle
)->auth_context
->local_port
=
316 *((int16_t *) input_chan_bindings
->application_data
.value
+ 1);
319 kret
= gss_address_to_krb5addr(input_chan_bindings
->acceptor_addrtype
,
320 &input_chan_bindings
->acceptor_address
,
321 (*context_handle
)->auth_context
->local_port
,
324 gssapi_krb5_set_error_string ();
325 ret
= GSS_S_BAD_BINDINGS
;
326 *minor_status
= kret
;
330 kret
= gss_address_to_krb5addr(input_chan_bindings
->initiator_addrtype
,
331 &input_chan_bindings
->initiator_address
,
332 (*context_handle
)->auth_context
->remote_port
,
335 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
336 gssapi_krb5_set_error_string ();
337 ret
= GSS_S_BAD_BINDINGS
;
338 *minor_status
= kret
;
342 kret
= krb5_auth_con_setaddrs(gssapi_krb5_context
,
343 (*context_handle
)->auth_context
,
344 &acceptor_addr
, /* local address */
345 &initiator_addr
); /* remote address */
347 krb5_free_address (gssapi_krb5_context
, &initiator_addr
);
348 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
351 free(input_chan_bindings
->application_data
.value
);
352 input_chan_bindings
->application_data
.value
= NULL
;
353 input_chan_bindings
->application_data
.length
= 0;
357 gssapi_krb5_set_error_string ();
358 ret
= GSS_S_BAD_BINDINGS
;
359 *minor_status
= kret
;
364 krb5_auth_con_addflags(gssapi_krb5_context
,
365 (*context_handle
)->auth_context
,
366 KRB5_AUTH_CONTEXT_DO_SEQUENCE
,
369 ret
= gssapi_krb5_decapsulate (minor_status
,
377 HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex
);
379 if (acceptor_cred_handle
== GSS_C_NO_CREDENTIAL
) {
380 if (gssapi_krb5_keytab
!= NULL
) {
381 keytab
= gssapi_krb5_keytab
;
383 } else if (acceptor_cred_handle
->keytab
!= NULL
) {
384 keytab
= acceptor_cred_handle
->keytab
;
387 kret
= krb5_rd_req (gssapi_krb5_context
,
388 &(*context_handle
)->auth_context
,
390 (acceptor_cred_handle
== GSS_C_NO_CREDENTIAL
) ? NULL
391 : acceptor_cred_handle
->principal
,
396 HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex
);
400 *minor_status
= kret
;
401 gssapi_krb5_set_error_string ();
405 kret
= krb5_copy_principal (gssapi_krb5_context
,
407 &(*context_handle
)->source
);
410 *minor_status
= kret
;
411 gssapi_krb5_set_error_string ();
415 kret
= krb5_copy_principal (gssapi_krb5_context
,
417 &(*context_handle
)->target
);
420 *minor_status
= kret
;
421 gssapi_krb5_set_error_string ();
425 ret
= _gss_DES3_get_mic_compat(minor_status
, *context_handle
);
429 if (src_name
!= NULL
) {
430 kret
= krb5_copy_principal (gssapi_krb5_context
,
435 *minor_status
= kret
;
436 gssapi_krb5_set_error_string ();
442 krb5_authenticator authenticator
;
444 kret
= krb5_auth_con_getauthenticator(gssapi_krb5_context
,
445 (*context_handle
)->auth_context
,
449 *minor_status
= kret
;
450 gssapi_krb5_set_error_string ();
454 ret
= gssapi_krb5_verify_8003_checksum(minor_status
,
456 authenticator
->cksum
,
459 krb5_free_authenticator(gssapi_krb5_context
, &authenticator
);
464 flags
|= GSS_C_TRANS_FLAG
;
468 (*context_handle
)->lifetime
= ticket
->ticket
.endtime
;
469 (*context_handle
)->flags
= flags
;
470 (*context_handle
)->more_flags
|= OPEN
;
473 *mech_type
= GSS_KRB5_MECHANISM
;
476 ret
= gssapi_lifetime_left(minor_status
,
477 (*context_handle
)->lifetime
,
483 gsskrb5_is_cfx(*context_handle
, &is_cfx
);
485 if(flags
& GSS_C_MUTUAL_FLAG
) {
489 || (ap_options
& AP_OPTS_USE_SUBKEY
)) {
490 kret
= krb5_auth_con_addflags(gssapi_krb5_context
,
491 (*context_handle
)->auth_context
,
492 KRB5_AUTH_CONTEXT_USE_SUBKEY
,
494 (*context_handle
)->more_flags
|= ACCEPTOR_SUBKEY
;
497 kret
= krb5_mk_rep (gssapi_krb5_context
,
498 (*context_handle
)->auth_context
,
502 *minor_status
= kret
;
503 gssapi_krb5_set_error_string ();
506 ret
= gssapi_krb5_encapsulate (minor_status
,
511 krb5_data_free (&outbuf
);
516 (*context_handle
)->ticket
= ticket
;
521 krb5_auth_getremoteseqnumber (gssapi_krb5_context
,
522 (*context_handle
)->auth_context
,
524 ret
= _gssapi_msg_order_create(minor_status
,
525 &(*context_handle
)->order
,
526 _gssapi_msg_order_f(flags
),
527 seq_number
, 0, is_cfx
);
531 if ((flags
& GSS_C_MUTUAL_FLAG
) == 0 && _gssapi_msg_order_f(flags
)) {
532 krb5_auth_con_setlocalseqnumber (gssapi_krb5_context
,
533 (*context_handle
)->auth_context
,
538 if (fwd_data
.length
> 0) {
540 if (flags
& GSS_C_DELEG_FLAG
) {
541 ret
= gsskrb5_accept_delegated_token(minor_status
,
546 delegated_cred_handle
);
551 krb5_data_zero(&fwd_data
);
555 return GSS_S_COMPLETE
;
558 if (fwd_data
.length
> 0)
561 krb5_free_ticket (gssapi_krb5_context
, ticket
);
562 krb5_auth_con_free (gssapi_krb5_context
,
563 (*context_handle
)->auth_context
);
564 if((*context_handle
)->source
)
565 krb5_free_principal (gssapi_krb5_context
,
566 (*context_handle
)->source
);
567 if((*context_handle
)->target
)
568 krb5_free_principal (gssapi_krb5_context
,
569 (*context_handle
)->target
);
570 if((*context_handle
)->order
)
571 _gssapi_msg_order_destroy(&(*context_handle
)->order
);
572 HEIMDAL_MUTEX_destroy(&(*context_handle
)->ctx_id_mutex
);
573 free (*context_handle
);
574 if (src_name
!= NULL
) {
575 gss_release_name (&minor
, src_name
);
578 *context_handle
= GSS_C_NO_CONTEXT
;
583 code_NegTokenArg(OM_uint32
*minor_status
,
584 const NegTokenTarg
*targ
,
590 size_t buf_size
, buf_len
;
593 buf
= malloc(buf_size
);
595 *minor_status
= ENOMEM
;
596 return GSS_S_FAILURE
;
600 ret
= encode_NegTokenTarg(buf
+ buf_size
- 1,
606 ret
= der_put_length_and_tag(buf
+ buf_size
- buf_len
- 1,
617 if (ret
== ASN1_OVERFLOW
) {
621 tmp
= realloc (buf
, buf_size
);
623 *minor_status
= ENOMEM
;
625 return GSS_S_FAILURE
;
631 return GSS_S_FAILURE
;
634 } while (ret
== ASN1_OVERFLOW
);
636 data
->data
= buf
+ buf_size
- buf_len
;
637 data
->length
= buf_len
;
639 return GSS_S_COMPLETE
;
643 send_reject (OM_uint32
*minor_status
,
644 gss_buffer_t output_token
)
651 ALLOC(targ
.negResult
, 1);
652 if (targ
.negResult
== NULL
) {
653 *minor_status
= ENOMEM
;
654 return GSS_S_FAILURE
;
656 *(targ
.negResult
) = reject
;
657 targ
.supportedMech
= NULL
;
658 targ
.responseToken
= NULL
;
659 targ
.mechListMIC
= NULL
;
661 ret
= code_NegTokenArg (minor_status
, &targ
, &data
, &buf
);
662 free_NegTokenTarg(&targ
);
667 ret
= _gssapi_encapsulate(minor_status
,
670 GSS_SPNEGO_MECHANISM
);
672 output_token
->value
= malloc(data
.length
);
673 if (output_token
->value
== NULL
) {
674 *minor_status
= ENOMEM
;
677 output_token
->length
= data
.length
;
678 memcpy(output_token
->value
, data
.data
, output_token
->length
);
684 return GSS_S_BAD_MECH
;
688 send_accept (OM_uint32
*minor_status
,
689 OM_uint32 major_status
,
690 gss_buffer_t output_token
,
691 gss_buffer_t mech_token
,
692 gss_ctx_id_t context_handle
,
693 const MechTypeList
*mechtypelist
)
699 gss_buffer_desc mech_buf
, mech_mic_buf
;
700 krb5_boolean require_mic
;
702 memset(&targ
, 0, sizeof(targ
));
703 ALLOC(targ
.negResult
, 1);
704 if (targ
.negResult
== NULL
) {
705 *minor_status
= ENOMEM
;
706 return GSS_S_FAILURE
;
708 *(targ
.negResult
) = accept_completed
;
710 ALLOC(targ
.supportedMech
, 1);
711 if (targ
.supportedMech
== NULL
) {
712 free_NegTokenTarg(&targ
);
713 *minor_status
= ENOMEM
;
714 return GSS_S_FAILURE
;
717 ret
= der_get_oid(GSS_KRB5_MECHANISM
->elements
,
718 GSS_KRB5_MECHANISM
->length
,
722 free_NegTokenTarg(&targ
);
723 *minor_status
= ENOMEM
;
724 return GSS_S_FAILURE
;
727 if (mech_token
!= NULL
&& mech_token
->length
!= 0) {
728 ALLOC(targ
.responseToken
, 1);
729 if (targ
.responseToken
== NULL
) {
730 free_NegTokenTarg(&targ
);
731 *minor_status
= ENOMEM
;
732 return GSS_S_FAILURE
;
734 targ
.responseToken
->length
= mech_token
->length
;
735 targ
.responseToken
->data
= mech_token
->value
;
736 mech_token
->length
= 0;
737 mech_token
->value
= NULL
;
739 targ
.responseToken
= NULL
;
742 ret
= _gss_spnego_require_mechlist_mic(minor_status
, context_handle
,
745 free_NegTokenTarg(&targ
);
749 if (major_status
== GSS_S_COMPLETE
&& require_mic
) {
752 ALLOC(targ
.mechListMIC
, 1);
753 if (targ
.mechListMIC
== NULL
) {
754 free_NegTokenTarg(&targ
);
755 *minor_status
= ENOMEM
;
756 return GSS_S_FAILURE
;
759 ASN1_MALLOC_ENCODE(MechTypeList
, mech_buf
.value
, mech_buf
.length
,
760 mechtypelist
, &buf_len
, ret
);
762 free_NegTokenTarg(&targ
);
765 if (mech_buf
.length
!= buf_len
)
768 ret
= gss_get_mic(minor_status
, context_handle
, 0, &mech_buf
,
770 free (mech_buf
.value
);
772 free_NegTokenTarg(&targ
);
776 targ
.mechListMIC
->length
= mech_mic_buf
.length
;
777 targ
.mechListMIC
->data
= mech_mic_buf
.value
;
779 targ
.mechListMIC
= NULL
;
781 ret
= code_NegTokenArg (minor_status
, &targ
, &data
, &buf
);
782 free_NegTokenTarg(&targ
);
787 ret
= _gssapi_encapsulate(minor_status
,
790 GSS_SPNEGO_MECHANISM
);
792 output_token
->value
= malloc(data
.length
);
793 if (output_token
->value
== NULL
) {
794 *minor_status
= ENOMEM
;
797 output_token
->length
= data
.length
;
798 memcpy(output_token
->value
, data
.data
, output_token
->length
);
804 return GSS_S_COMPLETE
;
808 spnego_accept_sec_context
809 (OM_uint32
* minor_status
,
810 gss_ctx_id_t
* context_handle
,
811 const gss_cred_id_t acceptor_cred_handle
,
812 const gss_buffer_t input_token_buffer
,
813 const gss_channel_bindings_t input_chan_bindings
,
814 gss_name_t
* src_name
,
816 gss_buffer_t output_token
,
817 OM_uint32
* ret_flags
,
818 OM_uint32
* time_rec
,
819 gss_cred_id_t
* delegated_cred_handle
830 output_token
->length
= 0;
831 output_token
->value
= NULL
;
833 ret
= _gssapi_decapsulate (minor_status
,
836 GSS_SPNEGO_MECHANISM
);
840 ret
= der_match_tag_and_length(data
.data
, data
.length
,
841 ASN1_C_CONTEXT
, CONS
, 0, &len
, &taglen
);
845 if(len
> data
.length
- taglen
)
848 ret
= decode_NegTokenInit((const char *)data
.data
+ taglen
, len
,
851 return GSS_S_DEFECTIVE_TOKEN
;
853 if (ni
.mechTypes
== NULL
) {
854 free_NegTokenInit(&ni
);
855 return send_reject (minor_status
, output_token
);
858 for (i
= 0; !found
&& i
< ni
.mechTypes
->len
; ++i
) {
862 ret
= der_put_oid (mechbuf
+ sizeof(mechbuf
) - 1,
864 &ni
.mechTypes
->val
[i
],
867 free_NegTokenInit(&ni
);
868 return GSS_S_DEFECTIVE_TOKEN
;
870 if (mech_len
== GSS_KRB5_MECHANISM
->length
871 && memcmp(GSS_KRB5_MECHANISM
->elements
,
872 mechbuf
+ sizeof(mechbuf
) - mech_len
,
877 gss_buffer_desc ibuf
, obuf
;
878 gss_buffer_t ot
= NULL
;
881 if (ni
.mechToken
!= NULL
) {
882 ibuf
.length
= ni
.mechToken
->length
;
883 ibuf
.value
= ni
.mechToken
->data
;
885 ret
= gsskrb5_accept_sec_context(&minor
,
887 acceptor_cred_handle
,
895 delegated_cred_handle
);
896 if (ret
== GSS_S_COMPLETE
|| ret
== GSS_S_CONTINUE_NEEDED
) {
899 free_NegTokenInit(&ni
);
900 send_reject (minor_status
, output_token
);
904 ret2
= send_accept (minor_status
, ret
, output_token
, ot
,
905 *context_handle
, ni
.mechTypes
);
906 if (ret2
!= GSS_S_COMPLETE
)
909 gss_release_buffer(&minor
, ot
);
910 free_NegTokenInit(&ni
);
913 free_NegTokenInit(&ni
);
914 return send_reject (minor_status
, output_token
);
919 gss_accept_sec_context
920 (OM_uint32
* minor_status
,
921 gss_ctx_id_t
* context_handle
,
922 const gss_cred_id_t acceptor_cred_handle
,
923 const gss_buffer_t input_token_buffer
,
924 const gss_channel_bindings_t input_chan_bindings
,
925 gss_name_t
* src_name
,
927 gss_buffer_t output_token
,
928 OM_uint32
* ret_flags
,
929 OM_uint32
* time_rec
,
930 gss_cred_id_t
* delegated_cred_handle
939 mech_len
= gssapi_krb5_get_mech (input_token_buffer
->value
,
940 input_token_buffer
->length
,
943 return GSS_S_DEFECTIVE_TOKEN
;
944 if (mech_len
== GSS_KRB5_MECHANISM
->length
945 && memcmp(p
, GSS_KRB5_MECHANISM
->elements
, mech_len
) == 0)
946 ret
= gsskrb5_accept_sec_context(minor_status
,
948 acceptor_cred_handle
,
956 delegated_cred_handle
);
957 else if (mech_len
== GSS_SPNEGO_MECHANISM
->length
958 && memcmp(p
, GSS_SPNEGO_MECHANISM
->elements
, mech_len
) == 0)
959 ret
= spnego_accept_sec_context(minor_status
,
961 acceptor_cred_handle
,
969 delegated_cred_handle
);
971 return GSS_S_BAD_MECH
;