OM_uint32 _gsskrb5_init_sec_context (OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, 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 ) { gsskrb5_cred cred = (gsskrb5_cred)initiator_cred_handle; krb5_const_principal name = (krb5_const_principal)target_name; gsskrb5_ctx ctx; OM_uint32 ret; GSSAPI_KRB5_INIT (); output_token->length = 0; output_token->value = NULL; if (context_handle == NULL) { *minor_status = 0; return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; } if (ret_flags) *ret_flags = 0; if (time_rec) *time_rec = 0; if (target_name == GSS_C_NO_NAME) { if (actual_mech_type) *actual_mech_type = GSS_C_NO_OID; *minor_status = 0; return GSS_S_BAD_NAME; } if (mech_type != GSS_C_NO_OID && !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) return GSS_S_BAD_MECH; if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { OM_uint32 ret; if (*context_handle != GSS_C_NO_CONTEXT) { *minor_status = 0; return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; } ret = _gsskrb5_create_ctx(minor_status, context_handle, input_chan_bindings, INITIATOR_START); if (ret) return ret; } if (*context_handle == GSS_C_NO_CONTEXT) { *minor_status = 0; return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; } ctx = (gsskrb5_ctx) *context_handle; HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); switch (ctx->state) { case INITIATOR_START: ret = init_auth(minor_status, cred, ctx, name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, time_rec); break; case INITIATOR_WAIT_FOR_MUTAL: ret = repl_mutual(minor_status, ctx, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, time_rec); break; case INITIATOR_READY: /* * If we get there, the caller have called * gss_init_sec_context() one time too many. */ *minor_status = 0; ret = GSS_S_BAD_STATUS; break; default: *minor_status = 0; ret = GSS_S_BAD_STATUS; break; } HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); /* destroy context in case of error */ if (GSS_ERROR(ret)) { OM_uint32 min2; _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); } return ret; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token_buffer, const gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle) { krb5_context context; OM_uint32 ret; gsskrb5_ctx ctx; GSSAPI_KRB5_INIT(&context); output_token->length = 0; output_token->value = NULL; if (src_name != NULL) *src_name = NULL; if (mech_type) *mech_type = GSS_KRB5_MECHANISM; if (*context_handle == GSS_C_NO_CONTEXT) { ret = _gsskrb5_create_ctx(minor_status, context_handle, context, input_chan_bindings, ACCEPTOR_START); if (ret) return ret; } ctx = (gsskrb5_ctx)*context_handle; /* * TODO: check the channel_bindings * (above just sets them to krb5 layer) */ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); switch (ctx->state) { case ACCEPTOR_START: ret = gsskrb5_acceptor_start(minor_status, ctx, context, acceptor_cred_handle, input_token_buffer, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle); break; case ACCEPTOR_WAIT_FOR_DCESTYLE: ret = acceptor_wait_for_dcestyle(minor_status, ctx, context, acceptor_cred_handle, input_token_buffer, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle); break; case ACCEPTOR_READY: /* * If we get there, the caller have called * gss_accept_sec_context() one time too many. */ ret = GSS_S_BAD_STATUS; break; default: /* TODO: is this correct here? --metze */ ret = GSS_S_BAD_STATUS; break; } HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (GSS_ERROR(ret)) { OM_uint32 min2; _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); } return ret; }
static OM_uint32 accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token_buffer, const gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle, gss_OID mech, gsskrb5_acceptor_state acceptor_state) { krb5_context context; OM_uint32 ret; gsskrb5_ctx ctx; GSSAPI_KRB5_INIT(&context); output_token->length = 0; output_token->value = NULL; if (src_name != NULL) *src_name = NULL; if (mech_type) *mech_type = mech; if (*context_handle == GSS_C_NO_CONTEXT) { ret = _gsskrb5_create_ctx(minor_status, context_handle, context, input_chan_bindings, mech); if (ret) return ret; /* mark as acceptor */ ctx = (gsskrb5_ctx)*context_handle; ctx->gk5c.flags |= GK5C_ACCEPTOR; ctx->acceptor_state = acceptor_state; } else { ctx = (gsskrb5_ctx)*context_handle; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); do { ret = ctx->acceptor_state(minor_status, ctx, context, acceptor_cred_handle, input_token_buffer, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle); } while (output_token->length == 0 && ret == GSS_S_COMPLETE && ctx->acceptor_state != step_acceptor_completed); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (GSS_ERROR(ret)) { OM_uint32 min2; _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); } return ret; }