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