#include <assert.h>
#include "putty.h"
+#include "terminal.h"
#include "tree234.h"
#include "ssh.h"
#define BUG_CHOKES_ON_RSA 8
#define BUG_SSH2_RSA_PADDING 16
#define BUG_SSH2_DERIVEKEY 32
+#define BUG_SSH2_DH_GEX 64
static int ssh_pkt_ctx = 0;
static int ssh_send_ok;
static int ssh_echoing, ssh_editing;
+static void *frontend;
+
static tree234 *ssh_channels; /* indexed by local id */
static struct ssh_channel *mainchan; /* primary session channel */
static int ssh_exitcode = -1;
fputc(buf[i], stderr);
return;
}
- from_backend(1, buf, len);
+ from_backend(frontend, 1, buf, len);
}
static void c_write_untrusted(char *buf, int len)
ssh_remote_bugs |= BUG_SSH2_RSA_PADDING;
logevent("We believe remote version has SSH2 RSA padding bug");
}
+
+ if (cfg.sshbug_dhgex2 == BUG_ON) {
+ /*
+ * These versions have the SSH2 DH GEX bug.
+ */
+ ssh_remote_bugs |= BUG_SSH2_DH_GEX;
+ logevent("We believe remote version has SSH2 DH group exchange bug");
+ }
}
static int do_ssh_init(unsigned char c)
if (!cfg.nopty) {
send_packet(SSH1_CMSG_REQUEST_PTY,
PKT_STR, cfg.termtype,
- PKT_INT, rows, PKT_INT, cols,
+ PKT_INT, term ? term->rows : 24,
+ PKT_INT, term ? term->cols : 80,
PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END);
ssh_state = SSH_STATE_INTERMED;
do {
pktin.type == SSH1_SMSG_STDERR_DATA) {
long len = GET_32BIT(pktin.body);
int bufsize =
- from_backend(pktin.type == SSH1_SMSG_STDERR_DATA,
+ from_backend(frontend, pktin.type == SSH1_SMSG_STDERR_DATA,
pktin.body + 4, len);
if (!ssh1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
ssh1_stdout_throttling = 1;
unsigned i = GET_32BIT(pktin.body);
struct ssh_channel *c;
c = find234(ssh_channels, &i, ssh_channelfind);
- if (c) {
+ if (c && ((int)c->remoteid) != -1) {
int closetype;
closetype =
(pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
del234(ssh_channels, c);
sfree(c);
}
+ } else {
+ bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n",
+ pktin.type == SSH1_MSG_CHANNEL_CLOSE ? "" :
+ "_CONFIRMATION", c ? "half-open" : "nonexistent",
+ i));
}
} else if (pktin.type == SSH1_MSG_CHANNEL_DATA) {
/* Data sent down one of our channels. */
/*
* Be prepared to work around the buggy MAC problem.
*/
- if (cfg.buggymac || (ssh_remote_bugs & BUG_SSH2_HMAC))
+ if (ssh_remote_bugs & BUG_SSH2_HMAC)
maclist = buggymacs, nmacs = lenof(buggymacs);
else
maclist = macs, nmacs = lenof(macs);
/* List key exchange algorithms. */
ssh2_pkt_addstring_start();
for (i = 0; i < lenof(kex_algs); i++) {
+ if (kex_algs[i] == &ssh_diffiehellman_gex &&
+ (ssh_remote_bugs & BUG_SSH2_DH_GEX))
+ continue;
ssh2_pkt_addstring_str(kex_algs[i]->name);
if (i < lenof(kex_algs) - 1)
ssh2_pkt_addstring_str(",");
pktin.savedpos += 16; /* skip garbage cookie */
ssh2_pkt_getstring(&str, &len); /* key exchange algorithms */
for (i = 0; i < lenof(kex_algs); i++) {
+ if (kex_algs[i] == &ssh_diffiehellman_gex &&
+ (ssh_remote_bugs & BUG_SSH2_DH_GEX))
+ continue;
if (in_commasep_string(kex_algs[i]->name, str, len)) {
kex = kex_algs[i];
break;
ssh2_pkt_addstring("pty-req");
ssh2_pkt_addbool(1); /* want reply */
ssh2_pkt_addstring(cfg.termtype);
- ssh2_pkt_adduint32(cols);
- ssh2_pkt_adduint32(rows);
+ ssh2_pkt_adduint32(term ? term->cols : 80);
+ ssh2_pkt_adduint32(term ? term->rows : 24);
ssh2_pkt_adduint32(0); /* pixel width */
ssh2_pkt_adduint32(0); /* pixel height */
ssh2_pkt_addstring_start();
switch (c->type) {
case CHAN_MAINSESSION:
bufsize =
- from_backend(pktin.type ==
+ from_backend(frontend, pktin.type ==
SSH2_MSG_CHANNEL_EXTENDED_DATA,
data, length);
break;
struct ssh_channel *c;
c = find234(ssh_channels, &i, ssh_channelfind);
- if (!c)
- continue; /* nonexistent channel */
+ if (!c || ((int)c->remoteid) == -1) {
+ bombout(("Received CHANNEL_CLOSE for %s channel %d\n",
+ c ? "half-open" : "nonexistent", i));
+ }
/* Do pre-close processing on the channel. */
switch (c->type) {
case CHAN_MAINSESSION:
*
* Returns an error message, or NULL on success.
*/
-static char *ssh_init(char *host, int port, char **realhost, int nodelay)
+static char *ssh_init(void *frontend_handle,
+ char *host, int port, char **realhost, int nodelay)
{
char *p;
return "Microsoft high encryption pack not installed!";
#endif
+ frontend = frontend_handle;
+
ssh_send_ok = 0;
ssh_editing = 0;
ssh_echoing = 0;
break;
case SSH_STATE_SESSION:
if (!cfg.nopty) {
+ if (!term)
+ return;
if (ssh_version == 1) {
send_packet(SSH1_CMSG_WINDOW_SIZE,
- PKT_INT, rows, PKT_INT, cols,
+ PKT_INT, term->rows, PKT_INT, term->cols,
PKT_INT, 0, PKT_INT, 0, PKT_END);
} else {
ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(mainchan->remoteid);
ssh2_pkt_addstring("window-change");
ssh2_pkt_addbool(0);
- ssh2_pkt_adduint32(cols);
- ssh2_pkt_adduint32(rows);
+ ssh2_pkt_adduint32(term->cols);
+ ssh2_pkt_adduint32(term->rows);
ssh2_pkt_adduint32(0);
ssh2_pkt_adduint32(0);
ssh2_pkt_send();