X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/4a62c66db92c9692b5e45566f3dd85455825317c..3ee4eedaec9cad4b5b2ff0f40567fa2e57a942a9:/ssh.c diff --git a/ssh.c b/ssh.c index b4d3884b..6ee5528c 100644 --- a/ssh.c +++ b/ssh.c @@ -525,7 +525,7 @@ static void ssh_channel_destroy(struct ssh_channel *c); const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss }; const static struct ssh_mac *macs[] = { - &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5 + &ssh_hmac_sha256, &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5 }; const static struct ssh_mac *buggymacs[] = { &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5 @@ -666,6 +666,7 @@ struct ssh_channel { unsigned char *message; unsigned char msglen[4]; unsigned lensofar, totallen; + int outstanding_requests; } a; struct ssh_x11_channel { Socket s; @@ -771,7 +772,7 @@ static int ssh_do_close(Ssh ssh, int notify_exit); static unsigned long ssh_pkt_getuint32(struct Packet *pkt); static int ssh2_pkt_getbool(struct Packet *pkt); static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length); -static void ssh2_timer(void *ctx, long now); +static void ssh2_timer(void *ctx, unsigned long now); static void do_ssh2_transport(Ssh ssh, void *vin, int inlen, struct Packet *pktin); static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin); @@ -980,7 +981,7 @@ struct ssh_tag { unsigned long incoming_data_size, outgoing_data_size, deferred_data_size; unsigned long max_data_size; int kex_in_progress; - long next_rekey, last_rekey; + unsigned long next_rekey, last_rekey; char *deferred_rekey_reason; /* points to STATIC string; don't free */ /* @@ -3201,6 +3202,7 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen) Ssh ssh = c->ssh; void *sentreply = reply; + c->u.a.outstanding_requests--; if (!sentreply) { /* Fake SSH_AGENT_FAILURE. */ sentreply = "\0\0\0\1\5"; @@ -3220,6 +3222,12 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen) } if (reply) sfree(reply); + /* + * If we've already seen an incoming EOF but haven't sent an + * outgoing one, this may be the moment to send it. + */ + if (c->u.a.outstanding_requests == 0 && (c->closes & CLOSES_RCVD_EOF)) + sshfwd_write_eof(c); } /* @@ -4610,9 +4618,9 @@ static void ssh_setup_portfwd(Ssh ssh, Conf *conf) /* XXX: rport_acceptall may not represent * what was used to open the original connection, * since it's reconfigurable. */ - ssh2_pkt_addstring(pktout, "0.0.0.0"); + ssh2_pkt_addstring(pktout, ""); } else { - ssh2_pkt_addstring(pktout, "127.0.0.1"); + ssh2_pkt_addstring(pktout, "localhost"); } ssh2_pkt_adduint32(pktout, epf->sport); ssh2_pkt_send(ssh, pktout); @@ -4725,9 +4733,9 @@ static void ssh_setup_portfwd(Ssh ssh, Conf *conf) if (epf->saddr) { ssh2_pkt_addstring(pktout, epf->saddr); } else if (conf_get_int(conf, CONF_rport_acceptall)) { - ssh2_pkt_addstring(pktout, "0.0.0.0"); + ssh2_pkt_addstring(pktout, ""); } else { - ssh2_pkt_addstring(pktout, "127.0.0.1"); + ssh2_pkt_addstring(pktout, "localhost"); } ssh2_pkt_adduint32(pktout, epf->sport); ssh2_pkt_send(ssh, pktout); @@ -4827,6 +4835,7 @@ static void ssh1_smsg_agent_open(Ssh ssh, struct Packet *pktin) c->type = CHAN_AGENT; /* identify channel type */ c->u.a.lensofar = 0; c->u.a.message = NULL; + c->u.a.outstanding_requests = 0; add234(ssh->channels, c); send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION, PKT_INT, c->remoteid, PKT_INT, c->localid, @@ -5052,6 +5061,7 @@ static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin) if (c->u.a.lensofar == c->u.a.totallen) { void *reply; int replylen; + c->u.a.outstanding_requests++; if (agent_query(c->u.a.message, c->u.a.totallen, &reply, &replylen, @@ -6847,6 +6857,7 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin) if (c->u.a.lensofar == c->u.a.totallen) { void *reply; int replylen; + c->u.a.outstanding_requests++; if (agent_query(c->u.a.message, c->u.a.totallen, &reply, &replylen, @@ -6985,8 +6996,10 @@ static void ssh2_channel_got_eof(struct ssh_channel *c) if (c->type == CHAN_X11) { x11_send_eof(c->u.x11.s); } else if (c->type == CHAN_AGENT) { - /* Manufacture an outgoing EOF in response to the incoming one. */ - sshfwd_write_eof(c); + if (c->u.a.outstanding_requests == 0) { + /* Manufacture an outgoing EOF in response to the incoming one. */ + sshfwd_write_eof(c); + } } else if (c->type == CHAN_SOCKDATA) { pfd_send_eof(c->u.pfd.s); } else if (c->type == CHAN_MAINSESSION) { @@ -7408,6 +7421,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin) else { c->type = CHAN_AGENT; /* identify channel type */ c->u.a.lensofar = 0; + c->u.a.outstanding_requests = 0; } } else { error = "Unsupported channel type requested"; @@ -9116,58 +9130,30 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, */ if (conf_get_int(ssh->conf, CONF_ssh_no_shell)) { ssh->mainchan = NULL; - } else if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) { - /* - * Just start a direct-tcpip channel and use it as the main - * channel. - */ + } else { ssh->mainchan = snew(struct ssh_channel); ssh->mainchan->ssh = ssh; ssh2_channel_init(ssh->mainchan); - logeventf(ssh, - "Opening direct-tcpip channel to %s:%d in place of session", - conf_get_str(ssh->conf, CONF_ssh_nc_host), - conf_get_int(ssh->conf, CONF_ssh_nc_port)); - s->pktout = ssh2_chanopen_init(ssh->mainchan, "direct-tcpip"); - ssh2_pkt_addstring(s->pktout, conf_get_str(ssh->conf, CONF_ssh_nc_host)); - ssh2_pkt_adduint32(s->pktout, conf_get_int(ssh->conf, CONF_ssh_nc_port)); - /* - * There's nothing meaningful to put in the originator - * fields, but some servers insist on syntactically correct - * information. - */ - ssh2_pkt_addstring(s->pktout, "0.0.0.0"); - ssh2_pkt_adduint32(s->pktout, 0); - ssh2_pkt_send(ssh, s->pktout); - crWaitUntilV(pktin); - if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) { - bombout(("Server refused to open a direct-tcpip channel")); - crStopV; - /* FIXME: error data comes back in FAILURE packet */ - } - if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) { - bombout(("Server's channel confirmation cited wrong channel")); - crStopV; + if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) { + /* + * Just start a direct-tcpip channel and use it as the main + * channel. + */ + ssh_send_port_open(ssh->mainchan, + conf_get_str(ssh->conf, CONF_ssh_nc_host), + conf_get_int(ssh->conf, CONF_ssh_nc_port), + "main channel"); + ssh->ncmode = TRUE; + } else { + s->pktout = ssh2_chanopen_init(ssh->mainchan, "session"); + logevent("Opening session as main channel"); + ssh2_pkt_send(ssh, s->pktout); + ssh->ncmode = FALSE; } - ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin); - ssh->mainchan->halfopen = FALSE; - ssh->mainchan->type = CHAN_MAINSESSION; - ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin); - ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin); - add234(ssh->channels, ssh->mainchan); - update_specials_menu(ssh->frontend); - logevent("Opened direct-tcpip channel"); - ssh->ncmode = TRUE; - } else { - ssh->mainchan = snew(struct ssh_channel); - ssh->mainchan->ssh = ssh; - ssh2_channel_init(ssh->mainchan); - s->pktout = ssh2_chanopen_init(ssh->mainchan, "session"); - ssh2_pkt_send(ssh, s->pktout); crWaitUntilV(pktin); if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) { - bombout(("Server refused to open a session")); + bombout(("Server refused to open channel")); crStopV; /* FIXME: error data comes back in FAILURE packet */ } @@ -9182,8 +9168,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin); add234(ssh->channels, ssh->mainchan); update_specials_menu(ssh->frontend); - logevent("Opened channel for session"); - ssh->ncmode = FALSE; + logevent("Opened main channel"); } /* @@ -9497,7 +9482,7 @@ static void ssh2_protocol_setup(Ssh ssh) ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug; } -static void ssh2_timer(void *ctx, long now) +static void ssh2_timer(void *ctx, unsigned long now) { Ssh ssh = (Ssh)ctx; @@ -9505,7 +9490,7 @@ static void ssh2_timer(void *ctx, long now) return; if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 && - now - ssh->next_rekey >= 0) { + now == ssh->next_rekey) { do_ssh2_transport(ssh, "timeout", -1, NULL); } } @@ -9788,10 +9773,10 @@ static void ssh_reconfig(void *handle, Conf *conf) rekey_time = conf_get_int(conf, CONF_ssh_rekey_time); if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time && rekey_time != 0) { - long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC; - long now = GETTICKCOUNT(); + unsigned long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC; + unsigned long now = GETTICKCOUNT(); - if (new_next - now < 0) { + if (now - ssh->last_rekey > rekey_time*60*TICKSPERSEC) { rekeying = "timeout shortened"; } else { ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh); @@ -10144,7 +10129,7 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org) Ssh ssh = c->ssh; struct Packet *pktout; - logeventf(ssh, "Opening forwarded connection to %s:%d", hostname, port); + logeventf(ssh, "Opening connection to %s:%d for %s", hostname, port, org); if (ssh->version == 1) { send_packet(ssh, SSH1_MSG_PORT_OPEN,