2 * SPNEGO wrapper for Kerberos5 GSS-API
3 * kouril@ics.muni.cz, 2003
9 #include <spnego_asn1.h>
11 #define ALLOC(X) (X) = calloc(1, sizeof(*(X)))
14 add_mech(MechTypeList *mech_list, oid *mech)
18 tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
22 copy_MechType(mech, mech_list->val + mech_list->len);
28 set_context_flags(OM_uint32 req_flags, ContextFlags *flags)
30 if (req_flags & GSS_C_DELEG_FLAG)
32 if (req_flags & GSS_C_MUTUAL_FLAG)
33 flags->mutualFlag = 1;
34 if (req_flags & GSS_C_REPLAY_FLAG)
35 flags->replayFlag = 1;
36 if (req_flags & GSS_C_SEQUENCE_FLAG)
37 flags->sequenceFlag = 1;
38 if (req_flags & GSS_C_ANON_FLAG)
40 if (req_flags & GSS_C_CONF_FLAG)
42 if (req_flags & GSS_C_INTEG_FLAG)
47 OM_uint32 gss_init_sec_context_spnego(
48 OM_uint32 * minor_status,
49 const gss_cred_id_t initiator_cred_handle,
50 gss_ctx_id_t * context_handle,
51 const gss_name_t target_name,
52 const gss_OID mech_type,
55 const gss_channel_bindings_t input_chan_bindings,
56 const gss_buffer_t input_token,
57 gss_OID * actual_mech_type,
58 gss_buffer_t output_token,
59 OM_uint32 * ret_flags,
62 NegTokenInit token_init;
63 OM_uint32 major_status, minor_status2;
64 gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
65 unsigned char *buf = NULL;
69 unsigned krb5_oid_array[] =
70 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02};
73 memset(&token_init, 0, sizeof(token_init));
75 krb5_oid.length = sizeof(krb5_oid_array);
76 krb5_oid.components = krb5_oid_array;
78 ALLOC(token_init.mechTypes);
79 if (token_init.mechTypes == NULL) {
80 *minor_status = ENOMEM;
84 ret = add_mech(token_init.mechTypes, &krb5_oid);
91 ALLOC(token_init.reqFlags);
92 if (token_init.reqFlags == NULL) {
93 *minor_status = ENOMEM;
97 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) */
132 ASN1_MALLOC_ENCODE(NegTokenInit, buf, buf_size, &token_init, &len, ret);
133 if (ret || buf_size != len) {
134 *minor_status = EINVAL; /* XXX */
139 output_token->value = buf;
140 output_token->length = buf_size;
145 free_NegTokenInit(&token_init);
146 if (krb5_output_token.length > 0)
147 gss_release_buffer(&minor_status2, &krb5_output_token);