From: Sam Hartman Date: Fri, 3 Apr 2009 03:39:50 +0000 (+0000) Subject: Implement KDC side cookie handling X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5937359d82674ce1b80eb6455c21913d3ec8ed03;p=thirdparty%2Fkrb5.git Implement KDC side cookie handling Return a constant cookie in errors to indicate that clients should continue their conversations. git-svn-id: svn://anonsvn.mit.edu/krb5/branches/fast@22163 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index a95398e0a4..da965f591a 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -342,8 +342,8 @@ krb5_error_code kdc_fast_handle_error krb5_fast_response resp; krb5_error fx_error; krb5_data *encoded_fx_error = NULL, *encrypted_reply = NULL; - krb5_pa_data pa[2]; - krb5_pa_data *outer_pa[3]; + krb5_pa_data pa[1]; + krb5_pa_data *outer_pa[3], *cookie = NULL; krb5_pa_data **inner_pa = NULL; size_t size = 0; krb5_data *encoded_e_data = NULL; @@ -369,7 +369,13 @@ krb5_error_code kdc_fast_handle_error pa[0].length = encoded_fx_error->length; pa[0].contents = (unsigned char *) encoded_fx_error->data; inner_pa[size++] = &pa[0]; - resp.padata = inner_pa; + if (find_pa_data(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; resp.rep_key = NULL; resp.finished = NULL; @@ -378,6 +384,11 @@ krb5_error_code kdc_fast_handle_error 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; @@ -399,3 +410,30 @@ krb5_error_code kdc_fast_handle_error krb5_free_data(kdc_context, encoded_fx_error); return retval; } + +krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, + krb5_pa_data **cookie) +{ + 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) + return ENOMEM; + pa = calloc(1, sizeof(krb5_pa_data)); + if (pa == NULL) { + free(contents); + return ENOMEM; + } + pa->pa_type = KRB5_PADATA_FX_COOKIE; + pa->length = strlen(contents); + pa->contents = (unsigned char *) contents; + *cookie = pa; + return 0; +} diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index cf269753d1..22ebe5393c 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -961,7 +961,8 @@ void get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client, e_data->data = 0; hw_only = isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH); - pa_data = malloc(sizeof(krb5_pa_data *) * (n_preauth_systems+1)); + /* Allocate 1 entry for the terminator and one for the cookie*/ + pa_data = malloc(sizeof(krb5_pa_data *) * (n_preauth_systems+21)); if (pa_data == 0) return; memset(pa_data, 0, sizeof(krb5_pa_data *) * (n_preauth_systems+1)); @@ -995,6 +996,8 @@ void get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client, "%spreauth required but hint list is empty", hw_only ? "hw" : ""); } +/* If we fail to get the cookie it is probably still reasonable to continue with the response*/ + kdc_preauth_get_cookie(request->kdc_state, pa); retval = encode_krb5_padata_sequence(pa_data, &edat); if (retval) goto errout; diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 90de8d39b7..e9ccc4477d 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -331,6 +331,9 @@ krb5_error_code kdc_fast_handle_error krb5_kdc_req *request, krb5_pa_data **in_padata, krb5_error *err); +krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, + krb5_pa_data **cookie); +