heimdal: fix endless loop for specific KDC error code
authorUri Simchoni <urisimchoni@gmail.com>
Mon, 15 Jun 2015 19:33:28 +0000 (22:33 +0300)
committerJeremy Allison <jra@samba.org>
Wed, 17 Jun 2015 00:34:31 +0000 (02:34 +0200)
When sending a Kerberos request, if at least one of the available
KDCs repeatedly replies with an error response of
KRB5KDC_ERR_SVC_UNAVAILABLE, and all other KDCs, if there are any,
do not reply at all or cannot be contacted, then the code repeatedly
retries to send the request in an endless loop.

This is fixed in upstream (post 1.5 branch) heimdal but the code
there is vastly refactored, so this is an independent fix to the issue.

Signed-off-by: Uri Simchoni <urisimchoni@gmail.com>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Jun 17 02:34:31 CEST 2015 on sn-devel-104

source4/heimdal/lib/krb5/krbhst.c
source4/heimdal/lib/krb5/send_to_kdc.c

index 3242cdb9995601194439147f95172aa1d7928040..9822bfb2f6d2751693c214066d9381c554a46241 100644 (file)
@@ -157,6 +157,7 @@ struct krb5_krbhst_data {
                                krb5_krbhst_info**);
 
     unsigned int fallback_count;
+    unsigned int try_count;
 
     struct krb5_krbhst_info *hosts, **index, **end;
 };
@@ -1011,6 +1012,21 @@ krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
     free(handle);
 }
 
+void KRB5_LIB_FUNCTION
+krb5_krbhst_retry(krb5_context context, krb5_krbhst_handle handle)
+{
+    ++handle->try_count;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_krbhst_retry_exceeded(krb5_context context, krb5_krbhst_handle handle)
+{
+    if (handle->try_count >= context->max_retries)
+        return TRUE;
+    else
+        return FALSE;
+}
+
 /* backwards compatibility ahead */
 
 static krb5_error_code
index edf1d33c9d1c17bd405633a426c6c881690f49f2..ee8f6aaff1f50e3e7d1b801f36c81986fab5270e 100644 (file)
@@ -375,7 +375,7 @@ krb5_sendto (krb5_context context,
 
      krb5_data_zero(receive);
 
-     for (i = 0; i < context->max_retries; ++i) {
+     while (!krb5_krbhst_retry_exceeded(context, handle)) {
         krb5_krbhst_info *hi;
 
         while (krb5_krbhst_next(context, handle, &hi) == 0) {
@@ -443,6 +443,7 @@ krb5_sendto (krb5_context context,
             }
         }
         krb5_krbhst_reset(context, handle);
+        krb5_krbhst_retry(context, handle);
      }
      krb5_clear_error_message (context);
      ret = KRB5_KDC_UNREACH;