]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Client AS-req error handling for FAST
authorSam Hartman <hartmans@mit.edu>
Thu, 26 Mar 2009 05:36:58 +0000 (05:36 +0000)
committerSam Hartman <hartmans@mit.edu>
Thu, 26 Mar 2009 05:36:58 +0000 (05:36 +0000)
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

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/fast@22131 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int-pkinit.h
src/include/k5-int.h
src/kdc/kdc_util.c
src/lib/krb5/krb/fast.c
src/lib/krb5/krb/kfree.c
src/lib/krb5/libkrb5.exports

index e75c8031f82161316e0dd2a8fcfc0377a0321968..2fb5f871921935679cbedda8b96478275051c147 100644 (file)
@@ -101,6 +101,9 @@ typedef struct _krb5_trusted_ca {
 } 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_trusted_certifiers
 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 */
index 8d5d817f8fa60020117e5320dbc9ef31f3f9d41e..957f39c8c50a684811006ae11eec1724f345ebb4 100644 (file)
@@ -1074,6 +1074,10 @@ krb5_error_code krb5_process_padata
                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);
 
index a6d8eabe49eb98ea09cfd692fed39d5d0ad2cee6..b7db1edb264cc2f372b8906d9929e6ce60019e77 100644 (file)
@@ -217,17 +217,7 @@ comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket,
 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 
index e224a2d84f9e813b504bdcf70e4ed5ef5229f567..446a6212663d1c6b3ae1ecef8b8dcfc42d72f9a9 100644 (file)
@@ -153,24 +153,88 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta
 {
     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)
-       if (retval == 0) {
-           *out_padata = result;
-
+           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);
-       krb5_set_error_message(context, retval,
-                              "Error decoding padata in error reply");
-       return retval;
-    }
-    return 0;
+       result = NULL;
+       if (retval == 0) {
+           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;
+               }
+           krb5_free_pa_data(context, result);
+           krb5_set_error_message(context, retval,
+                                  "Error decoding padata in error reply");
+           return retval;
+       }
+       }
+    return retval;
 }
 
 krb5_error_code
@@ -194,3 +258,20 @@ krb5int_fast_free_state( krb5_context context, struct krb5int_fast_request_state
     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;
+}
+
index a1f71c1eda72d25f3d6bfef842e6fdc4b9ca45ed..5813fc0242b7daf691dda5832a896aa2532b2f4a 100644 (file)
@@ -831,3 +831,16 @@ void krb5_free_fast_finished
   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);
+}
index 886553c222a2bebd5c87e345d3bd41d4b8e621be..17b8fd3c65e78aeef92692ba4fb04256724cf4d9 100644 (file)
@@ -37,6 +37,7 @@ decode_krb5_setpw_req
 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_tgt_creds
 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_cc_default
 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