OM_uint32 _gsskrb5_process_context_token ( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t token_buffer ) { OM_uint32 ret = GSS_S_FAILURE; gss_buffer_desc empty_buffer; gss_qop_t qop_state; empty_buffer.length = 0; empty_buffer.value = NULL; qop_state = GSS_C_QOP_DEFAULT; ret = _gsskrb5_verify_mic_internal(minor_status, (gsskrb5_ctx)context_handle, token_buffer, &empty_buffer, GSS_C_QOP_DEFAULT, "\x01\x02"); if (ret == GSS_S_COMPLETE) ret = _gsskrb5_delete_sec_context(minor_status, rk_UNCONST(&context_handle), GSS_C_NO_BUFFER); if (ret == GSS_S_COMPLETE) *minor_status = 0; return ret; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_sec_context ( OM_uint32 * minor_status, gss_ctx_id_t * context_handle, gss_buffer_t interprocess_token ) { krb5_context context; const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; krb5_storage *sp; krb5_auth_context ac; OM_uint32 ret = GSS_S_COMPLETE; krb5_data data; gss_buffer_desc buffer; int flags; OM_uint32 minor; krb5_error_code kret; GSSAPI_KRB5_INIT (&context); HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); if (!(ctx->flags & GSS_C_TRANS_FLAG)) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = 0; return GSS_S_UNAVAILABLE; } sp = krb5_storage_emem (); if (sp == NULL) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = ENOMEM; return GSS_S_FAILURE; } ac = ctx->auth_context; /* flagging included fields */ flags = 0; if (ac->local_address) flags |= SC_LOCAL_ADDRESS; if (ac->remote_address) flags |= SC_REMOTE_ADDRESS; if (ac->keyblock) flags |= SC_KEYBLOCK; if (ac->local_subkey) flags |= SC_LOCAL_SUBKEY; if (ac->remote_subkey) flags |= SC_REMOTE_SUBKEY; kret = krb5_store_int32 (sp, flags); if (kret) { *minor_status = kret; goto failure; } /* marshall auth context */ kret = krb5_store_int32 (sp, ac->flags); if (kret) { *minor_status = kret; goto failure; } if (ac->local_address) { kret = krb5_store_address (sp, *ac->local_address); if (kret) { *minor_status = kret; goto failure; } } if (ac->remote_address) { kret = krb5_store_address (sp, *ac->remote_address); if (kret) { *minor_status = kret; goto failure; } } kret = krb5_store_int16 (sp, ac->local_port); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int16 (sp, ac->remote_port); if (kret) { *minor_status = kret; goto failure; } if (ac->keyblock) { kret = krb5_store_keyblock (sp, *ac->keyblock); if (kret) { *minor_status = kret; goto failure; } } if (ac->local_subkey) { kret = krb5_store_keyblock (sp, *ac->local_subkey); if (kret) { *minor_status = kret; goto failure; } } if (ac->remote_subkey) { kret = krb5_store_keyblock (sp, *ac->remote_subkey); if (kret) { *minor_status = kret; goto failure; } } kret = krb5_store_int32 (sp, ac->local_seqnumber); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->remote_seqnumber); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->keytype); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->cksumtype); if (kret) { *minor_status = kret; goto failure; } /* names */ ret = _gsskrb5_export_name (minor_status, (gss_name_t)ctx->source, &buffer); if (ret) goto failure; data.data = buffer.value; data.length = buffer.length; kret = krb5_store_data (sp, data); _gsskrb5_release_buffer (&minor, &buffer); if (kret) { *minor_status = kret; goto failure; } ret = _gsskrb5_export_name (minor_status, (gss_name_t)ctx->target, &buffer); if (ret) goto failure; data.data = buffer.value; data.length = buffer.length; ret = GSS_S_FAILURE; kret = krb5_store_data (sp, data); _gsskrb5_release_buffer (&minor, &buffer); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->flags); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->more_flags); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->lifetime); if (kret) { *minor_status = kret; goto failure; } kret = _gssapi_msg_order_export(sp, ctx->order); if (kret ) { *minor_status = kret; goto failure; } kret = krb5_storage_to_data (sp, &data); krb5_storage_free (sp); if (kret) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = kret; return GSS_S_FAILURE; } interprocess_token->length = data.length; interprocess_token->value = data.data; HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); ret = _gsskrb5_delete_sec_context (minor_status, context_handle, GSS_C_NO_BUFFER); if (ret != GSS_S_COMPLETE) _gsskrb5_release_buffer (NULL, interprocess_token); *minor_status = 0; return ret; failure: HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); krb5_storage_free (sp); 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; }
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; }
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; }