diff options
Diffstat (limited to 'src/kdc')
| -rw-r--r-- | src/kdc/kdc_preauth.c | 246 | ||||
| -rw-r--r-- | src/kdc/kdc_preauth_ec.c | 44 |
2 files changed, 98 insertions, 192 deletions
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 87586d700..7e9cde1f9 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -107,24 +107,23 @@ typedef struct preauth_system_st { static void verify_enc_timestamp(krb5_context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, - krb5_kdcpreauth_get_data_fn get, - krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_verify_respond_fn respond, void *arg); static krb5_error_code get_enc_ts(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata modata, krb5_pa_data *data); static krb5_error_code get_etype_info(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *data); static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data); static krb5_error_code @@ -140,7 +139,7 @@ static krb5_error_code return_etype_info(krb5_context, krb5_pa_data *padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq); @@ -148,7 +147,7 @@ static krb5_error_code return_etype_info2(krb5_context, krb5_pa_data *padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq); @@ -156,7 +155,7 @@ static krb5_error_code return_pw_salt(krb5_context, krb5_pa_data *padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq); @@ -510,158 +509,87 @@ free_padata_context(krb5_context kcontext, void *padata_context) free(context); } -/* Retrieve a specified tl_data item from the given entry, and return its - * contents in a new krb5_data, which must be freed by the caller. - */ -static krb5_error_code -get_entry_tl_data(krb5_context context, krb5_db_entry *entry, - krb5_int16 tl_data_type, krb5_data **result) +static krb5_deltat +max_time_skew(krb5_context context, krb5_kdcpreauth_rock rock) { - krb5_tl_data *tl; - for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) { - if (tl->tl_data_type == tl_data_type) { - *result = malloc(sizeof(krb5_data)); - if (*result == NULL) { - return ENOMEM; - } - (*result)->magic = KV5M_DATA; - (*result)->data = malloc(tl->tl_data_length); - if ((*result)->data == NULL) { - free(*result); - *result = NULL; - return ENOMEM; - } - memcpy((*result)->data, tl->tl_data_contents, tl->tl_data_length); - return 0; - } - } - return ENOENT; + return context->clockskew; } -/* - * Retrieve a specific piece of information pertaining to the client entry or - * request and return it in a new krb5_data item which the caller must free. - * - * This may require massaging data into a contrived format, but it will - * hopefully keep us from having to reveal library-internal functions to - * modules. - */ static krb5_error_code -get_data(krb5_context context, krb5_kdcpreauth_rock rock, krb5_int32 type, - krb5_data **result) +client_keys(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_keyblock **keys_out) { - int i, k; - krb5_data *ret; - krb5_deltat *delta; - krb5_keyblock *keys; - krb5_key_data *entry_key; - krb5_error_code error; krb5_kdc_req *request = rock->request; - struct kdc_request_state *state = rock->rstate; krb5_db_entry *client = rock->client; + krb5_keyblock *keys, key; + krb5_key_data *entry_key; + int i, k; - switch (type) { - case krb5_kdcpreauth_request_certificate: - return get_entry_tl_data(context, client, KRB5_TL_USER_CERTIFICATE, - result); - break; - case krb5_kdcpreauth_max_time_skew: - ret = malloc(sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - delta = malloc(sizeof(krb5_deltat)); - if (delta == NULL) { - free(ret); - return ENOMEM; - } - *delta = context->clockskew; - ret->data = (char *) delta; - ret->length = sizeof(*delta); - *result = ret; - return 0; - break; - case krb5_kdcpreauth_keys: - ret = malloc(sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1)); - if (keys == NULL) { - free(ret); - return ENOMEM; - } - ret->data = (char *) keys; - ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1); - memset(ret->data, 0, ret->length); - k = 0; - for (i = 0; i < request->nktypes; i++) { - entry_key = NULL; - if (krb5_dbe_find_enctype(context, client, request->ktype[i], - -1, 0, &entry_key) != 0) - continue; - if (krb5_dbe_decrypt_key_data(context, NULL, entry_key, - &keys[k], NULL) != 0) { - if (keys[k].contents != NULL) - krb5_free_keyblock_contents(context, &keys[k]); - memset(&keys[k], 0, sizeof(keys[k])); - continue; - } - k++; - } - if (k > 0) { - *result = ret; - return 0; - } else { - free(keys); - free(ret); - } - break; - case krb5_kdcpreauth_request_body: - ret = NULL; - encode_krb5_kdc_req_body(request, &ret); - if (ret != NULL) { - *result = ret; - return 0; - } - return ASN1_PARSE_ERROR; - break; - case krb5_kdcpreauth_fast_armor: - ret = calloc(1, sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - if (state->armor_key == NULL) { - *result = ret; - return 0; - } - error = krb5_copy_keyblock(context, state->armor_key, &keys); - if (error == 0) { - ret->data = (char *) keys; - ret->length = sizeof(krb5_keyblock); - *result = ret; - return 0; - } - free(ret); - return error; - case krb5_kdcpreauth_free_fast_armor: - if ((*result)->data) { - keys = (krb5_keyblock *) (*result)->data; - krb5_free_keyblock(context, keys); - } - free(*result); - return 0; - case krb5_kdcpreauth_get_client: - ret = malloc(sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - ret->data = (char *)&rock->client; - ret->length = sizeof(rock->client); - *result = ret; - return 0; - default: - break; + keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1)); + if (keys == NULL) + return ENOMEM; + + memset(keys, 0, sizeof(krb5_keyblock) * (request->nktypes + 1)); + k = 0; + for (i = 0; i < request->nktypes; i++) { + entry_key = NULL; + if (krb5_dbe_find_enctype(context, client, request->ktype[i], + -1, 0, &entry_key) != 0) + continue; + if (krb5_dbe_decrypt_key_data(context, NULL, entry_key, + &key, NULL) != 0) + continue; + keys[k++] = key; } - return ENOENT; + if (k == 0) { + free(keys); + return ENOENT; + } + *keys_out = keys; + return 0; } +static void free_keys(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_keyblock *keys) +{ + krb5_keyblock *k; + + if (keys == NULL) + return; + for (k = keys; k->enctype != 0; k++) + krb5_free_keyblock_contents(context, k); + free(keys); +} + +static krb5_error_code +request_body(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_data **body_out) +{ + return encode_krb5_kdc_req_body(rock->request, body_out); +} + +static krb5_keyblock * +fast_armor(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->rstate->armor_key; +} + +static void * +client_entry(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->client; +} + +static struct krb5_kdcpreauth_callbacks_st callbacks = { + 1, + max_time_skew, + client_keys, + free_keys, + request_body, + fast_armor, + client_entry +}; + static krb5_error_code find_pa_system(int type, preauth_system **preauth) { @@ -851,7 +779,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, (*pa)->magic = KV5M_PA_DATA; (*pa)->pa_type = ap->type; if (ap->get_edata) { - retval = ap->get_edata(kdc_context, request, get_data, rock, + retval = ap->get_edata(kdc_context, request, &callbacks, rock, ap->moddata, *pa); if (retval) { /* just failed on this type, continue */ @@ -1139,7 +1067,7 @@ next_padata(struct padata_state *state) state->pa_found++; state->pa_sys->verify_padata(state->context, state->req_pkt, state->request, state->enc_tkt_reply, - *state->padata, get_data, state->rock, + *state->padata, &callbacks, state->rock, state->pa_sys->moddata, finish_verify_padata, state); return; @@ -1282,7 +1210,7 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock, } } retval = ap->return_padata(context, pa, req_pkt, request, reply, - encrypting_key, send_pa, get_data, rock, + encrypting_key, send_pa, &callbacks, rock, ap->moddata, *modreq_ptr); if (retval) goto cleanup; @@ -1321,7 +1249,7 @@ request_contains_enctype(krb5_context context, const krb5_kdc_req *request, static krb5_error_code get_enc_ts(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { if (rock->rstate->armor_key != NULL) @@ -1333,7 +1261,7 @@ get_enc_ts(krb5_context context, krb5_kdc_req *request, static void verify_enc_timestamp(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data *pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_verify_respond_fn respond, @@ -1576,7 +1504,7 @@ cleanup: static krb5_error_code get_etype_info(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data) { int i; @@ -1591,7 +1519,7 @@ get_etype_info(krb5_context context, krb5_kdc_req *request, static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data) { return etype_info_helper(context, request, rock->client, pa_data, 1); @@ -1678,7 +1606,7 @@ static krb5_error_code return_etype_info2(krb5_context context, krb5_pa_data * padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) { @@ -1692,7 +1620,7 @@ static krb5_error_code return_etype_info(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) { @@ -1705,7 +1633,7 @@ static krb5_error_code return_pw_salt(krb5_context context, krb5_pa_data *in_padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) { krb5_error_code retval; diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c index 62fa615e0..b52d03620 100644 --- a/src/kdc/kdc_preauth_ec.c +++ b/src/kdc/kdc_preauth_ec.c @@ -36,24 +36,18 @@ static krb5_error_code kdc_include_padata(krb5_context context, krb5_kdc_req *request, - krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { - krb5_error_code retval = 0; - krb5_keyblock *armor_key = NULL; - retval = fast_kdc_get_armor_key(context, get, rock, &armor_key); - if (retval) - return retval; - if (armor_key == 0) - return ENOENT; - krb5_free_keyblock(context, armor_key); - return 0; + krb5_keyblock *armor_key = cb->fast_armor(context, rock); + + return (armor_key == NULL) ? ENOENT : 0; } static void kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *data, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data *data, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_verify_respond_fn respond, void *arg) @@ -62,10 +56,9 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, krb5_timestamp now; krb5_enc_data *enc = NULL; krb5_data scratch, plain; - krb5_keyblock *armor_key = NULL; + krb5_keyblock *armor_key = cb->fast_armor(context, rock); krb5_pa_enc_ts *ts = NULL; krb5_keyblock *client_keys = NULL; - krb5_data *client_data = NULL; krb5_keyblock *challenge_key = NULL; krb5_keyblock *kdc_challenge_key; krb5_kdcpreauth_modreq modreq = NULL; @@ -73,8 +66,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, plain.data = NULL; - retval = fast_kdc_get_armor_key(context, get, rock, &armor_key); - if (retval == 0 &&armor_key == NULL) { + if (armor_key == NULL) { retval = ENOENT; krb5_set_error_message(context, ENOENT, "Encrypted Challenge used outside of FAST tunnel"); } @@ -89,9 +81,8 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, retval = ENOMEM; } if (retval == 0) - retval = (*get)(context, rock, krb5_kdcpreauth_keys, &client_data); + retval = cb->client_keys(context, rock, &client_keys); if (retval == 0) { - client_keys = (krb5_keyblock *) client_data->data; for (i = 0; client_keys[i].enctype&& (retval == 0); i++ ) { retval = krb5_c_fx_cf2_simple(context, armor_key, "clientchallengearmor", @@ -108,18 +99,11 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, break; /*We failed to decrypt. Try next key*/ retval = 0; - krb5_free_keyblock_contents(context, &client_keys[i]); } if (client_keys[i].enctype == 0) { retval = KRB5KDC_ERR_PREAUTH_FAILED; krb5_set_error_message(context, retval, "Incorrect password in encrypted challenge"); - } else { /*not run out of keys*/ - int j; - assert (retval == 0); - for (j = i+1; client_keys[j].enctype; j++) - krb5_free_keyblock_contents(context, &client_keys[j]); } - } if (retval == 0) retval = decode_krb5_pa_enc_ts(&plain, &ts); @@ -133,7 +117,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, * may cause the client to fail, but at this point the KDC has * considered this a success, so the return value is ignored. */ - fast_kdc_replace_reply_key(context, get, rock); + fast_kdc_replace_reply_key(context, cb, rock); if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", &client_keys[i], "challengelongterm", &kdc_challenge_key) == 0) @@ -142,13 +126,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, retval = KRB5KRB_AP_ERR_SKEW; } } - if (client_keys) { - if (client_keys[i].enctype) - krb5_free_keyblock_contents(context, &client_keys[i]); - krb5_free_data(context, client_data); - } - if (armor_key) - krb5_free_keyblock(context, armor_key); + cb->free_keys(context, rock, client_keys); if (plain.data) free(plain.data); if (enc) @@ -163,7 +141,7 @@ static krb5_error_code kdc_return_preauth(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get, + krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) { |
