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