From d3a1526a32c8f7881179dc937bf4188462620b81 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Fri, 18 Mar 2011 00:04:22 +0000 Subject: [PATCH] Use a helper function to clarify prepare_error_as() in the KDC git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24725 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/do_as_req.c | 145 +++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 63 deletions(-) diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 32ae12192..6c0921cad 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -115,7 +115,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, krb5_key_data *server_key, *client_key; krb5_keyblock server_keyblock, client_keyblock; krb5_enctype useenctype; - krb5_data e_data; + krb5_data e_data = empty_data(); register int i; krb5_timestamp rtime; char *cname = 0, *sname = 0; @@ -135,7 +135,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, #endif /* APPLE_PKINIT */ ticket_reply.enc_part.ciphertext.data = 0; - e_data.data = 0; server_keyblock.contents = NULL; client_keyblock.contents = NULL; reply.padata = 0; @@ -680,6 +679,61 @@ discard: if (emsg) return errcode; } +/* + * If e_data contains a padata or typed data sequence, produce a padata + * sequence for FAST in *pa_out. If e_data contains neither, set *pa_out to + * NULL and return successfully. + */ +static krb5_error_code +get_error_padata(const krb5_data *e_data, krb5_pa_data ***pa_out) +{ + krb5_error_code retval; + krb5_pa_data **pa = NULL, *pad; + krb5_typed_data **td = NULL; + size_t size, i; + + *pa_out = NULL; + + /* Try decoding e_data as padata. */ + retval = decode_krb5_padata_sequence(e_data, &pa); + if (retval == 0) { + *pa_out = pa; + return 0; + } + + /* Try decoding e_data as typed data. If it doesn't decode, assume there + * is no error padata. */ + retval = decode_krb5_typed_data(e_data, &td); + if (retval == ENOMEM) + return retval; + else if (retval != 0) + return 0; + + /* Convert the typed data to padata. */ + for (size = 0; td[size]; size++); + pa = k5alloc((size + 1) * sizeof(*pa), &retval); + if (pa == NULL) + goto cleanup; + for (i = 0; i < size; i++) { + pad = k5alloc(sizeof(*pad), &retval); + if (pad == NULL) + goto cleanup; + pad->pa_type = td[i]->type; + pad->contents = td[i]->data; + pad->length = td[i]->length; + pa[i] = pad; + td[i]->data = NULL; + } + + *pa_out = pa; + pa = NULL; + +cleanup: + krb5_free_typed_data(kdc_context, td); + krb5_free_pa_data(kdc_context, pa); + return retval; +} + static krb5_error_code prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, int error, krb5_data *e_data, @@ -690,77 +744,42 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, krb5_error_code retval; krb5_data *scratch, *fast_edata = NULL; krb5_pa_data **pa = NULL; - krb5_typed_data **td = NULL; - size_t size; errpkt.ctime = request->nonce; errpkt.cusec = 0; - if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime, - &errpkt.susec))) - return(retval); + retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec); + if (retval) + return retval; errpkt.error = error; errpkt.server = request->server; + errpkt.client = (error == KRB5KDC_ERR_WRONG_REALM) ? canon_client : + request->client; + errpkt.e_data = *e_data; + errpkt.text = string2data((char *)status); - if (error == KRB5KDC_ERR_WRONG_REALM) - errpkt.client = canon_client; - else - errpkt.client = request->client; - errpkt.text.length = strlen(status); - if (!(errpkt.text.data = strdup(status))) - return ENOMEM; + retval = get_error_padata(e_data, &pa); + if (retval) + goto cleanup; + retval = kdc_fast_handle_error(kdc_context, rstate, request, pa, &errpkt, + &fast_edata); + if (retval) + goto cleanup; + if (fast_edata != NULL) + errpkt.e_data = *fast_edata; + scratch = k5alloc(sizeof(*scratch), &retval); + if (scratch == NULL) + goto cleanup; + retval = krb5_mk_error(kdc_context, &errpkt, scratch); + if (retval) + goto cleanup; - if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { - free(errpkt.text.data); - return ENOMEM; - } - if (e_data != NULL&& e_data->data != NULL) { - errpkt.e_data = *e_data; - } else { - errpkt.e_data.length = 0; - errpkt.e_data.data = NULL; - } - /*We need to try and produce a padata sequence for FAST*/ - retval = decode_krb5_padata_sequence(e_data, &pa); - if (retval != 0) { - retval = decode_krb5_typed_data(e_data, &td); - if (retval == 0) { - for (size =0; td[size]; size++); - pa = calloc(size+1, sizeof(*pa)); - if (pa == NULL) - retval = ENOMEM; - else - for (size = 0; td[size]; size++) { - krb5_pa_data *pad = malloc(sizeof(krb5_pa_data )); - if (pad == NULL) { - retval = ENOMEM; - break; - } - pad->pa_type = td[size]->type; - pad->contents = td[size]->data; - pad->length = td[size]->length; - pa[size] = pad; - td[size]->data = NULL; - td[size]->length = 0; - } - krb5_free_typed_data(kdc_context, td); - } - } - retval = kdc_fast_handle_error(kdc_context, rstate, - 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); - } + *response = scratch; + scratch = NULL; - free(errpkt.text.data); - if (retval) - free(scratch); - else - *response = scratch; +cleanup: krb5_free_pa_data(kdc_context, pa); krb5_free_data(kdc_context, fast_edata); - + free(scratch); return retval; } -- 2.26.2