/* * Set up the request given by ctx->tgs_in_creds, using ctx->cur_tgt. KDC * options for the requests are determined by ctx->cur_tgt->ticket_flags and * extra_options. */ static krb5_error_code make_request(krb5_context context, krb5_tkt_creds_context ctx, int extra_options) { krb5_error_code code; krb5_data request = empty_data(); ctx->kdcopt = extra_options | FLAGS2OPTS(ctx->cur_tgt->ticket_flags); /* XXX This check belongs in gc_via_tgt.c or nowhere. */ if (!krb5_c_valid_enctype(ctx->cur_tgt->keyblock.enctype)) return KRB5_PROG_ETYPE_NOSUPP; /* Create a new FAST state structure to store this request's armor key. */ krb5int_fast_free_state(context, ctx->fast_state); ctx->fast_state = NULL; code = krb5int_fast_make_state(context, &ctx->fast_state); if (code) return code; krb5_free_keyblock(context, ctx->subkey); ctx->subkey = NULL; code = k5_make_tgs_req(context, ctx->fast_state, ctx->cur_tgt, ctx->kdcopt, ctx->cur_tgt->addresses, NULL, ctx->tgs_in_creds, NULL, NULL, &request, &ctx->timestamp, &ctx->nonce, &ctx->subkey); if (code != 0) return code; krb5_free_data_contents(context, &ctx->previous_request); ctx->previous_request = request; return set_caller_request(context, ctx); }
krb5_error_code krb5_get_cred_via_tkt_ext(krb5_context context, krb5_creds *tkt, krb5_flags kdcoptions, krb5_address *const *address, krb5_pa_data **in_padata, krb5_creds *in_cred, k5_pacb_fn pacb_fn, void *pacb_data, krb5_pa_data ***out_padata, krb5_pa_data ***out_enc_padata, krb5_creds **out_cred, krb5_keyblock **out_subkey) { krb5_error_code retval; krb5_data request_data; krb5_data response_data; krb5_timestamp timestamp; krb5_int32 nonce; krb5_keyblock *subkey = NULL; int tcp_only = 0, use_master = 0; struct krb5int_fast_request_state *fast_state = NULL; request_data.data = NULL; request_data.length = 0; response_data.data = NULL; response_data.length = 0; retval = krb5int_fast_make_state(context, &fast_state); if (retval) goto cleanup; TRACE_GET_CRED_VIA_TKT_EXT(context, in_cred->server, tkt->server, kdcoptions); retval = k5_make_tgs_req(context, fast_state, tkt, kdcoptions, address, in_padata, in_cred, pacb_fn, pacb_data, &request_data, ×tamp, &nonce, &subkey); if (retval != 0) goto cleanup; send_again: use_master = 0; retval = krb5_sendto_kdc(context, &request_data, &in_cred->server->realm, &response_data, &use_master, tcp_only); if (retval == 0) { if (krb5_is_krb_error(&response_data)) { if (!tcp_only) { krb5_error *err_reply; retval = decode_krb5_error(&response_data, &err_reply); if (retval != 0) goto cleanup; retval = krb5int_fast_process_error(context, fast_state, &err_reply, NULL, NULL); if (retval) goto cleanup; if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG) { tcp_only = 1; krb5_free_error(context, err_reply); krb5_free_data_contents(context, &response_data); goto send_again; } krb5_free_error(context, err_reply); } } } else goto cleanup; retval = krb5int_process_tgs_reply(context, fast_state, &response_data, tkt, kdcoptions, address, in_padata, in_cred, timestamp, nonce, subkey, out_padata, out_enc_padata, out_cred); if (retval != 0) goto cleanup; cleanup: krb5int_fast_free_state(context, fast_state); TRACE_GET_CRED_VIA_TKT_EXT_RETURN(context, retval); krb5_free_data_contents(context, &request_data); krb5_free_data_contents(context, &response_data); if (subkey != NULL) { if (retval == 0 && out_subkey != NULL) *out_subkey = subkey; else krb5_free_keyblock(context, subkey); } return retval; }