#define BUG_CHOKES_ON_SSH2_IGNORE 512
#define BUG_CHOKES_ON_WINADJ 1024
#define BUG_SENDS_LATE_REQUEST_REPLY 2048
+#define BUG_SSH2_OLDGEX 4096
+
+#define DH_MIN_SIZE 1024
+#define DH_MAX_SIZE 8192
/*
* Codes for terminal modes.
translate(SSH2_MSG_NEWKEYS);
translatek(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);
translatek(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);
+ translatek(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);
logevent("We believe remote version has SSH-2 ignore bug");
}
+ if (conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
+ (conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == AUTO &&
+ (wc_match("OpenSSH_2.[235]*", imp)))) {
+ /*
+ * These versions only support the original (pre-RFC4419)
+ * SSH-2 GEX request.
+ */
+ ssh->remote_bugs |= BUG_SSH2_OLDGEX;
+ logevent("We believe remote version has outdated SSH-2 GEX");
+ }
+
if (conf_get_int(ssh->conf, CONF_sshbug_winadj) == FORCE_ON) {
/*
* Servers that don't support our winadj request for one
if (conf_get_int(ssh->conf, CONF_sshbug_chanreq) == FORCE_ON ||
(conf_get_int(ssh->conf, CONF_sshbug_chanreq) == AUTO &&
(wc_match("OpenSSH_[2-5].*", imp) ||
- wc_match("OpenSSH_6.[0-6]*", imp)))) {
+ wc_match("OpenSSH_6.[0-6]*", imp) ||
+ wc_match("dropbear_0.[2-4][0-9]*", imp) ||
+ wc_match("dropbear_0.5[01]*", imp)))) {
/*
- * These versions have the SSH-2 channel request bug. 6.7 and
- * above do not:
+ * These versions have the SSH-2 channel request bug.
+ * OpenSSH 6.7 and above do not:
* https://bugzilla.mindrot.org/show_bug.cgi?id=1818
+ * dropbear_0.52 and above do not:
+ * https://secure.ucc.asn.au/hg/dropbear/rev/cd02449b709c
*/
ssh->remote_bugs |= BUG_SENDS_LATE_REQUEST_REPLY;
logevent("We believe remote version has SSH-2 channel request bug");
ssh->portfwds = NULL;
}
+ /*
+ * Also stop attempting to connection-share.
+ */
+ if (ssh->connshare) {
+ sharestate_free(ssh->connshare);
+ ssh->connshare = NULL;
+ }
+
return ret;
}
s->dlgret = verify_ssh_manual_host_key(ssh, fingerprint, NULL, NULL);
if (s->dlgret == 0) { /* did not match */
bombout(("Host key did not appear in manually configured list"));
+ sfree(keystr);
crStop(0);
} else if (s->dlgret < 0) { /* none configured; use standard handling */
ssh_set_frozen(ssh, 1);
NULL, 0, TRUE);
crStop(0);
}
+ } else {
+ sfree(keystr);
}
}
* much data.
*/
s->pbits = 512 << ((s->nbits - 1) / 64);
- s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
- ssh2_pkt_adduint32(s->pktout, s->pbits);
+ if (s->pbits < DH_MIN_SIZE)
+ s->pbits = DH_MIN_SIZE;
+ if (s->pbits > DH_MAX_SIZE)
+ s->pbits = DH_MAX_SIZE;
+ if ((ssh->remote_bugs & BUG_SSH2_OLDGEX)) {
+ s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
+ ssh2_pkt_adduint32(s->pktout, s->pbits);
+ } else {
+ s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
+ ssh2_pkt_adduint32(s->pktout, DH_MIN_SIZE);
+ ssh2_pkt_adduint32(s->pktout, s->pbits);
+ ssh2_pkt_adduint32(s->pktout, DH_MAX_SIZE);
+ }
ssh2_pkt_send_noqueue(ssh, s->pktout);
crWaitUntilV(pktin);
}
ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
+ {
+ const char *err = dh_validate_f(ssh->kex_ctx, s->f);
+ if (err) {
+ bombout(("key exchange reply failed validation: %s", err));
+ crStopV;
+ }
+ }
s->K = dh_find_K(ssh->kex_ctx, s->f);
/* We assume everything from now on will be quick, and it might
hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen);
if (!ssh->kex->pdata) {
+ if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
+ hash_uint32(ssh->kex->hash, ssh->exhash, DH_MIN_SIZE);
hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits);
+ if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
+ hash_uint32(ssh->kex->hash, ssh->exhash, DH_MAX_SIZE);
hash_mpint(ssh->kex->hash, ssh->exhash, s->p);
hash_mpint(ssh->kex->hash, ssh->exhash, s->g);
}
}
}
-void ssh_sharing_downstream_connected(Ssh ssh, unsigned id)
+void ssh_sharing_downstream_connected(Ssh ssh, unsigned id,
+ const char *peerinfo)
{
- logeventf(ssh, "Connection sharing downstream #%u connected", id);
+ if (peerinfo)
+ logeventf(ssh, "Connection sharing downstream #%u connected from %s",
+ id, peerinfo);
+ else
+ logeventf(ssh, "Connection sharing downstream #%u connected", id);
}
void ssh_sharing_downstream_disconnected(Ssh ssh, unsigned id)
logevent("Sent public key signature");
s->type = AUTH_TYPE_PUBLICKEY;
key->alg->freekey(key->data);
+ sfree(key->comment);
+ sfree(key);
}
#ifndef NO_GSSAPI
* Try to send data on all channels if we can.
*/
for (i = 0; NULL != (c = index234(ssh->channels, i)); i++)
- ssh2_try_send_and_unthrottle(ssh, c);
+ if (c->type != CHAN_SHARING)
+ ssh2_try_send_and_unthrottle(ssh, c);
}
}
ssh->sent_console_eof = FALSE;
ssh->got_pty = FALSE;
ssh->bare_connection = FALSE;
+ ssh->X11_fwd_enabled = FALSE;
+ ssh->connshare = NULL;
ssh->attempting_connshare = FALSE;
*backend_handle = ssh;
}
/*
- * cfg_info for SSH is the currently running version of the
- * protocol. (1 for 1; 2 for 2; 0 for not-decided-yet.)
+ * cfg_info for SSH is the protocol running in this session.
+ * (1 or 2 for the full SSH-1 or SSH-2 protocol; -1 for the bare
+ * SSH-2 connection protocol, i.e. a downstream; 0 for not-decided-yet.)
*/
static int ssh_cfg_info(void *handle)
{
Ssh ssh = (Ssh) handle;
- return ssh->version;
+ if (ssh->version == 0)
+ return 0; /* don't know yet */
+ else if (ssh->bare_connection)
+ return -1;
+ else
+ return ssh->version;
}
/*