svn rev #22140: branches/fast/src/lib/krb5/ error_tables/ krb/
hartmans@MIT.EDU
hartmans at MIT.EDU
Thu Mar 26 01:37:26 EDT 2009
http://src.mit.edu/fisheye/changelog/krb5/?cs=22140
Commit By: hartmans
Log Message:
FAST encrypted response for client
Implement routine to decrypt FAST response. Use this in
process_error. Implement new krb5int_fast_process_response to process
FAST in an AS-REP or TGS-rep. Call that routine from
krb5_get_init_creds.
Add a new error code for FAST required but not supported.
Changed Files:
U branches/fast/src/lib/krb5/error_tables/krb5_err.et
U branches/fast/src/lib/krb5/krb/fast.c
U branches/fast/src/lib/krb5/krb/fast.h
U branches/fast/src/lib/krb5/krb/get_in_tkt.c
Modified: branches/fast/src/lib/krb5/error_tables/krb5_err.et
===================================================================
--- branches/fast/src/lib/krb5/error_tables/krb5_err.et 2009-03-26 05:37:23 UTC (rev 22139)
+++ branches/fast/src/lib/krb5/error_tables/krb5_err.et 2009-03-26 05:37:25 UTC (rev 22140)
@@ -347,4 +347,5 @@
error_code KRB5_PLUGIN_OP_NOTSUPP, "Plugin does not support the operaton"
error_code KRB5_ERR_INVALID_UTF8, "Invalid UTF-8 string"
+error_code KRB5_ERR_FAST_REQUIRED, "FAST protected pre-authentication required but not supported by KDC"
end
Modified: branches/fast/src/lib/krb5/krb/fast.c
===================================================================
--- branches/fast/src/lib/krb5/krb/fast.c 2009-03-26 05:37:23 UTC (rev 22139)
+++ branches/fast/src/lib/krb5/krb/fast.c 2009-03-26 05:37:25 UTC (rev 22140)
@@ -246,6 +246,63 @@
return retval;
}
+static krb5_error_code decrypt_fast_reply
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_pa_data **in_padata,
+ krb5_fast_response **response)
+{
+ krb5_error_code retval = 0;
+ krb5_data scratch;
+ krb5_enc_data *encrypted_response = NULL;
+ krb5_pa_data *fx_reply = NULL;
+ krb5_fast_response *local_resp = NULL;
+ assert(state != NULL);
+ if (state->armor_key == NULL)
+ return 0;
+ fx_reply = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FX_FAST);
+ if (fx_reply == NULL)
+ retval = KRB5_ERR_FAST_REQUIRED;
+ if (retval == 0) {
+ scratch.data = (char *) fx_reply->contents;
+ scratch.length = fx_reply->length;
+ retval = decode_krb5_pa_fx_fast_reply(&scratch, &encrypted_response);
+ }
+ scratch.data = NULL;
+ if (retval == 0) {
+ scratch.data = malloc(encrypted_response->ciphertext.length);
+ if (scratch.data == NULL)
+ retval = ENOMEM;
+ scratch.length = encrypted_response->ciphertext.length;
+ }
+ if (retval == 0)
+ retval = krb5_c_decrypt(context, state->armor_key,
+ KRB5_KEYUSAGE_FAST_REP, NULL,
+ encrypted_response, &scratch);
+ if (retval != 0) {
+ const char * errmsg;
+ errmsg = krb5_get_error_message(context, retval);
+ krb5_set_error_message(context, retval, "%s while decrypting FAST reply", errmsg);
+ krb5_free_error_message(context, errmsg);
+ }
+ if (retval == 0)
+ retval = decode_krb5_fast_response(&scratch, &local_resp);
+ if (retval == 0) {
+ if (local_resp->nonce != state->nonce) {
+ retval = KRB5_KDCREP_MODIFIED;
+ krb5_set_error_message(context, retval, "nonce modified in FAST response: KDC response modified");
+ }
+ }
+ if (retval == 0) {
+ *response = local_resp;
+ local_resp = NULL;
+ }
+ if (scratch.data)
+ free(scratch.data);
+ if (encrypted_response)
+ krb5_free_enc_data(context, encrypted_response);
+ return retval;
+}
+
/*
* FAST separates two concepts: the set of padata we're using to
* decide what pre-auth mechanisms to use and the set of padata we're
@@ -269,15 +326,15 @@
*out_padata = NULL;
*retry = 0;
if (state->armor_key) {
- krb5_pa_data *fast_pa, *fx_error_pa;
+ krb5_pa_data *fx_error_pa;
krb5_pa_data **result = NULL;
krb5_data scratch, *encoded_td = NULL;
krb5_error *fx_error = NULL;
krb5_fast_response *fast_response = NULL;
retval = decode_krb5_padata_sequence(&err_reply->e_data, &result);
if (retval == 0)
- fast_pa = krb5int_find_pa_data(context, result, KRB5_PADATA_FX_FAST);
- if (retval || fast_pa == NULL) {
+ retval = decrypt_fast_reply(context, state, result, &fast_response);
+ if (retval) {
/*This can happen if the KDC does not understand FAST. We
* don't expect that, but treating it as the fatal error
* indicated by the KDC seems reasonable.
@@ -286,17 +343,8 @@
krb5_free_pa_data(context, result);
return 0;
}
- scratch.data = (char *) fast_pa->contents;
- scratch.length = fast_pa->length;
- retval = decode_krb5_fast_response(&scratch, &fast_response);
krb5_free_pa_data(context, result);
result = NULL;
- if (retval == 0) {
- if (fast_response->nonce != state->nonce) {
- krb5_set_error_message(context, KRB5_KDCREP_MODIFIED, "Nonce in reply did not match expected value");
- retval = KRB5_KDCREP_MODIFIED;
- }
- }
if (retval == 0) {
fx_error_pa = krb5int_find_pa_data(context, fast_response->padata, KRB5_PADATA_FX_ERROR);
if (fx_error_pa == NULL) {
@@ -317,7 +365,7 @@
*/
if (retval == 0)
retval = encode_krb5_typed_data( (krb5_typed_data **) fast_response->padata,
- &encoded_td);
+ &encoded_td);
if (retval == 0) {
fx_error->e_data = *encoded_td;
free(encoded_td); /*contents owned by fx_error*/
@@ -353,10 +401,58 @@
"Error decoding padata in error reply");
return retval;
}
+ }
+ return retval;
+}
+
+
+krb5_error_code krb5int_fast_process_response
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_kdc_rep *resp,
+ krb5_keyblock **as_key)
+{
+ krb5_error_code retval = 0;
+ krb5_fast_response *fast_response = NULL;
+ krb5_data *encoded_ticket = NULL;
+ krb5_boolean cksum_valid;
+ krb5_clear_error_message(context);
+ *as_key = NULL;
+ retval = decrypt_fast_reply(context, state, resp->padata,
+ &fast_response);
+ if (retval == 0) {
+ if (fast_response->finished == 0) {
+ retval = KRB5_KDCREP_MODIFIED;
+ krb5_set_error_message(context, retval, "FAST response missing finish message in KDC reply");
}
+ }
+ if (retval == 0)
+ retval = encode_krb5_ticket(resp->ticket, &encoded_ticket);
+ if (retval == 0)
+ retval = krb5_c_verify_checksum(context, state->armor_key,
+ KRB5_KEYUSAGE_FAST_FINISHED,
+ encoded_ticket,
+ &fast_response->finished->ticket_checksum,
+ &cksum_valid);
+ if (retval == 0 && cksum_valid == 0) {
+ retval = KRB5_KDCREP_MODIFIED;
+ krb5_set_error_message(context, retval, "ticket modified in KDC reply");
+ }
+ if (retval == 0) {
+ krb5_free_principal(context, resp->client);
+ resp->client = fast_response->finished->client;
+ fast_response->finished->client = NULL;
+ *as_key = fast_response->rep_key;
+ fast_response->rep_key = NULL;
+ krb5_free_pa_data(context, resp->padata);
+ resp->padata = fast_response->padata;
+ fast_response->padata = NULL;
+ }
+ if (fast_response)
+ krb5_free_fast_response(context, fast_response);
+ if (encoded_ticket)
+ krb5_free_data(context, encoded_ticket);
return retval;
}
-
krb5_error_code
krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state)
{
@@ -381,6 +477,7 @@
free(state->cookie);
state->cookie = NULL;
}
+ free(state);
}
krb5_pa_data * krb5int_find_pa_data
Modified: branches/fast/src/lib/krb5/krb/fast.h
===================================================================
--- branches/fast/src/lib/krb5/krb/fast.h 2009-03-26 05:37:23 UTC (rev 22139)
+++ branches/fast/src/lib/krb5/krb/fast.h 2009-03-26 05:37:25 UTC (rev 22140)
@@ -58,6 +58,11 @@
krb5_error **err_replyptr , krb5_pa_data ***out_padata,
krb5_boolean *retry);
+krb5_error_code krb5int_fast_process_response
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_kdc_rep *resp,
+ krb5_keyblock **as_key);
+
krb5_error_code
krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state);
Modified: branches/fast/src/lib/krb5/krb/get_in_tkt.c
===================================================================
--- branches/fast/src/lib/krb5/krb/get_in_tkt.c 2009-03-26 05:37:23 UTC (rev 22139)
+++ branches/fast/src/lib/krb5/krb/get_in_tkt.c 2009-03-26 05:37:25 UTC (rev 22140)
@@ -968,6 +968,7 @@
krb5_data salt;
krb5_data s2kparams;
krb5_keyblock as_key;
+ krb5_keyblock *fast_as_key = NULL;
krb5_error *err_reply;
krb5_kdc_rep *local_as_reply;
krb5_timestamp time_now;
@@ -993,7 +994,7 @@
preauth_to_use = NULL;
kdc_padata = NULL;
as_key.length = 0;
- salt.length = 0;
+ salt.length = 0;
salt.data = NULL;
local_as_reply = 0;
@@ -1396,6 +1397,10 @@
/* process any preauth data in the as_reply */
krb5_clear_preauth_context_use_counts(context);
+ ret = krb5int_fast_process_response(context, fast_state,
+ local_as_reply, &fast_as_key);
+ if (ret)
+ goto cleanup;
if ((ret = sort_krb5_padata_sequence(context, &request.server->realm,
local_as_reply->padata)))
goto cleanup;
@@ -1441,8 +1446,14 @@
it. If decrypting the as_rep fails, or if there isn't an
as_key at all yet, then use the gak_fct to get one, and try
again. */
-
- if (as_key.length)
+ if (fast_as_key) {
+ if (as_key.length)
+ krb5_free_keyblock_contents(context, &as_key);
+ as_key = *fast_as_key;
+ free(fast_as_key);
+ fast_as_key = NULL;
+ }
+ if (as_key.length)
ret = decrypt_as_reply(context, NULL, local_as_reply, NULL,
NULL, &as_key, krb5_kdc_rep_decrypt_proc,
NULL);
@@ -1499,6 +1510,7 @@
}
}
krb5_preauth_request_context_fini(context);
+ krb5_free_keyblock(context, fast_as_key);
if (fast_state)
krb5int_fast_free_state(context, fast_state);
if (out_padata)
More information about the cvs-krb5
mailing list