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