static OM_uint32 gsskrb5_accept_delegated_token (OM_uint32 * minor_status, gsskrb5_ctx ctx, krb5_context context, gss_cred_id_t * delegated_cred_handle ) { krb5_ccache ccache = NULL; krb5_error_code kret; int32_t ac_flags, ret = GSS_S_COMPLETE; *minor_status = 0; /* XXX Create a new delegated_cred_handle? */ if (delegated_cred_handle == NULL) { kret = krb5_cc_default (context, &ccache); } else { *delegated_cred_handle = NULL; kret = krb5_cc_new_unique (context, krb5_cc_type_memory, NULL, &ccache); } if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } kret = krb5_cc_initialize(context, ccache, ctx->source); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; goto out; } krb5_auth_con_removeflags(context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_TIME, &ac_flags); kret = krb5_rd_cred2(context, ctx->auth_context, ccache, &ctx->fwd_data); krb5_auth_con_setflags(context, ctx->auth_context, ac_flags); if (kret) { ctx->flags &= ~GSS_C_DELEG_FLAG; ret = GSS_S_FAILURE; *minor_status = kret; goto out; } if (delegated_cred_handle) { gsskrb5_cred handle; ret = _gsskrb5_krb5_import_cred(minor_status, ccache, NULL, NULL, delegated_cred_handle); if (ret != GSS_S_COMPLETE) goto out; handle = (gsskrb5_cred) *delegated_cred_handle; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; krb5_cc_close(context, ccache); ccache = NULL; } out: if (ccache) { /* Don't destroy the default cred cache */ if (delegated_cred_handle == NULL) krb5_cc_close(context, ccache); else krb5_cc_destroy(context, ccache); } return ret; }
static OM_uint32 acceptor_wait_for_dcestyle(OM_uint32 * minor_status, gsskrb5_ctx ctx, krb5_context context, 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) { OM_uint32 ret; krb5_error_code kret; krb5_data inbuf; int32_t r_seq_number, l_seq_number; /* * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP */ inbuf.length = input_token_buffer->length; inbuf.data = input_token_buffer->value; /* * We need to remeber the old remote seq_number, then check if the * client has replied with our local seq_number, and then reset * the remote seq_number to the old value */ { kret = krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &l_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } kret = krb5_auth_con_getremoteseqnumber(context, ctx->auth_context, &r_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } kret = krb5_auth_con_setremoteseqnumber(context, ctx->auth_context, l_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } } /* * We need to verify the AP_REP, but we need to flag that this is * DCE_STYLE, so don't check the timestamps this time, but put the * flag DO_TIME back afterward. */ { krb5_ap_rep_enc_part *repl; int32_t auth_flags; krb5_auth_con_removeflags(context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_TIME, &auth_flags); kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } krb5_free_ap_rep_enc_part(context, repl); krb5_auth_con_setflags(context, ctx->auth_context, auth_flags); } /* We need to check the liftime */ { OM_uint32 lifetime_rec; ret = _gsskrb5_lifetime_left(minor_status, context, ctx->lifetime, &lifetime_rec); if (ret) { return ret; } if (lifetime_rec == 0) { return GSS_S_CONTEXT_EXPIRED; } if (time_rec) *time_rec = lifetime_rec; } /* We need to give the caller the flags which are in use */ if (ret_flags) *ret_flags = ctx->flags; if (src_name) { kret = krb5_copy_principal(context, ctx->source, (gsskrb5_name*)src_name); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } } /* * After the krb5_rd_rep() the remote and local seq_number should * be the same, because the client just replies the seq_number * from our AP-REP in its AP-REP, but then the client uses the * seq_number from its AP-REQ for GSS_wrap() */ { int32_t tmp_r_seq_number, tmp_l_seq_number; kret = krb5_auth_con_getremoteseqnumber(context, ctx->auth_context, &tmp_r_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } kret = krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &tmp_l_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } /* * Here we check if the client has responsed with our local seq_number, */ if (tmp_r_seq_number != tmp_l_seq_number) { return GSS_S_UNSEQ_TOKEN; } } /* * We need to reset the remote seq_number, because the client will use, * the old one for the GSS_wrap() calls */ { kret = krb5_auth_con_setremoteseqnumber(context, ctx->auth_context, r_seq_number); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } } return gsskrb5_acceptor_ready(minor_status, ctx, context, delegated_cred_handle); }
static OM_uint32 repl_mutual (OM_uint32 * minor_status, gsskrb5_ctx ctx, 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 ) { OM_uint32 ret; krb5_error_code kret; krb5_data indata; krb5_ap_rep_enc_part *repl; int is_cfx = 0; output_token->length = 0; output_token->value = NULL; if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; if (ctx->flags & GSS_C_DCE_STYLE) { /* There is no OID wrapping. */ indata.length = input_token->length; indata.data = input_token->value; } else { ret = _gsskrb5_decapsulate (minor_status, input_token, &indata, "\x02\x00", GSS_KRB5_MECHANISM); if (ret) { /* XXX - Handle AP_ERROR */ return ret; } } kret = krb5_rd_rep (_gsskrb5_context, ctx->auth_context, &indata, &repl); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } krb5_free_ap_rep_enc_part (_gsskrb5_context, repl); _gsskrb5i_is_cfx(ctx, &is_cfx); if (is_cfx) { krb5_keyblock *key = NULL; kret = krb5_auth_con_getremotesubkey(_gsskrb5_context, ctx->auth_context, &key); if (kret == 0 && key != NULL) { ctx->more_flags |= ACCEPTOR_SUBKEY; krb5_free_keyblock (_gsskrb5_context, key); } } *minor_status = 0; if (time_rec) { ret = _gsskrb5_lifetime_left(minor_status, ctx->lifetime, time_rec); } else { ret = GSS_S_COMPLETE; } if (ret_flags) *ret_flags = ctx->flags; if (req_flags & GSS_C_DCE_STYLE) { int32_t con_flags; krb5_data outbuf; /* Do don't do sequence number for the mk-rep */ krb5_auth_con_removeflags(_gsskrb5_context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE, &con_flags); kret = krb5_mk_rep(_gsskrb5_context, ctx->auth_context, &outbuf); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } output_token->length = outbuf.length; output_token->value = outbuf.data; krb5_auth_con_removeflags(_gsskrb5_context, ctx->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE, NULL); } return gsskrb5_initiator_ready(minor_status, ctx); }