diff options
-rw-r--r-- | doc/appdev/refs/macros/index.rst | 1 | ||||
-rw-r--r-- | src/include/krb5/kdcpreauth_plugin.h | 21 | ||||
-rw-r--r-- | src/include/krb5/krb5.hin | 2 | ||||
-rw-r--r-- | src/kdc/do_as_req.c | 40 | ||||
-rw-r--r-- | src/kdc/fast_util.c | 363 | ||||
-rw-r--r-- | src/kdc/kdc_preauth.c | 24 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 20 | ||||
-rw-r--r-- | src/kdc/reqstate.h | 3 |
8 files changed, 382 insertions, 92 deletions
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst index 7b07122..2271e90 100644 --- a/doc/appdev/refs/macros/index.rst +++ b/doc/appdev/refs/macros/index.rst @@ -177,6 +177,7 @@ Public KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst + KRB5_KEYUSAGE_PA_FX_COOKIE.rst KRB5_KEYUSAGE_PA_OTP_REQUEST.rst KRB5_KEYUSAGE_PA_PKINIT_KX.rst KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h index 356004f..f455eff 100644 --- a/src/include/krb5/kdcpreauth_plugin.h +++ b/src/include/krb5/kdcpreauth_plugin.h @@ -198,6 +198,27 @@ typedef struct krb5_kdcpreauth_callbacks_st { krb5_kdcpreauth_rock rock, const char *indicator); + /* + * Read a data value for pa_type from the request cookie, placing it in + * *out. The value placed there is an alias and must not be freed. + * Returns true if a value for pa_type was retrieved, false if not. + */ + krb5_boolean (*get_cookie)(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, krb5_data *out); + + /* + * Set a data value for pa_type to be sent in a secure cookie in the next + * error response. If pa_type is already present, the value is ignored. + * If the preauth mechanism has different preauth types for requests and + * responses, use the request type. Secure cookies are encrypted in a key + * known only to the KDCs, but can be replayed within a short time window + * for requests using the same client principal. + */ + krb5_error_code (*set_cookie)(krb5_context context, + krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, + const krb5_data *data); + /* End of version 3 kdcpreauth callbacks. */ } *krb5_kdcpreauth_callbacks; diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index 55fa88e..0d19a65 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -1007,6 +1007,8 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, #define KRB5_KEYUSAGE_ENC_CHALLENGE_KDC 55 #define KRB5_KEYUSAGE_AS_REQ 56 #define KRB5_KEYUSAGE_CAMMAC 64 + +#define KRB5_KEYUSAGE_PA_FX_COOKIE 513 /**< Used for encrypted FAST cookies */ /** @} */ /* end of KRB5_KEYUSAGE group */ /** diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 64e849d..3a3ce8b 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -75,7 +75,7 @@ #include "extern.h" static krb5_error_code -prepare_error_as(struct kdc_request_state *, krb5_kdc_req *, +prepare_error_as(struct kdc_request_state *, krb5_kdc_req *, krb5_db_entry *, int, krb5_pa_data **, krb5_boolean, krb5_principal, krb5_data **, const char *); @@ -397,8 +397,8 @@ egress: errcode = KRB_ERR_GENERIC; errcode = prepare_error_as(state->rstate, state->request, - errcode, state->e_data, - state->typed_e_data, + state->local_tgt, errcode, + state->e_data, state->typed_e_data, ((state->client != NULL) ? state->client->princ : NULL), &response, state->status); @@ -805,6 +805,13 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, state->rock.client_keyblock = &state->client_keyblock; } + errcode = kdc_fast_read_cookie(kdc_context, state->rstate, state->request, + state->local_tgt); + if (errcode) { + state->status = "READ_COOKIE"; + goto errout; + } + /* * Check the preauthentication if it is there. */ @@ -822,15 +829,30 @@ errout: } static krb5_error_code -prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, - int error, krb5_pa_data **e_data, krb5_boolean typed_e_data, - krb5_principal canon_client, krb5_data **response, - const char *status) +prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request, + krb5_db_entry *local_tgt, int error, krb5_pa_data **e_data_in, + krb5_boolean typed_e_data, krb5_principal canon_client, + krb5_data **response, const char *status) { krb5_error errpkt; krb5_error_code retval; krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL; + krb5_pa_data **e_data = NULL, *cookie = NULL; kdc_realm_t *kdc_active_realm = rstate->realm_data; + size_t count; + + if (e_data_in != NULL) { + /* Add a PA-FX-COOKIE to e_data_in. e_data is a shallow copy + * containing aliases. */ + for (count = 0; e_data_in[count] != NULL; count++); + e_data = calloc(count + 2, sizeof(*e_data)); + if (e_data == NULL) + return ENOMEM; + memcpy(e_data, e_data_in, count * sizeof(*e_data)); + retval = kdc_fast_make_cookie(kdc_context, rstate, local_tgt, + request->client, &cookie); + e_data[count] = cookie; + } errpkt.ctime = request->nonce; errpkt.cusec = 0; @@ -878,5 +900,9 @@ cleanup: krb5_free_data(kdc_context, fast_edata); krb5_free_data(kdc_context, e_data_asn1); free(scratch); + free(e_data); + if (cookie != NULL) + free(cookie->contents); + free(cookie); return retval; } diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index 20b7fef..f76ad37 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -1,7 +1,7 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* kdc/fast_util.c */ /* - * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * Copyright (C) 2009, 2015 by the Massachusetts Institute of Technology. * All rights reserved. * * Export of this software from the United States of America may @@ -29,15 +29,8 @@ #include "kdc_util.h" #include "extern.h" - -/* - * This function will find the fast and cookie padata and if fast is - * successfully processed, will throw away (and free) the outer - * request and update the pointer to point to the inner request. The - * checksummed_data points to the data that is in the - * armored_fast_request checksum; either the pa-tgs-req or the - * kdc-req-body. - */ +/* Let cookies be valid for ten minutes. */ +#define COOKIE_LIFETIME 600 static krb5_error_code armor_ap_request (struct kdc_request_state *state, krb5_fast_armor *armor) @@ -123,6 +116,12 @@ encrypt_fast_reply(struct kdc_request_state *state, } +/* + * This function will find the FAST padata and, if FAST is successfully + * processed, will free the outer request and update the pointer to point to + * the inner request. checksummed_data points to the data that is in the + * armored_fast_request checksum; either the pa-tgs-req or the kdc-req-body. + */ krb5_error_code kdc_find_fast(krb5_kdc_req **requestptr, krb5_data *checksummed_data, @@ -132,7 +131,7 @@ kdc_find_fast(krb5_kdc_req **requestptr, krb5_data **inner_body_out) { krb5_error_code retval = 0; - krb5_pa_data *fast_padata, *cookie_padata = NULL; + krb5_pa_data *fast_padata; krb5_data scratch, *inner_body = NULL; krb5_fast_req * fast_req = NULL; krb5_kdc_req *request = *requestptr; @@ -229,10 +228,6 @@ kdc_find_fast(krb5_kdc_req **requestptr, if ((fast_req->fast_options & UNSUPPORTED_CRITICAL_FAST_OPTIONS) != 0) retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION; } - if (retval == 0) - cookie_padata = krb5int_find_pa_data(kdc_context, - fast_req->req_body->padata, - KRB5_PADATA_FX_COOKIE); if (retval == 0) { state->fast_options = fast_req->fast_options; fast_req->req_body->msg_type = request->msg_type; @@ -241,26 +236,6 @@ kdc_find_fast(krb5_kdc_req **requestptr, fast_req->req_body = NULL; } } - else { - cookie_padata = krb5int_find_pa_data(kdc_context, - request->padata, - KRB5_PADATA_FX_COOKIE); - } - if (retval == 0 && cookie_padata != NULL) { - krb5_pa_data *new_padata = malloc(sizeof (krb5_pa_data)); - if (new_padata == NULL) { - retval = ENOMEM; - } else { - new_padata->pa_type = KRB5_PADATA_FX_COOKIE; - new_padata->length = cookie_padata->length; - new_padata->contents = - k5memdup(cookie_padata->contents, new_padata->length, &retval); - if (new_padata->contents == NULL) - free(new_padata); - else - state->cookie = new_padata; - } - } if (retval == 0 && inner_body_out != NULL) { *inner_body_out = inner_body; inner_body = NULL; @@ -295,10 +270,8 @@ kdc_free_rstate (struct kdc_request_state *s) krb5_free_keyblock(kdc_context, s->armor_key); if (s->strengthen_key) krb5_free_keyblock(kdc_context, s->strengthen_key); - if (s->cookie) { - free(s->cookie->contents); - free(s->cookie); - } + krb5_free_pa_data(NULL, s->in_cookie_padata); + krb5_free_pa_data(NULL, s->out_cookie_padata); free(s); } @@ -403,7 +376,7 @@ kdc_fast_handle_error(krb5_context context, krb5_error fx_error; krb5_data *encoded_fx_error = NULL, *encrypted_reply = NULL; krb5_pa_data pa[1]; - krb5_pa_data *outer_pa[3], *cookie = NULL; + krb5_pa_data *outer_pa[3]; krb5_pa_data **inner_pa = NULL; size_t size = 0; kdc_realm_t *kdc_active_realm = state->realm_data; @@ -416,8 +389,7 @@ kdc_fast_handle_error(krb5_context context, fx_error.e_data.data = NULL; fx_error.e_data.length = 0; for (size = 0; in_padata&&in_padata[size]; size++); - size +=3; - inner_pa = calloc(size, sizeof(krb5_pa_data *)); + inner_pa = calloc(size + 2, sizeof(krb5_pa_data *)); if (inner_pa == NULL) retval = ENOMEM; if (retval == 0) @@ -430,12 +402,7 @@ kdc_fast_handle_error(krb5_context context, pa[0].length = encoded_fx_error->length; pa[0].contents = (unsigned char *) encoded_fx_error->data; inner_pa[size++] = &pa[0]; - if (krb5int_find_pa_data(kdc_context, - inner_pa, KRB5_PADATA_FX_COOKIE) == NULL) - retval = kdc_preauth_get_cookie(state, &cookie); } - if (cookie != NULL) - inner_pa[size++] = cookie; if (retval == 0) { resp.padata = inner_pa; resp.nonce = request->nonce; @@ -446,11 +413,6 @@ kdc_fast_handle_error(krb5_context context, retval = encrypt_fast_reply(state, &resp, &encrypted_reply); if (inner_pa) free(inner_pa); /*contained storage from caller and our stack*/ - if (cookie) { - free(cookie->contents); - free(cookie); - cookie = NULL; - } if (retval == 0) { pa[0].pa_type = KRB5_PADATA_FX_FAST; pa[0].length = encrypted_reply->length; @@ -483,38 +445,289 @@ kdc_fast_handle_reply_key(struct kdc_request_state *state, return retval; } +krb5_boolean +kdc_fast_hide_client(struct kdc_request_state *state) +{ + return (state->fast_options & KRB5_FAST_OPTION_HIDE_CLIENT_NAMES) != 0; +} -krb5_error_code -kdc_preauth_get_cookie(struct kdc_request_state *state, - krb5_pa_data **cookie) +/* Allocate a pa-data entry with an uninitialized buffer of size len. */ +static krb5_error_code +alloc_padata(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out) { - char *contents; - krb5_pa_data *pa = NULL; - - /* In our current implementation, the only purpose served by - * returning a cookie is to indicate that a conversation should - * continue on error. Thus, the cookie can have a constant - * string. If cookies are used for real, versioning so that KDCs - * can be upgraded, keying, expiration and many other issues need - * to be considered. - */ - contents = strdup("MIT"); - if (contents == NULL) + krb5_pa_data *pa; + uint8_t *buf; + + *out = NULL; + buf = malloc(len); + if (buf == NULL) return ENOMEM; - pa = calloc(1, sizeof(krb5_pa_data)); + pa = malloc(sizeof(*pa)); if (pa == NULL) { - free(contents); + free(buf); return ENOMEM; } - pa->pa_type = KRB5_PADATA_FX_COOKIE; - pa->length = strlen(contents); - pa->contents = (unsigned char *) contents; - *cookie = pa; + pa->magic = KV5M_PA_DATA; + pa->pa_type = pa_type; + pa->length = len; + pa->contents = buf; + *out = pa; return 0; } +/* Create a pa-data entry with the specified type and contents. */ +static krb5_error_code +make_padata(krb5_preauthtype pa_type, const void *contents, size_t len, + krb5_pa_data **out) +{ + if (alloc_padata(pa_type, len, out) != 0) + return ENOMEM; + memcpy((*out)->contents, contents, len); + return 0; +} + +/* + * Construct the secure cookie encryption key for the given local-realm TGT + * entry, kvno, and client principal. The cookie key is derived from the first + * TGT key for the given kvno, using the concatenation of "COOKIE" and the + * unparsed client principal name as input. If kvno is 0, the highest current + * kvno of the TGT is used. If kvno_out is not null, *kvno_out is set to the + * kvno used. + */ +static krb5_error_code +get_cookie_key(krb5_context context, krb5_db_entry *tgt, krb5_kvno kvno, + krb5_const_principal client_princ, krb5_keyblock **key_out, + krb5_kvno *kvno_out) +{ + krb5_error_code ret; + krb5_key_data *kd; + krb5_keyblock kb; + krb5_data d; + krb5_int32 start = 0; + char *princstr = NULL, *derive_input = NULL; + + *key_out = NULL; + memset(&kb, 0, sizeof(kb)); + + /* Find the first krbtgt key with the specified kvno. */ + ret = krb5_dbe_search_enctype(context, tgt, &start, -1, -1, kvno, &kd); + if (ret) + goto cleanup; + + /* Decrypt the key. */ + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL); + if (ret) + goto cleanup; + + /* Construct the input string and derive the cookie key. */ + ret = krb5_unparse_name(context, client_princ, &princstr); + if (ret) + goto cleanup; + if (asprintf(&derive_input, "COOKIE%s", princstr) < 0) { + ret = ENOMEM; + goto cleanup; + } + d = string2data(derive_input); + ret = krb5_c_derive_prfplus(context, &kb, &d, ENCTYPE_NULL, key_out); + + if (kvno_out != NULL) + *kvno_out = kd->key_data_kvno; + +cleanup: + krb5_free_keyblock_contents(context, &kb); + krb5_free_unparsed_name(context, princstr); + free(derive_input); + return ret; +} + +/* Return true if there is any overlap between padata types in cpadata + * (from the cookie) and rpadata (from the request). */ +static krb5_boolean +is_relevant(krb5_pa_data *const *cpadata, krb5_pa_data *const *rpadata) +{ + krb5_pa_data *const *p; + + for (p = cpadata; p != NULL && *p != NULL; p++) { + if (krb5int_find_pa_data(NULL, rpadata, (*p)->pa_type) != NULL) + return TRUE; + } + return FALSE; +} + +/* + * Locate and decode the FAST cookie in req, storing its contents in state for + * later access by preauth modules. If the cookie is expired, return + * KRB5KDC_ERR_PREAUTH_EXPIRED if its contents are relevant to req, and ignore + * it if they aren't. + */ +krb5_error_code +kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *req, krb5_db_entry *local_tgt) +{ + krb5_error_code ret; + krb5_secure_cookie *cookie = NULL; + krb5_timestamp now; + krb5_keyblock *key = NULL; + krb5_enc_data enc; + krb5_pa_data *pa; + krb5_kvno kvno; + krb5_data plain = empty_data(); + + pa = krb5int_find_pa_data(context, req->padata, KRB5_PADATA_FX_COOKIE); + if (pa == NULL) + return 0; + + /* If it's not an MIT version 1 cookie, ignore it. It may be an empty + * "MIT" cookie or a cookie generated by a different KDC implementation. */ + if (pa->length <= 8 || memcmp(pa->contents, "MIT1", 4) != 0) + return 0; + + /* Extract the kvno and generate the corresponding cookie key. */ + kvno = load_32_be(pa->contents + 4); + ret = get_cookie_key(context, local_tgt, kvno, req->client, &key, NULL); + if (ret) + goto cleanup; + + /* Decrypt and decode the cookie. */ + memset(&enc, 0, sizeof(enc)); + enc.enctype = key->enctype; + enc.ciphertext = make_data(pa->contents + 8, pa->length - 8); + ret = alloc_data(&plain, pa->length - 8); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, key, KRB5_KEYUSAGE_PA_FX_COOKIE, NULL, &enc, + &plain); + if (ret) + goto cleanup; + ret = decode_krb5_secure_cookie(&plain, &cookie); + if (ret) + goto cleanup; + + /* Check if the cookie is expired. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto cleanup; + if (now - COOKIE_LIFETIME > cookie->time) { + /* Don't accept the cookie contents. Only return an error if the + * cookie is relevant to the request. */ + if (is_relevant(cookie->data, req->padata)) + ret = KRB5KDC_ERR_PREAUTH_EXPIRED; + goto cleanup; + } + + /* Steal the pa-data list pointer from the cookie and store it in state. */ + state->in_cookie_padata = cookie->data; + cookie->data = NULL; + +cleanup: + krb5_free_data_contents(context, &plain); + krb5_free_keyblock(context, key); + k5_free_secure_cookie(context, cookie); + return 0; +} + +/* If state contains a cookie value for pa_type, set *out to the corresponding + * data and return true. Otherwise set *out to empty and return false. */ krb5_boolean -kdc_fast_hide_client(struct kdc_request_state *state) +kdc_fast_search_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, krb5_data *out) { - return (state->fast_options & KRB5_FAST_OPTION_HIDE_CLIENT_NAMES) != 0; + krb5_pa_data *pa; + + pa = krb5int_find_pa_data(NULL, state->in_cookie_padata, pa_type); + if (pa == NULL) { + *out = empty_data(); + return FALSE; + } else { + *out = make_data(pa->contents, pa->length); + return TRUE; + } +} + +/* Set a cookie value in state for data, to be included in the outgoing + * cookie. Duplicate values are ignored. */ +krb5_error_code +kdc_fast_set_cookie(struct kdc_request_state *state, krb5_preauthtype pa_type, + const krb5_data *data) +{ + krb5_pa_data **list = state->out_cookie_padata; + size_t count; + + for (count = 0; list != NULL && list[count] != NULL; count++) { + if (list[count]->pa_type == pa_type) + return 0; + } + + list = realloc(list, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + state->out_cookie_padata = list; + list[count] = list[count + 1] = NULL; + return make_padata(pa_type, data->data, data->length, &list[count]); +} + +/* Construct a cookie pa-data item using the cookie values from state, or a + * trivial "MIT" cookie if no values are set. */ +krb5_error_code +kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state, + krb5_db_entry *local_tgt, + krb5_const_principal client_princ, + krb5_pa_data **cookie_out) +{ + krb5_error_code ret; + krb5_secure_cookie cookie; + krb5_pa_data **contents = state->out_cookie_padata, *pa; + krb5_keyblock *key = NULL; + krb5_timestamp now; + krb5_enc_data enc; + krb5_data *der_cookie = NULL; + krb5_kvno kvno; + size_t ctlen; + + *cookie_out = NULL; + memset(&enc, 0, sizeof(enc)); + + /* Make a trivial cookie if there are no contents to marshal or we don't + * have a TGT entry to encrypt them. */ + if (contents == NULL || *contents == NULL || local_tgt == NULL) + return make_padata(KRB5_PADATA_FX_COOKIE, "MIT", 3, cookie_out); + + ret = get_cookie_key(context, local_tgt, 0, client_princ, &key, &kvno); + if (ret) + goto cleanup; + + /* Encode the cookie. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto cleanup; + cookie.time = now; + cookie.data = contents; + ret = encode_krb5_secure_cookie(&cookie, &der_cookie); + if (ret) + goto cleanup; + + /* Encrypt the cookie in key. */ + ret = krb5_c_encrypt_length(context, key->enctype, der_cookie->length, + &ctlen); + if (ret) + goto cleanup; + ret = alloc_data(&enc.ciphertext, ctlen); + if (ret) + goto cleanup; + ret = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_PA_FX_COOKIE, NULL, + der_cookie, &enc); + if (ret) + goto cleanup; + + /* Construct the cookie pa-data entry. */ + ret = alloc_padata(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa); + memcpy(pa->contents, "MIT1", 4); + store_32_be(kvno, pa->contents + 4); + memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length); + *cookie_out = pa; + +cleanup: + krb5_free_data(context, der_cookie); + krb5_free_data_contents(context, &enc.ciphertext); + return ret; } diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index b8d6e43..bbb4ed2 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -549,6 +549,20 @@ add_auth_indicator(krb5_context context, krb5_kdcpreauth_rock rock, return authind_add(context, indicator, rock->auth_indicators); } +static krb5_boolean +get_cookie(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, krb5_data *out) +{ + return kdc_fast_search_cookie(rock->rstate, pa_type, out); +} + +static krb5_error_code +set_cookie(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, const krb5_data *data) +{ + return kdc_fast_set_cookie(rock->rstate, pa_type, data); +} + static struct krb5_kdcpreauth_callbacks_st callbacks = { 3, max_time_skew, @@ -562,7 +576,9 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = { event_context, have_client_keys, client_keyblock, - add_auth_indicator + add_auth_indicator, + get_cookie, + set_cookie }; static krb5_error_code @@ -752,9 +768,6 @@ hint_list_finish(struct hint_state *state, krb5_error_code code) _("%spreauth required but hint list is empty"), state->hw_only ? "hw" : ""); } - /* If we fail to get the cookie it is probably still reasonable to - * continue with the response. */ - kdc_preauth_get_cookie(state->rock->rstate, state->pa_cur); *state->e_data_out = state->pa_data; state->pa_data = NULL; @@ -840,8 +853,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, state->realm = rock->rstate->realm_data; state->e_data_out = e_data_out; - /* Allocate two extra entries for the cookie and the terminator. */ - state->pa_data = calloc(n_preauth_systems + 2, sizeof(krb5_pa_data *)); + state->pa_data = calloc(n_preauth_systems + 1, sizeof(krb5_pa_data *)); if (!state->pa_data) { free(state); (*respond)(arg); diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 0f49ca0..137952d 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -409,9 +409,6 @@ krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, krb5_keyblock **out_key); -krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, - krb5_pa_data **cookie); - krb5_boolean kdc_fast_hide_client(struct kdc_request_state *state); @@ -421,6 +418,23 @@ kdc_handle_protected_negotiation( krb5_context context, const krb5_keyblock *reply_key, krb5_pa_data ***out_enc_padata); +krb5_error_code +kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *req, krb5_db_entry *local_tgt); + +krb5_boolean kdc_fast_search_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, krb5_data *out); + +krb5_error_code kdc_fast_set_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, + const krb5_data *data); + +krb5_error_code +kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state, + krb5_db_entry *local_tgt, + krb5_const_principal client_princ, + krb5_pa_data **cookie_out); + /* Information handle for kdcpreauth callbacks. All pointers are aliases. */ struct krb5_kdcpreauth_rock_st { krb5_kdc_req *request; diff --git a/src/kdc/reqstate.h b/src/kdc/reqstate.h index 58dd616..38c399d 100644 --- a/src/kdc/reqstate.h +++ b/src/kdc/reqstate.h @@ -40,7 +40,8 @@ struct kdc_request_state { krb5_keyblock *armor_key; krb5_keyblock *strengthen_key; - krb5_pa_data *cookie; + krb5_pa_data **in_cookie_padata; + krb5_pa_data **out_cookie_padata; krb5_int32 fast_options; krb5_int32 fast_internal_flags; kdc_realm_t *realm_data; |