lib/krb5: add TGS-REQ PA-DATA e.g. FOR_USER also to the outer req

We can't rely on having every KDC support FAST and should still
support S4U2Self against such a KDC.

We also have the order of the PA-DATA elements "corrected",
KRB5_PADATA_TGS_REQ followed by KRB5_PADATA_FX_FAST and
finally KRB5_PADATA_FOR_USER. While the inner PA-DATA
only contains KRB5_PADATA_FOR_USER.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15002

Signed-off-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Stefan Metzmacher
2022-03-07 23:28:12 +01:00
committed by Jeffrey Altman
parent 422419ddde
commit 7b75136113
3 changed files with 131 additions and 44 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);