static struct ssh_channel *mainchan; /* primary session channel */
static enum {
+ SSH_STATE_PREPACKET,
SSH_STATE_BEFORE_SIZE,
SSH_STATE_INTERMED,
SSH_STATE_SESSION,
SSH_STATE_CLOSED
-} ssh_state = SSH_STATE_BEFORE_SIZE;
+} ssh_state = SSH_STATE_PREPACKET;
-static int size_needed = FALSE;
+static int size_needed = FALSE, eof_needed = FALSE;
static struct Packet pktin = { 0, 0, NULL, NULL, 0 };
static struct Packet pktout = { 0, 0, NULL, NULL, 0 };
static void ssh1_protocol(unsigned char *in, int inlen, int ispkt);
static void ssh2_protocol(unsigned char *in, int inlen, int ispkt);
static void ssh_size(void);
+static void ssh_special (Telnet_Special);
static int (*s_rdpkt)(unsigned char **data, int *datalen);
ssh_version = 1;
s_rdpkt = ssh1_rdpkt;
}
+ ssh_state = SSH_STATE_BEFORE_SIZE;
crFinish(0);
}
/*
* Open socket.
*/
- s = sk_new(addr, port, ssh_receive);
+ s = sk_new(addr, port, 0, ssh_receive);
if ( (err = sk_socket_error(s)) )
return err;
ssh_state = SSH_STATE_SESSION;
if (size_needed)
ssh_size();
+ if (eof_needed)
+ ssh_special(TS_EOF);
ssh_send_ok = 1;
ssh_channels = newtree234(ssh_channelcmp);
* Set IVs after keys.
*/
ssh2_mkkey(K, exchange_hash, 'C', keyspace); cscipher->setcskey(keyspace);
- ssh2_mkkey(K, exchange_hash, 'D', keyspace); cscipher->setsckey(keyspace);
+ ssh2_mkkey(K, exchange_hash, 'D', keyspace); sccipher->setsckey(keyspace);
ssh2_mkkey(K, exchange_hash, 'A', keyspace); cscipher->setcsiv(keyspace);
ssh2_mkkey(K, exchange_hash, 'B', keyspace); sccipher->setsciv(keyspace);
ssh2_mkkey(K, exchange_hash, 'E', keyspace); csmac->setcskey(keyspace);
ssh_state = SSH_STATE_SESSION;
if (size_needed)
ssh_size();
+ if (eof_needed)
+ ssh_special(TS_EOF);
/*
* Transfer data!
static void ssh_size(void) {
switch (ssh_state) {
case SSH_STATE_BEFORE_SIZE:
+ case SSH_STATE_PREPACKET:
case SSH_STATE_CLOSED:
break; /* do nothing */
case SSH_STATE_INTERMED:
ssh2_pkt_send();
}
}
+ break;
}
}
*/
static void ssh_special (Telnet_Special code) {
if (code == TS_EOF) {
+ if (ssh_state != SSH_STATE_SESSION) {
+ /*
+ * Buffer the EOF in case we are pre-SESSION, so we can
+ * send it as soon as we reach SESSION.
+ */
+ if (code == TS_EOF)
+ eof_needed = TRUE;
+ return;
+ }
if (ssh_version == 1) {
send_packet(SSH1_CMSG_EOF, PKT_END);
} else {
}
logevent("Sent EOF message");
} else if (code == TS_PING) {
+ if (ssh_state == SSH_STATE_CLOSED || ssh_state == SSH_STATE_PREPACKET)
+ return;
if (ssh_version == 1) {
send_packet(SSH1_MSG_IGNORE, PKT_STR, "", PKT_END);
} else {