KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendto_kdc(krb5_context context, const krb5_data *send_data, const krb5_realm *realm, krb5_data *receive) { return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0); }
static krb5_error_code get_cred_kdc_usage(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, krb5_creds *in_creds, krb5_creds *krbtgt, krb5_creds *out_creds, krb5_key_usage usage) { TGS_REQ req; krb5_data enc; krb5_data resp; krb5_kdc_rep rep; KRB_ERROR error; krb5_error_code ret; unsigned nonce; krb5_keyblock *subkey = NULL; size_t len; Ticket second_ticket; int send_to_kdc_flags = 0; krb5_data_zero(&resp); krb5_data_zero(&enc); krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; if(flags.b.enc_tkt_in_skey){ ret = decode_Ticket(in_creds->second_ticket.data, in_creds->second_ticket.length, &second_ticket, &len); if(ret) return ret; } ret = init_tgs_req (context, id, addresses, flags, flags.b.enc_tkt_in_skey ? &second_ticket : NULL, in_creds, krbtgt, nonce, &subkey, &req, usage); if(flags.b.enc_tkt_in_skey) free_Ticket(&second_ticket); if (ret) goto out; ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); if (ret) goto out; if(enc.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); /* don't free addresses */ req.req_body.addresses = NULL; free_TGS_REQ(&req); /* * Send and receive */ again: ret = krb5_sendto_kdc_flags (context, &enc, &krbtgt->server->name.name_string.val[1], &resp, send_to_kdc_flags); if(ret) goto out; memset(&rep, 0, sizeof(rep)); if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){ ret = krb5_copy_principal(context, in_creds->client, &out_creds->client); if(ret) goto out; ret = krb5_copy_principal(context, in_creds->server, &out_creds->server); if(ret) goto out; /* this should go someplace else */ out_creds->times.endtime = in_creds->times.endtime; ret = _krb5_extract_ticket(context, &rep, out_creds, &krbtgt->session, NULL, KRB5_KU_TGS_REP_ENC_PART_SESSION, &krbtgt->addresses, nonce, TRUE, flags.b.request_anonymous, decrypt_tkt_with_subkey, subkey); krb5_free_kdc_rep(context, &rep); } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); krb5_free_error_contents(context, &error); if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) { send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; krb5_data_free(&resp); goto again; } } else if(resp.data && ((char*)resp.data)[0] == 4) { ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_clear_error_string(context); } else { ret = KRB5KRB_AP_ERR_MSG_TYPE; krb5_clear_error_string(context); } out: krb5_data_free(&resp); krb5_data_free(&enc); if(subkey){ krb5_free_keyblock_contents(context, subkey); free(subkey); } return ret; }