svn rev #22131: branches/fast/src/ include/ kdc/ lib/krb5/ lib/krb5/krb/
hartmans@MIT.EDU
hartmans at MIT.EDU
Thu Mar 26 01:36:59 EDT 2009
http://src.mit.edu/fisheye/changelog/krb5/?cs=22131
Commit By: hartmans
Log Message:
Client AS-req error handling for FAST
Find and decode the fast_response and fx_error.
Pull out padata and re-encode as typed-data
* Implement krb5_free_typed_data
* implement error handling logic in krb5int_fast_handle_error
* Implement krb5int_find_pa_data
Changed Files:
U branches/fast/src/include/k5-int-pkinit.h
U branches/fast/src/include/k5-int.h
U branches/fast/src/kdc/kdc_util.c
U branches/fast/src/lib/krb5/krb/fast.c
U branches/fast/src/lib/krb5/krb/kfree.c
U branches/fast/src/lib/krb5/libkrb5.exports
Modified: branches/fast/src/include/k5-int-pkinit.h
===================================================================
--- branches/fast/src/include/k5-int-pkinit.h 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/include/k5-int-pkinit.h 2009-03-26 05:36:58 UTC (rev 22131)
@@ -101,6 +101,9 @@
} krb5_trusted_ca;
/* typed data */
+/* The FAST error handling logic currently assumes that this structure and krb5_pa_data * can be safely cast to each other
+ * if this structure changes, that code needs to be updated to copy.
+ */
typedef struct _krb5_typed_data {
krb5_magic magic;
krb5_int32 type;
@@ -267,4 +270,6 @@
krb5_error_code decode_krb5_td_dh_parameters
(const krb5_data *, krb5_algorithm_identifier ***);
+void krb5_free_typed_data(krb5_context, krb5_typed_data **);
+
#endif /* _KRB5_INT_PKINIT_H */
Modified: branches/fast/src/include/k5-int.h
===================================================================
--- branches/fast/src/include/k5-int.h 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/include/k5-int.h 2009-03-26 05:36:58 UTC (rev 22131)
@@ -1074,6 +1074,10 @@
krb5_creds *,
krb5_int32 *);
+krb5_pa_data * krb5int_find_pa_data
+(krb5_context, krb5_pa_data * const *, krb5_preauthtype);
+/* Does not return a copy; original padata sequence responsible for freeing*/
+
void krb5_free_etype_info
(krb5_context, krb5_etype_info);
Modified: branches/fast/src/kdc/kdc_util.c
===================================================================
--- branches/fast/src/kdc/kdc_util.c 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/kdc/kdc_util.c 2009-03-26 05:36:58 UTC (rev 22131)
@@ -217,17 +217,7 @@
krb5_pa_data *
find_pa_data(krb5_pa_data **padata, krb5_preauthtype pa_type)
{
- krb5_pa_data **tmppa;
-
- if (padata == NULL)
- return NULL;
-
- for (tmppa = padata; *tmppa != NULL; tmppa++) {
- if ((*tmppa)->pa_type == pa_type)
- break;
- }
-
- return *tmppa;
+return krb5int_find_pa_data(kdc_context, padata, pa_type);
}
krb5_error_code
Modified: branches/fast/src/lib/krb5/krb/fast.c
===================================================================
--- branches/fast/src/lib/krb5/krb/fast.c 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/lib/krb5/krb/fast.c 2009-03-26 05:36:58 UTC (rev 22131)
@@ -153,24 +153,88 @@
{
krb5_error_code retval = 0;
krb5_error *err_reply = *err_replyptr;
- *retry = (err_reply->e_data.length > 0);
*out_padata = NULL;
- if ((err_reply->error == KDC_ERR_PREAUTH_REQUIRED
- ||err_reply->error == KDC_ERR_PREAUTH_FAILED) && err_reply->e_data.length) {
+ if (state->armor_key) {
+ krb5_pa_data *fast_pa, *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) {
+ /*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.
+ */
+ *retry = 0;
+ 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) {
- *out_padata = result;
+ fx_error_pa = krb5int_find_pa_data(context, fast_response->padata, KRB5_PADATA_FX_ERROR);
+ if (fx_error_pa == NULL) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, "Expecting FX_ERROR pa-data inside FAST container");
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ }
+ if (retval == 0) {
+ scratch.data = (char *) fx_error_pa->contents;
+ scratch.length = fx_error_pa->length;
+ retval = decode_krb5_error(&scratch, &fx_error);
+ }
+ /*
+ * krb5_pa_data and krb5_typed_data are safe to cast between:
+ * they have the same type fields in the same order.
+ * (krb5_preauthtype is a krb5_int32). If krb5_typed_data is
+ * ever changed then this will need to be a copy not a cast.
+ */
+ if (retval == 0)
+ retval = encode_krb5_typed_data( (krb5_typed_data **) fast_response->padata,
+ &encoded_td);
+ if (retval == 0) {
+ fx_error->e_data = *encoded_td;
+ free(encoded_td); /*contents owned by fx_error*/
+ encoded_td = NULL;
+ krb5_free_error(context, err_reply);
+ *err_replyptr = fx_error;
+ fx_error = NULL;
+ *out_padata = fast_response->padata;
+ fast_response->padata = NULL;
+ /*
+ * If there is more than the fx_error padata, then we want
+ * to retry the error
+ */
+ *retry = (*out_padata)[1] != NULL;
+ }
+ if (fx_error)
+ krb5_free_error(context, fx_error);
+ krb5_free_fast_response(context, fast_response);
+ } else { /*not FAST*/
+ *retry = (err_reply->e_data.length > 0);
+ if ((err_reply->error == KDC_ERR_PREAUTH_REQUIRED
+ ||err_reply->error == KDC_ERR_PREAUTH_FAILED) && err_reply->e_data.length) {
+ krb5_pa_data **result = NULL;
+ retval = decode_krb5_padata_sequence(&err_reply->e_data, &result);
+ if (retval == 0)
+ if (retval == 0) {
+ *out_padata = result;
- return 0;
+ return 0;
+ }
+ krb5_free_pa_data(context, result);
+ krb5_set_error_message(context, retval,
+ "Error decoding padata in error reply");
+ return retval;
}
- krb5_free_pa_data(context, result);
- krb5_set_error_message(context, retval,
- "Error decoding padata in error reply");
- return retval;
- }
- return 0;
+ }
+ return retval;
}
krb5_error_code
@@ -194,3 +258,20 @@
krb5_free_fast_armor(context, state->armor);
krb5_free_data_contents(context, &state->cookie_contents);
}
+
+krb5_pa_data * krb5int_find_pa_data
+(krb5_context context, krb5_pa_data *const *padata, krb5_preauthtype pa_type)
+{
+ krb5_pa_data * const *tmppa;
+
+ if (padata == NULL)
+ return NULL;
+
+ for (tmppa = padata; *tmppa != NULL; tmppa++) {
+ if ((*tmppa)->pa_type == pa_type)
+ break;
+ }
+
+ return *tmppa;
+}
+
Modified: branches/fast/src/lib/krb5/krb/kfree.c
===================================================================
--- branches/fast/src/lib/krb5/krb/kfree.c 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/lib/krb5/krb/kfree.c 2009-03-26 05:36:58 UTC (rev 22131)
@@ -831,3 +831,16 @@
krb5_free_checksum_contents(context, &val->checksum);
krb5_free_checksum_contents(context, &val->ticket_checksum);
}
+
+void krb5_free_typed_data(krb5_context context, krb5_typed_data **in)
+{
+ int i = 0;
+ if (in == NULL) return;
+ while (in[i] != NULL) {
+ if (in[i]->data != NULL)
+ free(in[i]->data);
+ free(in[i]);
+ i++;
+ }
+ free(in);
+}
Modified: branches/fast/src/lib/krb5/libkrb5.exports
===================================================================
--- branches/fast/src/lib/krb5/libkrb5.exports 2009-03-26 05:36:56 UTC (rev 22130)
+++ branches/fast/src/lib/krb5/libkrb5.exports 2009-03-26 05:36:58 UTC (rev 22131)
@@ -37,6 +37,7 @@
decode_krb5_tgs_rep
decode_krb5_tgs_req
decode_krb5_ticket
+decode_krb5_typed_data
encode_krb5_alt_method
encode_krb5_ap_rep
encode_krb5_ap_rep_enc_part
@@ -269,6 +270,7 @@
krb5_free_ticket
krb5_free_tickets
krb5_free_tkt_authent
+krb5_free_typed_data
krb5_free_unparsed_name
krb5_fwd_tgt_creds
krb5_gen_portaddr
@@ -519,6 +521,7 @@
krb5int_cleanup_library
krb5int_cm_call_select
krb5int_copy_data_contents_add0
+krb5int_find_pa_data
krb5int_foreach_localaddr
krb5int_free_addrlist
krb5int_init_context_kdc
More information about the cvs-krb5
mailing list