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"
39 * copy the addresses from `input_chan_bindings' (if any) to
40 * the auth context `ac'
44 set_addresses (krb5_auth_context ac
,
45 const gss_channel_bindings_t input_chan_bindings
)
47 /* Port numbers are expected to be in application_data.value,
48 * initator's port first */
50 krb5_address initiator_addr
, acceptor_addr
;
53 if (input_chan_bindings
== GSS_C_NO_CHANNEL_BINDINGS
54 || input_chan_bindings
->application_data
.length
!=
55 2 * sizeof(ac
->local_port
))
58 memset(&initiator_addr
, 0, sizeof(initiator_addr
));
59 memset(&acceptor_addr
, 0, sizeof(acceptor_addr
));
62 *(int16_t *) input_chan_bindings
->application_data
.value
;
65 *((int16_t *) input_chan_bindings
->application_data
.value
+ 1);
67 kret
= gss_address_to_krb5addr(input_chan_bindings
->acceptor_addrtype
,
68 &input_chan_bindings
->acceptor_address
,
74 kret
= gss_address_to_krb5addr(input_chan_bindings
->initiator_addrtype
,
75 &input_chan_bindings
->initiator_address
,
79 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
83 kret
= krb5_auth_con_setaddrs(gssapi_krb5_context
,
85 &initiator_addr
, /* local address */
86 &acceptor_addr
); /* remote address */
88 krb5_free_address (gssapi_krb5_context
, &initiator_addr
);
89 krb5_free_address (gssapi_krb5_context
, &acceptor_addr
);
92 free(input_chan_bindings
->application_data
.value
);
93 input_chan_bindings
->application_data
.value
= NULL
;
94 input_chan_bindings
->application_data
.length
= 0;
101 * handle delegated creds in init-sec-context
105 do_delegation (krb5_auth_context ac
,
108 const gss_name_t target_name
,
113 krb5_kdc_flags fwd_flags
;
114 krb5_error_code kret
;
116 memset (&creds
, 0, sizeof(creds
));
117 krb5_data_zero (fwd_data
);
119 kret
= krb5_cc_get_principal(gssapi_krb5_context
, ccache
, &creds
.client
);
123 kret
= krb5_build_principal(gssapi_krb5_context
,
125 strlen(creds
.client
->realm
),
133 creds
.times
.endtime
= 0;
136 fwd_flags
.b
.forwarded
= 1;
137 fwd_flags
.b
.forwardable
= 1;
139 if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/
140 target_name
->name
.name_string
.len
< 2)
143 kret
= krb5_get_forwarded_creds(gssapi_krb5_context
,
147 target_name
->name
.name_string
.val
[1],
153 *flags
&= ~GSS_C_DELEG_FLAG
;
155 *flags
|= GSS_C_DELEG_FLAG
;
158 krb5_free_principal(gssapi_krb5_context
, creds
.client
);
160 krb5_free_principal(gssapi_krb5_context
, creds
.server
);
164 * first stage of init-sec-context
169 (OM_uint32
* minor_status
,
170 const gss_cred_id_t initiator_cred_handle
,
171 gss_ctx_id_t
* context_handle
,
172 const gss_name_t target_name
,
173 const gss_OID mech_type
,
176 const gss_channel_bindings_t input_chan_bindings
,
177 const gss_buffer_t input_token
,
178 gss_OID
* actual_mech_type
,
179 gss_buffer_t output_token
,
180 OM_uint32
* ret_flags
,
184 OM_uint32 ret
= GSS_S_FAILURE
;
185 krb5_error_code kret
;
186 krb5_flags ap_options
;
187 krb5_creds this_cred
, *cred
= NULL
;
189 krb5_ccache ccache
= NULL
;
191 krb5_data authenticator
;
193 krb5_enctype enctype
;
195 OM_uint32 lifetime_rec
;
197 krb5_data_zero(&outbuf
);
198 krb5_data_zero(&fwd_data
);
202 *context_handle
= malloc(sizeof(**context_handle
));
203 if (*context_handle
== NULL
) {
204 *minor_status
= ENOMEM
;
205 return GSS_S_FAILURE
;
208 (*context_handle
)->auth_context
= NULL
;
209 (*context_handle
)->source
= NULL
;
210 (*context_handle
)->target
= NULL
;
211 (*context_handle
)->flags
= 0;
212 (*context_handle
)->more_flags
= 0;
213 (*context_handle
)->ticket
= NULL
;
214 (*context_handle
)->lifetime
= GSS_C_INDEFINITE
;
215 (*context_handle
)->order
= NULL
;
216 HEIMDAL_MUTEX_init(&(*context_handle
)->ctx_id_mutex
);
218 kret
= krb5_auth_con_init (gssapi_krb5_context
,
219 &(*context_handle
)->auth_context
);
221 gssapi_krb5_set_error_string ();
222 *minor_status
= kret
;
227 kret
= set_addresses ((*context_handle
)->auth_context
,
228 input_chan_bindings
);
230 *minor_status
= kret
;
231 ret
= GSS_S_BAD_BINDINGS
;
235 krb5_auth_con_addflags(gssapi_krb5_context
,
236 (*context_handle
)->auth_context
,
237 KRB5_AUTH_CONTEXT_DO_SEQUENCE
|
238 KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED
,
241 if (actual_mech_type
)
242 *actual_mech_type
= GSS_KRB5_MECHANISM
;
244 if (initiator_cred_handle
== GSS_C_NO_CREDENTIAL
) {
245 kret
= krb5_cc_default (gssapi_krb5_context
, &ccache
);
247 gssapi_krb5_set_error_string ();
248 *minor_status
= kret
;
253 ccache
= initiator_cred_handle
->ccache
;
255 kret
= krb5_cc_get_principal (gssapi_krb5_context
,
257 &(*context_handle
)->source
);
259 gssapi_krb5_set_error_string ();
260 *minor_status
= kret
;
265 kret
= krb5_copy_principal (gssapi_krb5_context
,
267 &(*context_handle
)->target
);
269 gssapi_krb5_set_error_string ();
270 *minor_status
= kret
;
275 ret
= _gss_DES3_get_mic_compat(minor_status
, *context_handle
);
280 memset(&this_cred
, 0, sizeof(this_cred
));
281 this_cred
.client
= (*context_handle
)->source
;
282 this_cred
.server
= (*context_handle
)->target
;
283 if (time_req
&& time_req
!= GSS_C_INDEFINITE
) {
286 krb5_timeofday (gssapi_krb5_context
, &ts
);
287 this_cred
.times
.endtime
= ts
+ time_req
;
289 this_cred
.times
.endtime
= 0;
290 this_cred
.session
.keytype
= KEYTYPE_NULL
;
292 kret
= krb5_get_credentials (gssapi_krb5_context
,
299 gssapi_krb5_set_error_string ();
300 *minor_status
= kret
;
305 (*context_handle
)->lifetime
= cred
->times
.endtime
;
307 ret
= gssapi_lifetime_left(minor_status
,
308 (*context_handle
)->lifetime
,
314 if (lifetime_rec
== 0) {
316 ret
= GSS_S_CONTEXT_EXPIRED
;
320 krb5_auth_con_setkey(gssapi_krb5_context
,
321 (*context_handle
)->auth_context
,
324 kret
= krb5_auth_con_generatelocalsubkey(gssapi_krb5_context
,
325 (*context_handle
)->auth_context
,
328 gssapi_krb5_set_error_string ();
329 *minor_status
= kret
;
335 * If the realm policy approves a delegation, lets check local
336 * policy if the credentials should be delegated, defafult to
339 if (cred
->flags
.b
.ok_as_delegate
) {
340 krb5_boolean delegate
= FALSE
;
342 _gss_check_compat(NULL
, target_name
, "ok-as-delegate",
344 krb5_appdefault_boolean(gssapi_krb5_context
,
345 "gssapi", target_name
->realm
,
346 "ok-as-delegate", delegate
, &delegate
);
348 req_flags
|= GSS_C_DELEG_FLAG
;
353 if (req_flags
& GSS_C_DELEG_FLAG
)
354 do_delegation ((*context_handle
)->auth_context
,
355 ccache
, cred
, target_name
, &fwd_data
, &flags
);
357 if (req_flags
& GSS_C_MUTUAL_FLAG
) {
358 flags
|= GSS_C_MUTUAL_FLAG
;
359 ap_options
|= AP_OPTS_MUTUAL_REQUIRED
;
362 if (req_flags
& GSS_C_REPLAY_FLAG
)
363 flags
|= GSS_C_REPLAY_FLAG
;
364 if (req_flags
& GSS_C_SEQUENCE_FLAG
)
365 flags
|= GSS_C_SEQUENCE_FLAG
;
366 if (req_flags
& GSS_C_ANON_FLAG
)
368 flags
|= GSS_C_CONF_FLAG
;
369 flags
|= GSS_C_INTEG_FLAG
;
370 flags
|= GSS_C_TRANS_FLAG
;
374 (*context_handle
)->flags
= flags
;
375 (*context_handle
)->more_flags
|= LOCAL
;
377 ret
= gssapi_krb5_create_8003_checksum (minor_status
,
382 krb5_data_free (&fwd_data
);
386 enctype
= (*context_handle
)->auth_context
->keyblock
->keytype
;
388 kret
= krb5_build_authenticator (gssapi_krb5_context
,
389 (*context_handle
)->auth_context
,
395 KRB5_KU_AP_REQ_AUTH
);
398 gssapi_krb5_set_error_string ();
399 *minor_status
= kret
;
404 kret
= krb5_build_ap_req (gssapi_krb5_context
,
412 gssapi_krb5_set_error_string ();
413 *minor_status
= kret
;
418 ret
= gssapi_krb5_encapsulate (minor_status
, &outbuf
, output_token
,
419 "\x01\x00", GSS_KRB5_MECHANISM
);
423 krb5_data_free (&outbuf
);
424 krb5_free_creds(gssapi_krb5_context
, cred
);
425 free_Checksum(&cksum
);
426 if (initiator_cred_handle
== GSS_C_NO_CREDENTIAL
)
427 krb5_cc_close(gssapi_krb5_context
, ccache
);
429 if (flags
& GSS_C_MUTUAL_FLAG
) {
430 return GSS_S_CONTINUE_NEEDED
;
435 krb5_auth_getremoteseqnumber (gssapi_krb5_context
,
436 (*context_handle
)->auth_context
,
439 gsskrb5_is_cfx(*context_handle
, &is_cfx
);
441 ret
= _gssapi_msg_order_create(minor_status
,
442 &(*context_handle
)->order
,
443 _gssapi_msg_order_f(flags
),
444 seq_number
, 0, is_cfx
);
449 *time_rec
= lifetime_rec
;
451 (*context_handle
)->more_flags
|= OPEN
;
452 return GSS_S_COMPLETE
;
456 krb5_auth_con_free (gssapi_krb5_context
,
457 (*context_handle
)->auth_context
);
458 krb5_data_free (&outbuf
);
460 krb5_free_creds(gssapi_krb5_context
, cred
);
461 if (ccache
&& initiator_cred_handle
== GSS_C_NO_CREDENTIAL
)
462 krb5_cc_close(gssapi_krb5_context
, ccache
);
463 if((*context_handle
)->source
)
464 krb5_free_principal (gssapi_krb5_context
,
465 (*context_handle
)->source
);
466 if((*context_handle
)->target
)
467 krb5_free_principal (gssapi_krb5_context
,
468 (*context_handle
)->target
);
469 if((*context_handle
)->order
)
470 _gssapi_msg_order_destroy(&(*context_handle
)->order
);
471 HEIMDAL_MUTEX_destroy(&(*context_handle
)->ctx_id_mutex
);
472 free (*context_handle
);
473 *context_handle
= GSS_C_NO_CONTEXT
;
479 (OM_uint32
* minor_status
,
480 const gss_cred_id_t initiator_cred_handle
,
481 gss_ctx_id_t
* context_handle
,
482 const gss_name_t target_name
,
483 const gss_OID mech_type
,
486 const gss_channel_bindings_t input_chan_bindings
,
487 const gss_buffer_t input_token
,
488 gss_OID
* actual_mech_type
,
489 gss_buffer_t output_token
,
490 OM_uint32
* ret_flags
,
494 OM_uint32 ret
, seq_number
;
495 krb5_error_code kret
;
497 krb5_ap_rep_enc_part
*repl
;
500 output_token
->length
= 0;
501 output_token
->value
= NULL
;
503 HEIMDAL_MUTEX_lock(&(*context_handle
)->ctx_id_mutex
);
505 if (actual_mech_type
)
506 *actual_mech_type
= GSS_KRB5_MECHANISM
;
508 ret
= gssapi_krb5_decapsulate (minor_status
, input_token
, &indata
,
509 "\x02\x00", GSS_KRB5_MECHANISM
);
511 HEIMDAL_MUTEX_unlock(&(*context_handle
)->ctx_id_mutex
);
512 /* XXX - Handle AP_ERROR */
516 kret
= krb5_rd_rep (gssapi_krb5_context
,
517 (*context_handle
)->auth_context
,
521 HEIMDAL_MUTEX_unlock(&(*context_handle
)->ctx_id_mutex
);
522 gssapi_krb5_set_error_string ();
523 *minor_status
= kret
;
524 return GSS_S_FAILURE
;
526 krb5_free_ap_rep_enc_part (gssapi_krb5_context
,
529 krb5_auth_getremoteseqnumber (gssapi_krb5_context
,
530 (*context_handle
)->auth_context
,
533 gsskrb5_is_cfx(*context_handle
, &is_cfx
);
535 ret
= _gssapi_msg_order_create(minor_status
,
536 &(*context_handle
)->order
,
537 _gssapi_msg_order_f((*context_handle
)->flags
),
538 seq_number
, 0, is_cfx
);
540 HEIMDAL_MUTEX_unlock(&(*context_handle
)->ctx_id_mutex
);
544 (*context_handle
)->more_flags
|= OPEN
;
548 ret
= gssapi_lifetime_left(minor_status
,
549 (*context_handle
)->lifetime
,
552 ret
= GSS_S_COMPLETE
;
555 *ret_flags
= (*context_handle
)->flags
;
556 HEIMDAL_MUTEX_unlock(&(*context_handle
)->ctx_id_mutex
);
562 gsskrb5_init_sec_context
563 (OM_uint32
* minor_status
,
564 const gss_cred_id_t initiator_cred_handle
,
565 gss_ctx_id_t
* context_handle
,
566 const gss_name_t target_name
,
567 const gss_OID mech_type
,
570 const gss_channel_bindings_t input_chan_bindings
,
571 const gss_buffer_t input_token
,
572 gss_OID
* actual_mech_type
,
573 gss_buffer_t output_token
,
574 OM_uint32
* ret_flags
,
578 if (input_token
== GSS_C_NO_BUFFER
|| input_token
->length
== 0)
579 return init_auth (minor_status
,
580 initiator_cred_handle
,
593 return repl_mutual(minor_status
,
594 initiator_cred_handle
,
610 (OM_uint32
* minor_status
,
611 const gss_cred_id_t initiator_cred_handle
,
612 gss_ctx_id_t
* context_handle
,
613 const gss_name_t target_name
,
614 const gss_OID mech_type
,
617 const gss_channel_bindings_t input_chan_bindings
,
618 const gss_buffer_t input_token
,
619 gss_OID
* actual_mech_type
,
620 gss_buffer_t output_token
,
621 OM_uint32
* ret_flags
,
630 gss_buffer_desc sub_token
;
634 krb5_boolean require_mic
;
636 output_token
->length
= 0;
637 output_token
->value
= NULL
;
640 * SPNEGO doesn't include gss wrapping on SubsequentContextToken
641 * like the Kerberos 5 mech does. But lets check for it anyway.
644 mech_len
= gssapi_krb5_get_mech (input_token
->value
,
649 indata
.data
= input_token
->value
;
650 indata
.length
= input_token
->length
;
651 } else if (mech_len
== GSS_KRB5_MECHANISM
->length
652 && memcmp(GSS_KRB5_MECHANISM
->elements
, p
, mech_len
) == 0)
653 return gsskrb5_init_sec_context (minor_status
,
654 initiator_cred_handle
,
666 else if (mech_len
== GSS_SPNEGO_MECHANISM
->length
667 && memcmp(GSS_SPNEGO_MECHANISM
->elements
, p
, mech_len
) == 0){
668 ret
= _gssapi_decapsulate (minor_status
,
671 GSS_SPNEGO_MECHANISM
);
675 return GSS_S_BAD_MECH
;
677 ret
= der_match_tag_and_length((const char *)indata
.data
,
679 ASN1_C_CONTEXT
, CONS
, 1, &len
, &taglen
);
683 if(len
> indata
.length
- taglen
)
686 ret
= decode_NegTokenTarg((const char *)indata
.data
+ taglen
,
689 *minor_status
= ENOMEM
;
690 return GSS_S_FAILURE
;
693 if (targ
.negResult
== NULL
694 || *(targ
.negResult
) == reject
695 || targ
.supportedMech
== NULL
) {
696 free_NegTokenTarg(&targ
);
697 return GSS_S_BAD_MECH
;
700 ret
= der_put_oid(oidbuf
+ sizeof(oidbuf
) - 1,
704 if (ret
|| oidlen
!= GSS_KRB5_MECHANISM
->length
705 || memcmp(oidbuf
+ sizeof(oidbuf
) - oidlen
,
706 GSS_KRB5_MECHANISM
->elements
,
708 free_NegTokenTarg(&targ
);
709 return GSS_S_BAD_MECH
;
712 if (targ
.responseToken
!= NULL
) {
713 sub_token
.length
= targ
.responseToken
->length
;
714 sub_token
.value
= targ
.responseToken
->data
;
716 sub_token
.length
= 0;
717 sub_token
.value
= NULL
;
720 ret
= gsskrb5_init_sec_context(minor_status
,
721 initiator_cred_handle
,
734 free_NegTokenTarg(&targ
);
739 * Verify the mechListMIC if CFX was used; or if local policy
742 ret
= _gss_spnego_require_mechlist_mic(minor_status
, *context_handle
,
745 free_NegTokenTarg(&targ
);
750 MechTypeList mechlist
;
753 gss_buffer_desc mic_buf
, mech_buf
;
755 if (targ
.mechListMIC
== NULL
) {
756 free_NegTokenTarg(&targ
);
758 return GSS_S_BAD_MIC
;
764 ret
= der_get_oid(GSS_KRB5_MECHANISM
->elements
,
765 GSS_KRB5_MECHANISM
->length
,
769 free_NegTokenTarg(&targ
);
770 *minor_status
= ENOMEM
;
771 return GSS_S_FAILURE
;
774 ASN1_MALLOC_ENCODE(MechTypeList
, mech_buf
.value
, mech_buf
.length
,
775 &mechlist
, &buf_len
, ret
);
777 free_NegTokenTarg(&targ
);
779 *minor_status
= ENOMEM
;
780 return GSS_S_FAILURE
;
782 if (mech_buf
.length
!= buf_len
)
785 mic_buf
.length
= targ
.mechListMIC
->length
;
786 mic_buf
.value
= targ
.mechListMIC
->data
;
788 ret
= gss_verify_mic(minor_status
, *context_handle
,
789 &mech_buf
, &mic_buf
, NULL
);
790 free(mech_buf
.value
);
793 free_NegTokenTarg(&targ
);
799 (OM_uint32
* minor_status
,
800 const gss_cred_id_t initiator_cred_handle
,
801 gss_ctx_id_t
* context_handle
,
802 const gss_name_t target_name
,
803 const gss_OID mech_type
,
806 const gss_channel_bindings_t input_chan_bindings
,
807 const gss_buffer_t input_token
,
808 gss_OID
* actual_mech_type
,
809 gss_buffer_t output_token
,
810 OM_uint32
* ret_flags
,
816 OM_uint32 sub
, minor
;
817 gss_buffer_desc mech_token
;
819 size_t buf_size
, buf_len
;
825 memset (&ni
, 0, sizeof(ni
));
827 ALLOC(ni
.mechTypes
, 1);
828 if (ni
.mechTypes
== NULL
) {
829 *minor_status
= ENOMEM
;
830 return GSS_S_FAILURE
;
832 ALLOC_SEQ(ni
.mechTypes
, 1);
833 if (ni
.mechTypes
->val
== NULL
) {
834 free_NegTokenInit(&ni
);
835 *minor_status
= ENOMEM
;
836 return GSS_S_FAILURE
;
838 ret
= der_get_oid(GSS_KRB5_MECHANISM
->elements
,
839 GSS_KRB5_MECHANISM
->length
,
840 &ni
.mechTypes
->val
[0],
843 free_NegTokenInit(&ni
);
844 *minor_status
= ENOMEM
;
845 return GSS_S_FAILURE
;
849 ALLOC(ni
.reqFlags
, 1);
850 if (ni
.reqFlags
== NULL
) {
851 free_NegTokenInit(&ni
);
852 *minor_status
= ENOMEM
;
853 return GSS_S_FAILURE
;
855 ni
.reqFlags
->delegFlag
= req_flags
& GSS_C_DELEG_FLAG
;
856 ni
.reqFlags
->mutualFlag
= req_flags
& GSS_C_MUTUAL_FLAG
;
857 ni
.reqFlags
->replayFlag
= req_flags
& GSS_C_REPLAY_FLAG
;
858 ni
.reqFlags
->sequenceFlag
= req_flags
& GSS_C_SEQUENCE_FLAG
;
859 ni
.reqFlags
->anonFlag
= req_flags
& GSS_C_ANON_FLAG
;
860 ni
.reqFlags
->confFlag
= req_flags
& GSS_C_CONF_FLAG
;
861 ni
.reqFlags
->integFlag
= req_flags
& GSS_C_INTEG_FLAG
;
866 sub
= gsskrb5_init_sec_context(&minor
,
867 initiator_cred_handle
,
879 if (GSS_ERROR(sub
)) {
880 free_NegTokenInit(&ni
);
883 if (mech_token
.length
!= 0) {
884 ALLOC(ni
.mechToken
, 1);
885 if (ni
.mechToken
== NULL
) {
886 free_NegTokenInit(&ni
);
887 gss_release_buffer(&minor
, &mech_token
);
888 *minor_status
= ENOMEM
;
889 return GSS_S_FAILURE
;
891 ni
.mechToken
->length
= mech_token
.length
;
892 ni
.mechToken
->data
= malloc(mech_token
.length
);
893 if (ni
.mechToken
->data
== NULL
&& mech_token
.length
!= 0) {
894 free_NegTokenInit(&ni
);
895 gss_release_buffer(&minor
, &mech_token
);
896 *minor_status
= ENOMEM
;
897 return GSS_S_FAILURE
;
899 memcpy(ni
.mechToken
->data
, mech_token
.value
, mech_token
.length
);
900 gss_release_buffer(&minor
, &mech_token
);
904 /* XXX ignore mech list mic for now */
905 ni
.mechListMIC
= NULL
;
913 nt
.element
= choice_NegotiationToken_negTokenInit
;
914 nt
.u
.negTokenInit
= ni
;
916 ASN1_MALLOC_ENCODE(NegotiationToken
, buf
, buf_size
,
918 if (buf_size
!= buf_len
)
922 ni_len
= length_NegTokenInit(&ni
);
923 buf_size
= 1 + length_len(ni_len
) + ni_len
;
925 buf
= malloc(buf_size
);
927 free_NegTokenInit(&ni
);
928 *minor_status
= ENOMEM
;
929 return GSS_S_FAILURE
;
932 ret
= encode_NegTokenInit(buf
+ buf_size
- 1,
935 if (ret
== 0 && ni_len
!= buf_len
)
941 ret
= der_put_length_and_tag(buf
+ buf_size
- buf_len
- 1,
948 if (ret
== 0 && tmp
+ buf_len
!= buf_size
)
954 free_NegTokenInit(&ni
);
955 return GSS_S_FAILURE
;
960 data
.length
= buf_size
;
962 free_NegTokenInit(&ni
);
966 sub
= _gssapi_encapsulate(minor_status
,
969 GSS_SPNEGO_MECHANISM
);
975 return GSS_S_CONTINUE_NEEDED
;
979 spnego_init_sec_context
980 (OM_uint32
* minor_status
,
981 const gss_cred_id_t initiator_cred_handle
,
982 gss_ctx_id_t
* context_handle
,
983 const gss_name_t target_name
,
984 const gss_OID mech_type
,
987 const gss_channel_bindings_t input_chan_bindings
,
988 const gss_buffer_t input_token
,
989 gss_OID
* actual_mech_type
,
990 gss_buffer_t output_token
,
991 OM_uint32
* ret_flags
,
995 if (input_token
== GSS_C_NO_BUFFER
|| input_token
->length
== 0)
996 return spnego_initial (minor_status
,
997 initiator_cred_handle
,
1003 input_chan_bindings
,
1010 return spnego_reply (minor_status
,
1011 initiator_cred_handle
,
1017 input_chan_bindings
,
1026 * gss_init_sec_context
1029 OM_uint32 gss_init_sec_context
1030 (OM_uint32
* minor_status
,
1031 const gss_cred_id_t initiator_cred_handle
,
1032 gss_ctx_id_t
* context_handle
,
1033 const gss_name_t target_name
,
1034 const gss_OID mech_type
,
1035 OM_uint32 req_flags
,
1037 const gss_channel_bindings_t input_chan_bindings
,
1038 const gss_buffer_t input_token
,
1039 gss_OID
* actual_mech_type
,
1040 gss_buffer_t output_token
,
1041 OM_uint32
* ret_flags
,
1042 OM_uint32
* time_rec
1045 GSSAPI_KRB5_INIT ();
1047 output_token
->length
= 0;
1048 output_token
->value
= NULL
;
1055 if (target_name
== GSS_C_NO_NAME
) {
1056 if (actual_mech_type
)
1057 *actual_mech_type
= GSS_C_NO_OID
;
1059 return GSS_S_BAD_NAME
;
1062 if (mech_type
== GSS_C_NO_OID
||
1063 gss_oid_equal(mech_type
, GSS_KRB5_MECHANISM
))
1064 return gsskrb5_init_sec_context(minor_status
,
1065 initiator_cred_handle
,
1071 input_chan_bindings
,
1077 else if (gss_oid_equal(mech_type
, GSS_SPNEGO_MECHANISM
))
1078 return spnego_init_sec_context (minor_status
,
1079 initiator_cred_handle
,
1085 input_chan_bindings
,
1092 return GSS_S_BAD_MECH
;