Ssh ssh; /* pointer back to main context */
unsigned remoteid, localid;
int type;
+ /* True if we opened this channel but server hasn't confirmed. */
+ int halfopen;
/*
* In SSH1, this value contains four bits:
*
int overall_bufsize;
int throttled_all;
int v1_stdout_throttling;
- int v2_outgoing_sequence;
+ unsigned long v2_outgoing_sequence;
int ssh1_rdpkt_crstate;
int ssh2_rdpkt_crstate;
if (c && !c->closes) {
/*
- * If the channel's remoteid is -1, we have sent
+ * If halfopen is true, we have sent
* CHANNEL_OPEN for this channel, but it hasn't even been
* acknowledged by the server. So we must set a close flag
* on it now, and then when the server acks the channel
* open, we can close it then.
*/
- if (((int)c->remoteid) != -1) {
+ if (!c->halfopen) {
if (ssh->version == 1) {
send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid,
PKT_END);
logevent
("Opening X11 forward connection succeeded");
c->remoteid = remoteid;
+ c->halfopen = FALSE;
c->localid = alloc_channel_id(ssh);
c->closes = 0;
c->v.v1.throttling = 0;
c = snew(struct ssh_channel);
c->ssh = ssh;
c->remoteid = remoteid;
+ c->halfopen = FALSE;
c->localid = alloc_channel_id(ssh);
c->closes = 0;
c->v.v1.throttling = 0;
PKT_INT, remoteid, PKT_END);
} else {
c->remoteid = remoteid;
+ c->halfopen = FALSE;
c->localid = alloc_channel_id(ssh);
c->closes = 0;
c->v.v1.throttling = 0;
c = find234(ssh->channels, &remoteid, ssh_channelfind);
if (c && c->type == CHAN_SOCKDATA_DORMANT) {
c->remoteid = localid;
+ c->halfopen = FALSE;
c->type = CHAN_SOCKDATA;
c->v.v1.throttling = 0;
pfd_confirm(c->u.pfd.s);
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
- if (c && ((int)c->remoteid) != -1) {
+ if (c && !c->halfopen) {
int closetype;
closetype =
(pktin->type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
/* Data sent down one of our channels. */
int i = ssh_pkt_getuint32(pktin);
char *p;
- unsigned int len;
+ int len;
struct ssh_channel *c;
ssh_pkt_getstring(pktin, &p, &len);
bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));
}
-void ssh_msg_ignore(Ssh ssh, struct Packet *pktin)
+static void ssh_msg_ignore(Ssh ssh, struct Packet *pktin)
{
/* Do nothing, because we're ignoring it! Duhh. */
}
}
/*
+ * Similar routine for checking whether we have the first string in a list.
+ */
+static int first_in_commasep_string(char *needle, char *haystack, int haylen)
+{
+ int needlen;
+ if (!needle || !haystack) /* protect against null pointers */
+ return 0;
+ needlen = strlen(needle);
+ /*
+ * Is it at the start of the string?
+ */
+ if (haylen >= needlen && /* haystack is long enough */
+ !memcmp(needle, haystack, needlen) && /* initial match */
+ (haylen == needlen || haystack[needlen] == ',')
+ /* either , or EOS follows */
+ )
+ return 1;
+ return 0;
+}
+
+
+/*
* SSH2 key creation method.
*/
static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H,
*/
{
char *str;
- int i, j, len;
+ int i, j, len, guessok;
if (pktin->type != SSH2_MSG_KEXINIT) {
bombout(("expected key exchange packet from server"));
str ? str : "(null)"));
crStop(0);
}
+ /*
+ * Note that the server's guess is considered wrong if it doesn't match
+ * the first algorithm in our list, even if it's still the algorithm
+ * we end up using.
+ */
+ guessok =
+ first_in_commasep_string(s->preferred_kex[0]->name, str, len);
ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */
for (i = 0; i < lenof(hostkey_algs); i++) {
if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
break;
}
}
+ guessok = guessok &&
+ first_in_commasep_string(hostkey_algs[0]->name, str, len);
ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */
s->warn = 0;
for (i = 0; i < s->n_preferred_ciphers; i++) {
break;
}
}
+ ssh_pkt_getstring(pktin, &str, &len); /* client->server language */
+ ssh_pkt_getstring(pktin, &str, &len); /* server->client language */
+ if (ssh2_pkt_getbool(pktin) && !guessok) /* first_kex_packet_follows */
+ crWaitUntil(pktin); /* Ignore packet */
}
/*
static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
{
char *data;
- unsigned int length;
+ int length;
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
struct Packet *pktout;
c = find234(ssh->channels, &i, ssh_channelfind);
- if (!c || ((int)c->remoteid) == -1) {
+ if (!c || c->halfopen) {
bombout(("Received CHANNEL_CLOSE for %s channel %d\n",
c ? "half-open" : "nonexistent", i));
return;
if (c->type != CHAN_SOCKDATA_DORMANT)
return; /* dunno why they're confirming this */
c->remoteid = ssh_pkt_getuint32(pktin);
+ c->halfopen = FALSE;
c->type = CHAN_SOCKDATA;
c->v.v2.remwindow = ssh_pkt_getuint32(pktin);
c->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
if (q >= 0 && q+4 <= len) { \
q = q + 4 + GET_32BIT(p+q); \
if (q >= 0 && q+4 <= len && \
- (q = q + 4 + GET_32BIT(p+q)) && q == len) \
+ ((q = q + 4 + GET_32BIT(p+q))!= 0) && q == len) \
result = TRUE; \
} \
} while(0)
}
c->remoteid = remid;
+ c->halfopen = FALSE;
if (error) {
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_FAILURE);
ssh2_pkt_adduint32(pktout, c->remoteid);
} else if (s->method == AUTH_KEYBOARD_INTERACTIVE) {
if (s->curr_prompt == 0) {
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
+ s->pktout->forcepad = 256;
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
}
if (s->need_pw) { /* only add pw if we just got one! */
crStopV;
}
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
+ ssh->mainchan->halfopen = FALSE;
ssh->mainchan->type = CHAN_MAINSESSION;
ssh->mainchan->closes = 0;
ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
/*
* Handlers for SSH2 messages that might arrive at any moment.
*/
-void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
+static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
{
/* log reason code in disconnect message */
char *buf, *msg;
sfree(buf);
}
-void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
+static void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
{
/* log the debug message */
char *buf, *msg;
sfree(buf);
}
-void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)
+static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)
{
struct Packet *pktout;
pktout = ssh2_pkt_init(SSH2_MSG_UNIMPLEMENTED);
c->ssh = ssh;
if (c) {
- c->remoteid = -1; /* to be set when open confirmed */
+ c->halfopen = TRUE;
c->localid = alloc_channel_id(ssh);
c->closes = 0;
c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */