static size_t n_preauth_systems;
static krb5_error_code
-make_etype_info(krb5_context context, krb5_preauthtype pa_type,
+make_etype_info(krb5_context context, krb5_boolean etype_info2,
krb5_principal client, krb5_key_data *client_key,
- krb5_enctype enctype, krb5_pa_data **pa_out);
+ krb5_enctype enctype, krb5_data **der_out);
/* Get all available kdcpreauth vtables and a count of preauth types they
* support. Return an empty list on failure. */
krb5_pa_data ***pa_list)
{
krb5_error_code ret;
- krb5_pa_data *pa;
+ krb5_data *der;
if (rock->client_key == NULL)
return 0;
if (!requires_info2(rock->request)) {
/* Include PA-ETYPE-INFO only for old clients. */
- ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO,
- rock->client->princ, rock->client_key,
- rock->client_keyblock->enctype, &pa);
+ ret = make_etype_info(context, FALSE, rock->client->princ,
+ rock->client_key, rock->client_keyblock->enctype,
+ &der);
if (ret)
return ret;
- /* add_pa_data_element() claims pa on success or failure. */
- ret = add_pa_data_element(pa_list, pa);
+ ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO, der);
+ krb5_free_data(context, der);
if (ret)
return ret;
}
/* Always include PA-ETYPE-INFO2. */
- ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
- rock->client->princ, rock->client_key,
- rock->client_keyblock->enctype, &pa);
+ ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key,
+ rock->client_keyblock->enctype, &der);
if (ret)
return ret;
- /* add_pa_data_element() claims pa on success or failure. */
- return add_pa_data_element(pa_list, pa);
+ ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO2, der);
+ krb5_free_data(context, der);
+ return ret;
}
/* Add PW-SALT entries to pa_list as appropriate for the request and client
krb5_pa_data ***pa_list)
{
krb5_error_code ret;
- krb5_pa_data *pa;
krb5_data *salt = NULL;
krb5_int16 salttype;
if (ret)
return 0;
- /* Steal memory from salt to make the pa-data entry. */
- ret = alloc_pa_data(KRB5_PADATA_PW_SALT, 0, &pa);
- if (ret)
- goto cleanup;
- pa->length = salt->length;
- pa->contents = (uint8_t *)salt->data;
- salt->data = NULL;
-
- /* add_pa_data_element() claims pa on success or failure. */
- ret = add_pa_data_element(pa_list, pa);
-
-cleanup:
+ ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_PW_SALT, salt);
krb5_free_data(context, salt);
return ret;
}
krb5_keyblock kb;
krb5_checksum cksum;
krb5_data d;
- krb5_pa_data *pa;
+ krb5_pa_data *pa = NULL;
char ckbuf[4];
memset(&cksum, 0, sizeof(cksum));
&d, &cksum);
/* Compose a freshness token from the time, krbtgt kvno, and checksum. */
- ret = alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
+ ret = k5_alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
if (ret)
goto cleanup;
store_32_be(now, pa->contents);
store_32_be(kd->key_data_kvno, pa->contents + 4);
memcpy(pa->contents + 8, cksum.contents, cksum.length);
- /* add_pa_data_element() claims pa on success or failure. */
- ret = add_pa_data_element(pa_list, pa);
+ ret = k5_add_pa_data_element(pa_list, &pa);
cleanup:
krb5_free_keyblock_contents(context, &kb);
krb5_free_checksum_contents(context, &cksum);
+ k5_free_pa_data_element(pa);
return ret;
}
if (code == 0) {
if (pa == NULL) {
- ret = alloc_pa_data(state->pa_type, 0, &pa);
+ ret = k5_alloc_pa_data(state->pa_type, 0, &pa);
if (ret)
goto error;
}
- /* add_pa_data_element() claims pa on success or failure. */
- ret = add_pa_data_element(&state->pa_data, pa);
+ ret = k5_add_pa_data_element(&state->pa_data, &pa);
+ k5_free_pa_data_element(pa);
if (ret)
goto error;
}
{
kdc_realm_t *kdc_active_realm = rock->rstate->realm_data;
struct hint_state *state;
- krb5_pa_data *pa;
*e_data_out = NULL;
state->ap = preauth_systems;
/* Add an empty PA-FX-FAST element to advertise FAST support. */
- if (alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa) != 0)
- goto error;
- /* add_pa_data_element() claims pa on success or failure. */
- if (add_pa_data_element(&state->pa_data, pa) != 0)
+ if (k5_add_empty_pa_data(&state->pa_data, KRB5_PADATA_FX_FAST) != 0)
goto error;
if (add_etype_info(kdc_context, rock, &state->pa_data) != 0)
krb5_error_code ret;
krb5_context context = state->context;
krb5_kdcpreauth_rock rock = state->rock;
- krb5_pa_data *pa;
+ krb5_data *der;
/* Only add key information when requesting another preauth round trip. */
if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
KRB5_PADATA_FX_COOKIE) != NULL)
return 0;
- ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
- rock->client->princ, rock->client_key,
- rock->client_keyblock->enctype, &pa);
+ ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key,
+ rock->client_keyblock->enctype, &der);
if (ret)
return ret;
-
- /* add_pa_data_element() claims pa on success or failure. */
- return add_pa_data_element(&state->pa_e_data, pa);
+ ret = k5_add_pa_data_from_data(&state->pa_e_data, KRB5_PADATA_ETYPE_INFO2,
+ der);
+ krb5_free_data(context, der);
+ return ret;
}
/* Release state and respond to the AS-REQ processing code with the result of
goto cleanup;
if (send_pa != NULL) {
- /* add_pa_data_element() claims send_pa on success or failure. */
- retval = add_pa_data_element(&send_pa_list, send_pa);
+ retval = k5_add_pa_data_element(&send_pa_list, &send_pa);
+ k5_free_pa_data_element(send_pa);
if (retval)
goto cleanup;
}
return retval;
}
-/* Create etype-info or etype-info2 padata for client_key with the given
+/* Encode an etype-info or etype-info2 message for client_key with the given
* enctype, using client to compute the salt if necessary. */
static krb5_error_code
-make_etype_info(krb5_context context, krb5_preauthtype pa_type,
+make_etype_info(krb5_context context, krb5_boolean etype_info2,
krb5_principal client, krb5_key_data *client_key,
- krb5_enctype enctype, krb5_pa_data **pa_out)
+ krb5_enctype enctype, krb5_data **der_out)
{
krb5_error_code retval;
krb5_etype_info_entry **entry = NULL;
- krb5_data *der_etype_info = NULL;
- int etype_info2 = (pa_type == KRB5_PADATA_ETYPE_INFO2);
- *pa_out = NULL;
+ *der_out = NULL;
entry = k5calloc(2, sizeof(*entry), &retval);
if (entry == NULL)
goto cleanup;
if (etype_info2)
- retval = encode_krb5_etype_info2(entry, &der_etype_info);
+ retval = encode_krb5_etype_info2(entry, der_out);
else
- retval = encode_krb5_etype_info(entry, &der_etype_info);
- if (retval)
- goto cleanup;
-
- /* Steal the data from der_etype_info to create a pa-data element. */
- retval = alloc_pa_data(pa_type, 0, pa_out);
- if (retval)
- goto cleanup;
- (*pa_out)->contents = (uint8_t *)der_etype_info->data;
- (*pa_out)->length = der_etype_info->length;
- der_etype_info->data = NULL;
+ retval = encode_krb5_etype_info(entry, der_out);
cleanup:
krb5_free_etype_info(context, entry);
- krb5_free_data(context, der_etype_info);
return retval;
}
if (code || tl_data.tl_data_length == 0)
return 0;
- code = alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO, tl_data.tl_data_length,
- &pa);
+ code = k5_alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO,
+ tl_data.tl_data_length, &pa);
if (code)
return code;
memcpy(pa->contents, tl_data.tl_data_contents, tl_data.tl_data_length);
- /* add_pa_data_element() claims pa on success or failure. */
- return add_pa_data_element(&reply->enc_padata, pa);
+ code = k5_add_pa_data_element(&reply->enc_padata, &pa);
+ k5_free_pa_data_element(pa);
+ return code;
}
krb5_error_code
krb5_error_code code;
krb5_data *der_user_id = NULL, *der_s4u_x509_user = NULL;
krb5_pa_s4u_x509_user rep_s4u_user;
- krb5_pa_data *pa;
+ krb5_pa_data *pa = NULL;
krb5_enctype enctype;
krb5_keyusage usage;
if (code != 0)
goto cleanup;
- /* Add a padata element, stealing memory from der_s4u_x509_user. */
- code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER, 0, &pa);
- if (code != 0)
- goto cleanup;
- pa->length = der_s4u_x509_user->length;
- pa->contents = (uint8_t *)der_s4u_x509_user->data;
- der_s4u_x509_user->data = NULL;
- /* add_pa_data_element() claims pa on success or failure. */
- code = add_pa_data_element(&reply->padata, pa);
+ code = k5_add_pa_data_from_data(&reply->padata, KRB5_PADATA_S4U_X509_USER,
+ der_s4u_x509_user);
if (code != 0)
goto cleanup;
*/
if ((req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) &&
enctype_requires_etype_info_2(enctype) == FALSE) {
- code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
- req_s4u_user->cksum.length +
- rep_s4u_user.cksum.length, &pa);
+ code = k5_alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
+ req_s4u_user->cksum.length +
+ rep_s4u_user.cksum.length, &pa);
if (code != 0)
goto cleanup;
memcpy(pa->contents,
memcpy(&pa->contents[req_s4u_user->cksum.length],
rep_s4u_user.cksum.contents, rep_s4u_user.cksum.length);
- /* add_pa_data_element() claims pa on success or failure. */
- code = add_pa_data_element(&reply_encpart->enc_padata, pa);
+ code = k5_add_pa_data_element(&reply_encpart->enc_padata, &pa);
if (code != 0)
goto cleanup;
}
krb5_free_checksum_contents(context, &rep_s4u_user.cksum);
krb5_free_data(context, der_user_id);
krb5_free_data(context, der_s4u_x509_user);
-
+ k5_free_pa_data_element(pa);
return code;
}
}
}
-/* Allocate a pa-data entry with an uninitialized buffer of size len. */
-krb5_error_code
-alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
-{
- krb5_pa_data *pa;
- uint8_t *buf = NULL;
-
- *out = NULL;
- if (len > 0) {
- buf = malloc(len);
- if (buf == NULL)
- return ENOMEM;
- }
- pa = malloc(sizeof(*pa));
- if (pa == NULL) {
- free(buf);
- return ENOMEM;
- }
- pa->magic = KV5M_PA_DATA;
- pa->pa_type = pa_type;
- pa->length = len;
- pa->contents = buf;
- *out = pa;
- return 0;
-}
-
-/* Add pa to list, claiming its memory. Free pa on failure. */
-krb5_error_code
-add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa)
-{
- size_t count;
- krb5_pa_data **newlist;
-
- for (count = 0; *list != NULL && (*list)[count] != NULL; count++);
-
- newlist = realloc(*list, (count + 2) * sizeof(*newlist));
- if (newlist == NULL) {
- free(pa->contents);
- free(pa);
- return ENOMEM;
- }
- newlist[count] = pa;
- newlist[count + 1] = NULL;
- *list = newlist;
- return 0;
-}
-
void
kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
krb5_timestamp starttime,
krb5_error_code retval = 0;
krb5_checksum checksum;
krb5_data *der_cksum = NULL;
- krb5_pa_data *pa, *pa_in;
+ krb5_pa_data *pa_in;
memset(&checksum, 0, sizeof(checksum));
if (retval != 0)
goto cleanup;
- /* Add a pa-data element to the list, stealing memory from der_cksum. */
- retval = alloc_pa_data(KRB5_ENCPADATA_REQ_ENC_PA_REP, 0, &pa);
- if (retval)
- goto cleanup;
- pa->length = der_cksum->length;
- pa->contents = (uint8_t *)der_cksum->data;
- der_cksum->data = NULL;
- /* add_pa_data_element() claims pa on success or failure. */
- retval = add_pa_data_element(out_enc_padata, pa);
+ retval = k5_add_pa_data_from_data(out_enc_padata,
+ KRB5_ENCPADATA_REQ_ENC_PA_REP,
+ der_cksum);
if (retval)
goto cleanup;
/* Add a zero-length PA-FX-FAST element to the list. */
- retval = alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa);
- if (retval)
- goto cleanup;
- /* add_pa_data_element() claims pa on success or failure. */
- retval = add_pa_data_element(out_enc_padata, pa);
+ retval = k5_add_empty_pa_data(out_enc_padata, KRB5_PADATA_FX_FAST);
cleanup:
krb5_free_checksum_contents(context, &checksum);
#define MAX_IN_TKT_LOOPS 16
-/* Add a pa-data item with the specified type and contents to *padptr. */
-static krb5_error_code
-add_padata(krb5_pa_data ***padptr, krb5_preauthtype pa_type,
- const void *contents, unsigned int length)
-{
- size_t size = 0;
- krb5_pa_data **pad = *padptr;
- krb5_pa_data *pa= NULL;
- if (pad)
- for (size=0; pad[size]; size++);
- pad = realloc(pad, sizeof(*pad)*(size+2));
- if (pad == NULL)
- return ENOMEM;
- *padptr = pad;
- pad[size] = pad[size + 1] = NULL;
-
- pa = malloc(sizeof(krb5_pa_data));
- if (pa == NULL)
- return ENOMEM;
- pa->contents = NULL;
- pa->length = length;
- if (contents != NULL) {
- pa->contents = malloc(length);
- if (pa->contents == NULL) {
- free(pa);
- return ENOMEM;
- }
- memcpy(pa->contents, contents, length);
- }
- pa->pa_type = pa_type;
- pad[size] = pa;
- return 0;
-}
-
/* Sort a pa_data sequence so that types named in the "preferred_preauth_types"
* libdefaults entry are listed before any others. */
static krb5_error_code
code = encode_krb5_pa_pac_req(&pac_req, &encoded);
if (code)
return code;
- code = add_padata(&ctx->request->padata, KRB5_PADATA_PAC_REQUEST,
- encoded->data, encoded->length);
+ code = k5_add_pa_data_from_data(&ctx->request->padata,
+ KRB5_PADATA_PAC_REQUEST, encoded);
krb5_free_data(context, encoded);
return code;
}
{
krb5_error_code code;
krb5_preauthtype pa_type;
+ krb5_data copy;
struct errinfo save = EMPTY_ERRINFO;
uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error;
ctx->encoded_previous_request = NULL;
}
if (ctx->info_pa_permitted) {
- code = add_padata(&ctx->request->padata, KRB5_PADATA_AS_FRESHNESS,
- NULL, 0);
+ code = k5_add_empty_pa_data(&ctx->request->padata,
+ KRB5_PADATA_AS_FRESHNESS);
if (code)
goto cleanup;
- code = add_padata(&ctx->request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP,
- NULL, 0);
+ code = k5_add_empty_pa_data(&ctx->request->padata,
+ KRB5_ENCPADATA_REQ_ENC_PA_REP);
}
if (code)
goto cleanup;
if (ctx->subject_cert != NULL) {
- code = add_padata(&ctx->request->padata, KRB5_PADATA_S4U_X509_USER,
- ctx->subject_cert->data, ctx->subject_cert->length);
+ code = krb5int_copy_data_contents(context, ctx->subject_cert, ©);
if (code)
- return code;
+ goto cleanup;
+ code = k5_add_pa_data_from_data(&ctx->request->padata,
+ KRB5_PADATA_S4U_X509_USER, ©);
+ krb5_free_data_contents(context, ©);
+ if (code)
+ goto cleanup;
}
code = maybe_add_pac_request(context, ctx);