/* * 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); }
void KRB5_CALLCONV krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx) { if (ctx == NULL) return; krb5int_fast_free_state(context, ctx->fast_state); krb5_free_creds(context, ctx->in_creds); krb5_cc_close(context, ctx->ccache); krb5_free_principal(context, ctx->req_server); krb5_free_authdata(context, ctx->authdata); krb5_free_creds(context, ctx->cur_tgt); krb5int_free_data_list(context, ctx->realms_seen); krb5_free_principal(context, ctx->tgt_princ); krb5_free_keyblock(context, ctx->subkey); krb5_free_data_contents(context, &ctx->previous_request); krb5int_free_data_list(context, ctx->realm_path); krb5_free_creds(context, ctx->reply_creds); free(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; }
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, krb5_error_code (*pacb_fct)(krb5_context, krb5_keyblock *, krb5_kdc_req *, void *), 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; #ifdef DEBUG_REFERRALS printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off"); krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server); krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server); #endif retval = krb5int_make_tgs_request(context, fast_state, tkt, kdcoptions, address, in_padata, in_cred, pacb_fct, pacb_data, &request_data, ×tamp, &nonce, &subkey); if (retval != 0) goto cleanup; send_again: use_master = 0; retval = krb5_sendto_kdc(context, &request_data, krb5_princ_realm(context, in_cred->server), &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); #ifdef DEBUG_REFERRALS printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error"); #endif 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; }