void _gssapi_encap_length (size_t data_len, size_t *len, size_t *total_len, const gss_OID mech) { size_t len_len; *len = 1 + 1 + mech->length + data_len; len_len = der_length_len(*len); *total_len = 1 + len_len + *len; }
void * _gssapi_make_mech_header(void *ptr, size_t len, const gss_OID mech) { u_char *p = ptr; int e; size_t len_len, foo; *p++ = 0x60; len_len = der_length_len(len); e = der_put_length (p + len_len - 1, len_len, len, &foo); if(e || foo != len_len) abort (); p += len_len; *p++ = 0x06; *p++ = mech->length; memcpy (p, mech->elements, mech->length); p += mech->length; return p; }
static OM_uint32 spnego_initial (OM_uint32 * minor_status, gssspnego_cred cred, gss_ctx_id_t * context_handle, const gss_name_t target_name, const gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec ) { NegTokenInit ni; int ret; OM_uint32 sub, minor; gss_buffer_desc mech_token; u_char *buf; size_t buf_size, buf_len; gss_buffer_desc data; size_t ni_len; gss_ctx_id_t context; gssspnego_ctx ctx; spnego_name name = (spnego_name)target_name; *minor_status = 0; memset (&ni, 0, sizeof(ni)); *context_handle = GSS_C_NO_CONTEXT; if (target_name == GSS_C_NO_NAME) return GSS_S_BAD_NAME; sub = _gss_spnego_alloc_sec_context(&minor, &context); if (GSS_ERROR(sub)) { *minor_status = minor; return sub; } ctx = (gssspnego_ctx)context; HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); ctx->local = 1; sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name); if (GSS_ERROR(sub)) { *minor_status = minor; _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } sub = _gss_spnego_indicate_mechtypelist(&minor, ctx->target_name, initiator_approved, 0, cred, &ni.mechTypes, &ctx->preferred_mech_type); if (GSS_ERROR(sub)) { *minor_status = minor; _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } ni.reqFlags = NULL; /* * If we have a credential handle, use it to select the mechanism * that we will use */ /* generate optimistic token */ sub = gss_init_sec_context(&minor, (cred != NULL) ? cred->negotiated_cred_id : GSS_C_NO_CREDENTIAL, &ctx->negotiated_ctx_id, ctx->target_name, ctx->preferred_mech_type, req_flags, time_req, input_chan_bindings, input_token, &ctx->negotiated_mech_type, &mech_token, &ctx->mech_flags, &ctx->mech_time_rec); if (GSS_ERROR(sub)) { free_NegTokenInit(&ni); *minor_status = minor; gss_mg_collect_error(ctx->preferred_mech_type, sub, minor); _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } if (sub == GSS_S_COMPLETE) ctx->maybe_open = 1; if (mech_token.length != 0) { ALLOC(ni.mechToken, 1); if (ni.mechToken == NULL) { free_NegTokenInit(&ni); gss_release_buffer(&minor, &mech_token); _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); *minor_status = ENOMEM; return GSS_S_FAILURE; } ni.mechToken->length = mech_token.length; ni.mechToken->data = malloc(mech_token.length); if (ni.mechToken->data == NULL && mech_token.length != 0) { free_NegTokenInit(&ni); gss_release_buffer(&minor, &mech_token); *minor_status = ENOMEM; _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return GSS_S_FAILURE; } memcpy(ni.mechToken->data, mech_token.value, mech_token.length); gss_release_buffer(&minor, &mech_token); } else ni.mechToken = NULL; ni.mechListMIC = NULL; ni_len = length_NegTokenInit(&ni); buf_size = 1 + der_length_len(ni_len) + ni_len; buf = malloc(buf_size); if (buf == NULL) { free_NegTokenInit(&ni); *minor_status = ENOMEM; _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return GSS_S_FAILURE; } ret = encode_NegTokenInit(buf + buf_size - 1, ni_len, &ni, &buf_len); if (ret == 0 && ni_len != buf_len) abort(); if (ret == 0) { size_t tmp; ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, buf_size - buf_len, buf_len, ASN1_C_CONTEXT, CONS, 0, &tmp); if (ret == 0 && tmp + buf_len != buf_size) abort(); } if (ret) { *minor_status = ret; free(buf); free_NegTokenInit(&ni); _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return GSS_S_FAILURE; } data.value = buf; data.length = buf_size; ctx->initiator_mech_types.len = ni.mechTypes.len; ctx->initiator_mech_types.val = ni.mechTypes.val; ni.mechTypes.len = 0; ni.mechTypes.val = NULL; free_NegTokenInit(&ni); sub = gss_encapsulate_token(&data, GSS_SPNEGO_MECHANISM, output_token); free (buf); if (sub) { _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); return sub; } if (actual_mech_type) *actual_mech_type = ctx->negotiated_mech_type; if (ret_flags) *ret_flags = ctx->mech_flags; if (time_rec) *time_rec = ctx->mech_time_rec; HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *context_handle = context; return GSS_S_CONTINUE_NEEDED; }