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