2 * SPNEGO wrapper for Kerberos5 GSS-API
3 * kouril@ics.muni.cz, 2003
6 #include "spnegokrb5_locl.h"
8 #define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
11 add_mech(MechTypeList *mech_list, gss_OID mech)
16 tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
21 ret = der_get_oid(mech->elements, mech->length,
22 &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)
50 OM_uint32 gss_init_sec_context_spnego(
51 OM_uint32 * minor_status,
52 const gss_cred_id_t initiator_cred_handle,
53 gss_ctx_id_t * context_handle,
54 const gss_name_t target_name,
55 const gss_OID mech_type,
58 const gss_channel_bindings_t input_chan_bindings,
59 const gss_buffer_t input_token,
60 gss_OID * actual_mech_type,
61 gss_buffer_t output_token,
62 OM_uint32 * ret_flags,
65 NegTokenInit token_init;
66 OM_uint32 major_status, minor_status2;
67 gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
68 unsigned char *buf = NULL;
73 memset(&token_init, 0, sizeof(token_init));
75 ALLOC(token_init.mechTypes);
76 if (token_init.mechTypes == NULL) {
77 *minor_status = ENOMEM;
81 ret = add_mech(token_init.mechTypes, GSS_KRB5_MECH);
89 ALLOC(token_init.reqFlags);
90 if (token_init.reqFlags == NULL) {
91 *minor_status = ENOMEM;
95 set_context_flags(req_flags, token_init.reqFlags);
98 major_status = gss_init_sec_context(minor_status,
99 initiator_cred_handle,
111 if (GSS_ERROR(major_status)) {
116 if (krb5_output_token.length > 0) {
117 ALLOC(token_init.mechToken);
118 if (token_init.mechToken == NULL) {
119 *minor_status = ENOMEM;
123 token_init.mechToken->data = krb5_output_token.value;
124 token_init.mechToken->length = krb5_output_token.length;
125 krb5_output_token.length = 0; /* don't free it later */
128 /* The MS implementation of SPNEGO seems to not like the mechListMIC field,
129 * so we omit it (it's optional anyway) */
132 buf = malloc(buf_size);
135 ret = encode_NegTokenInit(buf + buf_size -1,
141 ret = der_put_length_and_tag(buf + buf_size - len - 1,
152 if (ret == ASN1_OVERFLOW) {
156 tmp = realloc (buf, buf_size);
158 *minor_status = ENOMEM;
169 } while (ret == ASN1_OVERFLOW);
171 ret = gssapi_spnego_encapsulate(minor_status,
172 buf + buf_size - len, len,
173 output_token, "\x01\x00");
178 free_NegTokenInit(&token_init);
179 if (krb5_output_token.length > 0)
180 gss_release_buffer(&minor_status2, &krb5_output_token);