X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/38c4a8da5955bf0572be423ce46866285b7bcf59..ff89646a8828ce862d53b96a19ee6469dabce71a:/ssh.c diff --git a/ssh.c b/ssh.c index e6b0bcc4..f48d1426 100644 --- a/ssh.c +++ b/ssh.c @@ -17,7 +17,7 @@ #define logevent(s) { logevent(s); \ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \ - fprintf(stderr, "%s\n", s); } + { fprintf(stderr, "%s\n", s); fflush(stderr); } } #define bombout(msg) ( ssh_state = SSH_STATE_CLOSED, \ (s ? sk_close(s), s = NULL : 0), \ @@ -365,6 +365,42 @@ static int ssh_channelfind(void *av, void *bv) { return 0; } +static int alloc_channel_id(void) { + const unsigned CHANNEL_NUMBER_OFFSET = 256; + unsigned low, high, mid; + int tsize; + struct ssh_channel *c; + + /* + * First-fit allocation of channel numbers: always pick the + * lowest unused one. To do this, binary-search using the + * counted B-tree to find the largest channel ID which is in a + * contiguous sequence from the beginning. (Precisely + * everything in that sequence must have ID equal to its tree + * index plus CHANNEL_NUMBER_OFFSET.) + */ + tsize = count234(ssh_channels); + + low = -1; high = tsize; + while (high - low > 1) { + mid = (high + low) / 2; + c = index234(ssh_channels, mid); + if (c->localid == mid + CHANNEL_NUMBER_OFFSET) + low = mid; /* this one is fine */ + else + high = mid; /* this one is past it */ + } + /* + * Now low points to either -1, or the tree index of the + * largest ID in the initial sequence. + */ + { + unsigned i = low + 1 + CHANNEL_NUMBER_OFFSET; + assert(NULL == find234(ssh_channels, &i, ssh_channelfind)); + } + return low + 1 + CHANNEL_NUMBER_OFFSET; +} + static void c_write (char *buf, int len) { if ((flags & FLAG_STDERR)) { int i; @@ -536,8 +572,8 @@ next_packet: if (pktin.type == SSH1_MSG_DISCONNECT) { /* log reason code in disconnect message */ char buf[256]; - int msglen = GET_32BIT(pktin.body); - int nowlen; + unsigned msglen = GET_32BIT(pktin.body); + unsigned nowlen; strcpy(buf, "Remote sent disconnect: "); nowlen = strlen(buf); if (msglen > sizeof(buf)-nowlen-1) @@ -690,8 +726,8 @@ next_packet: /* log reason code in disconnect message */ char buf[256]; int reason = GET_32BIT(pktin.data+6); - int msglen = GET_32BIT(pktin.data+10); - int nowlen; + unsigned msglen = GET_32BIT(pktin.data+10); + unsigned nowlen; if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) { sprintf(buf, "Received disconnect message (%s)", ssh2_disconnect_reasons[reason]); @@ -987,7 +1023,7 @@ static void ssh2_pkt_addstring(char *data) { } static char *ssh2_mpint_fmt(Bignum b, int *len) { unsigned char *p; - int i, n = (ssh1_bignum_bitcount(b)+7)/8; + int i, n = (bignum_bitcount(b)+7)/8; p = smalloc(n + 1); if (!p) fatalbox("out of memory"); @@ -1753,7 +1789,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) PUT_32BIT(agentreq, len); q = agentreq + 4; *q++ = SSH1_AGENTC_RSA_CHALLENGE; - PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus)); + PUT_32BIT(q, bignum_bitcount(key.modulus)); q += 4; q += ssh1_write_bignum(q, key.exponent); q += ssh1_write_bignum(q, key.modulus); @@ -2234,9 +2270,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { } else if (pktin.type == SSH1_SMSG_X11_OPEN) { /* Remote side is trying to open a channel to talk to our * X-Server. Give them back a local channel number. */ - unsigned i; - struct ssh_channel *c, *d; - enum234 e; + struct ssh_channel *c; logevent("Received X11 connect request"); /* Refuse if X11 forwarding is disabled. */ @@ -2256,13 +2290,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { PKT_END); } else { logevent("opening X11 forward connection succeeded"); - for (i=1, d = first234(ssh_channels, &e); d; d = next234(&e)) { - if (d->localid > i) - break; /* found a free number */ - i = d->localid + 1; - } c->remoteid = GET_32BIT(pktin.body); - c->localid = i; + c->localid = alloc_channel_id(); c->closes = 0; c->type = CHAN_X11; /* identify channel type */ add234(ssh_channels, c); @@ -2275,9 +2304,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { } else if (pktin.type == SSH1_SMSG_AGENT_OPEN) { /* Remote side is trying to open a channel to talk to our * agent. Give them back a local channel number. */ - unsigned i; struct ssh_channel *c; - enum234 e; /* Refuse if agent forwarding is disabled. */ if (!ssh_agentfwd_enabled) { @@ -2285,15 +2312,9 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { PKT_INT, GET_32BIT(pktin.body), PKT_END); } else { - i = 1; - for (c = first234(ssh_channels, &e); c; c = next234(&e)) { - if (c->localid > i) - break; /* found a free number */ - i = c->localid + 1; - } c = smalloc(sizeof(struct ssh_channel)); c->remoteid = GET_32BIT(pktin.body); - c->localid = i; + c->localid = alloc_channel_id(); c->closes = 0; c->type = CHAN_AGENT; /* identify channel type */ c->u.a.lensofar = 0; @@ -3143,7 +3164,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) method = 0; - if (!method && can_pubkey && agent_exists && !tried_agent) { + if (!method && can_pubkey && agent_exists() && !tried_agent) { /* * Attempt public-key authentication using Pageant. */ @@ -3512,8 +3533,9 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) /* * So now create a channel with a session in it. */ + ssh_channels = newtree234(ssh_channelcmp); mainchan = smalloc(sizeof(struct ssh_channel)); - mainchan->localid = 100; /* as good as any */ + mainchan->localid = alloc_channel_id(); ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN); ssh2_pkt_addstring("session"); ssh2_pkt_adduint32(mainchan->localid); @@ -3537,7 +3559,6 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) mainchan->v2.remmaxpkt = ssh2_pkt_getuint32(); mainchan->v2.outbuffer = NULL; mainchan->v2.outbuflen = mainchan->v2.outbufsize = 0; - ssh_channels = newtree234(ssh_channelcmp); add234(ssh_channels, mainchan); logevent("Opened channel for session"); @@ -3816,7 +3837,6 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) } else if (pktin.type == SSH2_MSG_CHANNEL_CLOSE) { unsigned i = ssh2_pkt_getuint32(); struct ssh_channel *c; - enum234 e; c = find234(ssh_channels, &i, ssh_channelfind); if (!c) @@ -3842,8 +3862,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) /* * See if that was the last channel left open. */ - c = first234(ssh_channels, &e); - if (!c) { + if (count234(ssh_channels) == 0) { logevent("All channels closed. Disconnecting"); ssh2_pkt_init(SSH2_MSG_DISCONNECT); ssh2_pkt_adduint32(SSH2_DISCONNECT_BY_APPLICATION); @@ -3900,17 +3919,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) ssh2_pkt_send(); sfree(c); } else { - struct ssh_channel *d; - unsigned i; - enum234 e; - - for (i=1, d = first234(ssh_channels, &e); d; - d = next234(&e)) { - if (d->localid > i) - break; /* found a free number */ - i = d->localid + 1; - } - c->localid = i; + c->localid = alloc_channel_id(); c->closes = 0; c->v2.remwindow = ssh2_pkt_getuint32(); c->v2.remmaxpkt = ssh2_pkt_getuint32(); @@ -3936,12 +3945,12 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) try_send = TRUE; } if (try_send) { - enum234 e; + int i; struct ssh_channel *c; /* * Try to send data on all channels if we can. */ - for (c = first234(ssh_channels, &e); c; c = next234(&e)) + for (i = 0; NULL != (c = index234(ssh_channels, i)); i++) ssh2_try_send(c); } }