ef8129
--- contrib/mod_sftp/kbdint.c
ef8129
+++ contrib/mod_sftp/kbdint.c
ef8129
@@ -254,6 +254,77 @@ int sftp_kbdint_send_challenge(const cha
ef8129
   return res;
ef8129
 }
ef8129
 
ef8129
+static struct ssh2_packet *read_response_packet(pool *p) {
ef8129
+  struct ssh2_packet *pkt = NULL;
ef8129
+
ef8129
+  /* Keep looping until we get the desired message, or we time out. */
ef8129
+  while (pkt == NULL) {
ef8129
+    int res;
ef8129
+    char mesg_type;
ef8129
+
ef8129
+    pr_signals_handle();
ef8129
+
ef8129
+    pkt = sftp_ssh2_packet_create(kbdint_pool);
ef8129
+    res = sftp_ssh2_packet_read(sftp_conn->rfd, pkt);
ef8129
+    if (res < 0) {
ef8129
+      int xerrno = errno;
ef8129
+
ef8129
+      destroy_pool(pkt->pool);
ef8129
+
ef8129
+      errno = xerrno;
ef8129
+      return NULL;
ef8129
+    }
ef8129
+
ef8129
+    pr_response_clear(&resp_list);
ef8129
+    pr_response_clear(&resp_err_list);
ef8129
+
ef8129
+    /* Per RFC 4253, Section 11, DEBUG, DISCONNECT, IGNORE, and UNIMPLEMENTED
ef8129
+     * messages can occur at any time, even during KEX.  We have to be prepared
ef8129
+     * for this, and Do The Right Thing(tm).
ef8129
+     */
ef8129
+
ef8129
+    mesg_type = sftp_ssh2_packet_get_mesg_type(pkt);
ef8129
+
ef8129
+    switch (mesg_type) {
ef8129
+      case SFTP_SSH2_MSG_DEBUG:
ef8129
+        sftp_ssh2_packet_handle_debug(pkt);
ef8129
+        pkt = NULL;
ef8129
+        break;
ef8129
+
ef8129
+      case SFTP_SSH2_MSG_DISCONNECT:
ef8129
+        sftp_ssh2_packet_handle_disconnect(pkt);
ef8129
+        pkt = NULL;
ef8129
+        break;
ef8129
+
ef8129
+      case SFTP_SSH2_MSG_IGNORE:
ef8129
+        sftp_ssh2_packet_handle_ignore(pkt);
ef8129
+        pkt = NULL;
ef8129
+        break;
ef8129
+
ef8129
+      case SFTP_SSH2_MSG_UNIMPLEMENTED:
ef8129
+        sftp_ssh2_packet_handle_unimplemented(pkt);
ef8129
+        pkt = NULL;
ef8129
+        break;
ef8129
+
ef8129
+      case SFTP_SSH2_MSG_USER_AUTH_INFO_RESP:
ef8129
+        pr_trace_msg(trace_channel, 13,
ef8129
+          "received expected %s message",
ef8129
+          sftp_ssh2_packet_get_mesg_type_desc(mesg_type));
ef8129
+        break;
ef8129
+
ef8129
+      default:
ef8129
+        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
ef8129
+          "expecting USER_AUTH_INFO_RESP message, received %s (%d)",
ef8129
+          sftp_ssh2_packet_get_mesg_type_desc(mesg_type), mesg_type);
ef8129
+        destroy_pool(pkt->pool);
ef8129
+        errno = EPERM;
ef8129
+        return NULL;
ef8129
+    }
ef8129
+  }
ef8129
+
ef8129
+  return pkt;
ef8129
+}
ef8129
+
ef8129
 int sftp_kbdint_recv_response(pool *p, uint32_t expected_count,
ef8129
     uint32_t *rcvd_count, const char ***responses) {
ef8129
   register unsigned int i;
ef8129
@@ -261,9 +332,7 @@ int sftp_kbdint_recv_response(pool *p, u
ef8129
   cmd_rec *cmd;
ef8129
   array_header *list;
ef8129
   uint32_t buflen, resp_count;
ef8129
-  struct ssh2_packet *pkt;
ef8129
-  char mesg_type;
ef8129
-  int res;
ef8129
+  struct ssh2_packet *pkt = NULL;
ef8129
 
ef8129
   if (p == NULL ||
ef8129
       rcvd_count == NULL ||
ef8129
@@ -272,28 +341,13 @@ int sftp_kbdint_recv_response(pool *p, u
ef8129
     return -1;
ef8129
   }
ef8129
 
ef8129
-  pkt = sftp_ssh2_packet_create(kbdint_pool);
ef8129
-
ef8129
-  res = sftp_ssh2_packet_read(sftp_conn->rfd, pkt);
ef8129
-  if (res < 0) {
ef8129
-    destroy_pool(pkt->pool);
ef8129
-    return res;
ef8129
+  pkt = read_response_packet(p);
ef8129
+  if (pkt == NULL) {
ef8129
+    return -1;
ef8129
   }
ef8129
 
ef8129
-  pr_response_clear(&resp_list);
ef8129
-  pr_response_clear(&resp_err_list);
ef8129
   pr_response_set_pool(pkt->pool);
ef8129
 
ef8129
-  mesg_type = sftp_ssh2_packet_get_mesg_type(pkt);
ef8129
-  if (mesg_type != SFTP_SSH2_MSG_USER_AUTH_INFO_RESP) {
ef8129
-    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
ef8129
-      "expecting USER_AUTH_INFO_RESP message, received %s (%d)",
ef8129
-      sftp_ssh2_packet_get_mesg_type_desc(mesg_type), mesg_type);
ef8129
-    destroy_pool(pkt->pool);
ef8129
-    errno = EPERM;
ef8129
-    return -1;
ef8129
-  }
ef8129
-
ef8129
   cmd = pr_cmd_alloc(pkt->pool, 2, pstrdup(pkt->pool, "USER_AUTH_INFO_RESP"));
ef8129
   cmd->arg = "(data)";
ef8129