Fix 'winadj-success': since at least one server (boks_sshd) blithely responds
authorjacob <jacob@cda61777-01e9-0310-a592-d414129be87e>
Fri, 1 Jul 2011 21:53:41 +0000 (21:53 +0000)
committerjacob <jacob@cda61777-01e9-0310-a592-d414129be87e>
Fri, 1 Jul 2011 21:53:41 +0000 (21:53 +0000)
to "winadj@putty.projects.tartarus.org" with SSH_MSG_CHANNEL_SUCCESS despite
probably having no idea what it means, treat this just the same as
SSH_MSG_CHANNEL_FAILURE instead of killing the connection.
Tested only as far as making sure that winadj/FAILURE with a normal server
isn't _completely_ broken.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9185 cda61777-01e9-0310-a592-d414129be87e

ssh.c

diff --git a/ssh.c b/ssh.c
index 05530fe..017b48b 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -6627,25 +6627,44 @@ static struct ssh_channel *ssh2_channel_msg(Ssh ssh, struct Packet *pktin)
     return c;
 }
 
+static int ssh2_handle_winadj_response(struct ssh_channel *c)
+{
+    struct winadj *wa = c->v.v2.winadj_head;
+    if (!wa)
+       return FALSE;
+    c->v.v2.winadj_head = wa->next;
+    c->v.v2.remlocwin += wa->size;
+    sfree(wa);
+    /*
+     * winadj messages are only sent when the window is fully open, so
+     * if we get an ack of one, we know any pending unthrottle is
+     * complete.
+     */
+    if (c->v.v2.throttle_state == UNTHROTTLING)
+       c->v.v2.throttle_state = UNTHROTTLED;
+    return TRUE;
+}
+
 static void ssh2_msg_channel_success(Ssh ssh, struct Packet *pktin)
 {
     /*
      * This should never get called.  All channel requests are either
-     * sent with want_reply false or are sent before this handler gets
-     * installed.
+     * sent with want_reply false, are sent before this handler gets
+     * installed, or are "winadj@putty" requests, which servers should
+     * never respond to with success.
+     *
+     * However, at least one server ("boks_sshd") is known to return
+     * SUCCESS for channel requests it's never heard of, such as
+     * "winadj@putty". Raised with foxt.com as bug 090916-090424, but
+     * for the sake of a quiet life, we handle it just the same as the
+     * expected FAILURE.
      */
     struct ssh_channel *c;
-    struct winadj *wa;
 
     c = ssh2_channel_msg(ssh, pktin);
     if (!c)
        return;
-    wa = c->v.v2.winadj_head;
-    if (wa)
-       ssh_disconnect(ssh, NULL, "Received SSH_MSG_CHANNEL_SUCCESS for "
-                      "\"winadj@putty.projects.tartarus.org\"",
-                      SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
-    else
+    if (!ssh2_handle_winadj_response(c))
        ssh_disconnect(ssh, NULL,
                       "Received unsolicited SSH_MSG_CHANNEL_SUCCESS",
                       SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
@@ -6660,28 +6679,14 @@ static void ssh2_msg_channel_failure(Ssh ssh, struct Packet *pktin)
      * installed.
      */
     struct ssh_channel *c;
-    struct winadj *wa;
 
     c = ssh2_channel_msg(ssh, pktin);
     if (!c)
        return;
-    wa = c->v.v2.winadj_head;
-    if (!wa) {
+    if (!ssh2_handle_winadj_response(c))
        ssh_disconnect(ssh, NULL,
                       "Received unsolicited SSH_MSG_CHANNEL_FAILURE",
                       SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
-       return;
-    }
-    c->v.v2.winadj_head = wa->next;
-    c->v.v2.remlocwin += wa->size;
-    sfree(wa);
-    /*
-     * winadj messages are only sent when the window is fully open, so
-     * if we get an ack of one, we know any pending unthrottle is
-     * complete.
-     */
-    if (c->v.v2.throttle_state == UNTHROTTLING)
-       c->v.v2.throttle_state = UNTHROTTLED;
 }
 
 static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)