static OM_uint32 send_error_token(OM_uint32 *minor_status, krb5_context context, krb5_error_code kret, krb5_principal server, krb5_data *indata, gss_OID mech, gss_buffer_t output_token) { krb5_principal ap_req_server = NULL; krb5_error_code ret; OM_uint32 maj_stat; /* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which tells windows to try again with the corrected timestamp. See [MS-KILE] 2.2.1 KERB-ERROR-DATA */ krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") }; /* build server from request if the acceptor had not selected one */ if (server == NULL && indata) { AP_REQ ap_req; ret = krb5_decode_ap_req(context, indata, &ap_req); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = _krb5_principalname2krb5_principal(context, &ap_req_server, ap_req.ticket.sname, ap_req.ticket.realm); free_AP_REQ(&ap_req); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } server = ap_req_server; } maj_stat = _gsskrb5_error_token(minor_status, mech, context, kret, &e_data, server, output_token); if (ap_req_server) krb5_free_principal(context, ap_req_server); if (maj_stat) { *minor_status = ret; return GSS_S_FAILURE; } *minor_status = 0; return GSS_S_CONTINUE_NEEDED; }
static OM_uint32 iakerb_acceptor_start(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) { krb5_data indata, outdata; gss_buffer_desc idata; krb5_error_code kret; heim_ipc ictx; OM_uint32 ret; if (ctx->messages == NULL) { ctx->messages = krb5_storage_emem(); if (ctx->messages == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } } ret = _gsskrb5_iakerb_parse_header(minor_status, context, ctx, input_token_buffer, &indata); if (ret == GSS_S_DEFECTIVE_TOKEN) { ctx->acceptor_state = gsskrb5_acceptor_start; return GSS_S_COMPLETE; } else if (ret != GSS_S_COMPLETE) return ret; krb5_storage_write(ctx->messages, input_token_buffer->value, input_token_buffer->length); idata.value = indata.data; idata.length = indata.length; heim_assert(ctx->iakerbrealm != NULL, "realm not set by decoder, non OPT value"); if (krb5_realm_is_lkdc(ctx->iakerbrealm)) { kret = heim_ipc_init_context("ANY:org.h5l.kdc", &ictx); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } kret = heim_ipc_call(ictx, &indata, &outdata, NULL); heim_ipc_free_context(ictx); if (kret) { _gsskrb5_error_token(minor_status, ctx->mech, context, kret, NULL, NULL, output_token); *minor_status = kret; return GSS_S_FAILURE; } ret = _gsskrb5_iakerb_make_header(minor_status, context, ctx, ctx->iakerbrealm, &outdata, output_token); heim_ipc_free_data(&outdata); if (ret) return ret; } else { /* XXX dont support non local realms right now */ *minor_status = EINVAL; return GSS_S_FAILURE; } krb5_storage_write(ctx->messages, output_token->value, output_token->length); return GSS_S_CONTINUE_NEEDED; }