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