From: Greg Hudson Date: Thu, 17 Mar 2011 20:02:01 +0000 (+0000) Subject: KDC memory leak in FAST error path X-Git-Tag: krb5-1.10-alpha1~530 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b5d9f6e92ac9291c6f352a2d86b4b0bf9f74fc1f;p=krb5.git KDC memory leak in FAST error path When kdc_fast_handle_error() produces a FAST-encoded error, it puts it into err->e_data and it never gets freed (since in the non-FAST case, err->e_data contains aliased pointers). Fix this by storing the encoded error in an output variable which is placed into the error's e_data by the caller and then freed. ticket: 6884 target_version: 1.9.1 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24722 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 0cc21cec4..32ae12192 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -688,7 +688,7 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, { krb5_error errpkt; krb5_error_code retval; - krb5_data *scratch; + krb5_data *scratch, *fast_edata = NULL; krb5_pa_data **pa = NULL; krb5_typed_data **td = NULL; size_t size; @@ -747,9 +747,12 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, } } retval = kdc_fast_handle_error(kdc_context, rstate, - request, pa, &errpkt); - if (retval == 0) + request, pa, &errpkt, &fast_edata); + if (retval == 0) { + if (fast_edata != NULL) + errpkt.e_data = *fast_edata; retval = krb5_mk_error(kdc_context, &errpkt, scratch); + } free(errpkt.text.data); if (retval) @@ -757,6 +760,7 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, else *response = scratch; krb5_free_pa_data(kdc_context, pa); + krb5_free_data(kdc_context, fast_edata); return retval; } diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 087fc484c..f09ae4711 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -987,7 +987,7 @@ prepare_error_tgs (struct kdc_request_state *state, { krb5_error errpkt; krb5_error_code retval = 0; - krb5_data *scratch; + krb5_data *scratch, *fast_edata = NULL; errpkt.ctime = request->nonce; errpkt.cusec = 0; @@ -1010,15 +1010,20 @@ prepare_error_tgs (struct kdc_request_state *state, return ENOMEM; } errpkt.e_data = *e_data; - if (state) - retval = kdc_fast_handle_error(kdc_context, state, request, NULL, &errpkt); + if (state) { + retval = kdc_fast_handle_error(kdc_context, state, request, NULL, + &errpkt, &fast_edata); + } if (retval) { free(scratch); free(errpkt.text.data); return retval; } + if (fast_edata) + errpkt.e_data = *fast_edata; retval = krb5_mk_error(kdc_context, &errpkt, scratch); free(errpkt.text.data); + krb5_free_data(kdc_context, fast_edata); if (retval) free(scratch); else diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index 860dfcb9a..bc5a77bfa 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -363,14 +363,15 @@ kdc_fast_response_handle_padata(struct kdc_request_state *state, /* * We assume the caller is responsible for passing us an in_padata * sufficient to include in a FAST error. In the FAST case we will - * throw away the e_data in the error (if any); in the non-FAST case - * we will not use the in_padata. + * set *fast_edata_out to the edata to be included in the error; in + * the non-FAST case we will set it to NULL. */ krb5_error_code kdc_fast_handle_error(krb5_context context, struct kdc_request_state *state, krb5_kdc_req *request, - krb5_pa_data **in_padata, krb5_error *err) + krb5_pa_data **in_padata, krb5_error *err, + krb5_data **fast_edata_out) { krb5_error_code retval = 0; krb5_fast_response resp; @@ -380,8 +381,8 @@ kdc_fast_handle_error(krb5_context context, krb5_pa_data *outer_pa[3], *cookie = NULL; krb5_pa_data **inner_pa = NULL; size_t size = 0; - krb5_data *encoded_e_data = NULL; + *fast_edata_out = NULL; memset(outer_pa, 0, sizeof(outer_pa)); if (!state || !state->armor_key) return 0; @@ -429,15 +430,7 @@ kdc_fast_handle_error(krb5_context context, pa[0].contents = (unsigned char *) encrypted_reply->data; outer_pa[0] = &pa[0]; } - retval = encode_krb5_padata_sequence(outer_pa, &encoded_e_data); - if (retval == 0) { - /*process_as holds onto a pointer to the original e_data and frees it*/ - err->e_data = *encoded_e_data; - free(encoded_e_data); /*contents belong to err*/ - encoded_e_data = NULL; - } - if (encoded_e_data) - krb5_free_data(kdc_context, encoded_e_data); + retval = encode_krb5_padata_sequence(outer_pa, fast_edata_out); if (encrypted_reply) krb5_free_data(kdc_context, encrypted_reply); if (encoded_fx_error) diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 9eba0fc8d..2f85b0274 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -354,7 +354,8 @@ krb5_error_code kdc_fast_handle_error (krb5_context context, struct kdc_request_state *state, krb5_kdc_req *request, - krb5_pa_data **in_padata, krb5_error *err); + krb5_pa_data **in_padata, krb5_error *err, + krb5_data **fast_edata_out); krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, krb5_keyblock *existing_key,