From c84d94538281bd0fda738d0898430163c57eca57 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 21 Aug 1999 18:18:09 +0000 Subject: [PATCH] ssh_gotdata now compiles again [originally from svn r201] --- ssh.c | 614 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 297 insertions(+), 317 deletions(-) diff --git a/ssh.c b/ssh.c index 17a59238..789ee60c 100644 --- a/ssh.c +++ b/ssh.c @@ -1,6 +1,8 @@ #include #include +#ifndef macintosh #include +#endif #include "putty.h" @@ -14,21 +16,22 @@ #include "ssh.h" /* Coroutine mechanics for the sillier bits of the code */ -#define crBegin1 static int crLine = 0; -#define crBegin2 switch(crLine) { case 0:; -#define crBegin crBegin1; crBegin2; -#define crFinish(z) } crLine = 0; return (z) -#define crFinishV } crLine = 0; return -#define crReturn(z) \ +#define crBegin1(l) (l) = 0; +#define crBegin2(l) switch(l) { case 0:; +#define crBegin(l) crBegin1(l); crBegin2(l); +#define crFinish(l,z) } (l) = 0; return (l) +#define foolemacs { +#define crFinishV(l) } (l) = 0; return +#define crReturn(l,z) \ do {\ - crLine=__LINE__; return (z); case __LINE__:;\ + (l)=__LINE__; return (z); case __LINE__:;\ } while (0) -#define crReturnV \ +#define crReturnV(l) \ do {\ - crLine=__LINE__; return; case __LINE__:;\ + (l)=__LINE__; return; case __LINE__:;\ } while (0) -#define crStop(z) do{ crLine = 0; return (z); }while(0) -#define crStopV do{ crLine = 0; return; }while(0) +#define crStop(l,z) do{ (l) = 0; return (z); }while(0) +#define crStopV(l) do{ (l) = 0; return; }while(0) #ifndef FALSE #define FALSE 0 @@ -37,34 +40,61 @@ #define TRUE 1 #endif -static SOCKET s = INVALID_SOCKET; - -static unsigned char session_key[32]; -static struct ssh_cipher *cipher = NULL; - -static char *savedhost; +struct Packet { + long length; + int type; + unsigned long crc; + unsigned char *data; + unsigned char *body; + long maxlen; +}; -static enum { - SSH_STATE_BEFORE_SIZE, - SSH_STATE_INTERMED, - SSH_STATE_SESSION, - SSH_STATE_CLOSED -} ssh_state = SSH_STATE_BEFORE_SIZE; +struct ssh_private { + SOCKET s; + unsigned char session_key[32]; + struct ssh_cipher *cipher; + char *savedhost; + enum { + SSH_STATE_BEFORE_SIZE, + SSH_STATE_INTERMED, + SSH_STATE_SESSION, + SSH_STATE_CLOSED + } ssh_state; + int size_needed; +#ifdef FWHACK + char *FWhost; + int FWport; +#endif + struct Packet pktin; + struct Packet pktout; + /* State for ssh_gotdata coroutine */ + int gd_line; + long len, biglen, to_read; + unsigned char *p; + int i, pad; + int chunk; + char *sversion; + size_t sversion_space, sversion_len; + /* State for ssh_protocol coroutine */ + int pr_line; +}; -static int size_needed = FALSE; +static void s_write (Session *sess, unsigned char *buf, int len) { + struct ssh_private *sp = (struct ssh_private*)sess->back_priv; -static void s_write (char *buf, int len) { while (len > 0) { - int i = send (s, buf, len, 0); + int i = net_send (sp->s, buf, len, 0); if (i > 0) len -= i, buf += i; } } -static int s_read (char *buf, int len) { +static int s_read (Session *sess, unsigned char *buf, int len) { + struct ssh_private *sp = (struct ssh_private*)sess->back_priv; + int ret = 0; while (len > 0) { - int i = recv (s, buf, len, 0); + int i = net_recv (sp->s, buf, len, 0); if (i > 0) len -= i, buf += i, ret += i; else @@ -73,186 +103,174 @@ static int s_read (char *buf, int len) { return ret; } -static void c_write (char *buf, int len) { +static void c_write (Session *sess, char *buf, int len) { + while (len--) { - int new_head = (inbuf_head + 1) & INBUF_MASK; - if (new_head != inbuf_reap) { - inbuf[inbuf_head] = *buf++; - inbuf_head = new_head; + int new_head = (sess->inbuf_head + 1) & INBUF_MASK; + if (new_head != sess->inbuf_reap) { + sess->inbuf[sess->inbuf_head] = *buf++; + sess->inbuf_head = new_head; } } } -struct Packet { - long length; - int type; - unsigned long crc; - unsigned char *data; - unsigned char *body; - long maxlen; -}; +static void ssh_protocol(Session *,unsigned char *in, int inlen, int ispkt); +static void ssh_size(void); -static struct Packet pktin = { 0, 0, 0, NULL, 0 }; -static struct Packet pktout = { 0, 0, 0, NULL, 0 }; +static void ssh_gotdata(Session *sess, unsigned char *data, int datalen) { + struct ssh_private *sp = (struct ssh_private *)sess->back_priv; + unsigned char *eol; + size_t fraglen = datalen; + static char vstring[] = "SSH-1.5-PuTTY\n"; -static void ssh_protocol(unsigned char *in, int inlen, int ispkt); -static void ssh_size(void); + crBegin(sp->gd_line); + +#ifdef FWHACK + /* Should wait for "SSH-" */ +#endif + sp->sversion = smalloc(16); /* enough for "SSH-1.5-1.2.27\n" */ + sp->sversion_space = 16; + sp->sversion_len = 0; + do { + + while (datalen == 0) + crReturnV(sp->gd_line); + eol = memchr(data, '\n', datalen); + if (eol != NULL) + fraglen = eol + 1 - data; /* include \n */ + if (sp->sversion_len + fraglen > sp->sversion_space) { + /* FIXME Sanity-check length */ + srealloc(sp->sversion, sp->sversion_len + fraglen); + sp->sversion_space = sp->sversion_len + fraglen; + } + memcpy(sp->sversion + sp->sversion_len, data, fraglen); + data += fraglen; datalen -= fraglen; + } while (eol == NULL); + sp->sversion[sp->sversion_len - 1] = '\0'; + + if (sp->sversion_len < 4 || memcmp(sp->sversion, "SSH-", 4) != 0) + /* XXX explode! */; + + /* + * We ignore the rest of the banner on the grounds that we only + * speak SSH 1.5 anyway. If the server can't, that's its problem. + */ + + s_write(sess, (unsigned char *)vstring, strlen(vstring)); -static void ssh_gotdata(unsigned char *data, int datalen) { - static long len, biglen, to_read; - static unsigned char *p; - static int i, pad; + /* End of do_ssh_init */ - crBegin; while (1) { - for (i = len = 0; i < 4; i++) { + for (sp->i = sp->len = 0; sp->i < 4; sp->i++) { while (datalen == 0) - crReturnV; - len = (len << 8) + *data; + crReturnV(sp->gd_line); + sp->len = (sp->len << 8) + *data; data++, datalen--; } #ifdef FWHACK - if (len == 0x52656d6f) { /* "Remo"te server has closed ... */ - len = 0x300; /* big enough to carry to end */ + if (sp->len == 0x52656d6f) { /* "Remo"te server has closed ... */ + sp->len = 0x300; /* big enough to carry to end */ } #endif - pad = 8 - (len%8); + sp->pad = 8 - (sp->len%8); - biglen = len + pad; + sp->biglen = sp->len + sp->pad; - len -= 5; /* type and CRC */ + sp->len -= 5; /* type and CRC */ - pktin.length = len; - if (pktin.maxlen < biglen) { - pktin.maxlen = biglen; - pktin.data = (pktin.data == NULL ? malloc(biglen) : - realloc(pktin.data, biglen)); - if (!pktin.data) - fatalbox("Out of memory"); + sp->pktin.length = sp->len; + if (sp->pktin.maxlen < sp->biglen) { + sp->pktin.maxlen = sp->biglen; + sp->pktin.data = (sp->pktin.data == NULL ? smalloc(sp->biglen) : + srealloc(sp->pktin.data, sp->biglen)); } - p = pktin.data, to_read = biglen; - while (to_read > 0) { - static int chunk; - chunk = to_read; + sp->p = sp->pktin.data, sp->to_read = sp->biglen; + while (sp->to_read > 0) { + sp->chunk = sp->to_read; while (datalen == 0) - crReturnV; - if (chunk > datalen) - chunk = datalen; - memcpy(p, data, chunk); - data += chunk; - datalen -= chunk; - p += chunk; - to_read -= chunk; + crReturnV(sp->gd_line); + if (sp->chunk > datalen) + sp->chunk = datalen; + memcpy(sp->p, data, sp->chunk); + data += sp->chunk; + datalen -= sp->chunk; + sp->p += sp->chunk; + sp->to_read -= sp->chunk; } - if (cipher) - cipher->decrypt(pktin.data, biglen); + if (sp->cipher) + sp->cipher->decrypt(sp->pktin.data, sp->biglen); - pktin.type = pktin.data[pad]; - pktin.body = pktin.data+pad+1; + sp->pktin.type = sp->pktin.data[sp->pad]; + sp->pktin.body = sp->pktin.data+sp->pad+1; - if (pktin.type == 36) { /* SSH_MSG_DEBUG */ + if (sp->pktin.type == 36) { /* SSH_MSG_DEBUG */ /* FIXME: log it */ } else - ssh_protocol(NULL, 0, 1); + ssh_protocol(sess, NULL, 0, 1); } - crFinishV; + crFinishV(sp->gd_line); } -static void s_wrpkt_start(int type, int len) { +static void s_wrpkt_start(Session *sess, int type, int len) { + struct ssh_private *sp = (struct ssh_private *)sess->back_priv; int pad, biglen; len += 5; /* type and CRC */ pad = 8 - (len%8); biglen = len + pad; - pktout.length = len-5; - if (pktout.maxlen < biglen) { - pktout.maxlen = biglen; - pktout.data = (pktout.data == NULL ? malloc(biglen+4) : - realloc(pktout.data, biglen+4)); - if (!pktout.data) - fatalbox("Out of memory"); + sp->pktout.length = len-5; + if (sp->pktout.maxlen < biglen) { + sp->pktout.maxlen = biglen; + sp->pktout.data = (sp->pktout.data == NULL ? smalloc(biglen+4) : + srealloc(sp->pktout.data, biglen+4)); } - pktout.type = type; - pktout.body = pktout.data+4+pad+1; + sp->pktout.type = type; + sp->pktout.body = sp->pktout.data+4+pad+1; } -static void s_wrpkt(void) { +static void s_wrpkt(Session *sess) { + struct ssh_private *sp = (struct ssh_private *)sess->back_priv; + int pad, len, biglen, i; unsigned long crc; - len = pktout.length + 5; /* type and CRC */ + len = sp->pktout.length + 5; /* type and CRC */ pad = 8 - (len%8); biglen = len + pad; - pktout.body[-1] = pktout.type; + sp->pktout.body[-1] = sp->pktout.type; for (i=0; ipktout.data[i+4] = random_byte(); + crc = crc32(sp->pktout.data+4, biglen-4); - pktout.data[biglen+0] = (unsigned char) ((crc >> 24) & 0xFF); - pktout.data[biglen+1] = (unsigned char) ((crc >> 16) & 0xFF); - pktout.data[biglen+2] = (unsigned char) ((crc >> 8) & 0xFF); - pktout.data[biglen+3] = (unsigned char) (crc & 0xFF); + sp->pktout.data[biglen+0] = (unsigned char) ((crc >> 24) & 0xFF); + sp->pktout.data[biglen+1] = (unsigned char) ((crc >> 16) & 0xFF); + sp->pktout.data[biglen+2] = (unsigned char) ((crc >> 8) & 0xFF); + sp->pktout.data[biglen+3] = (unsigned char) (crc & 0xFF); - pktout.data[0] = (len >> 24) & 0xFF; - pktout.data[1] = (len >> 16) & 0xFF; - pktout.data[2] = (len >> 8) & 0xFF; - pktout.data[3] = len & 0xFF; + sp->pktout.data[0] = (len >> 24) & 0xFF; + sp->pktout.data[1] = (len >> 16) & 0xFF; + sp->pktout.data[2] = (len >> 8) & 0xFF; + sp->pktout.data[3] = len & 0xFF; - if (cipher) - cipher->encrypt(pktout.data+4, biglen); + if (sp->cipher) + sp->cipher->encrypt(sp->pktout.data+4, biglen); - s_write(pktout.data, biglen+4); + s_write(sess, sp->pktout.data, biglen+4); } -static int do_ssh_init(void) { - char c; - char version[10]; - char vstring[40]; - int i; - -#ifdef FWHACK - i = 0; - while (s_read(&c, 1) == 1) { - if (c == 'S' && i < 2) i++; - else if (c == 'S' && i == 2) i = 2; - else if (c == 'H' && i == 2) break; - else i = 0; - } -#else - if (s_read(&c,1) != 1 || c != 'S') return 0; - if (s_read(&c,1) != 1 || c != 'S') return 0; - if (s_read(&c,1) != 1 || c != 'H') return 0; -#endif - if (s_read(&c,1) != 1 || c != '-') return 0; - i = 0; - while (1) { - if (s_read(&c,1) != 1) - return 0; - if (i >= 0) { - if (c == '-') { - version[i] = '\0'; - i = -1; - } else if (i < sizeof(version)-1) - version[i++] = c; - } - else if (c == '\n') - break; - } - - sprintf(vstring, "SSH-%s-7.7.7\n", - (strcmp(version, "1.5") <= 0 ? version : "1.5")); - s_write(vstring, strlen(vstring)); - return 1; +static int do_ssh_init(Session *sess) { } -static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { +static void ssh_protocol(Session *sess, unsigned char *in, int inlen, + int ispkt) { + struct ssh_private *sp = (struct ssh_private *)sess->back_priv; int i, j, len; unsigned char session_id[16]; unsigned char *rsabuf, *keystr1, *keystr2; @@ -265,32 +283,32 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { extern struct ssh_cipher ssh_3des; extern struct ssh_cipher ssh_blowfish; - crBegin; + crBegin(sp->pr_line); random_init(); while (!ispkt) - crReturnV; + crReturnV(sp->pr_line); - if (pktin.type != 2) + if (sp->pktin.type != 2) fatalbox("Public key packet not received"); - memcpy(cookie, pktin.body, 8); + memcpy(cookie, sp->pktin.body, 8); MD5Init(&md5c); - i = makekey(pktin.body+8, &servkey, &keystr1); + i = makekey(sp->pktin.body+8, &servkey, &keystr1); - j = makekey(pktin.body+8+i, &hostkey, &keystr2); + j = makekey(sp->pktin.body+8+i, &hostkey, &keystr2); - supported_ciphers_mask = (pktin.body[12+i+j] << 24) | - (pktin.body[13+i+j] << 16) | - (pktin.body[14+i+j] << 8) | - (pktin.body[15+i+j]); + supported_ciphers_mask = (sp->pktin.body[12+i+j] << 24) | + (sp->pktin.body[13+i+j] << 16) | + (sp->pktin.body[14+i+j] << 8) | + (sp->pktin.body[15+i+j]); MD5Update(&md5c, keystr2, hostkey.bytes); MD5Update(&md5c, keystr1, servkey.bytes); - MD5Update(&md5c, pktin.body, 8); + MD5Update(&md5c, sp->pktin.body, 8); MD5Final(session_id, &md5c); @@ -327,13 +345,13 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { } s_wrpkt_start(3, len+15); - pktout.body[0] = cipher_type; - memcpy(pktout.body+1, cookie, 8); - pktout.body[9] = (len*8) >> 8; - pktout.body[10] = (len*8) & 0xFF; - memcpy(pktout.body+11, rsabuf, len); - pktout.body[len+11] = pktout.body[len+12] = 0; /* protocol flags */ - pktout.body[len+13] = pktout.body[len+14] = 0; + sp->pktout.body[0] = cipher_type; + memcpy(sp->pktout.body+1, cookie, 8); + sp->pktout.body[9] = (len*8) >> 8; + sp->pktout.body[10] = (len*8) & 0xFF; + memcpy(sp->pktout.body+11, rsabuf, len); + sp->pktout.body[len+11] = sp->pktout.body[len+12] = 0; /* protocol flags */ + sp->pktout.body[len+13] = sp->pktout.body[len+14] = 0; s_wrpkt(); free(rsabuf); @@ -342,9 +360,9 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { &ssh_3des; cipher->sesskey(session_key); - do { crReturnV; } while (!ispkt); + do { crReturnV(sp->pr_line); } while (!ispkt); - if (pktin.type != 14) + if (sp->pktin.type != 14) fatalbox("Encryption not successfully enabled"); fflush(stdout); @@ -355,7 +373,7 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { if (!*cfg.username) { c_write("login as: ", 10); while (pos >= 0) { - do { crReturnV; } while (ispkt); + do { crReturnV(sp->pr_line); } while (ispkt); while (inlen--) switch (c = *in++) { case 10: case 13: username[pos] = 0; @@ -395,22 +413,22 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { c_write(stuff, strlen(stuff)); } s_wrpkt_start(4, 4+strlen(username)); - pktout.body[0] = pktout.body[1] = pktout.body[2] = 0; - pktout.body[3] = strlen(username); - memcpy(pktout.body+4, username, strlen(username)); + sp->pktout.body[0] = sp->pktout.body[1] = sp->pktout.body[2] = 0; + sp->pktout.body[3] = strlen(username); + memcpy(sp->pktout.body+4, username, strlen(username)); s_wrpkt(); } - do { crReturnV; } while (!ispkt); + do { crReturnV(sp->pr_line); } while (!ispkt); - while (pktin.type == 15) { + while (sp->pktin.type == 15) { static char password[100]; static int pos; static char c; c_write("password: ", 10); pos = 0; while (pos >= 0) { - do { crReturnV; } while (ispkt); + do { crReturnV(sp->pr_line); } while (ispkt); while (inlen--) switch (c = *in++) { case 10: case 13: password[pos] = 0; @@ -435,43 +453,43 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { } c_write("\r\n", 2); s_wrpkt_start(9, 4+strlen(password)); - pktout.body[0] = pktout.body[1] = pktout.body[2] = 0; - pktout.body[3] = strlen(password); - memcpy(pktout.body+4, password, strlen(password)); + sp->pktout.body[0] = sp->pktout.body[1] = sp->pktout.body[2] = 0; + sp->pktout.body[3] = strlen(password); + memcpy(sp->pktout.body+4, password, strlen(password)); s_wrpkt(); memset(password, 0, strlen(password)); - do { crReturnV; } while (!ispkt); - if (pktin.type == 15) { + do { crReturnV(sp->pr_line); } while (!ispkt); + if (sp->pktin.type == 15) { c_write("Access denied\r\n", 15); - } else if (pktin.type != 14) { - fatalbox("Strange packet received, type %d", pktin.type); + } else if (sp->pktin.type != 14) { + fatalbox("Strange packet received, type %d", sp->pktin.type); } } if (!cfg.nopty) { i = strlen(cfg.termtype); s_wrpkt_start(10, i+5*4+1); - pktout.body[0] = (i >> 24) & 0xFF; - pktout.body[1] = (i >> 16) & 0xFF; - pktout.body[2] = (i >> 8) & 0xFF; - pktout.body[3] = i & 0xFF; - memcpy(pktout.body+4, cfg.termtype, i); + sp->pktout.body[0] = (i >> 24) & 0xFF; + sp->pktout.body[1] = (i >> 16) & 0xFF; + sp->pktout.body[2] = (i >> 8) & 0xFF; + sp->pktout.body[3] = i & 0xFF; + memcpy(sp->pktout.body+4, cfg.termtype, i); i += 4; - pktout.body[i++] = (rows >> 24) & 0xFF; - pktout.body[i++] = (rows >> 16) & 0xFF; - pktout.body[i++] = (rows >> 8) & 0xFF; - pktout.body[i++] = rows & 0xFF; - pktout.body[i++] = (cols >> 24) & 0xFF; - pktout.body[i++] = (cols >> 16) & 0xFF; - pktout.body[i++] = (cols >> 8) & 0xFF; - pktout.body[i++] = cols & 0xFF; - memset(pktout.body+i, 0, 9); /* 0 pixwidth, 0 pixheight, 0.b endofopt */ + sp->pktout.body[i++] = (rows >> 24) & 0xFF; + sp->pktout.body[i++] = (rows >> 16) & 0xFF; + sp->pktout.body[i++] = (rows >> 8) & 0xFF; + sp->pktout.body[i++] = rows & 0xFF; + sp->pktout.body[i++] = (cols >> 24) & 0xFF; + sp->pktout.body[i++] = (cols >> 16) & 0xFF; + sp->pktout.body[i++] = (cols >> 8) & 0xFF; + sp->pktout.body[i++] = cols & 0xFF; + memset(sp->pktout.body+i, 0, 9); /* 0 pixwidth, 0 pixheight, 0.b endofopt */ s_wrpkt(); ssh_state = SSH_STATE_INTERMED; - do { crReturnV; } while (!ispkt); - if (pktin.type != 14 && pktin.type != 15) { + do { crReturnV(sp->pr_line); } while (!ispkt); + if (sp->pktin.type != 14 && sp->pktin.type != 15) { fatalbox("Protocol confusion"); - } else if (pktin.type == 15) { + } else if (sp->pktin.type == 15) { c_write("Server refused to allocate pty\r\n", 32); } } @@ -484,35 +502,35 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { ssh_size(); while (1) { - crReturnV; + crReturnV(sp->pr_line); if (ispkt) { - if (pktin.type == 17 || pktin.type == 18) { + if (sp->pktin.type == 17 || sp->pktin.type == 18) { long len = 0; for (i = 0; i < 4; i++) - len = (len << 8) + pktin.body[i]; - c_write(pktin.body+4, len); - } else if (pktin.type == 1) { + len = (len << 8) + sp->pktin.body[i]; + c_write(sp->pktin.body+4, len); + } else if (sp->pktin.type == 1) { /* SSH_MSG_DISCONNECT */ ssh_state = SSH_STATE_CLOSED; - } else if (pktin.type == 14) { + } else if (sp->pktin.type == 14) { /* SSH_MSG_SUCCESS: may be from EXEC_SHELL on some servers */ - } else if (pktin.type == 15) { + } else if (sp->pktin.type == 15) { /* SSH_MSG_FAILURE: may be from EXEC_SHELL on some servers * if no pty is available or in other odd cases. Ignore */ - } else if (pktin.type == 20) { + } else if (sp->pktin.type == 20) { /* EXITSTATUS */ s_wrpkt_start(33, 0); s_wrpkt(); } else { - fatalbox("Strange packet received: type %d", pktin.type); + fatalbox("Strange packet received: type %d", sp->pktin.type); } } else { s_wrpkt_start(16, 4+inlen); - pktout.body[0] = (inlen >> 24) & 0xFF; - pktout.body[1] = (inlen >> 16) & 0xFF; - pktout.body[2] = (inlen >> 8) & 0xFF; - pktout.body[3] = inlen & 0xFF; - memcpy(pktout.body+4, in, inlen); + sp->pktout.body[0] = (inlen >> 24) & 0xFF; + sp->pktout.body[1] = (inlen >> 16) & 0xFF; + sp->pktout.body[2] = (inlen >> 8) & 0xFF; + sp->pktout.body[3] = inlen & 0xFF; + memcpy(sp->pktout.body+4, in, inlen); s_wrpkt(); } } @@ -529,91 +547,40 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { * * Also places the canonical host name into `realhost'. */ -static char *ssh_init (HWND hwnd, char *host, int port, char **realhost) { - SOCKADDR_IN addr; - struct hostent *h; - unsigned long a; -#ifdef FWHACK - char *FWhost; - int FWport; -#endif +static char *ssh_init(Session *sess) { + struct ssh_private *sp; + char *host = sess->cfg.host; + int port = sess->cfg.port; - savedhost = malloc(1+strlen(host)); - if (!savedhost) - fatalbox("Out of memory"); - strcpy(savedhost, host); + sess->back_priv = smalloc(sizeof(struct ssh_private)); + sp = (struct ssh_private *)sess->back_priv; + memset(*sp, 0, sizeof(*sp)); + sp->s = INVALID_SOCKET; + sp->ssh_state = SSH_STATE_BEFORE_SIZE; + + sp->savedhost = smalloc(1+strlen(host)); + strcpy(sp->savedhost, host); #ifdef FWHACK - FWhost = host; - FWport = port; + sp->FWhost = host; + sp->FWport = port; host = FWSTR; port = 23; #endif - /* - * Try to find host. - */ - if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) { - if ( (h = gethostbyname(host)) == NULL) - switch (WSAGetLastError()) { - case WSAENETDOWN: return "Network is down"; - case WSAHOST_NOT_FOUND: case WSANO_DATA: - return "Host does not exist"; - case WSATRY_AGAIN: return "Host not found"; - default: return "gethostbyname: unknown error"; - } - memcpy (&a, h->h_addr, sizeof(a)); - *realhost = h->h_name; - } else - *realhost = host; -#ifdef FWHACK - *realhost = FWhost; -#endif - a = ntohl(a); - if (port < 0) port = 22; /* default ssh port */ + sp->s = net_open(sess, host, port); - /* - * Open socket. - */ - s = socket(AF_INET, SOCK_STREAM, 0); - if (s == INVALID_SOCKET) - switch (WSAGetLastError()) { - case WSAENETDOWN: return "Network is down"; - case WSAEAFNOSUPPORT: return "TCP/IP support not present"; - default: return "socket(): unknown error"; - } - - /* - * Bind to local address. - */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(0); - if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) - switch (WSAGetLastError()) { - case WSAENETDOWN: return "Network is down"; - default: return "bind(): unknown error"; - } + return NULL; +} - /* - * Connect to remote address. - */ - addr.sin_addr.s_addr = htonl(a); - addr.sin_port = htons((short)port); - if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) - switch (WSAGetLastError()) { - case WSAENETDOWN: return "Network is down"; - case WSAECONNREFUSED: return "Connection refused"; - case WSAENETUNREACH: return "Network is unreachable"; - case WSAEHOSTUNREACH: return "No route to host"; - default: return "connect(): unknown error"; - } +static void ssh_opened(Session *sess) { + struct ssh_private *sp = (struct ssh_private *)sess->back_priv; #ifdef FWHACK - send(s, "connect ", 8, 0); - send(s, FWhost, strlen(FWhost), 0); + send(sp->s, "connect ", 8, 0); + send(sp->s, FWhost, strlen(FWhost), 0); { char buf[20]; sprintf(buf, " %d\n", FWport); @@ -637,33 +604,44 @@ static char *ssh_init (HWND hwnd, char *host, int port, char **realhost) { * Process a WM_NETEVENT message. Will return 0 if the connection * has closed, or <0 for a socket error. */ -static int ssh_msg (WPARAM wParam, LPARAM lParam) { +static int ssh_msg (Session *sess, SOCKET sock, Net_Event_Type ne) { + struct ssh_private *sp = (struct ssh_provate *)sess->back_priv; int ret; char buf[256]; if (s == INVALID_SOCKET) /* how the hell did we get here?! */ return -5000; - if (WSAGETSELECTERROR(lParam) != 0) - return -WSAGETSELECTERROR(lParam); - - switch (WSAGETSELECTEVENT(lParam)) { - case FD_READ: - ret = recv(s, buf, sizeof(buf), 0); - if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) - return 1; + switch (ne) { + case NE_OPEN: + ssh_opened(sess); + return 1; + case NE_DATA: + ret = net_recv(sock, buf, sizeof(buf), 0); if (ret < 0) /* any _other_ error */ - return -10000-WSAGetLastError(); + return -1; if (ret == 0) { - s = INVALID_SOCKET; + sp->s = INVALID_SOCKET; return 0; /* can't happen, in theory */ } - ssh_gotdata (buf, ret); + ssh_gotdata(sess, buf, ret); return 1; - case FD_CLOSE: - s = INVALID_SOCKET; - ssh_state = SSH_STATE_CLOSED; + case NE_CLOSING: + sp->s = INVALID_SOCKET; + sp->ssh_state = SSH_STATE_CLOSED; return 0; + case NE_NOHOST: + fatalbox("Host not found"); + case NE_REFUSED: + fatalbox("Connection refused"); + case NE_NOOPEN: + fatalbox("Unable to open connection"); + case NE_TIMEOUT: + fatalbox("Connection timed out"); + case NE_ABORT: + fatalbox("Connection reset by peer"); + case NE_DIED: + fatalbox("Connection died"); } return 1; /* shouldn't happen, but WTF */ } @@ -671,36 +649,38 @@ static int ssh_msg (WPARAM wParam, LPARAM lParam) { /* * Called to send data down the Telnet connection. */ -static void ssh_send (char *buf, int len) { +static void ssh_send(Session *sess, char *buf, int len) { if (s == INVALID_SOCKET) return; - ssh_protocol(buf, len, 0); + ssh_protocol(sess, buf, len, 0); } /* * Called to set the size of the window from Telnet's POV. */ -static void ssh_size(void) { - switch (ssh_state) { +static void ssh_size(Session *sess) { + struct ssh_private *sp = (struct ssh_private *sp)sess->back_priv; + + switch (sp->ssh_state) { case SSH_STATE_BEFORE_SIZE: case SSH_STATE_CLOSED: break; /* do nothing */ case SSH_STATE_INTERMED: - size_needed = TRUE; /* buffer for later */ + sp->size_needed = TRUE; /* buffer for later */ break; case SSH_STATE_SESSION: - if (!cfg.nopty) { + if (!sess->cfg.nopty) { s_wrpkt_start(11, 16); - pktout.body[0] = (rows >> 24) & 0xFF; - pktout.body[1] = (rows >> 16) & 0xFF; - pktout.body[2] = (rows >> 8) & 0xFF; - pktout.body[3] = rows & 0xFF; - pktout.body[4] = (cols >> 24) & 0xFF; - pktout.body[5] = (cols >> 16) & 0xFF; - pktout.body[6] = (cols >> 8) & 0xFF; - pktout.body[7] = cols & 0xFF; - memset(pktout.body+8, 0, 8); + sp->pktout.body[0] = (rows >> 24) & 0xFF; + sp->pktout.body[1] = (rows >> 16) & 0xFF; + sp->pktout.body[2] = (rows >> 8) & 0xFF; + sp->pktout.body[3] = rows & 0xFF; + sp->pktout.body[4] = (cols >> 24) & 0xFF; + sp->pktout.body[5] = (cols >> 16) & 0xFF; + sp->pktout.body[6] = (cols >> 8) & 0xFF; + sp->pktout.body[7] = cols & 0xFF; + memset(sp->pktout.body+8, 0, 8); s_wrpkt(); } } -- 2.45.2