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