Description: Prevent file descriptor leaks when multiple selects are issued.
 Cherry-picking two changes committed upstream:
 .
 https://github.com/heimdal/heimdal/commit/3f71aca59193785880469fd0757a651e965a594e
 https://github.com/heimdal/heimdal/commit/a95cae113dcb043e5a32d6576db82daaf4569ab2
Author: Dana Koch <dsk@google.com>
Reviewed-by: Love Hörnquist Åstrand <lha@h5l.org>
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/heimdal/+bug/1191704
Last-Update: 2013-07-03
Origin: upstream, commit:3f71aca59193785880469fd0757a651e965a594e, commit:a95cae113dcb043e5a32d6576db82daaf4569ab2
Applied-Upstream: 2012-11-24

Index: heimdal-1.6~git20120311.dfsg.1/kdc/connect.c
===================================================================
--- heimdal-1.6~git20120311.dfsg.1.orig/kdc/connect.c	2013-07-03 14:54:34.323464468 +0200
+++ heimdal-1.6~git20120311.dfsg.1/kdc/connect.c	2013-07-03 14:57:48.834256912 +0200
@@ -824,6 +824,48 @@
     }
 }
 
+krb5_boolean
+realloc_descrs(struct descr **d, unsigned int *ndescr)
+{
+    struct descr *tmp;
+    size_t i;
+
+    tmp = realloc(*d, (*ndescr + 4) * sizeof(**d));
+    if(tmp == NULL)
+        return FALSE;
+
+    *d = tmp;
+    reinit_descrs (*d, *ndescr);
+    memset(*d + *ndescr, 0, 4 * sizeof(**d));
+    for(i = *ndescr; i < *ndescr + 4; i++)
+        init_descr (*d + i);
+
+    *ndescr += 4;
+
+    return TRUE;
+}
+
+int
+next_min_free(krb5_context context, struct descr **d, unsigned int *ndescr)
+{
+    size_t i;
+    int min_free;
+
+    for(i = 0; i < *ndescr; i++) {
+        int s = (*d + i)->s;
+        if(rk_IS_BAD_SOCKET(s))
+            return i;
+    }
+
+    min_free = *ndescr;
+    if(!realloc_descrs(d, ndescr)) {
+        min_free = -1;
+        krb5_warnx(context, "No memory");
+    }
+
+    return min_free;
+}
+
 void
 loop(krb5_context context,
      krb5_kdc_configuration *config)
@@ -862,22 +904,6 @@
 #endif
 #endif
 		FD_SET(d[i].s, &fds);
-	    } else if(min_free < 0 || i < (size_t)min_free)
-		min_free = i;
-	}
-	if(min_free == -1){
-	    struct descr *tmp;
-	    tmp = realloc(d, (ndescr + 4) * sizeof(*d));
-	    if(tmp == NULL)
-		krb5_warnx(context, "No memory");
-	    else {
-		d = tmp;
-		reinit_descrs (d, ndescr);
-		memset(d + ndescr, 0, 4 * sizeof(*d));
-		for(i = ndescr; i < ndescr + 4; i++)
-		    init_descr (&d[i]);
-		min_free = ndescr;
-		ndescr += 4;
 	    }
 	}
 
@@ -893,6 +919,8 @@
 	default:
 	    for(i = 0; i < ndescr; i++)
 		if(!rk_IS_BAD_SOCKET(d[i].s) && FD_ISSET(d[i].s, &fds)) {
+		    min_free = next_min_free(context, &d, &ndescr);
+
 		    if(d[i].type == SOCK_DGRAM)
 			handle_udp(context, config, &d[i]);
 		    else if(d[i].type == SOCK_STREAM)
