OSDN Git Service

Enlarge buffers for replies on transferring files.
[ffftp/ffftp.git] / putty / SSH.C
1 /*\r
2  * SSH backend.\r
3  */\r
4 \r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 #include <stdarg.h>\r
8 #include <assert.h>\r
9 #include <limits.h>\r
10 #include <signal.h>\r
11 \r
12 #include "putty.h"\r
13 #include "tree234.h"\r
14 #include "ssh.h"\r
15 #ifndef NO_GSSAPI\r
16 #include "sshgssc.h"\r
17 #include "sshgss.h"\r
18 #endif\r
19 \r
20 #ifndef FALSE\r
21 #define FALSE 0\r
22 #endif\r
23 #ifndef TRUE\r
24 #define TRUE 1\r
25 #endif\r
26 \r
27 #define SSH1_MSG_DISCONNECT                       1     /* 0x1 */\r
28 #define SSH1_SMSG_PUBLIC_KEY                      2     /* 0x2 */\r
29 #define SSH1_CMSG_SESSION_KEY                     3     /* 0x3 */\r
30 #define SSH1_CMSG_USER                            4     /* 0x4 */\r
31 #define SSH1_CMSG_AUTH_RSA                        6     /* 0x6 */\r
32 #define SSH1_SMSG_AUTH_RSA_CHALLENGE              7     /* 0x7 */\r
33 #define SSH1_CMSG_AUTH_RSA_RESPONSE               8     /* 0x8 */\r
34 #define SSH1_CMSG_AUTH_PASSWORD                   9     /* 0x9 */\r
35 #define SSH1_CMSG_REQUEST_PTY                     10    /* 0xa */\r
36 #define SSH1_CMSG_WINDOW_SIZE                     11    /* 0xb */\r
37 #define SSH1_CMSG_EXEC_SHELL                      12    /* 0xc */\r
38 #define SSH1_CMSG_EXEC_CMD                        13    /* 0xd */\r
39 #define SSH1_SMSG_SUCCESS                         14    /* 0xe */\r
40 #define SSH1_SMSG_FAILURE                         15    /* 0xf */\r
41 #define SSH1_CMSG_STDIN_DATA                      16    /* 0x10 */\r
42 #define SSH1_SMSG_STDOUT_DATA                     17    /* 0x11 */\r
43 #define SSH1_SMSG_STDERR_DATA                     18    /* 0x12 */\r
44 #define SSH1_CMSG_EOF                             19    /* 0x13 */\r
45 #define SSH1_SMSG_EXIT_STATUS                     20    /* 0x14 */\r
46 #define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION        21    /* 0x15 */\r
47 #define SSH1_MSG_CHANNEL_OPEN_FAILURE             22    /* 0x16 */\r
48 #define SSH1_MSG_CHANNEL_DATA                     23    /* 0x17 */\r
49 #define SSH1_MSG_CHANNEL_CLOSE                    24    /* 0x18 */\r
50 #define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION       25    /* 0x19 */\r
51 #define SSH1_SMSG_X11_OPEN                        27    /* 0x1b */\r
52 #define SSH1_CMSG_PORT_FORWARD_REQUEST            28    /* 0x1c */\r
53 #define SSH1_MSG_PORT_OPEN                        29    /* 0x1d */\r
54 #define SSH1_CMSG_AGENT_REQUEST_FORWARDING        30    /* 0x1e */\r
55 #define SSH1_SMSG_AGENT_OPEN                      31    /* 0x1f */\r
56 #define SSH1_MSG_IGNORE                           32    /* 0x20 */\r
57 #define SSH1_CMSG_EXIT_CONFIRMATION               33    /* 0x21 */\r
58 #define SSH1_CMSG_X11_REQUEST_FORWARDING          34    /* 0x22 */\r
59 #define SSH1_CMSG_AUTH_RHOSTS_RSA                 35    /* 0x23 */\r
60 #define SSH1_MSG_DEBUG                            36    /* 0x24 */\r
61 #define SSH1_CMSG_REQUEST_COMPRESSION             37    /* 0x25 */\r
62 #define SSH1_CMSG_AUTH_TIS                        39    /* 0x27 */\r
63 #define SSH1_SMSG_AUTH_TIS_CHALLENGE              40    /* 0x28 */\r
64 #define SSH1_CMSG_AUTH_TIS_RESPONSE               41    /* 0x29 */\r
65 #define SSH1_CMSG_AUTH_CCARD                      70    /* 0x46 */\r
66 #define SSH1_SMSG_AUTH_CCARD_CHALLENGE            71    /* 0x47 */\r
67 #define SSH1_CMSG_AUTH_CCARD_RESPONSE             72    /* 0x48 */\r
68 \r
69 #define SSH1_AUTH_RHOSTS                          1     /* 0x1 */\r
70 #define SSH1_AUTH_RSA                             2     /* 0x2 */\r
71 #define SSH1_AUTH_PASSWORD                        3     /* 0x3 */\r
72 #define SSH1_AUTH_RHOSTS_RSA                      4     /* 0x4 */\r
73 #define SSH1_AUTH_TIS                             5     /* 0x5 */\r
74 #define SSH1_AUTH_CCARD                           16    /* 0x10 */\r
75 \r
76 #define SSH1_PROTOFLAG_SCREEN_NUMBER              1     /* 0x1 */\r
77 /* Mask for protoflags we will echo back to server if seen */\r
78 #define SSH1_PROTOFLAGS_SUPPORTED                 0     /* 0x1 */\r
79 \r
80 #define SSH2_MSG_DISCONNECT                       1     /* 0x1 */\r
81 #define SSH2_MSG_IGNORE                           2     /* 0x2 */\r
82 #define SSH2_MSG_UNIMPLEMENTED                    3     /* 0x3 */\r
83 #define SSH2_MSG_DEBUG                            4     /* 0x4 */\r
84 #define SSH2_MSG_SERVICE_REQUEST                  5     /* 0x5 */\r
85 #define SSH2_MSG_SERVICE_ACCEPT                   6     /* 0x6 */\r
86 #define SSH2_MSG_KEXINIT                          20    /* 0x14 */\r
87 #define SSH2_MSG_NEWKEYS                          21    /* 0x15 */\r
88 #define SSH2_MSG_KEXDH_INIT                       30    /* 0x1e */\r
89 #define SSH2_MSG_KEXDH_REPLY                      31    /* 0x1f */\r
90 #define SSH2_MSG_KEX_DH_GEX_REQUEST               30    /* 0x1e */\r
91 #define SSH2_MSG_KEX_DH_GEX_GROUP                 31    /* 0x1f */\r
92 #define SSH2_MSG_KEX_DH_GEX_INIT                  32    /* 0x20 */\r
93 #define SSH2_MSG_KEX_DH_GEX_REPLY                 33    /* 0x21 */\r
94 #define SSH2_MSG_KEXRSA_PUBKEY                    30    /* 0x1e */\r
95 #define SSH2_MSG_KEXRSA_SECRET                    31    /* 0x1f */\r
96 #define SSH2_MSG_KEXRSA_DONE                      32    /* 0x20 */\r
97 #define SSH2_MSG_USERAUTH_REQUEST                 50    /* 0x32 */\r
98 #define SSH2_MSG_USERAUTH_FAILURE                 51    /* 0x33 */\r
99 #define SSH2_MSG_USERAUTH_SUCCESS                 52    /* 0x34 */\r
100 #define SSH2_MSG_USERAUTH_BANNER                  53    /* 0x35 */\r
101 #define SSH2_MSG_USERAUTH_PK_OK                   60    /* 0x3c */\r
102 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ        60    /* 0x3c */\r
103 #define SSH2_MSG_USERAUTH_INFO_REQUEST            60    /* 0x3c */\r
104 #define SSH2_MSG_USERAUTH_INFO_RESPONSE           61    /* 0x3d */\r
105 #define SSH2_MSG_GLOBAL_REQUEST                   80    /* 0x50 */\r
106 #define SSH2_MSG_REQUEST_SUCCESS                  81    /* 0x51 */\r
107 #define SSH2_MSG_REQUEST_FAILURE                  82    /* 0x52 */\r
108 #define SSH2_MSG_CHANNEL_OPEN                     90    /* 0x5a */\r
109 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION        91    /* 0x5b */\r
110 #define SSH2_MSG_CHANNEL_OPEN_FAILURE             92    /* 0x5c */\r
111 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST            93    /* 0x5d */\r
112 #define SSH2_MSG_CHANNEL_DATA                     94    /* 0x5e */\r
113 #define SSH2_MSG_CHANNEL_EXTENDED_DATA            95    /* 0x5f */\r
114 #define SSH2_MSG_CHANNEL_EOF                      96    /* 0x60 */\r
115 #define SSH2_MSG_CHANNEL_CLOSE                    97    /* 0x61 */\r
116 #define SSH2_MSG_CHANNEL_REQUEST                  98    /* 0x62 */\r
117 #define SSH2_MSG_CHANNEL_SUCCESS                  99    /* 0x63 */\r
118 #define SSH2_MSG_CHANNEL_FAILURE                  100   /* 0x64 */\r
119 #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE               60\r
120 #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN                  61\r
121 #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE      63\r
122 #define SSH2_MSG_USERAUTH_GSSAPI_ERROR                  64\r
123 #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK                 65\r
124 #define SSH2_MSG_USERAUTH_GSSAPI_MIC                    66\r
125 \r
126 /*\r
127  * Packet type contexts, so that ssh2_pkt_type can correctly decode\r
128  * the ambiguous type numbers back into the correct type strings.\r
129  */\r
130 typedef enum {\r
131     SSH2_PKTCTX_NOKEX,\r
132     SSH2_PKTCTX_DHGROUP,\r
133     SSH2_PKTCTX_DHGEX,\r
134     SSH2_PKTCTX_RSAKEX\r
135 } Pkt_KCtx;\r
136 typedef enum {\r
137     SSH2_PKTCTX_NOAUTH,\r
138     SSH2_PKTCTX_PUBLICKEY,\r
139     SSH2_PKTCTX_PASSWORD,\r
140     SSH2_PKTCTX_GSSAPI,\r
141     SSH2_PKTCTX_KBDINTER\r
142 } Pkt_ACtx;\r
143 \r
144 #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1   /* 0x1 */\r
145 #define SSH2_DISCONNECT_PROTOCOL_ERROR            2     /* 0x2 */\r
146 #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED       3     /* 0x3 */\r
147 #define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4    /* 0x4 */\r
148 #define SSH2_DISCONNECT_MAC_ERROR                 5     /* 0x5 */\r
149 #define SSH2_DISCONNECT_COMPRESSION_ERROR         6     /* 0x6 */\r
150 #define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE     7     /* 0x7 */\r
151 #define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8        /* 0x8 */\r
152 #define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE   9     /* 0x9 */\r
153 #define SSH2_DISCONNECT_CONNECTION_LOST           10    /* 0xa */\r
154 #define SSH2_DISCONNECT_BY_APPLICATION            11    /* 0xb */\r
155 #define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS      12    /* 0xc */\r
156 #define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER    13    /* 0xd */\r
157 #define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14       /* 0xe */\r
158 #define SSH2_DISCONNECT_ILLEGAL_USER_NAME         15    /* 0xf */\r
159 \r
160 static const char *const ssh2_disconnect_reasons[] = {\r
161     NULL,\r
162     "host not allowed to connect",\r
163     "protocol error",\r
164     "key exchange failed",\r
165     "host authentication failed",\r
166     "MAC error",\r
167     "compression error",\r
168     "service not available",\r
169     "protocol version not supported",\r
170     "host key not verifiable",\r
171     "connection lost",\r
172     "by application",\r
173     "too many connections",\r
174     "auth cancelled by user",\r
175     "no more auth methods available",\r
176     "illegal user name",\r
177 };\r
178 \r
179 #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED     1     /* 0x1 */\r
180 #define SSH2_OPEN_CONNECT_FAILED                  2     /* 0x2 */\r
181 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE            3     /* 0x3 */\r
182 #define SSH2_OPEN_RESOURCE_SHORTAGE               4     /* 0x4 */\r
183 \r
184 #define SSH2_EXTENDED_DATA_STDERR                 1     /* 0x1 */\r
185 \r
186 /*\r
187  * Various remote-bug flags.\r
188  */\r
189 #define BUG_CHOKES_ON_SSH1_IGNORE                 1\r
190 #define BUG_SSH2_HMAC                             2\r
191 #define BUG_NEEDS_SSH1_PLAIN_PASSWORD             4\r
192 #define BUG_CHOKES_ON_RSA                         8\r
193 #define BUG_SSH2_RSA_PADDING                     16\r
194 #define BUG_SSH2_DERIVEKEY                       32\r
195 #define BUG_SSH2_REKEY                           64\r
196 #define BUG_SSH2_PK_SESSIONID                   128\r
197 #define BUG_SSH2_MAXPKT                         256\r
198 #define BUG_CHOKES_ON_SSH2_IGNORE               512\r
199 \r
200 /*\r
201  * Codes for terminal modes.\r
202  * Most of these are the same in SSH-1 and SSH-2.\r
203  * This list is derived from RFC 4254 and\r
204  * SSH-1 RFC-1.2.31.\r
205  */\r
206 static const struct {\r
207     const char* const mode;\r
208     int opcode;\r
209     enum { TTY_OP_CHAR, TTY_OP_BOOL } type;\r
210 } ssh_ttymodes[] = {\r
211     /* "V" prefix discarded for special characters relative to SSH specs */\r
212     { "INTR",         1, TTY_OP_CHAR },\r
213     { "QUIT",         2, TTY_OP_CHAR },\r
214     { "ERASE",        3, TTY_OP_CHAR },\r
215     { "KILL",         4, TTY_OP_CHAR },\r
216     { "EOF",          5, TTY_OP_CHAR },\r
217     { "EOL",          6, TTY_OP_CHAR },\r
218     { "EOL2",         7, TTY_OP_CHAR },\r
219     { "START",        8, TTY_OP_CHAR },\r
220     { "STOP",         9, TTY_OP_CHAR },\r
221     { "SUSP",        10, TTY_OP_CHAR },\r
222     { "DSUSP",       11, TTY_OP_CHAR },\r
223     { "REPRINT",     12, TTY_OP_CHAR },\r
224     { "WERASE",      13, TTY_OP_CHAR },\r
225     { "LNEXT",       14, TTY_OP_CHAR },\r
226     { "FLUSH",       15, TTY_OP_CHAR },\r
227     { "SWTCH",       16, TTY_OP_CHAR },\r
228     { "STATUS",      17, TTY_OP_CHAR },\r
229     { "DISCARD",     18, TTY_OP_CHAR },\r
230     { "IGNPAR",      30, TTY_OP_BOOL },\r
231     { "PARMRK",      31, TTY_OP_BOOL },\r
232     { "INPCK",       32, TTY_OP_BOOL },\r
233     { "ISTRIP",      33, TTY_OP_BOOL },\r
234     { "INLCR",       34, TTY_OP_BOOL },\r
235     { "IGNCR",       35, TTY_OP_BOOL },\r
236     { "ICRNL",       36, TTY_OP_BOOL },\r
237     { "IUCLC",       37, TTY_OP_BOOL },\r
238     { "IXON",        38, TTY_OP_BOOL },\r
239     { "IXANY",       39, TTY_OP_BOOL },\r
240     { "IXOFF",       40, TTY_OP_BOOL },\r
241     { "IMAXBEL",     41, TTY_OP_BOOL },\r
242     { "ISIG",        50, TTY_OP_BOOL },\r
243     { "ICANON",      51, TTY_OP_BOOL },\r
244     { "XCASE",       52, TTY_OP_BOOL },\r
245     { "ECHO",        53, TTY_OP_BOOL },\r
246     { "ECHOE",       54, TTY_OP_BOOL },\r
247     { "ECHOK",       55, TTY_OP_BOOL },\r
248     { "ECHONL",      56, TTY_OP_BOOL },\r
249     { "NOFLSH",      57, TTY_OP_BOOL },\r
250     { "TOSTOP",      58, TTY_OP_BOOL },\r
251     { "IEXTEN",      59, TTY_OP_BOOL },\r
252     { "ECHOCTL",     60, TTY_OP_BOOL },\r
253     { "ECHOKE",      61, TTY_OP_BOOL },\r
254     { "PENDIN",      62, TTY_OP_BOOL }, /* XXX is this a real mode? */\r
255     { "OPOST",       70, TTY_OP_BOOL },\r
256     { "OLCUC",       71, TTY_OP_BOOL },\r
257     { "ONLCR",       72, TTY_OP_BOOL },\r
258     { "OCRNL",       73, TTY_OP_BOOL },\r
259     { "ONOCR",       74, TTY_OP_BOOL },\r
260     { "ONLRET",      75, TTY_OP_BOOL },\r
261     { "CS7",         90, TTY_OP_BOOL },\r
262     { "CS8",         91, TTY_OP_BOOL },\r
263     { "PARENB",      92, TTY_OP_BOOL },\r
264     { "PARODD",      93, TTY_OP_BOOL }\r
265 };\r
266 \r
267 /* Miscellaneous other tty-related constants. */\r
268 #define SSH_TTY_OP_END            0\r
269 /* The opcodes for ISPEED/OSPEED differ between SSH-1 and SSH-2. */\r
270 #define SSH1_TTY_OP_ISPEED      192\r
271 #define SSH1_TTY_OP_OSPEED      193\r
272 #define SSH2_TTY_OP_ISPEED      128\r
273 #define SSH2_TTY_OP_OSPEED      129\r
274 \r
275 /* Helper functions for parsing tty-related config. */\r
276 static unsigned int ssh_tty_parse_specchar(char *s)\r
277 {\r
278     unsigned int ret;\r
279     if (*s) {\r
280         char *next = NULL;\r
281         ret = ctrlparse(s, &next);\r
282         if (!next) ret = s[0];\r
283     } else {\r
284         ret = 255; /* special value meaning "don't set" */\r
285     }\r
286     return ret;\r
287 }\r
288 static unsigned int ssh_tty_parse_boolean(char *s)\r
289 {\r
290     if (stricmp(s, "yes") == 0 ||\r
291         stricmp(s, "on") == 0 ||\r
292         stricmp(s, "true") == 0 ||\r
293         stricmp(s, "+") == 0)\r
294         return 1; /* true */\r
295     else if (stricmp(s, "no") == 0 ||\r
296              stricmp(s, "off") == 0 ||\r
297              stricmp(s, "false") == 0 ||\r
298              stricmp(s, "-") == 0)\r
299         return 0; /* false */\r
300     else\r
301         return (atoi(s) != 0);\r
302 }\r
303 \r
304 #define translate(x) if (type == x) return #x\r
305 #define translatek(x,ctx) if (type == x && (pkt_kctx == ctx)) return #x\r
306 #define translatea(x,ctx) if (type == x && (pkt_actx == ctx)) return #x\r
307 static char *ssh1_pkt_type(int type)\r
308 {\r
309     translate(SSH1_MSG_DISCONNECT);\r
310     translate(SSH1_SMSG_PUBLIC_KEY);\r
311     translate(SSH1_CMSG_SESSION_KEY);\r
312     translate(SSH1_CMSG_USER);\r
313     translate(SSH1_CMSG_AUTH_RSA);\r
314     translate(SSH1_SMSG_AUTH_RSA_CHALLENGE);\r
315     translate(SSH1_CMSG_AUTH_RSA_RESPONSE);\r
316     translate(SSH1_CMSG_AUTH_PASSWORD);\r
317     translate(SSH1_CMSG_REQUEST_PTY);\r
318     translate(SSH1_CMSG_WINDOW_SIZE);\r
319     translate(SSH1_CMSG_EXEC_SHELL);\r
320     translate(SSH1_CMSG_EXEC_CMD);\r
321     translate(SSH1_SMSG_SUCCESS);\r
322     translate(SSH1_SMSG_FAILURE);\r
323     translate(SSH1_CMSG_STDIN_DATA);\r
324     translate(SSH1_SMSG_STDOUT_DATA);\r
325     translate(SSH1_SMSG_STDERR_DATA);\r
326     translate(SSH1_CMSG_EOF);\r
327     translate(SSH1_SMSG_EXIT_STATUS);\r
328     translate(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);\r
329     translate(SSH1_MSG_CHANNEL_OPEN_FAILURE);\r
330     translate(SSH1_MSG_CHANNEL_DATA);\r
331     translate(SSH1_MSG_CHANNEL_CLOSE);\r
332     translate(SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION);\r
333     translate(SSH1_SMSG_X11_OPEN);\r
334     translate(SSH1_CMSG_PORT_FORWARD_REQUEST);\r
335     translate(SSH1_MSG_PORT_OPEN);\r
336     translate(SSH1_CMSG_AGENT_REQUEST_FORWARDING);\r
337     translate(SSH1_SMSG_AGENT_OPEN);\r
338     translate(SSH1_MSG_IGNORE);\r
339     translate(SSH1_CMSG_EXIT_CONFIRMATION);\r
340     translate(SSH1_CMSG_X11_REQUEST_FORWARDING);\r
341     translate(SSH1_CMSG_AUTH_RHOSTS_RSA);\r
342     translate(SSH1_MSG_DEBUG);\r
343     translate(SSH1_CMSG_REQUEST_COMPRESSION);\r
344     translate(SSH1_CMSG_AUTH_TIS);\r
345     translate(SSH1_SMSG_AUTH_TIS_CHALLENGE);\r
346     translate(SSH1_CMSG_AUTH_TIS_RESPONSE);\r
347     translate(SSH1_CMSG_AUTH_CCARD);\r
348     translate(SSH1_SMSG_AUTH_CCARD_CHALLENGE);\r
349     translate(SSH1_CMSG_AUTH_CCARD_RESPONSE);\r
350     return "unknown";\r
351 }\r
352 static char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)\r
353 {\r
354     translatea(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,SSH2_PKTCTX_GSSAPI);\r
355     translatea(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,SSH2_PKTCTX_GSSAPI);\r
356     translatea(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,SSH2_PKTCTX_GSSAPI);\r
357     translatea(SSH2_MSG_USERAUTH_GSSAPI_ERROR,SSH2_PKTCTX_GSSAPI);\r
358     translatea(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,SSH2_PKTCTX_GSSAPI);\r
359     translatea(SSH2_MSG_USERAUTH_GSSAPI_MIC, SSH2_PKTCTX_GSSAPI);\r
360     translate(SSH2_MSG_DISCONNECT);\r
361     translate(SSH2_MSG_IGNORE);\r
362     translate(SSH2_MSG_UNIMPLEMENTED);\r
363     translate(SSH2_MSG_DEBUG);\r
364     translate(SSH2_MSG_SERVICE_REQUEST);\r
365     translate(SSH2_MSG_SERVICE_ACCEPT);\r
366     translate(SSH2_MSG_KEXINIT);\r
367     translate(SSH2_MSG_NEWKEYS);\r
368     translatek(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);\r
369     translatek(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);\r
370     translatek(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);\r
371     translatek(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);\r
372     translatek(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);\r
373     translatek(SSH2_MSG_KEX_DH_GEX_REPLY, SSH2_PKTCTX_DHGEX);\r
374     translatek(SSH2_MSG_KEXRSA_PUBKEY, SSH2_PKTCTX_RSAKEX);\r
375     translatek(SSH2_MSG_KEXRSA_SECRET, SSH2_PKTCTX_RSAKEX);\r
376     translatek(SSH2_MSG_KEXRSA_DONE, SSH2_PKTCTX_RSAKEX);\r
377     translate(SSH2_MSG_USERAUTH_REQUEST);\r
378     translate(SSH2_MSG_USERAUTH_FAILURE);\r
379     translate(SSH2_MSG_USERAUTH_SUCCESS);\r
380     translate(SSH2_MSG_USERAUTH_BANNER);\r
381     translatea(SSH2_MSG_USERAUTH_PK_OK, SSH2_PKTCTX_PUBLICKEY);\r
382     translatea(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, SSH2_PKTCTX_PASSWORD);\r
383     translatea(SSH2_MSG_USERAUTH_INFO_REQUEST, SSH2_PKTCTX_KBDINTER);\r
384     translatea(SSH2_MSG_USERAUTH_INFO_RESPONSE, SSH2_PKTCTX_KBDINTER);\r
385     translate(SSH2_MSG_GLOBAL_REQUEST);\r
386     translate(SSH2_MSG_REQUEST_SUCCESS);\r
387     translate(SSH2_MSG_REQUEST_FAILURE);\r
388     translate(SSH2_MSG_CHANNEL_OPEN);\r
389     translate(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);\r
390     translate(SSH2_MSG_CHANNEL_OPEN_FAILURE);\r
391     translate(SSH2_MSG_CHANNEL_WINDOW_ADJUST);\r
392     translate(SSH2_MSG_CHANNEL_DATA);\r
393     translate(SSH2_MSG_CHANNEL_EXTENDED_DATA);\r
394     translate(SSH2_MSG_CHANNEL_EOF);\r
395     translate(SSH2_MSG_CHANNEL_CLOSE);\r
396     translate(SSH2_MSG_CHANNEL_REQUEST);\r
397     translate(SSH2_MSG_CHANNEL_SUCCESS);\r
398     translate(SSH2_MSG_CHANNEL_FAILURE);\r
399     return "unknown";\r
400 }\r
401 #undef translate\r
402 #undef translatec\r
403 \r
404 /* Enumeration values for fields in SSH-1 packets */\r
405 enum {\r
406     PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,\r
407     /* These values are for communicating relevant semantics of\r
408      * fields to the packet logging code. */\r
409     PKTT_OTHER, PKTT_PASSWORD, PKTT_DATA\r
410 };\r
411 \r
412 /*\r
413  * Coroutine mechanics for the sillier bits of the code. If these\r
414  * macros look impenetrable to you, you might find it helpful to\r
415  * read\r
416  * \r
417  *   http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html\r
418  * \r
419  * which explains the theory behind these macros.\r
420  * \r
421  * In particular, if you are getting `case expression not constant'\r
422  * errors when building with MS Visual Studio, this is because MS's\r
423  * Edit and Continue debugging feature causes their compiler to\r
424  * violate ANSI C. To disable Edit and Continue debugging:\r
425  * \r
426  *  - right-click ssh.c in the FileView\r
427  *  - click Settings\r
428  *  - select the C/C++ tab and the General category\r
429  *  - under `Debug info:', select anything _other_ than `Program\r
430  *    Database for Edit and Continue'.\r
431  */\r
432 #define crBegin(v)      { int *crLine = &v; switch(v) { case 0:;\r
433 #define crState(t) \\r
434     struct t *s; \\r
435     if (!ssh->t) ssh->t = snew(struct t); \\r
436     s = ssh->t;\r
437 #define crFinish(z)     } *crLine = 0; return (z); }\r
438 #define crFinishV       } *crLine = 0; return; }\r
439 #define crReturn(z)     \\r
440         do {\\r
441             *crLine =__LINE__; return (z); case __LINE__:;\\r
442         } while (0)\r
443 #define crReturnV       \\r
444         do {\\r
445             *crLine=__LINE__; return; case __LINE__:;\\r
446         } while (0)\r
447 #define crStop(z)       do{ *crLine = 0; return (z); }while(0)\r
448 #define crStopV         do{ *crLine = 0; return; }while(0)\r
449 #define crWaitUntil(c)  do { crReturn(0); } while (!(c))\r
450 #define crWaitUntilV(c) do { crReturnV; } while (!(c))\r
451 \r
452 typedef struct ssh_tag *Ssh;\r
453 struct Packet;\r
454 \r
455 static struct Packet *ssh1_pkt_init(int pkt_type);\r
456 static struct Packet *ssh2_pkt_init(int pkt_type);\r
457 static void ssh_pkt_ensure(struct Packet *, int length);\r
458 static void ssh_pkt_adddata(struct Packet *, void *data, int len);\r
459 static void ssh_pkt_addbyte(struct Packet *, unsigned char value);\r
460 static void ssh2_pkt_addbool(struct Packet *, unsigned char value);\r
461 static void ssh_pkt_adduint32(struct Packet *, unsigned long value);\r
462 static void ssh_pkt_addstring_start(struct Packet *);\r
463 static void ssh_pkt_addstring_str(struct Packet *, char *data);\r
464 static void ssh_pkt_addstring_data(struct Packet *, char *data, int len);\r
465 static void ssh_pkt_addstring(struct Packet *, char *data);\r
466 static unsigned char *ssh2_mpint_fmt(Bignum b, int *len);\r
467 static void ssh1_pkt_addmp(struct Packet *, Bignum b);\r
468 static void ssh2_pkt_addmp(struct Packet *, Bignum b);\r
469 static int ssh2_pkt_construct(Ssh, struct Packet *);\r
470 static void ssh2_pkt_send(Ssh, struct Packet *);\r
471 static void ssh2_pkt_send_noqueue(Ssh, struct Packet *);\r
472 static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,\r
473                          struct Packet *pktin);\r
474 static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,\r
475                              struct Packet *pktin);\r
476 \r
477 /*\r
478  * Buffer management constants. There are several of these for\r
479  * various different purposes:\r
480  * \r
481  *  - SSH1_BUFFER_LIMIT is the amount of backlog that must build up\r
482  *    on a local data stream before we throttle the whole SSH\r
483  *    connection (in SSH-1 only). Throttling the whole connection is\r
484  *    pretty drastic so we set this high in the hope it won't\r
485  *    happen very often.\r
486  * \r
487  *  - SSH_MAX_BACKLOG is the amount of backlog that must build up\r
488  *    on the SSH connection itself before we defensively throttle\r
489  *    _all_ local data streams. This is pretty drastic too (though\r
490  *    thankfully unlikely in SSH-2 since the window mechanism should\r
491  *    ensure that the server never has any need to throttle its end\r
492  *    of the connection), so we set this high as well.\r
493  * \r
494  *  - OUR_V2_WINSIZE is the maximum window size we present on SSH-2\r
495  *    channels.\r
496  *\r
497  *  - OUR_V2_BIGWIN is the window size we advertise for the only\r
498  *    channel in a simple connection.  It must be <= INT_MAX.\r
499  *\r
500  *  - OUR_V2_MAXPKT is the official "maximum packet size" we send\r
501  *    to the remote side. This actually has nothing to do with the\r
502  *    size of the _packet_, but is instead a limit on the amount\r
503  *    of data we're willing to receive in a single SSH2 channel\r
504  *    data message.\r
505  *\r
506  *  - OUR_V2_PACKETLIMIT is actually the maximum size of SSH\r
507  *    _packet_ we're prepared to cope with.  It must be a multiple\r
508  *    of the cipher block size, and must be at least 35000.\r
509  */\r
510 \r
511 #define SSH1_BUFFER_LIMIT 32768\r
512 #define SSH_MAX_BACKLOG 32768\r
513 #define OUR_V2_WINSIZE 16384\r
514 #define OUR_V2_BIGWIN 0x7fffffff\r
515 #define OUR_V2_MAXPKT 0x4000UL\r
516 #define OUR_V2_PACKETLIMIT 0x9000UL\r
517 \r
518 /* Maximum length of passwords/passphrases (arbitrary) */\r
519 #define SSH_MAX_PASSWORD_LEN 100\r
520 \r
521 const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss };\r
522 \r
523 const static struct ssh_mac *macs[] = {\r
524     &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5\r
525 };\r
526 const static struct ssh_mac *buggymacs[] = {\r
527     &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5\r
528 };\r
529 \r
530 static void *ssh_comp_none_init(void)\r
531 {\r
532     return NULL;\r
533 }\r
534 static void ssh_comp_none_cleanup(void *handle)\r
535 {\r
536 }\r
537 static int ssh_comp_none_block(void *handle, unsigned char *block, int len,\r
538                                unsigned char **outblock, int *outlen)\r
539 {\r
540     return 0;\r
541 }\r
542 static int ssh_comp_none_disable(void *handle)\r
543 {\r
544     return 0;\r
545 }\r
546 const static struct ssh_compress ssh_comp_none = {\r
547     "none", NULL,\r
548     ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,\r
549     ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,\r
550     ssh_comp_none_disable, NULL\r
551 };\r
552 extern const struct ssh_compress ssh_zlib;\r
553 const static struct ssh_compress *compressions[] = {\r
554     &ssh_zlib, &ssh_comp_none\r
555 };\r
556 \r
557 enum {                                 /* channel types */\r
558     CHAN_MAINSESSION,\r
559     CHAN_X11,\r
560     CHAN_AGENT,\r
561     CHAN_SOCKDATA,\r
562     CHAN_SOCKDATA_DORMANT              /* one the remote hasn't confirmed */\r
563 };\r
564 \r
565 /*\r
566  * little structure to keep track of outstanding WINDOW_ADJUSTs\r
567  */\r
568 struct winadj {\r
569     struct winadj *next;\r
570     unsigned size;\r
571 };\r
572 \r
573 /*\r
574  * 2-3-4 tree storing channels.\r
575  */\r
576 struct ssh_channel {\r
577     Ssh ssh;                           /* pointer back to main context */\r
578     unsigned remoteid, localid;\r
579     int type;\r
580     /* True if we opened this channel but server hasn't confirmed. */\r
581     int halfopen;\r
582     /*\r
583      * In SSH-1, this value contains four bits:\r
584      * \r
585      *   1   We have sent SSH1_MSG_CHANNEL_CLOSE.\r
586      *   2   We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.\r
587      *   4   We have received SSH1_MSG_CHANNEL_CLOSE.\r
588      *   8   We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.\r
589      * \r
590      * A channel is completely finished with when all four bits are set.\r
591      */\r
592     int closes;\r
593 \r
594     /*\r
595      * This flag indicates that a close is pending on the outgoing\r
596      * side of the channel: that is, wherever we're getting the data\r
597      * for this channel has sent us some data followed by EOF. We\r
598      * can't actually close the channel until we've finished sending\r
599      * the data, so we set this flag instead to remind us to\r
600      * initiate the closing process once our buffer is clear.\r
601      */\r
602     int pending_close;\r
603 \r
604     /*\r
605      * True if this channel is causing the underlying connection to be\r
606      * throttled.\r
607      */\r
608     int throttling_conn;\r
609     union {\r
610         struct ssh2_data_channel {\r
611             bufchain outbuffer;\r
612             unsigned remwindow, remmaxpkt;\r
613             /* locwindow is signed so we can cope with excess data. */\r
614             int locwindow, locmaxwin;\r
615             /*\r
616              * remlocwin is the amount of local window that we think\r
617              * the remote end had available to it after it sent the\r
618              * last data packet or window adjust ack.\r
619              */\r
620             int remlocwin;\r
621             /*\r
622              * These store the list of window adjusts that haven't\r
623              * been acked.\r
624              */\r
625             struct winadj *winadj_head, *winadj_tail;\r
626             enum { THROTTLED, UNTHROTTLING, UNTHROTTLED } throttle_state;\r
627         } v2;\r
628     } v;\r
629     union {\r
630         struct ssh_agent_channel {\r
631             unsigned char *message;\r
632             unsigned char msglen[4];\r
633             unsigned lensofar, totallen;\r
634         } a;\r
635         struct ssh_x11_channel {\r
636             Socket s;\r
637         } x11;\r
638         struct ssh_pfd_channel {\r
639             Socket s;\r
640         } pfd;\r
641     } u;\r
642 };\r
643 \r
644 /*\r
645  * 2-3-4 tree storing remote->local port forwardings. SSH-1 and SSH-2\r
646  * use this structure in different ways, reflecting SSH-2's\r
647  * altogether saner approach to port forwarding.\r
648  * \r
649  * In SSH-1, you arrange a remote forwarding by sending the server\r
650  * the remote port number, and the local destination host:port.\r
651  * When a connection comes in, the server sends you back that\r
652  * host:port pair, and you connect to it. This is a ready-made\r
653  * security hole if you're not on the ball: a malicious server\r
654  * could send you back _any_ host:port pair, so if you trustingly\r
655  * connect to the address it gives you then you've just opened the\r
656  * entire inside of your corporate network just by connecting\r
657  * through it to a dodgy SSH server. Hence, we must store a list of\r
658  * host:port pairs we _are_ trying to forward to, and reject a\r
659  * connection request from the server if it's not in the list.\r
660  * \r
661  * In SSH-2, each side of the connection minds its own business and\r
662  * doesn't send unnecessary information to the other. You arrange a\r
663  * remote forwarding by sending the server just the remote port\r
664  * number. When a connection comes in, the server tells you which\r
665  * of its ports was connected to; and _you_ have to remember what\r
666  * local host:port pair went with that port number.\r
667  * \r
668  * Hence, in SSH-1 this structure is indexed by destination\r
669  * host:port pair, whereas in SSH-2 it is indexed by source port.\r
670  */\r
671 struct ssh_portfwd; /* forward declaration */\r
672 \r
673 struct ssh_rportfwd {\r
674     unsigned sport, dport;\r
675     char dhost[256];\r
676     char *sportdesc;\r
677     struct ssh_portfwd *pfrec;\r
678 };\r
679 #define free_rportfwd(pf) ( \\r
680     ((pf) ? (sfree((pf)->sportdesc)) : (void)0 ), sfree(pf) )\r
681 \r
682 /*\r
683  * Separately to the rportfwd tree (which is for looking up port\r
684  * open requests from the server), a tree of _these_ structures is\r
685  * used to keep track of all the currently open port forwardings,\r
686  * so that we can reconfigure in mid-session if the user requests\r
687  * it.\r
688  */\r
689 struct ssh_portfwd {\r
690     enum { DESTROY, KEEP, CREATE } status;\r
691     int type;\r
692     unsigned sport, dport;\r
693     char *saddr, *daddr;\r
694     char *sserv, *dserv;\r
695     struct ssh_rportfwd *remote;\r
696     int addressfamily;\r
697     void *local;\r
698 };\r
699 #define free_portfwd(pf) ( \\r
700     ((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr), \\r
701              sfree((pf)->sserv), sfree((pf)->dserv)) : (void)0 ), sfree(pf) )\r
702 \r
703 struct Packet {\r
704     long length;            /* length of `data' actually used */\r
705     long forcepad;          /* SSH-2: force padding to at least this length */\r
706     int type;               /* only used for incoming packets */\r
707     unsigned long sequence; /* SSH-2 incoming sequence number */\r
708     unsigned char *data;    /* allocated storage */\r
709     unsigned char *body;    /* offset of payload within `data' */\r
710     long savedpos;          /* temporary index into `data' (for strings) */\r
711     long maxlen;            /* amount of storage allocated for `data' */\r
712     long encrypted_len;     /* for SSH-2 total-size counting */\r
713 \r
714     /*\r
715      * State associated with packet logging\r
716      */\r
717     int logmode;\r
718     int nblanks;\r
719     struct logblank_t *blanks;\r
720 };\r
721 \r
722 static void ssh1_protocol(Ssh ssh, void *vin, int inlen,\r
723                           struct Packet *pktin);\r
724 static void ssh2_protocol(Ssh ssh, void *vin, int inlen,\r
725                           struct Packet *pktin);\r
726 static void ssh1_protocol_setup(Ssh ssh);\r
727 static void ssh2_protocol_setup(Ssh ssh);\r
728 static void ssh_size(void *handle, int width, int height);\r
729 static void ssh_special(void *handle, Telnet_Special);\r
730 static int ssh2_try_send(struct ssh_channel *c);\r
731 static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);\r
732 static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);\r
733 static void ssh2_set_window(struct ssh_channel *c, int newwin);\r
734 static int ssh_sendbuffer(void *handle);\r
735 static int ssh_do_close(Ssh ssh, int notify_exit);\r
736 static unsigned long ssh_pkt_getuint32(struct Packet *pkt);\r
737 static int ssh2_pkt_getbool(struct Packet *pkt);\r
738 static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);\r
739 static void ssh2_timer(void *ctx, long now);\r
740 static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,\r
741                              struct Packet *pktin);\r
742 \r
743 struct rdpkt1_state_tag {\r
744     long len, pad, biglen, to_read;\r
745     unsigned long realcrc, gotcrc;\r
746     unsigned char *p;\r
747     int i;\r
748     int chunk;\r
749     struct Packet *pktin;\r
750 };\r
751 \r
752 struct rdpkt2_state_tag {\r
753     long len, pad, payload, packetlen, maclen;\r
754     int i;\r
755     int cipherblk;\r
756     unsigned long incoming_sequence;\r
757     struct Packet *pktin;\r
758 };\r
759 \r
760 typedef void (*handler_fn_t)(Ssh ssh, struct Packet *pktin);\r
761 typedef void (*chandler_fn_t)(Ssh ssh, struct Packet *pktin, void *ctx);\r
762 \r
763 struct queued_handler;\r
764 struct queued_handler {\r
765     int msg1, msg2;\r
766     chandler_fn_t handler;\r
767     void *ctx;\r
768     struct queued_handler *next;\r
769 };\r
770 \r
771 struct ssh_tag {\r
772     const struct plug_function_table *fn;\r
773     /* the above field _must_ be first in the structure */\r
774 \r
775     char *v_c, *v_s;\r
776     void *exhash;\r
777 \r
778     Socket s;\r
779 \r
780     void *ldisc;\r
781     void *logctx;\r
782 \r
783     unsigned char session_key[32];\r
784     int v1_compressing;\r
785     int v1_remote_protoflags;\r
786     int v1_local_protoflags;\r
787     int agentfwd_enabled;\r
788     int X11_fwd_enabled;\r
789     int remote_bugs;\r
790     const struct ssh_cipher *cipher;\r
791     void *v1_cipher_ctx;\r
792     void *crcda_ctx;\r
793     const struct ssh2_cipher *cscipher, *sccipher;\r
794     void *cs_cipher_ctx, *sc_cipher_ctx;\r
795     const struct ssh_mac *csmac, *scmac;\r
796     void *cs_mac_ctx, *sc_mac_ctx;\r
797     const struct ssh_compress *cscomp, *sccomp;\r
798     void *cs_comp_ctx, *sc_comp_ctx;\r
799     const struct ssh_kex *kex;\r
800     const struct ssh_signkey *hostkey;\r
801     unsigned char v2_session_id[SSH2_KEX_MAX_HASH_LEN];\r
802     int v2_session_id_len;\r
803     void *kex_ctx;\r
804 \r
805     char *savedhost;\r
806     int savedport;\r
807     int send_ok;\r
808     int echoing, editing;\r
809 \r
810     void *frontend;\r
811 \r
812     int ospeed, ispeed;                /* temporaries */\r
813     int term_width, term_height;\r
814 \r
815     tree234 *channels;                 /* indexed by local id */\r
816     struct ssh_channel *mainchan;      /* primary session channel */\r
817     int ncmode;                        /* is primary channel direct-tcpip? */\r
818     int exitcode;\r
819     int close_expected;\r
820     int clean_exit;\r
821 \r
822     tree234 *rportfwds, *portfwds;\r
823 \r
824     enum {\r
825         SSH_STATE_PREPACKET,\r
826         SSH_STATE_BEFORE_SIZE,\r
827         SSH_STATE_INTERMED,\r
828         SSH_STATE_SESSION,\r
829         SSH_STATE_CLOSED\r
830     } state;\r
831 \r
832     int size_needed, eof_needed;\r
833 \r
834     struct Packet **queue;\r
835     int queuelen, queuesize;\r
836     int queueing;\r
837     unsigned char *deferred_send_data;\r
838     int deferred_len, deferred_size;\r
839 \r
840     /*\r
841      * Gross hack: pscp will try to start SFTP but fall back to\r
842      * scp1 if that fails. This variable is the means by which\r
843      * scp.c can reach into the SSH code and find out which one it\r
844      * got.\r
845      */\r
846     int fallback_cmd;\r
847 \r
848     bufchain banner;    /* accumulates banners during do_ssh2_authconn */\r
849 \r
850     Pkt_KCtx pkt_kctx;\r
851     Pkt_ACtx pkt_actx;\r
852 \r
853     struct X11Display *x11disp;\r
854 \r
855     int version;\r
856     int conn_throttle_count;\r
857     int overall_bufsize;\r
858     int throttled_all;\r
859     int v1_stdout_throttling;\r
860     unsigned long v2_outgoing_sequence;\r
861 \r
862     int ssh1_rdpkt_crstate;\r
863     int ssh2_rdpkt_crstate;\r
864     int do_ssh_init_crstate;\r
865     int ssh_gotdata_crstate;\r
866     int do_ssh1_login_crstate;\r
867     int do_ssh1_connection_crstate;\r
868     int do_ssh2_transport_crstate;\r
869     int do_ssh2_authconn_crstate;\r
870 \r
871     void *do_ssh_init_state;\r
872     void *do_ssh1_login_state;\r
873     void *do_ssh2_transport_state;\r
874     void *do_ssh2_authconn_state;\r
875 \r
876     struct rdpkt1_state_tag rdpkt1_state;\r
877     struct rdpkt2_state_tag rdpkt2_state;\r
878 \r
879     /* SSH-1 and SSH-2 use this for different things, but both use it */\r
880     int protocol_initial_phase_done;\r
881 \r
882     void (*protocol) (Ssh ssh, void *vin, int inlen,\r
883                       struct Packet *pkt);\r
884     struct Packet *(*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);\r
885 \r
886     /*\r
887      * We maintain a full _copy_ of a Config structure here, not\r
888      * merely a pointer to it. That way, when we're passed a new\r
889      * one for reconfiguration, we can check the differences and\r
890      * potentially reconfigure port forwardings etc in mid-session.\r
891      */\r
892     Config cfg;\r
893 \r
894     /*\r
895      * Used to transfer data back from async callbacks.\r
896      */\r
897     void *agent_response;\r
898     int agent_response_len;\r
899     int user_response;\r
900 \r
901     /*\r
902      * The SSH connection can be set as `frozen', meaning we are\r
903      * not currently accepting incoming data from the network. This\r
904      * is slightly more serious than setting the _socket_ as\r
905      * frozen, because we may already have had data passed to us\r
906      * from the network which we need to delay processing until\r
907      * after the freeze is lifted, so we also need a bufchain to\r
908      * store that data.\r
909      */\r
910     int frozen;\r
911     bufchain queued_incoming_data;\r
912 \r
913     /*\r
914      * Dispatch table for packet types that we may have to deal\r
915      * with at any time.\r
916      */\r
917     handler_fn_t packet_dispatch[256];\r
918 \r
919     /*\r
920      * Queues of one-off handler functions for success/failure\r
921      * indications from a request.\r
922      */\r
923     struct queued_handler *qhead, *qtail;\r
924 \r
925     /*\r
926      * This module deals with sending keepalives.\r
927      */\r
928     Pinger pinger;\r
929 \r
930     /*\r
931      * Track incoming and outgoing data sizes and time, for\r
932      * size-based rekeys.\r
933      */\r
934     unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;\r
935     unsigned long max_data_size;\r
936     int kex_in_progress;\r
937     long next_rekey, last_rekey;\r
938     char *deferred_rekey_reason;    /* points to STATIC string; don't free */\r
939 \r
940     /*\r
941      * Fully qualified host name, which we need if doing GSSAPI.\r
942      */\r
943     char *fullhostname;\r
944 \r
945 #ifndef NO_GSSAPI\r
946     /*\r
947      * GSSAPI libraries for this session.\r
948      */\r
949     struct ssh_gss_liblist *gsslibs;\r
950 #endif\r
951 };\r
952 \r
953 #define logevent(s) logevent(ssh->frontend, s)\r
954 \r
955 /* logevent, only printf-formatted. */\r
956 static void logeventf(Ssh ssh, const char *fmt, ...)\r
957 {\r
958     va_list ap;\r
959     char *buf;\r
960 \r
961     va_start(ap, fmt);\r
962     buf = dupvprintf(fmt, ap);\r
963     va_end(ap);\r
964     logevent(buf);\r
965     sfree(buf);\r
966 }\r
967 \r
968 #define bombout(msg) \\r
969     do { \\r
970         char *text = dupprintf msg; \\r
971         ssh_do_close(ssh, FALSE); \\r
972         logevent(text); \\r
973         connection_fatal(ssh->frontend, "%s", text); \\r
974         sfree(text); \\r
975     } while (0)\r
976 \r
977 /* Functions to leave bits out of the SSH packet log file. */\r
978 \r
979 static void dont_log_password(Ssh ssh, struct Packet *pkt, int blanktype)\r
980 {\r
981     if (ssh->cfg.logomitpass)\r
982         pkt->logmode = blanktype;\r
983 }\r
984 \r
985 static void dont_log_data(Ssh ssh, struct Packet *pkt, int blanktype)\r
986 {\r
987     if (ssh->cfg.logomitdata)\r
988         pkt->logmode = blanktype;\r
989 }\r
990 \r
991 static void end_log_omission(Ssh ssh, struct Packet *pkt)\r
992 {\r
993     pkt->logmode = PKTLOG_EMIT;\r
994 }\r
995 \r
996 /* Helper function for common bits of parsing cfg.ttymodes. */\r
997 static void parse_ttymodes(Ssh ssh, char *modes,\r
998                            void (*do_mode)(void *data, char *mode, char *val),\r
999                            void *data)\r
1000 {\r
1001     while (*modes) {\r
1002         char *t = strchr(modes, '\t');\r
1003         char *m = snewn(t-modes+1, char);\r
1004         char *val;\r
1005         strncpy(m, modes, t-modes);\r
1006         m[t-modes] = '\0';\r
1007         if (*(t+1) == 'A')\r
1008             val = get_ttymode(ssh->frontend, m);\r
1009         else\r
1010             val = dupstr(t+2);\r
1011         if (val)\r
1012             do_mode(data, m, val);\r
1013         sfree(m);\r
1014         sfree(val);\r
1015         modes += strlen(modes) + 1;\r
1016     }\r
1017 }\r
1018 \r
1019 static int ssh_channelcmp(void *av, void *bv)\r
1020 {\r
1021     struct ssh_channel *a = (struct ssh_channel *) av;\r
1022     struct ssh_channel *b = (struct ssh_channel *) bv;\r
1023     if (a->localid < b->localid)\r
1024         return -1;\r
1025     if (a->localid > b->localid)\r
1026         return +1;\r
1027     return 0;\r
1028 }\r
1029 static int ssh_channelfind(void *av, void *bv)\r
1030 {\r
1031     unsigned *a = (unsigned *) av;\r
1032     struct ssh_channel *b = (struct ssh_channel *) bv;\r
1033     if (*a < b->localid)\r
1034         return -1;\r
1035     if (*a > b->localid)\r
1036         return +1;\r
1037     return 0;\r
1038 }\r
1039 \r
1040 static int ssh_rportcmp_ssh1(void *av, void *bv)\r
1041 {\r
1042     struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;\r
1043     struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;\r
1044     int i;\r
1045     if ( (i = strcmp(a->dhost, b->dhost)) != 0)\r
1046         return i < 0 ? -1 : +1;\r
1047     if (a->dport > b->dport)\r
1048         return +1;\r
1049     if (a->dport < b->dport)\r
1050         return -1;\r
1051     return 0;\r
1052 }\r
1053 \r
1054 static int ssh_rportcmp_ssh2(void *av, void *bv)\r
1055 {\r
1056     struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;\r
1057     struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;\r
1058 \r
1059     if (a->sport > b->sport)\r
1060         return +1;\r
1061     if (a->sport < b->sport)\r
1062         return -1;\r
1063     return 0;\r
1064 }\r
1065 \r
1066 /*\r
1067  * Special form of strcmp which can cope with NULL inputs. NULL is\r
1068  * defined to sort before even the empty string.\r
1069  */\r
1070 static int nullstrcmp(const char *a, const char *b)\r
1071 {\r
1072     if (a == NULL && b == NULL)\r
1073         return 0;\r
1074     if (a == NULL)\r
1075         return -1;\r
1076     if (b == NULL)\r
1077         return +1;\r
1078     return strcmp(a, b);\r
1079 }\r
1080 \r
1081 static int ssh_portcmp(void *av, void *bv)\r
1082 {\r
1083     struct ssh_portfwd *a = (struct ssh_portfwd *) av;\r
1084     struct ssh_portfwd *b = (struct ssh_portfwd *) bv;\r
1085     int i;\r
1086     if (a->type > b->type)\r
1087         return +1;\r
1088     if (a->type < b->type)\r
1089         return -1;\r
1090     if (a->addressfamily > b->addressfamily)\r
1091         return +1;\r
1092     if (a->addressfamily < b->addressfamily)\r
1093         return -1;\r
1094     if ( (i = nullstrcmp(a->saddr, b->saddr)) != 0)\r
1095         return i < 0 ? -1 : +1;\r
1096     if (a->sport > b->sport)\r
1097         return +1;\r
1098     if (a->sport < b->sport)\r
1099         return -1;\r
1100     if (a->type != 'D') {\r
1101         if ( (i = nullstrcmp(a->daddr, b->daddr)) != 0)\r
1102             return i < 0 ? -1 : +1;\r
1103         if (a->dport > b->dport)\r
1104             return +1;\r
1105         if (a->dport < b->dport)\r
1106             return -1;\r
1107     }\r
1108     return 0;\r
1109 }\r
1110 \r
1111 static int alloc_channel_id(Ssh ssh)\r
1112 {\r
1113     const unsigned CHANNEL_NUMBER_OFFSET = 256;\r
1114     unsigned low, high, mid;\r
1115     int tsize;\r
1116     struct ssh_channel *c;\r
1117 \r
1118     /*\r
1119      * First-fit allocation of channel numbers: always pick the\r
1120      * lowest unused one. To do this, binary-search using the\r
1121      * counted B-tree to find the largest channel ID which is in a\r
1122      * contiguous sequence from the beginning. (Precisely\r
1123      * everything in that sequence must have ID equal to its tree\r
1124      * index plus CHANNEL_NUMBER_OFFSET.)\r
1125      */\r
1126     tsize = count234(ssh->channels);\r
1127 \r
1128     low = -1;\r
1129     high = tsize;\r
1130     while (high - low > 1) {\r
1131         mid = (high + low) / 2;\r
1132         c = index234(ssh->channels, mid);\r
1133         if (c->localid == mid + CHANNEL_NUMBER_OFFSET)\r
1134             low = mid;                 /* this one is fine */\r
1135         else\r
1136             high = mid;                /* this one is past it */\r
1137     }\r
1138     /*\r
1139      * Now low points to either -1, or the tree index of the\r
1140      * largest ID in the initial sequence.\r
1141      */\r
1142     {\r
1143         unsigned i = low + 1 + CHANNEL_NUMBER_OFFSET;\r
1144         assert(NULL == find234(ssh->channels, &i, ssh_channelfind));\r
1145     }\r
1146     return low + 1 + CHANNEL_NUMBER_OFFSET;\r
1147 }\r
1148 \r
1149 static void c_write_stderr(int trusted, const char *buf, int len)\r
1150 {\r
1151     int i;\r
1152     for (i = 0; i < len; i++)\r
1153         if (buf[i] != '\r' && (trusted || buf[i] == '\n' || (buf[i] & 0x60)))\r
1154             fputc(buf[i], stderr);\r
1155 }\r
1156 \r
1157 static void c_write(Ssh ssh, const char *buf, int len)\r
1158 {\r
1159     if (flags & FLAG_STDERR)\r
1160         c_write_stderr(1, buf, len);\r
1161     else\r
1162         from_backend(ssh->frontend, 1, buf, len);\r
1163 }\r
1164 \r
1165 static void c_write_untrusted(Ssh ssh, const char *buf, int len)\r
1166 {\r
1167     if (flags & FLAG_STDERR)\r
1168         c_write_stderr(0, buf, len);\r
1169     else\r
1170         from_backend_untrusted(ssh->frontend, buf, len);\r
1171 }\r
1172 \r
1173 static void c_write_str(Ssh ssh, const char *buf)\r
1174 {\r
1175     c_write(ssh, buf, strlen(buf));\r
1176 }\r
1177 \r
1178 static void ssh_free_packet(struct Packet *pkt)\r
1179 {\r
1180     sfree(pkt->data);\r
1181     sfree(pkt);\r
1182 }\r
1183 static struct Packet *ssh_new_packet(void)\r
1184 {\r
1185     struct Packet *pkt = snew(struct Packet);\r
1186 \r
1187     pkt->body = pkt->data = NULL;\r
1188     pkt->maxlen = 0;\r
1189     pkt->logmode = PKTLOG_EMIT;\r
1190     pkt->nblanks = 0;\r
1191     pkt->blanks = NULL;\r
1192 \r
1193     return pkt;\r
1194 }\r
1195 \r
1196 /*\r
1197  * Collect incoming data in the incoming packet buffer.\r
1198  * Decipher and verify the packet when it is completely read.\r
1199  * Drop SSH1_MSG_DEBUG and SSH1_MSG_IGNORE packets.\r
1200  * Update the *data and *datalen variables.\r
1201  * Return a Packet structure when a packet is completed.\r
1202  */\r
1203 static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)\r
1204 {\r
1205     struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;\r
1206 \r
1207     crBegin(ssh->ssh1_rdpkt_crstate);\r
1208 \r
1209     st->pktin = ssh_new_packet();\r
1210 \r
1211     st->pktin->type = 0;\r
1212     st->pktin->length = 0;\r
1213 \r
1214     for (st->i = st->len = 0; st->i < 4; st->i++) {\r
1215         while ((*datalen) == 0)\r
1216             crReturn(NULL);\r
1217         st->len = (st->len << 8) + **data;\r
1218         (*data)++, (*datalen)--;\r
1219     }\r
1220 \r
1221     st->pad = 8 - (st->len % 8);\r
1222     st->biglen = st->len + st->pad;\r
1223     st->pktin->length = st->len - 5;\r
1224 \r
1225     if (st->biglen < 0) {\r
1226         bombout(("Extremely large packet length from server suggests"\r
1227                  " data stream corruption"));\r
1228         ssh_free_packet(st->pktin);\r
1229         crStop(NULL);\r
1230     }\r
1231 \r
1232     st->pktin->maxlen = st->biglen;\r
1233     st->pktin->data = snewn(st->biglen + APIEXTRA, unsigned char);\r
1234 \r
1235     st->to_read = st->biglen;\r
1236     st->p = st->pktin->data;\r
1237     while (st->to_read > 0) {\r
1238         st->chunk = st->to_read;\r
1239         while ((*datalen) == 0)\r
1240             crReturn(NULL);\r
1241         if (st->chunk > (*datalen))\r
1242             st->chunk = (*datalen);\r
1243         memcpy(st->p, *data, st->chunk);\r
1244         *data += st->chunk;\r
1245         *datalen -= st->chunk;\r
1246         st->p += st->chunk;\r
1247         st->to_read -= st->chunk;\r
1248     }\r
1249 \r
1250     if (ssh->cipher && detect_attack(ssh->crcda_ctx, st->pktin->data,\r
1251                                      st->biglen, NULL)) {\r
1252         bombout(("Network attack (CRC compensation) detected!"));\r
1253         ssh_free_packet(st->pktin);\r
1254         crStop(NULL);\r
1255     }\r
1256 \r
1257     if (ssh->cipher)\r
1258         ssh->cipher->decrypt(ssh->v1_cipher_ctx, st->pktin->data, st->biglen);\r
1259 \r
1260     st->realcrc = crc32_compute(st->pktin->data, st->biglen - 4);\r
1261     st->gotcrc = GET_32BIT(st->pktin->data + st->biglen - 4);\r
1262     if (st->gotcrc != st->realcrc) {\r
1263         bombout(("Incorrect CRC received on packet"));\r
1264         ssh_free_packet(st->pktin);\r
1265         crStop(NULL);\r
1266     }\r
1267 \r
1268     st->pktin->body = st->pktin->data + st->pad + 1;\r
1269     st->pktin->savedpos = 0;\r
1270 \r
1271     if (ssh->v1_compressing) {\r
1272         unsigned char *decompblk;\r
1273         int decomplen;\r
1274         if (!zlib_decompress_block(ssh->sc_comp_ctx,\r
1275                                    st->pktin->body - 1, st->pktin->length + 1,\r
1276                                    &decompblk, &decomplen)) {\r
1277             bombout(("Zlib decompression encountered invalid data"));\r
1278             ssh_free_packet(st->pktin);\r
1279             crStop(NULL);\r
1280         }\r
1281 \r
1282         if (st->pktin->maxlen < st->pad + decomplen) {\r
1283             st->pktin->maxlen = st->pad + decomplen;\r
1284             st->pktin->data = sresize(st->pktin->data,\r
1285                                       st->pktin->maxlen + APIEXTRA,\r
1286                                       unsigned char);\r
1287             st->pktin->body = st->pktin->data + st->pad + 1;\r
1288         }\r
1289 \r
1290         memcpy(st->pktin->body - 1, decompblk, decomplen);\r
1291         sfree(decompblk);\r
1292         st->pktin->length = decomplen - 1;\r
1293     }\r
1294 \r
1295     st->pktin->type = st->pktin->body[-1];\r
1296 \r
1297     /*\r
1298      * Log incoming packet, possibly omitting sensitive fields.\r
1299      */\r
1300     if (ssh->logctx) {\r
1301         int nblanks = 0;\r
1302         struct logblank_t blank;\r
1303         if (ssh->cfg.logomitdata) {\r
1304             int do_blank = FALSE, blank_prefix = 0;\r
1305             /* "Session data" packets - omit the data field */\r
1306             if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||\r
1307                 (st->pktin->type == SSH1_SMSG_STDERR_DATA)) {\r
1308                 do_blank = TRUE; blank_prefix = 4;\r
1309             } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {\r
1310                 do_blank = TRUE; blank_prefix = 8;\r
1311             }\r
1312             if (do_blank) {\r
1313                 blank.offset = blank_prefix;\r
1314                 blank.len = st->pktin->length;\r
1315                 blank.type = PKTLOG_OMIT;\r
1316                 nblanks = 1;\r
1317             }\r
1318         }\r
1319         log_packet(ssh->logctx,\r
1320                    PKT_INCOMING, st->pktin->type,\r
1321                    ssh1_pkt_type(st->pktin->type),\r
1322                    st->pktin->body, st->pktin->length,\r
1323                    nblanks, &blank, NULL);\r
1324     }\r
1325 \r
1326     crFinish(st->pktin);\r
1327 }\r
1328 \r
1329 static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)\r
1330 {\r
1331     struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;\r
1332 \r
1333     crBegin(ssh->ssh2_rdpkt_crstate);\r
1334 \r
1335     st->pktin = ssh_new_packet();\r
1336 \r
1337     st->pktin->type = 0;\r
1338     st->pktin->length = 0;\r
1339     if (ssh->sccipher)\r
1340         st->cipherblk = ssh->sccipher->blksize;\r
1341     else\r
1342         st->cipherblk = 8;\r
1343     if (st->cipherblk < 8)\r
1344         st->cipherblk = 8;\r
1345     st->maclen = ssh->scmac ? ssh->scmac->len : 0;\r
1346 \r
1347     if (ssh->sccipher && (ssh->sccipher->flags & SSH_CIPHER_IS_CBC) &&\r
1348         ssh->scmac) {\r
1349         /*\r
1350          * When dealing with a CBC-mode cipher, we want to avoid the\r
1351          * possibility of an attacker's tweaking the ciphertext stream\r
1352          * so as to cause us to feed the same block to the block\r
1353          * cipher more than once and thus leak information\r
1354          * (VU#958563).  The way we do this is not to take any\r
1355          * decisions on the basis of anything we've decrypted until\r
1356          * we've verified it with a MAC.  That includes the packet\r
1357          * length, so we just read data and check the MAC repeatedly,\r
1358          * and when the MAC passes, see if the length we've got is\r
1359          * plausible.\r
1360          */\r
1361 \r
1362         /* May as well allocate the whole lot now. */\r
1363         st->pktin->data = snewn(OUR_V2_PACKETLIMIT + st->maclen + APIEXTRA,\r
1364                                 unsigned char);\r
1365 \r
1366         /* Read an amount corresponding to the MAC. */\r
1367         for (st->i = 0; st->i < st->maclen; st->i++) {\r
1368             while ((*datalen) == 0)\r
1369                 crReturn(NULL);\r
1370             st->pktin->data[st->i] = *(*data)++;\r
1371             (*datalen)--;\r
1372         }\r
1373 \r
1374         st->packetlen = 0;\r
1375         {\r
1376             unsigned char seq[4];\r
1377             ssh->scmac->start(ssh->sc_mac_ctx);\r
1378             PUT_32BIT(seq, st->incoming_sequence);\r
1379             ssh->scmac->bytes(ssh->sc_mac_ctx, seq, 4);\r
1380         }\r
1381 \r
1382         for (;;) { /* Once around this loop per cipher block. */\r
1383             /* Read another cipher-block's worth, and tack it onto the end. */\r
1384             for (st->i = 0; st->i < st->cipherblk; st->i++) {\r
1385                 while ((*datalen) == 0)\r
1386                     crReturn(NULL);\r
1387                 st->pktin->data[st->packetlen+st->maclen+st->i] = *(*data)++;\r
1388                 (*datalen)--;\r
1389             }\r
1390             /* Decrypt one more block (a little further back in the stream). */\r
1391             ssh->sccipher->decrypt(ssh->sc_cipher_ctx,\r
1392                                    st->pktin->data + st->packetlen,\r
1393                                    st->cipherblk);\r
1394             /* Feed that block to the MAC. */\r
1395             ssh->scmac->bytes(ssh->sc_mac_ctx,\r
1396                               st->pktin->data + st->packetlen, st->cipherblk);\r
1397             st->packetlen += st->cipherblk;\r
1398             /* See if that gives us a valid packet. */\r
1399             if (ssh->scmac->verresult(ssh->sc_mac_ctx,\r
1400                                       st->pktin->data + st->packetlen) &&\r
1401                 (st->len = GET_32BIT(st->pktin->data)) + 4 == st->packetlen)\r
1402                     break;\r
1403             if (st->packetlen >= OUR_V2_PACKETLIMIT) {\r
1404                 bombout(("No valid incoming packet found"));\r
1405                 ssh_free_packet(st->pktin);\r
1406                 crStop(NULL);\r
1407             }       \r
1408         }\r
1409         st->pktin->maxlen = st->packetlen + st->maclen;\r
1410         st->pktin->data = sresize(st->pktin->data,\r
1411                                   st->pktin->maxlen + APIEXTRA,\r
1412                                   unsigned char);\r
1413     } else {\r
1414         st->pktin->data = snewn(st->cipherblk + APIEXTRA, unsigned char);\r
1415 \r
1416         /*\r
1417          * Acquire and decrypt the first block of the packet. This will\r
1418          * contain the length and padding details.\r
1419          */\r
1420         for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {\r
1421             while ((*datalen) == 0)\r
1422                 crReturn(NULL);\r
1423             st->pktin->data[st->i] = *(*data)++;\r
1424             (*datalen)--;\r
1425         }\r
1426 \r
1427         if (ssh->sccipher)\r
1428             ssh->sccipher->decrypt(ssh->sc_cipher_ctx,\r
1429                                    st->pktin->data, st->cipherblk);\r
1430 \r
1431         /*\r
1432          * Now get the length figure.\r
1433          */\r
1434         st->len = GET_32BIT(st->pktin->data);\r
1435 \r
1436         /*\r
1437          * _Completely_ silly lengths should be stomped on before they\r
1438          * do us any more damage.\r
1439          */\r
1440         if (st->len < 0 || st->len > OUR_V2_PACKETLIMIT ||\r
1441             (st->len + 4) % st->cipherblk != 0) {\r
1442             bombout(("Incoming packet was garbled on decryption"));\r
1443             ssh_free_packet(st->pktin);\r
1444             crStop(NULL);\r
1445         }\r
1446 \r
1447         /*\r
1448          * So now we can work out the total packet length.\r
1449          */\r
1450         st->packetlen = st->len + 4;\r
1451 \r
1452         /*\r
1453          * Allocate memory for the rest of the packet.\r
1454          */\r
1455         st->pktin->maxlen = st->packetlen + st->maclen;\r
1456         st->pktin->data = sresize(st->pktin->data,\r
1457                                   st->pktin->maxlen + APIEXTRA,\r
1458                                   unsigned char);\r
1459 \r
1460         /*\r
1461          * Read and decrypt the remainder of the packet.\r
1462          */\r
1463         for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;\r
1464              st->i++) {\r
1465             while ((*datalen) == 0)\r
1466                 crReturn(NULL);\r
1467             st->pktin->data[st->i] = *(*data)++;\r
1468             (*datalen)--;\r
1469         }\r
1470         /* Decrypt everything _except_ the MAC. */\r
1471         if (ssh->sccipher)\r
1472             ssh->sccipher->decrypt(ssh->sc_cipher_ctx,\r
1473                                    st->pktin->data + st->cipherblk,\r
1474                                    st->packetlen - st->cipherblk);\r
1475 \r
1476         /*\r
1477          * Check the MAC.\r
1478          */\r
1479         if (ssh->scmac\r
1480             && !ssh->scmac->verify(ssh->sc_mac_ctx, st->pktin->data,\r
1481                                    st->len + 4, st->incoming_sequence)) {\r
1482             bombout(("Incorrect MAC received on packet"));\r
1483             ssh_free_packet(st->pktin);\r
1484             crStop(NULL);\r
1485         }\r
1486     }\r
1487     /* Get and sanity-check the amount of random padding. */\r
1488     st->pad = st->pktin->data[4];\r
1489     if (st->pad < 4 || st->len - st->pad < 1) {\r
1490         bombout(("Invalid padding length on received packet"));\r
1491         ssh_free_packet(st->pktin);\r
1492         crStop(NULL);\r
1493     }\r
1494     /*\r
1495      * This enables us to deduce the payload length.\r
1496      */\r
1497     st->payload = st->len - st->pad - 1;\r
1498 \r
1499     st->pktin->length = st->payload + 5;\r
1500     st->pktin->encrypted_len = st->packetlen;\r
1501 \r
1502     st->pktin->sequence = st->incoming_sequence++;\r
1503 \r
1504     /*\r
1505      * Decompress packet payload.\r
1506      */\r
1507     {\r
1508         unsigned char *newpayload;\r
1509         int newlen;\r
1510         if (ssh->sccomp &&\r
1511             ssh->sccomp->decompress(ssh->sc_comp_ctx,\r
1512                                     st->pktin->data + 5, st->pktin->length - 5,\r
1513                                     &newpayload, &newlen)) {\r
1514             if (st->pktin->maxlen < newlen + 5) {\r
1515                 st->pktin->maxlen = newlen + 5;\r
1516                 st->pktin->data = sresize(st->pktin->data,\r
1517                                           st->pktin->maxlen + APIEXTRA,\r
1518                                           unsigned char);\r
1519             }\r
1520             st->pktin->length = 5 + newlen;\r
1521             memcpy(st->pktin->data + 5, newpayload, newlen);\r
1522             sfree(newpayload);\r
1523         }\r
1524     }\r
1525 \r
1526     st->pktin->savedpos = 6;\r
1527     st->pktin->body = st->pktin->data;\r
1528     st->pktin->type = st->pktin->data[5];\r
1529 \r
1530     /*\r
1531      * Log incoming packet, possibly omitting sensitive fields.\r
1532      */\r
1533     if (ssh->logctx) {\r
1534         int nblanks = 0;\r
1535         struct logblank_t blank;\r
1536         if (ssh->cfg.logomitdata) {\r
1537             int do_blank = FALSE, blank_prefix = 0;\r
1538             /* "Session data" packets - omit the data field */\r
1539             if (st->pktin->type == SSH2_MSG_CHANNEL_DATA) {\r
1540                 do_blank = TRUE; blank_prefix = 8;\r
1541             } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {\r
1542                 do_blank = TRUE; blank_prefix = 12;\r
1543             }\r
1544             if (do_blank) {\r
1545                 blank.offset = blank_prefix;\r
1546                 blank.len = (st->pktin->length-6) - blank_prefix;\r
1547                 blank.type = PKTLOG_OMIT;\r
1548                 nblanks = 1;\r
1549             }\r
1550         }\r
1551         log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,\r
1552                    ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,\r
1553                                  st->pktin->type),\r
1554                    st->pktin->data+6, st->pktin->length-6,\r
1555                    nblanks, &blank, &st->pktin->sequence);\r
1556     }\r
1557 \r
1558     crFinish(st->pktin);\r
1559 }\r
1560 \r
1561 static int s_wrpkt_prepare(Ssh ssh, struct Packet *pkt, int *offset_p)\r
1562 {\r
1563     int pad, biglen, i, pktoffs;\r
1564     unsigned long crc;\r
1565 #ifdef __SC__\r
1566     /*\r
1567      * XXX various versions of SC (including 8.8.4) screw up the\r
1568      * register allocation in this function and use the same register\r
1569      * (D6) for len and as a temporary, with predictable results.  The\r
1570      * following sledgehammer prevents this.\r
1571      */\r
1572     volatile\r
1573 #endif\r
1574     int len;\r
1575 \r
1576     if (ssh->logctx)\r
1577         log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[12],\r
1578                    ssh1_pkt_type(pkt->data[12]),\r
1579                    pkt->body, pkt->length - (pkt->body - pkt->data),\r
1580                    pkt->nblanks, pkt->blanks, NULL);\r
1581     sfree(pkt->blanks); pkt->blanks = NULL;\r
1582     pkt->nblanks = 0;\r
1583 \r
1584     if (ssh->v1_compressing) {\r
1585         unsigned char *compblk;\r
1586         int complen;\r
1587         zlib_compress_block(ssh->cs_comp_ctx,\r
1588                             pkt->data + 12, pkt->length - 12,\r
1589                             &compblk, &complen);\r
1590         ssh_pkt_ensure(pkt, complen + 2);   /* just in case it's got bigger */\r
1591         memcpy(pkt->data + 12, compblk, complen);\r
1592         sfree(compblk);\r
1593         pkt->length = complen + 12;\r
1594     }\r
1595 \r
1596     ssh_pkt_ensure(pkt, pkt->length + 4); /* space for CRC */\r
1597     pkt->length += 4;\r
1598     len = pkt->length - 4 - 8;  /* len(type+data+CRC) */\r
1599     pad = 8 - (len % 8);\r
1600     pktoffs = 8 - pad;\r
1601     biglen = len + pad;         /* len(padding+type+data+CRC) */\r
1602 \r
1603     for (i = pktoffs; i < 4+8; i++)\r
1604         pkt->data[i] = random_byte();\r
1605     crc = crc32_compute(pkt->data + pktoffs + 4, biglen - 4); /* all ex len */\r
1606     PUT_32BIT(pkt->data + pktoffs + 4 + biglen - 4, crc);\r
1607     PUT_32BIT(pkt->data + pktoffs, len);\r
1608 \r
1609     if (ssh->cipher)\r
1610         ssh->cipher->encrypt(ssh->v1_cipher_ctx,\r
1611                              pkt->data + pktoffs + 4, biglen);\r
1612 \r
1613     if (offset_p) *offset_p = pktoffs;\r
1614     return biglen + 4;          /* len(length+padding+type+data+CRC) */\r
1615 }\r
1616 \r
1617 static int s_write(Ssh ssh, void *data, int len)\r
1618 {\r
1619     if (ssh->logctx)\r
1620         log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len,\r
1621                    0, NULL, NULL);\r
1622     return sk_write(ssh->s, (char *)data, len);\r
1623 }\r
1624 \r
1625 static void s_wrpkt(Ssh ssh, struct Packet *pkt)\r
1626 {\r
1627     int len, backlog, offset;\r
1628     len = s_wrpkt_prepare(ssh, pkt, &offset);\r
1629     backlog = s_write(ssh, pkt->data + offset, len);\r
1630     if (backlog > SSH_MAX_BACKLOG)\r
1631         ssh_throttle_all(ssh, 1, backlog);\r
1632     ssh_free_packet(pkt);\r
1633 }\r
1634 \r
1635 static void s_wrpkt_defer(Ssh ssh, struct Packet *pkt)\r
1636 {\r
1637     int len, offset;\r
1638     len = s_wrpkt_prepare(ssh, pkt, &offset);\r
1639     if (ssh->deferred_len + len > ssh->deferred_size) {\r
1640         ssh->deferred_size = ssh->deferred_len + len + 128;\r
1641         ssh->deferred_send_data = sresize(ssh->deferred_send_data,\r
1642                                           ssh->deferred_size,\r
1643                                           unsigned char);\r
1644     }\r
1645     memcpy(ssh->deferred_send_data + ssh->deferred_len,\r
1646            pkt->data + offset, len);\r
1647     ssh->deferred_len += len;\r
1648     ssh_free_packet(pkt);\r
1649 }\r
1650 \r
1651 /*\r
1652  * Construct a SSH-1 packet with the specified contents.\r
1653  * (This all-at-once interface used to be the only one, but now SSH-1\r
1654  * packets can also be constructed incrementally.)\r
1655  */\r
1656 static struct Packet *construct_packet(Ssh ssh, int pkttype, va_list ap)\r
1657 {\r
1658     int argtype;\r
1659     Bignum bn;\r
1660     struct Packet *pkt;\r
1661 \r
1662     pkt = ssh1_pkt_init(pkttype);\r
1663 \r
1664     while ((argtype = va_arg(ap, int)) != PKT_END) {\r
1665         unsigned char *argp, argchar;\r
1666         char *sargp;\r
1667         unsigned long argint;\r
1668         int arglen;\r
1669         switch (argtype) {\r
1670           /* Actual fields in the packet */\r
1671           case PKT_INT:\r
1672             argint = va_arg(ap, int);\r
1673             ssh_pkt_adduint32(pkt, argint);\r
1674             break;\r
1675           case PKT_CHAR:\r
1676             argchar = (unsigned char) va_arg(ap, int);\r
1677             ssh_pkt_addbyte(pkt, argchar);\r
1678             break;\r
1679           case PKT_DATA:\r
1680             argp = va_arg(ap, unsigned char *);\r
1681             arglen = va_arg(ap, int);\r
1682             ssh_pkt_adddata(pkt, argp, arglen);\r
1683             break;\r
1684           case PKT_STR:\r
1685             sargp = va_arg(ap, char *);\r
1686             ssh_pkt_addstring(pkt, sargp);\r
1687             break;\r
1688           case PKT_BIGNUM:\r
1689             bn = va_arg(ap, Bignum);\r
1690             ssh1_pkt_addmp(pkt, bn);\r
1691             break;\r
1692           /* Tokens for modifications to packet logging */\r
1693           case PKTT_PASSWORD:\r
1694             dont_log_password(ssh, pkt, PKTLOG_BLANK);\r
1695             break;\r
1696           case PKTT_DATA:\r
1697             dont_log_data(ssh, pkt, PKTLOG_OMIT);\r
1698             break;\r
1699           case PKTT_OTHER:\r
1700             end_log_omission(ssh, pkt);\r
1701             break;\r
1702         }\r
1703     }\r
1704 \r
1705     return pkt;\r
1706 }\r
1707 \r
1708 static void send_packet(Ssh ssh, int pkttype, ...)\r
1709 {\r
1710     struct Packet *pkt;\r
1711     va_list ap;\r
1712     va_start(ap, pkttype);\r
1713     pkt = construct_packet(ssh, pkttype, ap);\r
1714     va_end(ap);\r
1715     s_wrpkt(ssh, pkt);\r
1716 }\r
1717 \r
1718 static void defer_packet(Ssh ssh, int pkttype, ...)\r
1719 {\r
1720     struct Packet *pkt;\r
1721     va_list ap;\r
1722     va_start(ap, pkttype);\r
1723     pkt = construct_packet(ssh, pkttype, ap);\r
1724     va_end(ap);\r
1725     s_wrpkt_defer(ssh, pkt);\r
1726 }\r
1727 \r
1728 static int ssh_versioncmp(char *a, char *b)\r
1729 {\r
1730     char *ae, *be;\r
1731     unsigned long av, bv;\r
1732 \r
1733     av = strtoul(a, &ae, 10);\r
1734     bv = strtoul(b, &be, 10);\r
1735     if (av != bv)\r
1736         return (av < bv ? -1 : +1);\r
1737     if (*ae == '.')\r
1738         ae++;\r
1739     if (*be == '.')\r
1740         be++;\r
1741     av = strtoul(ae, &ae, 10);\r
1742     bv = strtoul(be, &be, 10);\r
1743     if (av != bv)\r
1744         return (av < bv ? -1 : +1);\r
1745     return 0;\r
1746 }\r
1747 \r
1748 /*\r
1749  * Utility routines for putting an SSH-protocol `string' and\r
1750  * `uint32' into a hash state.\r
1751  */\r
1752 static void hash_string(const struct ssh_hash *h, void *s, void *str, int len)\r
1753 {\r
1754     unsigned char lenblk[4];\r
1755     PUT_32BIT(lenblk, len);\r
1756     h->bytes(s, lenblk, 4);\r
1757     h->bytes(s, str, len);\r
1758 }\r
1759 \r
1760 static void hash_uint32(const struct ssh_hash *h, void *s, unsigned i)\r
1761 {\r
1762     unsigned char intblk[4];\r
1763     PUT_32BIT(intblk, i);\r
1764     h->bytes(s, intblk, 4);\r
1765 }\r
1766 \r
1767 /*\r
1768  * Packet construction functions. Mostly shared between SSH-1 and SSH-2.\r
1769  */\r
1770 static void ssh_pkt_ensure(struct Packet *pkt, int length)\r
1771 {\r
1772     if (pkt->maxlen < length) {\r
1773         unsigned char *body = pkt->body;\r
1774         int offset = body ? body - pkt->data : 0;\r
1775         pkt->maxlen = length + 256;\r
1776         pkt->data = sresize(pkt->data, pkt->maxlen + APIEXTRA, unsigned char);\r
1777         if (body) pkt->body = pkt->data + offset;\r
1778     }\r
1779 }\r
1780 static void ssh_pkt_adddata(struct Packet *pkt, void *data, int len)\r
1781 {\r
1782     if (pkt->logmode != PKTLOG_EMIT) {\r
1783         pkt->nblanks++;\r
1784         pkt->blanks = sresize(pkt->blanks, pkt->nblanks, struct logblank_t);\r
1785         assert(pkt->body);\r
1786         pkt->blanks[pkt->nblanks-1].offset = pkt->length -\r
1787                                              (pkt->body - pkt->data);\r
1788         pkt->blanks[pkt->nblanks-1].len = len;\r
1789         pkt->blanks[pkt->nblanks-1].type = pkt->logmode;\r
1790     }\r
1791     pkt->length += len;\r
1792     ssh_pkt_ensure(pkt, pkt->length);\r
1793     memcpy(pkt->data + pkt->length - len, data, len);\r
1794 }\r
1795 static void ssh_pkt_addbyte(struct Packet *pkt, unsigned char byte)\r
1796 {\r
1797     ssh_pkt_adddata(pkt, &byte, 1);\r
1798 }\r
1799 static void ssh2_pkt_addbool(struct Packet *pkt, unsigned char value)\r
1800 {\r
1801     ssh_pkt_adddata(pkt, &value, 1);\r
1802 }\r
1803 static void ssh_pkt_adduint32(struct Packet *pkt, unsigned long value)\r
1804 {\r
1805     unsigned char x[4];\r
1806     PUT_32BIT(x, value);\r
1807     ssh_pkt_adddata(pkt, x, 4);\r
1808 }\r
1809 static void ssh_pkt_addstring_start(struct Packet *pkt)\r
1810 {\r
1811     ssh_pkt_adduint32(pkt, 0);\r
1812     pkt->savedpos = pkt->length;\r
1813 }\r
1814 static void ssh_pkt_addstring_str(struct Packet *pkt, char *data)\r
1815 {\r
1816     ssh_pkt_adddata(pkt, data, strlen(data));\r
1817     PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);\r
1818 }\r
1819 static void ssh_pkt_addstring_data(struct Packet *pkt, char *data, int len)\r
1820 {\r
1821     ssh_pkt_adddata(pkt, data, len);\r
1822     PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);\r
1823 }\r
1824 static void ssh_pkt_addstring(struct Packet *pkt, char *data)\r
1825 {\r
1826     ssh_pkt_addstring_start(pkt);\r
1827     ssh_pkt_addstring_str(pkt, data);\r
1828 }\r
1829 static void ssh1_pkt_addmp(struct Packet *pkt, Bignum b)\r
1830 {\r
1831     int len = ssh1_bignum_length(b);\r
1832     unsigned char *data = snewn(len, unsigned char);\r
1833     (void) ssh1_write_bignum(data, b);\r
1834     ssh_pkt_adddata(pkt, data, len);\r
1835     sfree(data);\r
1836 }\r
1837 static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)\r
1838 {\r
1839     unsigned char *p;\r
1840     int i, n = (bignum_bitcount(b) + 7) / 8;\r
1841     p = snewn(n + 1, unsigned char);\r
1842     p[0] = 0;\r
1843     for (i = 1; i <= n; i++)\r
1844         p[i] = bignum_byte(b, n - i);\r
1845     i = 0;\r
1846     while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)\r
1847         i++;\r
1848     memmove(p, p + i, n + 1 - i);\r
1849     *len = n + 1 - i;\r
1850     return p;\r
1851 }\r
1852 static void ssh2_pkt_addmp(struct Packet *pkt, Bignum b)\r
1853 {\r
1854     unsigned char *p;\r
1855     int len;\r
1856     p = ssh2_mpint_fmt(b, &len);\r
1857     ssh_pkt_addstring_start(pkt);\r
1858     ssh_pkt_addstring_data(pkt, (char *)p, len);\r
1859     sfree(p);\r
1860 }\r
1861 \r
1862 static struct Packet *ssh1_pkt_init(int pkt_type)\r
1863 {\r
1864     struct Packet *pkt = ssh_new_packet();\r
1865     pkt->length = 4 + 8;            /* space for length + max padding */\r
1866     ssh_pkt_addbyte(pkt, pkt_type);\r
1867     pkt->body = pkt->data + pkt->length;\r
1868     return pkt;\r
1869 }\r
1870 \r
1871 /* For legacy code (SSH-1 and -2 packet construction used to be separate) */\r
1872 #define ssh2_pkt_ensure(pkt, length) ssh_pkt_ensure(pkt, length)\r
1873 #define ssh2_pkt_adddata(pkt, data, len) ssh_pkt_adddata(pkt, data, len)\r
1874 #define ssh2_pkt_addbyte(pkt, byte) ssh_pkt_addbyte(pkt, byte)\r
1875 #define ssh2_pkt_adduint32(pkt, value) ssh_pkt_adduint32(pkt, value)\r
1876 #define ssh2_pkt_addstring_start(pkt) ssh_pkt_addstring_start(pkt)\r
1877 #define ssh2_pkt_addstring_str(pkt, data) ssh_pkt_addstring_str(pkt, data)\r
1878 #define ssh2_pkt_addstring_data(pkt, data, len) ssh_pkt_addstring_data(pkt, data, len)\r
1879 #define ssh2_pkt_addstring(pkt, data) ssh_pkt_addstring(pkt, data)\r
1880 \r
1881 static struct Packet *ssh2_pkt_init(int pkt_type)\r
1882 {\r
1883     struct Packet *pkt = ssh_new_packet();\r
1884     pkt->length = 5; /* space for packet length + padding length */\r
1885     pkt->forcepad = 0;\r
1886     ssh_pkt_addbyte(pkt, (unsigned char) pkt_type);\r
1887     pkt->body = pkt->data + pkt->length; /* after packet type */\r
1888     return pkt;\r
1889 }\r
1890 \r
1891 /*\r
1892  * Construct an SSH-2 final-form packet: compress it, encrypt it,\r
1893  * put the MAC on it. Final packet, ready to be sent, is stored in\r
1894  * pkt->data. Total length is returned.\r
1895  */\r
1896 static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)\r
1897 {\r
1898     int cipherblk, maclen, padding, i;\r
1899 \r
1900     if (ssh->logctx)\r
1901         log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[5],\r
1902                    ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx, pkt->data[5]),\r
1903                    pkt->body, pkt->length - (pkt->body - pkt->data),\r
1904                    pkt->nblanks, pkt->blanks, &ssh->v2_outgoing_sequence);\r
1905     sfree(pkt->blanks); pkt->blanks = NULL;\r
1906     pkt->nblanks = 0;\r
1907 \r
1908     /*\r
1909      * Compress packet payload.\r
1910      */\r
1911     {\r
1912         unsigned char *newpayload;\r
1913         int newlen;\r
1914         if (ssh->cscomp &&\r
1915             ssh->cscomp->compress(ssh->cs_comp_ctx, pkt->data + 5,\r
1916                                   pkt->length - 5,\r
1917                                   &newpayload, &newlen)) {\r
1918             pkt->length = 5;\r
1919             ssh2_pkt_adddata(pkt, newpayload, newlen);\r
1920             sfree(newpayload);\r
1921         }\r
1922     }\r
1923 \r
1924     /*\r
1925      * Add padding. At least four bytes, and must also bring total\r
1926      * length (minus MAC) up to a multiple of the block size.\r
1927      * If pkt->forcepad is set, make sure the packet is at least that size\r
1928      * after padding.\r
1929      */\r
1930     cipherblk = ssh->cscipher ? ssh->cscipher->blksize : 8;  /* block size */\r
1931     cipherblk = cipherblk < 8 ? 8 : cipherblk;  /* or 8 if blksize < 8 */\r
1932     padding = 4;\r
1933     if (pkt->length + padding < pkt->forcepad)\r
1934         padding = pkt->forcepad - pkt->length;\r
1935     padding +=\r
1936         (cipherblk - (pkt->length + padding) % cipherblk) % cipherblk;\r
1937     assert(padding <= 255);\r
1938     maclen = ssh->csmac ? ssh->csmac->len : 0;\r
1939     ssh2_pkt_ensure(pkt, pkt->length + padding + maclen);\r
1940     pkt->data[4] = padding;\r
1941     for (i = 0; i < padding; i++)\r
1942         pkt->data[pkt->length + i] = random_byte();\r
1943     PUT_32BIT(pkt->data, pkt->length + padding - 4);\r
1944     if (ssh->csmac)\r
1945         ssh->csmac->generate(ssh->cs_mac_ctx, pkt->data,\r
1946                              pkt->length + padding,\r
1947                              ssh->v2_outgoing_sequence);\r
1948     ssh->v2_outgoing_sequence++;       /* whether or not we MACed */\r
1949 \r
1950     if (ssh->cscipher)\r
1951         ssh->cscipher->encrypt(ssh->cs_cipher_ctx,\r
1952                                pkt->data, pkt->length + padding);\r
1953 \r
1954     pkt->encrypted_len = pkt->length + padding;\r
1955 \r
1956     /* Ready-to-send packet starts at pkt->data. We return length. */\r
1957     return pkt->length + padding + maclen;\r
1958 }\r
1959 \r
1960 /*\r
1961  * Routines called from the main SSH code to send packets. There\r
1962  * are quite a few of these, because we have two separate\r
1963  * mechanisms for delaying the sending of packets:\r
1964  * \r
1965  *  - In order to send an IGNORE message and a password message in\r
1966  *    a single fixed-length blob, we require the ability to\r
1967  *    concatenate the encrypted forms of those two packets _into_ a\r
1968  *    single blob and then pass it to our <network.h> transport\r
1969  *    layer in one go. Hence, there's a deferment mechanism which\r
1970  *    works after packet encryption.\r
1971  * \r
1972  *  - In order to avoid sending any connection-layer messages\r
1973  *    during repeat key exchange, we have to queue up any such\r
1974  *    outgoing messages _before_ they are encrypted (and in\r
1975  *    particular before they're allocated sequence numbers), and\r
1976  *    then send them once we've finished.\r
1977  * \r
1978  * I call these mechanisms `defer' and `queue' respectively, so as\r
1979  * to distinguish them reasonably easily.\r
1980  * \r
1981  * The functions send_noqueue() and defer_noqueue() free the packet\r
1982  * structure they are passed. Every outgoing packet goes through\r
1983  * precisely one of these functions in its life; packets passed to\r
1984  * ssh2_pkt_send() or ssh2_pkt_defer() either go straight to one of\r
1985  * these or get queued, and then when the queue is later emptied\r
1986  * the packets are all passed to defer_noqueue().\r
1987  *\r
1988  * When using a CBC-mode cipher, it's necessary to ensure that an\r
1989  * attacker can't provide data to be encrypted using an IV that they\r
1990  * know.  We ensure this by prefixing each packet that might contain\r
1991  * user data with an SSH_MSG_IGNORE.  This is done using the deferral\r
1992  * mechanism, so in this case send_noqueue() ends up redirecting to\r
1993  * defer_noqueue().  If you don't like this inefficiency, don't use\r
1994  * CBC.\r
1995  */\r
1996 \r
1997 static void ssh2_pkt_defer_noqueue(Ssh, struct Packet *, int);\r
1998 static void ssh_pkt_defersend(Ssh);\r
1999 \r
2000 /*\r
2001  * Send an SSH-2 packet immediately, without queuing or deferring.\r
2002  */\r
2003 static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)\r
2004 {\r
2005     int len;\r
2006     int backlog;\r
2007     if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) {\r
2008         /* We need to send two packets, so use the deferral mechanism. */\r
2009         ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);\r
2010         ssh_pkt_defersend(ssh);\r
2011         return;\r
2012     }\r
2013     len = ssh2_pkt_construct(ssh, pkt);\r
2014     backlog = s_write(ssh, pkt->data, len);\r
2015     if (backlog > SSH_MAX_BACKLOG)\r
2016         ssh_throttle_all(ssh, 1, backlog);\r
2017 \r
2018     ssh->outgoing_data_size += pkt->encrypted_len;\r
2019     if (!ssh->kex_in_progress &&\r
2020         ssh->max_data_size != 0 &&\r
2021         ssh->outgoing_data_size > ssh->max_data_size)\r
2022         do_ssh2_transport(ssh, "too much data sent", -1, NULL);\r
2023 \r
2024     ssh_free_packet(pkt);\r
2025 }\r
2026 \r
2027 /*\r
2028  * Defer an SSH-2 packet.\r
2029  */\r
2030 static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt, int noignore)\r
2031 {\r
2032     int len;\r
2033     if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) &&\r
2034         ssh->deferred_len == 0 && !noignore &&\r
2035         !(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {\r
2036         /*\r
2037          * Interpose an SSH_MSG_IGNORE to ensure that user data don't\r
2038          * get encrypted with a known IV.\r
2039          */\r
2040         struct Packet *ipkt = ssh2_pkt_init(SSH2_MSG_IGNORE);\r
2041         ssh2_pkt_addstring_start(ipkt);\r
2042         ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE);\r
2043     }\r
2044     len = ssh2_pkt_construct(ssh, pkt);\r
2045     if (ssh->deferred_len + len > ssh->deferred_size) {\r
2046         ssh->deferred_size = ssh->deferred_len + len + 128;\r
2047         ssh->deferred_send_data = sresize(ssh->deferred_send_data,\r
2048                                           ssh->deferred_size,\r
2049                                           unsigned char);\r
2050     }\r
2051     memcpy(ssh->deferred_send_data + ssh->deferred_len, pkt->data, len);\r
2052     ssh->deferred_len += len;\r
2053     ssh->deferred_data_size += pkt->encrypted_len;\r
2054     ssh_free_packet(pkt);\r
2055 }\r
2056 \r
2057 /*\r
2058  * Queue an SSH-2 packet.\r
2059  */\r
2060 static void ssh2_pkt_queue(Ssh ssh, struct Packet *pkt)\r
2061 {\r
2062     assert(ssh->queueing);\r
2063 \r
2064     if (ssh->queuelen >= ssh->queuesize) {\r
2065         ssh->queuesize = ssh->queuelen + 32;\r
2066         ssh->queue = sresize(ssh->queue, ssh->queuesize, struct Packet *);\r
2067     }\r
2068 \r
2069     ssh->queue[ssh->queuelen++] = pkt;\r
2070 }\r
2071 \r
2072 /*\r
2073  * Either queue or send a packet, depending on whether queueing is\r
2074  * set.\r
2075  */\r
2076 static void ssh2_pkt_send(Ssh ssh, struct Packet *pkt)\r
2077 {\r
2078     if (ssh->queueing)\r
2079         ssh2_pkt_queue(ssh, pkt);\r
2080     else\r
2081         ssh2_pkt_send_noqueue(ssh, pkt);\r
2082 }\r
2083 \r
2084 /*\r
2085  * Either queue or defer a packet, depending on whether queueing is\r
2086  * set.\r
2087  */\r
2088 static void ssh2_pkt_defer(Ssh ssh, struct Packet *pkt)\r
2089 {\r
2090     if (ssh->queueing)\r
2091         ssh2_pkt_queue(ssh, pkt);\r
2092     else\r
2093         ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);\r
2094 }\r
2095 \r
2096 /*\r
2097  * Send the whole deferred data block constructed by\r
2098  * ssh2_pkt_defer() or SSH-1's defer_packet().\r
2099  * \r
2100  * The expected use of the defer mechanism is that you call\r
2101  * ssh2_pkt_defer() a few times, then call ssh_pkt_defersend(). If\r
2102  * not currently queueing, this simply sets up deferred_send_data\r
2103  * and then sends it. If we _are_ currently queueing, the calls to\r
2104  * ssh2_pkt_defer() put the deferred packets on to the queue\r
2105  * instead, and therefore ssh_pkt_defersend() has no deferred data\r
2106  * to send. Hence, there's no need to make it conditional on\r
2107  * ssh->queueing.\r
2108  */\r
2109 static void ssh_pkt_defersend(Ssh ssh)\r
2110 {\r
2111     int backlog;\r
2112     backlog = s_write(ssh, ssh->deferred_send_data, ssh->deferred_len);\r
2113     ssh->deferred_len = ssh->deferred_size = 0;\r
2114     sfree(ssh->deferred_send_data);\r
2115     ssh->deferred_send_data = NULL;\r
2116     if (backlog > SSH_MAX_BACKLOG)\r
2117         ssh_throttle_all(ssh, 1, backlog);\r
2118 \r
2119     ssh->outgoing_data_size += ssh->deferred_data_size;\r
2120     if (!ssh->kex_in_progress &&\r
2121         ssh->max_data_size != 0 &&\r
2122         ssh->outgoing_data_size > ssh->max_data_size)\r
2123         do_ssh2_transport(ssh, "too much data sent", -1, NULL);\r
2124     ssh->deferred_data_size = 0;\r
2125 }\r
2126 \r
2127 /*\r
2128  * Send a packet whose length needs to be disguised (typically\r
2129  * passwords or keyboard-interactive responses).\r
2130  */\r
2131 static void ssh2_pkt_send_with_padding(Ssh ssh, struct Packet *pkt,\r
2132                                        int padsize)\r
2133 {\r
2134 #if 0\r
2135     if (0) {\r
2136         /*\r
2137          * The simplest way to do this is to adjust the\r
2138          * variable-length padding field in the outgoing packet.\r
2139          * \r
2140          * Currently compiled out, because some Cisco SSH servers\r
2141          * don't like excessively padded packets (bah, why's it\r
2142          * always Cisco?)\r
2143          */\r
2144         pkt->forcepad = padsize;\r
2145         ssh2_pkt_send(ssh, pkt);\r
2146     } else\r
2147 #endif\r
2148     {\r
2149         /*\r
2150          * If we can't do that, however, an alternative approach is\r
2151          * to use the pkt_defer mechanism to bundle the packet\r
2152          * tightly together with an SSH_MSG_IGNORE such that their\r
2153          * combined length is a constant. So first we construct the\r
2154          * final form of this packet and defer its sending.\r
2155          */\r
2156         ssh2_pkt_defer(ssh, pkt);\r
2157 \r
2158         /*\r
2159          * Now construct an SSH_MSG_IGNORE which includes a string\r
2160          * that's an exact multiple of the cipher block size. (If\r
2161          * the cipher is NULL so that the block size is\r
2162          * unavailable, we don't do this trick at all, because we\r
2163          * gain nothing by it.)\r
2164          */\r
2165         if (ssh->cscipher &&\r
2166             !(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {\r
2167             int stringlen, i;\r
2168 \r
2169             stringlen = (256 - ssh->deferred_len);\r
2170             stringlen += ssh->cscipher->blksize - 1;\r
2171             stringlen -= (stringlen % ssh->cscipher->blksize);\r
2172             if (ssh->cscomp) {\r
2173                 /*\r
2174                  * Temporarily disable actual compression, so we\r
2175                  * can guarantee to get this string exactly the\r
2176                  * length we want it. The compression-disabling\r
2177                  * routine should return an integer indicating how\r
2178                  * many bytes we should adjust our string length\r
2179                  * by.\r
2180                  */\r
2181                 stringlen -=\r
2182                     ssh->cscomp->disable_compression(ssh->cs_comp_ctx);\r
2183             }\r
2184             pkt = ssh2_pkt_init(SSH2_MSG_IGNORE);\r
2185             ssh2_pkt_addstring_start(pkt);\r
2186             for (i = 0; i < stringlen; i++) {\r
2187                 char c = (char) random_byte();\r
2188                 ssh2_pkt_addstring_data(pkt, &c, 1);\r
2189             }\r
2190             ssh2_pkt_defer(ssh, pkt);\r
2191         }\r
2192         ssh_pkt_defersend(ssh);\r
2193     }\r
2194 }\r
2195 \r
2196 /*\r
2197  * Send all queued SSH-2 packets. We send them by means of\r
2198  * ssh2_pkt_defer_noqueue(), in case they included a pair of\r
2199  * packets that needed to be lumped together.\r
2200  */\r
2201 static void ssh2_pkt_queuesend(Ssh ssh)\r
2202 {\r
2203     int i;\r
2204 \r
2205     assert(!ssh->queueing);\r
2206 \r
2207     for (i = 0; i < ssh->queuelen; i++)\r
2208         ssh2_pkt_defer_noqueue(ssh, ssh->queue[i], FALSE);\r
2209     ssh->queuelen = 0;\r
2210 \r
2211     ssh_pkt_defersend(ssh);\r
2212 }\r
2213 \r
2214 #if 0\r
2215 void bndebug(char *string, Bignum b)\r
2216 {\r
2217     unsigned char *p;\r
2218     int i, len;\r
2219     p = ssh2_mpint_fmt(b, &len);\r
2220     debug(("%s", string));\r
2221     for (i = 0; i < len; i++)\r
2222         debug((" %02x", p[i]));\r
2223     debug(("\n"));\r
2224     sfree(p);\r
2225 }\r
2226 #endif\r
2227 \r
2228 static void hash_mpint(const struct ssh_hash *h, void *s, Bignum b)\r
2229 {\r
2230     unsigned char *p;\r
2231     int len;\r
2232     p = ssh2_mpint_fmt(b, &len);\r
2233     hash_string(h, s, p, len);\r
2234     sfree(p);\r
2235 }\r
2236 \r
2237 /*\r
2238  * Packet decode functions for both SSH-1 and SSH-2.\r
2239  */\r
2240 static unsigned long ssh_pkt_getuint32(struct Packet *pkt)\r
2241 {\r
2242     unsigned long value;\r
2243     if (pkt->length - pkt->savedpos < 4)\r
2244         return 0;                      /* arrgh, no way to decline (FIXME?) */\r
2245     value = GET_32BIT(pkt->body + pkt->savedpos);\r
2246     pkt->savedpos += 4;\r
2247     return value;\r
2248 }\r
2249 static int ssh2_pkt_getbool(struct Packet *pkt)\r
2250 {\r
2251     unsigned long value;\r
2252     if (pkt->length - pkt->savedpos < 1)\r
2253         return 0;                      /* arrgh, no way to decline (FIXME?) */\r
2254     value = pkt->body[pkt->savedpos] != 0;\r
2255     pkt->savedpos++;\r
2256     return value;\r
2257 }\r
2258 static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length)\r
2259 {\r
2260     int len;\r
2261     *p = NULL;\r
2262     *length = 0;\r
2263     if (pkt->length - pkt->savedpos < 4)\r
2264         return;\r
2265     len = GET_32BIT(pkt->body + pkt->savedpos);\r
2266     if (len < 0)\r
2267         return;\r
2268     *length = len;\r
2269     pkt->savedpos += 4;\r
2270     if (pkt->length - pkt->savedpos < *length)\r
2271         return;\r
2272     *p = (char *)(pkt->body + pkt->savedpos);\r
2273     pkt->savedpos += *length;\r
2274 }\r
2275 static void *ssh_pkt_getdata(struct Packet *pkt, int length)\r
2276 {\r
2277     if (pkt->length - pkt->savedpos < length)\r
2278         return NULL;\r
2279     pkt->savedpos += length;\r
2280     return pkt->body + (pkt->savedpos - length);\r
2281 }\r
2282 static int ssh1_pkt_getrsakey(struct Packet *pkt, struct RSAKey *key,\r
2283                               unsigned char **keystr)\r
2284 {\r
2285     int j;\r
2286 \r
2287     j = makekey(pkt->body + pkt->savedpos,\r
2288                 pkt->length - pkt->savedpos,\r
2289                 key, keystr, 0);\r
2290 \r
2291     if (j < 0)\r
2292         return FALSE;\r
2293     \r
2294     pkt->savedpos += j;\r
2295     assert(pkt->savedpos < pkt->length);\r
2296 \r
2297     return TRUE;\r
2298 }\r
2299 static Bignum ssh1_pkt_getmp(struct Packet *pkt)\r
2300 {\r
2301     int j;\r
2302     Bignum b;\r
2303 \r
2304     j = ssh1_read_bignum(pkt->body + pkt->savedpos,\r
2305                          pkt->length - pkt->savedpos, &b);\r
2306 \r
2307     if (j < 0)\r
2308         return NULL;\r
2309 \r
2310     pkt->savedpos += j;\r
2311     return b;\r
2312 }\r
2313 static Bignum ssh2_pkt_getmp(struct Packet *pkt)\r
2314 {\r
2315     char *p;\r
2316     int length;\r
2317     Bignum b;\r
2318 \r
2319     ssh_pkt_getstring(pkt, &p, &length);\r
2320     if (!p)\r
2321         return NULL;\r
2322     if (p[0] & 0x80)\r
2323         return NULL;\r
2324     b = bignum_from_bytes((unsigned char *)p, length);\r
2325     return b;\r
2326 }\r
2327 \r
2328 /*\r
2329  * Helper function to add an SSH-2 signature blob to a packet.\r
2330  * Expects to be shown the public key blob as well as the signature\r
2331  * blob. Normally works just like ssh2_pkt_addstring, but will\r
2332  * fiddle with the signature packet if necessary for\r
2333  * BUG_SSH2_RSA_PADDING.\r
2334  */\r
2335 static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,\r
2336                              void *pkblob_v, int pkblob_len,\r
2337                              void *sigblob_v, int sigblob_len)\r
2338 {\r
2339     unsigned char *pkblob = (unsigned char *)pkblob_v;\r
2340     unsigned char *sigblob = (unsigned char *)sigblob_v;\r
2341 \r
2342     /* dmemdump(pkblob, pkblob_len); */\r
2343     /* dmemdump(sigblob, sigblob_len); */\r
2344 \r
2345     /*\r
2346      * See if this is in fact an ssh-rsa signature and a buggy\r
2347      * server; otherwise we can just do this the easy way.\r
2348      */\r
2349     if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&\r
2350         (GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {\r
2351         int pos, len, siglen;\r
2352 \r
2353         /*\r
2354          * Find the byte length of the modulus.\r
2355          */\r
2356 \r
2357         pos = 4+7;                     /* skip over "ssh-rsa" */\r
2358         pos += 4 + GET_32BIT(pkblob+pos);   /* skip over exponent */\r
2359         len = GET_32BIT(pkblob+pos);   /* find length of modulus */\r
2360         pos += 4;                      /* find modulus itself */\r
2361         while (len > 0 && pkblob[pos] == 0)\r
2362             len--, pos++;\r
2363         /* debug(("modulus length is %d\n", len)); */\r
2364 \r
2365         /*\r
2366          * Now find the signature integer.\r
2367          */\r
2368         pos = 4+7;                     /* skip over "ssh-rsa" */\r
2369         siglen = GET_32BIT(sigblob+pos);\r
2370         /* debug(("signature length is %d\n", siglen)); */\r
2371 \r
2372         if (len != siglen) {\r
2373             unsigned char newlen[4];\r
2374             ssh2_pkt_addstring_start(pkt);\r
2375             ssh2_pkt_addstring_data(pkt, (char *)sigblob, pos);\r
2376             /* dmemdump(sigblob, pos); */\r
2377             pos += 4;                  /* point to start of actual sig */\r
2378             PUT_32BIT(newlen, len);\r
2379             ssh2_pkt_addstring_data(pkt, (char *)newlen, 4);\r
2380             /* dmemdump(newlen, 4); */\r
2381             newlen[0] = 0;\r
2382             while (len-- > siglen) {\r
2383                 ssh2_pkt_addstring_data(pkt, (char *)newlen, 1);\r
2384                 /* dmemdump(newlen, 1); */\r
2385             }\r
2386             ssh2_pkt_addstring_data(pkt, (char *)(sigblob+pos), siglen);\r
2387             /* dmemdump(sigblob+pos, siglen); */\r
2388             return;\r
2389         }\r
2390 \r
2391         /* Otherwise fall through and do it the easy way. */\r
2392     }\r
2393 \r
2394     ssh2_pkt_addstring_start(pkt);\r
2395     ssh2_pkt_addstring_data(pkt, (char *)sigblob, sigblob_len);\r
2396 }\r
2397 \r
2398 /*\r
2399  * Examine the remote side's version string and compare it against\r
2400  * a list of known buggy implementations.\r
2401  */\r
2402 static void ssh_detect_bugs(Ssh ssh, char *vstring)\r
2403 {\r
2404     char *imp;                         /* pointer to implementation part */\r
2405     imp = vstring;\r
2406     imp += strcspn(imp, "-");\r
2407     if (*imp) imp++;\r
2408     imp += strcspn(imp, "-");\r
2409     if (*imp) imp++;\r
2410 \r
2411     ssh->remote_bugs = 0;\r
2412 \r
2413     /*\r
2414      * General notes on server version strings:\r
2415      *  - Not all servers reporting "Cisco-1.25" have all the bugs listed\r
2416      *    here -- in particular, we've heard of one that's perfectly happy\r
2417      *    with SSH1_MSG_IGNOREs -- but this string never seems to change,\r
2418      *    so we can't distinguish them.\r
2419      */\r
2420     if (ssh->cfg.sshbug_ignore1 == FORCE_ON ||\r
2421         (ssh->cfg.sshbug_ignore1 == AUTO &&\r
2422          (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||\r
2423           !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||\r
2424           !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||\r
2425           !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {\r
2426         /*\r
2427          * These versions don't support SSH1_MSG_IGNORE, so we have\r
2428          * to use a different defence against password length\r
2429          * sniffing.\r
2430          */\r
2431         ssh->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;\r
2432         logevent("We believe remote version has SSH-1 ignore bug");\r
2433     }\r
2434 \r
2435     if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||\r
2436         (ssh->cfg.sshbug_plainpw1 == AUTO &&\r
2437          (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {\r
2438         /*\r
2439          * These versions need a plain password sent; they can't\r
2440          * handle having a null and a random length of data after\r
2441          * the password.\r
2442          */\r
2443         ssh->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;\r
2444         logevent("We believe remote version needs a plain SSH-1 password");\r
2445     }\r
2446 \r
2447     if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||\r
2448         (ssh->cfg.sshbug_rsa1 == AUTO &&\r
2449          (!strcmp(imp, "Cisco-1.25")))) {\r
2450         /*\r
2451          * These versions apparently have no clue whatever about\r
2452          * RSA authentication and will panic and die if they see\r
2453          * an AUTH_RSA message.\r
2454          */\r
2455         ssh->remote_bugs |= BUG_CHOKES_ON_RSA;\r
2456         logevent("We believe remote version can't handle SSH-1 RSA authentication");\r
2457     }\r
2458 \r
2459     if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||\r
2460         (ssh->cfg.sshbug_hmac2 == AUTO &&\r
2461          !wc_match("* VShell", imp) &&\r
2462          (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||\r
2463           wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||\r
2464           wc_match("2.1 *", imp)))) {\r
2465         /*\r
2466          * These versions have the HMAC bug.\r
2467          */\r
2468         ssh->remote_bugs |= BUG_SSH2_HMAC;\r
2469         logevent("We believe remote version has SSH-2 HMAC bug");\r
2470     }\r
2471 \r
2472     if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||\r
2473         (ssh->cfg.sshbug_derivekey2 == AUTO &&\r
2474          !wc_match("* VShell", imp) &&\r
2475          (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {\r
2476         /*\r
2477          * These versions have the key-derivation bug (failing to\r
2478          * include the literal shared secret in the hashes that\r
2479          * generate the keys).\r
2480          */\r
2481         ssh->remote_bugs |= BUG_SSH2_DERIVEKEY;\r
2482         logevent("We believe remote version has SSH-2 key-derivation bug");\r
2483     }\r
2484 \r
2485     if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||\r
2486         (ssh->cfg.sshbug_rsapad2 == AUTO &&\r
2487          (wc_match("OpenSSH_2.[5-9]*", imp) ||\r
2488           wc_match("OpenSSH_3.[0-2]*", imp)))) {\r
2489         /*\r
2490          * These versions have the SSH-2 RSA padding bug.\r
2491          */\r
2492         ssh->remote_bugs |= BUG_SSH2_RSA_PADDING;\r
2493         logevent("We believe remote version has SSH-2 RSA padding bug");\r
2494     }\r
2495 \r
2496     if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||\r
2497         (ssh->cfg.sshbug_pksessid2 == AUTO &&\r
2498          wc_match("OpenSSH_2.[0-2]*", imp))) {\r
2499         /*\r
2500          * These versions have the SSH-2 session-ID bug in\r
2501          * public-key authentication.\r
2502          */\r
2503         ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;\r
2504         logevent("We believe remote version has SSH-2 public-key-session-ID bug");\r
2505     }\r
2506 \r
2507     if (ssh->cfg.sshbug_rekey2 == FORCE_ON ||\r
2508         (ssh->cfg.sshbug_rekey2 == AUTO &&\r
2509          (wc_match("DigiSSH_2.0", imp) ||\r
2510           wc_match("OpenSSH_2.[0-4]*", imp) ||\r
2511           wc_match("OpenSSH_2.5.[0-3]*", imp) ||\r
2512           wc_match("Sun_SSH_1.0", imp) ||\r
2513           wc_match("Sun_SSH_1.0.1", imp) ||\r
2514           /* All versions <= 1.2.6 (they changed their format in 1.2.7) */\r
2515           wc_match("WeOnlyDo-*", imp)))) {\r
2516         /*\r
2517          * These versions have the SSH-2 rekey bug.\r
2518          */\r
2519         ssh->remote_bugs |= BUG_SSH2_REKEY;\r
2520         logevent("We believe remote version has SSH-2 rekey bug");\r
2521     }\r
2522 \r
2523     if (ssh->cfg.sshbug_maxpkt2 == FORCE_ON ||\r
2524         (ssh->cfg.sshbug_maxpkt2 == AUTO &&\r
2525          (wc_match("1.36_sshlib GlobalSCAPE", imp) ||\r
2526           wc_match("1.36 sshlib: GlobalScape", imp)))) {\r
2527         /*\r
2528          * This version ignores our makpkt and needs to be throttled.\r
2529          */\r
2530         ssh->remote_bugs |= BUG_SSH2_MAXPKT;\r
2531         logevent("We believe remote version ignores SSH-2 maximum packet size");\r
2532     }\r
2533 \r
2534     if (ssh->cfg.sshbug_ignore2 == FORCE_ON) {\r
2535         /*\r
2536          * Servers that don't support SSH2_MSG_IGNORE. Currently,\r
2537          * none detected automatically.\r
2538          */\r
2539         ssh->remote_bugs |= BUG_CHOKES_ON_SSH2_IGNORE;\r
2540         logevent("We believe remote version has SSH-2 ignore bug");\r
2541     }\r
2542 }\r
2543 \r
2544 /*\r
2545  * The `software version' part of an SSH version string is required\r
2546  * to contain no spaces or minus signs.\r
2547  */\r
2548 static void ssh_fix_verstring(char *str)\r
2549 {\r
2550     /* Eat "SSH-<protoversion>-". */\r
2551     assert(*str == 'S'); str++;\r
2552     assert(*str == 'S'); str++;\r
2553     assert(*str == 'H'); str++;\r
2554     assert(*str == '-'); str++;\r
2555     while (*str && *str != '-') str++;\r
2556     assert(*str == '-'); str++;\r
2557 \r
2558     /* Convert minus signs and spaces in the remaining string into\r
2559      * underscores. */\r
2560     while (*str) {\r
2561         if (*str == '-' || *str == ' ')\r
2562             *str = '_';\r
2563         str++;\r
2564     }\r
2565 }\r
2566 \r
2567 /*\r
2568  * Send an appropriate SSH version string.\r
2569  */\r
2570 static void ssh_send_verstring(Ssh ssh, char *svers)\r
2571 {\r
2572     char *verstring;\r
2573 \r
2574     if (ssh->version == 2) {\r
2575         /*\r
2576          * Construct a v2 version string.\r
2577          */\r
2578         verstring = dupprintf("SSH-2.0-%s\015\012", sshver);\r
2579     } else {\r
2580         /*\r
2581          * Construct a v1 version string.\r
2582          */\r
2583         verstring = dupprintf("SSH-%s-%s\012",\r
2584                               (ssh_versioncmp(svers, "1.5") <= 0 ?\r
2585                                svers : "1.5"),\r
2586                               sshver);\r
2587     }\r
2588 \r
2589     ssh_fix_verstring(verstring);\r
2590 \r
2591     if (ssh->version == 2) {\r
2592         size_t len;\r
2593         /*\r
2594          * Record our version string.\r
2595          */\r
2596         len = strcspn(verstring, "\015\012");\r
2597         ssh->v_c = snewn(len + 1, char);\r
2598         memcpy(ssh->v_c, verstring, len);\r
2599         ssh->v_c[len] = 0;\r
2600     }\r
2601 \r
2602     logeventf(ssh, "We claim version: %.*s",\r
2603               strcspn(verstring, "\015\012"), verstring);\r
2604     s_write(ssh, verstring, strlen(verstring));\r
2605     sfree(verstring);\r
2606 }\r
2607 \r
2608 static int do_ssh_init(Ssh ssh, unsigned char c)\r
2609 {\r
2610     struct do_ssh_init_state {\r
2611         int vslen;\r
2612         char version[10];\r
2613         char *vstring;\r
2614         int vstrsize;\r
2615         int i;\r
2616         int proto1, proto2;\r
2617     };\r
2618     crState(do_ssh_init_state);\r
2619 \r
2620     crBegin(ssh->do_ssh_init_crstate);\r
2621 \r
2622     /* Search for a line beginning with the string "SSH-" in the input. */\r
2623     for (;;) {\r
2624         if (c != 'S') goto no;\r
2625         crReturn(1);\r
2626         if (c != 'S') goto no;\r
2627         crReturn(1);\r
2628         if (c != 'H') goto no;\r
2629         crReturn(1);\r
2630         if (c != '-') goto no;\r
2631         break;\r
2632       no:\r
2633         while (c != '\012')\r
2634             crReturn(1);\r
2635         crReturn(1);\r
2636     }\r
2637 \r
2638     s->vstrsize = 16;\r
2639     s->vstring = snewn(s->vstrsize, char);\r
2640     strcpy(s->vstring, "SSH-");\r
2641     s->vslen = 4;\r
2642     s->i = 0;\r
2643     while (1) {\r
2644         crReturn(1);                   /* get another char */\r
2645         if (s->vslen >= s->vstrsize - 1) {\r
2646             s->vstrsize += 16;\r
2647             s->vstring = sresize(s->vstring, s->vstrsize, char);\r
2648         }\r
2649         s->vstring[s->vslen++] = c;\r
2650         if (s->i >= 0) {\r
2651             if (c == '-') {\r
2652                 s->version[s->i] = '\0';\r
2653                 s->i = -1;\r
2654             } else if (s->i < sizeof(s->version) - 1)\r
2655                 s->version[s->i++] = c;\r
2656         } else if (c == '\012')\r
2657             break;\r
2658     }\r
2659 \r
2660     ssh->agentfwd_enabled = FALSE;\r
2661     ssh->rdpkt2_state.incoming_sequence = 0;\r
2662 \r
2663     s->vstring[s->vslen] = 0;\r
2664     s->vstring[strcspn(s->vstring, "\015\012")] = '\0';/* remove EOL chars */\r
2665     logeventf(ssh, "Server version: %s", s->vstring);\r
2666     ssh_detect_bugs(ssh, s->vstring);\r
2667 \r
2668     /*\r
2669      * Decide which SSH protocol version to support.\r
2670      */\r
2671 \r
2672     /* Anything strictly below "2.0" means protocol 1 is supported. */\r
2673     s->proto1 = ssh_versioncmp(s->version, "2.0") < 0;\r
2674     /* Anything greater or equal to "1.99" means protocol 2 is supported. */\r
2675     s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;\r
2676 \r
2677     if (ssh->cfg.sshprot == 0 && !s->proto1) {\r
2678         bombout(("SSH protocol version 1 required by user but not provided by server"));\r
2679         crStop(0);\r
2680     }\r
2681     if (ssh->cfg.sshprot == 3 && !s->proto2) {\r
2682         bombout(("SSH protocol version 2 required by user but not provided by server"));\r
2683         crStop(0);\r
2684     }\r
2685 \r
2686     if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1))\r
2687         ssh->version = 2;\r
2688     else\r
2689         ssh->version = 1;\r
2690 \r
2691     logeventf(ssh, "Using SSH protocol version %d", ssh->version);\r
2692 \r
2693     /* Send the version string, if we haven't already */\r
2694     if (ssh->cfg.sshprot != 3)\r
2695         ssh_send_verstring(ssh, s->version);\r
2696 \r
2697     if (ssh->version == 2) {\r
2698         size_t len;\r
2699         /*\r
2700          * Record their version string.\r
2701          */\r
2702         len = strcspn(s->vstring, "\015\012");\r
2703         ssh->v_s = snewn(len + 1, char);\r
2704         memcpy(ssh->v_s, s->vstring, len);\r
2705         ssh->v_s[len] = 0;\r
2706             \r
2707         /*\r
2708          * Initialise SSH-2 protocol.\r
2709          */\r
2710         ssh->protocol = ssh2_protocol;\r
2711         ssh2_protocol_setup(ssh);\r
2712         ssh->s_rdpkt = ssh2_rdpkt;\r
2713     } else {\r
2714         /*\r
2715          * Initialise SSH-1 protocol.\r
2716          */\r
2717         ssh->protocol = ssh1_protocol;\r
2718         ssh1_protocol_setup(ssh);\r
2719         ssh->s_rdpkt = ssh1_rdpkt;\r
2720     }\r
2721     if (ssh->version == 2)\r
2722         do_ssh2_transport(ssh, NULL, -1, NULL);\r
2723 \r
2724     update_specials_menu(ssh->frontend);\r
2725     ssh->state = SSH_STATE_BEFORE_SIZE;\r
2726     ssh->pinger = pinger_new(&ssh->cfg, &ssh_backend, ssh);\r
2727 \r
2728     sfree(s->vstring);\r
2729 \r
2730     crFinish(0);\r
2731 }\r
2732 \r
2733 static void ssh_process_incoming_data(Ssh ssh,\r
2734                                       unsigned char **data, int *datalen)\r
2735 {\r
2736     struct Packet *pktin;\r
2737 \r
2738     pktin = ssh->s_rdpkt(ssh, data, datalen);\r
2739     if (pktin) {\r
2740         ssh->protocol(ssh, NULL, 0, pktin);\r
2741         ssh_free_packet(pktin);\r
2742     }\r
2743 }\r
2744 \r
2745 static void ssh_queue_incoming_data(Ssh ssh,\r
2746                                     unsigned char **data, int *datalen)\r
2747 {\r
2748     bufchain_add(&ssh->queued_incoming_data, *data, *datalen);\r
2749     *data += *datalen;\r
2750     *datalen = 0;\r
2751 }\r
2752 \r
2753 static void ssh_process_queued_incoming_data(Ssh ssh)\r
2754 {\r
2755     void *vdata;\r
2756     unsigned char *data;\r
2757     int len, origlen;\r
2758 \r
2759     while (!ssh->frozen && bufchain_size(&ssh->queued_incoming_data)) {\r
2760         bufchain_prefix(&ssh->queued_incoming_data, &vdata, &len);\r
2761         data = vdata;\r
2762         origlen = len;\r
2763 \r
2764         while (!ssh->frozen && len > 0)\r
2765             ssh_process_incoming_data(ssh, &data, &len);\r
2766 \r
2767         if (origlen > len)\r
2768             bufchain_consume(&ssh->queued_incoming_data, origlen - len);\r
2769     }\r
2770 }\r
2771 \r
2772 static void ssh_set_frozen(Ssh ssh, int frozen)\r
2773 {\r
2774     if (ssh->s)\r
2775         sk_set_frozen(ssh->s, frozen);\r
2776     ssh->frozen = frozen;\r
2777 }\r
2778 \r
2779 static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)\r
2780 {\r
2781     /* Log raw data, if we're in that mode. */\r
2782     if (ssh->logctx)\r
2783         log_packet(ssh->logctx, PKT_INCOMING, -1, NULL, data, datalen,\r
2784                    0, NULL, NULL);\r
2785 \r
2786     crBegin(ssh->ssh_gotdata_crstate);\r
2787 \r
2788     /*\r
2789      * To begin with, feed the characters one by one to the\r
2790      * protocol initialisation / selection function do_ssh_init().\r
2791      * When that returns 0, we're done with the initial greeting\r
2792      * exchange and can move on to packet discipline.\r
2793      */\r
2794     while (1) {\r
2795         int ret;                       /* need not be kept across crReturn */\r
2796         if (datalen == 0)\r
2797             crReturnV;                 /* more data please */\r
2798         ret = do_ssh_init(ssh, *data);\r
2799         data++;\r
2800         datalen--;\r
2801         if (ret == 0)\r
2802             break;\r
2803     }\r
2804 \r
2805     /*\r
2806      * We emerge from that loop when the initial negotiation is\r
2807      * over and we have selected an s_rdpkt function. Now pass\r
2808      * everything to s_rdpkt, and then pass the resulting packets\r
2809      * to the proper protocol handler.\r
2810      */\r
2811 \r
2812     while (1) {\r
2813         while (bufchain_size(&ssh->queued_incoming_data) > 0 || datalen > 0) {\r
2814             if (ssh->frozen) {\r
2815                 ssh_queue_incoming_data(ssh, &data, &datalen);\r
2816                 /* This uses up all data and cannot cause anything interesting\r
2817                  * to happen; indeed, for anything to happen at all, we must\r
2818                  * return, so break out. */\r
2819                 break;\r
2820             } else if (bufchain_size(&ssh->queued_incoming_data) > 0) {\r
2821                 /* This uses up some or all data, and may freeze the\r
2822                  * session. */\r
2823                 ssh_process_queued_incoming_data(ssh);\r
2824             } else {\r
2825                 /* This uses up some or all data, and may freeze the\r
2826                  * session. */\r
2827                 ssh_process_incoming_data(ssh, &data, &datalen);\r
2828             }\r
2829             /* FIXME this is probably EBW. */\r
2830             if (ssh->state == SSH_STATE_CLOSED)\r
2831                 return;\r
2832         }\r
2833         /* We're out of data. Go and get some more. */\r
2834         crReturnV;\r
2835     }\r
2836     crFinishV;\r
2837 }\r
2838 \r
2839 static int ssh_do_close(Ssh ssh, int notify_exit)\r
2840 {\r
2841     int ret = 0;\r
2842     struct ssh_channel *c;\r
2843 \r
2844     ssh->state = SSH_STATE_CLOSED;\r
2845     expire_timer_context(ssh);\r
2846     if (ssh->s) {\r
2847         sk_close(ssh->s);\r
2848         ssh->s = NULL;\r
2849         if (notify_exit)\r
2850             notify_remote_exit(ssh->frontend);\r
2851         else\r
2852             ret = 1;\r
2853     }\r
2854     /*\r
2855      * Now we must shut down any port- and X-forwarded channels going\r
2856      * through this connection.\r
2857      */\r
2858     if (ssh->channels) {\r
2859         while (NULL != (c = index234(ssh->channels, 0))) {\r
2860             switch (c->type) {\r
2861               case CHAN_X11:\r
2862                 x11_close(c->u.x11.s);\r
2863                 break;\r
2864               case CHAN_SOCKDATA:\r
2865               case CHAN_SOCKDATA_DORMANT:\r
2866                 pfd_close(c->u.pfd.s);\r
2867                 break;\r
2868             }\r
2869             del234(ssh->channels, c); /* moving next one to index 0 */\r
2870             if (ssh->version == 2)\r
2871                 bufchain_clear(&c->v.v2.outbuffer);\r
2872             sfree(c);\r
2873         }\r
2874     }\r
2875     /*\r
2876      * Go through port-forwardings, and close any associated\r
2877      * listening sockets.\r
2878      */\r
2879     if (ssh->portfwds) {\r
2880         struct ssh_portfwd *pf;\r
2881         while (NULL != (pf = index234(ssh->portfwds, 0))) {\r
2882             /* Dispose of any listening socket. */\r
2883             if (pf->local)\r
2884                 pfd_terminate(pf->local);\r
2885             del234(ssh->portfwds, pf); /* moving next one to index 0 */\r
2886             free_portfwd(pf);\r
2887         }\r
2888         freetree234(ssh->portfwds);\r
2889         ssh->portfwds = NULL;\r
2890     }\r
2891 \r
2892     return ret;\r
2893 }\r
2894 \r
2895 static void ssh_log(Plug plug, int type, SockAddr addr, int port,\r
2896                     const char *error_msg, int error_code)\r
2897 {\r
2898     Ssh ssh = (Ssh) plug;\r
2899     char addrbuf[256], *msg;\r
2900 \r
2901     sk_getaddr(addr, addrbuf, lenof(addrbuf));\r
2902 \r
2903     if (type == 0)\r
2904         msg = dupprintf("Connecting to %s port %d", addrbuf, port);\r
2905     else\r
2906         msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);\r
2907 \r
2908     logevent(msg);\r
2909     sfree(msg);\r
2910 }\r
2911 \r
2912 static int ssh_closing(Plug plug, const char *error_msg, int error_code,\r
2913                        int calling_back)\r
2914 {\r
2915     Ssh ssh = (Ssh) plug;\r
2916     int need_notify = ssh_do_close(ssh, FALSE);\r
2917 \r
2918     if (!error_msg) {\r
2919         if (!ssh->close_expected)\r
2920             error_msg = "Server unexpectedly closed network connection";\r
2921         else\r
2922             error_msg = "Server closed network connection";\r
2923     }\r
2924 \r
2925     if (ssh->close_expected && ssh->clean_exit && ssh->exitcode < 0)\r
2926         ssh->exitcode = 0;\r
2927 \r
2928     if (need_notify)\r
2929         notify_remote_exit(ssh->frontend);\r
2930 \r
2931     if (error_msg)\r
2932         logevent(error_msg);\r
2933     if (!ssh->close_expected || !ssh->clean_exit)\r
2934         connection_fatal(ssh->frontend, "%s", error_msg);\r
2935     return 0;\r
2936 }\r
2937 \r
2938 static int ssh_receive(Plug plug, int urgent, char *data, int len)\r
2939 {\r
2940     Ssh ssh = (Ssh) plug;\r
2941     ssh_gotdata(ssh, (unsigned char *)data, len);\r
2942     if (ssh->state == SSH_STATE_CLOSED) {\r
2943         ssh_do_close(ssh, TRUE);\r
2944         return 0;\r
2945     }\r
2946     return 1;\r
2947 }\r
2948 \r
2949 static void ssh_sent(Plug plug, int bufsize)\r
2950 {\r
2951     Ssh ssh = (Ssh) plug;\r
2952     /*\r
2953      * If the send backlog on the SSH socket itself clears, we\r
2954      * should unthrottle the whole world if it was throttled.\r
2955      */\r
2956     if (bufsize < SSH_MAX_BACKLOG)\r
2957         ssh_throttle_all(ssh, 0, bufsize);\r
2958 }\r
2959 \r
2960 /*\r
2961  * Connect to specified host and port.\r
2962  * Returns an error message, or NULL on success.\r
2963  * Also places the canonical host name into `realhost'. It must be\r
2964  * freed by the caller.\r
2965  */\r
2966 static const char *connect_to_host(Ssh ssh, char *host, int port,\r
2967                                    char **realhost, int nodelay, int keepalive)\r
2968 {\r
2969     static const struct plug_function_table fn_table = {\r
2970         ssh_log,\r
2971         ssh_closing,\r
2972         ssh_receive,\r
2973         ssh_sent,\r
2974         NULL\r
2975     };\r
2976 \r
2977     SockAddr addr;\r
2978     const char *err;\r
2979 \r
2980     if (*ssh->cfg.loghost) {\r
2981         char *colon;\r
2982 \r
2983         ssh->savedhost = dupstr(ssh->cfg.loghost);\r
2984         ssh->savedport = 22;           /* default ssh port */\r
2985 \r
2986         /*\r
2987          * A colon suffix on savedhost also lets us affect\r
2988          * savedport.\r
2989          * \r
2990          * (FIXME: do something about IPv6 address literals here.)\r
2991          */\r
2992         colon = strrchr(ssh->savedhost, ':');\r
2993         if (colon) {\r
2994             *colon++ = '\0';\r
2995             if (*colon)\r
2996                 ssh->savedport = atoi(colon);\r
2997         }\r
2998     } else {\r
2999         ssh->savedhost = dupstr(host);\r
3000         if (port < 0)\r
3001             port = 22;                 /* default ssh port */\r
3002         ssh->savedport = port;\r
3003     }\r
3004 \r
3005     /*\r
3006      * Try to find host.\r
3007      */\r
3008     logeventf(ssh, "Looking up host \"%s\"%s", host,\r
3009               (ssh->cfg.addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :\r
3010                (ssh->cfg.addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));\r
3011     addr = name_lookup(host, port, realhost, &ssh->cfg,\r
3012                        ssh->cfg.addressfamily);\r
3013     if ((err = sk_addr_error(addr)) != NULL) {\r
3014         sk_addr_free(addr);\r
3015         return err;\r
3016     }\r
3017     ssh->fullhostname = dupstr(*realhost);   /* save in case of GSSAPI */\r
3018 \r
3019     /*\r
3020      * Open socket.\r
3021      */\r
3022     ssh->fn = &fn_table;\r
3023     ssh->s = new_connection(addr, *realhost, port,\r
3024                             0, 1, nodelay, keepalive, (Plug) ssh, &ssh->cfg);\r
3025     if ((err = sk_socket_error(ssh->s)) != NULL) {\r
3026         ssh->s = NULL;\r
3027         notify_remote_exit(ssh->frontend);\r
3028         return err;\r
3029     }\r
3030 \r
3031     /*\r
3032      * If the SSH version number's fixed, set it now, and if it's SSH-2,\r
3033      * send the version string too.\r
3034      */\r
3035     if (ssh->cfg.sshprot == 0)\r
3036         ssh->version = 1;\r
3037     if (ssh->cfg.sshprot == 3) {\r
3038         ssh->version = 2;\r
3039         ssh_send_verstring(ssh, NULL);\r
3040     }\r
3041 \r
3042     /*\r
3043      * loghost, if configured, overrides realhost.\r
3044      */\r
3045     if (*ssh->cfg.loghost) {\r
3046         sfree(*realhost);\r
3047         *realhost = dupstr(ssh->cfg.loghost);\r
3048     }\r
3049 \r
3050     return NULL;\r
3051 }\r
3052 \r
3053 /*\r
3054  * Throttle or unthrottle the SSH connection.\r
3055  */\r
3056 static void ssh_throttle_conn(Ssh ssh, int adjust)\r
3057 {\r
3058     int old_count = ssh->conn_throttle_count;\r
3059     ssh->conn_throttle_count += adjust;\r
3060     assert(ssh->conn_throttle_count >= 0);\r
3061     if (ssh->conn_throttle_count && !old_count) {\r
3062         ssh_set_frozen(ssh, 1);\r
3063     } else if (!ssh->conn_throttle_count && old_count) {\r
3064         ssh_set_frozen(ssh, 0);\r
3065     }\r
3066 }\r
3067 \r
3068 /*\r
3069  * Throttle or unthrottle _all_ local data streams (for when sends\r
3070  * on the SSH connection itself back up).\r
3071  */\r
3072 static void ssh_throttle_all(Ssh ssh, int enable, int bufsize)\r
3073 {\r
3074     int i;\r
3075     struct ssh_channel *c;\r
3076 \r
3077     if (enable == ssh->throttled_all)\r
3078         return;\r
3079     ssh->throttled_all = enable;\r
3080     ssh->overall_bufsize = bufsize;\r
3081     if (!ssh->channels)\r
3082         return;\r
3083     for (i = 0; NULL != (c = index234(ssh->channels, i)); i++) {\r
3084         switch (c->type) {\r
3085           case CHAN_MAINSESSION:\r
3086             /*\r
3087              * This is treated separately, outside the switch.\r
3088              */\r
3089             break;\r
3090           case CHAN_X11:\r
3091             x11_override_throttle(c->u.x11.s, enable);\r
3092             break;\r
3093           case CHAN_AGENT:\r
3094             /* Agent channels require no buffer management. */\r
3095             break;\r
3096           case CHAN_SOCKDATA:\r
3097             pfd_override_throttle(c->u.pfd.s, enable);\r
3098             break;\r
3099         }\r
3100     }\r
3101 }\r
3102 \r
3103 static void ssh_agent_callback(void *sshv, void *reply, int replylen)\r
3104 {\r
3105     Ssh ssh = (Ssh) sshv;\r
3106 \r
3107     ssh->agent_response = reply;\r
3108     ssh->agent_response_len = replylen;\r
3109 \r
3110     if (ssh->version == 1)\r
3111         do_ssh1_login(ssh, NULL, -1, NULL);\r
3112     else\r
3113         do_ssh2_authconn(ssh, NULL, -1, NULL);\r
3114 }\r
3115 \r
3116 static void ssh_dialog_callback(void *sshv, int ret)\r
3117 {\r
3118     Ssh ssh = (Ssh) sshv;\r
3119 \r
3120     ssh->user_response = ret;\r
3121 \r
3122     if (ssh->version == 1)\r
3123         do_ssh1_login(ssh, NULL, -1, NULL);\r
3124     else\r
3125         do_ssh2_transport(ssh, NULL, -1, NULL);\r
3126 \r
3127     /*\r
3128      * This may have unfrozen the SSH connection, so do a\r
3129      * queued-data run.\r
3130      */\r
3131     ssh_process_queued_incoming_data(ssh);\r
3132 }\r
3133 \r
3134 static void ssh_agentf_callback(void *cv, void *reply, int replylen)\r
3135 {\r
3136     struct ssh_channel *c = (struct ssh_channel *)cv;\r
3137     Ssh ssh = c->ssh;\r
3138     void *sentreply = reply;\r
3139 \r
3140     if (!sentreply) {\r
3141         /* Fake SSH_AGENT_FAILURE. */\r
3142         sentreply = "\0\0\0\1\5";\r
3143         replylen = 5;\r
3144     }\r
3145     if (ssh->version == 2) {\r
3146         ssh2_add_channel_data(c, sentreply, replylen);\r
3147         ssh2_try_send(c);\r
3148     } else {\r
3149         send_packet(ssh, SSH1_MSG_CHANNEL_DATA,\r
3150                     PKT_INT, c->remoteid,\r
3151                     PKT_INT, replylen,\r
3152                     PKTT_DATA,\r
3153                     PKT_DATA, sentreply, replylen,\r
3154                     PKTT_OTHER,\r
3155                     PKT_END);\r
3156     }\r
3157     if (reply)\r
3158         sfree(reply);\r
3159 }\r
3160 \r
3161 /*\r
3162  * Client-initiated disconnection. Send a DISCONNECT if `wire_reason'\r
3163  * non-NULL, otherwise just close the connection. `client_reason' == NULL\r
3164  * => log `wire_reason'.\r
3165  */\r
3166 static void ssh_disconnect(Ssh ssh, char *client_reason, char *wire_reason,\r
3167                            int code, int clean_exit)\r
3168 {\r
3169     char *error;\r
3170     if (!client_reason)\r
3171         client_reason = wire_reason;\r
3172     if (client_reason)\r
3173         error = dupprintf("Disconnected: %s", client_reason);\r
3174     else\r
3175         error = dupstr("Disconnected");\r
3176     if (wire_reason) {\r
3177         if (ssh->version == 1) {\r
3178             send_packet(ssh, SSH1_MSG_DISCONNECT, PKT_STR, wire_reason,\r
3179                         PKT_END);\r
3180         } else if (ssh->version == 2) {\r
3181             struct Packet *pktout = ssh2_pkt_init(SSH2_MSG_DISCONNECT);\r
3182             ssh2_pkt_adduint32(pktout, code);\r
3183             ssh2_pkt_addstring(pktout, wire_reason);\r
3184             ssh2_pkt_addstring(pktout, "en");   /* language tag */\r
3185             ssh2_pkt_send_noqueue(ssh, pktout);\r
3186         }\r
3187     }\r
3188     ssh->close_expected = TRUE;\r
3189     ssh->clean_exit = clean_exit;\r
3190     ssh_closing((Plug)ssh, error, 0, 0);\r
3191     sfree(error);\r
3192 }\r
3193 \r
3194 /*\r
3195  * Handle the key exchange and user authentication phases.\r
3196  */\r
3197 static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,\r
3198                          struct Packet *pktin)\r
3199 {\r
3200     int i, j, ret;\r
3201     unsigned char cookie[8], *ptr;\r
3202     struct RSAKey servkey, hostkey;\r
3203     struct MD5Context md5c;\r
3204     struct do_ssh1_login_state {\r
3205         int len;\r
3206         unsigned char *rsabuf, *keystr1, *keystr2;\r
3207         unsigned long supported_ciphers_mask, supported_auths_mask;\r
3208         int tried_publickey, tried_agent;\r
3209         int tis_auth_refused, ccard_auth_refused;\r
3210         unsigned char session_id[16];\r
3211         int cipher_type;\r
3212         char username[100];\r
3213         void *publickey_blob;\r
3214         int publickey_bloblen;\r
3215         char *publickey_comment;\r
3216         int publickey_encrypted;\r
3217         prompts_t *cur_prompt;\r
3218         char c;\r
3219         int pwpkt_type;\r
3220         unsigned char request[5], *response, *p;\r
3221         int responselen;\r
3222         int keyi, nkeys;\r
3223         int authed;\r
3224         struct RSAKey key;\r
3225         Bignum challenge;\r
3226         char *commentp;\r
3227         int commentlen;\r
3228         int dlgret;\r
3229     };\r
3230     crState(do_ssh1_login_state);\r
3231 \r
3232     crBegin(ssh->do_ssh1_login_crstate);\r
3233 \r
3234     if (!pktin)\r
3235         crWaitUntil(pktin);\r
3236 \r
3237     if (pktin->type != SSH1_SMSG_PUBLIC_KEY) {\r
3238         bombout(("Public key packet not received"));\r
3239         crStop(0);\r
3240     }\r
3241 \r
3242     logevent("Received public keys");\r
3243 \r
3244     ptr = ssh_pkt_getdata(pktin, 8);\r
3245     if (!ptr) {\r
3246         bombout(("SSH-1 public key packet stopped before random cookie"));\r
3247         crStop(0);\r
3248     }\r
3249     memcpy(cookie, ptr, 8);\r
3250 \r
3251     if (!ssh1_pkt_getrsakey(pktin, &servkey, &s->keystr1) ||\r
3252         !ssh1_pkt_getrsakey(pktin, &hostkey, &s->keystr2)) {    \r
3253         bombout(("Failed to read SSH-1 public keys from public key packet"));\r
3254         crStop(0);\r
3255     }\r
3256 \r
3257     /*\r
3258      * Log the host key fingerprint.\r
3259      */\r
3260     {\r
3261         char logmsg[80];\r
3262         logevent("Host key fingerprint is:");\r
3263         strcpy(logmsg, "      ");\r
3264         hostkey.comment = NULL;\r
3265         rsa_fingerprint(logmsg + strlen(logmsg),\r
3266                         sizeof(logmsg) - strlen(logmsg), &hostkey);\r
3267         logevent(logmsg);\r
3268     }\r
3269 \r
3270     ssh->v1_remote_protoflags = ssh_pkt_getuint32(pktin);\r
3271     s->supported_ciphers_mask = ssh_pkt_getuint32(pktin);\r
3272     s->supported_auths_mask = ssh_pkt_getuint32(pktin);\r
3273     if ((ssh->remote_bugs & BUG_CHOKES_ON_RSA))\r
3274         s->supported_auths_mask &= ~(1 << SSH1_AUTH_RSA);\r
3275 \r
3276     ssh->v1_local_protoflags =\r
3277         ssh->v1_remote_protoflags & SSH1_PROTOFLAGS_SUPPORTED;\r
3278     ssh->v1_local_protoflags |= SSH1_PROTOFLAG_SCREEN_NUMBER;\r
3279 \r
3280     MD5Init(&md5c);\r
3281     MD5Update(&md5c, s->keystr2, hostkey.bytes);\r
3282     MD5Update(&md5c, s->keystr1, servkey.bytes);\r
3283     MD5Update(&md5c, cookie, 8);\r
3284     MD5Final(s->session_id, &md5c);\r
3285 \r
3286     for (i = 0; i < 32; i++)\r
3287         ssh->session_key[i] = random_byte();\r
3288 \r
3289     /*\r
3290      * Verify that the `bits' and `bytes' parameters match.\r
3291      */\r
3292     if (hostkey.bits > hostkey.bytes * 8 ||\r
3293         servkey.bits > servkey.bytes * 8) {\r
3294         bombout(("SSH-1 public keys were badly formatted"));\r
3295         crStop(0);\r
3296     }\r
3297 \r
3298     s->len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);\r
3299 \r
3300     s->rsabuf = snewn(s->len, unsigned char);\r
3301 \r
3302     /*\r
3303      * Verify the host key.\r
3304      */\r
3305     {\r
3306         /*\r
3307          * First format the key into a string.\r
3308          */\r
3309         int len = rsastr_len(&hostkey);\r
3310         char fingerprint[100];\r
3311         char *keystr = snewn(len, char);\r
3312         rsastr_fmt(keystr, &hostkey);\r
3313         rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);\r
3314 \r
3315         ssh_set_frozen(ssh, 1);\r
3316         s->dlgret = verify_ssh_host_key(ssh->frontend,\r
3317                                         ssh->savedhost, ssh->savedport,\r
3318                                         "rsa", keystr, fingerprint,\r
3319                                         ssh_dialog_callback, ssh);\r
3320         sfree(keystr);\r
3321         if (s->dlgret < 0) {\r
3322             do {\r
3323                 crReturn(0);\r
3324                 if (pktin) {\r
3325                     bombout(("Unexpected data from server while waiting"\r
3326                              " for user host key response"));\r
3327                     crStop(0);\r
3328                 }\r
3329             } while (pktin || inlen > 0);\r
3330             s->dlgret = ssh->user_response;\r
3331         }\r
3332         ssh_set_frozen(ssh, 0);\r
3333 \r
3334         if (s