]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - ssh.c
More strictness in ssh_channel_msg().
[PuTTY.git] / ssh.c
diff --git a/ssh.c b/ssh.c
index df303b7be12276ee29cc5b93b8a69efd77995c54..e2b2d0e3dd34e63f900df889a26e0889cc657903 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -365,6 +365,7 @@ static int do_ssh1_login(Ssh ssh, const unsigned char *in, int inlen,
 static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
                             struct Packet *pktin);
 static void ssh_channel_init(struct ssh_channel *c);
+static struct ssh_channel *ssh_channel_msg(Ssh ssh, struct Packet *pktin);
 static void ssh2_channel_check_close(struct ssh_channel *c);
 static void ssh_channel_destroy(struct ssh_channel *c);
 static void ssh_channel_unthrottle(struct ssh_channel *c, int bufsize);
@@ -985,6 +986,14 @@ struct ssh_tag {
     int cross_certifying;
 };
 
+static const char *ssh_pkt_type(Ssh ssh, int type)
+{
+    if (ssh->version == 1)
+       return ssh1_pkt_type(type);
+    else
+       return ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx, type);
+}
+
 #define logevent(s) logevent(ssh->frontend, s)
 
 /* logevent, only printf-formatted. */
@@ -5609,13 +5618,11 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
 
 static void ssh1_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
 {
-    unsigned int remoteid = ssh_pkt_getuint32(pktin);
-    unsigned int localid = ssh_pkt_getuint32(pktin);
     struct ssh_channel *c;
 
-    c = find234(ssh->channels, &remoteid, ssh_channelfind);
+    c = ssh_channel_msg(ssh, pktin);
     if (c && c->type == CHAN_SOCKDATA_DORMANT) {
-       c->remoteid = localid;
+       c->remoteid = ssh_pkt_getuint32(pktin);
        c->halfopen = FALSE;
        c->type = CHAN_SOCKDATA;
        c->throttling_conn = 0;
@@ -5635,10 +5642,9 @@ static void ssh1_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
 
 static void ssh1_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
 {
-    unsigned int remoteid = ssh_pkt_getuint32(pktin);
     struct ssh_channel *c;
 
-    c = find234(ssh->channels, &remoteid, ssh_channelfind);
+    c = ssh_channel_msg(ssh, pktin);
     if (c && c->type == CHAN_SOCKDATA_DORMANT) {
        logevent("Forwarded connection refused by server");
        pfd_close(c->u.pfd.pf);
@@ -5650,10 +5656,10 @@ static void ssh1_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
 static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
 {
     /* Remote side closes a channel. */
-    unsigned i = ssh_pkt_getuint32(pktin);
     struct ssh_channel *c;
-    c = find234(ssh->channels, &i, ssh_channelfind);
-    if (c && !c->halfopen) {
+
+    c = ssh_channel_msg(ssh, pktin);
+    if (c) {
 
         if (pktin->type == SSH1_MSG_CHANNEL_CLOSE &&
             !(c->closes & CLOSES_RCVD_EOF)) {
@@ -5694,8 +5700,9 @@ static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
             !(c->closes & CLOSES_RCVD_CLOSE)) {
 
             if (!(c->closes & CLOSES_SENT_EOF)) {
-                bombout(("Received CHANNEL_CLOSE_CONFIRMATION for channel %d"
-                         " for which we never sent CHANNEL_CLOSE\n", i));
+                bombout(("Received CHANNEL_CLOSE_CONFIRMATION for channel %u"
+                         " for which we never sent CHANNEL_CLOSE\n",
+                        c->localid));
             }
 
             c->closes |= CLOSES_RCVD_CLOSE;
@@ -5710,11 +5717,6 @@ static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
 
        if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes))
             ssh_channel_destroy(c);
-    } else {
-       bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n",
-                pktin->type == SSH1_MSG_CHANNEL_CLOSE ? "" :
-                "_CONFIRMATION", c ? "half-open" : "nonexistent",
-                i));
     }
 }
 
@@ -5779,14 +5781,13 @@ static int ssh_channel_data(struct ssh_channel *c, int is_stderr,
 static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
 {
     /* Data sent down one of our channels. */
-    int i = ssh_pkt_getuint32(pktin);
     char *p;
     int len;
     struct ssh_channel *c;
 
+    c = ssh_channel_msg(ssh, pktin);
     ssh_pkt_getstring(pktin, &p, &len);
 
-    c = find234(ssh->channels, &i, ssh_channelfind);
     if (c) {
        int bufsize = ssh_channel_data(c, FALSE, p, len);
        if (!c->throttling_conn && bufsize > SSH1_BUFFER_LIMIT) {
@@ -7971,20 +7972,26 @@ static void ssh2_set_window(struct ssh_channel *c, int newwin)
  * Find the channel associated with a message.  If there's no channel,
  * or it's not properly open, make a noise about it and return NULL.
  */
-static struct ssh_channel *ssh2_channel_msg(Ssh ssh, struct Packet *pktin)
+static struct ssh_channel *ssh_channel_msg(Ssh ssh, struct Packet *pktin)
 {
     unsigned localid = ssh_pkt_getuint32(pktin);
     struct ssh_channel *c;
+    int halfopen_ok;
 
+    /* Is this message OK on a half-open connection? */
+    if (ssh->version == 1)
+       halfopen_ok = (pktin->type == SSH1_MSG_CHANNEL_OPEN_CONFIRMATION ||
+                      pktin->type == SSH1_MSG_CHANNEL_OPEN_FAILURE);
+    else
+       halfopen_ok = (pktin->type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION ||
+                      pktin->type == SSH2_MSG_CHANNEL_OPEN_FAILURE);
     c = find234(ssh->channels, &localid, ssh_channelfind);
-    if (!c ||
-       (c->type != CHAN_SHARING && c->halfopen &&
-         pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
-        pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE)) {
+    if (!c || (c->type != CHAN_SHARING && (c->halfopen != halfopen_ok))) {
        char *buf = dupprintf("Received %s for %s channel %u",
-                             ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
-                                           pktin->type),
-                             c ? "half-open" : "nonexistent", localid);
+                             ssh_pkt_type(ssh, pktin->type),
+                             !c ? "nonexistent" :
+                             c->halfopen ? "half-open" : "open",
+                             localid);
        ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
        sfree(buf);
        return NULL;
@@ -8018,7 +8025,7 @@ static void ssh2_handle_winadj_response(struct ssh_channel *c,
 
 static void ssh2_msg_channel_response(Ssh ssh, struct Packet *pktin)
 {
-    struct ssh_channel *c = ssh2_channel_msg(ssh, pktin);
+    struct ssh_channel *c = ssh_channel_msg(ssh, pktin);
     struct outstanding_channel_request *ocr;
 
     if (!c) return;
@@ -8046,7 +8053,7 @@ static void ssh2_msg_channel_response(Ssh ssh, struct Packet *pktin)
 static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
 {
     struct ssh_channel *c;
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8065,7 +8072,7 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
     char *data;
     int length;
     struct ssh_channel *c;
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8207,6 +8214,7 @@ static void ssh2_channel_check_close(struct ssh_channel *c)
     Ssh ssh = c->ssh;
     struct Packet *pktout;
 
+    assert(ssh->version == 2);
     if (c->halfopen) {
         /*
          * If we've sent out our own CHANNEL_OPEN but not yet seen
@@ -8282,7 +8290,7 @@ static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
 {
     struct ssh_channel *c;
 
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8297,7 +8305,7 @@ static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin)
 {
     struct ssh_channel *c;
 
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8379,7 +8387,7 @@ static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
 {
     struct ssh_channel *c;
 
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8387,7 +8395,7 @@ static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
                                   pktin->body, pktin->length);
         return;
     }
-    assert(c->halfopen); /* ssh2_channel_msg will have enforced this */
+    assert(c->halfopen); /* ssh_channel_msg will have enforced this */
     c->remoteid = ssh_pkt_getuint32(pktin);
     c->halfopen = FALSE;
     c->v.v2.remwindow = ssh_pkt_getuint32(pktin);
@@ -8439,7 +8447,7 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
     int reason_length;
     struct ssh_channel *c;
 
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {
@@ -8447,7 +8455,7 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
                                   pktin->body, pktin->length);
         return;
     }
-    assert(c->halfopen); /* ssh2_channel_msg will have enforced this */
+    assert(c->halfopen); /* ssh_channel_msg will have enforced this */
 
     if (c->type == CHAN_SOCKDATA_DORMANT) {
         reason_code = ssh_pkt_getuint32(pktin);
@@ -8492,7 +8500,7 @@ static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin)
     struct ssh_channel *c;
     struct Packet *pktout;
 
-    c = ssh2_channel_msg(ssh, pktin);
+    c = ssh_channel_msg(ssh, pktin);
     if (!c)
        return;
     if (c->type == CHAN_SHARING) {