]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - ssh.c
Added a fourth application: plink, a command line connection utility
[PuTTY.git] / ssh.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <assert.h>
5 #include <winsock.h>
6
7 #include "putty.h"
8 #include "ssh.h"
9 #include "scp.h"
10
11 #ifndef FALSE
12 #define FALSE 0
13 #endif
14 #ifndef TRUE
15 #define TRUE 1
16 #endif
17
18 #define logevent(s) { logevent(s); \
19                       if (!(flags & FLAG_CONNECTION) && (flags & FLAG_VERBOSE)) \
20                       fprintf(stderr, "%s\n", s); }
21
22 #define SSH1_MSG_DISCONNECT     1
23 #define SSH1_SMSG_PUBLIC_KEY    2
24 #define SSH1_CMSG_SESSION_KEY   3
25 #define SSH1_CMSG_USER          4
26 #define SSH1_CMSG_AUTH_RSA      6
27 #define SSH1_SMSG_AUTH_RSA_CHALLENGE 7
28 #define SSH1_CMSG_AUTH_RSA_RESPONSE 8
29 #define SSH1_CMSG_AUTH_PASSWORD 9
30 #define SSH1_CMSG_REQUEST_PTY   10
31 #define SSH1_CMSG_WINDOW_SIZE   11
32 #define SSH1_CMSG_EXEC_SHELL    12
33 #define SSH1_CMSG_EXEC_CMD      13
34 #define SSH1_SMSG_SUCCESS       14
35 #define SSH1_SMSG_FAILURE       15
36 #define SSH1_CMSG_STDIN_DATA    16
37 #define SSH1_SMSG_STDOUT_DATA   17
38 #define SSH1_SMSG_STDERR_DATA   18
39 #define SSH1_CMSG_EOF           19
40 #define SSH1_SMSG_EXIT_STATUS   20
41 #define SSH1_CMSG_EXIT_CONFIRMATION     33
42 #define SSH1_MSG_IGNORE         32
43 #define SSH1_MSG_DEBUG          36
44 #define SSH1_CMSG_AUTH_TIS      39
45 #define SSH1_SMSG_AUTH_TIS_CHALLENGE    40
46 #define SSH1_CMSG_AUTH_TIS_RESPONSE     41
47
48 #define SSH1_AUTH_TIS           5
49
50 #define SSH2_MSG_DISCONNECT             1
51 #define SSH2_MSG_IGNORE                 2
52 #define SSH2_MSG_UNIMPLEMENTED          3
53 #define SSH2_MSG_DEBUG                  4
54 #define SSH2_MSG_SERVICE_REQUEST        5
55 #define SSH2_MSG_SERVICE_ACCEPT         6
56 #define SSH2_MSG_KEXINIT                20
57 #define SSH2_MSG_NEWKEYS                21
58 #define SSH2_MSG_KEXDH_INIT             30
59 #define SSH2_MSG_KEXDH_REPLY            31
60 #define SSH2_MSG_USERAUTH_REQUEST            50
61 #define SSH2_MSG_USERAUTH_FAILURE            51
62 #define SSH2_MSG_USERAUTH_SUCCESS            52
63 #define SSH2_MSG_USERAUTH_BANNER             53
64 #define SSH2_MSG_USERAUTH_PK_OK              60
65 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ   60
66 #define SSH2_MSG_GLOBAL_REQUEST                  80
67 #define SSH2_MSG_REQUEST_SUCCESS                 81
68 #define SSH2_MSG_REQUEST_FAILURE                 82
69 #define SSH2_MSG_CHANNEL_OPEN                    90
70 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION       91
71 #define SSH2_MSG_CHANNEL_OPEN_FAILURE            92
72 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST           93
73 #define SSH2_MSG_CHANNEL_DATA                    94
74 #define SSH2_MSG_CHANNEL_EXTENDED_DATA           95
75 #define SSH2_MSG_CHANNEL_EOF                     96
76 #define SSH2_MSG_CHANNEL_CLOSE                   97
77 #define SSH2_MSG_CHANNEL_REQUEST                 98
78 #define SSH2_MSG_CHANNEL_SUCCESS                 99
79 #define SSH2_MSG_CHANNEL_FAILURE                 100
80
81 #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED    1
82 #define SSH2_OPEN_CONNECT_FAILED                 2
83 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE           3
84 #define SSH2_OPEN_RESOURCE_SHORTAGE              4
85 #define SSH2_EXTENDED_DATA_STDERR                1
86
87 #define GET_32BIT(cp) \
88     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
89     ((unsigned long)(unsigned char)(cp)[1] << 16) | \
90     ((unsigned long)(unsigned char)(cp)[2] << 8) | \
91     ((unsigned long)(unsigned char)(cp)[3]))
92
93 #define PUT_32BIT(cp, value) { \
94     (cp)[0] = (unsigned char)((value) >> 24); \
95     (cp)[1] = (unsigned char)((value) >> 16); \
96     (cp)[2] = (unsigned char)((value) >> 8); \
97     (cp)[3] = (unsigned char)(value); }
98
99 enum { PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM };
100
101 /* Coroutine mechanics for the sillier bits of the code */
102 #define crBegin1        static int crLine = 0;
103 #define crBegin2        switch(crLine) { case 0:;
104 #define crBegin         crBegin1; crBegin2;
105 #define crFinish(z)     } crLine = 0; return (z)
106 #define crFinishV       } crLine = 0; return
107 #define crReturn(z)     \
108         do {\
109             crLine=__LINE__; return (z); case __LINE__:;\
110         } while (0)
111 #define crReturnV       \
112         do {\
113             crLine=__LINE__; return; case __LINE__:;\
114         } while (0)
115 #define crStop(z)       do{ crLine = 0; return (z); }while(0)
116 #define crStopV         do{ crLine = 0; return; }while(0)
117 #define crWaitUntil(c)  do { crReturn(0); } while (!(c))
118 #define crWaitUntilV(c) do { crReturnV; } while (!(c))
119
120 extern struct ssh_cipher ssh_3des;
121 extern struct ssh_cipher ssh_3des_ssh2;
122 extern struct ssh_cipher ssh_des;
123 extern struct ssh_cipher ssh_blowfish;
124
125 /* for ssh 2; we miss out single-DES because it isn't supported */
126 struct ssh_cipher *ciphers[] = { &ssh_3des_ssh2, &ssh_blowfish };
127
128 extern struct ssh_kex ssh_diffiehellman;
129 struct ssh_kex *kex_algs[] = { &ssh_diffiehellman };
130
131 extern struct ssh_hostkey ssh_dss;
132 struct ssh_hostkey *hostkey_algs[] = { &ssh_dss };
133
134 extern struct ssh_mac ssh_sha1;
135
136 SHA_State exhash;
137
138 static void nullmac_key(unsigned char *key) { }
139 static void nullmac_generate(unsigned char *blk, int len, unsigned long seq) { }
140 static int nullmac_verify(unsigned char *blk, int len, unsigned long seq) { return 1; }
141 struct ssh_mac ssh_mac_none = {
142     nullmac_key, nullmac_key, nullmac_generate, nullmac_verify, "none", 0
143 };
144 struct ssh_mac *macs[] = { &ssh_sha1, &ssh_mac_none };
145
146 struct ssh_compress ssh_comp_none = {
147     "none"
148 };
149 struct ssh_compress *compressions[] = { &ssh_comp_none };
150
151 static SOCKET s = INVALID_SOCKET;
152
153 static unsigned char session_key[32];
154 static struct ssh_cipher *cipher = NULL;
155 static struct ssh_cipher *cscipher = NULL;
156 static struct ssh_cipher *sccipher = NULL;
157 static struct ssh_mac *csmac = NULL;
158 static struct ssh_mac *scmac = NULL;
159 static struct ssh_compress *cscomp = NULL;
160 static struct ssh_compress *sccomp = NULL;
161 static struct ssh_kex *kex = NULL;
162 static struct ssh_hostkey *hostkey = NULL;
163 int (*ssh_get_password)(const char *prompt, char *str, int maxlen) = NULL;
164
165 static char *savedhost;
166
167 static enum {
168     SSH_STATE_BEFORE_SIZE,
169     SSH_STATE_INTERMED,
170     SSH_STATE_SESSION,
171     SSH_STATE_CLOSED
172 } ssh_state = SSH_STATE_BEFORE_SIZE;
173
174 static int size_needed = FALSE;
175
176 static void s_write (char *buf, int len) {
177     while (len > 0) {
178         int i = send (s, buf, len, 0);
179         noise_ultralight(i);
180         if (i <= 0)
181             fatalbox("Lost connection while sending");
182         if (i > 0)
183             len -= i, buf += i;
184     }
185 }
186
187 static int s_read (char *buf, int len) {
188     int ret = 0;
189     while (len > 0) {
190         int i = recv (s, buf, len, 0);
191         noise_ultralight(i);
192         if (i > 0)
193             len -= i, buf += i, ret += i;
194         else
195             return i;
196     }
197     return ret;
198 }
199
200 static void c_write (char *buf, int len) {
201     if (!(flags & FLAG_CONNECTION)) {
202         int i;
203         for (i = 0; i < len; i++)
204             if (buf[i] != '\r')
205                 fputc(buf[i], stderr);
206         return;
207     }
208     while (len--) 
209         c_write1(*buf++);
210 }
211
212 struct Packet {
213     long length;
214     int type;
215     unsigned char *data;
216     unsigned char *body;
217     long savedpos;
218     long maxlen;
219 };
220
221 static struct Packet pktin = { 0, 0, NULL, NULL, 0 };
222 static struct Packet pktout = { 0, 0, NULL, NULL, 0 };
223
224 static void (*ssh_protocol)(unsigned char *in, int inlen, int ispkt);
225 static void ssh1_protocol(unsigned char *in, int inlen, int ispkt);
226 static void ssh2_protocol(unsigned char *in, int inlen, int ispkt);
227 static void ssh_size(void);
228
229 static int (*s_rdpkt)(unsigned char **data, int *datalen);
230
231 /*
232  * Collect incoming data in the incoming packet buffer.
233  * Decipher and verify the packet when it is completely read.
234  * Drop SSH1_MSG_DEBUG and SSH1_MSG_IGNORE packets.
235  * Update the *data and *datalen variables.
236  * Return the additional nr of bytes needed, or 0 when
237  * a complete packet is available.
238  */
239 static int ssh1_rdpkt(unsigned char **data, int *datalen)
240 {
241     static long len, pad, biglen, to_read;
242     static unsigned long realcrc, gotcrc;
243     static unsigned char *p;
244     static int i;
245
246     crBegin;
247
248 next_packet:
249
250     pktin.type = 0;
251     pktin.length = 0;
252
253     for (i = len = 0; i < 4; i++) {
254         while ((*datalen) == 0)
255             crReturn(4-i);
256         len = (len << 8) + **data;
257         (*data)++, (*datalen)--;
258     }
259
260 #ifdef FWHACK
261     if (len == 0x52656d6f) {       /* "Remo"te server has closed ... */
262         len = 0x300;               /* big enough to carry to end */
263     }
264 #endif
265
266     pad = 8 - (len % 8);
267     biglen = len + pad;
268     pktin.length = len - 5;
269
270     if (pktin.maxlen < biglen) {
271         pktin.maxlen = biglen;
272         pktin.data = (pktin.data == NULL ? malloc(biglen+APIEXTRA) :
273                       realloc(pktin.data, biglen+APIEXTRA));
274         if (!pktin.data)
275             fatalbox("Out of memory");
276     }
277
278     to_read = biglen;
279     p = pktin.data;
280     while (to_read > 0) {
281         static int chunk;
282         chunk = to_read;
283         while ((*datalen) == 0)
284             crReturn(to_read);
285         if (chunk > (*datalen))
286             chunk = (*datalen);
287         memcpy(p, *data, chunk);
288         *data += chunk;
289         *datalen -= chunk;
290         p += chunk;
291         to_read -= chunk;
292     }
293
294     if (cipher)
295         cipher->decrypt(pktin.data, biglen);
296
297     pktin.type = pktin.data[pad];
298     pktin.body = pktin.data + pad + 1;
299
300     realcrc = crc32(pktin.data, biglen-4);
301     gotcrc = GET_32BIT(pktin.data+biglen-4);
302     if (gotcrc != realcrc) {
303         fatalbox("Incorrect CRC received on packet");
304     }
305
306     if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
307         pktin.type == SSH1_SMSG_STDERR_DATA ||
308         pktin.type == SSH1_MSG_DEBUG ||
309         pktin.type == SSH1_SMSG_AUTH_TIS_CHALLENGE) {
310         long strlen = GET_32BIT(pktin.body);
311         if (strlen + 4 != pktin.length)
312             fatalbox("Received data packet with bogus string length");
313     }
314
315     if (pktin.type == SSH1_MSG_DEBUG) {
316         /* log debug message */
317         char buf[80];
318         int strlen = GET_32BIT(pktin.body);
319         strcpy(buf, "Remote: ");
320         if (strlen > 70) strlen = 70;
321         memcpy(buf+8, pktin.body+4, strlen);
322         buf[8+strlen] = '\0';
323         logevent(buf);
324         goto next_packet;
325     } else if (pktin.type == SSH1_MSG_IGNORE) {
326         /* do nothing */
327         goto next_packet;
328     }
329
330     crFinish(0);
331 }
332
333 static int ssh2_rdpkt(unsigned char **data, int *datalen)
334 {
335     static long len, pad, payload, packetlen, maclen;
336     static int i;
337     static int cipherblk;
338     static unsigned long incoming_sequence = 0;
339
340     crBegin;
341
342 next_packet:
343
344     pktin.type = 0;
345     pktin.length = 0;
346
347     if (cipher)
348         cipherblk = cipher->blksize;
349     else
350         cipherblk = 8;
351     if (cipherblk < 8)
352         cipherblk = 8;
353
354     if (pktin.maxlen < cipherblk) {
355         pktin.maxlen = cipherblk;
356         pktin.data = (pktin.data == NULL ? malloc(cipherblk+APIEXTRA) :
357                       realloc(pktin.data, cipherblk+APIEXTRA));
358         if (!pktin.data)
359             fatalbox("Out of memory");
360     }
361
362     /*
363      * Acquire and decrypt the first block of the packet. This will
364      * contain the length and padding details.
365      */
366      for (i = len = 0; i < cipherblk; i++) {
367         while ((*datalen) == 0)
368             crReturn(cipherblk-i);
369         pktin.data[i] = *(*data)++;
370         (*datalen)--;
371     }
372 #ifdef FWHACK
373     if (!memcmp(pktin.data, "Remo", 4)) {/* "Remo"te server has closed ... */
374         /* FIXME */
375     }
376 #endif
377     if (sccipher)
378         sccipher->decrypt(pktin.data, cipherblk);
379
380     /*
381      * Now get the length and padding figures.
382      */
383     len = GET_32BIT(pktin.data);
384     pad = pktin.data[4];
385
386     /*
387      * This enables us to deduce the payload length.
388      */
389     payload = len - pad - 1;
390
391     pktin.length = payload + 5;
392
393     /*
394      * So now we can work out the total packet length.
395      */
396     packetlen = len + 4;
397     maclen = scmac ? scmac->len : 0;
398
399     /*
400      * Adjust memory allocation if packet is too big.
401      */
402     if (pktin.maxlen < packetlen) {
403         pktin.maxlen = packetlen;
404         pktin.data = (pktin.data == NULL ? malloc(packetlen+APIEXTRA) :
405                       realloc(pktin.data, packetlen+APIEXTRA));
406         if (!pktin.data)
407             fatalbox("Out of memory");
408     }
409
410     /*
411      * Read and decrypt the remainder of the packet.
412      */
413     for (i = cipherblk; i < packetlen + maclen; i++) {
414         while ((*datalen) == 0)
415             crReturn(packetlen + maclen - i);
416         pktin.data[i] = *(*data)++;
417         (*datalen)--;
418     }
419     /* Decrypt everything _except_ the MAC. */
420     if (sccipher)
421         sccipher->decrypt(pktin.data + cipherblk, packetlen - cipherblk);
422
423 #if 0
424     debug(("Got packet len=%d pad=%d\r\n", len, pad));
425     for (i = 0; i < packetlen; i++)
426         debug(("  %02x", (unsigned char)pktin.data[i]));
427     debug(("\r\n"));
428 #endif
429
430     /*
431      * Check the MAC.
432      */
433     if (scmac && !scmac->verify(pktin.data, len+4, incoming_sequence))
434         fatalbox("Incorrect MAC received on packet");
435     incoming_sequence++;               /* whether or not we MACed */
436
437     pktin.savedpos = 6;
438     pktin.type = pktin.data[5];
439
440     if (pktin.type == SSH2_MSG_IGNORE || pktin.type == SSH2_MSG_DEBUG)
441         goto next_packet;              /* FIXME: print DEBUG message */
442
443     crFinish(0);
444 }
445
446 static void ssh_gotdata(unsigned char *data, int datalen)
447 {
448     while (datalen > 0) {
449         if ( s_rdpkt(&data, &datalen) == 0 ) {
450             ssh_protocol(NULL, 0, 1);
451             if (ssh_state == SSH_STATE_CLOSED) {
452                 return;
453             }
454         }
455     }
456 }
457
458
459 static void s_wrpkt_start(int type, int len) {
460     int pad, biglen;
461
462     len += 5;                          /* type and CRC */
463     pad = 8 - (len%8);
464     biglen = len + pad;
465
466     pktout.length = len-5;
467     if (pktout.maxlen < biglen) {
468         pktout.maxlen = biglen;
469 #ifdef MSCRYPTOAPI
470         /* Allocate enough buffer space for extra block
471          * for MS CryptEncrypt() */
472         pktout.data = (pktout.data == NULL ? malloc(biglen+12) :
473                        realloc(pktout.data, biglen+12));
474 #else
475         pktout.data = (pktout.data == NULL ? malloc(biglen+4) :
476                        realloc(pktout.data, biglen+4));
477 #endif
478         if (!pktout.data)
479             fatalbox("Out of memory");
480     }
481
482     pktout.type = type;
483     pktout.body = pktout.data+4+pad+1;
484 }
485
486 static void s_wrpkt(void) {
487     int pad, len, biglen, i;
488     unsigned long crc;
489
490     len = pktout.length + 5;           /* type and CRC */
491     pad = 8 - (len%8);
492     biglen = len + pad;
493
494     pktout.body[-1] = pktout.type;
495     for (i=0; i<pad; i++)
496         pktout.data[i+4] = random_byte();
497     crc = crc32(pktout.data+4, biglen-4);
498     PUT_32BIT(pktout.data+biglen, crc);
499     PUT_32BIT(pktout.data, len);
500
501     if (cipher)
502         cipher->encrypt(pktout.data+4, biglen);
503
504     s_write(pktout.data, biglen+4);
505 }
506
507 /*
508  * Construct a packet with the specified contents and
509  * send it to the server.
510  */
511 static void send_packet(int pkttype, ...)
512 {
513     va_list args;
514     unsigned char *p, *argp, argchar;
515     unsigned long argint;
516     int pktlen, argtype, arglen;
517     Bignum bn;
518     int i;
519
520     pktlen = 0;
521     va_start(args, pkttype);
522     while ((argtype = va_arg(args, int)) != PKT_END) {
523         switch (argtype) {
524           case PKT_INT:
525             (void) va_arg(args, int);
526             pktlen += 4;
527             break;
528           case PKT_CHAR:
529             (void) va_arg(args, char);
530             pktlen++;
531             break;
532           case PKT_DATA:
533             (void) va_arg(args, unsigned char *);
534             arglen = va_arg(args, int);
535             pktlen += arglen;
536             break;
537           case PKT_STR:
538             argp = va_arg(args, unsigned char *);
539             arglen = strlen(argp);
540             pktlen += 4 + arglen;
541             break;
542           case PKT_BIGNUM:
543             bn = va_arg(args, Bignum);
544             i = 16 * bn[0] - 1;
545             while ( i > 0 && (bn[i/16+1] >> (i%16)) == 0 )
546                 i--;
547             pktlen += 2 + (i+7)/8;
548             break;
549           default:
550             assert(0);
551         }
552     }
553     va_end(args);
554
555     s_wrpkt_start(pkttype, pktlen);
556     p = pktout.body;
557
558     va_start(args, pkttype);
559     while ((argtype = va_arg(args, int)) != PKT_END) {
560         switch (argtype) {
561           case PKT_INT:
562             argint = va_arg(args, int);
563             PUT_32BIT(p, argint);
564             p += 4;
565             break;
566           case PKT_CHAR:
567             argchar = va_arg(args, unsigned char);
568             *p = argchar;
569             p++;
570             break;
571           case PKT_DATA:
572             argp = va_arg(args, unsigned char *);
573             arglen = va_arg(args, int);
574             memcpy(p, argp, arglen);
575             p += arglen;
576             break;
577           case PKT_STR:
578             argp = va_arg(args, unsigned char *);
579             arglen = strlen(argp);
580             PUT_32BIT(p, arglen);
581             memcpy(p + 4, argp, arglen);
582             p += 4 + arglen;
583             break;
584           case PKT_BIGNUM:
585             bn = va_arg(args, Bignum);
586             i = 16 * bn[0] - 1;
587             while ( i > 0 && (bn[i/16+1] >> (i%16)) == 0 )
588                 i--;
589             *p++ = (i >> 8) & 0xFF;
590             *p++ = i & 0xFF;
591             i = (i + 7) / 8;
592             while (i-- > 0) {
593                 if (i % 2)
594                     *p++ = bn[i/2+1] >> 8;
595                 else
596                     *p++ = bn[i/2+1] & 0xFF;
597             }
598             break;
599         }
600     }
601     va_end(args);
602
603     s_wrpkt();
604 }
605
606
607 /*
608  * Connect to specified host and port.
609  * Returns an error message, or NULL on success.
610  * Also places the canonical host name into `realhost'.
611  */
612 static char *connect_to_host(char *host, int port, char **realhost)
613 {
614     SOCKADDR_IN addr;
615     struct hostent *h;
616     unsigned long a;
617 #ifdef FWHACK
618     char *FWhost;
619     int FWport;
620 #endif
621
622     savedhost = malloc(1+strlen(host));
623     if (!savedhost)
624         fatalbox("Out of memory");
625     strcpy(savedhost, host);
626
627     if (port < 0)
628         port = 22;                     /* default ssh port */
629
630 #ifdef FWHACK
631     FWhost = host;
632     FWport = port;
633     host = FWSTR;
634     port = 23;
635 #endif
636
637     /*
638      * Try to find host.
639      */
640     if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
641         if ( (h = gethostbyname(host)) == NULL)
642             switch (WSAGetLastError()) {
643               case WSAENETDOWN: return "Network is down";
644               case WSAHOST_NOT_FOUND: case WSANO_DATA:
645                 return "Host does not exist";
646               case WSATRY_AGAIN: return "Host not found";
647               default: return "gethostbyname: unknown error";
648             }
649         memcpy (&a, h->h_addr, sizeof(a));
650         *realhost = h->h_name;
651     } else
652         *realhost = host;
653 #ifdef FWHACK
654     *realhost = FWhost;
655 #endif
656     a = ntohl(a);
657
658     /*
659      * Open socket.
660      */
661     s = socket(AF_INET, SOCK_STREAM, 0);
662     if (s == INVALID_SOCKET)
663         switch (WSAGetLastError()) {
664           case WSAENETDOWN: return "Network is down";
665           case WSAEAFNOSUPPORT: return "TCP/IP support not present";
666           default: return "socket(): unknown error";
667         }
668
669     /*
670      * Bind to local address.
671      */
672     addr.sin_family = AF_INET;
673     addr.sin_addr.s_addr = htonl(INADDR_ANY);
674     addr.sin_port = htons(0);
675     if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
676         switch (WSAGetLastError()) {
677           case WSAENETDOWN: return "Network is down";
678           default: return "bind(): unknown error";
679         }
680
681     /*
682      * Connect to remote address.
683      */
684     addr.sin_addr.s_addr = htonl(a);
685     addr.sin_port = htons((short)port);
686     if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
687         switch (WSAGetLastError()) {
688           case WSAENETDOWN: return "Network is down";
689           case WSAECONNREFUSED: return "Connection refused";
690           case WSAENETUNREACH: return "Network is unreachable";
691           case WSAEHOSTUNREACH: return "No route to host";
692           default: return "connect(): unknown error";
693         }
694
695 #ifdef FWHACK
696     send(s, "connect ", 8, 0);
697     send(s, FWhost, strlen(FWhost), 0);
698     {
699         char buf[20];
700         sprintf(buf, " %d\n", FWport);
701         send (s, buf, strlen(buf), 0);
702     }
703 #endif
704
705     return NULL;
706 }
707
708 static int ssh_versioncmp(char *a, char *b) {
709     char *ae, *be;
710     unsigned long av, bv;
711
712     av = strtoul(a, &ae, 10);
713     bv = strtoul(b, &be, 10);
714     if (av != bv) return (av < bv ? -1 : +1);
715     if (*ae == '.') ae++;
716     if (*be == '.') be++;
717     av = strtoul(ae, &ae, 10);
718     bv = strtoul(be, &be, 10);
719     if (av != bv) return (av < bv ? -1 : +1);
720     return 0;
721 }
722
723
724 /*
725  * Utility routine for putting an SSH-protocol `string' into a SHA
726  * state.
727  */
728 #include <stdio.h>
729 void sha_string(SHA_State *s, void *str, int len) {
730     unsigned char lenblk[4];
731 static FILE *fp;
732     PUT_32BIT(lenblk, len);
733 if (!fp) fp = fopen("h:\\statham\\windows\\putty\\data","wb");
734 fwrite(lenblk, 4, 1, fp);
735     SHA_Bytes(s, lenblk, 4);
736 fwrite(str, len, 1, fp);
737 fflush(fp);
738     SHA_Bytes(s, str, len);
739 }
740
741 /*
742  * SSH2 packet construction functions.
743  */
744 void ssh2_pkt_adddata(void *data, int len) {
745     pktout.length += len;
746     if (pktout.maxlen < pktout.length) {
747         pktout.maxlen = pktout.length + 256;
748         pktout.data = (pktout.data == NULL ? malloc(pktout.maxlen+APIEXTRA) :
749                        realloc(pktout.data, pktout.maxlen+APIEXTRA));
750         if (!pktout.data)
751             fatalbox("Out of memory");
752     }
753     memcpy(pktout.data+pktout.length-len, data, len);
754 }
755 void ssh2_pkt_addbyte(unsigned char byte) {
756     ssh2_pkt_adddata(&byte, 1);
757 }
758 void ssh2_pkt_init(int pkt_type) {
759     pktout.length = 5;
760     ssh2_pkt_addbyte((unsigned char)pkt_type);
761 }
762 void ssh2_pkt_addbool(unsigned char value) {
763     ssh2_pkt_adddata(&value, 1);
764 }
765 void ssh2_pkt_adduint32(unsigned long value) {
766     unsigned char x[4];
767     PUT_32BIT(x, value);
768     ssh2_pkt_adddata(x, 4);
769 }
770 void ssh2_pkt_addstring_start(void) {
771     ssh2_pkt_adduint32(0);
772     pktout.savedpos = pktout.length;
773 }
774 void ssh2_pkt_addstring_str(char *data) {
775     ssh2_pkt_adddata(data, strlen(data));
776     PUT_32BIT(pktout.data + pktout.savedpos - 4,
777               pktout.length - pktout.savedpos);
778 }
779 void ssh2_pkt_addstring_data(char *data, int len) {
780     ssh2_pkt_adddata(data, len);
781     PUT_32BIT(pktout.data + pktout.savedpos - 4,
782               pktout.length - pktout.savedpos);
783 }
784 void ssh2_pkt_addstring(char *data) {
785     ssh2_pkt_addstring_start();
786     ssh2_pkt_addstring_str(data);
787 }
788 char *ssh2_mpint_fmt(Bignum b, int *len) {
789     unsigned char *p;
790     int i, n = b[0];
791     p = malloc(n * 2 + 1);
792     if (!p)
793         fatalbox("out of memory");
794     p[0] = 0;
795     for (i = 0; i < n; i++) {
796         p[i*2+1] = (b[n-i] >> 8) & 0xFF;
797         p[i*2+2] = (b[n-i]     ) & 0xFF;
798     }
799     i = 0;
800     while (p[i] == 0 && (p[i+1] & 0x80) == 0)
801         i++;
802     memmove(p, p+i, n*2+1-i);
803     *len = n*2+1-i;
804     return p;
805 }
806 void ssh2_pkt_addmp(Bignum b) {
807     unsigned char *p;
808     int len;
809     p = ssh2_mpint_fmt(b, &len);
810     ssh2_pkt_addstring_start();
811     ssh2_pkt_addstring_data(p, len);
812     free(p);
813 }
814 void ssh2_pkt_send(void) {
815     int cipherblk, maclen, padding, i;
816     static unsigned long outgoing_sequence = 0;
817
818     /*
819      * Add padding. At least four bytes, and must also bring total
820      * length (minus MAC) up to a multiple of the block size.
821      */
822     cipherblk = cipher ? cipher->blksize : 8;   /* block size */
823     cipherblk = cipherblk < 8 ? 8 : cipherblk;   /* or 8 if blksize < 8 */
824     padding = 4;
825     padding += (cipherblk - (pktout.length + padding) % cipherblk) % cipherblk;
826     pktout.data[4] = padding;
827     for (i = 0; i < padding; i++)
828         pktout.data[pktout.length + i] = random_byte();
829     PUT_32BIT(pktout.data, pktout.length + padding - 4);
830     if (csmac)
831         csmac->generate(pktout.data, pktout.length + padding,
832                         outgoing_sequence);
833     outgoing_sequence++;               /* whether or not we MACed */
834
835 #if 0
836     debug(("Sending packet len=%d\r\n", pktout.length+padding));
837     for (i = 0; i < pktout.length+padding; i++)
838         debug(("  %02x", (unsigned char)pktout.data[i]));
839     debug(("\r\n"));
840 #endif
841
842     if (cscipher)
843         cscipher->encrypt(pktout.data, pktout.length + padding);
844     maclen = csmac ? csmac->len : 0;
845
846     s_write(pktout.data, pktout.length + padding + maclen);
847 }
848
849 #if 0
850 void bndebug(char *string, Bignum b) {
851     unsigned char *p;
852     int i, len;
853     p = ssh2_mpint_fmt(b, &len);
854     debug(("%s", string));
855     for (i = 0; i < len; i++)
856         debug((" %02x", p[i]));
857     debug(("\r\n"));
858     free(p);
859 }
860 #endif
861
862 void sha_mpint(SHA_State *s, Bignum b) {
863     unsigned char *p;
864     int len;
865     p = ssh2_mpint_fmt(b, &len);
866     sha_string(s, p, len);
867     free(p);
868 }
869
870 /*
871  * SSH2 packet decode functions.
872  */
873 unsigned long ssh2_pkt_getuint32(void) {
874     unsigned long value;
875     if (pktin.length - pktin.savedpos < 4)
876         return 0;                      /* arrgh, no way to decline (FIXME?) */
877     value = GET_32BIT(pktin.data+pktin.savedpos);
878     pktin.savedpos += 4;
879     return value;
880 }
881 void ssh2_pkt_getstring(char **p, int *length) {
882     *p = NULL;
883     if (pktin.length - pktin.savedpos < 4)
884         return;
885     *length = GET_32BIT(pktin.data+pktin.savedpos);
886     pktin.savedpos += 4;
887     if (pktin.length - pktin.savedpos < *length)
888         return;
889     *p = pktin.data+pktin.savedpos;
890     pktin.savedpos += *length;
891 }
892 Bignum ssh2_pkt_getmp(void) {
893     char *p;
894     int i, j, length;
895     Bignum b;
896
897     ssh2_pkt_getstring(&p, &length);
898     if (!p)
899         return NULL;
900     if (p[0] & 0x80)
901         fatalbox("internal error: Can't handle negative mpints");
902     b = newbn((length+1)/2);
903     for (i = 0; i < length; i++) {
904         j = length - 1 - i;
905         if (j & 1)
906             b[j/2+1] |= ((unsigned char)p[i]) << 8;
907         else
908             b[j/2+1] |= ((unsigned char)p[i]);
909     }
910     return b;
911 }
912
913 static int do_ssh_init(void) {
914     char c, *vsp;
915     char version[10];
916     char vstring[80];
917     char vlog[sizeof(vstring)+20];
918     int i;
919
920 #ifdef FWHACK
921     i = 0;
922     while (s_read(&c, 1) == 1) {
923         if (c == 'S' && i < 2) i++;
924         else if (c == 'S' && i == 2) i = 2;
925         else if (c == 'H' && i == 2) break;
926         else i = 0;
927     }
928 #else
929     if (s_read(&c,1) != 1 || c != 'S') return 0;
930     if (s_read(&c,1) != 1 || c != 'S') return 0;
931     if (s_read(&c,1) != 1 || c != 'H') return 0;
932 #endif
933     strcpy(vstring, "SSH-");
934     vsp = vstring+4;
935     if (s_read(&c,1) != 1 || c != '-') return 0;
936     i = 0;
937     while (1) {
938         if (s_read(&c,1) != 1)
939             return 0;
940         if (vsp < vstring+sizeof(vstring)-1)
941             *vsp++ = c;
942         if (i >= 0) {
943             if (c == '-') {
944                 version[i] = '\0';
945                 i = -1;
946             } else if (i < sizeof(version)-1)
947                 version[i++] = c;
948         }
949         else if (c == '\n')
950             break;
951     }
952
953     *vsp = 0;
954     sprintf(vlog, "Server version: %s", vstring);
955     vlog[strcspn(vlog, "\r\n")] = '\0';
956     logevent(vlog);
957
958     if (ssh_versioncmp(version, "2.0" /* FIXME: "1.99" */ ) >= 0) {
959         /*
960          * This is a v2 server. Begin v2 protocol.
961          */
962         char *verstring = "SSH-2.0-PuTTY";
963         SHA_Init(&exhash);
964         /*
965          * Hash our version string and their version string.
966          */
967         sha_string(&exhash, verstring, strlen(verstring));
968         sha_string(&exhash, vstring, strcspn(vstring, "\r\n"));
969         sprintf(vstring, "%s\n", verstring);
970         sprintf(vlog, "We claim version: %s", verstring);
971         logevent(vlog);
972         logevent("Using SSH protocol version 2");
973         s_write(vstring, strlen(vstring));
974         ssh_protocol = ssh2_protocol;
975         s_rdpkt = ssh2_rdpkt;
976     } else {
977         /*
978          * This is a v1 server. Begin v1 protocol.
979          */
980         sprintf(vstring, "SSH-%s-PuTTY\n",
981                 (ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"));
982         sprintf(vlog, "We claim version: %s", vstring);
983         vlog[strcspn(vlog, "\r\n")] = '\0';
984         logevent(vlog);
985         logevent("Using SSH protocol version 1");
986         s_write(vstring, strlen(vstring));
987         ssh_protocol = ssh1_protocol;
988         s_rdpkt = ssh1_rdpkt;
989     }
990     return 1;
991 }
992
993 /*
994  * Handle the key exchange and user authentication phases.
995  */
996 static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
997 {
998     int i, j, len;
999     unsigned char *rsabuf, *keystr1, *keystr2;
1000     unsigned char cookie[8];
1001     struct RSAKey servkey, hostkey;
1002     struct MD5Context md5c;
1003     static unsigned long supported_ciphers_mask, supported_auths_mask;
1004     static int tried_publickey;
1005     static unsigned char session_id[16];
1006     int cipher_type;
1007
1008     crBegin;
1009
1010     if (!ispkt) crWaitUntil(ispkt);
1011
1012     if (pktin.type != SSH1_SMSG_PUBLIC_KEY)
1013         fatalbox("Public key packet not received");
1014
1015     logevent("Received public keys");
1016
1017     memcpy(cookie, pktin.body, 8);
1018
1019     i = makekey(pktin.body+8, &servkey, &keystr1, 0);
1020     j = makekey(pktin.body+8+i, &hostkey, &keystr2, 0);
1021
1022     /*
1023      * Hash the host key and print the hash in the log box. Just as
1024      * a last resort in case the registry's host key checking is
1025      * compromised, we'll allow the user some ability to verify
1026      * host keys by eye.
1027      */
1028     MD5Init(&md5c);
1029     MD5Update(&md5c, keystr2, hostkey.bytes);
1030     MD5Final(session_id, &md5c);
1031     {
1032         char logmsg[80];
1033         int i;
1034         logevent("Host key MD5 is:");
1035         strcpy(logmsg, "      ");
1036         for (i = 0; i < 16; i++)
1037             sprintf(logmsg+strlen(logmsg), "%02x", session_id[i]);
1038         logevent(logmsg);
1039     }
1040
1041     supported_ciphers_mask = GET_32BIT(pktin.body+12+i+j);
1042     supported_auths_mask = GET_32BIT(pktin.body+16+i+j);
1043
1044     MD5Init(&md5c);
1045     MD5Update(&md5c, keystr2, hostkey.bytes);
1046     MD5Update(&md5c, keystr1, servkey.bytes);
1047     MD5Update(&md5c, pktin.body, 8);
1048     MD5Final(session_id, &md5c);
1049
1050     for (i=0; i<32; i++)
1051         session_key[i] = random_byte();
1052
1053     len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);
1054
1055     rsabuf = malloc(len);
1056     if (!rsabuf)
1057         fatalbox("Out of memory");
1058
1059     /*
1060      * Verify the host key.
1061      */
1062     {
1063         /*
1064          * First format the key into a string.
1065          */
1066         int len = rsastr_len(&hostkey);
1067         char *keystr = malloc(len);
1068         if (!keystr)
1069             fatalbox("Out of memory");
1070         rsastr_fmt(keystr, &hostkey);
1071         verify_ssh_host_key(savedhost, keystr);
1072         free(keystr);
1073     }
1074
1075     for (i=0; i<32; i++) {
1076         rsabuf[i] = session_key[i];
1077         if (i < 16)
1078             rsabuf[i] ^= session_id[i];
1079     }
1080
1081     if (hostkey.bytes > servkey.bytes) {
1082         rsaencrypt(rsabuf, 32, &servkey);
1083         rsaencrypt(rsabuf, servkey.bytes, &hostkey);
1084     } else {
1085         rsaencrypt(rsabuf, 32, &hostkey);
1086         rsaencrypt(rsabuf, hostkey.bytes, &servkey);
1087     }
1088
1089     logevent("Encrypted session key");
1090
1091     cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :
1092                   cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES : 
1093                   SSH_CIPHER_3DES;
1094     if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {
1095         c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);
1096         cipher_type = SSH_CIPHER_3DES;
1097     }
1098     switch (cipher_type) {
1099       case SSH_CIPHER_3DES: logevent("Using 3DES encryption"); break;
1100       case SSH_CIPHER_DES: logevent("Using single-DES encryption"); break;
1101       case SSH_CIPHER_BLOWFISH: logevent("Using Blowfish encryption"); break;
1102     }
1103
1104     send_packet(SSH1_CMSG_SESSION_KEY,
1105                 PKT_CHAR, cipher_type,
1106                 PKT_DATA, cookie, 8,
1107                 PKT_CHAR, (len*8) >> 8, PKT_CHAR, (len*8) & 0xFF,
1108                 PKT_DATA, rsabuf, len,
1109                 PKT_INT, 0,
1110                 PKT_END);
1111
1112     logevent("Trying to enable encryption...");
1113
1114     free(rsabuf);
1115
1116     cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish :
1117              cipher_type == SSH_CIPHER_DES ? &ssh_des :
1118              &ssh_3des;
1119     cipher->sesskey(session_key);
1120
1121     crWaitUntil(ispkt);
1122
1123     if (pktin.type != SSH1_SMSG_SUCCESS)
1124         fatalbox("Encryption not successfully enabled");
1125
1126     logevent("Successfully started encryption");
1127
1128     fflush(stdout);
1129     {
1130         static char username[100];
1131         static int pos = 0;
1132         static char c;
1133         if (!(flags & FLAG_CONNECTION) && !*cfg.username) {
1134             c_write("login as: ", 10);
1135             while (pos >= 0) {
1136                 crWaitUntil(!ispkt);
1137                 while (inlen--) switch (c = *in++) {
1138                   case 10: case 13:
1139                     username[pos] = 0;
1140                     pos = -1;
1141                     break;
1142                   case 8: case 127:
1143                     if (pos > 0) {
1144                         c_write("\b \b", 3);
1145                         pos--;
1146                     }
1147                     break;
1148                   case 21: case 27:
1149                     while (pos > 0) {
1150                         c_write("\b \b", 3);
1151                         pos--;
1152                     }
1153                     break;
1154                   case 3: case 4:
1155                     random_save_seed();
1156                     exit(0);
1157                     break;
1158                   default:
1159                     if (((c >= ' ' && c <= '~') ||
1160                          ((unsigned char)c >= 160)) && pos < 40) {
1161                         username[pos++] = c;
1162                         c_write(&c, 1);
1163                     }
1164                     break;
1165                 }
1166             }
1167             c_write("\r\n", 2);
1168             username[strcspn(username, "\n\r")] = '\0';
1169         } else {
1170             char stuff[200];
1171             strncpy(username, cfg.username, 99);
1172             username[99] = '\0';
1173             if (flags & FLAG_VERBOSE) {
1174                 sprintf(stuff, "Sent username \"%s\".\r\n", username);
1175                 c_write(stuff, strlen(stuff));
1176             }
1177         }
1178
1179         send_packet(SSH1_CMSG_USER, PKT_STR, username, PKT_END);
1180         {
1181             char userlog[20+sizeof(username)];
1182             sprintf(userlog, "Sent username \"%s\"", username);
1183             logevent(userlog);
1184         }
1185     }
1186
1187     crWaitUntil(ispkt);
1188
1189     tried_publickey = 0;
1190
1191     while (pktin.type == SSH1_SMSG_FAILURE) {
1192         static char password[100];
1193         static int pos;
1194         static char c;
1195         static int pwpkt_type;
1196         /*
1197          * Show password prompt, having first obtained it via a TIS
1198          * exchange if we're doing TIS authentication.
1199          */
1200         pwpkt_type = SSH1_CMSG_AUTH_PASSWORD;
1201         if (*cfg.keyfile && !tried_publickey)
1202             pwpkt_type = SSH1_CMSG_AUTH_RSA;
1203
1204         if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD && !FLAG_WINDOWED) {
1205             char prompt[200];
1206             sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
1207             if (!ssh_get_password(prompt, password, sizeof(password))) {
1208                 /*
1209                  * get_password failed to get a password (for
1210                  * example because one was supplied on the command
1211                  * line which has already failed to work).
1212                  * Terminate.
1213                  */
1214                 logevent("No more passwords to try");
1215                 ssh_state = SSH_STATE_CLOSED;
1216                 crReturn(1);
1217             }
1218         } else {
1219
1220             if (pktin.type == SSH1_SMSG_FAILURE &&
1221                 cfg.try_tis_auth &&
1222                 (supported_auths_mask & (1<<SSH1_AUTH_TIS))) {
1223                 pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
1224                 logevent("Requested TIS authentication");
1225                 send_packet(SSH1_CMSG_AUTH_TIS, PKT_END);
1226                 crWaitUntil(ispkt);
1227                 if (pktin.type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
1228                     logevent("TIS authentication declined");
1229                     c_write("TIS authentication refused.\r\n", 29);
1230                 } else {
1231                     int challengelen = ((pktin.body[0] << 24) |
1232                                         (pktin.body[1] << 16) |
1233                                         (pktin.body[2] << 8) |
1234                                         (pktin.body[3]));
1235                     logevent("Received TIS challenge");
1236                     c_write(pktin.body+4, challengelen);
1237                 }
1238             }
1239             if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD)
1240                 c_write("password: ", 10);
1241             if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
1242                 if (flags & FLAG_VERBOSE)
1243                     c_write("Trying public key authentication.\r\n", 35);
1244                 if (!rsakey_encrypted(cfg.keyfile)) {
1245                     if (flags & FLAG_VERBOSE)
1246                         c_write("No passphrase required.\r\n", 25);
1247                     goto tryauth;
1248                 }
1249                 c_write("passphrase: ", 12);
1250             }
1251
1252             pos = 0;
1253             while (pos >= 0) {
1254                 crWaitUntil(!ispkt);
1255                 while (inlen--) switch (c = *in++) {
1256                   case 10: case 13:
1257                     password[pos] = 0;
1258                     pos = -1;
1259                     break;
1260                   case 8: case 127:
1261                     if (pos > 0)
1262                         pos--;
1263                     break;
1264                   case 21: case 27:
1265                     pos = 0;
1266                     break;
1267                   case 3: case 4:
1268                     random_save_seed();
1269                     exit(0);
1270                     break;
1271                   default:
1272                     if (((c >= ' ' && c <= '~') ||
1273                          ((unsigned char)c >= 160)) && pos < sizeof(password))
1274                         password[pos++] = c;
1275                     break;
1276                 }
1277             }
1278             c_write("\r\n", 2);
1279
1280         }
1281
1282         tryauth:
1283         if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
1284             /*
1285              * Try public key authentication with the specified
1286              * key file.
1287              */
1288             static struct RSAKey pubkey;
1289             static Bignum challenge, response;
1290             static int i;
1291             static unsigned char buffer[32];
1292
1293             tried_publickey = 1;
1294             i = loadrsakey(cfg.keyfile, &pubkey, password);
1295             if (i == 0) {
1296                 c_write("Couldn't load public key from ", 30);
1297                 c_write(cfg.keyfile, strlen(cfg.keyfile));
1298                 c_write(".\r\n", 3);
1299                 continue;              /* go and try password */
1300             }
1301             if (i == -1) {
1302                 c_write("Wrong passphrase.\r\n", 19);
1303                 tried_publickey = 0;
1304                 continue;              /* try again */
1305             }
1306
1307             /*
1308              * Send a public key attempt.
1309              */
1310             send_packet(SSH1_CMSG_AUTH_RSA,
1311                         PKT_BIGNUM, pubkey.modulus, PKT_END);
1312
1313             crWaitUntil(ispkt);
1314             if (pktin.type == SSH1_SMSG_FAILURE) {
1315                 if (flags & FLAG_VERBOSE)
1316                     c_write("Server refused our public key.\r\n", 32);
1317                 continue;              /* go and try password */
1318             }
1319             if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE)
1320                 fatalbox("Bizarre response to offer of public key");
1321             ssh1_read_bignum(pktin.body, &challenge);
1322             response = rsadecrypt(challenge, &pubkey);
1323             freebn(pubkey.private_exponent);   /* burn the evidence */
1324
1325             for (i = 0; i < 32; i += 2) {
1326                 buffer[i] = response[16-i/2] >> 8;
1327                 buffer[i+1] = response[16-i/2] & 0xFF;
1328             }
1329
1330             MD5Init(&md5c);
1331             MD5Update(&md5c, buffer, 32);
1332             MD5Update(&md5c, session_id, 16);
1333             MD5Final(buffer, &md5c);
1334
1335             send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
1336                         PKT_DATA, buffer, 16, PKT_END);
1337
1338             crWaitUntil(ispkt);
1339             if (pktin.type == SSH1_SMSG_FAILURE) {
1340                 if (flags & FLAG_VERBOSE)
1341                     c_write("Failed to authenticate with our public key.\r\n",
1342                             45);
1343                 continue;              /* go and try password */
1344             } else if (pktin.type != SSH1_SMSG_SUCCESS) {
1345                 fatalbox("Bizarre response to RSA authentication response");
1346             }
1347
1348             break;                     /* we're through! */
1349         } else {
1350             send_packet(pwpkt_type, PKT_STR, password, PKT_END);
1351         }
1352         logevent("Sent password");
1353         memset(password, 0, strlen(password));
1354         crWaitUntil(ispkt);
1355         if (pktin.type == SSH1_SMSG_FAILURE) {
1356             if (flags & FLAG_VERBOSE)
1357                 c_write("Access denied\r\n", 15);
1358             logevent("Authentication refused");
1359         } else if (pktin.type == SSH1_MSG_DISCONNECT) {
1360             logevent("Received disconnect request");
1361             ssh_state = SSH_STATE_CLOSED;
1362             crReturn(1);
1363         } else if (pktin.type != SSH1_SMSG_SUCCESS) {
1364             fatalbox("Strange packet received, type %d", pktin.type);
1365         }
1366     }
1367
1368     logevent("Authentication successful");
1369
1370     crFinish(1);
1371 }
1372
1373 static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
1374     crBegin;
1375
1376     random_init();
1377
1378     while (!do_ssh1_login(in, inlen, ispkt)) {
1379         crReturnV;
1380     }
1381     if (ssh_state == SSH_STATE_CLOSED)
1382         crReturnV;
1383
1384     if (!cfg.nopty) {
1385         send_packet(SSH1_CMSG_REQUEST_PTY,
1386                     PKT_STR, cfg.termtype,
1387                     PKT_INT, rows, PKT_INT, cols,
1388                     PKT_INT, 0, PKT_INT, 0,
1389                     PKT_CHAR, 0,
1390                     PKT_END);
1391         ssh_state = SSH_STATE_INTERMED;
1392         do { crReturnV; } while (!ispkt);
1393         if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) {
1394             fatalbox("Protocol confusion");
1395         } else if (pktin.type == SSH1_SMSG_FAILURE) {
1396             c_write("Server refused to allocate pty\r\n", 32);
1397         }
1398         logevent("Allocated pty");
1399     }
1400
1401     send_packet(SSH1_CMSG_EXEC_SHELL, PKT_END);
1402     logevent("Started session");
1403
1404     ssh_state = SSH_STATE_SESSION;
1405     if (size_needed)
1406         ssh_size();
1407
1408     while (1) {
1409         crReturnV;
1410         if (ispkt) {
1411             if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
1412                 pktin.type == SSH1_SMSG_STDERR_DATA) {
1413                 long len = GET_32BIT(pktin.body);
1414                 c_write(pktin.body+4, len);
1415             } else if (pktin.type == SSH1_MSG_DISCONNECT) {
1416                 ssh_state = SSH_STATE_CLOSED;
1417                 logevent("Received disconnect request");
1418             } else if (pktin.type == SSH1_SMSG_SUCCESS) {
1419                 /* may be from EXEC_SHELL on some servers */
1420             } else if (pktin.type == SSH1_SMSG_FAILURE) {
1421                 /* may be from EXEC_SHELL on some servers
1422                  * if no pty is available or in other odd cases. Ignore */
1423             } else if (pktin.type == SSH1_SMSG_EXIT_STATUS) {
1424                 send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
1425             } else {
1426                 fatalbox("Strange packet received: type %d", pktin.type);
1427             }
1428         } else {
1429             send_packet(SSH1_CMSG_STDIN_DATA,
1430                         PKT_INT, inlen, PKT_DATA, in, inlen, PKT_END);
1431         }
1432     }
1433
1434     crFinishV;
1435 }
1436
1437 /*
1438  * Utility routine for decoding comma-separated strings in KEXINIT.
1439  */
1440 int in_commasep_string(char *needle, char *haystack, int haylen) {
1441     int needlen = strlen(needle);
1442     while (1) {
1443         /*
1444          * Is it at the start of the string?
1445          */
1446         if (haylen >= needlen &&       /* haystack is long enough */
1447             !memcmp(needle, haystack, needlen) &&    /* initial match */
1448             (haylen == needlen || haystack[needlen] == ',')
1449                                        /* either , or EOS follows */
1450             )
1451             return 1;
1452         /*
1453          * If not, search for the next comma and resume after that.
1454          * If no comma found, terminate.
1455          */
1456         while (haylen > 0 && *haystack != ',')
1457             haylen--, haystack++;
1458         if (haylen == 0)
1459             return 0;
1460         haylen--, haystack++;          /* skip over comma itself */
1461     }
1462 }
1463
1464 /*
1465  * SSH2 key creation method.
1466  */
1467 void ssh2_mkkey(Bignum K, char *H, char chr, char *keyspace) {
1468     SHA_State s;
1469     /* First 20 bytes. */
1470     SHA_Init(&s);
1471     sha_mpint(&s, K);
1472     SHA_Bytes(&s, H, 20);
1473     SHA_Bytes(&s, &chr, 1);
1474     SHA_Bytes(&s, H, 20);
1475     SHA_Final(&s, keyspace);
1476     /* Next 20 bytes. */
1477     SHA_Init(&s);
1478     sha_mpint(&s, K);
1479     SHA_Bytes(&s, H, 20);
1480     SHA_Bytes(&s, keyspace, 20);
1481     SHA_Final(&s, keyspace+20);
1482 }
1483
1484 /*
1485  * Handle the SSH2 transport layer.
1486  */
1487 static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
1488 {
1489     static int i, len;
1490     static char *str;
1491     static Bignum e, f, K;
1492     static struct ssh_cipher *cscipher_tobe = NULL;
1493     static struct ssh_cipher *sccipher_tobe = NULL;
1494     static struct ssh_mac *csmac_tobe = NULL;
1495     static struct ssh_mac *scmac_tobe = NULL;
1496     static struct ssh_compress *cscomp_tobe = NULL;
1497     static struct ssh_compress *sccomp_tobe = NULL;
1498     static char *hostkeydata, *sigdata, *keystr;
1499     static int hostkeylen, siglen;
1500     static unsigned char exchange_hash[20];
1501     static unsigned char keyspace[40];
1502
1503     crBegin;
1504     random_init();
1505
1506     begin_key_exchange:
1507     /*
1508      * Construct and send our key exchange packet.
1509      */
1510     ssh2_pkt_init(SSH2_MSG_KEXINIT);
1511     for (i = 0; i < 16; i++)
1512         ssh2_pkt_addbyte((unsigned char)random_byte());
1513     /* List key exchange algorithms. */
1514     ssh2_pkt_addstring_start();
1515     for (i = 0; i < lenof(kex_algs); i++) {
1516         ssh2_pkt_addstring_str(kex_algs[i]->name);
1517         if (i < lenof(kex_algs)-1)
1518             ssh2_pkt_addstring_str(",");
1519     }
1520     /* List server host key algorithms. */
1521     ssh2_pkt_addstring_start();
1522     for (i = 0; i < lenof(hostkey_algs); i++) {
1523         ssh2_pkt_addstring_str(hostkey_algs[i]->name);
1524         if (i < lenof(hostkey_algs)-1)
1525             ssh2_pkt_addstring_str(",");
1526     }
1527     /* List client->server encryption algorithms. */
1528     ssh2_pkt_addstring_start();
1529     for (i = 0; i < lenof(ciphers); i++) {
1530         ssh2_pkt_addstring_str(ciphers[i]->name);
1531         if (i < lenof(ciphers)-1)
1532             ssh2_pkt_addstring_str(",");
1533     }
1534     /* List server->client encryption algorithms. */
1535     ssh2_pkt_addstring_start();
1536     for (i = 0; i < lenof(ciphers); i++) {
1537         ssh2_pkt_addstring_str(ciphers[i]->name);
1538         if (i < lenof(ciphers)-1)
1539             ssh2_pkt_addstring_str(",");
1540     }
1541     /* List client->server MAC algorithms. */
1542     ssh2_pkt_addstring_start();
1543     for (i = 0; i < lenof(macs); i++) {
1544         ssh2_pkt_addstring_str(macs[i]->name);
1545         if (i < lenof(macs)-1)
1546             ssh2_pkt_addstring_str(",");
1547     }
1548     /* List server->client MAC algorithms. */
1549     ssh2_pkt_addstring_start();
1550     for (i = 0; i < lenof(macs); i++) {
1551         ssh2_pkt_addstring_str(macs[i]->name);
1552         if (i < lenof(macs)-1)
1553             ssh2_pkt_addstring_str(",");
1554     }
1555     /* List client->server compression algorithms. */
1556     ssh2_pkt_addstring_start();
1557     for (i = 0; i < lenof(compressions); i++) {
1558         ssh2_pkt_addstring_str(compressions[i]->name);
1559         if (i < lenof(compressions)-1)
1560             ssh2_pkt_addstring_str(",");
1561     }
1562     /* List server->client compression algorithms. */
1563     ssh2_pkt_addstring_start();
1564     for (i = 0; i < lenof(compressions); i++) {
1565         ssh2_pkt_addstring_str(compressions[i]->name);
1566         if (i < lenof(compressions)-1)
1567             ssh2_pkt_addstring_str(",");
1568     }
1569     /* List client->server languages. Empty list. */
1570     ssh2_pkt_addstring_start();
1571     /* List server->client languages. Empty list. */
1572     ssh2_pkt_addstring_start();
1573     /* First KEX packet does _not_ follow, because we're not that brave. */
1574     ssh2_pkt_addbool(FALSE);
1575     /* Reserved. */
1576     ssh2_pkt_adduint32(0);
1577     sha_string(&exhash, pktout.data+5, pktout.length-5);
1578     ssh2_pkt_send();
1579
1580     if (!ispkt) crWaitUntil(ispkt);
1581     sha_string(&exhash, pktin.data+5, pktin.length-5);
1582
1583     /*
1584      * Now examine the other side's KEXINIT to see what we're up
1585      * to.
1586      */
1587     if (pktin.type != SSH2_MSG_KEXINIT) {
1588         fatalbox("expected key exchange packet from server");
1589     }
1590     kex = NULL; hostkey = NULL; cscipher_tobe = NULL; sccipher_tobe = NULL;
1591     csmac_tobe = NULL; scmac_tobe = NULL; cscomp_tobe = NULL; sccomp_tobe = NULL;
1592     pktin.savedpos += 16;              /* skip garbage cookie */
1593     ssh2_pkt_getstring(&str, &len);    /* key exchange algorithms */
1594     for (i = 0; i < lenof(kex_algs); i++) {
1595         if (in_commasep_string(kex_algs[i]->name, str, len)) {
1596             kex = kex_algs[i];
1597             break;
1598         }
1599     }
1600     ssh2_pkt_getstring(&str, &len);    /* host key algorithms */
1601     for (i = 0; i < lenof(hostkey_algs); i++) {
1602         if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
1603             hostkey = hostkey_algs[i];
1604             break;
1605         }
1606     }
1607     ssh2_pkt_getstring(&str, &len);    /* client->server cipher */
1608     for (i = 0; i < lenof(ciphers); i++) {
1609         if (in_commasep_string(ciphers[i]->name, str, len)) {
1610             cscipher_tobe = ciphers[i];
1611             break;
1612         }
1613     }
1614     ssh2_pkt_getstring(&str, &len);    /* server->client cipher */
1615     for (i = 0; i < lenof(ciphers); i++) {
1616         if (in_commasep_string(ciphers[i]->name, str, len)) {
1617             sccipher_tobe = ciphers[i];
1618             break;
1619         }
1620     }
1621     ssh2_pkt_getstring(&str, &len);    /* client->server mac */
1622     for (i = 0; i < lenof(macs); i++) {
1623         if (in_commasep_string(macs[i]->name, str, len)) {
1624             csmac_tobe = macs[i];
1625             break;
1626         }
1627     }
1628     ssh2_pkt_getstring(&str, &len);    /* server->client mac */
1629     for (i = 0; i < lenof(macs); i++) {
1630         if (in_commasep_string(macs[i]->name, str, len)) {
1631             scmac_tobe = macs[i];
1632             break;
1633         }
1634     }
1635     ssh2_pkt_getstring(&str, &len);    /* client->server compression */
1636     for (i = 0; i < lenof(compressions); i++) {
1637         if (in_commasep_string(compressions[i]->name, str, len)) {
1638             cscomp_tobe = compressions[i];
1639             break;
1640         }
1641     }
1642     ssh2_pkt_getstring(&str, &len);    /* server->client compression */
1643     for (i = 0; i < lenof(compressions); i++) {
1644         if (in_commasep_string(compressions[i]->name, str, len)) {
1645             sccomp_tobe = compressions[i];
1646             break;
1647         }
1648     }
1649
1650     /*
1651      * Currently we only support Diffie-Hellman and DSS, so let's
1652      * bomb out if those aren't selected.
1653      */
1654     if (kex != &ssh_diffiehellman || hostkey != &ssh_dss)
1655         fatalbox("internal fault: chaos in SSH 2 transport layer");
1656
1657     /*
1658      * Now we begin the fun. Generate and send e for Diffie-Hellman.
1659      */
1660     e = dh_create_e();
1661     ssh2_pkt_init(SSH2_MSG_KEXDH_INIT);
1662     ssh2_pkt_addmp(e);
1663     ssh2_pkt_send();
1664
1665     crWaitUntil(ispkt);
1666     if (pktin.type != SSH2_MSG_KEXDH_REPLY) {
1667         fatalbox("expected key exchange packet from server");
1668     }
1669     ssh2_pkt_getstring(&hostkeydata, &hostkeylen);
1670     f = ssh2_pkt_getmp();
1671     ssh2_pkt_getstring(&sigdata, &siglen);
1672
1673     K = dh_find_K(f);
1674
1675     sha_string(&exhash, hostkeydata, hostkeylen);
1676     sha_mpint(&exhash, e);
1677     sha_mpint(&exhash, f);
1678     sha_mpint(&exhash, K);
1679     SHA_Final(&exhash, exchange_hash);
1680
1681 #if 0
1682     debug(("Exchange hash is:\r\n"));
1683     for (i = 0; i < 20; i++)
1684         debug((" %02x", exchange_hash[i]));
1685     debug(("\r\n"));
1686 #endif
1687
1688     hostkey->setkey(hostkeydata, hostkeylen);
1689     if (!hostkey->verifysig(sigdata, siglen, exchange_hash, 20))
1690         fatalbox("Server failed host key check");
1691
1692     /*
1693      * Expect SSH2_MSG_NEWKEYS from server.
1694      */
1695     crWaitUntil(ispkt);
1696     if (pktin.type != SSH2_MSG_NEWKEYS)
1697         fatalbox("expected new-keys packet from server");
1698
1699     /*
1700      * Authenticate remote host: verify host key. (We've already
1701      * checked the signature of the exchange hash.)
1702      */
1703     keystr = hostkey->fmtkey();
1704     verify_ssh_host_key(savedhost, keystr);
1705     free(keystr);
1706
1707     /*
1708      * Send SSH2_MSG_NEWKEYS.
1709      */
1710     ssh2_pkt_init(SSH2_MSG_NEWKEYS);
1711     ssh2_pkt_send();
1712
1713     /*
1714      * Create and initialise session keys.
1715      */
1716     cscipher = cscipher_tobe;
1717     sccipher = sccipher_tobe;
1718     csmac = csmac_tobe;
1719     scmac = scmac_tobe;
1720     cscomp = cscomp_tobe;
1721     sccomp = sccomp_tobe;
1722     /*
1723      * Set IVs after keys.
1724      */
1725     ssh2_mkkey(K, exchange_hash, 'C', keyspace); cscipher->setcskey(keyspace);
1726     ssh2_mkkey(K, exchange_hash, 'D', keyspace); cscipher->setsckey(keyspace);
1727     ssh2_mkkey(K, exchange_hash, 'A', keyspace); cscipher->setcsiv(keyspace);
1728     ssh2_mkkey(K, exchange_hash, 'B', keyspace); sccipher->setsciv(keyspace);
1729     ssh2_mkkey(K, exchange_hash, 'E', keyspace); csmac->setcskey(keyspace);
1730     ssh2_mkkey(K, exchange_hash, 'F', keyspace); scmac->setsckey(keyspace);
1731
1732     /*
1733      * Now we're encrypting. Begin returning 1 to the protocol main
1734      * function so that other things can run on top of the
1735      * transport. If we ever see a KEXINIT, we must go back to the
1736      * start.
1737      */
1738     do {
1739         crReturn(1);
1740     } while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT));
1741     goto begin_key_exchange;
1742
1743     crFinish(1);
1744 }
1745
1746 /*
1747  * Handle the SSH2 userauth and connection layers.
1748  */
1749 static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
1750 {
1751     static unsigned long their_channel;
1752     static unsigned long remote_winsize;
1753     static unsigned long remote_maxpkt;
1754
1755     crBegin;
1756
1757     /*
1758      * Request userauth protocol, and await a response to it.
1759      */
1760     ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
1761     ssh2_pkt_addstring("ssh-userauth");
1762     ssh2_pkt_send();
1763     crWaitUntilV(ispkt);
1764     if (pktin.type != SSH2_MSG_SERVICE_ACCEPT)
1765         fatalbox("Server refused user authentication protocol");
1766
1767     /*
1768      * FIXME: currently we support only password authentication.
1769      * (This places us technically in violation of the SSH2 spec.
1770      * We must fix this.)
1771      */
1772     while (1) {
1773         /*
1774          * Get a username and a password.
1775          */
1776         static char username[100];
1777         static char password[100];
1778         static int pos = 0;
1779         static char c;
1780
1781         if ((flags & FLAG_CONNECTION) && !*cfg.username) {
1782             c_write("login as: ", 10);
1783             while (pos >= 0) {
1784                 crWaitUntilV(!ispkt);
1785                 while (inlen--) switch (c = *in++) {
1786                   case 10: case 13:
1787                     username[pos] = 0;
1788                     pos = -1;
1789                     break;
1790                   case 8: case 127:
1791                     if (pos > 0) {
1792                         c_write("\b \b", 3);
1793                         pos--;
1794                     }
1795                     break;
1796                   case 21: case 27:
1797                     while (pos > 0) {
1798                         c_write("\b \b", 3);
1799                         pos--;
1800                     }
1801                     break;
1802                   case 3: case 4:
1803                     random_save_seed();
1804                     exit(0);
1805                     break;
1806                   default:
1807                     if (((c >= ' ' && c <= '~') ||
1808                          ((unsigned char)c >= 160)) && pos < 40) {
1809                         username[pos++] = c;
1810                         c_write(&c, 1);
1811                     }
1812                     break;
1813                 }
1814             }
1815             c_write("\r\n", 2);
1816             username[strcspn(username, "\n\r")] = '\0';
1817         } else {
1818             char stuff[200];
1819             strncpy(username, cfg.username, 99);
1820             username[99] = '\0';
1821             if (flags & FLAG_VERBOSE) {
1822                 sprintf(stuff, "Using username \"%s\".\r\n", username);
1823                 c_write(stuff, strlen(stuff));
1824             }
1825         }
1826
1827         if (!(flags & FLAG_WINDOWED)) {
1828             char prompt[200];
1829             sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
1830             if (!ssh_get_password(prompt, password, sizeof(password))) {
1831                 /*
1832                  * get_password failed to get a password (for
1833                  * example because one was supplied on the command
1834                  * line which has already failed to work).
1835                  * Terminate.
1836                  */
1837                 logevent("No more passwords to try");
1838                 ssh_state = SSH_STATE_CLOSED;
1839                 crReturnV;
1840             }
1841         } else {
1842             c_write("password: ", 10);
1843
1844             pos = 0;
1845             while (pos >= 0) {
1846                 crWaitUntilV(!ispkt);
1847                 while (inlen--) switch (c = *in++) {
1848                   case 10: case 13:
1849                     password[pos] = 0;
1850                     pos = -1;
1851                     break;
1852                   case 8: case 127:
1853                     if (pos > 0)
1854                         pos--;
1855                     break;
1856                   case 21: case 27:
1857                     pos = 0;
1858                     break;
1859                   case 3: case 4:
1860                     random_save_seed();
1861                     exit(0);
1862                     break;
1863                   default:
1864                     if (((c >= ' ' && c <= '~') ||
1865                          ((unsigned char)c >= 160)) && pos < 40)
1866                         password[pos++] = c;
1867                     break;
1868                 }
1869             }
1870             c_write("\r\n", 2);
1871         }
1872
1873         ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
1874         ssh2_pkt_addstring(username);
1875         ssh2_pkt_addstring("ssh-connection");   /* service requested */
1876         ssh2_pkt_addstring("password");
1877         ssh2_pkt_addbool(FALSE);
1878         ssh2_pkt_addstring(password);
1879         ssh2_pkt_send();
1880
1881         crWaitUntilV(ispkt);
1882         if (pktin.type != SSH2_MSG_USERAUTH_SUCCESS) {
1883             c_write("Access denied\r\n", 15);
1884             logevent("Authentication refused");
1885         } else
1886             break;
1887     }
1888
1889     /*
1890      * Now we're authenticated for the connection protocol. The
1891      * connection protocol will automatically have started at this
1892      * point; there's no need to send SERVICE_REQUEST.
1893      */
1894
1895     /*
1896      * So now create a channel with a session in it.
1897      */
1898     ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
1899     ssh2_pkt_addstring("session");
1900     ssh2_pkt_adduint32(100);           /* as good as any */
1901     ssh2_pkt_adduint32(0xFFFFFFFFUL);  /* very big window which we ignore */
1902     ssh2_pkt_adduint32(0xFFFFFFFFUL);  /* very big max pkt size */
1903     ssh2_pkt_send();
1904     crWaitUntilV(ispkt);
1905     if (pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
1906         fatalbox("Server refused to open a session");
1907         /* FIXME: error data comes back in FAILURE packet */
1908     }
1909     if (ssh2_pkt_getuint32() != 100) {
1910         fatalbox("Server's channel confirmation cited wrong channel");
1911     }
1912     their_channel = ssh2_pkt_getuint32();
1913     remote_winsize = ssh2_pkt_getuint32();
1914     remote_maxpkt = ssh2_pkt_getuint32();
1915     logevent("Opened channel for session");
1916
1917     /*
1918      * Now allocate a pty for the session.
1919      */
1920     ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
1921     ssh2_pkt_adduint32(their_channel); /* recipient channel */
1922     ssh2_pkt_addstring("pty-req");
1923     ssh2_pkt_addbool(1);               /* want reply */
1924     ssh2_pkt_addstring(cfg.termtype);
1925     ssh2_pkt_adduint32(cols);
1926     ssh2_pkt_adduint32(rows);
1927     ssh2_pkt_adduint32(0);             /* pixel width */
1928     ssh2_pkt_adduint32(0);             /* pixel height */
1929     ssh2_pkt_addstring_start();
1930     ssh2_pkt_addstring_data("\0", 1);  /* TTY_OP_END, no special options */
1931     ssh2_pkt_send();
1932
1933     do {                               /* FIXME: pay attention to these */
1934         crWaitUntilV(ispkt);
1935     } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
1936
1937     if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
1938         if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
1939             fatalbox("Server got confused by pty request");
1940         }
1941         c_write("Server refused to allocate pty\r\n", 32);
1942     } else {
1943         logevent("Allocated pty");
1944     }
1945
1946     /*
1947      * Start a shell.
1948      */
1949     ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
1950     ssh2_pkt_adduint32(their_channel); /* recipient channel */
1951     ssh2_pkt_addstring("shell");
1952     ssh2_pkt_addbool(1);               /* want reply */
1953     ssh2_pkt_send();
1954     do {                               /* FIXME: pay attention to these */
1955         crWaitUntilV(ispkt);
1956     } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
1957     if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
1958         if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
1959             fatalbox("Server got confused by shell request");
1960         }
1961         fatalbox("Server refused to start a shell");
1962     } else {
1963         logevent("Started a shell");
1964     }
1965
1966     /*
1967      * Transfer data!
1968      */
1969     while (1) {
1970         crReturnV;
1971         if (ispkt) {
1972             if (pktin.type == SSH2_MSG_CHANNEL_DATA ||
1973                 pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
1974                 char *data;
1975                 int length;
1976                 if (ssh2_pkt_getuint32() != 100)
1977                     continue;          /* wrong channel */
1978                 if (pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA &&
1979                     ssh2_pkt_getuint32() != SSH2_EXTENDED_DATA_STDERR)
1980                     continue;          /* extended but not stderr */
1981                 ssh2_pkt_getstring(&data, &length);
1982                 if (data)
1983                     c_write(data, length);
1984             } else if (pktin.type == SSH2_MSG_DISCONNECT) {
1985                 ssh_state = SSH_STATE_CLOSED;
1986                 logevent("Received disconnect request");
1987             } else if (pktin.type == SSH2_MSG_CHANNEL_REQUEST) {
1988                 continue;              /* exit status et al; ignore (FIXME?) */
1989             } else if (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
1990                 continue;              /* ignore for now (FIXME!) */
1991             } else {
1992                 fatalbox("Strange packet received: type %d", pktin.type);
1993             }
1994         } else {
1995             /* FIXME: for now, ignore window size */
1996             ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
1997             ssh2_pkt_adduint32(their_channel);
1998             ssh2_pkt_addstring_start();
1999             ssh2_pkt_addstring_data(in, inlen);
2000             ssh2_pkt_send();
2001         }
2002     }
2003
2004     crFinishV;
2005 }
2006
2007 /*
2008  * Handle the top-level SSH2 protocol.
2009  */
2010 static void ssh2_protocol(unsigned char *in, int inlen, int ispkt)
2011 {
2012     if (do_ssh2_transport(in, inlen, ispkt) == 0)
2013         return;
2014     do_ssh2_authconn(in, inlen, ispkt);
2015 }
2016
2017 /*
2018  * Called to set up the connection. Will arrange for WM_NETEVENT
2019  * messages to be passed to the specified window, whose window
2020  * procedure should then call telnet_msg().
2021  *
2022  * Returns an error message, or NULL on success.
2023  */
2024 static char *ssh_init (HWND hwnd, char *host, int port, char **realhost) {
2025     char *p;
2026         
2027 #ifdef MSCRYPTOAPI
2028     if(crypto_startup() == 0)
2029         return "Microsoft high encryption pack not installed!";
2030 #endif
2031
2032     p = connect_to_host(host, port, realhost);
2033     if (p != NULL)
2034         return p;
2035
2036     if (!do_ssh_init())
2037         return "Protocol initialisation error";
2038
2039     if (hwnd && WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ | FD_CLOSE) == SOCKET_ERROR)
2040         switch (WSAGetLastError()) {
2041           case WSAENETDOWN: return "Network is down";
2042           default: return "WSAAsyncSelect(): unknown error";
2043         }
2044
2045     return NULL;
2046 }
2047
2048 /*
2049  * Process a WM_NETEVENT message. Will return 0 if the connection
2050  * has closed, or <0 for a socket error.
2051  */
2052 static int ssh_msg (WPARAM wParam, LPARAM lParam) {
2053     int ret;
2054     char buf[256];
2055
2056     /*
2057      * Because reading less than the whole of the available pending
2058      * data can generate an FD_READ event, we need to allow for the
2059      * possibility that FD_READ may arrive with FD_CLOSE already in
2060      * the queue; so it's possible that we can get here even with s
2061      * invalid. If so, we return 1 and don't worry about it.
2062      */
2063     if (s == INVALID_SOCKET)
2064         return 1;
2065
2066     if (WSAGETSELECTERROR(lParam) != 0)
2067         return -WSAGETSELECTERROR(lParam);
2068
2069     switch (WSAGETSELECTEVENT(lParam)) {
2070       case FD_READ:
2071       case FD_CLOSE:
2072         ret = recv(s, buf, sizeof(buf), 0);
2073         if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
2074             return 1;
2075         if (ret < 0)                   /* any _other_ error */
2076             return -10000-WSAGetLastError();
2077         if (ret == 0) {
2078             s = INVALID_SOCKET;
2079             return 0;
2080         }
2081         ssh_gotdata (buf, ret);
2082         if (ssh_state == SSH_STATE_CLOSED) {
2083             closesocket(s);
2084             s = INVALID_SOCKET;
2085             return 0;
2086         }
2087         return 1;
2088     }
2089     return 1;                          /* shouldn't happen, but WTF */
2090 }
2091
2092 /*
2093  * Called to send data down the Telnet connection.
2094  */
2095 static void ssh_send (char *buf, int len) {
2096     if (s == INVALID_SOCKET)
2097         return;
2098
2099     ssh_protocol(buf, len, 0);
2100 }
2101
2102 /*
2103  * Called to set the size of the window from Telnet's POV.
2104  */
2105 static void ssh_size(void) {
2106     switch (ssh_state) {
2107       case SSH_STATE_BEFORE_SIZE:
2108       case SSH_STATE_CLOSED:
2109         break;                         /* do nothing */
2110       case SSH_STATE_INTERMED:
2111         size_needed = TRUE;            /* buffer for later */
2112         break;
2113       case SSH_STATE_SESSION:
2114         if (!cfg.nopty) {
2115             send_packet(SSH1_CMSG_WINDOW_SIZE,
2116                         PKT_INT, rows, PKT_INT, cols,
2117                         PKT_INT, 0, PKT_INT, 0, PKT_END);
2118         }
2119     }
2120 }
2121
2122 /*
2123  * (Send Telnet special codes)
2124  */
2125 static void ssh_special (Telnet_Special code) {
2126     /* do nothing */
2127 }
2128
2129
2130 /*
2131  * Read and decrypt one incoming SSH packet.
2132  * (only used by pSCP)
2133  */
2134 static void get_packet(void)
2135 {
2136     unsigned char buf[4096], *p;
2137     long to_read;
2138     int len;
2139
2140     p = NULL;
2141     len = 0;
2142
2143     while ((to_read = s_rdpkt(&p, &len)) > 0) {
2144         if (to_read > sizeof(buf)) to_read = sizeof(buf);
2145         len = s_read(buf, to_read);
2146         if (len != to_read) {
2147             closesocket(s);
2148             s = INVALID_SOCKET;
2149             return;
2150         }
2151         p = buf;
2152     }
2153
2154     assert(len == 0);
2155 }
2156
2157 /*
2158  * Receive a block of data over the SSH link. Block until
2159  * all data is available. Return nr of bytes read (0 if lost connection).
2160  * (only used by pSCP)
2161  */
2162 int ssh_scp_recv(unsigned char *buf, int len)
2163 {
2164     static int pending_input_len = 0;
2165     static unsigned char *pending_input_ptr;
2166     int to_read = len;
2167
2168     if (pending_input_len >= to_read) {
2169         memcpy(buf, pending_input_ptr, to_read);
2170         pending_input_ptr += to_read;
2171         pending_input_len -= to_read;
2172         return len;
2173     }
2174     
2175     if (pending_input_len > 0) {
2176         memcpy(buf, pending_input_ptr, pending_input_len);
2177         buf += pending_input_len;
2178         to_read -= pending_input_len;
2179         pending_input_len = 0;
2180     }
2181
2182     if (s == INVALID_SOCKET)
2183         return 0;
2184     while (to_read > 0) {
2185         get_packet();
2186         if (s == INVALID_SOCKET)
2187             return 0;
2188         if (pktin.type == SSH1_SMSG_STDOUT_DATA) {
2189             int plen = GET_32BIT(pktin.body);
2190             if (plen <= to_read) {
2191                 memcpy(buf, pktin.body + 4, plen);
2192                 buf += plen;
2193                 to_read -= plen;
2194             } else {
2195                 memcpy(buf, pktin.body + 4, to_read);
2196                 pending_input_len = plen - to_read;
2197                 pending_input_ptr = pktin.body + 4 + to_read;
2198                 to_read = 0;
2199             }
2200         } else if (pktin.type == SSH1_SMSG_STDERR_DATA) {
2201             int plen = GET_32BIT(pktin.body);
2202             fwrite(pktin.body + 4, plen, 1, stderr);
2203         } else if (pktin.type == SSH1_MSG_DISCONNECT) {
2204                 logevent("Received disconnect request");
2205         } else if (pktin.type == SSH1_SMSG_SUCCESS ||
2206                    pktin.type == SSH1_SMSG_FAILURE) {
2207                 /* ignore */
2208         } else if (pktin.type == SSH1_SMSG_EXIT_STATUS) {
2209             char logbuf[100];
2210             sprintf(logbuf, "Remote exit status: %d", GET_32BIT(pktin.body));
2211             logevent(logbuf);
2212             send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
2213             logevent("Closing connection");
2214             closesocket(s);
2215             s = INVALID_SOCKET;
2216         } else {
2217             fatalbox("Strange packet received: type %d", pktin.type);
2218         }
2219     }
2220
2221     return len;
2222 }
2223
2224 /*
2225  * Send a block of data over the SSH link.
2226  * Block until all data is sent.
2227  * (only used by pSCP)
2228  */
2229 void ssh_scp_send(unsigned char *buf, int len)
2230 {
2231     if (s == INVALID_SOCKET)
2232         return;
2233     send_packet(SSH1_CMSG_STDIN_DATA,
2234                 PKT_INT, len, PKT_DATA, buf, len, PKT_END);
2235 }
2236
2237 /*
2238  * Send an EOF notification to the server.
2239  * (only used by pSCP)
2240  */
2241 void ssh_scp_send_eof(void)
2242 {
2243     if (s == INVALID_SOCKET)
2244         return;
2245     send_packet(SSH1_CMSG_EOF, PKT_END);
2246 }
2247
2248 /*
2249  * Set up the connection, login on the remote host and
2250  * start execution of a command.
2251  * Returns an error message, or NULL on success.
2252  * (only used by pSCP)
2253  */
2254 char *ssh_scp_init(char *host, int port, char *cmd, char **realhost)
2255 {
2256     char buf[160], *p;
2257
2258 #ifdef MSCRYPTOAPI
2259     if (crypto_startup() == 0)
2260         return "Microsoft high encryption pack not installed!";
2261 #endif
2262
2263     p = connect_to_host(host, port, realhost);
2264     if (p != NULL)
2265         return p;
2266
2267     random_init();
2268
2269     if (!do_ssh_init())
2270         return "Protocol initialisation error";
2271
2272     /* Exchange keys and login */
2273     do {
2274         get_packet();
2275         if (s == INVALID_SOCKET)
2276             return "Connection closed by remote host";
2277     } while (!do_ssh1_login(NULL, 0, 1));
2278
2279     if (ssh_state == SSH_STATE_CLOSED) {
2280         closesocket(s);
2281         s = INVALID_SOCKET;
2282         return "Session initialisation error";
2283     }
2284
2285     /* Execute command */
2286     sprintf(buf, "Sending command: %.100s", cmd);
2287     logevent(buf);
2288     send_packet(SSH1_CMSG_EXEC_CMD, PKT_STR, cmd, PKT_END);
2289
2290     return NULL;
2291 }
2292
2293 SOCKET ssh_socket(void) { return s; }
2294
2295 Backend ssh_backend = {
2296     ssh_init,
2297     ssh_msg,
2298     ssh_send,
2299     ssh_size,
2300     ssh_special,
2301     ssh_socket
2302 };