diff --git a/lib/krb5/fast.c b/lib/krb5/fast.c index bc0f41fcc..c72594cc8 100644 --- a/lib/krb5/fast.c +++ b/lib/krb5/fast.c @@ -461,14 +461,15 @@ _krb5_fast_create_armor(krb5_context context, krb5_error_code _krb5_fast_wrap_req(krb5_context context, struct krb5_fast_state *state, - krb5_data *checksum_data, KDC_REQ *req) { PA_FX_FAST_REQUEST fxreq; krb5_error_code ret; KrbFastReq fastreq; - krb5_data data, aschecksum_data; + krb5_data data, aschecksum_data, tgschecksum_data; + const krb5_data *checksum_data = NULL; size_t size = 0; + krb5_boolean readd_padata_to_outer = FALSE; if (state->flags & KRB5_FAST_DISABLED) { _krb5_debug(context, 10, "fast disabled, not doing any fast wrapping"); @@ -479,6 +480,7 @@ _krb5_fast_wrap_req(krb5_context context, memset(&fastreq, 0, sizeof(fastreq)); krb5_data_zero(&data); krb5_data_zero(&aschecksum_data); + krb5_data_zero(&tgschecksum_data); if (state->armor_crypto == NULL) return check_fast(context, state); @@ -517,8 +519,6 @@ _krb5_fast_wrap_req(krb5_context context, ALLOC(req->req_body.till, 1); *req->req_body.till = 0; - heim_assert(checksum_data == NULL, "checksum data not NULL"); - ASN1_MALLOC_ENCODE(KDC_REQ_BODY, aschecksum_data.data, aschecksum_data.length, @@ -529,14 +529,63 @@ _krb5_fast_wrap_req(krb5_context context, heim_assert(aschecksum_data.length == size, "ASN.1 internal error"); checksum_data = &aschecksum_data; + + if (req->padata) { + ret = copy_METHOD_DATA(req->padata, &fastreq.padata); + free_METHOD_DATA(req->padata); + if (ret) + goto out; + } + } else { + const PA_DATA *tgs_req_ptr = NULL; + int tgs_req_idx = 0; + size_t i; + + heim_assert(req->padata != NULL, "req->padata is NULL"); + + tgs_req_ptr = krb5_find_padata(req->padata->val, + req->padata->len, + KRB5_PADATA_TGS_REQ, + &tgs_req_idx); + heim_assert(tgs_req_ptr != NULL, "KRB5_PADATA_TGS_REQ not found"); + heim_assert(tgs_req_idx == 0, "KRB5_PADATA_TGS_REQ not first"); + + tgschecksum_data.data = tgs_req_ptr->padata_value.data; + tgschecksum_data.length = tgs_req_ptr->padata_value.length; + checksum_data = &tgschecksum_data; + + /* + * Now copy all remaining once to + * the fastreq.padata and clear + * them in the outer req first, + * and remember to readd them later. + */ + readd_padata_to_outer = TRUE; + + for (i = 1; i < req->padata->len; i++) { + PA_DATA *val = &req->padata->val[i]; + + ret = krb5_padata_add(context, + &fastreq.padata, + val->padata_type, + val->padata_value.data, + val->padata_value.length); + if (ret) { + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); + goto out; + } + val->padata_value.data = NULL; + val->padata_value.length = 0; + } + + /* + * Only TGS-REQ remaining + */ + req->padata->len = 1; } - if (req->padata) { - ret = copy_METHOD_DATA(req->padata, &fastreq.padata); - free_METHOD_DATA(req->padata); - if (ret) - goto out; - } else { + if (req->padata == NULL) { ALLOC(req->padata, 1); if (req->padata == NULL) { ret = krb5_enomem(context); @@ -592,6 +641,27 @@ _krb5_fast_wrap_req(krb5_context context, goto out; krb5_data_zero(&data); + if (readd_padata_to_outer) { + size_t i; + + for (i = 0; i < fastreq.padata.len; i++) { + PA_DATA *val = &fastreq.padata.val[i]; + + ret = krb5_padata_add(context, + req->padata, + val->padata_type, + val->padata_value.data, + val->padata_value.length); + if (ret) { + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); + goto out; + } + val->padata_value.data = NULL; + val->padata_value.length = 0; + } + } + out: free_KrbFastReq(&fastreq); free_PA_FX_FAST_REQUEST(&fxreq); diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c index ec7577978..6e48846bc 100644 --- a/lib/krb5/get_cred.c +++ b/lib/krb5/get_cred.c @@ -239,20 +239,6 @@ init_tgs_req (krb5_context context, if (ret) goto fail; } - - if (padata) { - if (t->padata == NULL) { - ALLOC(t->padata, 1); - if (t->padata == NULL) { - ret = krb5_enomem(context); - goto fail; - } - } - - ret = copy_METHOD_DATA(padata, t->padata); - if (ret) - goto fail; - } ret = krb5_auth_con_init(context, &ac); if(ret) @@ -278,14 +264,6 @@ init_tgs_req (krb5_context context, if (ret) goto fail; - if (t->padata == NULL) { - ALLOC(t->padata, 1); - if (t->padata == NULL) { - ret = krb5_enomem(context); - goto fail; - } - } - ret = make_pa_tgs_req(context, &ac, &t->req_body, @@ -295,19 +273,17 @@ init_tgs_req (krb5_context context, if(ret) goto fail; - if (state) { - state->armor_ac = ac; - ret = _krb5_fast_create_armor(context, state, NULL); - state->armor_ac = NULL; - if (ret) - goto fail; + /* + * Add KRB5_PADATA_TGS_REQ first + * followed by all others. + */ - ret = _krb5_fast_wrap_req(context, state, &tgs_req, t); - if (ret) + if (t->padata == NULL) { + ALLOC(t->padata, 1); + if (t->padata == NULL) { + ret = krb5_enomem(context); goto fail; - - /* Its ok if there is no fast in the TGS-REP, older heimdal only support it in the AS code path */ - state->flags &= ~KRB5_FAST_EXPECTED; + } } ret = krb5_padata_add(context, t->padata, KRB5_PADATA_TGS_REQ, @@ -317,6 +293,48 @@ init_tgs_req (krb5_context context, krb5_data_zero(&tgs_req); + { + size_t i; + for (i = 0; i < padata->len; i++) { + const PA_DATA *val1 = &padata->val[i]; + PA_DATA val2; + + ret = copy_PA_DATA(val1, &val2); + if (ret) { + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); + goto fail; + } + + ret = krb5_padata_add(context, t->padata, + val2.padata_type, + val2.padata_value.data, + val2.padata_value.length); + if (ret) { + free_PA_DATA(&val2); + + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); + goto fail; + } + } + } + + if (state) { + state->armor_ac = ac; + ret = _krb5_fast_create_armor(context, state, NULL); + state->armor_ac = NULL; + if (ret) + goto fail; + + ret = _krb5_fast_wrap_req(context, state, t); + if (ret) + goto fail; + + /* Its ok if there is no fast in the TGS-REP, older heimdal only support it in the AS code path */ + state->flags &= ~KRB5_FAST_EXPECTED; + } + ret = krb5_auth_con_getlocalsubkey(context, ac, subkey); if (ret) goto fail; diff --git a/lib/krb5/init_creds_pw.c b/lib/krb5/init_creds_pw.c index 4bab28ad1..7b5142727 100644 --- a/lib/krb5/init_creds_pw.c +++ b/lib/krb5/init_creds_pw.c @@ -3392,7 +3392,6 @@ init_creds_step(krb5_context context, ret = _krb5_fast_wrap_req(context, &ctx->fast_state, - NULL, &req2); krb5_data_free(&checksum_data);