2 * SPNEGO wrapper for Kerberos5 GSS-API
3 * kouril@ics.muni.cz, 2003
4 * (mostly based on Heimdal code)
7 #include "spnegokrb5_locl.h"
10 add_mech(MechTypeList *mech_list, gss_OID mech)
15 tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
20 ret = der_get_oid(mech->elements, mech->length,
21 &mech_list->val[mech_list->len], NULL);
31 set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
33 if (req_flags & GSS_C_DELEG_FLAG)
35 if (req_flags & GSS_C_MUTUAL_FLAG)
36 flags->mutualFlag = 1;
37 if (req_flags & GSS_C_REPLAY_FLAG)
38 flags->replayFlag = 1;
39 if (req_flags & GSS_C_SEQUENCE_FLAG)
40 flags->sequenceFlag = 1;
41 if (req_flags & GSS_C_ANON_FLAG)
43 if (req_flags & GSS_C_CONF_FLAG)
45 if (req_flags & GSS_C_INTEG_FLAG)
51 OM_uint32 gss_init_sec_context_spnego(
52 OM_uint32 * minor_status,
53 const gss_cred_id_t initiator_cred_handle,
54 gss_ctx_id_t * context_handle,
55 const gss_name_t target_name,
56 const gss_OID mech_type,
59 const gss_channel_bindings_t input_chan_bindings,
60 const gss_buffer_t input_token,
61 gss_OID * actual_mech_type,
62 gss_buffer_t output_token,
63 OM_uint32 * ret_flags,
66 NegTokenInit token_init;
67 OM_uint32 major_status, minor_status2;
68 gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
69 unsigned char *buf = NULL;
74 memset(&token_init, 0, sizeof(token_init));
76 ALLOC(token_init.mechTypes);
77 if (token_init.mechTypes == NULL) {
78 *minor_status = ENOMEM;
82 ret = add_mech(token_init.mechTypes, GSS_KRB5_MECH);
90 ALLOC(token_init.reqFlags);
91 if (token_init.reqFlags == NULL) {
92 *minor_status = ENOMEM;
96 set_context_flags(req_flags, token_init.reqFlags);
99 major_status = gss_init_sec_context(minor_status,
100 initiator_cred_handle,
112 if (GSS_ERROR(major_status)) {
117 if (krb5_output_token.length > 0) {
118 ALLOC(token_init.mechToken);
119 if (token_init.mechToken == NULL) {
120 *minor_status = ENOMEM;
124 token_init.mechToken->data = krb5_output_token.value;
125 token_init.mechToken->length = krb5_output_token.length;
126 krb5_output_token.length = 0; /* don't free it later */
129 /* The MS implementation of SPNEGO seems to not like the mechListMIC field,
130 * so we omit it (it's optional anyway) */
133 buf = malloc(buf_size);
136 ret = encode_NegTokenInit(buf + buf_size -1,
142 ret = der_put_length_and_tag(buf + buf_size - len - 1,
153 if (ret == ASN1_OVERFLOW) {
157 tmp = realloc (buf, buf_size);
159 *minor_status = ENOMEM;
170 } while (ret == ASN1_OVERFLOW);
172 ret = gssapi_spnego_encapsulate(minor_status,
173 buf + buf_size - len, len,
174 output_token, GSS_SPNEGO_MECH);
179 free_NegTokenInit(&token_init);
180 if (krb5_output_token.length > 0)
181 gss_release_buffer(&minor_status2, &krb5_output_token);