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