In Unix PuTTYgen, existing SSH-1 key comments were coming out as "(null)"
[u/mdw/putty] / ssh.c
CommitLineData
374330e2 1#include <stdio.h>
2#include <stdlib.h>
fb09bf1c 3#include <stdarg.h>
4#include <assert.h>
374330e2 5
6#include "putty.h"
dacbd0e8 7#include "tree234.h"
fb09bf1c 8#include "ssh.h"
374330e2 9
10#ifndef FALSE
11#define FALSE 0
12#endif
13#ifndef TRUE
14#define TRUE 1
15#endif
16
32874aea 17#define SSH1_MSG_DISCONNECT 1 /* 0x1 */
18#define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */
19#define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */
20#define SSH1_CMSG_USER 4 /* 0x4 */
21#define SSH1_CMSG_AUTH_RSA 6 /* 0x6 */
22#define SSH1_SMSG_AUTH_RSA_CHALLENGE 7 /* 0x7 */
23#define SSH1_CMSG_AUTH_RSA_RESPONSE 8 /* 0x8 */
24#define SSH1_CMSG_AUTH_PASSWORD 9 /* 0x9 */
25#define SSH1_CMSG_REQUEST_PTY 10 /* 0xa */
26#define SSH1_CMSG_WINDOW_SIZE 11 /* 0xb */
27#define SSH1_CMSG_EXEC_SHELL 12 /* 0xc */
28#define SSH1_CMSG_EXEC_CMD 13 /* 0xd */
29#define SSH1_SMSG_SUCCESS 14 /* 0xe */
30#define SSH1_SMSG_FAILURE 15 /* 0xf */
31#define SSH1_CMSG_STDIN_DATA 16 /* 0x10 */
32#define SSH1_SMSG_STDOUT_DATA 17 /* 0x11 */
33#define SSH1_SMSG_STDERR_DATA 18 /* 0x12 */
34#define SSH1_CMSG_EOF 19 /* 0x13 */
35#define SSH1_SMSG_EXIT_STATUS 20 /* 0x14 */
36#define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* 0x15 */
37#define SSH1_MSG_CHANNEL_OPEN_FAILURE 22 /* 0x16 */
38#define SSH1_MSG_CHANNEL_DATA 23 /* 0x17 */
39#define SSH1_MSG_CHANNEL_CLOSE 24 /* 0x18 */
40#define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* 0x19 */
41#define SSH1_SMSG_X11_OPEN 27 /* 0x1b */
42#define SSH1_CMSG_PORT_FORWARD_REQUEST 28 /* 0x1c */
43#define SSH1_MSG_PORT_OPEN 29 /* 0x1d */
44#define SSH1_CMSG_AGENT_REQUEST_FORWARDING 30 /* 0x1e */
45#define SSH1_SMSG_AGENT_OPEN 31 /* 0x1f */
46#define SSH1_MSG_IGNORE 32 /* 0x20 */
47#define SSH1_CMSG_EXIT_CONFIRMATION 33 /* 0x21 */
48#define SSH1_CMSG_X11_REQUEST_FORWARDING 34 /* 0x22 */
49#define SSH1_CMSG_AUTH_RHOSTS_RSA 35 /* 0x23 */
50#define SSH1_MSG_DEBUG 36 /* 0x24 */
51#define SSH1_CMSG_REQUEST_COMPRESSION 37 /* 0x25 */
52#define SSH1_CMSG_AUTH_TIS 39 /* 0x27 */
53#define SSH1_SMSG_AUTH_TIS_CHALLENGE 40 /* 0x28 */
54#define SSH1_CMSG_AUTH_TIS_RESPONSE 41 /* 0x29 */
55#define SSH1_CMSG_AUTH_CCARD 70 /* 0x46 */
56#define SSH1_SMSG_AUTH_CCARD_CHALLENGE 71 /* 0x47 */
57#define SSH1_CMSG_AUTH_CCARD_RESPONSE 72 /* 0x48 */
58
59#define SSH1_AUTH_TIS 5 /* 0x5 */
60#define SSH1_AUTH_CCARD 16 /* 0x10 */
61
62#define SSH1_PROTOFLAG_SCREEN_NUMBER 1 /* 0x1 */
b96dc54c 63/* Mask for protoflags we will echo back to server if seen */
32874aea 64#define SSH1_PROTOFLAGS_SUPPORTED 0 /* 0x1 */
65
66#define SSH2_MSG_DISCONNECT 1 /* 0x1 */
67#define SSH2_MSG_IGNORE 2 /* 0x2 */
68#define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
69#define SSH2_MSG_DEBUG 4 /* 0x4 */
70#define SSH2_MSG_SERVICE_REQUEST 5 /* 0x5 */
71#define SSH2_MSG_SERVICE_ACCEPT 6 /* 0x6 */
72#define SSH2_MSG_KEXINIT 20 /* 0x14 */
73#define SSH2_MSG_NEWKEYS 21 /* 0x15 */
74#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
75#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
76#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
77#define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
78#define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
79#define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */
80#define SSH2_MSG_USERAUTH_REQUEST 50 /* 0x32 */
81#define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
82#define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */
83#define SSH2_MSG_USERAUTH_BANNER 53 /* 0x35 */
84#define SSH2_MSG_USERAUTH_PK_OK 60 /* 0x3c */
85#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 /* 0x3c */
761187b6 86#define SSH2_MSG_USERAUTH_INFO_REQUEST 60 /* 0x3c */
87#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* 0x3d */
32874aea 88#define SSH2_MSG_GLOBAL_REQUEST 80 /* 0x50 */
89#define SSH2_MSG_REQUEST_SUCCESS 81 /* 0x51 */
90#define SSH2_MSG_REQUEST_FAILURE 82 /* 0x52 */
91#define SSH2_MSG_CHANNEL_OPEN 90 /* 0x5a */
92#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 /* 0x5b */
93#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 /* 0x5c */
94#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 /* 0x5d */
95#define SSH2_MSG_CHANNEL_DATA 94 /* 0x5e */
96#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 /* 0x5f */
97#define SSH2_MSG_CHANNEL_EOF 96 /* 0x60 */
98#define SSH2_MSG_CHANNEL_CLOSE 97 /* 0x61 */
99#define SSH2_MSG_CHANNEL_REQUEST 98 /* 0x62 */
100#define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
101#define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */
102
00db133f 103/*
104 * Packet type contexts, so that ssh2_pkt_type can correctly decode
105 * the ambiguous type numbers back into the correct type strings.
106 */
d1aaf71d 107#define SSH2_PKTCTX_DHGROUP 0x0001
00db133f 108#define SSH2_PKTCTX_DHGEX 0x0002
149d2abc 109#define SSH2_PKTCTX_KEX_MASK 0x000F
00db133f 110#define SSH2_PKTCTX_PUBLICKEY 0x0010
111#define SSH2_PKTCTX_PASSWORD 0x0020
112#define SSH2_PKTCTX_KBDINTER 0x0040
113#define SSH2_PKTCTX_AUTH_MASK 0x00F0
114
32874aea 115#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */
116#define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */
117#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */
118#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 /* 0x4 */
119#define SSH2_DISCONNECT_MAC_ERROR 5 /* 0x5 */
120#define SSH2_DISCONNECT_COMPRESSION_ERROR 6 /* 0x6 */
121#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 /* 0x7 */
122#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 /* 0x8 */
123#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 /* 0x9 */
124#define SSH2_DISCONNECT_CONNECTION_LOST 10 /* 0xa */
125#define SSH2_DISCONNECT_BY_APPLICATION 11 /* 0xb */
126#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 /* 0xc */
127#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 /* 0xd */
128#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 /* 0xe */
129#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* 0xf */
38c4a8da 130
131static const char *const ssh2_disconnect_reasons[] = {
132 NULL,
afb4d0dc 133 "host not allowed to connect",
134 "protocol error",
135 "key exchange failed",
136 "host authentication failed",
1da38d29 137 "MAC error",
afb4d0dc 138 "compression error",
139 "service not available",
140 "protocol version not supported",
141 "host key not verifiable",
142 "connection lost",
143 "by application",
144 "too many connections",
145 "auth cancelled by user",
146 "no more auth methods available",
147 "illegal user name",
38c4a8da 148};
9005f3ba 149
32874aea 150#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 /* 0x1 */
151#define SSH2_OPEN_CONNECT_FAILED 2 /* 0x2 */
152#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 /* 0x3 */
153#define SSH2_OPEN_RESOURCE_SHORTAGE 4 /* 0x4 */
d211621f 154
32874aea 155#define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
fb09bf1c 156
7d503c31 157/*
158 * Various remote-bug flags.
159 */
160#define BUG_CHOKES_ON_SSH1_IGNORE 1
161#define BUG_SSH2_HMAC 2
bd358db1 162#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
0df73905 163#define BUG_CHOKES_ON_RSA 8
1dd353b5 164#define BUG_SSH2_RSA_PADDING 16
088bde77 165#define BUG_SSH2_DERIVEKEY 32
f382c87d 166#define BUG_SSH2_REKEY 64
dda87a28 167#define BUG_SSH2_PK_SESSIONID 128
bd358db1 168
c6ccd5c2 169/*
170 * Codes for terminal modes.
171 * Most of these are the same in SSH-1 and SSH-2.
172 * This list is derived from draft-ietf-secsh-connect-25 and
173 * SSH-1 RFC-1.2.31.
174 */
175static const struct {
176 const char* const mode;
177 int opcode;
178 enum { TTY_OP_CHAR, TTY_OP_BOOL } type;
179} ssh_ttymodes[] = {
180 /* "V" prefix discarded for special characters relative to SSH specs */
181 { "INTR", 1, TTY_OP_CHAR },
182 { "QUIT", 2, TTY_OP_CHAR },
183 { "ERASE", 3, TTY_OP_CHAR },
184 { "KILL", 4, TTY_OP_CHAR },
185 { "EOF", 5, TTY_OP_CHAR },
186 { "EOL", 6, TTY_OP_CHAR },
187 { "EOL2", 7, TTY_OP_CHAR },
188 { "START", 8, TTY_OP_CHAR },
189 { "STOP", 9, TTY_OP_CHAR },
190 { "SUSP", 10, TTY_OP_CHAR },
191 { "DSUSP", 11, TTY_OP_CHAR },
192 { "REPRINT", 12, TTY_OP_CHAR },
193 { "WERASE", 13, TTY_OP_CHAR },
194 { "LNEXT", 14, TTY_OP_CHAR },
195 { "FLUSH", 15, TTY_OP_CHAR },
196 { "SWTCH", 16, TTY_OP_CHAR },
197 { "STATUS", 17, TTY_OP_CHAR },
198 { "DISCARD", 18, TTY_OP_CHAR },
199 { "IGNPAR", 30, TTY_OP_BOOL },
200 { "PARMRK", 31, TTY_OP_BOOL },
201 { "INPCK", 32, TTY_OP_BOOL },
202 { "ISTRIP", 33, TTY_OP_BOOL },
203 { "INLCR", 34, TTY_OP_BOOL },
204 { "IGNCR", 35, TTY_OP_BOOL },
205 { "ICRNL", 36, TTY_OP_BOOL },
206 { "IUCLC", 37, TTY_OP_BOOL },
207 { "IXON", 38, TTY_OP_BOOL },
208 { "IXANY", 39, TTY_OP_BOOL },
209 { "IXOFF", 40, TTY_OP_BOOL },
210 { "IMAXBEL", 41, TTY_OP_BOOL },
211 { "ISIG", 50, TTY_OP_BOOL },
212 { "ICANON", 51, TTY_OP_BOOL },
213 { "XCASE", 52, TTY_OP_BOOL },
214 { "ECHO", 53, TTY_OP_BOOL },
215 { "ECHOE", 54, TTY_OP_BOOL },
216 { "ECHOK", 55, TTY_OP_BOOL },
217 { "ECHONL", 56, TTY_OP_BOOL },
218 { "NOFLSH", 57, TTY_OP_BOOL },
219 { "TOSTOP", 58, TTY_OP_BOOL },
220 { "IEXTEN", 59, TTY_OP_BOOL },
221 { "ECHOCTL", 60, TTY_OP_BOOL },
222 { "ECHOKE", 61, TTY_OP_BOOL },
223 { "PENDIN", 62, TTY_OP_BOOL }, /* XXX is this a real mode? */
224 { "OPOST", 70, TTY_OP_BOOL },
225 { "OLCUC", 71, TTY_OP_BOOL },
226 { "ONLCR", 72, TTY_OP_BOOL },
227 { "OCRNL", 73, TTY_OP_BOOL },
228 { "ONOCR", 74, TTY_OP_BOOL },
229 { "ONLRET", 75, TTY_OP_BOOL },
230 { "CS7", 90, TTY_OP_BOOL },
231 { "CS8", 91, TTY_OP_BOOL },
232 { "PARENB", 92, TTY_OP_BOOL },
233 { "PARODD", 93, TTY_OP_BOOL }
234};
235
236/* Miscellaneous other tty-related constants. */
237#define SSH_TTY_OP_END 0
238/* The opcodes for ISPEED/OSPEED differ between SSH-1 and SSH-2. */
239#define SSH1_TTY_OP_ISPEED 192
240#define SSH1_TTY_OP_OSPEED 193
241#define SSH2_TTY_OP_ISPEED 128
242#define SSH2_TTY_OP_OSPEED 129
243
244/* Helper functions for parsing tty-related config. */
245static unsigned int ssh_tty_parse_specchar(char *s)
246{
247 unsigned int ret;
248 if (*s) {
249 char *next = NULL;
250 ret = ctrlparse(s, &next);
251 if (!next) ret = s[0];
252 } else {
253 ret = 255; /* special value meaning "don't set" */
254 }
255 return ret;
256}
257static unsigned int ssh_tty_parse_boolean(char *s)
258{
259 if (stricmp(s, "yes") == 0 ||
260 stricmp(s, "on") == 0 ||
261 stricmp(s, "true") == 0 ||
262 stricmp(s, "+") == 0)
263 return 1; /* true */
264 else if (stricmp(s, "no") == 0 ||
265 stricmp(s, "off") == 0 ||
266 stricmp(s, "false") == 0 ||
267 stricmp(s, "-") == 0)
268 return 0; /* false */
269 else
270 return (atoi(s) != 0);
271}
272
00db133f 273#define translate(x) if (type == x) return #x
51470298 274#define translatec(x,ctx) if (type == x && (pkt_ctx & ctx)) return #x
ae9ae89f 275static char *ssh1_pkt_type(int type)
00db133f 276{
277 translate(SSH1_MSG_DISCONNECT);
278 translate(SSH1_SMSG_PUBLIC_KEY);
279 translate(SSH1_CMSG_SESSION_KEY);
280 translate(SSH1_CMSG_USER);
281 translate(SSH1_CMSG_AUTH_RSA);
282 translate(SSH1_SMSG_AUTH_RSA_CHALLENGE);
283 translate(SSH1_CMSG_AUTH_RSA_RESPONSE);
284 translate(SSH1_CMSG_AUTH_PASSWORD);
285 translate(SSH1_CMSG_REQUEST_PTY);
286 translate(SSH1_CMSG_WINDOW_SIZE);
287 translate(SSH1_CMSG_EXEC_SHELL);
288 translate(SSH1_CMSG_EXEC_CMD);
289 translate(SSH1_SMSG_SUCCESS);
290 translate(SSH1_SMSG_FAILURE);
291 translate(SSH1_CMSG_STDIN_DATA);
292 translate(SSH1_SMSG_STDOUT_DATA);
293 translate(SSH1_SMSG_STDERR_DATA);
294 translate(SSH1_CMSG_EOF);
295 translate(SSH1_SMSG_EXIT_STATUS);
296 translate(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
297 translate(SSH1_MSG_CHANNEL_OPEN_FAILURE);
298 translate(SSH1_MSG_CHANNEL_DATA);
299 translate(SSH1_MSG_CHANNEL_CLOSE);
300 translate(SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION);
301 translate(SSH1_SMSG_X11_OPEN);
302 translate(SSH1_CMSG_PORT_FORWARD_REQUEST);
303 translate(SSH1_MSG_PORT_OPEN);
304 translate(SSH1_CMSG_AGENT_REQUEST_FORWARDING);
305 translate(SSH1_SMSG_AGENT_OPEN);
306 translate(SSH1_MSG_IGNORE);
307 translate(SSH1_CMSG_EXIT_CONFIRMATION);
308 translate(SSH1_CMSG_X11_REQUEST_FORWARDING);
309 translate(SSH1_CMSG_AUTH_RHOSTS_RSA);
310 translate(SSH1_MSG_DEBUG);
311 translate(SSH1_CMSG_REQUEST_COMPRESSION);
312 translate(SSH1_CMSG_AUTH_TIS);
313 translate(SSH1_SMSG_AUTH_TIS_CHALLENGE);
314 translate(SSH1_CMSG_AUTH_TIS_RESPONSE);
315 translate(SSH1_CMSG_AUTH_CCARD);
316 translate(SSH1_SMSG_AUTH_CCARD_CHALLENGE);
317 translate(SSH1_CMSG_AUTH_CCARD_RESPONSE);
318 return "unknown";
319}
ae9ae89f 320static char *ssh2_pkt_type(int pkt_ctx, int type)
00db133f 321{
322 translate(SSH2_MSG_DISCONNECT);
323 translate(SSH2_MSG_IGNORE);
324 translate(SSH2_MSG_UNIMPLEMENTED);
325 translate(SSH2_MSG_DEBUG);
326 translate(SSH2_MSG_SERVICE_REQUEST);
327 translate(SSH2_MSG_SERVICE_ACCEPT);
328 translate(SSH2_MSG_KEXINIT);
329 translate(SSH2_MSG_NEWKEYS);
d1aaf71d 330 translatec(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);
331 translatec(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);
00db133f 332 translatec(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);
333 translatec(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);
334 translatec(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);
335 translatec(SSH2_MSG_KEX_DH_GEX_REPLY, SSH2_PKTCTX_DHGEX);
336 translate(SSH2_MSG_USERAUTH_REQUEST);
337 translate(SSH2_MSG_USERAUTH_FAILURE);
338 translate(SSH2_MSG_USERAUTH_SUCCESS);
339 translate(SSH2_MSG_USERAUTH_BANNER);
340 translatec(SSH2_MSG_USERAUTH_PK_OK, SSH2_PKTCTX_PUBLICKEY);
341 translatec(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, SSH2_PKTCTX_PASSWORD);
342 translatec(SSH2_MSG_USERAUTH_INFO_REQUEST, SSH2_PKTCTX_KBDINTER);
343 translatec(SSH2_MSG_USERAUTH_INFO_RESPONSE, SSH2_PKTCTX_KBDINTER);
344 translate(SSH2_MSG_GLOBAL_REQUEST);
345 translate(SSH2_MSG_REQUEST_SUCCESS);
346 translate(SSH2_MSG_REQUEST_FAILURE);
347 translate(SSH2_MSG_CHANNEL_OPEN);
348 translate(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
349 translate(SSH2_MSG_CHANNEL_OPEN_FAILURE);
350 translate(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
351 translate(SSH2_MSG_CHANNEL_DATA);
352 translate(SSH2_MSG_CHANNEL_EXTENDED_DATA);
353 translate(SSH2_MSG_CHANNEL_EOF);
354 translate(SSH2_MSG_CHANNEL_CLOSE);
355 translate(SSH2_MSG_CHANNEL_REQUEST);
356 translate(SSH2_MSG_CHANNEL_SUCCESS);
357 translate(SSH2_MSG_CHANNEL_FAILURE);
358 return "unknown";
359}
360#undef translate
361#undef translatec
7d503c31 362
9a10ecf4 363/* Enumeration values for fields in SSH-1 packets */
364enum {
365 PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,
366 /* These values are for communicating relevant semantics of
367 * fields to the packet logging code. */
368 PKTT_OTHER, PKTT_PASSWORD, PKTT_DATA
369};
972a41c8 370
acddebd9 371/*
372 * Coroutine mechanics for the sillier bits of the code. If these
373 * macros look impenetrable to you, you might find it helpful to
374 * read
375 *
376 * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
377 *
378 * which explains the theory behind these macros.
b624d1e6 379 *
380 * In particular, if you are getting `case expression not constant'
381 * errors when building with MS Visual Studio, this is because MS's
382 * Edit and Continue debugging feature causes their compiler to
383 * violate ANSI C. To disable Edit and Continue debugging:
384 *
385 * - right-click ssh.c in the FileView
386 * - click Settings
387 * - select the C/C++ tab and the General category
388 * - under `Debug info:', select anything _other_ than `Program
389 * Database for Edit and Continue'.
acddebd9 390 */
51470298 391#define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
392#define crState(t) \
393 struct t *s; \
3d88e64d 394 if (!ssh->t) ssh->t = snew(struct t); \
51470298 395 s = ssh->t;
396#define crFinish(z) } *crLine = 0; return (z); }
397#define crFinishV } *crLine = 0; return; }
374330e2 398#define crReturn(z) \
399 do {\
51470298 400 *crLine =__LINE__; return (z); case __LINE__:;\
374330e2 401 } while (0)
402#define crReturnV \
403 do {\
51470298 404 *crLine=__LINE__; return; case __LINE__:;\
374330e2 405 } while (0)
51470298 406#define crStop(z) do{ *crLine = 0; return (z); }while(0)
407#define crStopV do{ *crLine = 0; return; }while(0)
fb09bf1c 408#define crWaitUntil(c) do { crReturn(0); } while (!(c))
7cca0d81 409#define crWaitUntilV(c) do { crReturnV; } while (!(c))
374330e2 410
51470298 411typedef struct ssh_tag *Ssh;
ff3187f6 412struct Packet;
413
dacd8872 414static struct Packet *ssh1_pkt_init(int pkt_type);
ff3187f6 415static struct Packet *ssh2_pkt_init(int pkt_type);
dacd8872 416static void ssh_pkt_ensure(struct Packet *, int length);
417static void ssh_pkt_adddata(struct Packet *, void *data, int len);
418static void ssh_pkt_addbyte(struct Packet *, unsigned char value);
ff3187f6 419static void ssh2_pkt_addbool(struct Packet *, unsigned char value);
dacd8872 420static void ssh_pkt_adduint32(struct Packet *, unsigned long value);
421static void ssh_pkt_addstring_start(struct Packet *);
422static void ssh_pkt_addstring_str(struct Packet *, char *data);
423static void ssh_pkt_addstring_data(struct Packet *, char *data, int len);
424static void ssh_pkt_addstring(struct Packet *, char *data);
d8baa528 425static unsigned char *ssh2_mpint_fmt(Bignum b, int *len);
dacd8872 426static void ssh1_pkt_addmp(struct Packet *, Bignum b);
ff3187f6 427static void ssh2_pkt_addmp(struct Packet *, Bignum b);
428static int ssh2_pkt_construct(Ssh, struct Packet *);
429static void ssh2_pkt_send(Ssh, struct Packet *);
590f6a5f 430static void ssh2_pkt_send_noqueue(Ssh, struct Packet *);
ff3187f6 431static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
432 struct Packet *pktin);
433static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
434 struct Packet *pktin);
3d63ca2e 435
5471d09a 436/*
437 * Buffer management constants. There are several of these for
438 * various different purposes:
439 *
440 * - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
441 * on a local data stream before we throttle the whole SSH
2e85c969 442 * connection (in SSH-1 only). Throttling the whole connection is
5471d09a 443 * pretty drastic so we set this high in the hope it won't
444 * happen very often.
445 *
446 * - SSH_MAX_BACKLOG is the amount of backlog that must build up
447 * on the SSH connection itself before we defensively throttle
448 * _all_ local data streams. This is pretty drastic too (though
2e85c969 449 * thankfully unlikely in SSH-2 since the window mechanism should
5471d09a 450 * ensure that the server never has any need to throttle its end
451 * of the connection), so we set this high as well.
452 *
2e85c969 453 * - OUR_V2_WINSIZE is the maximum window size we present on SSH-2
5471d09a 454 * channels.
455 */
456
457#define SSH1_BUFFER_LIMIT 32768
458#define SSH_MAX_BACKLOG 32768
459#define OUR_V2_WINSIZE 16384
954d5c5a 460#define OUR_V2_MAXPKT 0x4000UL
d74d141c 461
85cc02bb 462const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss };
e5574168 463
8b2715b2 464const static struct ssh_mac *macs[] = {
6668a75e 465 &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5
32874aea 466};
8b2715b2 467const static struct ssh_mac *buggymacs[] = {
6668a75e 468 &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5
32874aea 469};
e5574168 470
5366aed8 471static void *ssh_comp_none_init(void)
472{
473 return NULL;
474}
475static void ssh_comp_none_cleanup(void *handle)
32874aea 476{
477}
5366aed8 478static int ssh_comp_none_block(void *handle, unsigned char *block, int len,
32874aea 479 unsigned char **outblock, int *outlen)
480{
481 return 0;
482}
5366aed8 483static int ssh_comp_none_disable(void *handle)
32874aea 484{
4ba9b64b 485 return 0;
486}
57476f6b 487const static struct ssh_compress ssh_comp_none = {
4ba9b64b 488 "none",
5366aed8 489 ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
490 ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
491 ssh_comp_none_disable, NULL
e5574168 492};
4ba9b64b 493extern const struct ssh_compress ssh_zlib;
494const static struct ssh_compress *compressions[] = {
32874aea 495 &ssh_zlib, &ssh_comp_none
496};
374330e2 497
32874aea 498enum { /* channel types */
783415f8 499 CHAN_MAINSESSION,
500 CHAN_X11,
501 CHAN_AGENT,
bc240b21 502 CHAN_SOCKDATA,
503 CHAN_SOCKDATA_DORMANT /* one the remote hasn't confirmed */
783415f8 504};
505
dacbd0e8 506/*
507 * 2-3-4 tree storing channels.
508 */
509struct ssh_channel {
51470298 510 Ssh ssh; /* pointer back to main context */
d211621f 511 unsigned remoteid, localid;
dacbd0e8 512 int type;
64d6ff88 513 /* True if we opened this channel but server hasn't confirmed. */
514 int halfopen;
0357890f 515 /*
2e85c969 516 * In SSH-1, this value contains four bits:
0357890f 517 *
518 * 1 We have sent SSH1_MSG_CHANNEL_CLOSE.
519 * 2 We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
520 * 4 We have received SSH1_MSG_CHANNEL_CLOSE.
521 * 8 We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
522 *
523 * A channel is completely finished with when all four bits are set.
524 */
dacbd0e8 525 int closes;
5471d09a 526 union {
527 struct ssh1_data_channel {
528 int throttling;
529 } v1;
530 struct ssh2_data_channel {
531 bufchain outbuffer;
532 unsigned remwindow, remmaxpkt;
533 unsigned locwindow;
534 } v2;
535 } v;
dacbd0e8 536 union {
32874aea 537 struct ssh_agent_channel {
538 unsigned char *message;
539 unsigned char msglen[4];
a03c9f9c 540 unsigned lensofar, totallen;
32874aea 541 } a;
542 struct ssh_x11_channel {
543 Socket s;
544 } x11;
d74d141c 545 struct ssh_pfd_channel {
546 Socket s;
547 } pfd;
dacbd0e8 548 } u;
549};
57476f6b 550
d74d141c 551/*
2e85c969 552 * 2-3-4 tree storing remote->local port forwardings. SSH-1 and SSH-2
553 * use this structure in different ways, reflecting SSH-2's
bc240b21 554 * altogether saner approach to port forwarding.
555 *
2e85c969 556 * In SSH-1, you arrange a remote forwarding by sending the server
bc240b21 557 * the remote port number, and the local destination host:port.
558 * When a connection comes in, the server sends you back that
559 * host:port pair, and you connect to it. This is a ready-made
560 * security hole if you're not on the ball: a malicious server
561 * could send you back _any_ host:port pair, so if you trustingly
562 * connect to the address it gives you then you've just opened the
563 * entire inside of your corporate network just by connecting
564 * through it to a dodgy SSH server. Hence, we must store a list of
565 * host:port pairs we _are_ trying to forward to, and reject a
566 * connection request from the server if it's not in the list.
567 *
2e85c969 568 * In SSH-2, each side of the connection minds its own business and
bc240b21 569 * doesn't send unnecessary information to the other. You arrange a
570 * remote forwarding by sending the server just the remote port
571 * number. When a connection comes in, the server tells you which
572 * of its ports was connected to; and _you_ have to remember what
573 * local host:port pair went with that port number.
574 *
2e85c969 575 * Hence, in SSH-1 this structure is indexed by destination
576 * host:port pair, whereas in SSH-2 it is indexed by source port.
d74d141c 577 */
fda2feb1 578struct ssh_portfwd; /* forward declaration */
579
d74d141c 580struct ssh_rportfwd {
bc240b21 581 unsigned sport, dport;
582 char dhost[256];
06fadff5 583 char *sportdesc;
fda2feb1 584 struct ssh_portfwd *pfrec;
d74d141c 585};
fda2feb1 586#define free_rportfwd(pf) ( \
587 ((pf) ? (sfree((pf)->sportdesc)) : (void)0 ), sfree(pf) )
588
589/*
590 * Separately to the rportfwd tree (which is for looking up port
591 * open requests from the server), a tree of _these_ structures is
592 * used to keep track of all the currently open port forwardings,
593 * so that we can reconfigure in mid-session if the user requests
594 * it.
595 */
596struct ssh_portfwd {
84328ddb 597 enum { DESTROY, KEEP, CREATE } status;
fda2feb1 598 int type;
599 unsigned sport, dport;
600 char *saddr, *daddr;
3fe92132 601 char *sserv, *dserv;
fda2feb1 602 struct ssh_rportfwd *remote;
05581745 603 int addressfamily;
fda2feb1 604 void *local;
605};
606#define free_portfwd(pf) ( \
3fe92132 607 ((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr), \
608 sfree((pf)->sserv), sfree((pf)->dserv)) : (void)0 ), sfree(pf) )
d74d141c 609
57476f6b 610struct Packet {
dacd8872 611 long length; /* length of `data' actually used */
612 long forcepad; /* SSH-2: force padding to at least this length */
613 int type; /* only used for incoming packets */
614 unsigned long sequence; /* SSH-2 incoming sequence number */
615 unsigned char *data; /* allocated storage */
616 unsigned char *body; /* offset of payload within `data' */
617 long savedpos; /* temporary index into `data' (for strings) */
618 long maxlen; /* amount of storage allocated for `data' */
619 long encrypted_len; /* for SSH-2 total-size counting */
ff3187f6 620
621 /*
622 * State associated with packet logging
623 */
624 int logmode;
625 int nblanks;
626 struct logblank_t *blanks;
57476f6b 627};
628
1c1a7262 629static void ssh1_protocol(Ssh ssh, void *vin, int inlen,
ff3187f6 630 struct Packet *pktin);
1c1a7262 631static void ssh2_protocol(Ssh ssh, void *vin, int inlen,
ff3187f6 632 struct Packet *pktin);
b09eaa88 633static void ssh1_protocol_setup(Ssh ssh);
634static void ssh2_protocol_setup(Ssh ssh);
51470298 635static void ssh_size(void *handle, int width, int height);
636static void ssh_special(void *handle, Telnet_Special);
5471d09a 637static int ssh2_try_send(struct ssh_channel *c);
51470298 638static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);
639static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
5471d09a 640static void ssh2_set_window(struct ssh_channel *c, unsigned newwin);
51470298 641static int ssh_sendbuffer(void *handle);
ac934965 642static int ssh_do_close(Ssh ssh, int notify_exit);
ff3187f6 643static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
644static int ssh2_pkt_getbool(struct Packet *pkt);
645static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);
9442dd57 646static void ssh2_timer(void *ctx, long now);
1c1a7262 647static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
9442dd57 648 struct Packet *pktin);
57476f6b 649
51470298 650struct rdpkt1_state_tag {
57476f6b 651 long len, pad, biglen, to_read;
652 unsigned long realcrc, gotcrc;
653 unsigned char *p;
654 int i;
655 int chunk;
ff3187f6 656 struct Packet *pktin;
51470298 657};
57476f6b 658
51470298 659struct rdpkt2_state_tag {
960e736a 660 long len, pad, payload, packetlen, maclen;
661 int i;
662 int cipherblk;
663 unsigned long incoming_sequence;
ff3187f6 664 struct Packet *pktin;
51470298 665};
666
b09eaa88 667typedef void (*handler_fn_t)(Ssh ssh, struct Packet *pktin);
06fadff5 668typedef void (*chandler_fn_t)(Ssh ssh, struct Packet *pktin, void *ctx);
669
670struct queued_handler;
671struct queued_handler {
672 int msg1, msg2;
673 chandler_fn_t handler;
674 void *ctx;
675 struct queued_handler *next;
676};
b09eaa88 677
51470298 678struct ssh_tag {
679 const struct plug_function_table *fn;
680 /* the above field _must_ be first in the structure */
681
4320baf7 682 char *v_c, *v_s;
b672f405 683 void *exhash;
51470298 684
685 Socket s;
686
b9d7bcad 687 void *ldisc;
a8327734 688 void *logctx;
b9d7bcad 689
51470298 690 unsigned char session_key[32];
691 int v1_compressing;
692 int v1_remote_protoflags;
693 int v1_local_protoflags;
694 int agentfwd_enabled;
695 int X11_fwd_enabled;
696 int remote_bugs;
697 const struct ssh_cipher *cipher;
371e569c 698 void *v1_cipher_ctx;
0183b242 699 void *crcda_ctx;
51470298 700 const struct ssh2_cipher *cscipher, *sccipher;
371e569c 701 void *cs_cipher_ctx, *sc_cipher_ctx;
51470298 702 const struct ssh_mac *csmac, *scmac;
e0e1a00d 703 void *cs_mac_ctx, *sc_mac_ctx;
51470298 704 const struct ssh_compress *cscomp, *sccomp;
5366aed8 705 void *cs_comp_ctx, *sc_comp_ctx;
51470298 706 const struct ssh_kex *kex;
707 const struct ssh_signkey *hostkey;
2ccb2fc8 708 unsigned char v2_session_id[32];
b672f405 709 int v2_session_id_len;
27cd7fc2 710 void *kex_ctx;
51470298 711
712 char *savedhost;
713 int savedport;
714 int send_ok;
715 int echoing, editing;
716
717 void *frontend;
718
db219738 719 int ospeed, ispeed; /* temporaries */
51470298 720 int term_width, term_height;
721
722 tree234 *channels; /* indexed by local id */
723 struct ssh_channel *mainchan; /* primary session channel */
724 int exitcode;
ac934965 725 int close_expected;
9e296bfa 726 int clean_exit;
51470298 727
fda2feb1 728 tree234 *rportfwds, *portfwds;
51470298 729
730 enum {
731 SSH_STATE_PREPACKET,
732 SSH_STATE_BEFORE_SIZE,
733 SSH_STATE_INTERMED,
734 SSH_STATE_SESSION,
735 SSH_STATE_CLOSED
736 } state;
737
738 int size_needed, eof_needed;
739
590f6a5f 740 struct Packet **queue;
741 int queuelen, queuesize;
742 int queueing;
51470298 743 unsigned char *deferred_send_data;
744 int deferred_len, deferred_size;
745
746 /*
747 * Gross hack: pscp will try to start SFTP but fall back to
748 * scp1 if that fails. This variable is the means by which
749 * scp.c can reach into the SSH code and find out which one it
750 * got.
751 */
752 int fallback_cmd;
753
6bbce591 754 bufchain banner; /* accumulates banners during do_ssh2_authconn */
51470298 755 /*
756 * Used for username and password input.
757 */
758 char *userpass_input_buffer;
759 int userpass_input_buflen;
760 int userpass_input_bufpos;
761 int userpass_input_echo;
762
51470298 763 int pkt_ctx;
764
302121de 765 void *x11auth;
766
51470298 767 int version;
768 int v1_throttle_count;
769 int overall_bufsize;
770 int throttled_all;
771 int v1_stdout_throttling;
a8756193 772 unsigned long v2_outgoing_sequence;
51470298 773
774 int ssh1_rdpkt_crstate;
775 int ssh2_rdpkt_crstate;
776 int do_ssh_init_crstate;
777 int ssh_gotdata_crstate;
51470298 778 int do_ssh1_login_crstate;
b09eaa88 779 int do_ssh1_connection_crstate;
51470298 780 int do_ssh2_transport_crstate;
781 int do_ssh2_authconn_crstate;
782
783 void *do_ssh_init_state;
784 void *do_ssh1_login_state;
785 void *do_ssh2_transport_state;
786 void *do_ssh2_authconn_state;
787
788 struct rdpkt1_state_tag rdpkt1_state;
789 struct rdpkt2_state_tag rdpkt2_state;
790
2e85c969 791 /* SSH-1 and SSH-2 use this for different things, but both use it */
b09eaa88 792 int protocol_initial_phase_done;
793
1c1a7262 794 void (*protocol) (Ssh ssh, void *vin, int inlen,
ff3187f6 795 struct Packet *pkt);
796 struct Packet *(*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
86916870 797
798 /*
799 * We maintain a full _copy_ of a Config structure here, not
800 * merely a pointer to it. That way, when we're passed a new
801 * one for reconfiguration, we can check the differences and
802 * potentially reconfigure port forwardings etc in mid-session.
803 */
804 Config cfg;
839f10db 805
806 /*
3d9449a1 807 * Used to transfer data back from async callbacks.
839f10db 808 */
809 void *agent_response;
810 int agent_response_len;
3d9449a1 811 int user_response;
812
813 /*
814 * The SSH connection can be set as `frozen', meaning we are
815 * not currently accepting incoming data from the network. This
816 * is slightly more serious than setting the _socket_ as
817 * frozen, because we may already have had data passed to us
818 * from the network which we need to delay processing until
819 * after the freeze is lifted, so we also need a bufchain to
820 * store that data.
821 */
822 int frozen;
823 bufchain queued_incoming_data;
b09eaa88 824
825 /*
826 * Dispatch table for packet types that we may have to deal
827 * with at any time.
828 */
829 handler_fn_t packet_dispatch[256];
39934deb 830
831 /*
06fadff5 832 * Queues of one-off handler functions for success/failure
833 * indications from a request.
834 */
835 struct queued_handler *qhead, *qtail;
836
837 /*
39934deb 838 * This module deals with sending keepalives.
839 */
840 Pinger pinger;
9442dd57 841
842 /*
843 * Track incoming and outgoing data sizes and time, for
844 * size-based rekeys.
845 */
846 unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
d57f70af 847 unsigned long max_data_size;
9442dd57 848 int kex_in_progress;
e6c1536e 849 long next_rekey, last_rekey;
e13bba36 850 char *deferred_rekey_reason; /* points to STATIC string; don't free */
51470298 851};
960e736a 852
382908ad 853#define logevent(s) logevent(ssh->frontend, s)
a8327734 854
855/* logevent, only printf-formatted. */
cbe2d68f 856static void logeventf(Ssh ssh, const char *fmt, ...)
a8327734 857{
858 va_list ap;
57356d63 859 char *buf;
a8327734 860
861 va_start(ap, fmt);
57356d63 862 buf = dupvprintf(fmt, ap);
a8327734 863 va_end(ap);
57356d63 864 logevent(buf);
57356d63 865 sfree(buf);
a8327734 866}
867
6b5cf8b4 868#define bombout(msg) \
869 do { \
870 char *text = dupprintf msg; \
ac934965 871 ssh_do_close(ssh, FALSE); \
6b5cf8b4 872 logevent(text); \
873 connection_fatal(ssh->frontend, "%s", text); \
874 sfree(text); \
875 } while (0)
a8327734 876
9a10ecf4 877/* Functions to leave bits out of the SSH packet log file. */
878
ff3187f6 879static void dont_log_password(Ssh ssh, struct Packet *pkt, int blanktype)
9a10ecf4 880{
881 if (ssh->cfg.logomitpass)
ff3187f6 882 pkt->logmode = blanktype;
9a10ecf4 883}
884
ff3187f6 885static void dont_log_data(Ssh ssh, struct Packet *pkt, int blanktype)
9a10ecf4 886{
887 if (ssh->cfg.logomitdata)
ff3187f6 888 pkt->logmode = blanktype;
9a10ecf4 889}
890
ff3187f6 891static void end_log_omission(Ssh ssh, struct Packet *pkt)
9a10ecf4 892{
ff3187f6 893 pkt->logmode = PKTLOG_EMIT;
9a10ecf4 894}
895
c6ccd5c2 896/* Helper function for common bits of parsing cfg.ttymodes. */
897static void parse_ttymodes(Ssh ssh, char *modes,
898 void (*do_mode)(void *data, char *mode, char *val),
899 void *data)
900{
901 while (*modes) {
902 char *t = strchr(modes, '\t');
903 char *m = snewn(t-modes+1, char);
904 char *val;
905 strncpy(m, modes, t-modes);
906 m[t-modes] = '\0';
907 if (*(t+1) == 'A')
908 val = get_ttymode(ssh->frontend, m);
909 else
910 val = dupstr(t+2);
911 if (val)
912 do_mode(data, m, val);
913 sfree(m);
914 sfree(val);
915 modes += strlen(modes) + 1;
916 }
917}
918
32874aea 919static int ssh_channelcmp(void *av, void *bv)
920{
921 struct ssh_channel *a = (struct ssh_channel *) av;
922 struct ssh_channel *b = (struct ssh_channel *) bv;
923 if (a->localid < b->localid)
924 return -1;
925 if (a->localid > b->localid)
926 return +1;
dacbd0e8 927 return 0;
928}
32874aea 929static int ssh_channelfind(void *av, void *bv)
930{
931 unsigned *a = (unsigned *) av;
932 struct ssh_channel *b = (struct ssh_channel *) bv;
933 if (*a < b->localid)
934 return -1;
935 if (*a > b->localid)
936 return +1;
dacbd0e8 937 return 0;
938}
939
bc240b21 940static int ssh_rportcmp_ssh1(void *av, void *bv)
d74d141c 941{
942 struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;
943 struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
944 int i;
bc240b21 945 if ( (i = strcmp(a->dhost, b->dhost)) != 0)
d74d141c 946 return i < 0 ? -1 : +1;
bc240b21 947 if (a->dport > b->dport)
948 return +1;
949 if (a->dport < b->dport)
950 return -1;
951 return 0;
952}
953
954static int ssh_rportcmp_ssh2(void *av, void *bv)
955{
956 struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;
957 struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
cdcbdf3b 958
bc240b21 959 if (a->sport > b->sport)
d74d141c 960 return +1;
bc240b21 961 if (a->sport < b->sport)
962 return -1;
d74d141c 963 return 0;
964}
965
fda2feb1 966/*
967 * Special form of strcmp which can cope with NULL inputs. NULL is
968 * defined to sort before even the empty string.
969 */
970static int nullstrcmp(const char *a, const char *b)
971{
972 if (a == NULL && b == NULL)
973 return 0;
974 if (a == NULL)
975 return -1;
976 if (b == NULL)
977 return +1;
978 return strcmp(a, b);
979}
980
981static int ssh_portcmp(void *av, void *bv)
982{
983 struct ssh_portfwd *a = (struct ssh_portfwd *) av;
984 struct ssh_portfwd *b = (struct ssh_portfwd *) bv;
985 int i;
986 if (a->type > b->type)
987 return +1;
988 if (a->type < b->type)
989 return -1;
84328ddb 990 if (a->addressfamily > b->addressfamily)
991 return +1;
992 if (a->addressfamily < b->addressfamily)
993 return -1;
fda2feb1 994 if ( (i = nullstrcmp(a->saddr, b->saddr)) != 0)
995 return i < 0 ? -1 : +1;
996 if (a->sport > b->sport)
997 return +1;
998 if (a->sport < b->sport)
999 return -1;
1000 if (a->type != 'D') {
1001 if ( (i = nullstrcmp(a->daddr, b->daddr)) != 0)
1002 return i < 0 ? -1 : +1;
1003 if (a->dport > b->dport)
1004 return +1;
1005 if (a->dport < b->dport)
1006 return -1;
1007 }
1008 return 0;
1009}
1010
51470298 1011static int alloc_channel_id(Ssh ssh)
32874aea 1012{
260f3dec 1013 const unsigned CHANNEL_NUMBER_OFFSET = 256;
1014 unsigned low, high, mid;
d2371c81 1015 int tsize;
1016 struct ssh_channel *c;
1017
1018 /*
1019 * First-fit allocation of channel numbers: always pick the
1020 * lowest unused one. To do this, binary-search using the
1021 * counted B-tree to find the largest channel ID which is in a
1022 * contiguous sequence from the beginning. (Precisely
1023 * everything in that sequence must have ID equal to its tree
1024 * index plus CHANNEL_NUMBER_OFFSET.)
1025 */
51470298 1026 tsize = count234(ssh->channels);
d2371c81 1027
32874aea 1028 low = -1;
1029 high = tsize;
d2371c81 1030 while (high - low > 1) {
1031 mid = (high + low) / 2;
51470298 1032 c = index234(ssh->channels, mid);
d2371c81 1033 if (c->localid == mid + CHANNEL_NUMBER_OFFSET)
1034 low = mid; /* this one is fine */
1035 else
1036 high = mid; /* this one is past it */
1037 }
1038 /*
1039 * Now low points to either -1, or the tree index of the
1040 * largest ID in the initial sequence.
1041 */
1042 {
1043 unsigned i = low + 1 + CHANNEL_NUMBER_OFFSET;
51470298 1044 assert(NULL == find234(ssh->channels, &i, ssh_channelfind));
d2371c81 1045 }
1046 return low + 1 + CHANNEL_NUMBER_OFFSET;
1047}
1048
9fab77dc 1049static void c_write(Ssh ssh, const char *buf, int len)
32874aea 1050{
67779be7 1051 if ((flags & FLAG_STDERR)) {
32874aea 1052 int i;
1053 for (i = 0; i < len; i++)
1054 if (buf[i] != '\r')
1055 fputc(buf[i], stderr);
fb09bf1c 1056 return;
1057 }
51470298 1058 from_backend(ssh->frontend, 1, buf, len);
3bdaf79d 1059}
1060
9fab77dc 1061static void c_write_untrusted(Ssh ssh, const char *buf, int len)
32874aea 1062{
a209e957 1063 int i;
1064 for (i = 0; i < len; i++) {
32874aea 1065 if (buf[i] == '\n')
51470298 1066 c_write(ssh, "\r\n", 2);
32874aea 1067 else if ((buf[i] & 0x60) || (buf[i] == '\r'))
51470298 1068 c_write(ssh, buf + i, 1);
a209e957 1069 }
1070}
1071
9fab77dc 1072static void c_write_str(Ssh ssh, const char *buf)
32874aea 1073{
51470298 1074 c_write(ssh, buf, strlen(buf));
1408a877 1075}
1076
ff3187f6 1077static void ssh_free_packet(struct Packet *pkt)
1078{
1079 sfree(pkt->data);
1080 sfree(pkt);
1081}
1082static struct Packet *ssh_new_packet(void)
1083{
1084 struct Packet *pkt = snew(struct Packet);
1085
dacd8872 1086 pkt->body = pkt->data = NULL;
ff3187f6 1087 pkt->maxlen = 0;
1088 pkt->logmode = PKTLOG_EMIT;
1089 pkt->nblanks = 0;
1090 pkt->blanks = NULL;
1091
1092 return pkt;
1093}
1094
fb09bf1c 1095/*
1096 * Collect incoming data in the incoming packet buffer.
e5574168 1097 * Decipher and verify the packet when it is completely read.
1098 * Drop SSH1_MSG_DEBUG and SSH1_MSG_IGNORE packets.
fb09bf1c 1099 * Update the *data and *datalen variables.
ff3187f6 1100 * Return a Packet structure when a packet is completed.
fb09bf1c 1101 */
ff3187f6 1102static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
fb09bf1c 1103{
51470298 1104 struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;
374330e2 1105
51470298 1106 crBegin(ssh->ssh1_rdpkt_crstate);
374330e2 1107
ff3187f6 1108 st->pktin = ssh_new_packet();
1109
1110 st->pktin->type = 0;
1111 st->pktin->length = 0;
374330e2 1112
57476f6b 1113 for (st->i = st->len = 0; st->i < 4; st->i++) {
fb09bf1c 1114 while ((*datalen) == 0)
ff3187f6 1115 crReturn(NULL);
57476f6b 1116 st->len = (st->len << 8) + **data;
fb09bf1c 1117 (*data)++, (*datalen)--;
1118 }
374330e2 1119
57476f6b 1120 st->pad = 8 - (st->len % 8);
1121 st->biglen = st->len + st->pad;
ff3187f6 1122 st->pktin->length = st->len - 5;
fb09bf1c 1123
ae0500e5 1124 if (st->biglen < 0) {
1125 bombout(("Extremely large packet length from server suggests"
1126 " data stream corruption"));
ff3187f6 1127 ssh_free_packet(st->pktin);
1128 crStop(NULL);
ae0500e5 1129 }
1130
ff3187f6 1131 st->pktin->maxlen = st->biglen;
1132 st->pktin->data = snewn(st->biglen + APIEXTRA, unsigned char);
374330e2 1133
57476f6b 1134 st->to_read = st->biglen;
ff3187f6 1135 st->p = st->pktin->data;
57476f6b 1136 while (st->to_read > 0) {
32874aea 1137 st->chunk = st->to_read;
fb09bf1c 1138 while ((*datalen) == 0)
ff3187f6 1139 crReturn(NULL);
57476f6b 1140 if (st->chunk > (*datalen))
1141 st->chunk = (*datalen);
1142 memcpy(st->p, *data, st->chunk);
1143 *data += st->chunk;
1144 *datalen -= st->chunk;
1145 st->p += st->chunk;
1146 st->to_read -= st->chunk;
fb09bf1c 1147 }
374330e2 1148
ff3187f6 1149 if (ssh->cipher && detect_attack(ssh->crcda_ctx, st->pktin->data,
0183b242 1150 st->biglen, NULL)) {
6b5cf8b4 1151 bombout(("Network attack (CRC compensation) detected!"));
ff3187f6 1152 ssh_free_packet(st->pktin);
1153 crStop(NULL);
9a3a93a5 1154 }
1155
51470298 1156 if (ssh->cipher)
ff3187f6 1157 ssh->cipher->decrypt(ssh->v1_cipher_ctx, st->pktin->data, st->biglen);
374330e2 1158
ff3187f6 1159 st->realcrc = crc32_compute(st->pktin->data, st->biglen - 4);
1160 st->gotcrc = GET_32BIT(st->pktin->data + st->biglen - 4);
57476f6b 1161 if (st->gotcrc != st->realcrc) {
6b5cf8b4 1162 bombout(("Incorrect CRC received on packet"));
ff3187f6 1163 ssh_free_packet(st->pktin);
1164 crStop(NULL);
fb09bf1c 1165 }
572f871e 1166
ff3187f6 1167 st->pktin->body = st->pktin->data + st->pad + 1;
1168 st->pktin->savedpos = 0;
4ba9b64b 1169
51470298 1170 if (ssh->v1_compressing) {
4ba9b64b 1171 unsigned char *decompblk;
1172 int decomplen;
36b8d9bb 1173 if (!zlib_decompress_block(ssh->sc_comp_ctx,
ff3187f6 1174 st->pktin->body - 1, st->pktin->length + 1,
36b8d9bb 1175 &decompblk, &decomplen)) {
1176 bombout(("Zlib decompression encountered invalid data"));
ff3187f6 1177 ssh_free_packet(st->pktin);
1178 crStop(NULL);
36b8d9bb 1179 }
4ba9b64b 1180
ff3187f6 1181 if (st->pktin->maxlen < st->pad + decomplen) {
1182 st->pktin->maxlen = st->pad + decomplen;
1183 st->pktin->data = sresize(st->pktin->data,
1184 st->pktin->maxlen + APIEXTRA,
3d88e64d 1185 unsigned char);
ff3187f6 1186 st->pktin->body = st->pktin->data + st->pad + 1;
4ba9b64b 1187 }
1188
ff3187f6 1189 memcpy(st->pktin->body - 1, decompblk, decomplen);
dcbde236 1190 sfree(decompblk);
ff3187f6 1191 st->pktin->length = decomplen - 1;
4ba9b64b 1192 }
1193
ff3187f6 1194 st->pktin->type = st->pktin->body[-1];
00db133f 1195
9a10ecf4 1196 /*
1197 * Log incoming packet, possibly omitting sensitive fields.
1198 */
1199 if (ssh->logctx) {
1200 int nblanks = 0;
1201 struct logblank_t blank;
1202 if (ssh->cfg.logomitdata) {
1203 int do_blank = FALSE, blank_prefix = 0;
1204 /* "Session data" packets - omit the data field */
ff3187f6 1205 if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||
1206 (st->pktin->type == SSH1_SMSG_STDERR_DATA)) {
9a10ecf4 1207 do_blank = TRUE; blank_prefix = 0;
ff3187f6 1208 } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {
9a10ecf4 1209 do_blank = TRUE; blank_prefix = 4;
1210 }
1211 if (do_blank) {
1212 blank.offset = blank_prefix;
ff3187f6 1213 blank.len = st->pktin->length;
9a10ecf4 1214 blank.type = PKTLOG_OMIT;
1215 nblanks = 1;
1216 }
1217 }
a8327734 1218 log_packet(ssh->logctx,
ff3187f6 1219 PKT_INCOMING, st->pktin->type,
1220 ssh1_pkt_type(st->pktin->type),
1221 st->pktin->body, st->pktin->length,
9a10ecf4 1222 nblanks, &blank);
1223 }
00db133f 1224
ff3187f6 1225 crFinish(st->pktin);
fb09bf1c 1226}
1227
ff3187f6 1228static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
e5574168 1229{
51470298 1230 struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;
e5574168 1231
51470298 1232 crBegin(ssh->ssh2_rdpkt_crstate);
e5574168 1233
ff3187f6 1234 st->pktin = ssh_new_packet();
1235
1236 st->pktin->type = 0;
1237 st->pktin->length = 0;
51470298 1238 if (ssh->sccipher)
1239 st->cipherblk = ssh->sccipher->blksize;
e5574168 1240 else
32874aea 1241 st->cipherblk = 8;
960e736a 1242 if (st->cipherblk < 8)
32874aea 1243 st->cipherblk = 8;
960e736a 1244
ff3187f6 1245 st->pktin->data = snewn(st->cipherblk + APIEXTRA, unsigned char);
e5574168 1246
1247 /*
1248 * Acquire and decrypt the first block of the packet. This will
1249 * contain the length and padding details.
1250 */
32874aea 1251 for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {
e5574168 1252 while ((*datalen) == 0)
ff3187f6 1253 crReturn(NULL);
1254 st->pktin->data[st->i] = *(*data)++;
32874aea 1255 (*datalen)--;
e5574168 1256 }
4252c9cc 1257
51470298 1258 if (ssh->sccipher)
371e569c 1259 ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
ff3187f6 1260 st->pktin->data, st->cipherblk);
e5574168 1261
1262 /*
1263 * Now get the length and padding figures.
1264 */
ff3187f6 1265 st->len = GET_32BIT(st->pktin->data);
1266 st->pad = st->pktin->data[4];
e5574168 1267
1268 /*
717dc483 1269 * _Completely_ silly lengths should be stomped on before they
1270 * do us any more damage.
1271 */
cba1e4b5 1272 if (st->len < 0 || st->len > 35000 || st->pad < 4 ||
1273 st->len - st->pad < 1 || (st->len + 4) % st->cipherblk != 0) {
6b5cf8b4 1274 bombout(("Incoming packet was garbled on decryption"));
ff3187f6 1275 ssh_free_packet(st->pktin);
1276 crStop(NULL);
717dc483 1277 }
1278
1279 /*
e5574168 1280 * This enables us to deduce the payload length.
1281 */
960e736a 1282 st->payload = st->len - st->pad - 1;
e5574168 1283
ff3187f6 1284 st->pktin->length = st->payload + 5;
e5574168 1285
1286 /*
1287 * So now we can work out the total packet length.
1288 */
960e736a 1289 st->packetlen = st->len + 4;
51470298 1290 st->maclen = ssh->scmac ? ssh->scmac->len : 0;
e5574168 1291
1292 /*
ff3187f6 1293 * Allocate memory for the rest of the packet.
e5574168 1294 */
ff3187f6 1295 st->pktin->maxlen = st->packetlen + st->maclen;
1296 st->pktin->data = sresize(st->pktin->data,
1297 st->pktin->maxlen + APIEXTRA,
1298 unsigned char);
e5574168 1299
1300 /*
1301 * Read and decrypt the remainder of the packet.
1302 */
32874aea 1303 for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;
1304 st->i++) {
e5574168 1305 while ((*datalen) == 0)
ff3187f6 1306 crReturn(NULL);
1307 st->pktin->data[st->i] = *(*data)++;
32874aea 1308 (*datalen)--;
e5574168 1309 }
1310 /* Decrypt everything _except_ the MAC. */
51470298 1311 if (ssh->sccipher)
371e569c 1312 ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
ff3187f6 1313 st->pktin->data + st->cipherblk,
51470298 1314 st->packetlen - st->cipherblk);
e5574168 1315
9442dd57 1316 st->pktin->encrypted_len = st->packetlen;
1317
e5574168 1318 /*
1319 * Check the MAC.
1320 */
51470298 1321 if (ssh->scmac
ff3187f6 1322 && !ssh->scmac->verify(ssh->sc_mac_ctx, st->pktin->data, st->len + 4,
51470298 1323 st->incoming_sequence)) {
6b5cf8b4 1324 bombout(("Incorrect MAC received on packet"));
ff3187f6 1325 ssh_free_packet(st->pktin);
1326 crStop(NULL);
8d5de777 1327 }
b09eaa88 1328
1329 st->pktin->sequence = st->incoming_sequence++;
e5574168 1330
4ba9b64b 1331 /*
1332 * Decompress packet payload.
1333 */
1334 {
1335 unsigned char *newpayload;
1336 int newlen;
51470298 1337 if (ssh->sccomp &&
5366aed8 1338 ssh->sccomp->decompress(ssh->sc_comp_ctx,
ff3187f6 1339 st->pktin->data + 5, st->pktin->length - 5,
51470298 1340 &newpayload, &newlen)) {
ff3187f6 1341 if (st->pktin->maxlen < newlen + 5) {
1342 st->pktin->maxlen = newlen + 5;
1343 st->pktin->data = sresize(st->pktin->data,
1344 st->pktin->maxlen + APIEXTRA,
3d88e64d 1345 unsigned char);
4ba9b64b 1346 }
ff3187f6 1347 st->pktin->length = 5 + newlen;
1348 memcpy(st->pktin->data + 5, newpayload, newlen);
dcbde236 1349 sfree(newpayload);
4ba9b64b 1350 }
1351 }
1352
ff3187f6 1353 st->pktin->savedpos = 6;
1354 st->pktin->body = st->pktin->data;
1355 st->pktin->type = st->pktin->data[5];
e5574168 1356
9a10ecf4 1357 /*
1358 * Log incoming packet, possibly omitting sensitive fields.
1359 */
1360 if (ssh->logctx) {
1361 int nblanks = 0;
1362 struct logblank_t blank;
1363 if (ssh->cfg.logomitdata) {
1364 int do_blank = FALSE, blank_prefix = 0;
1365 /* "Session data" packets - omit the data field */
ff3187f6 1366 if (st->pktin->type == SSH2_MSG_CHANNEL_DATA) {
9a10ecf4 1367 do_blank = TRUE; blank_prefix = 4;
ff3187f6 1368 } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
9a10ecf4 1369 do_blank = TRUE; blank_prefix = 8;
1370 }
1371 if (do_blank) {
1372 blank.offset = blank_prefix;
ff3187f6 1373 blank.len = (st->pktin->length-6) - blank_prefix;
9a10ecf4 1374 blank.type = PKTLOG_OMIT;
1375 nblanks = 1;
1376 }
1377 }
ff3187f6 1378 log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,
1379 ssh2_pkt_type(ssh->pkt_ctx, st->pktin->type),
1380 st->pktin->data+6, st->pktin->length-6,
9a10ecf4 1381 nblanks, &blank);
1382 }
00db133f 1383
ff3187f6 1384 crFinish(st->pktin);
e5574168 1385}
1386
dacd8872 1387static int s_wrpkt_prepare(Ssh ssh, struct Packet *pkt, int *offset_p)
32874aea 1388{
dacd8872 1389 int pad, biglen, i, pktoffs;
374330e2 1390 unsigned long crc;
fd7a4aad 1391#ifdef __SC__
1392 /*
1393 * XXX various versions of SC (including 8.8.4) screw up the
1394 * register allocation in this function and use the same register
1395 * (D6) for len and as a temporary, with predictable results. The
1396 * following sledgehammer prevents this.
1397 */
1398 volatile
1399#endif
1400 int len;
374330e2 1401
a8327734 1402 if (ssh->logctx)
dacd8872 1403 log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[12],
1404 ssh1_pkt_type(pkt->data[12]),
1405 pkt->body, pkt->length - (pkt->body - pkt->data),
ff3187f6 1406 pkt->nblanks, pkt->blanks);
1407 sfree(pkt->blanks); pkt->blanks = NULL;
1408 pkt->nblanks = 0;
00db133f 1409
51470298 1410 if (ssh->v1_compressing) {
4ba9b64b 1411 unsigned char *compblk;
1412 int complen;
5366aed8 1413 zlib_compress_block(ssh->cs_comp_ctx,
dacd8872 1414 pkt->data + 12, pkt->length - 12,
4ba9b64b 1415 &compblk, &complen);
dacd8872 1416 memcpy(pkt->data + 12, compblk, complen);
dcbde236 1417 sfree(compblk);
dacd8872 1418 pkt->length = complen + 12;
4ba9b64b 1419 }
1420
dacd8872 1421 ssh_pkt_ensure(pkt, pkt->length + 4); /* space for CRC */
1422 pkt->length += 4;
1423 len = pkt->length - 4 - 8; /* len(type+data+CRC) */
32874aea 1424 pad = 8 - (len % 8);
dacd8872 1425 pktoffs = 8 - pad;
1426 biglen = len + pad; /* len(padding+type+data+CRC) */
374330e2 1427
dacd8872 1428 for (i = pktoffs; i < 4+8; i++)
1429 pkt->data[i] = random_byte();
1430 crc = crc32_compute(pkt->data + pktoffs + 4, biglen - 4); /* all ex len */
1431 PUT_32BIT(pkt->data + pktoffs + 4 + biglen - 4, crc);
1432 PUT_32BIT(pkt->data + pktoffs, len);
374330e2 1433
51470298 1434 if (ssh->cipher)
dacd8872 1435 ssh->cipher->encrypt(ssh->v1_cipher_ctx,
1436 pkt->data + pktoffs + 4, biglen);
374330e2 1437
dacd8872 1438 if (offset_p) *offset_p = pktoffs;
1439 return biglen + 4; /* len(length+padding+type+data+CRC) */
39065bed 1440}
1441
ff3187f6 1442static void s_wrpkt(Ssh ssh, struct Packet *pkt)
32874aea 1443{
dacd8872 1444 int len, backlog, offset;
1445 len = s_wrpkt_prepare(ssh, pkt, &offset);
1446 backlog = sk_write(ssh->s, (char *)pkt->data + offset, len);
5471d09a 1447 if (backlog > SSH_MAX_BACKLOG)
51470298 1448 ssh_throttle_all(ssh, 1, backlog);
dacd8872 1449 ssh_free_packet(pkt);
39065bed 1450}
1451
ff3187f6 1452static void s_wrpkt_defer(Ssh ssh, struct Packet *pkt)
32874aea 1453{
dacd8872 1454 int len, offset;
1455 len = s_wrpkt_prepare(ssh, pkt, &offset);
51470298 1456 if (ssh->deferred_len + len > ssh->deferred_size) {
1457 ssh->deferred_size = ssh->deferred_len + len + 128;
3d88e64d 1458 ssh->deferred_send_data = sresize(ssh->deferred_send_data,
1459 ssh->deferred_size,
1460 unsigned char);
39065bed 1461 }
dacd8872 1462 memcpy(ssh->deferred_send_data + ssh->deferred_len,
1463 pkt->data + offset, len);
51470298 1464 ssh->deferred_len += len;
dacd8872 1465 ssh_free_packet(pkt);
374330e2 1466}
1467
fb09bf1c 1468/*
dacd8872 1469 * Construct a SSH-1 packet with the specified contents.
1470 * (This all-at-once interface used to be the only one, but now SSH-1
1471 * packets can also be constructed incrementally.)
fb09bf1c 1472 */
dacd8872 1473static struct Packet *construct_packet(Ssh ssh, int pkttype, va_list ap)
fb09bf1c 1474{
dacd8872 1475 int argtype;
7cca0d81 1476 Bignum bn;
ff3187f6 1477 struct Packet *pkt;
fb09bf1c 1478
dacd8872 1479 pkt = ssh1_pkt_init(pkttype);
fb09bf1c 1480
dacd8872 1481 while ((argtype = va_arg(ap, int)) != PKT_END) {
1482 unsigned char *argp, argchar;
1483 unsigned long argint;
1484 int arglen;
fb09bf1c 1485 switch (argtype) {
9a10ecf4 1486 /* Actual fields in the packet */
fb09bf1c 1487 case PKT_INT:
dacd8872 1488 argint = va_arg(ap, int);
1489 ssh_pkt_adduint32(pkt, argint);
fb09bf1c 1490 break;
1491 case PKT_CHAR:
dacd8872 1492 argchar = (unsigned char) va_arg(ap, int);
1493 ssh_pkt_addbyte(pkt, argchar);
fb09bf1c 1494 break;
1495 case PKT_DATA:
dacd8872 1496 argp = va_arg(ap, unsigned char *);
1497 arglen = va_arg(ap, int);
1498 ssh_pkt_adddata(pkt, argp, arglen);
fb09bf1c 1499 break;
1500 case PKT_STR:
dacd8872 1501 argp = va_arg(ap, unsigned char *);
1502 ssh_pkt_addstring(pkt, argp);
fb09bf1c 1503 break;
7cca0d81 1504 case PKT_BIGNUM:
dacd8872 1505 bn = va_arg(ap, Bignum);
1506 ssh1_pkt_addmp(pkt, bn);
9a10ecf4 1507 break;
1508 /* Tokens for modifications to packet logging */
1509 case PKTT_PASSWORD:
ff3187f6 1510 dont_log_password(ssh, pkt, PKTLOG_BLANK);
9a10ecf4 1511 break;
1512 case PKTT_DATA:
ff3187f6 1513 dont_log_data(ssh, pkt, PKTLOG_OMIT);
7cca0d81 1514 break;
9a10ecf4 1515 case PKTT_OTHER:
ff3187f6 1516 end_log_omission(ssh, pkt);
9a10ecf4 1517 break;
1518 }
fb09bf1c 1519 }
ff3187f6 1520
1521 return pkt;
39065bed 1522}
fb09bf1c 1523
51470298 1524static void send_packet(Ssh ssh, int pkttype, ...)
32874aea 1525{
ff3187f6 1526 struct Packet *pkt;
dacd8872 1527 va_list ap;
1528 va_start(ap, pkttype);
1529 pkt = construct_packet(ssh, pkttype, ap);
1530 va_end(ap);
ff3187f6 1531 s_wrpkt(ssh, pkt);
fb09bf1c 1532}
1533
51470298 1534static void defer_packet(Ssh ssh, int pkttype, ...)
32874aea 1535{
ff3187f6 1536 struct Packet *pkt;
dacd8872 1537 va_list ap;
1538 va_start(ap, pkttype);
1539 pkt = construct_packet(ssh, pkttype, ap);
1540 va_end(ap);
ff3187f6 1541 s_wrpkt_defer(ssh, pkt);
39065bed 1542}
1543
32874aea 1544static int ssh_versioncmp(char *a, char *b)
1545{
9697bfd2 1546 char *ae, *be;
1547 unsigned long av, bv;
1548
43aa02a7 1549 av = strtoul(a, &ae, 10);
1550 bv = strtoul(b, &be, 10);
32874aea 1551 if (av != bv)
1552 return (av < bv ? -1 : +1);
1553 if (*ae == '.')
1554 ae++;
1555 if (*be == '.')
1556 be++;
43aa02a7 1557 av = strtoul(ae, &ae, 10);
1558 bv = strtoul(be, &be, 10);
32874aea 1559 if (av != bv)
1560 return (av < bv ? -1 : +1);
9697bfd2 1561 return 0;
1562}
1563
e5574168 1564/*
a92dd380 1565 * Utility routines for putting an SSH-protocol `string' and
b672f405 1566 * `uint32' into a hash state.
e5574168 1567 */
b672f405 1568static void hash_string(const struct ssh_hash *h, void *s, void *str, int len)
32874aea 1569{
e5574168 1570 unsigned char lenblk[4];
e5574168 1571 PUT_32BIT(lenblk, len);
b672f405 1572 h->bytes(s, lenblk, 4);
1573 h->bytes(s, str, len);
e5574168 1574}
1575
b672f405 1576static void hash_uint32(const struct ssh_hash *h, void *s, unsigned i)
32874aea 1577{
a92dd380 1578 unsigned char intblk[4];
1579 PUT_32BIT(intblk, i);
b672f405 1580 h->bytes(s, intblk, 4);
a92dd380 1581}
1582
7cca0d81 1583/*
dacd8872 1584 * Packet construction functions. Mostly shared between SSH-1 and SSH-2.
7cca0d81 1585 */
dacd8872 1586static void ssh_pkt_ensure(struct Packet *pkt, int length)
32874aea 1587{
ff3187f6 1588 if (pkt->maxlen < length) {
dacd8872 1589 unsigned char *body = pkt->body;
3d71de0b 1590 int offset = body ? body - pkt->data : 0;
ff3187f6 1591 pkt->maxlen = length + 256;
1592 pkt->data = sresize(pkt->data, pkt->maxlen + APIEXTRA, unsigned char);
dacd8872 1593 if (body) pkt->body = pkt->data + offset;
7cca0d81 1594 }
783415f8 1595}
dacd8872 1596static void ssh_pkt_adddata(struct Packet *pkt, void *data, int len)
32874aea 1597{
ff3187f6 1598 if (pkt->logmode != PKTLOG_EMIT) {
1599 pkt->nblanks++;
1600 pkt->blanks = sresize(pkt->blanks, pkt->nblanks, struct logblank_t);
dacd8872 1601 assert(pkt->body);
1602 pkt->blanks[pkt->nblanks-1].offset = pkt->length -
1603 (pkt->body - pkt->data);
ff3187f6 1604 pkt->blanks[pkt->nblanks-1].len = len;
1605 pkt->blanks[pkt->nblanks-1].type = pkt->logmode;
1606 }
1607 pkt->length += len;
dacd8872 1608 ssh_pkt_ensure(pkt, pkt->length);
ff3187f6 1609 memcpy(pkt->data + pkt->length - len, data, len);
7cca0d81 1610}
dacd8872 1611static void ssh_pkt_addbyte(struct Packet *pkt, unsigned char byte)
32874aea 1612{
dacd8872 1613 ssh_pkt_adddata(pkt, &byte, 1);
7cca0d81 1614}
ff3187f6 1615static void ssh2_pkt_addbool(struct Packet *pkt, unsigned char value)
32874aea 1616{
dacd8872 1617 ssh_pkt_adddata(pkt, &value, 1);
7cca0d81 1618}
dacd8872 1619static void ssh_pkt_adduint32(struct Packet *pkt, unsigned long value)
32874aea 1620{
7cca0d81 1621 unsigned char x[4];
1622 PUT_32BIT(x, value);
dacd8872 1623 ssh_pkt_adddata(pkt, x, 4);
7cca0d81 1624}
dacd8872 1625static void ssh_pkt_addstring_start(struct Packet *pkt)
32874aea 1626{
dacd8872 1627 ssh_pkt_adduint32(pkt, 0);
ff3187f6 1628 pkt->savedpos = pkt->length;
7cca0d81 1629}
dacd8872 1630static void ssh_pkt_addstring_str(struct Packet *pkt, char *data)
32874aea 1631{
dacd8872 1632 ssh_pkt_adddata(pkt, data, strlen(data));
ff3187f6 1633 PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
7cca0d81 1634}
dacd8872 1635static void ssh_pkt_addstring_data(struct Packet *pkt, char *data, int len)
32874aea 1636{
dacd8872 1637 ssh_pkt_adddata(pkt, data, len);
ff3187f6 1638 PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
7cca0d81 1639}
dacd8872 1640static void ssh_pkt_addstring(struct Packet *pkt, char *data)
1641{
1642 ssh_pkt_addstring_start(pkt);
1643 ssh_pkt_addstring_str(pkt, data);
1644}
1645static void ssh1_pkt_addmp(struct Packet *pkt, Bignum b)
32874aea 1646{
dacd8872 1647 int len = ssh1_bignum_length(b);
1648 unsigned char *data = snewn(len, char);
1649 (void) ssh1_write_bignum(data, b);
1650 ssh_pkt_adddata(pkt, data, len);
1651 sfree(data);
7cca0d81 1652}
d8baa528 1653static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
32874aea 1654{
7cca0d81 1655 unsigned char *p;
32874aea 1656 int i, n = (bignum_bitcount(b) + 7) / 8;
3d88e64d 1657 p = snewn(n + 1, unsigned char);
7cca0d81 1658 p[0] = 0;
3709bfe9 1659 for (i = 1; i <= n; i++)
32874aea 1660 p[i] = bignum_byte(b, n - i);
7cca0d81 1661 i = 0;
32874aea 1662 while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)
1663 i++;
1664 memmove(p, p + i, n + 1 - i);
1665 *len = n + 1 - i;
7cca0d81 1666 return p;
1667}
ff3187f6 1668static void ssh2_pkt_addmp(struct Packet *pkt, Bignum b)
32874aea 1669{
7cca0d81 1670 unsigned char *p;
1671 int len;
1672 p = ssh2_mpint_fmt(b, &len);
dacd8872 1673 ssh_pkt_addstring_start(pkt);
1674 ssh_pkt_addstring_data(pkt, (char *)p, len);
dcbde236 1675 sfree(p);
7cca0d81 1676}
b185170a 1677
dacd8872 1678static struct Packet *ssh1_pkt_init(int pkt_type)
1679{
1680 struct Packet *pkt = ssh_new_packet();
1681 pkt->length = 4 + 8; /* space for length + max padding */
1682 ssh_pkt_addbyte(pkt, pkt_type);
1683 pkt->body = pkt->data + pkt->length;
1684 return pkt;
1685}
1686
1687/* For legacy code (SSH-1 and -2 packet construction used to be separate) */
1688#define ssh2_pkt_ensure(pkt, length) ssh_pkt_ensure(pkt, length)
1689#define ssh2_pkt_adddata(pkt, data, len) ssh_pkt_adddata(pkt, data, len)
1690#define ssh2_pkt_addbyte(pkt, byte) ssh_pkt_addbyte(pkt, byte)
1691#define ssh2_pkt_adduint32(pkt, value) ssh_pkt_adduint32(pkt, value)
1692#define ssh2_pkt_addstring_start(pkt) ssh_pkt_addstring_start(pkt)
1693#define ssh2_pkt_addstring_str(pkt, data) ssh_pkt_addstring_str(pkt, data)
1694#define ssh2_pkt_addstring_data(pkt, data, len) ssh_pkt_addstring_data(pkt, data, len)
1695#define ssh2_pkt_addstring(pkt, data) ssh_pkt_addstring(pkt, data)
1696
1697static struct Packet *ssh2_pkt_init(int pkt_type)
1698{
1699 struct Packet *pkt = ssh_new_packet();
3d71de0b 1700 pkt->length = 5; /* space for packet length + padding length */
dacd8872 1701 pkt->forcepad = 0;
1702 ssh_pkt_addbyte(pkt, (unsigned char) pkt_type);
3d71de0b 1703 pkt->body = pkt->data + pkt->length; /* after packet type */
dacd8872 1704 return pkt;
1705}
1706
b185170a 1707/*
2e85c969 1708 * Construct an SSH-2 final-form packet: compress it, encrypt it,
b185170a 1709 * put the MAC on it. Final packet, ready to be sent, is stored in
ff3187f6 1710 * pkt->data. Total length is returned.
b185170a 1711 */
ff3187f6 1712static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)
32874aea 1713{
7cca0d81 1714 int cipherblk, maclen, padding, i;
7cca0d81 1715
a8327734 1716 if (ssh->logctx)
ff3187f6 1717 log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[5],
1718 ssh2_pkt_type(ssh->pkt_ctx, pkt->data[5]),
dacd8872 1719 pkt->body, pkt->length - (pkt->body - pkt->data),
ff3187f6 1720 pkt->nblanks, pkt->blanks);
1721 sfree(pkt->blanks); pkt->blanks = NULL;
1722 pkt->nblanks = 0;
00db133f 1723
7cca0d81 1724 /*
4ba9b64b 1725 * Compress packet payload.
1726 */
4ba9b64b 1727 {
1728 unsigned char *newpayload;
1729 int newlen;
51470298 1730 if (ssh->cscomp &&
ff3187f6 1731 ssh->cscomp->compress(ssh->cs_comp_ctx, pkt->data + 5,
1732 pkt->length - 5,
51470298 1733 &newpayload, &newlen)) {
ff3187f6 1734 pkt->length = 5;
1735 ssh2_pkt_adddata(pkt, newpayload, newlen);
dcbde236 1736 sfree(newpayload);
4ba9b64b 1737 }
1738 }
1739
1740 /*
7cca0d81 1741 * Add padding. At least four bytes, and must also bring total
1742 * length (minus MAC) up to a multiple of the block size.
95d2d262 1743 * If pkt->forcepad is set, make sure the packet is at least that size
1744 * after padding.
7cca0d81 1745 */
51470298 1746 cipherblk = ssh->cscipher ? ssh->cscipher->blksize : 8; /* block size */
32874aea 1747 cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
7cca0d81 1748 padding = 4;
95d2d262 1749 if (pkt->length + padding < pkt->forcepad)
1750 padding = pkt->forcepad - pkt->length;
32874aea 1751 padding +=
ff3187f6 1752 (cipherblk - (pkt->length + padding) % cipherblk) % cipherblk;
95d2d262 1753 assert(padding <= 255);
51470298 1754 maclen = ssh->csmac ? ssh->csmac->len : 0;
ff3187f6 1755 ssh2_pkt_ensure(pkt, pkt->length + padding + maclen);
1756 pkt->data[4] = padding;
7cca0d81 1757 for (i = 0; i < padding; i++)
ff3187f6 1758 pkt->data[pkt->length + i] = random_byte();
1759 PUT_32BIT(pkt->data, pkt->length + padding - 4);
51470298 1760 if (ssh->csmac)
ff3187f6 1761 ssh->csmac->generate(ssh->cs_mac_ctx, pkt->data,
1762 pkt->length + padding,
51470298 1763 ssh->v2_outgoing_sequence);
1764 ssh->v2_outgoing_sequence++; /* whether or not we MACed */
1765
1766 if (ssh->cscipher)
371e569c 1767 ssh->cscipher->encrypt(ssh->cs_cipher_ctx,
ff3187f6 1768 pkt->data, pkt->length + padding);
51470298 1769
9442dd57 1770 pkt->encrypted_len = pkt->length + padding;
1771
ff3187f6 1772 /* Ready-to-send packet starts at pkt->data. We return length. */
1773 return pkt->length + padding + maclen;
b185170a 1774}
1775
1776/*
590f6a5f 1777 * Routines called from the main SSH code to send packets. There
1778 * are quite a few of these, because we have two separate
1779 * mechanisms for delaying the sending of packets:
1780 *
1781 * - In order to send an IGNORE message and a password message in
1782 * a single fixed-length blob, we require the ability to
1783 * concatenate the encrypted forms of those two packets _into_ a
1784 * single blob and then pass it to our <network.h> transport
1785 * layer in one go. Hence, there's a deferment mechanism which
1786 * works after packet encryption.
1787 *
1788 * - In order to avoid sending any connection-layer messages
1789 * during repeat key exchange, we have to queue up any such
1790 * outgoing messages _before_ they are encrypted (and in
1791 * particular before they're allocated sequence numbers), and
1792 * then send them once we've finished.
1793 *
1794 * I call these mechanisms `defer' and `queue' respectively, so as
1795 * to distinguish them reasonably easily.
1796 *
1797 * The functions send_noqueue() and defer_noqueue() free the packet
1798 * structure they are passed. Every outgoing packet goes through
1799 * precisely one of these functions in its life; packets passed to
1800 * ssh2_pkt_send() or ssh2_pkt_defer() either go straight to one of
1801 * these or get queued, and then when the queue is later emptied
1802 * the packets are all passed to defer_noqueue().
97ab28d7 1803 *
1804 * When using a CBC-mode cipher, it's necessary to ensure that an
1805 * attacker can't provide data to be encrypted using an IV that they
1806 * know. We ensure this by prefixing each packet that might contain
1807 * user data with an SSH_MSG_IGNORE. This is done using the deferral
1808 * mechanism, so in this case send_noqueue() ends up redirecting to
1809 * defer_noqueue(). If you don't like this inefficiency, don't use
1810 * CBC.
b185170a 1811 */
590f6a5f 1812
97ab28d7 1813static void ssh2_pkt_defer_noqueue(Ssh, struct Packet *, int);
1814static void ssh_pkt_defersend(Ssh);
1815
590f6a5f 1816/*
2e85c969 1817 * Send an SSH-2 packet immediately, without queuing or deferring.
590f6a5f 1818 */
1819static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)
32874aea 1820{
5471d09a 1821 int len;
1822 int backlog;
97ab28d7 1823 if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) {
1824 /* We need to send two packets, so use the deferral mechanism. */
1825 ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
1826 ssh_pkt_defersend(ssh);
1827 return;
1828 }
ff3187f6 1829 len = ssh2_pkt_construct(ssh, pkt);
1830 backlog = sk_write(ssh->s, (char *)pkt->data, len);
5471d09a 1831 if (backlog > SSH_MAX_BACKLOG)
51470298 1832 ssh_throttle_all(ssh, 1, backlog);
9442dd57 1833
1834 ssh->outgoing_data_size += pkt->encrypted_len;
1835 if (!ssh->kex_in_progress &&
d57f70af 1836 ssh->max_data_size != 0 &&
1837 ssh->outgoing_data_size > ssh->max_data_size)
f382c87d 1838 do_ssh2_transport(ssh, "too much data sent", -1, NULL);
9442dd57 1839
ff3187f6 1840 ssh_free_packet(pkt);
b185170a 1841}
1842
1843/*
2e85c969 1844 * Defer an SSH-2 packet.
b185170a 1845 */
97ab28d7 1846static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt, int noignore)
32874aea 1847{
97ab28d7 1848 int len;
1849 if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) &&
1850 ssh->deferred_len == 0 && !noignore) {
1851 /*
1852 * Interpose an SSH_MSG_IGNORE to ensure that user data don't
1853 * get encrypted with a known IV.
1854 */
1855 struct Packet *ipkt = ssh2_pkt_init(SSH2_MSG_IGNORE);
1856 ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE);
1857 }
1858 len = ssh2_pkt_construct(ssh, pkt);
51470298 1859 if (ssh->deferred_len + len > ssh->deferred_size) {
1860 ssh->deferred_size = ssh->deferred_len + len + 128;
3d88e64d 1861 ssh->deferred_send_data = sresize(ssh->deferred_send_data,
1862 ssh->deferred_size,
1863 unsigned char);
b185170a 1864 }
ff3187f6 1865 memcpy(ssh->deferred_send_data + ssh->deferred_len, pkt->data, len);
51470298 1866 ssh->deferred_len += len;
9442dd57 1867 ssh->deferred_data_size += pkt->encrypted_len;
ff3187f6 1868 ssh_free_packet(pkt);
b185170a 1869}
1870
1871/*
2e85c969 1872 * Queue an SSH-2 packet.
590f6a5f 1873 */
1874static void ssh2_pkt_queue(Ssh ssh, struct Packet *pkt)
1875{
1876 assert(ssh->queueing);
1877
1878 if (ssh->queuelen >= ssh->queuesize) {
1879 ssh->queuesize = ssh->queuelen + 32;
1880 ssh->queue = sresize(ssh->queue, ssh->queuesize, struct Packet *);
1881 }
1882
1883 ssh->queue[ssh->queuelen++] = pkt;
1884}
1885
1886/*
1887 * Either queue or send a packet, depending on whether queueing is
1888 * set.
1889 */
1890static void ssh2_pkt_send(Ssh ssh, struct Packet *pkt)
1891{
1892 if (ssh->queueing)
1893 ssh2_pkt_queue(ssh, pkt);
1894 else
1895 ssh2_pkt_send_noqueue(ssh, pkt);
1896}
1897
95d2d262 1898#if 0 /* disused */
590f6a5f 1899/*
1900 * Either queue or defer a packet, depending on whether queueing is
1901 * set.
1902 */
1903static void ssh2_pkt_defer(Ssh ssh, struct Packet *pkt)
1904{
1905 if (ssh->queueing)
1906 ssh2_pkt_queue(ssh, pkt);
1907 else
97ab28d7 1908 ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
590f6a5f 1909}
95d2d262 1910#endif
590f6a5f 1911
1912/*
b185170a 1913 * Send the whole deferred data block constructed by
2e85c969 1914 * ssh2_pkt_defer() or SSH-1's defer_packet().
590f6a5f 1915 *
1916 * The expected use of the defer mechanism is that you call
1917 * ssh2_pkt_defer() a few times, then call ssh_pkt_defersend(). If
1918 * not currently queueing, this simply sets up deferred_send_data
1919 * and then sends it. If we _are_ currently queueing, the calls to
1920 * ssh2_pkt_defer() put the deferred packets on to the queue
1921 * instead, and therefore ssh_pkt_defersend() has no deferred data
1922 * to send. Hence, there's no need to make it conditional on
1923 * ssh->queueing.
b185170a 1924 */
51470298 1925static void ssh_pkt_defersend(Ssh ssh)
32874aea 1926{
5471d09a 1927 int backlog;
d8baa528 1928 backlog = sk_write(ssh->s, (char *)ssh->deferred_send_data,
1929 ssh->deferred_len);
51470298 1930 ssh->deferred_len = ssh->deferred_size = 0;
1931 sfree(ssh->deferred_send_data);
1932 ssh->deferred_send_data = NULL;
5471d09a 1933 if (backlog > SSH_MAX_BACKLOG)
51470298 1934 ssh_throttle_all(ssh, 1, backlog);
9442dd57 1935
1936 ssh->outgoing_data_size += ssh->deferred_data_size;
1937 if (!ssh->kex_in_progress &&
d57f70af 1938 ssh->max_data_size != 0 &&
1939 ssh->outgoing_data_size > ssh->max_data_size)
f382c87d 1940 do_ssh2_transport(ssh, "too much data sent", -1, NULL);
9442dd57 1941 ssh->deferred_data_size = 0;
7cca0d81 1942}
1943
590f6a5f 1944/*
2e85c969 1945 * Send all queued SSH-2 packets. We send them by means of
590f6a5f 1946 * ssh2_pkt_defer_noqueue(), in case they included a pair of
1947 * packets that needed to be lumped together.
1948 */
1949static void ssh2_pkt_queuesend(Ssh ssh)
1950{
1951 int i;
1952
1953 assert(!ssh->queueing);
1954
1955 for (i = 0; i < ssh->queuelen; i++)
97ab28d7 1956 ssh2_pkt_defer_noqueue(ssh, ssh->queue[i], FALSE);
590f6a5f 1957 ssh->queuelen = 0;
1958
1959 ssh_pkt_defersend(ssh);
1960}
1961
7cca0d81 1962#if 0
32874aea 1963void bndebug(char *string, Bignum b)
1964{
7cca0d81 1965 unsigned char *p;
1966 int i, len;
1967 p = ssh2_mpint_fmt(b, &len);
1968 debug(("%s", string));
1969 for (i = 0; i < len; i++)
32874aea 1970 debug((" %02x", p[i]));
765c4200 1971 debug(("\n"));
dcbde236 1972 sfree(p);
7cca0d81 1973}
1974#endif
1975
b672f405 1976static void hash_mpint(const struct ssh_hash *h, void *s, Bignum b)
32874aea 1977{
7cca0d81 1978 unsigned char *p;
1979 int len;
1980 p = ssh2_mpint_fmt(b, &len);
b672f405 1981 hash_string(h, s, p, len);
dcbde236 1982 sfree(p);
7cca0d81 1983}
1984
1985/*
2e85c969 1986 * Packet decode functions for both SSH-1 and SSH-2.
7cca0d81 1987 */
ff3187f6 1988static unsigned long ssh_pkt_getuint32(struct Packet *pkt)
32874aea 1989{
7cca0d81 1990 unsigned long value;
ff3187f6 1991 if (pkt->length - pkt->savedpos < 4)
32874aea 1992 return 0; /* arrgh, no way to decline (FIXME?) */
ff3187f6 1993 value = GET_32BIT(pkt->body + pkt->savedpos);
1994 pkt->savedpos += 4;
7cca0d81 1995 return value;
1996}
ff3187f6 1997static int ssh2_pkt_getbool(struct Packet *pkt)
32874aea 1998{
65a22376 1999 unsigned long value;
ff3187f6 2000 if (pkt->length - pkt->savedpos < 1)
32874aea 2001 return 0; /* arrgh, no way to decline (FIXME?) */
ff3187f6 2002 value = pkt->body[pkt->savedpos] != 0;
2003 pkt->savedpos++;
65a22376 2004 return value;
2005}
ff3187f6 2006static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length)
32874aea 2007{
57356d63 2008 int len;
7cca0d81 2009 *p = NULL;
45068b27 2010 *length = 0;
ff3187f6 2011 if (pkt->length - pkt->savedpos < 4)
32874aea 2012 return;
ff3187f6 2013 len = GET_32BIT(pkt->body + pkt->savedpos);
57356d63 2014 if (len < 0)
2015 return;
2016 *length = len;
ff3187f6 2017 pkt->savedpos += 4;
2018 if (pkt->length - pkt->savedpos < *length)
32874aea 2019 return;
ff3187f6 2020 *p = (char *)(pkt->body + pkt->savedpos);
2021 pkt->savedpos += *length;
7cca0d81 2022}
ff3187f6 2023static void *ssh_pkt_getdata(struct Packet *pkt, int length)
0016d70b 2024{
ff3187f6 2025 if (pkt->length - pkt->savedpos < length)
0016d70b 2026 return NULL;
ff3187f6 2027 pkt->savedpos += length;
2028 return pkt->body + (pkt->savedpos - length);
0016d70b 2029}
ff3187f6 2030static int ssh1_pkt_getrsakey(struct Packet *pkt, struct RSAKey *key,
0016d70b 2031 unsigned char **keystr)
2032{
2033 int j;
2034
ff3187f6 2035 j = makekey(pkt->body + pkt->savedpos,
2036 pkt->length - pkt->savedpos,
0016d70b 2037 key, keystr, 0);
2038
2039 if (j < 0)
2040 return FALSE;
2041
ff3187f6 2042 pkt->savedpos += j;
2043 assert(pkt->savedpos < pkt->length);
0016d70b 2044
2045 return TRUE;
2046}
ff3187f6 2047static Bignum ssh1_pkt_getmp(struct Packet *pkt)
0016d70b 2048{
2049 int j;
2050 Bignum b;
2051
ff3187f6 2052 j = ssh1_read_bignum(pkt->body + pkt->savedpos,
2053 pkt->length - pkt->savedpos, &b);
0016d70b 2054
2055 if (j < 0)
2056 return NULL;
2057
ff3187f6 2058 pkt->savedpos += j;
0016d70b 2059 return b;
2060}
ff3187f6 2061static Bignum ssh2_pkt_getmp(struct Packet *pkt)
32874aea 2062{
7cca0d81 2063 char *p;
3709bfe9 2064 int length;
7cca0d81 2065 Bignum b;
2066
ff3187f6 2067 ssh_pkt_getstring(pkt, &p, &length);
7cca0d81 2068 if (!p)
32874aea 2069 return NULL;
ff3187f6 2070 if (p[0] & 0x80)
32874aea 2071 return NULL;
d8baa528 2072 b = bignum_from_bytes((unsigned char *)p, length);
7cca0d81 2073 return b;
2074}
2075
7d503c31 2076/*
2e85c969 2077 * Helper function to add an SSH-2 signature blob to a packet.
1dd353b5 2078 * Expects to be shown the public key blob as well as the signature
2079 * blob. Normally works just like ssh2_pkt_addstring, but will
2080 * fiddle with the signature packet if necessary for
2081 * BUG_SSH2_RSA_PADDING.
2082 */
ff3187f6 2083static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
2084 void *pkblob_v, int pkblob_len,
1dd353b5 2085 void *sigblob_v, int sigblob_len)
2086{
2087 unsigned char *pkblob = (unsigned char *)pkblob_v;
2088 unsigned char *sigblob = (unsigned char *)sigblob_v;
2089
2090 /* dmemdump(pkblob, pkblob_len); */
2091 /* dmemdump(sigblob, sigblob_len); */
2092
2093 /*
2094 * See if this is in fact an ssh-rsa signature and a buggy
2095 * server; otherwise we can just do this the easy way.
2096 */
51470298 2097 if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&
1dd353b5 2098 (GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
2099 int pos, len, siglen;
2100
2101 /*
2102 * Find the byte length of the modulus.
2103 */
2104
2105 pos = 4+7; /* skip over "ssh-rsa" */
2106 pos += 4 + GET_32BIT(pkblob+pos); /* skip over exponent */
2107 len = GET_32BIT(pkblob+pos); /* find length of modulus */
2108 pos += 4; /* find modulus itself */
2109 while (len > 0 && pkblob[pos] == 0)
2110 len--, pos++;
2111 /* debug(("modulus length is %d\n", len)); */
2112
2113 /*
2114 * Now find the signature integer.
2115 */
2116 pos = 4+7; /* skip over "ssh-rsa" */
2117 siglen = GET_32BIT(sigblob+pos);
2118 /* debug(("signature length is %d\n", siglen)); */
2119
2120 if (len != siglen) {
2121 unsigned char newlen[4];
ff3187f6 2122 ssh2_pkt_addstring_start(pkt);
2123 ssh2_pkt_addstring_data(pkt, (char *)sigblob, pos);
1dd353b5 2124 /* dmemdump(sigblob, pos); */
2125 pos += 4; /* point to start of actual sig */
2126 PUT_32BIT(newlen, len);
ff3187f6 2127 ssh2_pkt_addstring_data(pkt, (char *)newlen, 4);
1dd353b5 2128 /* dmemdump(newlen, 4); */
2129 newlen[0] = 0;
2130 while (len-- > siglen) {
ff3187f6 2131 ssh2_pkt_addstring_data(pkt, (char *)newlen, 1);
1dd353b5 2132 /* dmemdump(newlen, 1); */
2133 }
ff3187f6 2134 ssh2_pkt_addstring_data(pkt, (char *)(sigblob+pos), siglen);
1dd353b5 2135 /* dmemdump(sigblob+pos, siglen); */
2136 return;
2137 }
2138
2139 /* Otherwise fall through and do it the easy way. */
2140 }
2141
ff3187f6 2142 ssh2_pkt_addstring_start(pkt);
2143 ssh2_pkt_addstring_data(pkt, (char *)sigblob, sigblob_len);
1dd353b5 2144}
2145
2146/*
7d503c31 2147 * Examine the remote side's version string and compare it against
2148 * a list of known buggy implementations.
2149 */
51470298 2150static void ssh_detect_bugs(Ssh ssh, char *vstring)
32874aea 2151{
2152 char *imp; /* pointer to implementation part */
7d503c31 2153 imp = vstring;
2154 imp += strcspn(imp, "-");
bd358db1 2155 if (*imp) imp++;
7d503c31 2156 imp += strcspn(imp, "-");
bd358db1 2157 if (*imp) imp++;
7d503c31 2158
51470298 2159 ssh->remote_bugs = 0;
7d503c31 2160
5ecd7ad0 2161 if (ssh->cfg.sshbug_ignore1 == FORCE_ON ||
2162 (ssh->cfg.sshbug_ignore1 == AUTO &&
2c9c6388 2163 (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
2164 !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
46ac09aa 2165 !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||
bd0b4caf 2166 !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {
32874aea 2167 /*
2168 * These versions don't support SSH1_MSG_IGNORE, so we have
2169 * to use a different defence against password length
2170 * sniffing.
2171 */
51470298 2172 ssh->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
2e85c969 2173 logevent("We believe remote version has SSH-1 ignore bug");
7d503c31 2174 }
2175
5ecd7ad0 2176 if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||
2177 (ssh->cfg.sshbug_plainpw1 == AUTO &&
46ac09aa 2178 (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {
bd358db1 2179 /*
2180 * These versions need a plain password sent; they can't
2181 * handle having a null and a random length of data after
2182 * the password.
2183 */
51470298 2184 ssh->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
2e85c969 2185 logevent("We believe remote version needs a plain SSH-1 password");
bd358db1 2186 }
2187
5ecd7ad0 2188 if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||
2189 (ssh->cfg.sshbug_rsa1 == AUTO &&
2c9c6388 2190 (!strcmp(imp, "Cisco-1.25")))) {
0df73905 2191 /*
2192 * These versions apparently have no clue whatever about
2193 * RSA authentication and will panic and die if they see
2194 * an AUTH_RSA message.
2195 */
51470298 2196 ssh->remote_bugs |= BUG_CHOKES_ON_RSA;
19f47a7d 2197 logevent("We believe remote version can't handle SSH-1 RSA authentication");
0df73905 2198 }
2199
5ecd7ad0 2200 if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||
2201 (ssh->cfg.sshbug_hmac2 == AUTO &&
b9f387af 2202 !wc_match("* VShell", imp) &&
831301f6 2203 (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
2204 wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
2205 wc_match("2.1 *", imp)))) {
32874aea 2206 /*
2207 * These versions have the HMAC bug.
2208 */
51470298 2209 ssh->remote_bugs |= BUG_SSH2_HMAC;
2e85c969 2210 logevent("We believe remote version has SSH-2 HMAC bug");
7d503c31 2211 }
1dd353b5 2212
5ecd7ad0 2213 if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||
2214 (ssh->cfg.sshbug_derivekey2 == AUTO &&
b9f387af 2215 !wc_match("* VShell", imp) &&
2856a1b9 2216 (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {
088bde77 2217 /*
2218 * These versions have the key-derivation bug (failing to
2219 * include the literal shared secret in the hashes that
2220 * generate the keys).
2221 */
51470298 2222 ssh->remote_bugs |= BUG_SSH2_DERIVEKEY;
2e85c969 2223 logevent("We believe remote version has SSH-2 key-derivation bug");
088bde77 2224 }
2225
5ecd7ad0 2226 if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||
2227 (ssh->cfg.sshbug_rsapad2 == AUTO &&
831301f6 2228 (wc_match("OpenSSH_2.[5-9]*", imp) ||
2229 wc_match("OpenSSH_3.[0-2]*", imp)))) {
1dd353b5 2230 /*
2e85c969 2231 * These versions have the SSH-2 RSA padding bug.
1dd353b5 2232 */
51470298 2233 ssh->remote_bugs |= BUG_SSH2_RSA_PADDING;
2e85c969 2234 logevent("We believe remote version has SSH-2 RSA padding bug");
1dd353b5 2235 }
8e975795 2236
dda87a28 2237 if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||
2238 (ssh->cfg.sshbug_pksessid2 == AUTO &&
2239 wc_match("OpenSSH_2.[0-2]*", imp))) {
2240 /*
2e85c969 2241 * These versions have the SSH-2 session-ID bug in
dda87a28 2242 * public-key authentication.
2243 */
2244 ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;
2e85c969 2245 logevent("We believe remote version has SSH-2 public-key-session-ID bug");
dda87a28 2246 }
f382c87d 2247
2248 if (ssh->cfg.sshbug_rekey2 == FORCE_ON ||
2249 (ssh->cfg.sshbug_rekey2 == AUTO &&
39b8712f 2250 (wc_match("DigiSSH_2.0", imp) ||
2251 wc_match("OpenSSH_2.[0-4]*", imp) ||
e12d95a5 2252 wc_match("OpenSSH_2.5.[0-3]*", imp) ||
2253 wc_match("Sun_SSH_1.0", imp) ||
f4275b53 2254 wc_match("Sun_SSH_1.0.1", imp) ||
96bd26de 2255 /* All versions <= 1.2.6 (they changed their format in 1.2.7) */
2256 wc_match("WeOnlyDo-*", imp)))) {
f382c87d 2257 /*
2e85c969 2258 * These versions have the SSH-2 rekey bug.
f382c87d 2259 */
2260 ssh->remote_bugs |= BUG_SSH2_REKEY;
2e85c969 2261 logevent("We believe remote version has SSH-2 rekey bug");
f382c87d 2262 }
7d503c31 2263}
2264
d38d6a1f 2265/*
2266 * The `software version' part of an SSH version string is required
2267 * to contain no spaces or minus signs.
2268 */
2269static void ssh_fix_verstring(char *str)
2270{
2271 /* Eat "SSH-<protoversion>-". */
2272 assert(*str == 'S'); str++;
2273 assert(*str == 'S'); str++;
2274 assert(*str == 'H'); str++;
2275 assert(*str == '-'); str++;
2276 while (*str && *str != '-') str++;
2277 assert(*str == '-'); str++;
2278
2279 /* Convert minus signs and spaces in the remaining string into
2280 * underscores. */
2281 while (*str) {
2282 if (*str == '-' || *str == ' ')
2283 *str = '_';
2284 str++;
2285 }
2286}
2287
51470298 2288static int do_ssh_init(Ssh ssh, unsigned char c)
32874aea 2289{
51470298 2290 struct do_ssh_init_state {
2291 int vslen;
2292 char version[10];
2293 char *vstring;
2294 int vstrsize;
2295 int i;
2296 int proto1, proto2;
2297 };
2298 crState(do_ssh_init_state);
374330e2 2299
51470298 2300 crBegin(ssh->do_ssh_init_crstate);
8df7a775 2301
8c1835c0 2302 /* Search for a line beginning with the string "SSH-" in the input. */
2303 for (;;) {
2304 if (c != 'S') goto no;
2305 crReturn(1);
2306 if (c != 'S') goto no;
2307 crReturn(1);
2308 if (c != 'H') goto no;
2309 crReturn(1);
2310 if (c != '-') goto no;
2311 break;
2312 no:
2313 while (c != '\012')
2314 crReturn(1);
2315 crReturn(1);
374330e2 2316 }
8df7a775 2317
51470298 2318 s->vstrsize = 16;
3d88e64d 2319 s->vstring = snewn(s->vstrsize, char);
51470298 2320 strcpy(s->vstring, "SSH-");
2321 s->vslen = 4;
2322 s->i = 0;
374330e2 2323 while (1) {
8df7a775 2324 crReturn(1); /* get another char */
51470298 2325 if (s->vslen >= s->vstrsize - 1) {
2326 s->vstrsize += 16;
3d88e64d 2327 s->vstring = sresize(s->vstring, s->vstrsize, char);
32874aea 2328 }
51470298 2329 s->vstring[s->vslen++] = c;
2330 if (s->i >= 0) {
374330e2 2331 if (c == '-') {
51470298 2332 s->version[s->i] = '\0';
2333 s->i = -1;
2334 } else if (s->i < sizeof(s->version) - 1)
2335 s->version[s->i++] = c;
c4ffc4d0 2336 } else if (c == '\012')
374330e2 2337 break;
2338 }
2339
51470298 2340 ssh->agentfwd_enabled = FALSE;
2341 ssh->rdpkt2_state.incoming_sequence = 0;
960e736a 2342
51470298 2343 s->vstring[s->vslen] = 0;
a7d4653a 2344 s->vstring[strcspn(s->vstring, "\015\012")] = '\0';/* remove EOL chars */
fb983202 2345 logeventf(ssh, "Server version: %s", s->vstring);
51470298 2346 ssh_detect_bugs(ssh, s->vstring);
c5e9c988 2347
adf799dd 2348 /*
38d228a2 2349 * Decide which SSH protocol version to support.
adf799dd 2350 */
38d228a2 2351
2352 /* Anything strictly below "2.0" means protocol 1 is supported. */
51470298 2353 s->proto1 = ssh_versioncmp(s->version, "2.0") < 0;
38d228a2 2354 /* Anything greater or equal to "1.99" means protocol 2 is supported. */
51470298 2355 s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
38d228a2 2356
86916870 2357 if (ssh->cfg.sshprot == 0 && !s->proto1) {
6b5cf8b4 2358 bombout(("SSH protocol version 1 required by user but not provided by server"));
7ffdbc1a 2359 crStop(0);
38d228a2 2360 }
86916870 2361 if (ssh->cfg.sshprot == 3 && !s->proto2) {
6b5cf8b4 2362 bombout(("SSH protocol version 2 required by user but not provided by server"));
7ffdbc1a 2363 crStop(0);
38d228a2 2364 }
2365
d38d6a1f 2366 {
2367 char *verstring;
2368
2369 if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1)) {
2370 /*
2371 * Construct a v2 version string.
2372 */
a7d4653a 2373 verstring = dupprintf("SSH-2.0-%s\015\012", sshver);
d38d6a1f 2374 ssh->version = 2;
2375 } else {
2376 /*
2377 * Construct a v1 version string.
2378 */
a7d4653a 2379 verstring = dupprintf("SSH-%s-%s\012",
d38d6a1f 2380 (ssh_versioncmp(s->version, "1.5") <= 0 ?
2381 s->version : "1.5"),
2382 sshver);
2383 ssh->version = 1;
2384 }
2385
2386 ssh_fix_verstring(verstring);
2387
2388 if (ssh->version == 2) {
4320baf7 2389 size_t len;
d38d6a1f 2390 /*
2391 * Hash our version string and their version string.
2392 */
4320baf7 2393 len = strcspn(verstring, "\015\012");
2394 ssh->v_c = snewn(len + 1, char);
2395 memcpy(ssh->v_c, verstring, len);
2396 ssh->v_c[len] = 0;
2397 len = strcspn(s->vstring, "\015\012");
2398 ssh->v_s = snewn(len + 1, char);
2399 memcpy(ssh->v_s, s->vstring, len);
2400 ssh->v_s[len] = 0;
2401
d38d6a1f 2402 /*
2e85c969 2403 * Initialise SSH-2 protocol.
d38d6a1f 2404 */
2405 ssh->protocol = ssh2_protocol;
2406 ssh2_protocol_setup(ssh);
2407 ssh->s_rdpkt = ssh2_rdpkt;
2408 } else {
2409 /*
2e85c969 2410 * Initialise SSH-1 protocol.
d38d6a1f 2411 */
2412 ssh->protocol = ssh1_protocol;
2413 ssh1_protocol_setup(ssh);
2414 ssh->s_rdpkt = ssh1_rdpkt;
2415 }
2416 logeventf(ssh, "We claim version: %.*s",
a7d4653a 2417 strcspn(verstring, "\015\012"), verstring);
51470298 2418 sk_write(ssh->s, verstring, strlen(verstring));
d38d6a1f 2419 sfree(verstring);
f475e40a 2420 if (ssh->version == 2)
6a755251 2421 do_ssh2_transport(ssh, NULL, -1, NULL);
e5574168 2422 }
d38d6a1f 2423
2424 logeventf(ssh, "Using SSH protocol version %d", ssh->version);
2425
125105d1 2426 update_specials_menu(ssh->frontend);
51470298 2427 ssh->state = SSH_STATE_BEFORE_SIZE;
39934deb 2428 ssh->pinger = pinger_new(&ssh->cfg, &ssh_backend, ssh);
8df7a775 2429
51470298 2430 sfree(s->vstring);
50526e47 2431
8df7a775 2432 crFinish(0);
2433}
2434
3d9449a1 2435static void ssh_process_incoming_data(Ssh ssh,
2436 unsigned char **data, int *datalen)
2437{
2438 struct Packet *pktin = ssh->s_rdpkt(ssh, data, datalen);
2439 if (pktin) {
2440 ssh->protocol(ssh, NULL, 0, pktin);
2441 ssh_free_packet(pktin);
2442 }
2443}
2444
2445static void ssh_queue_incoming_data(Ssh ssh,
2446 unsigned char **data, int *datalen)
2447{
2448 bufchain_add(&ssh->queued_incoming_data, *data, *datalen);
2449 *data += *datalen;
2450 *datalen = 0;
2451}
2452
2453static void ssh_process_queued_incoming_data(Ssh ssh)
2454{
2455 void *vdata;
2456 unsigned char *data;
2457 int len, origlen;
2458
2459 while (!ssh->frozen && bufchain_size(&ssh->queued_incoming_data)) {
2460 bufchain_prefix(&ssh->queued_incoming_data, &vdata, &len);
2461 data = vdata;
2462 origlen = len;
2463
2464 while (!ssh->frozen && len > 0)
2465 ssh_process_incoming_data(ssh, &data, &len);
2466
2467 if (origlen > len)
2468 bufchain_consume(&ssh->queued_incoming_data, origlen - len);
2469 }
2470}
2471
2472static void ssh_set_frozen(Ssh ssh, int frozen)
2473{
a5a6f839 2474 if (ssh->s)
2475 sk_set_frozen(ssh->s, frozen);
3d9449a1 2476 ssh->frozen = frozen;
2477}
2478
51470298 2479static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)
8df7a775 2480{
51470298 2481 crBegin(ssh->ssh_gotdata_crstate);
8df7a775 2482
2483 /*
2484 * To begin with, feed the characters one by one to the
2485 * protocol initialisation / selection function do_ssh_init().
2486 * When that returns 0, we're done with the initial greeting
2487 * exchange and can move on to packet discipline.
2488 */
2489 while (1) {
51470298 2490 int ret; /* need not be kept across crReturn */
8df7a775 2491 if (datalen == 0)
2492 crReturnV; /* more data please */
51470298 2493 ret = do_ssh_init(ssh, *data);
32874aea 2494 data++;
2495 datalen--;
8df7a775 2496 if (ret == 0)
2497 break;
2498 }
2499
2500 /*
2501 * We emerge from that loop when the initial negotiation is
2502 * over and we have selected an s_rdpkt function. Now pass
2503 * everything to s_rdpkt, and then pass the resulting packets
2504 * to the proper protocol handler.
2505 */
3d9449a1 2506
8df7a775 2507 while (1) {
e375106c 2508 while (bufchain_size(&ssh->queued_incoming_data) > 0 || datalen > 0) {
2509 if (ssh->frozen) {
3d9449a1 2510 ssh_queue_incoming_data(ssh, &data, &datalen);
e375106c 2511 /* This uses up all data and cannot cause anything interesting
2512 * to happen; indeed, for anything to happen at all, we must
2513 * return, so break out. */
2514 break;
2515 } else if (bufchain_size(&ssh->queued_incoming_data) > 0) {
2516 /* This uses up some or all data, and may freeze the
2517 * session. */
2518 ssh_process_queued_incoming_data(ssh);
2519 } else {
2520 /* This uses up some or all data, and may freeze the
2521 * session. */
2522 ssh_process_incoming_data(ssh, &data, &datalen);
2523 }
2524 /* FIXME this is probably EBW. */
ff3187f6 2525 if (ssh->state == SSH_STATE_CLOSED)
2526 return;
8df7a775 2527 }
e375106c 2528 /* We're out of data. Go and get some more. */
8df7a775 2529 crReturnV;
2530 }
2531 crFinishV;
2532}
2533
ac934965 2534static int ssh_do_close(Ssh ssh, int notify_exit)
32874aea 2535{
80ffa58b 2536 int ret = 0;
36f94d1f 2537 struct ssh_channel *c;
2538
51470298 2539 ssh->state = SSH_STATE_CLOSED;
ecbb0000 2540 expire_timer_context(ssh);
51470298 2541 if (ssh->s) {
2542 sk_close(ssh->s);
2543 ssh->s = NULL;
ac934965 2544 if (notify_exit)
2545 notify_remote_exit(ssh->frontend);
2546 else
2547 ret = 1;
f3ab576e 2548 }
36f94d1f 2549 /*
80ffa58b 2550 * Now we must shut down any port- and X-forwarded channels going
36f94d1f 2551 * through this connection.
2552 */
74a98066 2553 if (ssh->channels) {
80ffa58b 2554 while (NULL != (c = index234(ssh->channels, 0))) {
74a98066 2555 switch (c->type) {
2556 case CHAN_X11:
2557 x11_close(c->u.x11.s);
2558 break;
2559 case CHAN_SOCKDATA:
2560 pfd_close(c->u.pfd.s);
2561 break;
2562 }
80ffa58b 2563 del234(ssh->channels, c); /* moving next one to index 0 */
74a98066 2564 if (ssh->version == 2)
2565 bufchain_clear(&c->v.v2.outbuffer);
2566 sfree(c);
36f94d1f 2567 }
36f94d1f 2568 }
f8c9f9df 2569 /*
2570 * Go through port-forwardings, and close any associated
2571 * listening sockets.
2572 */
2573 if (ssh->portfwds) {
2574 struct ssh_portfwd *pf;
2575 while (NULL != (pf = index234(ssh->portfwds, 0))) {
2576 /* Dispose of any listening socket. */
2577 if (pf->local)
2578 pfd_terminate(pf->local);
2579 del234(ssh->portfwds, pf); /* moving next one to index 0 */
2580 free_portfwd(pf);
2581 }
2582 }
ac934965 2583
2584 return ret;
36f94d1f 2585}
2586
7555d6a5 2587static void ssh_log(Plug plug, int type, SockAddr addr, int port,
2588 const char *error_msg, int error_code)
2589{
2590 Ssh ssh = (Ssh) plug;
2591 char addrbuf[256], *msg;
2592
2593 sk_getaddr(addr, addrbuf, lenof(addrbuf));
2594
2595 if (type == 0)
2596 msg = dupprintf("Connecting to %s port %d", addrbuf, port);
2597 else
2598 msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
2599
2600 logevent(msg);
fb983202 2601 sfree(msg);
7555d6a5 2602}
2603
cbe2d68f 2604static int ssh_closing(Plug plug, const char *error_msg, int error_code,
36f94d1f 2605 int calling_back)
2606{
2607 Ssh ssh = (Ssh) plug;
ac934965 2608 int need_notify = ssh_do_close(ssh, FALSE);
2609
9e296bfa 2610 if (!error_msg) {
2611 if (!ssh->close_expected)
2612 error_msg = "Server unexpectedly closed network connection";
2613 else
2614 error_msg = "Server closed network connection";
ac934965 2615 }
2616
2425184b 2617 if (need_notify)
2618 notify_remote_exit(ssh->frontend);
2619
9e296bfa 2620 if (error_msg)
247308b5 2621 logevent(error_msg);
9e296bfa 2622 if (!ssh->close_expected || !ssh->clean_exit)
971bcc0a 2623 connection_fatal(ssh->frontend, "%s", error_msg);
7e78000d 2624 return 0;
2625}
2626
32874aea 2627static int ssh_receive(Plug plug, int urgent, char *data, int len)
2628{
51470298 2629 Ssh ssh = (Ssh) plug;
d8baa528 2630 ssh_gotdata(ssh, (unsigned char *)data, len);
51470298 2631 if (ssh->state == SSH_STATE_CLOSED) {
ac934965 2632 ssh_do_close(ssh, TRUE);
32874aea 2633 return 0;
3257deae 2634 }
fef97f43 2635 return 1;
374330e2 2636}
2637
5471d09a 2638static void ssh_sent(Plug plug, int bufsize)
2639{
51470298 2640 Ssh ssh = (Ssh) plug;
5471d09a 2641 /*
2642 * If the send backlog on the SSH socket itself clears, we
2643 * should unthrottle the whole world if it was throttled.
2644 */
2645 if (bufsize < SSH_MAX_BACKLOG)
51470298 2646 ssh_throttle_all(ssh, 0, bufsize);
5471d09a 2647}
2648
fb09bf1c 2649/*
8df7a775 2650 * Connect to specified host and port.
2651 * Returns an error message, or NULL on success.
6e1ebb76 2652 * Also places the canonical host name into `realhost'. It must be
2653 * freed by the caller.
8df7a775 2654 */
cbe2d68f 2655static const char *connect_to_host(Ssh ssh, char *host, int port,
79bf227b 2656 char **realhost, int nodelay, int keepalive)
8df7a775 2657{
51470298 2658 static const struct plug_function_table fn_table = {
7555d6a5 2659 ssh_log,
7e78000d 2660 ssh_closing,
5471d09a 2661 ssh_receive,
2662 ssh_sent,
2663 NULL
51470298 2664 };
7e78000d 2665
8df7a775 2666 SockAddr addr;
cbe2d68f 2667 const char *err;
8df7a775 2668
3d88e64d 2669 ssh->savedhost = snewn(1 + strlen(host), char);
51470298 2670 strcpy(ssh->savedhost, host);
8df7a775 2671
2672 if (port < 0)
2673 port = 22; /* default ssh port */
51470298 2674 ssh->savedport = port;
8df7a775 2675
2676 /*
2677 * Try to find host.
2678 */
05581745 2679 logeventf(ssh, "Looking up host \"%s\"%s", host,
2680 (ssh->cfg.addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
2681 (ssh->cfg.addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
2682 addr = name_lookup(host, port, realhost, &ssh->cfg,
2683 ssh->cfg.addressfamily);
170c1e6e 2684 if ((err = sk_addr_error(addr)) != NULL) {
2685 sk_addr_free(addr);
8df7a775 2686 return err;
170c1e6e 2687 }
8df7a775 2688
8df7a775 2689 /*
2690 * Open socket.
2691 */
51470298 2692 ssh->fn = &fn_table;
e8fa8f62 2693 ssh->s = new_connection(addr, *realhost, port,
79bf227b 2694 0, 1, nodelay, keepalive, (Plug) ssh, &ssh->cfg);
70e5d0fd 2695 if ((err = sk_socket_error(ssh->s)) != NULL) {
51470298 2696 ssh->s = NULL;
39934deb 2697 notify_remote_exit(ssh->frontend);
8df7a775 2698 return err;
67c4ba2e 2699 }
8df7a775 2700
8df7a775 2701 return NULL;
2702}
2703
2704/*
5471d09a 2705 * Throttle or unthrottle the SSH connection.
2706 */
51470298 2707static void ssh1_throttle(Ssh ssh, int adjust)
5471d09a 2708{
51470298 2709 int old_count = ssh->v1_throttle_count;
2710 ssh->v1_throttle_count += adjust;
2711 assert(ssh->v1_throttle_count >= 0);
2712 if (ssh->v1_throttle_count && !old_count) {
3d9449a1 2713 ssh_set_frozen(ssh, 1);
51470298 2714 } else if (!ssh->v1_throttle_count && old_count) {
3d9449a1 2715 ssh_set_frozen(ssh, 0);
5471d09a 2716 }
2717}
2718
2719/*
2720 * Throttle or unthrottle _all_ local data streams (for when sends
2721 * on the SSH connection itself back up).
2722 */
51470298 2723static void ssh_throttle_all(Ssh ssh, int enable, int bufsize)
5471d09a 2724{
2725 int i;
2726 struct ssh_channel *c;
2727
51470298 2728 if (enable == ssh->throttled_all)
5471d09a 2729 return;
51470298 2730 ssh->throttled_all = enable;
2731 ssh->overall_bufsize = bufsize;
2732 if (!ssh->channels)
5471d09a 2733 return;
51470298 2734 for (i = 0; NULL != (c = index234(ssh->channels, i)); i++) {
5471d09a 2735 switch (c->type) {
2736 case CHAN_MAINSESSION:
2737 /*
2738 * This is treated separately, outside the switch.
2739 */
2740 break;
2741 case CHAN_X11:
2742 x11_override_throttle(c->u.x11.s, enable);
2743 break;
2744 case CHAN_AGENT:
2745 /* Agent channels require no buffer management. */
2746 break;
2747 case CHAN_SOCKDATA:
36f94d1f 2748 pfd_override_throttle(c->u.pfd.s, enable);
5471d09a 2749 break;
2750 }
2751 }
2752}
2753
2754/*
51470298 2755 * Username and password input, abstracted off into routines
2e85c969 2756 * reusable in several places - even between SSH-1 and SSH-2.
0405e71f 2757 */
0405e71f 2758
2759/* Set up a username or password input loop on a given buffer. */
ae9ae89f 2760static void setup_userpass_input(Ssh ssh, char *buffer, int buflen, int echo)
0405e71f 2761{
51470298 2762 ssh->userpass_input_buffer = buffer;
2763 ssh->userpass_input_buflen = buflen;
2764 ssh->userpass_input_bufpos = 0;
2765 ssh->userpass_input_echo = echo;
0405e71f 2766}
2767
2768/*
2769 * Process some terminal data in the course of username/password
2770 * input. Returns >0 for success (line of input returned in
2771 * buffer), <0 for failure (user hit ^C/^D, bomb out and exit), 0
2772 * for inconclusive (keep waiting for more input please).
2773 */
ae9ae89f 2774static int process_userpass_input(Ssh ssh, unsigned char *in, int inlen)
0405e71f 2775{
2776 char c;
2777
2778 while (inlen--) {
2779 switch (c = *in++) {
2780 case 10:
2781 case 13:
51470298 2782 ssh->userpass_input_buffer[ssh->userpass_input_bufpos] = 0;
2783 ssh->userpass_input_buffer[ssh->userpass_input_buflen-1] = 0;
0405e71f 2784 return +1;
2785 break;
2786 case 8:
2787 case 127:
51470298 2788 if (ssh->userpass_input_bufpos > 0) {
2789 if (ssh->userpass_input_echo)
2790 c_write_str(ssh, "\b \b");
2791 ssh->userpass_input_bufpos--;
0405e71f 2792 }
2793 break;
2794 case 21:
2795 case 27:
51470298 2796 while (ssh->userpass_input_bufpos > 0) {
2797 if (ssh->userpass_input_echo)
2798 c_write_str(ssh, "\b \b");
2799 ssh->userpass_input_bufpos--;
0405e71f 2800 }
2801 break;
2802 case 3:
2803 case 4:
2804 return -1;
2805 break;
2806 default:
4692a14a 2807 /*
2808 * This simplistic check for printability is disabled
2809 * when we're doing password input, because some people
2810 * have control characters in their passwords.o
2811 */
2812 if ((!ssh->userpass_input_echo ||
2813 (c >= ' ' && c <= '~') ||
0405e71f 2814 ((unsigned char) c >= 160))
51470298 2815 && ssh->userpass_input_bufpos < ssh->userpass_input_buflen-1) {
2816 ssh->userpass_input_buffer[ssh->userpass_input_bufpos++] = c;
2817 if (ssh->userpass_input_echo)
2818 c_write(ssh, &c, 1);
0405e71f 2819 }
2820 break;
2821 }
2822 }
2823 return 0;
2824}
2825
f11d78f2 2826static void ssh_agent_callback(void *sshv, void *reply, int replylen)
839f10db 2827{
2828 Ssh ssh = (Ssh) sshv;
2829
2830 ssh->agent_response = reply;
2831 ssh->agent_response_len = replylen;
2832
2833 if (ssh->version == 1)
ff3187f6 2834 do_ssh1_login(ssh, NULL, -1, NULL);
839f10db 2835 else
ff3187f6 2836 do_ssh2_authconn(ssh, NULL, -1, NULL);
839f10db 2837}
2838
3d9449a1 2839static void ssh_dialog_callback(void *sshv, int ret)
2840{
2841 Ssh ssh = (Ssh) sshv;
2842
2843 ssh->user_response = ret;
2844
2845 if (ssh->version == 1)
2846 do_ssh1_login(ssh, NULL, -1, NULL);
2847 else
2848 do_ssh2_transport(ssh, NULL, -1, NULL);
2849
2850 /*
2851 * This may have unfrozen the SSH connection, so do a
2852 * queued-data run.
2853 */
2854 ssh_process_queued_incoming_data(ssh);
2855}
2856
f11d78f2 2857static void ssh_agentf_callback(void *cv, void *reply, int replylen)
839f10db 2858{
2859 struct ssh_channel *c = (struct ssh_channel *)cv;
2860 Ssh ssh = c->ssh;
2861 void *sentreply = reply;
2862
2863 if (!sentreply) {
2864 /* Fake SSH_AGENT_FAILURE. */
2865 sentreply = "\0\0\0\1\5";
2866 replylen = 5;
2867 }
2868 if (ssh->version == 2) {
2869 ssh2_add_channel_data(c, sentreply, replylen);
2870 ssh2_try_send(c);
2871 } else {
2872 send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
2873 PKT_INT, c->remoteid,
9a10ecf4 2874 PKTT_DATA,
839f10db 2875 PKT_INT, replylen,
2876 PKT_DATA, sentreply, replylen,
9a10ecf4 2877 PKTT_OTHER,
839f10db 2878 PKT_END);
2879 }
2880 if (reply)
2881 sfree(reply);
2882}
2883
0405e71f 2884/*
9e296bfa 2885 * Client-initiated disconnection. Send a DISCONNECT if `wire_reason'
2886 * non-NULL, otherwise just close the connection. `client_reason' == NULL
2887 * => log `wire_reason'.
2888 */
2889static void ssh_disconnect(Ssh ssh, char *client_reason, char *wire_reason,
2890 int code, int clean_exit)
2891{
2892 char *error;
2893 if (!client_reason)
2894 client_reason = wire_reason;
2895 if (client_reason)
2896 error = dupprintf("Disconnected: %s", client_reason);
2897 else
2898 error = dupstr("Disconnected");
2899 if (wire_reason) {
2900 if (ssh->version == 1) {
2901 send_packet(ssh, SSH1_MSG_DISCONNECT, PKT_STR, wire_reason,
2902 PKT_END);
2903 } else if (ssh->version == 2) {
2904 struct Packet *pktout = ssh2_pkt_init(SSH2_MSG_DISCONNECT);
2905 ssh2_pkt_adduint32(pktout, code);
2906 ssh2_pkt_addstring(pktout, wire_reason);
2907 ssh2_pkt_addstring(pktout, "en"); /* language tag */
2908 ssh2_pkt_send_noqueue(ssh, pktout);
2909 }
2910 }
2911 ssh->close_expected = TRUE;
2912 ssh->clean_exit = clean_exit;
2913 ssh_closing((Plug)ssh, error, 0, 0);
2914 sfree(error);
2915}
2916
2917/*
fb09bf1c 2918 * Handle the key exchange and user authentication phases.
2919 */
ff3187f6 2920static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
2921 struct Packet *pktin)
fb09bf1c 2922{
0016d70b 2923 int i, j, ret;
2924 unsigned char cookie[8], *ptr;
374330e2 2925 struct RSAKey servkey, hostkey;
2926 struct MD5Context md5c;
51470298 2927 struct do_ssh1_login_state {
2928 int len;
2929 unsigned char *rsabuf, *keystr1, *keystr2;
2930 unsigned long supported_ciphers_mask, supported_auths_mask;
2931 int tried_publickey, tried_agent;
2932 int tis_auth_refused, ccard_auth_refused;
2933 unsigned char session_id[16];
2934 int cipher_type;
2935 char username[100];
2936 void *publickey_blob;
2937 int publickey_bloblen;
2938 char password[100];
2939 char prompt[200];
2940 int pos;
2941 char c;
2942 int pwpkt_type;
2943 unsigned char request[5], *response, *p;
2944 int responselen;
2945 int keyi, nkeys;
2946 int authed;
2947 struct RSAKey key;
2948 Bignum challenge;
2949 char *commentp;
2950 int commentlen;
3d9449a1 2951 int dlgret;
51470298 2952 };
2953 crState(do_ssh1_login_state);
2954
2955 crBegin(ssh->do_ssh1_login_crstate);
374330e2 2956
ff3187f6 2957 if (!pktin)
2958 crWaitUntil(pktin);
374330e2 2959
ff3187f6 2960 if (pktin->type != SSH1_SMSG_PUBLIC_KEY) {
6b5cf8b4 2961 bombout(("Public key packet not received"));
7ffdbc1a 2962 crStop(0);
8d5de777 2963 }
374330e2 2964
c5e9c988 2965 logevent("Received public keys");
374330e2 2966
ff3187f6 2967 ptr = ssh_pkt_getdata(pktin, 8);
0016d70b 2968 if (!ptr) {
2e85c969 2969 bombout(("SSH-1 public key packet stopped before random cookie"));
0016d70b 2970 crStop(0);
2971 }
2972 memcpy(cookie, ptr, 8);
374330e2 2973
ff3187f6 2974 if (!ssh1_pkt_getrsakey(pktin, &servkey, &s->keystr1) ||
2975 !ssh1_pkt_getrsakey(pktin, &hostkey, &s->keystr2)) {
2e85c969 2976 bombout(("Failed to read SSH-1 public keys from public key packet"));
0016d70b 2977 crStop(0);
2978 }
374330e2 2979
c5e9c988 2980 /*
1c2a93c4 2981 * Log the host key fingerprint.
c5e9c988 2982 */
c5e9c988 2983 {
2984 char logmsg[80];
1c2a93c4 2985 logevent("Host key fingerprint is:");
c5e9c988 2986 strcpy(logmsg, " ");
32874aea 2987 hostkey.comment = NULL;
2988 rsa_fingerprint(logmsg + strlen(logmsg),
2989 sizeof(logmsg) - strlen(logmsg), &hostkey);
c5e9c988 2990 logevent(logmsg);
2991 }
2992
ff3187f6 2993 ssh->v1_remote_protoflags = ssh_pkt_getuint32(pktin);
2994 s->supported_ciphers_mask = ssh_pkt_getuint32(pktin);
2995 s->supported_auths_mask = ssh_pkt_getuint32(pktin);
bea1ef5f 2996
51470298 2997 ssh->v1_local_protoflags =
2998 ssh->v1_remote_protoflags & SSH1_PROTOFLAGS_SUPPORTED;
2999 ssh->v1_local_protoflags |= SSH1_PROTOFLAG_SCREEN_NUMBER;
b96dc54c 3000
c5e9c988 3001 MD5Init(&md5c);
51470298 3002 MD5Update(&md5c, s->keystr2, hostkey.bytes);
3003 MD5Update(&md5c, s->keystr1, servkey.bytes);
0016d70b 3004 MD5Update(&md5c, cookie, 8);
51470298 3005 MD5Final(s->session_id, &md5c);
374330e2 3006
32874aea 3007 for (i = 0; i < 32; i++)
51470298 3008 ssh->session_key[i] = random_byte();
374330e2 3009
0016d70b 3010 /*
3011 * Verify that the `bits' and `bytes' parameters match.
3012 */
3013 if (hostkey.bits > hostkey.bytes * 8 ||
3014 servkey.bits > servkey.bytes * 8) {
2e85c969 3015 bombout(("SSH-1 public keys were badly formatted"));
0016d70b 3016 crStop(0);
3017 }
3018
51470298 3019 s->len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);
374330e2 3020
3d88e64d 3021 s->rsabuf = snewn(s->len, unsigned char);
374330e2 3022
89ee5268 3023 /*
3024 * Verify the host key.
3025 */
3026 {
32874aea 3027 /*
3028 * First format the key into a string.
3029 */
3030 int len = rsastr_len(&hostkey);
3031 char fingerprint[100];
3d88e64d 3032 char *keystr = snewn(len, char);
32874aea 3033 rsastr_fmt(keystr, &hostkey);
3034 rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);
3d9449a1 3035
3036 ssh_set_frozen(ssh, 1);
3037 s->dlgret = verify_ssh_host_key(ssh->frontend,
3038 ssh->savedhost, ssh->savedport,
3039 "rsa", keystr, fingerprint,
3040 ssh_dialog_callback, ssh);
32874aea 3041 sfree(keystr);
3d9449a1 3042 if (s->dlgret < 0) {
3043 do {
3044 crReturn(0);
3045 if (pktin) {
3046 bombout(("Unexpected data from server while waiting"
3047 " for user host key response"));
3048 crStop(0);
3049 }
3050 } while (pktin || inlen > 0);
3051 s->dlgret = ssh->user_response;
3052 }
3053 ssh_set_frozen(ssh, 0);
3054
3055 if (s->dlgret == 0) {
9e296bfa 3056 ssh_disconnect(ssh, "User aborted at host key verification",
3057 NULL, 0, TRUE);
2b3f6c19 3058 crStop(0);
3d9449a1 3059 }
32874aea 3060 }
3061
3062 for (i = 0; i < 32; i++) {
51470298 3063 s->rsabuf[i] = ssh->session_key[i];
374330e2 3064 if (i < 16)
51470298 3065 s->rsabuf[i] ^= s->session_id[i];
374330e2 3066 }
3067
3068 if (hostkey.bytes > servkey.bytes) {
0016d70b 3069 ret = rsaencrypt(s->rsabuf, 32, &servkey);
3070 if (ret)
3071 ret = rsaencrypt(s->rsabuf, servkey.bytes, &hostkey);
374330e2 3072 } else {
0016d70b 3073 ret = rsaencrypt(s->rsabuf, 32, &hostkey);
3074 if (ret)
3075 ret = rsaencrypt(s->rsabuf, hostkey.bytes, &servkey);
3076 }
3077 if (!ret) {
2e85c969 3078 bombout(("SSH-1 public key encryptions failed due to bad formatting"));
0016d70b 3079 crStop(0);
374330e2 3080 }
3081
c5e9c988 3082 logevent("Encrypted session key");
3083
ca20bfcf 3084 {
3085 int cipher_chosen = 0, warn = 0;
3086 char *cipher_string = NULL;
51470298 3087 int i;
ca20bfcf 3088 for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
86916870 3089 int next_cipher = ssh->cfg.ssh_cipherlist[i];
ca20bfcf 3090 if (next_cipher == CIPHER_WARN) {
3091 /* If/when we choose a cipher, warn about it */
3092 warn = 1;
3093 } else if (next_cipher == CIPHER_AES) {
3094 /* XXX Probably don't need to mention this. */
2e85c969 3095 logevent("AES not supported in SSH-1, skipping");
ca20bfcf 3096 } else {
3097 switch (next_cipher) {
51470298 3098 case CIPHER_3DES: s->cipher_type = SSH_CIPHER_3DES;
ca20bfcf 3099 cipher_string = "3DES"; break;
51470298 3100 case CIPHER_BLOWFISH: s->cipher_type = SSH_CIPHER_BLOWFISH;
ca20bfcf 3101 cipher_string = "Blowfish"; break;
51470298 3102 case CIPHER_DES: s->cipher_type = SSH_CIPHER_DES;
ca20bfcf 3103 cipher_string = "single-DES"; break;
3104 }
51470298 3105 if (s->supported_ciphers_mask & (1 << s->cipher_type))
ca20bfcf 3106 cipher_chosen = 1;
3107 }
3108 }
3109 if (!cipher_chosen) {
51470298 3110 if ((s->supported_ciphers_mask & (1 << SSH_CIPHER_3DES)) == 0)
2e85c969 3111 bombout(("Server violates SSH-1 protocol by not "
ca20bfcf 3112 "supporting 3DES encryption"));
3113 else
3114 /* shouldn't happen */
6b5cf8b4 3115 bombout(("No supported ciphers found"));
7ffdbc1a 3116 crStop(0);
a99a05c0 3117 }
ca20bfcf 3118
3119 /* Warn about chosen cipher if necessary. */
bb348ab1 3120 if (warn) {
3d9449a1 3121 ssh_set_frozen(ssh, 1);
3122 s->dlgret = askalg(ssh->frontend, "cipher", cipher_string,
3123 ssh_dialog_callback, ssh);
3124 if (s->dlgret < 0) {
3125 do {
3126 crReturn(0);
3127 if (pktin) {
3128 bombout(("Unexpected data from server while waiting"
3129 " for user response"));
3130 crStop(0);
3131 }
3132 } while (pktin || inlen > 0);
3133 s->dlgret = ssh->user_response;
3134 }
3135 ssh_set_frozen(ssh, 0);
3136 if (s->dlgret == 0) {
9e296bfa 3137 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
3138 0, TRUE);
96ccde8b 3139 crStop(0);
3d9449a1 3140 }
bb348ab1 3141 }
bea1ef5f 3142 }
ca20bfcf 3143
51470298 3144 switch (s->cipher_type) {
32874aea 3145 case SSH_CIPHER_3DES:
3146 logevent("Using 3DES encryption");
3147 break;
3148 case SSH_CIPHER_DES:
3149 logevent("Using single-DES encryption");
3150 break;
3151 case SSH_CIPHER_BLOWFISH:
3152 logevent("Using Blowfish encryption");
3153 break;
c5e9c988 3154 }
bea1ef5f 3155
51470298 3156 send_packet(ssh, SSH1_CMSG_SESSION_KEY,
3157 PKT_CHAR, s->cipher_type,
32874aea 3158 PKT_DATA, cookie, 8,
51470298 3159 PKT_CHAR, (s->len * 8) >> 8, PKT_CHAR, (s->len * 8) & 0xFF,
3160 PKT_DATA, s->rsabuf, s->len,
3161 PKT_INT, ssh->v1_local_protoflags, PKT_END);
fb09bf1c 3162
c5e9c988 3163 logevent("Trying to enable encryption...");
374330e2 3164
51470298 3165 sfree(s->rsabuf);
374330e2 3166
51470298 3167 ssh->cipher = (s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
3168 s->cipher_type == SSH_CIPHER_DES ? &ssh_des :
3169 &ssh_3des);
371e569c 3170 ssh->v1_cipher_ctx = ssh->cipher->make_context();
3171 ssh->cipher->sesskey(ssh->v1_cipher_ctx, ssh->session_key);
57356d63 3172 logeventf(ssh, "Initialised %s encryption", ssh->cipher->text_name);
374330e2 3173
0183b242 3174 ssh->crcda_ctx = crcda_make_context();
3175 logevent("Installing CRC compensation attack detector");
3176
679539d7 3177 if (servkey.modulus) {
3178 sfree(servkey.modulus);
3179 servkey.modulus = NULL;
3180 }
3181 if (servkey.exponent) {
3182 sfree(servkey.exponent);
3183 servkey.exponent = NULL;
3184 }
3185 if (hostkey.modulus) {
3186 sfree(hostkey.modulus);
3187 hostkey.modulus = NULL;
3188 }
3189 if (hostkey.exponent) {
3190 sfree(hostkey.exponent);
3191 hostkey.exponent = NULL;
3192 }
ff3187f6 3193 crWaitUntil(pktin);
374330e2 3194
ff3187f6 3195 if (pktin->type != SSH1_SMSG_SUCCESS) {
6b5cf8b4 3196 bombout(("Encryption not successfully enabled"));
7ffdbc1a 3197 crStop(0);
8d5de777 3198 }
374330e2 3199
c5e9c988 3200 logevent("Successfully started encryption");
3201
374330e2 3202 fflush(stdout);
3203 {
aa09f7d0 3204 if (!*ssh->cfg.username) {
c0a81592 3205 if (ssh_get_line && !ssh_getline_pw_only) {
32874aea 3206 if (!ssh_get_line("login as: ",
51470298 3207 s->username, sizeof(s->username), FALSE)) {
32874aea 3208 /*
3209 * get_line failed to get a username.
3210 * Terminate.
3211 */
9e296bfa 3212 ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
7ffdbc1a 3213 crStop(1);
32874aea 3214 }
3215 } else {
51470298 3216 int ret; /* need not be kept over crReturn */
3217 c_write_str(ssh, "login as: ");
3218 ssh->send_ok = 1;
0405e71f 3219
51470298 3220 setup_userpass_input(ssh, s->username, sizeof(s->username), 1);
0405e71f 3221 do {
ff3187f6 3222 crWaitUntil(!pktin);
51470298 3223 ret = process_userpass_input(ssh, in, inlen);
0405e71f 3224 } while (ret == 0);
3225 if (ret < 0)
3226 cleanup_exit(0);
51470298 3227 c_write_str(ssh, "\r\n");
32874aea 3228 }
3229 } else {
86916870 3230 strncpy(s->username, ssh->cfg.username, sizeof(s->username));
51470298 3231 s->username[sizeof(s->username)-1] = '\0';
374330e2 3232 }
fb09bf1c 3233
51470298 3234 send_packet(ssh, SSH1_CMSG_USER, PKT_STR, s->username, PKT_END);
c5e9c988 3235 {
51470298 3236 char userlog[22 + sizeof(s->username)];
3237 sprintf(userlog, "Sent username \"%s\"", s->username);
c5e9c988 3238 logevent(userlog);
32874aea 3239 if (flags & FLAG_INTERACTIVE &&
3240 (!((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)))) {
3c8e959b 3241 strcat(userlog, "\r\n");
51470298 3242 c_write_str(ssh, userlog);
3c8e959b 3243 }
c5e9c988 3244 }
374330e2 3245 }
3246
ff3187f6 3247 crWaitUntil(pktin);
374330e2 3248
51470298 3249 if ((ssh->remote_bugs & BUG_CHOKES_ON_RSA)) {
0df73905 3250 /* We must not attempt PK auth. Pretend we've already tried it. */
51470298 3251 s->tried_publickey = s->tried_agent = 1;
0df73905 3252 } else {
51470298 3253 s->tried_publickey = s->tried_agent = 0;
0df73905 3254 }
51470298 3255 s->tis_auth_refused = s->ccard_auth_refused = 0;
86916870 3256 /* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */
9a30e26b 3257 if (!filename_is_null(ssh->cfg.keyfile)) {
3258 if (!rsakey_pubblob(&ssh->cfg.keyfile,
4bcf919e 3259 &s->publickey_blob, &s->publickey_bloblen,
3260 NULL, NULL))
51470298 3261 s->publickey_blob = NULL;
396778f1 3262 } else
51470298 3263 s->publickey_blob = NULL;
7cca0d81 3264
ff3187f6 3265 while (pktin->type == SSH1_SMSG_FAILURE) {
51470298 3266 s->pwpkt_type = SSH1_CMSG_AUTH_PASSWORD;
614a20a0 3267
51470298 3268 if (agent_exists() && !s->tried_agent) {
32874aea 3269 /*
3270 * Attempt RSA authentication using Pageant.
3271 */
32874aea 3272 void *r;
3273
51470298 3274 s->authed = FALSE;
3275 s->tried_agent = 1;
32874aea 3276 logevent("Pageant is running. Requesting keys.");
3277
3278 /* Request the keys held by the agent. */
51470298 3279 PUT_32BIT(s->request, 1);
3280 s->request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
839f10db 3281 if (!agent_query(s->request, 5, &r, &s->responselen,
3282 ssh_agent_callback, ssh)) {
3283 do {
3284 crReturn(0);
ff3187f6 3285 if (pktin) {
839f10db 3286 bombout(("Unexpected data from server while waiting"
3287 " for agent response"));
3288 crStop(0);
3289 }
ff3187f6 3290 } while (pktin || inlen > 0);
839f10db 3291 r = ssh->agent_response;
3292 s->responselen = ssh->agent_response_len;
3293 }
51470298 3294 s->response = (unsigned char *) r;
3295 if (s->response && s->responselen >= 5 &&
3296 s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
3297 s->p = s->response + 5;
3298 s->nkeys = GET_32BIT(s->p);
3299 s->p += 4;
2e85c969 3300 logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
51470298 3301 for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
fb983202 3302 logeventf(ssh, "Trying Pageant key #%d", s->keyi);
51470298 3303 if (s->publickey_blob &&
3304 !memcmp(s->p, s->publickey_blob,
3305 s->publickey_bloblen)) {
396778f1 3306 logevent("This key matches configured key file");
51470298 3307 s->tried_publickey = 1;
396778f1 3308 }
51470298 3309 s->p += 4;
0016d70b 3310 {
3311 int n, ok = FALSE;
3312 do { /* do while (0) to make breaking easy */
3313 n = ssh1_read_bignum
3314 (s->p, s->responselen-(s->p-s->response),
3315 &s->key.exponent);
3316 if (n < 0)
3317 break;
3318 s->p += n;
3319 n = ssh1_read_bignum
3320 (s->p, s->responselen-(s->p-s->response),
3321 &s->key.modulus);
3322 if (n < 0)
3323 break;
3324 s->p += n;
3325 if (s->responselen - (s->p-s->response) < 4)
3326 break;
3327 s->commentlen = GET_32BIT(s->p);
3328 s->p += 4;
3329 if (s->responselen - (s->p-s->response) <
3330 s->commentlen)
3331 break;
3332 s->commentp = (char *)s->p;
3333 s->p += s->commentlen;
3334 ok = TRUE;
3335 } while (0);
3336 if (!ok) {
3337 logevent("Pageant key list packet was truncated");
3338 break;
3339 }
3340 }
51470298 3341 send_packet(ssh, SSH1_CMSG_AUTH_RSA,
3342 PKT_BIGNUM, s->key.modulus, PKT_END);
ff3187f6 3343 crWaitUntil(pktin);
3344 if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
32874aea 3345 logevent("Key refused");
3346 continue;
3347 }
3348 logevent("Received RSA challenge");
ff3187f6 3349 if ((s->challenge = ssh1_pkt_getmp(pktin)) == NULL) {
0016d70b 3350 bombout(("Server's RSA challenge was badly formatted"));
3351 crStop(0);
3352 }
3353
32874aea 3354 {
3355 char *agentreq, *q, *ret;
2d466ffd 3356 void *vret;
32874aea 3357 int len, retlen;
3358 len = 1 + 4; /* message type, bit count */
51470298 3359 len += ssh1_bignum_length(s->key.exponent);
3360 len += ssh1_bignum_length(s->key.modulus);
3361 len += ssh1_bignum_length(s->challenge);
32874aea 3362 len += 16; /* session id */
3363 len += 4; /* response format */
3d88e64d 3364 agentreq = snewn(4 + len, char);
32874aea 3365 PUT_32BIT(agentreq, len);
3366 q = agentreq + 4;
3367 *q++ = SSH1_AGENTC_RSA_CHALLENGE;
51470298 3368 PUT_32BIT(q, bignum_bitcount(s->key.modulus));
32874aea 3369 q += 4;
51470298 3370 q += ssh1_write_bignum(q, s->key.exponent);
3371 q += ssh1_write_bignum(q, s->key.modulus);
3372 q += ssh1_write_bignum(q, s->challenge);
3373 memcpy(q, s->session_id, 16);
32874aea 3374 q += 16;
3375 PUT_32BIT(q, 1); /* response format */
839f10db 3376 if (!agent_query(agentreq, len + 4, &vret, &retlen,
3377 ssh_agent_callback, ssh)) {
3378 sfree(agentreq);
3379 do {
3380 crReturn(0);
ff3187f6 3381 if (pktin) {
839f10db 3382 bombout(("Unexpected data from server"
3383 " while waiting for agent"
3384 " response"));
3385 crStop(0);
3386 }
ff3187f6 3387 } while (pktin || inlen > 0);
839f10db 3388 vret = ssh->agent_response;
3389 retlen = ssh->agent_response_len;
3390 } else
3391 sfree(agentreq);
2d466ffd 3392 ret = vret;
32874aea 3393 if (ret) {
3394 if (ret[4] == SSH1_AGENT_RSA_RESPONSE) {
3395 logevent("Sending Pageant's response");
51470298 3396 send_packet(ssh, SSH1_CMSG_AUTH_RSA_RESPONSE,
32874aea 3397 PKT_DATA, ret + 5, 16,
3398 PKT_END);
3399 sfree(ret);
ff3187f6 3400 crWaitUntil(pktin);
3401 if (pktin->type == SSH1_SMSG_SUCCESS) {
32874aea 3402 logevent
3403 ("Pageant's response accepted");
3404 if (flags & FLAG_VERBOSE) {
51470298 3405 c_write_str(ssh, "Authenticated using"
3406 " RSA key \"");
3407 c_write(ssh, s->commentp,
3408 s->commentlen);
3409 c_write_str(ssh, "\" from agent\r\n");
32874aea 3410 }
51470298 3411 s->authed = TRUE;
32874aea 3412 } else
3413 logevent
3414 ("Pageant's response not accepted");
3415 } else {
3416 logevent
3417 ("Pageant failed to answer challenge");
3418 sfree(ret);
3419 }
3420 } else {
3421 logevent("No reply received from Pageant");
3422 }
3423 }
51470298 3424 freebn(s->key.exponent);
3425 freebn(s->key.modulus);
3426 freebn(s->challenge);
3427 if (s->authed)
32874aea 3428 break;
3429 }
29b1d0b3 3430 sfree(s->response);
32874aea 3431 }
51470298 3432 if (s->authed)
32874aea 3433 break;
3434 }
9a30e26b 3435 if (!filename_is_null(ssh->cfg.keyfile) && !s->tried_publickey)
51470298 3436 s->pwpkt_type = SSH1_CMSG_AUTH_RSA;
32874aea 3437
86916870 3438 if (ssh->cfg.try_tis_auth &&
51470298 3439 (s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
3440 !s->tis_auth_refused) {
3441 s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
32874aea 3442 logevent("Requested TIS authentication");
51470298 3443 send_packet(ssh, SSH1_CMSG_AUTH_TIS, PKT_END);
ff3187f6 3444 crWaitUntil(pktin);
3445 if (pktin->type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
32874aea 3446 logevent("TIS authentication declined");
3447 if (flags & FLAG_INTERACTIVE)
51470298 3448 c_write_str(ssh, "TIS authentication refused.\r\n");
3449 s->tis_auth_refused = 1;
614a20a0 3450 continue;
32874aea 3451 } else {
0016d70b 3452 char *challenge;
3453 int challengelen;
3454
ff3187f6 3455 ssh_pkt_getstring(pktin, &challenge, &challengelen);
0016d70b 3456 if (!challenge) {
3457 bombout(("TIS challenge packet was badly formed"));
3458 crStop(0);
3459 }
fb2ec557 3460 c_write_str(ssh, "Using TIS authentication.\r\n");
32874aea 3461 logevent("Received TIS challenge");
51470298 3462 if (challengelen > sizeof(s->prompt) - 1)
3463 challengelen = sizeof(s->prompt) - 1;/* prevent overrun */
0016d70b 3464 memcpy(s->prompt, challenge, challengelen);
614a20a0 3465 /* Prompt heuristic comes from OpenSSH */
51470298 3466 strncpy(s->prompt + challengelen,
3467 memchr(s->prompt, '\n', challengelen) ?
614a20a0 3468 "": "\r\nResponse: ",
51470298 3469 (sizeof s->prompt) - challengelen);
3470 s->prompt[(sizeof s->prompt) - 1] = '\0';
32874aea 3471 }
3472 }
86916870 3473 if (ssh->cfg.try_tis_auth &&
51470298 3474 (s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
3475 !s->ccard_auth_refused) {
3476 s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
32874aea 3477 logevent("Requested CryptoCard authentication");
51470298 3478 send_packet(ssh, SSH1_CMSG_AUTH_CCARD, PKT_END);
ff3187f6 3479 crWaitUntil(pktin);
3480 if (pktin->type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
32874aea 3481 logevent("CryptoCard authentication declined");
51470298 3482 c_write_str(ssh, "CryptoCard authentication refused.\r\n");
3483 s->ccard_auth_refused = 1;
614a20a0 3484 continue;
32874aea 3485 } else {
0016d70b 3486 char *challenge;
3487 int challengelen;
3488
ff3187f6 3489 ssh_pkt_getstring(pktin, &challenge, &challengelen);
0016d70b 3490 if (!challenge) {
3491 bombout(("CryptoCard challenge packet was badly formed"));
3492 crStop(0);
3493 }
fb2ec557 3494 c_write_str(ssh, "Using CryptoCard authentication.\r\n");
32874aea 3495 logevent("Received CryptoCard challenge");
51470298 3496 if (challengelen > sizeof(s->prompt) - 1)
3497 challengelen = sizeof(s->prompt) - 1;/* prevent overrun */
0016d70b 3498 memcpy(s->prompt, challenge, challengelen);
51470298 3499 strncpy(s->prompt + challengelen,
3500 memchr(s->prompt, '\n', challengelen) ?
614a20a0 3501 "" : "\r\nResponse: ",
51470298 3502 sizeof(s->prompt) - challengelen);
3503 s->prompt[sizeof(s->prompt) - 1] = '\0';
32874aea 3504 }
3505 }
51470298 3506 if (s->pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
3507 sprintf(s->prompt, "%.90s@%.90s's password: ",
3508 s->username, ssh->savedhost);
32874aea 3509 }
51470298 3510 if (s->pwpkt_type == SSH1_CMSG_AUTH_RSA) {
32874aea 3511 char *comment = NULL;
231ee168 3512 int type;
32874aea 3513 if (flags & FLAG_VERBOSE)
51470298 3514 c_write_str(ssh, "Trying public key authentication.\r\n");
6c6d9ed9 3515 logeventf(ssh, "Trying public key \"%s\"",
3516 filename_to_str(&ssh->cfg.keyfile));
9a30e26b 3517 type = key_type(&ssh->cfg.keyfile);
231ee168 3518 if (type != SSH_KEYTYPE_SSH1) {
fb983202 3519 char *msg = dupprintf("Key is of wrong type (%s)",
3520 key_type_to_str(type));
3521 logevent(msg);
3522 c_write_str(ssh, msg);
51470298 3523 c_write_str(ssh, "\r\n");
fb983202 3524 sfree(msg);
51470298 3525 s->tried_publickey = 1;
231ee168 3526 continue;
3527 }
9a30e26b 3528 if (!rsakey_encrypted(&ssh->cfg.keyfile, &comment)) {
32874aea 3529 if (flags & FLAG_VERBOSE)
51470298 3530 c_write_str(ssh, "No passphrase required.\r\n");
32874aea 3531 goto tryauth;
3532 }
51470298 3533 sprintf(s->prompt, "Passphrase for key \"%.100s\": ", comment);
32874aea 3534 sfree(comment);
3535 }
a52f067e 3536
614a20a0 3537 /*
3538 * Show password prompt, having first obtained it via a TIS
3539 * or CryptoCard exchange if we're doing TIS or CryptoCard
3540 * authentication.
3541 */
fa17a66e 3542 if (ssh_get_line) {
51470298 3543 if (!ssh_get_line(s->prompt, s->password,
3544 sizeof(s->password), TRUE)) {
32874aea 3545 /*
3546 * get_line failed to get a password (for example
3547 * because one was supplied on the command line
3548 * which has already failed to work). Terminate.
3549 */
9e296bfa 3550 ssh_disconnect(ssh, NULL, "Unable to authenticate", 0, FALSE);
7ffdbc1a 3551 crStop(1);
32874aea 3552 }
fb09bf1c 3553 } else {
614a20a0 3554 /* Prompt may have come from server. We've munged it a bit, so
3555 * we know it to be zero-terminated at least once. */
51470298 3556 int ret; /* need not be saved over crReturn */
3557 c_write_untrusted(ssh, s->prompt, strlen(s->prompt));
3558 s->pos = 0;
0405e71f 3559
51470298 3560 setup_userpass_input(ssh, s->password, sizeof(s->password), 0);
0405e71f 3561 do {
ff3187f6 3562 crWaitUntil(!pktin);
51470298 3563 ret = process_userpass_input(ssh, in, inlen);
0405e71f 3564 } while (ret == 0);
3565 if (ret < 0)
3566 cleanup_exit(0);
51470298 3567 c_write_str(ssh, "\r\n");
32874aea 3568 }
3569
3570 tryauth:
51470298 3571 if (s->pwpkt_type == SSH1_CMSG_AUTH_RSA) {
32874aea 3572 /*
3573 * Try public key authentication with the specified
3574 * key file.
3575 */
51470298 3576 s->tried_publickey = 1;
3577
3578 {
222d54dc 3579 const char *error = NULL;
3580 int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password,
3581 &error);
51470298 3582 if (ret == 0) {
3583 c_write_str(ssh, "Couldn't load private key from ");
9fab77dc 3584 c_write_str(ssh, filename_to_str(&ssh->cfg.keyfile));
222d54dc 3585 c_write_str(ssh, " (");
3586 c_write_str(ssh, error);
3587 c_write_str(ssh, ").\r\n");
51470298 3588 continue; /* go and try password */
3589 }
3590 if (ret == -1) {
3591 c_write_str(ssh, "Wrong passphrase.\r\n");
3592 s->tried_publickey = 0;
3593 continue; /* try again */
3594 }
32874aea 3595 }
3596
3597 /*
3598 * Send a public key attempt.
3599 */
51470298 3600 send_packet(ssh, SSH1_CMSG_AUTH_RSA,
3601 PKT_BIGNUM, s->key.modulus, PKT_END);
32874aea 3602
ff3187f6 3603 crWaitUntil(pktin);
3604 if (pktin->type == SSH1_SMSG_FAILURE) {
51470298 3605 c_write_str(ssh, "Server refused our public key.\r\n");
32874aea 3606 continue; /* go and try password */
3607 }
ff3187f6 3608 if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
6b5cf8b4 3609 bombout(("Bizarre response to offer of public key"));
7ffdbc1a 3610 crStop(0);
32874aea 3611 }
32874aea 3612
51470298 3613 {
3614 int i;
3615 unsigned char buffer[32];
3616 Bignum challenge, response;
3617
ff3187f6 3618 if ((challenge = ssh1_pkt_getmp(pktin)) == NULL) {
0016d70b 3619 bombout(("Server's RSA challenge was badly formatted"));
3620 crStop(0);
3621 }
51470298 3622 response = rsadecrypt(challenge, &s->key);
3623 freebn(s->key.private_exponent);/* burn the evidence */
32874aea 3624
51470298 3625 for (i = 0; i < 32; i++) {
3626 buffer[i] = bignum_byte(response, 31 - i);
3627 }
3628
3629 MD5Init(&md5c);
3630 MD5Update(&md5c, buffer, 32);
3631 MD5Update(&md5c, s->session_id, 16);
3632 MD5Final(buffer, &md5c);
32874aea 3633
51470298 3634 send_packet(ssh, SSH1_CMSG_AUTH_RSA_RESPONSE,
3635 PKT_DATA, buffer, 16, PKT_END);
3636
3637 freebn(challenge);
3638 freebn(response);
3639 }
32874aea 3640
ff3187f6 3641 crWaitUntil(pktin);
3642 if (pktin->type == SSH1_SMSG_FAILURE) {
32874aea 3643 if (flags & FLAG_VERBOSE)
51470298 3644 c_write_str(ssh, "Failed to authenticate with"
3645 " our public key.\r\n");
32874aea 3646 continue; /* go and try password */
ff3187f6 3647 } else if (pktin->type != SSH1_SMSG_SUCCESS) {
6b5cf8b4 3648 bombout(("Bizarre response to RSA authentication response"));
7ffdbc1a 3649 crStop(0);
32874aea 3650 }
3651
3652 break; /* we're through! */
3653 } else {
51470298 3654 if (s->pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
32874aea 3655 /*
3656 * Defence against traffic analysis: we send a
3657 * whole bunch of packets containing strings of
3658 * different lengths. One of these strings is the
3659 * password, in a SSH1_CMSG_AUTH_PASSWORD packet.
3660 * The others are all random data in
3661 * SSH1_MSG_IGNORE packets. This way a passive
3662 * listener can't tell which is the password, and
3663 * hence can't deduce the password length.
3664 *
3665 * Anybody with a password length greater than 16
3666 * bytes is going to have enough entropy in their
3667 * password that a listener won't find it _that_
3668 * much help to know how long it is. So what we'll
3669 * do is:
3670 *
3671 * - if password length < 16, we send 15 packets
3672 * containing string lengths 1 through 15
3673 *
3674 * - otherwise, we let N be the nearest multiple
3675 * of 8 below the password length, and send 8
3676 * packets containing string lengths N through
3677 * N+7. This won't obscure the order of
3678 * magnitude of the password length, but it will
3679 * introduce a bit of extra uncertainty.
3680 *
3681 * A few servers (the old 1.2.18 through 1.2.22)
3682 * can't deal with SSH1_MSG_IGNORE. For these
3683 * servers, we need an alternative defence. We make
3684 * use of the fact that the password is interpreted
3685 * as a C string: so we can append a NUL, then some
3686 * random data.
bd358db1 3687 *
3688 * One server (a Cisco one) can deal with neither
3689 * SSH1_MSG_IGNORE _nor_ a padded password string.
3690 * For this server we are left with no defences
3691 * against password length sniffing.
32874aea 3692 */
51470298 3693 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE)) {
b17c8428 3694 /*
3695 * The server can deal with SSH1_MSG_IGNORE, so
3696 * we can use the primary defence.
3697 */
32874aea 3698 int bottom, top, pwlen, i;
3699 char *randomstr;
3700
51470298 3701 pwlen = strlen(s->password);
32874aea 3702 if (pwlen < 16) {
3703 bottom = 0; /* zero length passwords are OK! :-) */
3704 top = 15;
3705 } else {
3706 bottom = pwlen & ~7;
3707 top = bottom + 7;
3708 }
3709
3710 assert(pwlen >= bottom && pwlen <= top);
3711
3d88e64d 3712 randomstr = snewn(top + 1, char);
32874aea 3713
3714 for (i = bottom; i <= top; i++) {
9a10ecf4 3715 if (i == pwlen) {
51470298 3716 defer_packet(ssh, s->pwpkt_type,
9a10ecf4 3717 PKTT_PASSWORD, PKT_STR, s->password,
3718 PKTT_OTHER, PKT_END);
3719 } else {
32874aea 3720 for (j = 0; j < i; j++) {
3721 do {
3722 randomstr[j] = random_byte();
3723 } while (randomstr[j] == '\0');
3724 }
3725 randomstr[i] = '\0';
51470298 3726 defer_packet(ssh, SSH1_MSG_IGNORE,
32874aea 3727 PKT_STR, randomstr, PKT_END);
3728 }
3729 }
bd358db1 3730 logevent("Sending password with camouflage packets");
51470298 3731 ssh_pkt_defersend(ssh);
679539d7 3732 sfree(randomstr);
bd358db1 3733 }
51470298 3734 else if (!(ssh->remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
b17c8428 3735 /*
3736 * The server can't deal with SSH1_MSG_IGNORE
3737 * but can deal with padded passwords, so we
3738 * can use the secondary defence.
3739 */
bd358db1 3740 char string[64];
51470298 3741 char *ss;
bd358db1 3742 int len;
3743
51470298 3744 len = strlen(s->password);
bd358db1 3745 if (len < sizeof(string)) {
51470298 3746 ss = string;
3747 strcpy(string, s->password);
bd358db1 3748 len++; /* cover the zero byte */
3749 while (len < sizeof(string)) {
3750 string[len++] = (char) random_byte();
3751 }
3752 } else {
51470298 3753 ss = s->password;
bd358db1 3754 }
3755 logevent("Sending length-padded password");
9a10ecf4 3756 send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
3757 PKT_INT, len, PKT_DATA, ss, len,
3758 PKTT_OTHER, PKT_END);
bd358db1 3759 } else {
3760 /*
3761 * The server has _both_
3762 * BUG_CHOKES_ON_SSH1_IGNORE and
3763 * BUG_NEEDS_SSH1_PLAIN_PASSWORD. There is
3764 * therefore nothing we can do.
3765 */
3766 int len;
51470298 3767 len = strlen(s->password);
bd358db1 3768 logevent("Sending unpadded password");
9a10ecf4 3769 send_packet(ssh, s->pwpkt_type,
3770 PKTT_PASSWORD, PKT_INT, len,
3771 PKT_DATA, s->password, len,
3772 PKTT_OTHER, PKT_END);
32874aea 3773 }
3774 } else {
9a10ecf4 3775 send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
3776 PKT_STR, s->password, PKTT_OTHER, PKT_END);
32874aea 3777 }
3778 }
c5e9c988 3779 logevent("Sent password");
51470298 3780 memset(s->password, 0, strlen(s->password));
ff3187f6 3781 crWaitUntil(pktin);
3782 if (pktin->type == SSH1_SMSG_FAILURE) {
32874aea 3783 if (flags & FLAG_VERBOSE)
51470298 3784 c_write_str(ssh, "Access denied\r\n");
c5e9c988 3785 logevent("Authentication refused");
ff3187f6 3786 } else if (pktin->type != SSH1_SMSG_SUCCESS) {
3787 bombout(("Strange packet received, type %d", pktin->type));
7ffdbc1a 3788 crStop(0);
374330e2 3789 }
3790 }
3791
c5e9c988 3792 logevent("Authentication successful");
3793
fb09bf1c 3794 crFinish(1);
3795}
3796
32874aea 3797void sshfwd_close(struct ssh_channel *c)
3798{
51470298 3799 Ssh ssh = c->ssh;
3800
1ef619ae 3801 if (ssh->state == SSH_STATE_CLOSED)
36f94d1f 3802 return;
36f94d1f 3803
80e48603 3804 if (c && !c->closes) {
4ed34d25 3805 /*
64d6ff88 3806 * If halfopen is true, we have sent
4ed34d25 3807 * CHANNEL_OPEN for this channel, but it hasn't even been
3808 * acknowledged by the server. So we must set a close flag
3809 * on it now, and then when the server acks the channel
3810 * open, we can close it then.
3811 */
64d6ff88 3812 if (!c->halfopen) {
51470298 3813 if (ssh->version == 1) {
3814 send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid,
4ed34d25 3815 PKT_END);
3816 } else {
ff3187f6 3817 struct Packet *pktout;
3818 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
3819 ssh2_pkt_adduint32(pktout, c->remoteid);
3820 ssh2_pkt_send(ssh, pktout);
4ed34d25 3821 }
32874aea 3822 }
0357890f 3823 c->closes = 1; /* sent MSG_CLOSE */
32874aea 3824 if (c->type == CHAN_X11) {
3825 c->u.x11.s = NULL;
d74d141c 3826 logevent("Forwarded X11 connection terminated");
4ed34d25 3827 } else if (c->type == CHAN_SOCKDATA ||
3828 c->type == CHAN_SOCKDATA_DORMANT) {
d74d141c 3829 c->u.pfd.s = NULL;
3830 logevent("Forwarded port closed");
32874aea 3831 }
3832 }
3833}
3834
5471d09a 3835int sshfwd_write(struct ssh_channel *c, char *buf, int len)
32874aea 3836{
51470298 3837 Ssh ssh = c->ssh;
3838
1ef619ae 3839 if (ssh->state == SSH_STATE_CLOSED)
36f94d1f 3840 return 0;
36f94d1f 3841
51470298 3842 if (ssh->version == 1) {
3843 send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
32874aea 3844 PKT_INT, c->remoteid,
9a10ecf4 3845 PKTT_DATA,
3846 PKT_INT, len, PKT_DATA, buf, len,
3847 PKTT_OTHER, PKT_END);
5471d09a 3848 /*
2e85c969 3849 * In SSH-1 we can return 0 here - implying that forwarded
5471d09a 3850 * connections are never individually throttled - because
3851 * the only circumstance that can cause throttling will be
3852 * the whole SSH connection backing up, in which case
3853 * _everything_ will be throttled as a whole.
3854 */
3855 return 0;
783415f8 3856 } else {
32874aea 3857 ssh2_add_channel_data(c, buf, len);
5471d09a 3858 return ssh2_try_send(c);
3859 }
3860}
3861
3862void sshfwd_unthrottle(struct ssh_channel *c, int bufsize)
3863{
51470298 3864 Ssh ssh = c->ssh;
3865
1ef619ae 3866 if (ssh->state == SSH_STATE_CLOSED)
36f94d1f 3867 return;
36f94d1f 3868
51470298 3869 if (ssh->version == 1) {
5471d09a 3870 if (c->v.v1.throttling && bufsize < SSH1_BUFFER_LIMIT) {
3871 c->v.v1.throttling = 0;
51470298 3872 ssh1_throttle(ssh, -1);
5471d09a 3873 }
3874 } else {
3875 ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
783415f8 3876 }
9c964e85 3877}
3878
06fadff5 3879static void ssh_queueing_handler(Ssh ssh, struct Packet *pktin)
3880{
3881 struct queued_handler *qh = ssh->qhead;
3882
3883 assert(qh != NULL);
3884
3885 assert(pktin->type == qh->msg1 || pktin->type == qh->msg2);
3886
3887 if (qh->msg1 > 0) {
3888 assert(ssh->packet_dispatch[qh->msg1] == ssh_queueing_handler);
3889 ssh->packet_dispatch[qh->msg1] = NULL;
3890 }
3891 if (qh->msg2 > 0) {
3892 assert(ssh->packet_dispatch[qh->msg2] == ssh_queueing_handler);
3893 ssh->packet_dispatch[qh->msg2] = NULL;
3894 }
3895
3896 if (qh->next) {
3897 ssh->qhead = qh->next;
3898
3899 if (ssh->qhead->msg1 > 0) {
3900 assert(ssh->packet_dispatch[ssh->qhead->msg1] == NULL);
3901 ssh->packet_dispatch[ssh->qhead->msg1] = ssh_queueing_handler;
3902 }
3903 if (ssh->qhead->msg2 > 0) {
3904 assert(ssh->packet_dispatch[ssh->qhead->msg2] == NULL);
3905 ssh->packet_dispatch[ssh->qhead->msg2] = ssh_queueing_handler;
3906 }
3907 } else {
3908 ssh->qhead = ssh->qtail = NULL;
3909 ssh->packet_dispatch[pktin->type] = NULL;
3910 }
3911
3912 qh->handler(ssh, pktin, qh->ctx);
3913
3914 sfree(qh);
3915}
3916
3917static void ssh_queue_handler(Ssh ssh, int msg1, int msg2,
3918 chandler_fn_t handler, void *ctx)
3919{
3920 struct queued_handler *qh;
3921
3922 qh = snew(struct queued_handler);
3923 qh->msg1 = msg1;
3924 qh->msg2 = msg2;
3925 qh->handler = handler;
3926 qh->ctx = ctx;
3927 qh->next = NULL;
3928
3929 if (ssh->qtail == NULL) {
3930 ssh->qhead = qh;
3931
3932 if (qh->msg1 > 0) {
3933 assert(ssh->packet_dispatch[qh->msg1] == NULL);
3934 ssh->packet_dispatch[qh->msg1] = ssh_queueing_handler;
3935 }
3936 if (qh->msg2 > 0) {
3937 assert(ssh->packet_dispatch[qh->msg2] == NULL);
3938 ssh->packet_dispatch[qh->msg2] = ssh_queueing_handler;
3939 }
3940 } else {
3941 ssh->qtail->next = qh;
3942 }
3943 ssh->qtail = qh;
3944}
3945
3946static void ssh_rportfwd_succfail(Ssh ssh, struct Packet *pktin, void *ctx)
3947{
3948 struct ssh_rportfwd *rpf, *pf = (struct ssh_rportfwd *)ctx;
3949
3950 if (pktin->type == (ssh->version == 1 ? SSH1_SMSG_SUCCESS :
3951 SSH2_MSG_REQUEST_SUCCESS)) {
3952 logeventf(ssh, "Remote port forwarding from %s enabled",
3953 pf->sportdesc);
3954 } else {
3955 logeventf(ssh, "Remote port forwarding from %s refused",
3956 pf->sportdesc);
3957
3958 rpf = del234(ssh->rportfwds, pf);
3959 assert(rpf == pf);
fda2feb1 3960 free_rportfwd(pf);
06fadff5 3961 }
3962}
3963
3964static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
3965{
84328ddb 3966 const char *portfwd_strptr = cfg->portfwd;
3967 struct ssh_portfwd *epf;
3968 int i;
06fadff5 3969
fda2feb1 3970 if (!ssh->portfwds) {
3971 ssh->portfwds = newtree234(ssh_portcmp);
3972 } else {
3973 /*
3974 * Go through the existing port forwardings and tag them
84328ddb 3975 * with status==DESTROY. Any that we want to keep will be
3976 * re-enabled (status==KEEP) as we go through the
3977 * configuration and find out which bits are the same as
3978 * they were before.
fda2feb1 3979 */
3980 struct ssh_portfwd *epf;
3981 int i;
3982 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
84328ddb 3983 epf->status = DESTROY;
fda2feb1 3984 }
3985
06fadff5 3986 while (*portfwd_strptr) {
84328ddb 3987 char address_family, type;
3988 int sport,dport,sserv,dserv;
3989 char sports[256], dports[256], saddr[256], host[256];
3990 int n;
3991
05581745 3992 address_family = 'A';
3993 type = 'L';
84328ddb 3994 if (*portfwd_strptr == 'A' ||
3995 *portfwd_strptr == '4' ||
3996 *portfwd_strptr == '6')
3997 address_family = *portfwd_strptr++;
3998 if (*portfwd_strptr == 'L' ||
3999 *portfwd_strptr == 'R' ||
4000 *portfwd_strptr == 'D')
4001 type = *portfwd_strptr++;
05581745 4002
06fadff5 4003 saddr[0] = '\0';
05581745 4004
06fadff5 4005 n = 0;
4006 while (*portfwd_strptr && *portfwd_strptr != '\t') {
4007 if (*portfwd_strptr == ':') {
4008 /*
4009 * We've seen a colon in the middle of the
4010 * source port number. This means that
4011 * everything we've seen until now is the
4012 * source _address_, so we'll move it into
4013 * saddr and start sports from the beginning
4014 * again.
4015 */
4016 portfwd_strptr++;
4017 sports[n] = '\0';
4018 if (ssh->version == 1 && type == 'R') {
2e85c969 4019 logeventf(ssh, "SSH-1 cannot handle remote source address "
06fadff5 4020 "spec \"%s\"; ignoring", sports);
4021 } else
4022 strcpy(saddr, sports);
4023 n = 0;
4024 }
019164b0 4025 if (n < lenof(sports)-1) sports[n++] = *portfwd_strptr++;
06fadff5 4026 }
4027 sports[n] = 0;
4028 if (type != 'D') {
4029 if (*portfwd_strptr == '\t')
4030 portfwd_strptr++;
4031 n = 0;
4032 while (*portfwd_strptr && *portfwd_strptr != ':') {
019164b0 4033 if (n < lenof(host)-1) host[n++] = *portfwd_strptr++;
06fadff5 4034 }
4035 host[n] = 0;
4036 if (*portfwd_strptr == ':')
4037 portfwd_strptr++;
4038 n = 0;
4039 while (*portfwd_strptr) {
019164b0 4040 if (n < lenof(dports)-1) dports[n++] = *portfwd_strptr++;
06fadff5 4041 }
4042 dports[n] = 0;
4043 portfwd_strptr++;
4044 dport = atoi(dports);
4045 dserv = 0;
4046 if (dport == 0) {
4047 dserv = 1;
4048 dport = net_service_lookup(dports);
4049 if (!dport) {
4050 logeventf(ssh, "Service lookup failed for destination"
4051 " port \"%s\"", dports);
4052 }
4053 }
4054 } else {
4055 while (*portfwd_strptr) portfwd_strptr++;
a9e72926 4056 host[0] = 0;
4057 dports[0] = 0;
06fadff5 4058 dport = dserv = -1;
4059 portfwd_strptr++; /* eat the NUL and move to next one */
4060 }
4061 sport = atoi(sports);
4062 sserv = 0;
4063 if (sport == 0) {
4064 sserv = 1;
4065 sport = net_service_lookup(sports);
4066 if (!sport) {
4067 logeventf(ssh, "Service lookup failed for source"
4068 " port \"%s\"", sports);
4069 }
4070 }
4071 if (sport && dport) {
4072 /* Set up a description of the source port. */
fda2feb1 4073 struct ssh_portfwd *pfrec, *epfrec;
fda2feb1 4074
4075 pfrec = snew(struct ssh_portfwd);
4076 pfrec->type = type;
4077 pfrec->saddr = *saddr ? dupstr(saddr) : NULL;
3fe92132 4078 pfrec->sserv = sserv ? dupstr(sports) : NULL;
fda2feb1 4079 pfrec->sport = sport;
84328ddb 4080 pfrec->daddr = *host ? dupstr(host) : NULL;
3fe92132 4081 pfrec->dserv = dserv ? dupstr(dports) : NULL;
fda2feb1 4082 pfrec->dport = dport;
4083 pfrec->local = NULL;
4084 pfrec->remote = NULL;
05581745 4085 pfrec->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
4086 address_family == '6' ? ADDRTYPE_IPV6 :
4087 ADDRTYPE_UNSPEC);
fda2feb1 4088
4089 epfrec = add234(ssh->portfwds, pfrec);
4090 if (epfrec != pfrec) {
4091 /*
4092 * We already have a port forwarding with precisely
4093 * these parameters. Hence, no need to do anything;
84328ddb 4094 * simply tag the existing one as KEEP.
fda2feb1 4095 */
84328ddb 4096 epfrec->status = KEEP;
fda2feb1 4097 free_portfwd(pfrec);
84328ddb 4098 } else {
4099 pfrec->status = CREATE;
4100 }
4101 }
4102 }
4103
4104 /*
4105 * Now go through and destroy any port forwardings which were
4106 * not re-enabled.
4107 */
4108 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
4109 if (epf->status == DESTROY) {
4110 char *message;
4111
4112 message = dupprintf("%s port forwarding from %s%s%d",
4113 epf->type == 'L' ? "local" :
4114 epf->type == 'R' ? "remote" : "dynamic",
4115 epf->saddr ? epf->saddr : "",
4116 epf->saddr ? ":" : "",
4117 epf->sport);
4118
4119 if (epf->type != 'D') {
4120 char *msg2 = dupprintf("%s to %s:%d", message,
4121 epf->daddr, epf->dport);
4122 sfree(message);
4123 message = msg2;
4124 }
4125
4126 logeventf(ssh, "Cancelling %s", message);
4127 sfree(message);
4128
4129 if (epf->remote) {
4130 struct ssh_rportfwd *rpf = epf->remote;
4131 struct Packet *pktout;
4132
4133 /*
4134 * Cancel the port forwarding at the server
4135 * end.
4136 */
4137 if (ssh->version == 1) {
4138 /*
4139 * We cannot cancel listening ports on the
2e85c969 4140 * server side in SSH-1! There's no message
84328ddb 4141 * to support it. Instead, we simply remove
4142 * the rportfwd record from the local end
4143 * so that any connections the server tries
4144 * to make on it are rejected.
4145 */
4146 } else {
4147 pktout = ssh2_pkt_init(SSH2_MSG_GLOBAL_REQUEST);
4148 ssh2_pkt_addstring(pktout, "cancel-tcpip-forward");
4149 ssh2_pkt_addbool(pktout, 0);/* _don't_ want reply */
4150 if (epf->saddr) {
4151 ssh2_pkt_addstring(pktout, epf->saddr);
4152 } else if (ssh->cfg.rport_acceptall) {
5188540b 4153 /* XXX: ssh->cfg.rport_acceptall may not represent
4154 * what was used to open the original connection,
4155 * since it's reconfigurable. */
84328ddb 4156 ssh2_pkt_addstring(pktout, "0.0.0.0");
4157 } else {
4158 ssh2_pkt_addstring(pktout, "127.0.0.1");
4159 }
4160 ssh2_pkt_adduint32(pktout, epf->sport);
4161 ssh2_pkt_send(ssh, pktout);
4162 }
4163
4164 del234(ssh->rportfwds, rpf);
4165 free_rportfwd(rpf);
4166 } else if (epf->local) {
4167 pfd_terminate(epf->local);
4168 }
4169
4170 delpos234(ssh->portfwds, i);
4171 free_portfwd(epf);
4172 i--; /* so we don't skip one in the list */
4173 }
4174
4175 /*
4176 * And finally, set up any new port forwardings (status==CREATE).
4177 */
4178 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
4179 if (epf->status == CREATE) {
4180 char *sportdesc, *dportdesc;
3fe92132 4181 sportdesc = dupprintf("%s%s%s%s%d%s",
84328ddb 4182 epf->saddr ? epf->saddr : "",
4183 epf->saddr ? ":" : "",
3fe92132 4184 epf->sserv ? epf->sserv : "",
4185 epf->sserv ? "(" : "",
4186 epf->sport,
4187 epf->sserv ? ")" : "");
84328ddb 4188 if (epf->type == 'D') {
4189 dportdesc = NULL;
4190 } else {
3fe92132 4191 dportdesc = dupprintf("%s:%s%s%d%s",
4192 epf->daddr,
4193 epf->dserv ? epf->dserv : "",
4194 epf->dserv ? "(" : "",
4195 epf->dport,
4196 epf->dserv ? ")" : "");
84328ddb 4197 }
05581745 4198
84328ddb 4199 if (epf->type == 'L') {
4200 const char *err = pfd_addforward(epf->daddr, epf->dport,
4201 epf->saddr, epf->sport,
5188540b 4202 ssh, cfg,
84328ddb 4203 &epf->local,
4204 epf->addressfamily);
4205
4206 logeventf(ssh, "Local %sport %s forwarding to %s%s%s",
4207 epf->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
4208 epf->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
4209 sportdesc, dportdesc,
4210 err ? " failed: " : "", err ? err : "");
4211 } else if (epf->type == 'D') {
06fadff5 4212 const char *err = pfd_addforward(NULL, -1,
84328ddb 4213 epf->saddr, epf->sport,
5188540b 4214 ssh, cfg,
84328ddb 4215 &epf->local,
4216 epf->addressfamily);
4217
4218 logeventf(ssh, "Local %sport %s SOCKS dynamic forwarding%s%s",
4219 epf->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
4220 epf->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
4221 sportdesc,
4222 err ? " failed: " : "", err ? err : "");
06fadff5 4223 } else {
4224 struct ssh_rportfwd *pf;
4225
4226 /*
4227 * Ensure the remote port forwardings tree exists.
4228 */
4229 if (!ssh->rportfwds) {
4230 if (ssh->version == 1)
4231 ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);
4232 else
4233 ssh->rportfwds = newtree234(ssh_rportcmp_ssh2);
4234 }
4235
4236 pf = snew(struct ssh_rportfwd);
84328ddb 4237 strncpy(pf->dhost, epf->daddr, lenof(pf->dhost)-1);
4238 pf->dhost[lenof(pf->dhost)-1] = '\0';
4239 pf->dport = epf->dport;
4240 pf->sport = epf->sport;
06fadff5 4241 if (add234(ssh->rportfwds, pf) != pf) {
4242 logeventf(ssh, "Duplicate remote port forwarding to %s:%d",
84328ddb 4243 epf->daddr, epf->dport);
06fadff5 4244 sfree(pf);
4245 } else {
4246 logeventf(ssh, "Requesting remote port %s"
84328ddb 4247 " forward to %s", sportdesc, dportdesc);
06fadff5 4248
4249 pf->sportdesc = sportdesc;
4250 sportdesc = NULL;
84328ddb 4251 epf->remote = pf;
4252 pf->pfrec = epf;
06fadff5 4253
4254 if (ssh->version == 1) {
4255 send_packet(ssh, SSH1_CMSG_PORT_FORWARD_REQUEST,
84328ddb 4256 PKT_INT, epf->sport,
4257 PKT_STR, epf->daddr,
4258 PKT_INT, epf->dport,
06fadff5 4259 PKT_END);
4260 ssh_queue_handler(ssh, SSH1_SMSG_SUCCESS,
4261 SSH1_SMSG_FAILURE,
4262 ssh_rportfwd_succfail, pf);
4263 } else {
4264 struct Packet *pktout;
4265 pktout = ssh2_pkt_init(SSH2_MSG_GLOBAL_REQUEST);
4266 ssh2_pkt_addstring(pktout, "tcpip-forward");
4267 ssh2_pkt_addbool(pktout, 1);/* want reply */
84328ddb 4268 if (epf->saddr) {
4269 ssh2_pkt_addstring(pktout, epf->saddr);
5188540b 4270 } else if (cfg->rport_acceptall) {
06fadff5 4271 ssh2_pkt_addstring(pktout, "0.0.0.0");
4272 } else {
4273 ssh2_pkt_addstring(pktout, "127.0.0.1");
4274 }
84328ddb 4275 ssh2_pkt_adduint32(pktout, epf->sport);
06fadff5 4276 ssh2_pkt_send(ssh, pktout);
4277
4278 ssh_queue_handler(ssh, SSH2_MSG_REQUEST_SUCCESS,
4279 SSH2_MSG_REQUEST_FAILURE,
4280 ssh_rportfwd_succfail, pf);
4281 }
4282 }
4283 }
4284 sfree(sportdesc);
84328ddb 4285 sfree(dportdesc);
06fadff5 4286 }
06fadff5 4287}
4288
51df0ab5 4289static void ssh1_smsg_stdout_stderr_data(Ssh ssh, struct Packet *pktin)
4290{
4291 char *string;
4292 int stringlen, bufsize;
4293
4294 ssh_pkt_getstring(pktin, &string, &stringlen);
4295 if (string == NULL) {
4296 bombout(("Incoming terminal data packet was badly formed"));
4297 return;
4298 }
4299
4300 bufsize = from_backend(ssh->frontend, pktin->type == SSH1_SMSG_STDERR_DATA,
4301 string, stringlen);
4302 if (!ssh->v1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
4303 ssh->v1_stdout_throttling = 1;
4304 ssh1_throttle(ssh, +1);
4305 }
4306}
4307
4308static void ssh1_smsg_x11_open(Ssh ssh, struct Packet *pktin)
4309{
4310 /* Remote side is trying to open a channel to talk to our
4311 * X-Server. Give them back a local channel number. */
4312 struct ssh_channel *c;
4313 int remoteid = ssh_pkt_getuint32(pktin);
4314
4315 logevent("Received X11 connect request");
4316 /* Refuse if X11 forwarding is disabled. */
4317 if (!ssh->X11_fwd_enabled) {
4318 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
4319 PKT_INT, remoteid, PKT_END);
4320 logevent("Rejected X11 connect request");
4321 } else {
4322 c = snew(struct ssh_channel);
4323 c->ssh = ssh;
4324
4325 if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
4326 ssh->x11auth, NULL, -1, &ssh->cfg) != NULL) {
4327 logevent("Opening X11 forward connection failed");
4328 sfree(c);
4329 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
4330 PKT_INT, remoteid, PKT_END);
4331 } else {
4332 logevent
4333 ("Opening X11 forward connection succeeded");
4334 c->remoteid = remoteid;
64d6ff88 4335 c->halfopen = FALSE;
51df0ab5 4336 c->localid = alloc_channel_id(ssh);
4337 c->closes = 0;
4338 c->v.v1.throttling = 0;
4339 c->type = CHAN_X11; /* identify channel type */
4340 add234(ssh->channels, c);
4341 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
4342 PKT_INT, c->remoteid, PKT_INT,
4343 c->localid, PKT_END);
4344 logevent("Opened X11 forward channel");
4345 }
4346 }
4347}
4348
4349static void ssh1_smsg_agent_open(Ssh ssh, struct Packet *pktin)
4350{
4351 /* Remote side is trying to open a channel to talk to our
4352 * agent. Give them back a local channel number. */
4353 struct ssh_channel *c;
4354 int remoteid = ssh_pkt_getuint32(pktin);
4355
4356 /* Refuse if agent forwarding is disabled. */
4357 if (!ssh->agentfwd_enabled) {
4358 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
4359 PKT_INT, remoteid, PKT_END);
4360 } else {
4361 c = snew(struct ssh_channel);
4362 c->ssh = ssh;
4363 c->remoteid = remoteid;
64d6ff88 4364 c->halfopen = FALSE;
51df0ab5 4365 c->localid = alloc_channel_id(ssh);
4366 c->closes = 0;
4367 c->v.v1.throttling = 0;
4368 c->type = CHAN_AGENT; /* identify channel type */
4369 c->u.a.lensofar = 0;
4370 add234(ssh->channels, c);
4371 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
4372 PKT_INT, c->remoteid, PKT_INT, c->localid,
4373 PKT_END);
4374 }
4375}
4376
4377static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
4378{
4379 /* Remote side is trying to open a channel to talk to a
4380 * forwarded port. Give them back a local channel number. */
4381 struct ssh_channel *c;
05581745 4382 struct ssh_rportfwd pf, *pfp;
51df0ab5 4383 int remoteid;
4384 int hostsize, port;
fb983202 4385 char *host;
51df0ab5 4386 const char *e;
4387 c = snew(struct ssh_channel);
4388 c->ssh = ssh;
4389
4390 remoteid = ssh_pkt_getuint32(pktin);
4391 ssh_pkt_getstring(pktin, &host, &hostsize);
4392 port = ssh_pkt_getuint32(pktin);
4393
4394 if (hostsize >= lenof(pf.dhost))
4395 hostsize = lenof(pf.dhost)-1;
4396 memcpy(pf.dhost, host, hostsize);
4397 pf.dhost[hostsize] = '\0';
4398 pf.dport = port;
05581745 4399 pfp = find234(ssh->rportfwds, &pf, NULL);
51df0ab5 4400
05581745 4401 if (pfp == NULL) {
fb983202 4402 logeventf(ssh, "Rejected remote port open request for %s:%d",
4403 pf.dhost, port);
51df0ab5 4404 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
4405 PKT_INT, remoteid, PKT_END);
4406 } else {
fb983202 4407 logeventf(ssh, "Received remote port open request for %s:%d",
4408 pf.dhost, port);
51df0ab5 4409 e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
05581745 4410 c, &ssh->cfg, pfp->pfrec->addressfamily);
51df0ab5 4411 if (e != NULL) {
fb983202 4412 logeventf(ssh, "Port open failed: %s", e);
51df0ab5 4413 sfree(c);
4414 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
4415 PKT_INT, remoteid, PKT_END);
4416 } else {
4417 c->remoteid = remoteid;
64d6ff88 4418 c->halfopen = FALSE;
51df0ab5 4419 c->localid = alloc_channel_id(ssh);
4420 c->closes = 0;
4421 c->v.v1.throttling = 0;
4422 c->type = CHAN_SOCKDATA; /* identify channel type */
4423 add234(ssh->channels, c);
4424 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
4425 PKT_INT, c->remoteid, PKT_INT,
4426 c->localid, PKT_END);
4427 logevent("Forwarded port opened successfully");
4428 }
4429 }
4430}
4431
4432static void ssh1_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
4433{
4434 unsigned int remoteid = ssh_pkt_getuint32(pktin);
4435 unsigned int localid = ssh_pkt_getuint32(pktin);
4436 struct ssh_channel *c;
4437
4438 c = find234(ssh->channels, &remoteid, ssh_channelfind);
4439 if (c && c->type == CHAN_SOCKDATA_DORMANT) {
4440 c->remoteid = localid;
64d6ff88 4441 c->halfopen = FALSE;
51df0ab5 4442 c->type = CHAN_SOCKDATA;
4443 c->v.v1.throttling = 0;
4444 pfd_confirm(c->u.pfd.s);
4445 }
4446
4447 if (c && c->closes) {
4448 /*
4449 * We have a pending close on this channel,
4450 * which we decided on before the server acked
4451 * the channel open. So now we know the
4452 * remoteid, we can close it again.
4453 */
4454 send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE,
4455 PKT_INT, c->remoteid, PKT_END);
4456 }
4457}
4458
4459static void ssh1_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
4460{
4461 unsigned int remoteid = ssh_pkt_getuint32(pktin);
4462 struct ssh_channel *c;
4463
4464 c = find234(ssh->channels, &remoteid, ssh_channelfind);
4465 if (c && c->type == CHAN_SOCKDATA_DORMANT) {
4466 logevent("Forwarded connection refused by server");
4467 pfd_close(c->u.pfd.s);
4468 del234(ssh->channels, c);
4469 sfree(c);
4470 }
4471}
4472
4473static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
4474{
4475 /* Remote side closes a channel. */
4476 unsigned i = ssh_pkt_getuint32(pktin);
4477 struct ssh_channel *c;
4478 c = find234(ssh->channels, &i, ssh_channelfind);
64d6ff88 4479 if (c && !c->halfopen) {
51df0ab5 4480 int closetype;
4481 closetype =
4482 (pktin->type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
4483
4484 if ((c->closes == 0) && (c->type == CHAN_X11)) {
4485 logevent("Forwarded X11 connection terminated");
4486 assert(c->u.x11.s != NULL);
4487 x11_close(c->u.x11.s);
4488 c->u.x11.s = NULL;
4489 }
4490 if ((c->closes == 0) && (c->type == CHAN_SOCKDATA)) {
4491 logevent("Forwarded port closed");
4492 assert(c->u.pfd.s != NULL);
4493 pfd_close(c->u.pfd.s);
4494 c->u.pfd.s = NULL;
4495 }
4496
4497 c->closes |= (closetype << 2); /* seen this message */
4498 if (!(c->closes & closetype)) {
4499 send_packet(ssh, pktin->type, PKT_INT, c->remoteid,
4500 PKT_END);
4501 c->closes |= closetype; /* sent it too */
4502 }
4503
4504 if (c->closes == 15) {
4505 del234(ssh->channels, c);
4506 sfree(c);
4507 }
4508 } else {
4509 bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n",
4510 pktin->type == SSH1_MSG_CHANNEL_CLOSE ? "" :
4511 "_CONFIRMATION", c ? "half-open" : "nonexistent",
4512 i));
4513 }
4514}
4515
4516static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
4517{
4518 /* Data sent down one of our channels. */
4519 int i = ssh_pkt_getuint32(pktin);
4520 char *p;
6d44acc9 4521 int len;
51df0ab5 4522 struct ssh_channel *c;
4523
4524 ssh_pkt_getstring(pktin, &p, &len);
4525
4526 c = find234(ssh->channels, &i, ssh_channelfind);
4527 if (c) {
4528 int bufsize = 0;
4529 switch (c->type) {
4530 case CHAN_X11:
4531 bufsize = x11_send(c->u.x11.s, p, len);
4532 break;
4533 case CHAN_SOCKDATA:
4534 bufsize = pfd_send(c->u.pfd.s, p, len);
4535 break;
4536 case CHAN_AGENT:
4537 /* Data for an agent message. Buffer it. */
4538 while (len > 0) {
4539 if (c->u.a.lensofar < 4) {
aa63ab7e 4540 unsigned int l = min(4 - c->u.a.lensofar, len);
51df0ab5 4541 memcpy(c->u.a.msglen + c->u.a.lensofar, p,
4542 l);
4543 p += l;
4544 len -= l;
4545 c->u.a.lensofar += l;
4546 }
4547 if (c->u.a.lensofar == 4) {
4548 c->u.a.totallen =
4549 4 + GET_32BIT(c->u.a.msglen);
4550 c->u.a.message = snewn(c->u.a.totallen,
4551 unsigned char);
4552 memcpy(c->u.a.message, c->u.a.msglen, 4);
4553 }
4554 if (c->u.a.lensofar >= 4 && len > 0) {
aa63ab7e 4555 unsigned int l =
51df0ab5 4556 min(c->u.a.totallen - c->u.a.lensofar,
4557 len);
4558 memcpy(c->u.a.message + c->u.a.lensofar, p,
4559 l);
4560 p += l;
4561 len -= l;
4562 c->u.a.lensofar += l;
4563 }
4564 if (c->u.a.lensofar == c->u.a.totallen) {
4565 void *reply;
4566 int replylen;
4567 if (agent_query(c->u.a.message,
4568 c->u.a.totallen,
4569 &reply, &replylen,
4570 ssh_agentf_callback, c))
4571 ssh_agentf_callback(c, reply, replylen);
4572 sfree(c->u.a.message);
4573 c->u.a.lensofar = 0;
4574 }
4575 }
4576 bufsize = 0; /* agent channels never back up */
4577 break;
4578 }
4579 if (!c->v.v1.throttling && bufsize > SSH1_BUFFER_LIMIT) {
4580 c->v.v1.throttling = 1;
4581 ssh1_throttle(ssh, +1);
4582 }
4583 }
4584}
4585
4586static void ssh1_smsg_exit_status(Ssh ssh, struct Packet *pktin)
4587{
51df0ab5 4588 ssh->exitcode = ssh_pkt_getuint32(pktin);
fb983202 4589 logeventf(ssh, "Server sent command exit status %d", ssh->exitcode);
51df0ab5 4590 send_packet(ssh, SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
4591 /*
4592 * In case `helpful' firewalls or proxies tack
4593 * extra human-readable text on the end of the
4594 * session which we might mistake for another
4595 * encrypted packet, we close the session once
4596 * we've sent EXIT_CONFIRMATION.
4597 */
9e296bfa 4598 ssh_disconnect(ssh, NULL, NULL, 0, TRUE);
51df0ab5 4599}
4600
c6ccd5c2 4601/* Helper function to deal with sending tty modes for REQUEST_PTY */
4602static void ssh1_send_ttymode(void *data, char *mode, char *val)
4603{
4604 struct Packet *pktout = (struct Packet *)data;
4605 int i = 0;
4606 unsigned int arg = 0;
4607 while (strcmp(mode, ssh_ttymodes[i].mode) != 0) i++;
4608 if (i == lenof(ssh_ttymodes)) return;
4609 switch (ssh_ttymodes[i].type) {
4610 case TTY_OP_CHAR:
4611 arg = ssh_tty_parse_specchar(val);
4612 break;
4613 case TTY_OP_BOOL:
4614 arg = ssh_tty_parse_boolean(val);
4615 break;
4616 }
4617 ssh2_pkt_addbyte(pktout, ssh_ttymodes[i].opcode);
4618 ssh2_pkt_addbyte(pktout, arg);
4619}
4620
4621
b09eaa88 4622static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
4623 struct Packet *pktin)
32874aea 4624{
b09eaa88 4625 crBegin(ssh->do_ssh1_connection_crstate);
fb09bf1c 4626
51df0ab5 4627 ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] =
4628 ssh->packet_dispatch[SSH1_SMSG_STDERR_DATA] =
4629 ssh1_smsg_stdout_stderr_data;
4630
4631 ssh->packet_dispatch[SSH1_MSG_CHANNEL_OPEN_CONFIRMATION] =
4632 ssh1_msg_channel_open_confirmation;
4633 ssh->packet_dispatch[SSH1_MSG_CHANNEL_OPEN_FAILURE] =
4634 ssh1_msg_channel_open_failure;
4635 ssh->packet_dispatch[SSH1_MSG_CHANNEL_CLOSE] =
4636 ssh->packet_dispatch[SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION] =
4637 ssh1_msg_channel_close;
4638 ssh->packet_dispatch[SSH1_MSG_CHANNEL_DATA] = ssh1_msg_channel_data;
4639 ssh->packet_dispatch[SSH1_SMSG_EXIT_STATUS] = ssh1_smsg_exit_status;
4640
86916870 4641 if (ssh->cfg.agentfwd && agent_exists()) {
32874aea 4642 logevent("Requesting agent forwarding");
51470298 4643 send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
32874aea 4644 do {
4645 crReturnV;
ff3187f6 4646 } while (!pktin);
4647 if (pktin->type != SSH1_SMSG_SUCCESS
4648 && pktin->type != SSH1_SMSG_FAILURE) {
6b5cf8b4 4649 bombout(("Protocol confusion"));
7ffdbc1a 4650 crStopV;
ff3187f6 4651 } else if (pktin->type == SSH1_SMSG_FAILURE) {
32874aea 4652 logevent("Agent forwarding refused");
4653 } else {
4654 logevent("Agent forwarding enabled");
51470298 4655 ssh->agentfwd_enabled = TRUE;
51df0ab5 4656 ssh->packet_dispatch[SSH1_SMSG_AGENT_OPEN] = ssh1_smsg_agent_open;
db7d555c 4657 }
dacbd0e8 4658 }
4659
86916870 4660 if (ssh->cfg.x11_forward) {
32874aea 4661 char proto[20], data[64];
4662 logevent("Requesting X11 forwarding");
302121de 4663 ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
86916870 4664 data, sizeof(data), ssh->cfg.x11_auth);
4665 x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display);
f68353be 4666 /*
4667 * Note that while we blank the X authentication data here, we don't
4668 * take any special action to blank the start of an X11 channel,
4669 * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection
4670 * without having session blanking enabled is likely to leak your
4671 * cookie into the log.
4672 */
51470298 4673 if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
4674 send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
f68353be 4675 PKT_STR, proto,
4676 PKTT_PASSWORD, PKT_STR, data, PKTT_OTHER,
86916870 4677 PKT_INT, x11_get_screen_number(ssh->cfg.x11_display),
421d6835 4678 PKT_END);
32874aea 4679 } else {
51470298 4680 send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
f68353be 4681 PKT_STR, proto,
4682 PKTT_PASSWORD, PKT_STR, data, PKTT_OTHER, PKT_END);
32874aea 4683 }
4684 do {
4685 crReturnV;
ff3187f6 4686 } while (!pktin);
4687 if (pktin->type != SSH1_SMSG_SUCCESS
4688 && pktin->type != SSH1_SMSG_FAILURE) {
6b5cf8b4 4689 bombout(("Protocol confusion"));
7ffdbc1a 4690 crStopV;
ff3187f6 4691 } else if (pktin->type == SSH1_SMSG_FAILURE) {
32874aea 4692 logevent("X11 forwarding refused");
4693 } else {
4694 logevent("X11 forwarding enabled");
51470298 4695 ssh->X11_fwd_enabled = TRUE;
51df0ab5 4696 ssh->packet_dispatch[SSH1_SMSG_X11_OPEN] = ssh1_smsg_x11_open;
9c964e85 4697 }
4698 }
4699
06fadff5 4700 ssh_setup_portfwd(ssh, &ssh->cfg);
4701 ssh->packet_dispatch[SSH1_MSG_PORT_OPEN] = ssh1_msg_port_open;
d74d141c 4702
86916870 4703 if (!ssh->cfg.nopty) {
c6ccd5c2 4704 struct Packet *pkt;
a5dd8467 4705 /* Unpick the terminal-speed string. */
4706 /* XXX perhaps we should allow no speeds to be sent. */
db219738 4707 ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
4708 sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
a5dd8467 4709 /* Send the pty request. */
c6ccd5c2 4710 pkt = ssh1_pkt_init(SSH1_CMSG_REQUEST_PTY);
4711 ssh_pkt_addstring(pkt, ssh->cfg.termtype);
4712 ssh_pkt_adduint32(pkt, ssh->term_height);
4713 ssh_pkt_adduint32(pkt, ssh->term_width);
4714 ssh_pkt_adduint32(pkt, 0); /* width in pixels */
4715 ssh_pkt_adduint32(pkt, 0); /* height in pixels */
4716 parse_ttymodes(ssh, ssh->cfg.ttymodes,
4717 ssh1_send_ttymode, (void *)pkt);
4718 ssh_pkt_addbyte(pkt, SSH1_TTY_OP_ISPEED);
4719 ssh_pkt_adduint32(pkt, ssh->ispeed);
4720 ssh_pkt_addbyte(pkt, SSH1_TTY_OP_OSPEED);
4721 ssh_pkt_adduint32(pkt, ssh->ospeed);
4722 ssh_pkt_addbyte(pkt, SSH_TTY_OP_END);
4723 s_wrpkt(ssh, pkt);
51470298 4724 ssh->state = SSH_STATE_INTERMED;
32874aea 4725 do {
4726 crReturnV;
ff3187f6 4727 } while (!pktin);
4728 if (pktin->type != SSH1_SMSG_SUCCESS
4729 && pktin->type != SSH1_SMSG_FAILURE) {
6b5cf8b4 4730 bombout(("Protocol confusion"));
7ffdbc1a 4731 crStopV;
ff3187f6 4732 } else if (pktin->type == SSH1_SMSG_FAILURE) {
51470298 4733 c_write_str(ssh, "Server refused to allocate pty\r\n");
4734 ssh->editing = ssh->echoing = 1;
32874aea 4735 }
a5dd8467 4736 logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
db219738 4737 ssh->ospeed, ssh->ispeed);
0965bee0 4738 } else {
51470298 4739 ssh->editing = ssh->echoing = 1;
374330e2 4740 }
4741
86916870 4742 if (ssh->cfg.compression) {
51470298 4743 send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
32874aea 4744 do {
4745 crReturnV;
ff3187f6 4746 } while (!pktin);
4747 if (pktin->type != SSH1_SMSG_SUCCESS
4748 && pktin->type != SSH1_SMSG_FAILURE) {
6b5cf8b4 4749 bombout(("Protocol confusion"));
7ffdbc1a 4750 crStopV;
ff3187f6 4751 } else if (pktin->type == SSH1_SMSG_FAILURE) {
51470298 4752 c_write_str(ssh, "Server refused to compress\r\n");
32874aea 4753 }
4ba9b64b 4754 logevent("Started compression");
51470298 4755 ssh->v1_compressing = TRUE;
5366aed8 4756 ssh->cs_comp_ctx = zlib_compress_init();
4757 logevent("Initialised zlib (RFC1950) compression");
4758 ssh->sc_comp_ctx = zlib_decompress_init();
4759 logevent("Initialised zlib (RFC1950) decompression");
4ba9b64b 4760 }
4761
fd5e5847 4762 /*
4763 * Start the shell or command.
4764 *
2e85c969 4765 * Special case: if the first-choice command is an SSH-2
fd5e5847 4766 * subsystem (hence not usable here) and the second choice
4767 * exists, we fall straight back to that.
4768 */
4769 {
86916870 4770 char *cmd = ssh->cfg.remote_cmd_ptr;
04c52f10 4771
4772 if (!cmd) cmd = ssh->cfg.remote_cmd;
fd5e5847 4773
86916870 4774 if (ssh->cfg.ssh_subsys && ssh->cfg.remote_cmd_ptr2) {
4775 cmd = ssh->cfg.remote_cmd_ptr2;
51470298 4776 ssh->fallback_cmd = TRUE;
fd5e5847 4777 }
4778 if (*cmd)
51470298 4779 send_packet(ssh, SSH1_CMSG_EXEC_CMD, PKT_STR, cmd, PKT_END);
fd5e5847 4780 else
51470298 4781 send_packet(ssh, SSH1_CMSG_EXEC_SHELL, PKT_END);
fd5e5847 4782 logevent("Started session");
4783 }
374330e2 4784
51470298 4785 ssh->state = SSH_STATE_SESSION;
4786 if (ssh->size_needed)
4787 ssh_size(ssh, ssh->term_width, ssh->term_height);
4788 if (ssh->eof_needed)
4789 ssh_special(ssh, TS_EOF);
374330e2 4790
b9d7bcad 4791 if (ssh->ldisc)
4792 ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
51470298 4793 ssh->send_ok = 1;
4794 ssh->channels = newtree234(ssh_channelcmp);
374330e2 4795 while (1) {
d74d141c 4796
51df0ab5 4797 /*
4798 * By this point, most incoming packets are already being
4799 * handled by the dispatch table, and we need only pay
4800 * attention to the unusual ones.
4801 */
0357890f 4802
51df0ab5 4803 crReturnV;
4804 if (pktin) {
4805 if (pktin->type == SSH1_SMSG_SUCCESS) {
972a41c8 4806 /* may be from EXEC_SHELL on some servers */
ff3187f6 4807 } else if (pktin->type == SSH1_SMSG_FAILURE) {
972a41c8 4808 /* may be from EXEC_SHELL on some servers
374330e2 4809 * if no pty is available or in other odd cases. Ignore */
374330e2 4810 } else {
ff3187f6 4811 bombout(("Strange packet received: type %d", pktin->type));
7ffdbc1a 4812 crStopV;
374330e2 4813 }
4814 } else {
8df7a775 4815 while (inlen > 0) {
4816 int len = min(inlen, 512);
9a10ecf4 4817 send_packet(ssh, SSH1_CMSG_STDIN_DATA, PKTT_DATA,
4818 PKT_INT, len, PKT_DATA, in, len,
4819 PKTT_OTHER, PKT_END);
8df7a775 4820 in += len;
4821 inlen -= len;
4822 }
374330e2 4823 }
4824 }
4825
4826 crFinishV;
4827}
4828
4829/*
2e85c969 4830 * Handle the top-level SSH-2 protocol.
b09eaa88 4831 */
4832static void ssh1_msg_debug(Ssh ssh, struct Packet *pktin)
4833{
fb983202 4834 char *msg;
b09eaa88 4835 int msglen;
4836
4837 ssh_pkt_getstring(pktin, &msg, &msglen);
fb983202 4838 logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
b09eaa88 4839}
4840
4841static void ssh1_msg_disconnect(Ssh ssh, struct Packet *pktin)
4842{
4843 /* log reason code in disconnect message */
4844 char *msg;
4845 int msglen;
4846
4847 ssh_pkt_getstring(pktin, &msg, &msglen);
4848 bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));
4849}
4850
409bfa77 4851static void ssh_msg_ignore(Ssh ssh, struct Packet *pktin)
b09eaa88 4852{
4853 /* Do nothing, because we're ignoring it! Duhh. */
4854}
4855
4856static void ssh1_protocol_setup(Ssh ssh)
4857{
4858 int i;
4859
4860 /*
4861 * Most messages are handled by the coroutines.
4862 */
4863 for (i = 0; i < 256; i++)
4864 ssh->packet_dispatch[i] = NULL;
4865
4866 /*
4867 * These special message types we install handlers for.
4868 */
4869 ssh->packet_dispatch[SSH1_MSG_DISCONNECT] = ssh1_msg_disconnect;
4870 ssh->packet_dispatch[SSH1_MSG_IGNORE] = ssh_msg_ignore;
4871 ssh->packet_dispatch[SSH1_MSG_DEBUG] = ssh1_msg_debug;
4872}
4873
1c1a7262 4874static void ssh1_protocol(Ssh ssh, void *vin, int inlen,
b09eaa88 4875 struct Packet *pktin)
4876{
1c1a7262 4877 unsigned char *in=(unsigned char*)vin;
b09eaa88 4878 if (ssh->state == SSH_STATE_CLOSED)
4879 return;
4880
4881 if (pktin && ssh->packet_dispatch[pktin->type]) {
4882 ssh->packet_dispatch[pktin->type](ssh, pktin);
4883 return;
4884 }
4885
4886 if (!ssh->protocol_initial_phase_done) {
4887 if (do_ssh1_login(ssh, in, inlen, pktin))
4888 ssh->protocol_initial_phase_done = TRUE;
4889 else
4890 return;
4891 }
4892
4893 do_ssh1_connection(ssh, in, inlen, pktin);
4894}
4895
4896/*
e5574168 4897 * Utility routine for decoding comma-separated strings in KEXINIT.
4898 */
32874aea 4899static int in_commasep_string(char *needle, char *haystack, int haylen)
4900{
57356d63 4901 int needlen;
4902 if (!needle || !haystack) /* protect against null pointers */
4903 return 0;
4904 needlen = strlen(needle);
e5574168 4905 while (1) {
32874aea 4906 /*
4907 * Is it at the start of the string?
4908 */
4909 if (haylen >= needlen && /* haystack is long enough */
4910 !memcmp(needle, haystack, needlen) && /* initial match */
4911 (haylen == needlen || haystack[needlen] == ',')
4912 /* either , or EOS follows */
4913 )
4914 return 1;
4915 /*
4916 * If not, search for the next comma and resume after that.
4917 * If no comma found, terminate.
4918 */
4919 while (haylen > 0 && *haystack != ',')
4920 haylen--, haystack++;
4921 if (haylen == 0)
4922 return 0;
4923 haylen--, haystack++; /* skip over comma itself */
e5574168 4924 }
4925}
4926
4927/*
b59743d5 4928 * Similar routine for checking whether we have the first string in a list.
4929 */
4930static int first_in_commasep_string(char *needle, char *haystack, int haylen)
4931{
4932 int needlen;
4933 if (!needle || !haystack) /* protect against null pointers */
4934 return 0;
4935 needlen = strlen(needle);
4936 /*
4937 * Is it at the start of the string?
4938 */
4939 if (haylen >= needlen && /* haystack is long enough */
4940 !memcmp(needle, haystack, needlen) && /* initial match */
4941 (haylen == needlen || haystack[needlen] == ',')
4942 /* either , or EOS follows */
4943 )
4944 return 1;
4945 return 0;
4946}
4947
4948
4949/*
2e85c969 4950 * SSH-2 key creation method.
d39f364a 4951 */
b672f405 4952static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H, char chr,
d8baa528 4953 unsigned char *keyspace)
32874aea 4954{
b672f405 4955 const struct ssh_hash *h = ssh->kex->hash;
4956 void *s;
4957 /* First hlen bytes. */
4958 s = h->init();
51470298 4959 if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
b672f405 4960 hash_mpint(h, s, K);
4961 h->bytes(s, H, h->hlen);
4962 h->bytes(s, &chr, 1);
4963 h->bytes(s, ssh->v2_session_id, ssh->v2_session_id_len);
4964 h->final(s, keyspace);
4965 /* Next hlen bytes. */
4966 s = h->init();
51470298 4967 if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
b672f405 4968 hash_mpint(h, s, K);
4969 h->bytes(s, H, h->hlen);
4970 h->bytes(s, keyspace, h->hlen);
4971 h->final(s, keyspace + h->hlen);
d39f364a 4972}
4973
4974/*
2e85c969 4975 * Handle the SSH-2 transport layer.
e5574168 4976 */
1c1a7262 4977static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
ff3187f6 4978 struct Packet *pktin)
e5574168 4979{
1c1a7262 4980 unsigned char *in = (unsigned char *)vin;
51470298 4981 struct do_ssh2_transport_state {
4763c1c2 4982 int nbits, pbits, warn_kex, warn_cscipher, warn_sccipher;
51470298 4983 Bignum p, g, e, f, K;
3dc9a6a7 4984 void *our_kexinit;
4985 int our_kexinitlen;
51470298 4986 int kex_init_value, kex_reply_value;
4987 const struct ssh_mac **maclist;
4988 int nmacs;
4989 const struct ssh2_cipher *cscipher_tobe;
4990 const struct ssh2_cipher *sccipher_tobe;
4991 const struct ssh_mac *csmac_tobe;
4992 const struct ssh_mac *scmac_tobe;
4993 const struct ssh_compress *cscomp_tobe;
4994 const struct ssh_compress *sccomp_tobe;
4995 char *hostkeydata, *sigdata, *keystr, *fingerprint;
4996 int hostkeylen, siglen;
4997 void *hkey; /* actual host key */
2ccb2fc8 4998 unsigned char exchange_hash[32];
83e7d008 4999 int n_preferred_kex;
34557659 5000 const struct ssh_kexes *preferred_kex[KEX_MAX];
51470298 5001 int n_preferred_ciphers;
5002 const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
5003 const struct ssh_compress *preferred_comp;
e13bba36 5004 int got_session_id, activated_authconn;
ff3187f6 5005 struct Packet *pktout;
3d9449a1 5006 int dlgret;
5007 int guessok;
4763c1c2 5008 int ignorepkt;
51470298 5009 };
5010 crState(do_ssh2_transport_state);
5011
5012 crBegin(ssh->do_ssh2_transport_crstate);
5013
5014 s->cscipher_tobe = s->sccipher_tobe = NULL;
5015 s->csmac_tobe = s->scmac_tobe = NULL;
5016 s->cscomp_tobe = s->sccomp_tobe = NULL;
5017
e13bba36 5018 s->got_session_id = s->activated_authconn = FALSE;
e5574168 5019
e13bba36 5020 /*
5021 * Be prepared to work around the buggy MAC problem.
5022 */
5023 if (ssh->remote_bugs & BUG_SSH2_HMAC)
5024 s->maclist = buggymacs, s->nmacs = lenof(buggymacs);
5025 else
5026 s->maclist = macs, s->nmacs = lenof(macs);
5027
5028 begin_key_exchange:
149d2abc 5029 ssh->pkt_ctx &= ~SSH2_PKTCTX_KEX_MASK;
51470298 5030 {
e13bba36 5031 int i, j, commalist_started;
5032
51470298 5033 /*
83e7d008 5034 * Set up the preferred key exchange. (NULL => warn below here)
5035 */
5036 s->n_preferred_kex = 0;
5037 for (i = 0; i < KEX_MAX; i++) {
5038 switch (ssh->cfg.ssh_kexlist[i]) {
5039 case KEX_DHGEX:
5040 s->preferred_kex[s->n_preferred_kex++] =
5041 &ssh_diffiehellman_gex;
5042 break;
5043 case KEX_DHGROUP14:
5044 s->preferred_kex[s->n_preferred_kex++] =
5045 &ssh_diffiehellman_group14;
5046 break;
5047 case KEX_DHGROUP1:
5048 s->preferred_kex[s->n_preferred_kex++] =
5049 &ssh_diffiehellman_group1;
5050 break;
5051 case CIPHER_WARN:
5052 /* Flag for later. Don't bother if it's the last in
5053 * the list. */
5054 if (i < KEX_MAX - 1) {
5055 s->preferred_kex[s->n_preferred_kex++] = NULL;
5056 }
5057 break;
5058 }
5059 }
83e7d008 5060
83e7d008 5061 /*
51470298 5062 * Set up the preferred ciphers. (NULL => warn below here)
5063 */
5064 s->n_preferred_ciphers = 0;
5065 for (i = 0; i < CIPHER_MAX; i++) {
86916870 5066 switch (ssh->cfg.ssh_cipherlist[i]) {
51470298 5067 case CIPHER_BLOWFISH:
5068 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;
5069 break;
5070 case CIPHER_DES:
86916870 5071 if (ssh->cfg.ssh2_des_cbc) {
51470298 5072 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;
5073 }
5074 break;
5075 case CIPHER_3DES:
5076 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_3des;
5077 break;
5078 case CIPHER_AES:
5079 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_aes;
5080 break;
a2add208 5081 case CIPHER_ARCFOUR:
5082 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_arcfour;
5083 break;
51470298 5084 case CIPHER_WARN:
5085 /* Flag for later. Don't bother if it's the last in
5086 * the list. */
5087 if (i < CIPHER_MAX - 1) {
5088 s->preferred_ciphers[s->n_preferred_ciphers++] = NULL;
5089 }
5090 break;
ca20bfcf 5091 }
ca20bfcf 5092 }
7591b9ff 5093
e13bba36 5094 /*
5095 * Set up preferred compression.
5096 */
5097 if (ssh->cfg.compression)
5098 s->preferred_comp = &ssh_zlib;
5099 else
5100 s->preferred_comp = &ssh_comp_none;
51470298 5101
5102 /*
590f6a5f 5103 * Enable queueing of outgoing auth- or connection-layer
5104 * packets while we are in the middle of a key exchange.
5105 */
5106 ssh->queueing = TRUE;
5107
5108 /*
9442dd57 5109 * Flag that KEX is in progress.
5110 */
5111 ssh->kex_in_progress = TRUE;
5112
5113 /*
51470298 5114 * Construct and send our key exchange packet.
5115 */
ff3187f6 5116 s->pktout = ssh2_pkt_init(SSH2_MSG_KEXINIT);
51470298 5117 for (i = 0; i < 16; i++)
ff3187f6 5118 ssh2_pkt_addbyte(s->pktout, (unsigned char) random_byte());
51470298 5119 /* List key exchange algorithms. */
ff3187f6 5120 ssh2_pkt_addstring_start(s->pktout);
83e7d008 5121 commalist_started = 0;
5122 for (i = 0; i < s->n_preferred_kex; i++) {
34557659 5123 const struct ssh_kexes *k = s->preferred_kex[i];
83e7d008 5124 if (!k) continue; /* warning flag */
34557659 5125 for (j = 0; j < k->nkexes; j++) {
5126 if (commalist_started)
5127 ssh2_pkt_addstring_str(s->pktout, ",");
5128 ssh2_pkt_addstring_str(s->pktout, k->list[j]->name);
5129 commalist_started = 1;
5130 }
32874aea 5131 }
51470298 5132 /* List server host key algorithms. */
ff3187f6 5133 ssh2_pkt_addstring_start(s->pktout);
51470298 5134 for (i = 0; i < lenof(hostkey_algs); i++) {
ff3187f6 5135 ssh2_pkt_addstring_str(s->pktout, hostkey_algs[i]->name);
51470298 5136 if (i < lenof(hostkey_algs) - 1)
ff3187f6 5137 ssh2_pkt_addstring_str(s->pktout, ",");
32874aea 5138 }
51470298 5139 /* List client->server encryption algorithms. */
ff3187f6 5140 ssh2_pkt_addstring_start(s->pktout);
83e7d008 5141 commalist_started = 0;
51470298 5142 for (i = 0; i < s->n_preferred_ciphers; i++) {
5143 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
5144 if (!c) continue; /* warning flag */
5145 for (j = 0; j < c->nciphers; j++) {
83e7d008 5146 if (commalist_started)
ff3187f6 5147 ssh2_pkt_addstring_str(s->pktout, ",");
5148 ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);
83e7d008 5149 commalist_started = 1;
51470298 5150 }
5151 }
5152 /* List server->client encryption algorithms. */
ff3187f6 5153 ssh2_pkt_addstring_start(s->pktout);
83e7d008 5154 commalist_started = 0;
51470298 5155 for (i = 0; i < s->n_preferred_ciphers; i++) {
5156 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
5157 if (!c) continue; /* warning flag */
5158 for (j = 0; j < c->nciphers; j++) {
83e7d008 5159 if (commalist_started)
ff3187f6 5160 ssh2_pkt_addstring_str(s->pktout, ",");
5161 ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);
83e7d008 5162 commalist_started = 1;
51470298 5163 }
5164 }
5165 /* List client->server MAC algorithms. */
ff3187f6 5166 ssh2_pkt_addstring_start(s->pktout);
51470298 5167 for (i = 0; i < s->nmacs; i++) {
ff3187f6 5168 ssh2_pkt_addstring_str(s->pktout, s->maclist[i]->name);
51470298 5169 if (i < s->nmacs - 1)
ff3187f6 5170 ssh2_pkt_addstring_str(s->pktout, ",");
51470298 5171 }
5172 /* List server->client MAC algorithms. */
ff3187f6 5173 ssh2_pkt_addstring_start(s->pktout);
51470298 5174 for (i = 0; i < s->nmacs; i++) {
ff3187f6 5175 ssh2_pkt_addstring_str(s->pktout, s->maclist[i]->name);
51470298 5176 if (i < s->nmacs - 1)
ff3187f6 5177 ssh2_pkt_addstring_str(s->pktout, ",");
51470298 5178 }
5179 /* List client->server compression algorithms. */
ff3187f6 5180 ssh2_pkt_addstring_start(s->pktout);
f6e0abe2 5181 assert(lenof(compressions) > 1);
ff3187f6 5182 ssh2_pkt_addstring_str(s->pktout, s->preferred_comp->name);
f6e0abe2 5183 for (i = 0; i < lenof(compressions); i++) {
5184 const struct ssh_compress *c = compressions[i];
5185 if (c != s->preferred_comp) {
ff3187f6 5186 ssh2_pkt_addstring_str(s->pktout, ",");
5187 ssh2_pkt_addstring_str(s->pktout, c->name);
f6e0abe2 5188 }
51470298 5189 }
5190 /* List server->client compression algorithms. */
ff3187f6 5191 ssh2_pkt_addstring_start(s->pktout);
f6e0abe2 5192 assert(lenof(compressions) > 1);
ff3187f6 5193 ssh2_pkt_addstring_str(s->pktout, s->preferred_comp->name);
f6e0abe2 5194 for (i = 0; i < lenof(compressions); i++) {
5195 const struct ssh_compress *c = compressions[i];
5196 if (c != s->preferred_comp) {
ff3187f6 5197 ssh2_pkt_addstring_str(s->pktout, ",");
5198 ssh2_pkt_addstring_str(s->pktout, c->name);
f6e0abe2 5199 }
51470298 5200 }
5201 /* List client->server languages. Empty list. */
ff3187f6 5202 ssh2_pkt_addstring_start(s->pktout);
51470298 5203 /* List server->client languages. Empty list. */
ff3187f6 5204 ssh2_pkt_addstring_start(s->pktout);
51470298 5205 /* First KEX packet does _not_ follow, because we're not that brave. */
ff3187f6 5206 ssh2_pkt_addbool(s->pktout, FALSE);
51470298 5207 /* Reserved. */
ff3187f6 5208 ssh2_pkt_adduint32(s->pktout, 0);
e5574168 5209 }
0db56f73 5210
3dc9a6a7 5211 s->our_kexinitlen = s->pktout->length - 5;
5212 s->our_kexinit = snewn(s->our_kexinitlen, unsigned char);
5213 memcpy(s->our_kexinit, s->pktout->data + 5, s->our_kexinitlen);
0db56f73 5214
590f6a5f 5215 ssh2_pkt_send_noqueue(ssh, s->pktout);
e5574168 5216
ff3187f6 5217 if (!pktin)
5218 crWaitUntil(pktin);
e5574168 5219
5220 /*
5221 * Now examine the other side's KEXINIT to see what we're up
5222 * to.
5223 */
51470298 5224 {
4763c1c2 5225 char *str, *preferred;
3d9449a1 5226 int i, j, len;
51470298 5227
ff3187f6 5228 if (pktin->type != SSH2_MSG_KEXINIT) {
6b5cf8b4 5229 bombout(("expected key exchange packet from server"));
7ffdbc1a 5230 crStop(0);
32874aea 5231 }
51470298 5232 ssh->kex = NULL;
5233 ssh->hostkey = NULL;
5234 s->cscipher_tobe = NULL;
5235 s->sccipher_tobe = NULL;
5236 s->csmac_tobe = NULL;
5237 s->scmac_tobe = NULL;
5238 s->cscomp_tobe = NULL;
5239 s->sccomp_tobe = NULL;
4763c1c2 5240 s->warn_kex = s->warn_cscipher = s->warn_sccipher = FALSE;
5241
ff3187f6 5242 pktin->savedpos += 16; /* skip garbage cookie */
5243 ssh_pkt_getstring(pktin, &str, &len); /* key exchange algorithms */
4763c1c2 5244
5245 preferred = NULL;
83e7d008 5246 for (i = 0; i < s->n_preferred_kex; i++) {
34557659 5247 const struct ssh_kexes *k = s->preferred_kex[i];
83e7d008 5248 if (!k) {
4763c1c2 5249 s->warn_kex = TRUE;
5250 } else {
34557659 5251 for (j = 0; j < k->nkexes; j++) {
5252 if (!preferred) preferred = k->list[j]->name;
5253 if (in_commasep_string(k->list[j]->name, str, len)) {
5254 ssh->kex = k->list[j];
5255 break;
5256 }
5257 }
83e7d008 5258 }
4763c1c2 5259 if (ssh->kex)
51470298 5260 break;
32874aea 5261 }
83e7d008 5262 if (!ssh->kex) {
5263 bombout(("Couldn't agree a key exchange algorithm (available: %s)",
5264 str ? str : "(null)"));
5265 crStop(0);
5266 }
b59743d5 5267 /*
5268 * Note that the server's guess is considered wrong if it doesn't match
5269 * the first algorithm in our list, even if it's still the algorithm
5270 * we end up using.
5271 */
4763c1c2 5272 s->guessok = first_in_commasep_string(preferred, str, len);
ff3187f6 5273 ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */
51470298 5274 for (i = 0; i < lenof(hostkey_algs); i++) {
5275 if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
5276 ssh->hostkey = hostkey_algs[i];
5277 break;
5278 }
5279 }
3d9449a1 5280 s->guessok = s->guessok &&
b59743d5 5281 first_in_commasep_string(hostkey_algs[0]->name, str, len);
ff3187f6 5282 ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */
51470298 5283 for (i = 0; i < s->n_preferred_ciphers; i++) {
5284 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
5285 if (!c) {
4763c1c2 5286 s->warn_cscipher = TRUE;
51470298 5287 } else {
5288 for (j = 0; j < c->nciphers; j++) {
5289 if (in_commasep_string(c->list[j]->name, str, len)) {
5290 s->cscipher_tobe = c->list[j];
5291 break;
5292 }
ca20bfcf 5293 }
32874aea 5294 }
4763c1c2 5295 if (s->cscipher_tobe)
51470298 5296 break;
32874aea 5297 }
51470298 5298 if (!s->cscipher_tobe) {
6b5cf8b4 5299 bombout(("Couldn't agree a client-to-server cipher (available: %s)",
57356d63 5300 str ? str : "(null)"));
7ffdbc1a 5301 crStop(0);
ca20bfcf 5302 }
0ef8f407 5303
ff3187f6 5304 ssh_pkt_getstring(pktin, &str, &len); /* server->client cipher */
51470298 5305 for (i = 0; i < s->n_preferred_ciphers; i++) {
5306 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
5307 if (!c) {
4763c1c2 5308 s->warn_sccipher = TRUE;
51470298 5309 } else {
5310 for (j = 0; j < c->nciphers; j++) {
5311 if (in_commasep_string(c->list[j]->name, str, len)) {
5312 s->sccipher_tobe = c->list[j];
5313 break;
5314 }
ca20bfcf 5315 }
32874aea 5316 }
4763c1c2 5317 if (s->sccipher_tobe)
51470298 5318 break;
32874aea 5319 }
51470298 5320 if (!s->sccipher_tobe) {
6b5cf8b4 5321 bombout(("Couldn't agree a server-to-client cipher (available: %s)",
57356d63 5322 str ? str : "(null)"));
7ffdbc1a 5323 crStop(0);
ca20bfcf 5324 }
0ef8f407 5325
ff3187f6 5326 ssh_pkt_getstring(pktin, &str, &len); /* client->server mac */
51470298 5327 for (i = 0; i < s->nmacs; i++) {
5328 if (in_commasep_string(s->maclist[i]->name, str, len)) {
5329 s->csmac_tobe = s->maclist[i];
5330 break;
5331 }
32874aea 5332 }
ff3187f6 5333 ssh_pkt_getstring(pktin, &str, &len); /* server->client mac */
51470298 5334 for (i = 0; i < s->nmacs; i++) {
5335 if (in_commasep_string(s->maclist[i]->name, str, len)) {
5336 s->scmac_tobe = s->maclist[i];
5337 break;
5338 }
32874aea 5339 }
ff3187f6 5340 ssh_pkt_getstring(pktin, &str, &len); /* client->server compression */
51470298 5341 for (i = 0; i < lenof(compressions) + 1; i++) {
5342 const struct ssh_compress *c =
5343 i == 0 ? s->preferred_comp : compressions[i - 1];
5344 if (in_commasep_string(c->name, str, len)) {
5345 s->cscomp_tobe = c;
5346 break;
5347 }
32874aea 5348 }
ff3187f6 5349 ssh_pkt_getstring(pktin, &str, &len); /* server->client compression */
51470298 5350 for (i = 0; i < lenof(compressions) + 1; i++) {
5351 const struct ssh_compress *c =
5352 i == 0 ? s->preferred_comp : compressions[i - 1];
5353 if (in_commasep_string(c->name, str, len)) {
5354 s->sccomp_tobe = c;
5355 break;
5356 }
32874aea 5357 }
b59743d5 5358 ssh_pkt_getstring(pktin, &str, &len); /* client->server language */
5359 ssh_pkt_getstring(pktin, &str, &len); /* server->client language */
4763c1c2 5360 s->ignorepkt = ssh2_pkt_getbool(pktin) && !s->guessok;
5361
5362 if (s->warn_kex) {
5363 ssh_set_frozen(ssh, 1);
5364 s->dlgret = askalg(ssh->frontend, "key-exchange algorithm",
5365 ssh->kex->name,
5366 ssh_dialog_callback, ssh);
5367 if (s->dlgret < 0) {
5368 do {
5369 crReturn(0);
5370 if (pktin) {
5371 bombout(("Unexpected data from server while"
5372 " waiting for user response"));
5373 crStop(0);
5374 }
5375 } while (pktin || inlen > 0);
5376 s->dlgret = ssh->user_response;
5377 }
5378 ssh_set_frozen(ssh, 0);
5379 if (s->dlgret == 0) {
9e296bfa 5380 ssh_disconnect(ssh, "User aborted at kex warning", NULL,
5381 0, TRUE);
a5a6f839 5382 crStop(0);
4763c1c2 5383 }
5384 }
5385
5386 if (s->warn_cscipher) {
5387 ssh_set_frozen(ssh, 1);
5388 s->dlgret = askalg(ssh->frontend,
5389 "client-to-server cipher",
5390 s->cscipher_tobe->name,
5391 ssh_dialog_callback, ssh);
5392 if (s->dlgret < 0) {
5393 do {
5394 crReturn(0);
5395 if (pktin) {
5396 bombout(("Unexpected data from server while"
5397 " waiting for user response"));
5398 crStop(0);
5399 }
5400 } while (pktin || inlen > 0);
5401 s->dlgret = ssh->user_response;
5402 }
5403 ssh_set_frozen(ssh, 0);
5404 if (s->dlgret == 0) {
9e296bfa 5405 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
5406 0, TRUE);
a5a6f839 5407 crStop(0);
4763c1c2 5408 }
5409 }
5410
5411 if (s->warn_sccipher) {
5412 ssh_set_frozen(ssh, 1);
5413 s->dlgret = askalg(ssh->frontend,
5414 "server-to-client cipher",
5415 s->sccipher_tobe->name,
5416 ssh_dialog_callback, ssh);
5417 if (s->dlgret < 0) {
5418 do {
5419 crReturn(0);
5420 if (pktin) {
5421 bombout(("Unexpected data from server while"
5422 " waiting for user response"));
5423 crStop(0);
5424 }
5425 } while (pktin || inlen > 0);
5426 s->dlgret = ssh->user_response;
5427 }
5428 ssh_set_frozen(ssh, 0);
5429 if (s->dlgret == 0) {
9e296bfa 5430 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
5431 0, TRUE);
a5a6f839 5432 crStop(0);
4763c1c2 5433 }
5434 }
5435
b672f405 5436 ssh->exhash = ssh->kex->hash->init();
5437 hash_string(ssh->kex->hash, ssh->exhash, ssh->v_c, strlen(ssh->v_c));
5438 hash_string(ssh->kex->hash, ssh->exhash, ssh->v_s, strlen(ssh->v_s));
5439 hash_string(ssh->kex->hash, ssh->exhash,
5440 s->our_kexinit, s->our_kexinitlen);
3dc9a6a7 5441 sfree(s->our_kexinit);
5442 if (pktin->length > 5)
b672f405 5443 hash_string(ssh->kex->hash, ssh->exhash,
5444 pktin->data + 5, pktin->length - 5);
3dc9a6a7 5445
4763c1c2 5446 if (s->ignorepkt) /* first_kex_packet_follows */
b59743d5 5447 crWaitUntil(pktin); /* Ignore packet */
e5574168 5448 }
e5574168 5449
5450 /*
7bd5a860 5451 * Work out the number of bits of key we will need from the key
5452 * exchange. We start with the maximum key length of either
5453 * cipher...
5454 */
5455 {
32874aea 5456 int csbits, scbits;
7bd5a860 5457
51470298 5458 csbits = s->cscipher_tobe->keylen;
5459 scbits = s->sccipher_tobe->keylen;
5460 s->nbits = (csbits > scbits ? csbits : scbits);
7bd5a860 5461 }
b672f405 5462 /* The keys only have hlen-bit entropy, since they're based on
5463 * a hash. So cap the key size at hlen bits. */
5464 if (s->nbits > ssh->kex->hash->hlen * 8)
5465 s->nbits = ssh->kex->hash->hlen * 8;
7bd5a860 5466
5467 /*
a92dd380 5468 * If we're doing Diffie-Hellman group exchange, start by
5469 * requesting a group.
e5574168 5470 */
d1aaf71d 5471 if (!ssh->kex->pdata) {
32874aea 5472 logevent("Doing Diffie-Hellman group exchange");
51470298 5473 ssh->pkt_ctx |= SSH2_PKTCTX_DHGEX;
32874aea 5474 /*
5475 * Work out how big a DH group we will need to allow that
5476 * much data.
7bd5a860 5477 */
51470298 5478 s->pbits = 512 << ((s->nbits - 1) / 64);
ff3187f6 5479 s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
5480 ssh2_pkt_adduint32(s->pktout, s->pbits);
590f6a5f 5481 ssh2_pkt_send_noqueue(ssh, s->pktout);
32874aea 5482
ff3187f6 5483 crWaitUntil(pktin);
5484 if (pktin->type != SSH2_MSG_KEX_DH_GEX_GROUP) {
6b5cf8b4 5485 bombout(("expected key exchange group packet from server"));
7ffdbc1a 5486 crStop(0);
32874aea 5487 }
ff3187f6 5488 s->p = ssh2_pkt_getmp(pktin);
5489 s->g = ssh2_pkt_getmp(pktin);
5490 if (!s->p || !s->g) {
5491 bombout(("unable to read mp-ints from incoming group packet"));
5492 crStop(0);
5493 }
d1aaf71d 5494 ssh->kex_ctx = dh_setup_gex(s->p, s->g);
51470298 5495 s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
5496 s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
a92dd380 5497 } else {
d1aaf71d 5498 ssh->pkt_ctx |= SSH2_PKTCTX_DHGROUP;
5499 ssh->kex_ctx = dh_setup_group(ssh->kex);
51470298 5500 s->kex_init_value = SSH2_MSG_KEXDH_INIT;
5501 s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;
d1aaf71d 5502 logeventf(ssh, "Using Diffie-Hellman with standard group \"%s\"",
5503 ssh->kex->groupname);
8d5de777 5504 }
e5574168 5505
a92dd380 5506 logevent("Doing Diffie-Hellman key exchange");
e5574168 5507 /*
a92dd380 5508 * Now generate and send e for Diffie-Hellman.
e5574168 5509 */
755e0524 5510 set_busy_status(ssh->frontend, BUSY_CPU); /* this can take a while */
27cd7fc2 5511 s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);
ff3187f6 5512 s->pktout = ssh2_pkt_init(s->kex_init_value);
5513 ssh2_pkt_addmp(s->pktout, s->e);
590f6a5f 5514 ssh2_pkt_send_noqueue(ssh, s->pktout);
e5574168 5515
755e0524 5516 set_busy_status(ssh->frontend, BUSY_WAITING); /* wait for server */
ff3187f6 5517 crWaitUntil(pktin);
5518 if (pktin->type != s->kex_reply_value) {
6b5cf8b4 5519 bombout(("expected key exchange reply packet from server"));
7ffdbc1a 5520 crStop(0);
7cca0d81 5521 }
755e0524 5522 set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */
ff3187f6 5523 ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
5524 s->f = ssh2_pkt_getmp(pktin);
5525 if (!s->f) {
5526 bombout(("unable to parse key exchange reply packet"));
5527 crStop(0);
5528 }
5529 ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
e5574168 5530
27cd7fc2 5531 s->K = dh_find_K(ssh->kex_ctx, s->f);
e5574168 5532
755e0524 5533 /* We assume everything from now on will be quick, and it might
5534 * involve user interaction. */
5535 set_busy_status(ssh->frontend, BUSY_NOT);
5536
b672f405 5537 hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen);
34557659 5538 if (!ssh->kex->pdata) {
b672f405 5539 hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits);
5540 hash_mpint(ssh->kex->hash, ssh->exhash, s->p);
5541 hash_mpint(ssh->kex->hash, ssh->exhash, s->g);
a92dd380 5542 }
b672f405 5543 hash_mpint(ssh->kex->hash, ssh->exhash, s->e);
5544 hash_mpint(ssh->kex->hash, ssh->exhash, s->f);
5545 hash_mpint(ssh->kex->hash, ssh->exhash, s->K);
5546 assert(ssh->kex->hash->hlen <= sizeof(s->exchange_hash));
5547 ssh->kex->hash->final(ssh->exhash, s->exchange_hash);
e5574168 5548
27cd7fc2 5549 dh_cleanup(ssh->kex_ctx);
fabd1805 5550 ssh->kex_ctx = NULL;
3709bfe9 5551
7cca0d81 5552#if 0
765c4200 5553 debug(("Exchange hash is:\n"));
b672f405 5554 dmemdump(s->exchange_hash, ssh->kex->hash->hlen);
7cca0d81 5555#endif
5556
51470298 5557 s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen);
5558 if (!s->hkey ||
5559 !ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,
b672f405 5560 (char *)s->exchange_hash,
5561 ssh->kex->hash->hlen)) {
6b5cf8b4 5562 bombout(("Server's host key did not match the signature supplied"));
7ffdbc1a 5563 crStop(0);
8d5de777 5564 }
e5574168 5565
5566 /*
7cca0d81 5567 * Authenticate remote host: verify host key. (We've already
5568 * checked the signature of the exchange hash.)
e5574168 5569 */
51470298 5570 s->keystr = ssh->hostkey->fmtkey(s->hkey);
5571 s->fingerprint = ssh->hostkey->fingerprint(s->hkey);
3d9449a1 5572 ssh_set_frozen(ssh, 1);
5573 s->dlgret = verify_ssh_host_key(ssh->frontend,
5574 ssh->savedhost, ssh->savedport,
5575 ssh->hostkey->keytype, s->keystr,
5576 s->fingerprint,
5577 ssh_dialog_callback, ssh);
5578 if (s->dlgret < 0) {
5579 do {
5580 crReturn(0);
5581 if (pktin) {
5582 bombout(("Unexpected data from server while waiting"
5583 " for user host key response"));
5584 crStop(0);
5585 }
5586 } while (pktin || inlen > 0);
5587 s->dlgret = ssh->user_response;
5588 }
5589 ssh_set_frozen(ssh, 0);
5590 if (s->dlgret == 0) {
9e296bfa 5591 ssh_disconnect(ssh, "User aborted at host key verification", NULL,
5592 0, TRUE);
3d9449a1 5593 crStop(0);
5594 }
e13bba36 5595 if (!s->got_session_id) { /* don't bother logging this in rekeys */
5e0d7cb8 5596 logevent("Host key fingerprint is:");
51470298 5597 logevent(s->fingerprint);
5e0d7cb8 5598 }
51470298 5599 sfree(s->fingerprint);
5600 sfree(s->keystr);
5601 ssh->hostkey->freekey(s->hkey);
d39f364a 5602
5603 /*
9442dd57 5604 * The exchange hash from the very first key exchange is also
5605 * the session id, used in session key construction and
5606 * authentication.
5607 */
e13bba36 5608 if (!s->got_session_id) {
b672f405 5609 assert(sizeof(s->exchange_hash) <= sizeof(ssh->v2_session_id));
9442dd57 5610 memcpy(ssh->v2_session_id, s->exchange_hash,
5611 sizeof(s->exchange_hash));
b672f405 5612 ssh->v2_session_id_len = ssh->kex->hash->hlen;
6052bb76 5613 assert(ssh->v2_session_id_len <= sizeof(ssh->v2_session_id));
e13bba36 5614 s->got_session_id = TRUE;
5615 }
9442dd57 5616
5617 /*
7cca0d81 5618 * Send SSH2_MSG_NEWKEYS.
d39f364a 5619 */
ff3187f6 5620 s->pktout = ssh2_pkt_init(SSH2_MSG_NEWKEYS);
590f6a5f 5621 ssh2_pkt_send_noqueue(ssh, s->pktout);
9442dd57 5622 ssh->outgoing_data_size = 0; /* start counting from here */
5623
5624 /*
5625 * We've sent client NEWKEYS, so create and initialise
c64fe7d4 5626 * client-to-server session keys.
9442dd57 5627 */
5628 if (ssh->cs_cipher_ctx)
5629 ssh->cscipher->free_context(ssh->cs_cipher_ctx);
5630 ssh->cscipher = s->cscipher_tobe;
5631 ssh->cs_cipher_ctx = ssh->cscipher->make_context();
5632
5633 if (ssh->cs_mac_ctx)
5634 ssh->csmac->free_context(ssh->cs_mac_ctx);
5635 ssh->csmac = s->csmac_tobe;
5636 ssh->cs_mac_ctx = ssh->csmac->make_context();
5637
5638 if (ssh->cs_comp_ctx)
5639 ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
5640 ssh->cscomp = s->cscomp_tobe;
5641 ssh->cs_comp_ctx = ssh->cscomp->compress_init();
5642
5643 /*
5644 * Set IVs on client-to-server keys. Here we use the exchange
5645 * hash from the _first_ key exchange.
5646 */
5647 {
5648 unsigned char keyspace[40];
b672f405 5649 ssh2_mkkey(ssh,s->K,s->exchange_hash,'C',keyspace);
9442dd57 5650 ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);
b672f405 5651 ssh2_mkkey(ssh,s->K,s->exchange_hash,'A',keyspace);
9442dd57 5652 ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);
b672f405 5653 ssh2_mkkey(ssh,s->K,s->exchange_hash,'E',keyspace);
9442dd57 5654 ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
5655 }
5656
5657 logeventf(ssh, "Initialised %.200s client->server encryption",
5658 ssh->cscipher->text_name);
5659 logeventf(ssh, "Initialised %.200s client->server MAC algorithm",
5660 ssh->csmac->text_name);
5661 if (ssh->cscomp->text_name)
5662 logeventf(ssh, "Initialised %s compression",
5663 ssh->cscomp->text_name);
590f6a5f 5664
5665 /*
5666 * Now our end of the key exchange is complete, we can send all
5667 * our queued higher-layer packets.
5668 */
5669 ssh->queueing = FALSE;
5670 ssh2_pkt_queuesend(ssh);
d39f364a 5671
5672 /*
8406eaf9 5673 * Expect SSH2_MSG_NEWKEYS from server.
5674 */
ff3187f6 5675 crWaitUntil(pktin);
5676 if (pktin->type != SSH2_MSG_NEWKEYS) {
6b5cf8b4 5677 bombout(("expected new-keys packet from server"));
7ffdbc1a 5678 crStop(0);
8406eaf9 5679 }
9442dd57 5680 ssh->incoming_data_size = 0; /* start counting from here */
8406eaf9 5681
5682 /*
9442dd57 5683 * We've seen server NEWKEYS, so create and initialise
5684 * server-to-client session keys.
d39f364a 5685 */
371e569c 5686 if (ssh->sc_cipher_ctx)
5687 ssh->sccipher->free_context(ssh->sc_cipher_ctx);
51470298 5688 ssh->sccipher = s->sccipher_tobe;
371e569c 5689 ssh->sc_cipher_ctx = ssh->sccipher->make_context();
e0e1a00d 5690
e0e1a00d 5691 if (ssh->sc_mac_ctx)
5692 ssh->scmac->free_context(ssh->sc_mac_ctx);
51470298 5693 ssh->scmac = s->scmac_tobe;
e0e1a00d 5694 ssh->sc_mac_ctx = ssh->scmac->make_context();
5695
5366aed8 5696 if (ssh->sc_comp_ctx)
5697 ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);
51470298 5698 ssh->sccomp = s->sccomp_tobe;
5366aed8 5699 ssh->sc_comp_ctx = ssh->sccomp->decompress_init();
5700
d39f364a 5701 /*
9442dd57 5702 * Set IVs on server-to-client keys. Here we use the exchange
5703 * hash from the _first_ key exchange.
d39f364a 5704 */
51470298 5705 {
5706 unsigned char keyspace[40];
b672f405 5707 ssh2_mkkey(ssh,s->K,s->exchange_hash,'D',keyspace);
371e569c 5708 ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);
b672f405 5709 ssh2_mkkey(ssh,s->K,s->exchange_hash,'B',keyspace);
371e569c 5710 ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
b672f405 5711 ssh2_mkkey(ssh,s->K,s->exchange_hash,'F',keyspace);
e0e1a00d 5712 ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
51470298 5713 }
57356d63 5714 logeventf(ssh, "Initialised %.200s server->client encryption",
5715 ssh->sccipher->text_name);
6c135243 5716 logeventf(ssh, "Initialised %.200s server->client MAC algorithm",
5717 ssh->scmac->text_name);
57356d63 5718 if (ssh->sccomp->text_name)
5719 logeventf(ssh, "Initialised %s decompression",
5720 ssh->sccomp->text_name);
9442dd57 5721
5722 /*
5723 * Free key exchange data.
5724 */
679539d7 5725 freebn(s->f);
679539d7 5726 freebn(s->K);
34557659 5727 if (!ssh->kex->pdata) {
b3949e7e 5728 freebn(s->g);
5729 freebn(s->p);
5730 }
d39f364a 5731
033b4cef 5732 /*
e13bba36 5733 * Key exchange is over. Loop straight back round if we have a
5734 * deferred rekey reason.
5735 */
5736 if (ssh->deferred_rekey_reason) {
5737 logevent(ssh->deferred_rekey_reason);
5738 pktin = NULL;
5739 ssh->deferred_rekey_reason = NULL;
5740 goto begin_key_exchange;
5741 }
5742
5743 /*
5744 * Otherwise, schedule a timer for our next rekey.
9442dd57 5745 */
5746 ssh->kex_in_progress = FALSE;
e6c1536e 5747 ssh->last_rekey = GETTICKCOUNT();
d57f70af 5748 if (ssh->cfg.ssh_rekey_time != 0)
5749 ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
5750 ssh2_timer, ssh);
e13bba36 5751
9442dd57 5752 /*
0db56f73 5753 * If this is the first key exchange phase, we must pass the
5754 * SSH2_MSG_NEWKEYS packet to the next layer, not because it
5755 * wants to see it but because it will need time to initialise
5756 * itself before it sees an actual packet. In subsequent key
5757 * exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because
5758 * it would only confuse the layer above.
5759 */
e13bba36 5760 if (s->activated_authconn) {
0e3607ed 5761 crReturn(0);
0db56f73 5762 }
e13bba36 5763 s->activated_authconn = TRUE;
0db56f73 5764
5765 /*
7cca0d81 5766 * Now we're encrypting. Begin returning 1 to the protocol main
5767 * function so that other things can run on top of the
5768 * transport. If we ever see a KEXINIT, we must go back to the
5769 * start.
9442dd57 5770 *
5771 * We _also_ go back to the start if we see pktin==NULL and
5772 * inlen==-1, because this is a special signal meaning
5773 * `initiate client-driven rekey', and `in' contains a message
5774 * giving the reason for the rekey.
033b4cef 5775 */
9442dd57 5776 while (!((pktin && pktin->type == SSH2_MSG_KEXINIT) ||
5777 (!pktin && inlen == -1))) {
f382c87d 5778 wait_for_rekey:
32874aea 5779 crReturn(1);
e96adf72 5780 }
9442dd57 5781 if (pktin) {
5782 logevent("Server initiated key re-exchange");
5783 } else {
f382c87d 5784 /*
5785 * Special case: if the server bug is set that doesn't
5786 * allow rekeying, we give a different log message and
5787 * continue waiting. (If such a server _initiates_ a rekey,
5788 * we process it anyway!)
5789 */
5790 if ((ssh->remote_bugs & BUG_SSH2_REKEY)) {
5791 logeventf(ssh, "Server bug prevents key re-exchange (%s)",
5792 (char *)in);
5793 /* Reset the counters, so that at least this message doesn't
5794 * hit the event log _too_ often. */
5795 ssh->outgoing_data_size = 0;
5796 ssh->incoming_data_size = 0;
5797 if (ssh->cfg.ssh_rekey_time != 0) {
5798 ssh->next_rekey =
5799 schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
5800 ssh2_timer, ssh);
5801 }
5802 goto wait_for_rekey; /* this is utterly horrid */
5803 } else {
5804 logeventf(ssh, "Initiating key re-exchange (%s)", (char *)in);
f382c87d 5805 }
9442dd57 5806 }
7cca0d81 5807 goto begin_key_exchange;
e5574168 5808
5809 crFinish(1);
5810}
5811
7cca0d81 5812/*
2e85c969 5813 * Add data to an SSH-2 channel output buffer.
783415f8 5814 */
32874aea 5815static void ssh2_add_channel_data(struct ssh_channel *c, char *buf,
5816 int len)
5817{
5471d09a 5818 bufchain_add(&c->v.v2.outbuffer, buf, len);
783415f8 5819}
5820
5821/*
2e85c969 5822 * Attempt to send data on an SSH-2 channel.
783415f8 5823 */
5471d09a 5824static int ssh2_try_send(struct ssh_channel *c)
32874aea 5825{
51470298 5826 Ssh ssh = c->ssh;
ff3187f6 5827 struct Packet *pktout;
51470298 5828
5471d09a 5829 while (c->v.v2.remwindow > 0 && bufchain_size(&c->v.v2.outbuffer) > 0) {
5830 int len;
5831 void *data;
5832 bufchain_prefix(&c->v.v2.outbuffer, &data, &len);
5833 if ((unsigned)len > c->v.v2.remwindow)
5834 len = c->v.v2.remwindow;
5835 if ((unsigned)len > c->v.v2.remmaxpkt)
5836 len = c->v.v2.remmaxpkt;
ff3187f6 5837 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
5838 ssh2_pkt_adduint32(pktout, c->remoteid);
5839 dont_log_data(ssh, pktout, PKTLOG_OMIT);
5840 ssh2_pkt_addstring_start(pktout);
5841 ssh2_pkt_addstring_data(pktout, data, len);
5842 end_log_omission(ssh, pktout);
5843 ssh2_pkt_send(ssh, pktout);
5471d09a 5844 bufchain_consume(&c->v.v2.outbuffer, len);
5845 c->v.v2.remwindow -= len;
5846 }
5847
5848 /*
5849 * After having sent as much data as we can, return the amount
5850 * still buffered.
5851 */
5852 return bufchain_size(&c->v.v2.outbuffer);
5853}
5854
1bfc7e93 5855static void ssh2_try_send_and_unthrottle(struct ssh_channel *c)
5856{
5857 int bufsize;
5858 if (c->closes)
5859 return; /* don't send on closing channels */
5860 bufsize = ssh2_try_send(c);
5861 if (bufsize == 0) {
5862 switch (c->type) {
5863 case CHAN_MAINSESSION:
5864 /* stdin need not receive an unthrottle
5865 * notification since it will be polled */
5866 break;
5867 case CHAN_X11:
5868 x11_unthrottle(c->u.x11.s);
5869 break;
5870 case CHAN_AGENT:
5871 /* agent sockets are request/response and need no
5872 * buffer management */
5873 break;
5874 case CHAN_SOCKDATA:
5875 pfd_unthrottle(c->u.pfd.s);
5876 break;
5877 }
5878 }
5879}
5880
5471d09a 5881/*
2e85c969 5882 * Potentially enlarge the window on an SSH-2 channel.
5471d09a 5883 */
5884static void ssh2_set_window(struct ssh_channel *c, unsigned newwin)
5885{
51470298 5886 Ssh ssh = c->ssh;
5887
6b69f42e 5888 /*
5889 * Never send WINDOW_ADJUST for a channel that the remote side
5890 * already thinks it's closed; there's no point, since it won't
5891 * be sending any more data anyway.
5892 */
5893 if (c->closes != 0)
5894 return;
5895
d252310a 5896 /*
5897 * Only send a WINDOW_ADJUST if there's significantly more window
5898 * available than the other end thinks there is. This saves us
5899 * sending a WINDOW_ADJUST for every character in a shell session.
5900 *
5901 * "Significant" is arbitrarily defined as half the window size.
5902 */
5903 if (newwin > c->v.v2.locwindow * 2) {
ff3187f6 5904 struct Packet *pktout;
5905
5906 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
5907 ssh2_pkt_adduint32(pktout, c->remoteid);
5908 ssh2_pkt_adduint32(pktout, newwin - c->v.v2.locwindow);
5909 ssh2_pkt_send(ssh, pktout);
5471d09a 5910 c->v.v2.locwindow = newwin;
783415f8 5911 }
5912}
5913
51df0ab5 5914static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
b09eaa88 5915{
5916 unsigned i = ssh_pkt_getuint32(pktin);
5917 struct ssh_channel *c;
5918 c = find234(ssh->channels, &i, ssh_channelfind);
1bfc7e93 5919 if (c && !c->closes) {
b09eaa88 5920 c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
1bfc7e93 5921 ssh2_try_send_and_unthrottle(c);
5922 }
b09eaa88 5923}
5924
51df0ab5 5925static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
5926{
5927 char *data;
6d44acc9 5928 int length;
51df0ab5 5929 unsigned i = ssh_pkt_getuint32(pktin);
5930 struct ssh_channel *c;
5931 c = find234(ssh->channels, &i, ssh_channelfind);
5932 if (!c)
5933 return; /* nonexistent channel */
5934 if (pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA &&
5935 ssh_pkt_getuint32(pktin) != SSH2_EXTENDED_DATA_STDERR)
5936 return; /* extended but not stderr */
5937 ssh_pkt_getstring(pktin, &data, &length);
5938 if (data) {
5939 int bufsize = 0;
5940 c->v.v2.locwindow -= length;
5941 switch (c->type) {
5942 case CHAN_MAINSESSION:
5943 bufsize =
5944 from_backend(ssh->frontend, pktin->type ==
5945 SSH2_MSG_CHANNEL_EXTENDED_DATA,
5946 data, length);
5947 break;
5948 case CHAN_X11:
5949 bufsize = x11_send(c->u.x11.s, data, length);
5950 break;
5951 case CHAN_SOCKDATA:
5952 bufsize = pfd_send(c->u.pfd.s, data, length);
5953 break;
5954 case CHAN_AGENT:
5955 while (length > 0) {
5956 if (c->u.a.lensofar < 4) {
aa63ab7e 5957 unsigned int l = min(4 - c->u.a.lensofar, length);
51df0ab5 5958 memcpy(c->u.a.msglen + c->u.a.lensofar,
5959 data, l);
5960 data += l;
5961 length -= l;
5962 c->u.a.lensofar += l;
5963 }
5964 if (c->u.a.lensofar == 4) {
5965 c->u.a.totallen =
5966 4 + GET_32BIT(c->u.a.msglen);
5967 c->u.a.message = snewn(c->u.a.totallen,
5968 unsigned char);
5969 memcpy(c->u.a.message, c->u.a.msglen, 4);
5970 }
5971 if (c->u.a.lensofar >= 4 && length > 0) {
aa63ab7e 5972 unsigned int l =
51df0ab5 5973 min(c->u.a.totallen - c->u.a.lensofar,
5974 length);
5975 memcpy(c->u.a.message + c->u.a.lensofar,
5976 data, l);
5977 data += l;
5978 length -= l;
5979 c->u.a.lensofar += l;
5980 }
5981 if (c->u.a.lensofar == c->u.a.totallen) {
5982 void *reply;
5983 int replylen;
5984 if (agent_query(c->u.a.message,
5985 c->u.a.totallen,
5986 &reply, &replylen,
5987 ssh_agentf_callback, c))
5988 ssh_agentf_callback(c, reply, replylen);
5989 sfree(c->u.a.message);
5990 c->u.a.lensofar = 0;
5991 }
5992 }
5993 bufsize = 0;
5994 break;
5995 }
5996 /*
5997 * If we are not buffering too much data,
5998 * enlarge the window again at the remote side.
5999 */
6000 if (bufsize < OUR_V2_WINSIZE)
6001 ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
6002 }
6003}
6004
6005static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
6006{
6007 unsigned i = ssh_pkt_getuint32(pktin);
6008 struct ssh_channel *c;
6009
6010 c = find234(ssh->channels, &i, ssh_channelfind);
6011 if (!c)
6012 return; /* nonexistent channel */
6013
6014 if (c->type == CHAN_X11) {
6015 /*
6016 * Remote EOF on an X11 channel means we should
6017 * wrap up and close the channel ourselves.
6018 */
6019 x11_close(c->u.x11.s);
6020 sshfwd_close(c);
6021 } else if (c->type == CHAN_AGENT) {
6022 sshfwd_close(c);
6023 } else if (c->type == CHAN_SOCKDATA) {
6024 pfd_close(c->u.pfd.s);
6025 sshfwd_close(c);
6026 }
6027}
6028
6029static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin)
6030{
6031 unsigned i = ssh_pkt_getuint32(pktin);
6032 struct ssh_channel *c;
6033 struct Packet *pktout;
6034
6035 c = find234(ssh->channels, &i, ssh_channelfind);
64d6ff88 6036 if (!c || c->halfopen) {
51df0ab5 6037 bombout(("Received CHANNEL_CLOSE for %s channel %d\n",
6038 c ? "half-open" : "nonexistent", i));
6039 return;
6040 }
6041 /* Do pre-close processing on the channel. */
6042 switch (c->type) {
6043 case CHAN_MAINSESSION:
6044 ssh->mainchan = NULL;
6045 update_specials_menu(ssh->frontend);
6046 break;
6047 case CHAN_X11:
6048 if (c->u.x11.s != NULL)
6049 x11_close(c->u.x11.s);
6050 sshfwd_close(c);
6051 break;
6052 case CHAN_AGENT:
6053 sshfwd_close(c);
6054 break;
6055 case CHAN_SOCKDATA:
6056 if (c->u.pfd.s != NULL)
6057 pfd_close(c->u.pfd.s);
6058 sshfwd_close(c);
6059 break;
6060 }
6061 if (c->closes == 0) {
6062 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
6063 ssh2_pkt_adduint32(pktout, c->remoteid);
6064 ssh2_pkt_send(ssh, pktout);
6065 }
6066 del234(ssh->channels, c);
6067 bufchain_clear(&c->v.v2.outbuffer);
6068 sfree(c);
6069
6070 /*
6071 * See if that was the last channel left open.
6072 * (This is only our termination condition if we're
6073 * not running in -N mode.)
6074 */
6075 if (!ssh->cfg.ssh_no_shell && count234(ssh->channels) == 0) {
51df0ab5 6076 /*
6077 * We used to send SSH_MSG_DISCONNECT here,
6078 * because I'd believed that _every_ conforming
2e85c969 6079 * SSH-2 connection had to end with a disconnect
51df0ab5 6080 * being sent by at least one side; apparently
6081 * I was wrong and it's perfectly OK to
6082 * unceremoniously slam the connection shut
6083 * when you're done, and indeed OpenSSH feels
6084 * this is more polite than sending a
6085 * DISCONNECT. So now we don't.
6086 */
9e296bfa 6087 ssh_disconnect(ssh, "All channels closed", NULL, 0, TRUE);
51df0ab5 6088 }
6089}
6090
6091static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
6092{
6093 unsigned i = ssh_pkt_getuint32(pktin);
6094 struct ssh_channel *c;
6095 struct Packet *pktout;
6096
6097 c = find234(ssh->channels, &i, ssh_channelfind);
6098 if (!c)
6099 return; /* nonexistent channel */
6100 if (c->type != CHAN_SOCKDATA_DORMANT)
6101 return; /* dunno why they're confirming this */
6102 c->remoteid = ssh_pkt_getuint32(pktin);
64d6ff88 6103 c->halfopen = FALSE;
51df0ab5 6104 c->type = CHAN_SOCKDATA;
6105 c->v.v2.remwindow = ssh_pkt_getuint32(pktin);
6106 c->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
6107 if (c->u.pfd.s)
6108 pfd_confirm(c->u.pfd.s);
6109 if (c->closes) {
6110 /*
6111 * We have a pending close on this channel,
6112 * which we decided on before the server acked
6113 * the channel open. So now we know the
6114 * remoteid, we can close it again.
6115 */
6116 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
6117 ssh2_pkt_adduint32(pktout, c->remoteid);
6118 ssh2_pkt_send(ssh, pktout);
6119 }
6120}
6121
6122static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
6123{
6124 static const char *const reasons[] = {
6125 "<unknown reason code>",
6126 "Administratively prohibited",
6127 "Connect failed",
6128 "Unknown channel type",
6129 "Resource shortage",
6130 };
6131 unsigned i = ssh_pkt_getuint32(pktin);
6132 unsigned reason_code;
6133 char *reason_string;
6134 int reason_length;
51df0ab5 6135 struct ssh_channel *c;
6136 c = find234(ssh->channels, &i, ssh_channelfind);
6137 if (!c)
6138 return; /* nonexistent channel */
6139 if (c->type != CHAN_SOCKDATA_DORMANT)
6140 return; /* dunno why they're failing this */
6141
6142 reason_code = ssh_pkt_getuint32(pktin);
6143 if (reason_code >= lenof(reasons))
6144 reason_code = 0; /* ensure reasons[reason_code] in range */
6145 ssh_pkt_getstring(pktin, &reason_string, &reason_length);
fb983202 6146 logeventf(ssh, "Forwarded connection refused by server: %s [%.*s]",
6147 reasons[reason_code], reason_length, reason_string);
51df0ab5 6148
6149 pfd_close(c->u.pfd.s);
6150
6151 del234(ssh->channels, c);
6152 sfree(c);
6153}
6154
6155static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin)
6156{
6157 unsigned localid;
6158 char *type;
6159 int typelen, want_reply;
6160 int reply = SSH2_MSG_CHANNEL_FAILURE; /* default */
6161 struct ssh_channel *c;
6162 struct Packet *pktout;
6163
6164 localid = ssh_pkt_getuint32(pktin);
6165 ssh_pkt_getstring(pktin, &type, &typelen);
6166 want_reply = ssh2_pkt_getbool(pktin);
6167
6168 /*
6169 * First, check that the channel exists. Otherwise,
6170 * we can instantly disconnect with a rude message.
6171 */
6172 c = find234(ssh->channels, &localid, ssh_channelfind);
6173 if (!c) {
9e296bfa 6174 char *buf = dupprintf("Received channel request for nonexistent"
6175 " channel %d", localid);
6176 ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
6177 sfree(buf);
51df0ab5 6178 return;
6179 }
6180
6181 /*
6182 * Having got the channel number, we now look at
6183 * the request type string to see if it's something
6184 * we recognise.
6185 */
6186 if (c == ssh->mainchan) {
6187 /*
6188 * We recognise "exit-status" and "exit-signal" on
6189 * the primary channel.
6190 */
6191 if (typelen == 11 &&
6192 !memcmp(type, "exit-status", 11)) {
6193
6194 ssh->exitcode = ssh_pkt_getuint32(pktin);
6195 logeventf(ssh, "Server sent command exit status %d",
6196 ssh->exitcode);
6197 reply = SSH2_MSG_CHANNEL_SUCCESS;
6198
6199 } else if (typelen == 11 &&
6200 !memcmp(type, "exit-signal", 11)) {
6201
6202 int is_plausible = TRUE, is_int = FALSE;
6203 char *fmt_sig = "", *fmt_msg = "";
6204 char *msg;
6205 int msglen = 0, core = FALSE;
6206 /* ICK: older versions of OpenSSH (e.g. 3.4p1)
6207 * provide an `int' for the signal, despite its
6208 * having been a `string' in the drafts since at
6209 * least 2001. (Fixed in session.c 1.147.) Try to
6210 * infer which we can safely parse it as. */
6211 {
6212 unsigned char *p = pktin->body +
6213 pktin->savedpos;
6214 long len = pktin->length - pktin->savedpos;
6215 unsigned long num = GET_32BIT(p); /* what is it? */
6216 /* If it's 0, it hardly matters; assume string */
6217 if (num == 0) {
6218 is_int = FALSE;
6219 } else {
6220 int maybe_int = FALSE, maybe_str = FALSE;
6221#define CHECK_HYPOTHESIS(offset, result) \
6222 do { \
6223 long q = offset; \
6224 if (q >= 0 && q+4 <= len) { \
6225 q = q + 4 + GET_32BIT(p+q); \
6226 if (q >= 0 && q+4 <= len && \
c849ff23 6227 ((q = q + 4 + GET_32BIT(p+q))!= 0) && q == len) \
51df0ab5 6228 result = TRUE; \
6229 } \
6230 } while(0)
6231 CHECK_HYPOTHESIS(4+1, maybe_int);
6232 CHECK_HYPOTHESIS(4+num+1, maybe_str);
6233#undef CHECK_HYPOTHESIS
6234 if (maybe_int && !maybe_str)
6235 is_int = TRUE;
6236 else if (!maybe_int && maybe_str)
6237 is_int = FALSE;
6238 else
6239 /* Crikey. Either or neither. Panic. */
6240 is_plausible = FALSE;
6241 }
6242 }
6243 if (is_plausible) {
6244 if (is_int) {
6245 /* Old non-standard OpenSSH. */
6246 int signum = ssh_pkt_getuint32(pktin);
6247 fmt_sig = dupprintf(" %d", signum);
6248 } else {
6249 /* As per the drafts. */
6250 char *sig;
6251 int siglen;
6252 ssh_pkt_getstring(pktin, &sig, &siglen);
6253 /* Signal name isn't supposed to be blank, but
6254 * let's cope gracefully if it is. */
6255 if (siglen) {
6256 fmt_sig = dupprintf(" \"%.*s\"",
6257 siglen, sig);
6258 }
6259 }
6260 core = ssh2_pkt_getbool(pktin);
6261 ssh_pkt_getstring(pktin, &msg, &msglen);
6262 if (msglen) {
6263 fmt_msg = dupprintf(" (\"%.*s\")", msglen, msg);
6264 }
6265 /* ignore lang tag */
6266 } /* else don't attempt to parse */
6267 logeventf(ssh, "Server exited on signal%s%s%s",
6268 fmt_sig, core ? " (core dumped)" : "",
6269 fmt_msg);
6270 if (*fmt_sig) sfree(fmt_sig);
6271 if (*fmt_msg) sfree(fmt_msg);
6272 reply = SSH2_MSG_CHANNEL_SUCCESS;
6273
6274 }
6275 } else {
6276 /*
6277 * This is a channel request we don't know
6278 * about, so we now either ignore the request
6279 * or respond with CHANNEL_FAILURE, depending
6280 * on want_reply.
6281 */
6282 reply = SSH2_MSG_CHANNEL_FAILURE;
6283 }
6284 if (want_reply) {
6285 pktout = ssh2_pkt_init(reply);
6286 ssh2_pkt_adduint32(pktout, c->remoteid);
6287 ssh2_pkt_send(ssh, pktout);
6288 }
6289}
6290
6291static void ssh2_msg_global_request(Ssh ssh, struct Packet *pktin)
6292{
6293 char *type;
6294 int typelen, want_reply;
6295 struct Packet *pktout;
6296
6297 ssh_pkt_getstring(pktin, &type, &typelen);
6298 want_reply = ssh2_pkt_getbool(pktin);
6299
6300 /*
6301 * We currently don't support any global requests
6302 * at all, so we either ignore the request or
6303 * respond with REQUEST_FAILURE, depending on
6304 * want_reply.
6305 */
6306 if (want_reply) {
6307 pktout = ssh2_pkt_init(SSH2_MSG_REQUEST_FAILURE);
6308 ssh2_pkt_send(ssh, pktout);
6309 }
6310}
6311
6312static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
6313{
6314 char *type;
6315 int typelen;
6316 char *peeraddr;
6317 int peeraddrlen;
6318 int peerport;
6319 char *error = NULL;
6320 struct ssh_channel *c;
6321 unsigned remid, winsize, pktsize;
6322 struct Packet *pktout;
6323
6324 ssh_pkt_getstring(pktin, &type, &typelen);
6325 c = snew(struct ssh_channel);
6326 c->ssh = ssh;
6327
6328 remid = ssh_pkt_getuint32(pktin);
6329 winsize = ssh_pkt_getuint32(pktin);
6330 pktsize = ssh_pkt_getuint32(pktin);
6331
6332 if (typelen == 3 && !memcmp(type, "x11", 3)) {
6333 char *addrstr;
6334
6335 ssh_pkt_getstring(pktin, &peeraddr, &peeraddrlen);
6336 addrstr = snewn(peeraddrlen+1, char);
6337 memcpy(addrstr, peeraddr, peeraddrlen);
6338 addrstr[peeraddrlen] = '\0';
6339 peerport = ssh_pkt_getuint32(pktin);
6340
6341 logeventf(ssh, "Received X11 connect request from %s:%d",
6342 addrstr, peerport);
6343
6344 if (!ssh->X11_fwd_enabled)
6345 error = "X11 forwarding is not enabled";
6346 else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
6347 ssh->x11auth, addrstr, peerport,
6348 &ssh->cfg) != NULL) {
6349 error = "Unable to open an X11 connection";
6350 } else {
6351 logevent("Opening X11 forward connection succeeded");
6352 c->type = CHAN_X11;
6353 }
6354
6355 sfree(addrstr);
6356 } else if (typelen == 15 &&
6357 !memcmp(type, "forwarded-tcpip", 15)) {
6358 struct ssh_rportfwd pf, *realpf;
6359 char *dummy;
6360 int dummylen;
6361 ssh_pkt_getstring(pktin, &dummy, &dummylen);/* skip address */
6362 pf.sport = ssh_pkt_getuint32(pktin);
6363 ssh_pkt_getstring(pktin, &peeraddr, &peeraddrlen);
6364 peerport = ssh_pkt_getuint32(pktin);
6365 realpf = find234(ssh->rportfwds, &pf, NULL);
6366 logeventf(ssh, "Received remote port %d open request "
6367 "from %s:%d", pf.sport, peeraddr, peerport);
6368 if (realpf == NULL) {
6369 error = "Remote port is not recognised";
6370 } else {
6371 const char *e = pfd_newconnect(&c->u.pfd.s,
6372 realpf->dhost,
6373 realpf->dport, c,
05581745 6374 &ssh->cfg,
6375 realpf->pfrec->addressfamily);
51df0ab5 6376 logeventf(ssh, "Attempting to forward remote port to "
6377 "%s:%d", realpf->dhost, realpf->dport);
6378 if (e != NULL) {
6379 logeventf(ssh, "Port open failed: %s", e);
6380 error = "Port open failed";
6381 } else {
6382 logevent("Forwarded port opened successfully");
6383 c->type = CHAN_SOCKDATA;
6384 }
6385 }
6386 } else if (typelen == 22 &&
c49cf994 6387 !memcmp(type, "auth-agent@openssh.com", 22)) {
51df0ab5 6388 if (!ssh->agentfwd_enabled)
6389 error = "Agent forwarding is not enabled";
6390 else {
6391 c->type = CHAN_AGENT; /* identify channel type */
6392 c->u.a.lensofar = 0;
6393 }
6394 } else {
6395 error = "Unsupported channel type requested";
6396 }
6397
6398 c->remoteid = remid;
64d6ff88 6399 c->halfopen = FALSE;
51df0ab5 6400 if (error) {
6401 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_FAILURE);
6402 ssh2_pkt_adduint32(pktout, c->remoteid);
6403 ssh2_pkt_adduint32(pktout, SSH2_OPEN_CONNECT_FAILED);
6404 ssh2_pkt_addstring(pktout, error);
6405 ssh2_pkt_addstring(pktout, "en"); /* language tag */
6406 ssh2_pkt_send(ssh, pktout);
6407 logeventf(ssh, "Rejected channel open: %s", error);
6408 sfree(c);
6409 } else {
6410 c->localid = alloc_channel_id(ssh);
6411 c->closes = 0;
6412 c->v.v2.locwindow = OUR_V2_WINSIZE;
6413 c->v.v2.remwindow = winsize;
6414 c->v.v2.remmaxpkt = pktsize;
6415 bufchain_init(&c->v.v2.outbuffer);
6416 add234(ssh->channels, c);
6417 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
6418 ssh2_pkt_adduint32(pktout, c->remoteid);
6419 ssh2_pkt_adduint32(pktout, c->localid);
6420 ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);
954d5c5a 6421 ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
51df0ab5 6422 ssh2_pkt_send(ssh, pktout);
6423 }
6424}
6425
6bbce591 6426/*
6427 * Buffer banner messages for later display at some convenient point.
6428 */
6429static void ssh2_msg_userauth_banner(Ssh ssh, struct Packet *pktin)
6430{
6431 /* Arbitrary limit to prevent unbounded inflation of buffer */
6432 if (bufchain_size(&ssh->banner) <= 131072) {
6433 char *banner = NULL;
6434 int size = 0;
6435 ssh_pkt_getstring(pktin, &banner, &size);
6436 if (banner)
6437 bufchain_add(&ssh->banner, banner, size);
6438 }
6439}
6440
c6ccd5c2 6441/* Helper function to deal with sending tty modes for "pty-req" */
6442static void ssh2_send_ttymode(void *data, char *mode, char *val)
6443{
6444 struct Packet *pktout = (struct Packet *)data;
6445 int i = 0;
6446 unsigned int arg = 0;
6447 while (strcmp(mode, ssh_ttymodes[i].mode) != 0) i++;
6448 if (i == lenof(ssh_ttymodes)) return;
6449 switch (ssh_ttymodes[i].type) {
6450 case TTY_OP_CHAR:
6451 arg = ssh_tty_parse_specchar(val);
6452 break;
6453 case TTY_OP_BOOL:
6454 arg = ssh_tty_parse_boolean(val);
6455 break;
6456 }
6457 ssh2_pkt_addbyte(pktout, ssh_ttymodes[i].opcode);
6458 ssh2_pkt_adduint32(pktout, arg);
6459}
6460
783415f8 6461/*
2e85c969 6462 * Handle the SSH-2 userauth and connection layers.
7cca0d81 6463 */
ff3187f6 6464static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
6465 struct Packet *pktin)
7cca0d81 6466{
51470298 6467 struct do_ssh2_authconn_state {
6468 enum {
6469 AUTH_INVALID, AUTH_PUBLICKEY_AGENT, AUTH_PUBLICKEY_FILE,
6470 AUTH_PASSWORD,
6471 AUTH_KEYBOARD_INTERACTIVE
6472 } method;
6473 enum {
6474 AUTH_TYPE_NONE,
6475 AUTH_TYPE_PUBLICKEY,
6476 AUTH_TYPE_PUBLICKEY_OFFER_LOUD,
6477 AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
6478 AUTH_TYPE_PASSWORD,
6479 AUTH_TYPE_KEYBOARD_INTERACTIVE,
6480 AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET
6481 } type;
a1a1fae4 6482 int done_service_req;
51470298 6483 int gotit, need_pw, can_pubkey, can_passwd, can_keyb_inter;
6ac3a551 6484 int tried_pubkey_config, tried_agent;
6485 int kbd_inter_running, kbd_inter_refused;
51470298 6486 int we_are_in;
6487 int num_prompts, curr_prompt, echo;
6488 char username[100];
6489 int got_username;
85fdbe25 6490 char pwprompt[512];
51470298 6491 char password[100];
6492 void *publickey_blob;
6493 int publickey_bloblen;
6494 unsigned char request[5], *response, *p;
6495 int responselen;
6496 int keyi, nkeys;
6497 int authed;
6498 char *pkblob, *alg, *commentp;
6499 int pklen, alglen, commentlen;
6500 int siglen, retlen, len;
6501 char *q, *agentreq, *ret;
6502 int try_send;
73feed4f 6503 int num_env, env_left, env_ok;
ff3187f6 6504 struct Packet *pktout;
51470298 6505 };
6506 crState(do_ssh2_authconn_state);
6507
6508 crBegin(ssh->do_ssh2_authconn_crstate);
e5574168 6509
a1a1fae4 6510 s->done_service_req = FALSE;
6511 s->we_are_in = FALSE;
6512 if (!ssh->cfg.ssh_no_userauth) {
6513 /*
6514 * Request userauth protocol, and await a response to it.
6515 */
6516 s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
6517 ssh2_pkt_addstring(s->pktout, "ssh-userauth");
6518 ssh2_pkt_send(ssh, s->pktout);
6519 crWaitUntilV(pktin);
6520 if (pktin->type == SSH2_MSG_SERVICE_ACCEPT)
6521 s->done_service_req = TRUE;
6522 }
6523 if (!s->done_service_req) {
6524 /*
6525 * Request connection protocol directly, without authentication.
6526 */
6527 s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
6528 ssh2_pkt_addstring(s->pktout, "ssh-connection");
6529 ssh2_pkt_send(ssh, s->pktout);
6530 crWaitUntilV(pktin);
6531 if (pktin->type == SSH2_MSG_SERVICE_ACCEPT) {
6532 s->we_are_in = TRUE; /* no auth required */
6533 } else {
6534 bombout(("Server refused service request"));
6535 crStopV;
6536 }
8d5de777 6537 }
7cca0d81 6538
6539 /*
1408a877 6540 * We repeat this whole loop, including the username prompt,
6541 * until we manage a successful authentication. If the user
51470298 6542 * types the wrong _password_, they can be sent back to the
6543 * beginning to try another username, if this is configured on.
6544 * (If they specify a username in the config, they are never
6545 * asked, even if they do give a wrong password.)
1408a877 6546 *
6547 * I think this best serves the needs of
6548 *
6549 * - the people who have no configuration, no keys, and just
6550 * want to try repeated (username,password) pairs until they
6551 * type both correctly
6552 *
6553 * - people who have keys and configuration but occasionally
6554 * need to fall back to passwords
6555 *
6556 * - people with a key held in Pageant, who might not have
6557 * logged in to a particular machine before; so they want to
6558 * type a username, and then _either_ their key will be
6559 * accepted, _or_ they will type a password. If they mistype
6560 * the username they will want to be able to get back and
6561 * retype it!
7cca0d81 6562 */
51470298 6563 s->username[0] = '\0';
6564 s->got_username = FALSE;
6bbce591 6565 bufchain_init(&ssh->banner);
6566 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] =
6567 ssh2_msg_userauth_banner;
a1a1fae4 6568 while (!s->we_are_in) {
1408a877 6569 /*
6570 * Get a username.
6571 */
86916870 6572 if (s->got_username && !ssh->cfg.change_username) {
5bb641e1 6573 /*
6574 * We got a username last time round this loop, and
6575 * with change_username turned off we don't try to get
6576 * it again.
6577 */
aa09f7d0 6578 } else if (!*ssh->cfg.username) {
c0a81592 6579 if (ssh_get_line && !ssh_getline_pw_only) {
32874aea 6580 if (!ssh_get_line("login as: ",
51470298 6581 s->username, sizeof(s->username), FALSE)) {
32874aea 6582 /*
6583 * get_line failed to get a username.
6584 * Terminate.
6585 */
9e296bfa 6586 ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
7ffdbc1a 6587 crStopV;
32874aea 6588 }
6589 } else {
51470298 6590 int ret; /* need not be saved across crReturn */
6591 c_write_str(ssh, "login as: ");
6592 ssh->send_ok = 1;
6593 setup_userpass_input(ssh, s->username, sizeof(s->username), 1);
0405e71f 6594 do {
ff3187f6 6595 crWaitUntilV(!pktin);
51470298 6596 ret = process_userpass_input(ssh, in, inlen);
0405e71f 6597 } while (ret == 0);
6598 if (ret < 0)
6599 cleanup_exit(0);
4ca0c9d1 6600 c_write_str(ssh, "\r\n");
32874aea 6601 }
51470298 6602 s->username[strcspn(s->username, "\n\r")] = '\0';
7cca0d81 6603 } else {
57356d63 6604 char *stuff;
86916870 6605 strncpy(s->username, ssh->cfg.username, sizeof(s->username));
51470298 6606 s->username[sizeof(s->username)-1] = '\0';
65a22376 6607 if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
57356d63 6608 stuff = dupprintf("Using username \"%s\".\r\n", s->username);
51470298 6609 c_write_str(ssh, stuff);
57356d63 6610 sfree(stuff);
7cca0d81 6611 }
6612 }
51470298 6613 s->got_username = TRUE;
7cca0d81 6614
65a22376 6615 /*
1408a877 6616 * Send an authentication request using method "none": (a)
6617 * just in case it succeeds, and (b) so that we know what
6618 * authentication methods we can usefully try next.
65a22376 6619 */
51470298 6620 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
6621
ff3187f6 6622 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
6623 ssh2_pkt_addstring(s->pktout, s->username);
6624 ssh2_pkt_addstring(s->pktout, "ssh-connection");/* service requested */
6625 ssh2_pkt_addstring(s->pktout, "none"); /* method */
6626 ssh2_pkt_send(ssh, s->pktout);
51470298 6627 s->type = AUTH_TYPE_NONE;
6628 s->gotit = FALSE;
6629 s->we_are_in = FALSE;
6630
6631 s->tried_pubkey_config = FALSE;
6632 s->tried_agent = FALSE;
51470298 6633 s->kbd_inter_running = FALSE;
6ac3a551 6634 s->kbd_inter_refused = FALSE;
86916870 6635 /* Load the pub half of ssh->cfg.keyfile so we notice if it's in Pageant */
9a30e26b 6636 if (!filename_is_null(ssh->cfg.keyfile)) {
231ee168 6637 int keytype;
6c6d9ed9 6638 logeventf(ssh, "Reading private key file \"%.150s\"",
6639 filename_to_str(&ssh->cfg.keyfile));
9a30e26b 6640 keytype = key_type(&ssh->cfg.keyfile);
51470298 6641 if (keytype == SSH_KEYTYPE_SSH2) {
6642 s->publickey_blob =
9a30e26b 6643 ssh2_userkey_loadpub(&ssh->cfg.keyfile, NULL,
06897bd7 6644 &s->publickey_bloblen, NULL, NULL);
51470298 6645 } else {
57356d63 6646 char *msgbuf;
c2ad7d0d 6647 logeventf(ssh, "Unable to use this key file (%s)",
a8327734 6648 key_type_to_str(keytype));
57356d63 6649 msgbuf = dupprintf("Unable to use key file \"%.150s\""
6c6d9ed9 6650 " (%s)\r\n",
6651 filename_to_str(&ssh->cfg.keyfile),
57356d63 6652 key_type_to_str(keytype));
51470298 6653 c_write_str(ssh, msgbuf);
57356d63 6654 sfree(msgbuf);
51470298 6655 s->publickey_blob = NULL;
231ee168 6656 }
396778f1 6657 } else
51470298 6658 s->publickey_blob = NULL;
65a22376 6659
1408a877 6660 while (1) {
6661 /*
6662 * Wait for the result of the last authentication request.
6663 */
51470298 6664 if (!s->gotit)
ff3187f6 6665 crWaitUntilV(pktin);
6bbce591 6666 /*
6667 * Now is a convenient point to spew any banner material
6668 * that we've accumulated. (This should ensure that when
6669 * we exit the auth loop, we haven't any left to deal
6670 * with.)
6671 */
6672 {
6673 int size = bufchain_size(&ssh->banner);
32874aea 6674 /*
6675 * Don't show the banner if we're operating in
6676 * non-verbose non-interactive mode. (It's probably
6677 * a script, which means nobody will read the
6678 * banner _anyway_, and moreover the printing of
6679 * the banner will screw up processing on the
6680 * output of (say) plink.)
6681 */
6bbce591 6682 if (size && (flags & (FLAG_VERBOSE | FLAG_INTERACTIVE))) {
6683 char *banner = snewn(size, char);
6684 bufchain_fetch(&ssh->banner, banner, size);
6685 c_write_untrusted(ssh, banner, size);
6686 sfree(banner);
32874aea 6687 }
6bbce591 6688 bufchain_clear(&ssh->banner);
1408a877 6689 }
ff3187f6 6690 if (pktin->type == SSH2_MSG_USERAUTH_SUCCESS) {
1408a877 6691 logevent("Access granted");
51470298 6692 s->we_are_in = TRUE;
1408a877 6693 break;
6694 }
65a22376 6695
51470298 6696 if (s->kbd_inter_running &&
ff3187f6 6697 pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) {
b3186d64 6698 /*
45068b27 6699 * This is either a further set-of-prompts packet
6700 * in keyboard-interactive authentication, or it's
6701 * the same one and we came back here with `gotit'
6702 * set. In the former case, we must reset the
6703 * curr_prompt variable.
b3186d64 6704 */
51470298 6705 if (!s->gotit)
6706 s->curr_prompt = 0;
4c6e53e3 6707 } else if (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) {
6708 /* FIXME: perhaps we should support this? */
6709 bombout(("PASSWD_CHANGEREQ not yet supported"));
6710 crStopV;
ff3187f6 6711 } else if (pktin->type != SSH2_MSG_USERAUTH_FAILURE) {
6b5cf8b4 6712 bombout(("Strange packet received during authentication: type %d",
ff3187f6 6713 pktin->type));
7ffdbc1a 6714 crStopV;
65a22376 6715 }
6716
51470298 6717 s->gotit = FALSE;
65a22376 6718
1408a877 6719 /*
6720 * OK, we're now sitting on a USERAUTH_FAILURE message, so
6721 * we can look at the string in it and know what we can
6722 * helpfully try next.
6723 */
ff3187f6 6724 if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
1408a877 6725 char *methods;
6726 int methlen;
ff3187f6 6727 ssh_pkt_getstring(pktin, &methods, &methlen);
51470298 6728 s->kbd_inter_running = FALSE;
ff3187f6 6729 if (!ssh2_pkt_getbool(pktin)) {
1408a877 6730 /*
6731 * We have received an unequivocal Access
6732 * Denied. This can translate to a variety of
6733 * messages:
6734 *
6735 * - if we'd just tried "none" authentication,
6736 * it's not worth printing anything at all
6737 *
6738 * - if we'd just tried a public key _offer_,
6739 * the message should be "Server refused our
6740 * key" (or no message at all if the key
6741 * came from Pageant)
6742 *
6743 * - if we'd just tried anything else, the
6744 * message really should be "Access denied".
6745 *
6746 * Additionally, if we'd just tried password
6747 * authentication, we should break out of this
6748 * whole loop so as to go back to the username
91f57d1f 6749 * prompt (iff we're configured to allow
6750 * username change attempts).
1408a877 6751 */
51470298 6752 if (s->type == AUTH_TYPE_NONE) {
1408a877 6753 /* do nothing */
51470298 6754 } else if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD ||
6755 s->type == AUTH_TYPE_PUBLICKEY_OFFER_QUIET) {
6756 if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD)
6757 c_write_str(ssh, "Server refused our key\r\n");
1408a877 6758 logevent("Server refused public key");
51470298 6759 } else if (s->type==AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET) {
4bdf7c46 6760 /* server declined keyboard-interactive; ignore */
1408a877 6761 } else {
51470298 6762 c_write_str(ssh, "Access denied\r\n");
1408a877 6763 logevent("Access denied");
91f57d1f 6764 if (s->type == AUTH_TYPE_PASSWORD &&
6765 ssh->cfg.change_username) {
6c9dce7c 6766 /* XXX perhaps we should allow
6767 * keyboard-interactive to do this too? */
51470298 6768 s->we_are_in = FALSE;
1408a877 6769 break;
6770 }
6771 }
6772 } else {
51470298 6773 c_write_str(ssh, "Further authentication required\r\n");
1408a877 6774 logevent("Further authentication required");
6775 }
65a22376 6776
51470298 6777 s->can_pubkey =
32874aea 6778 in_commasep_string("publickey", methods, methlen);
51470298 6779 s->can_passwd =
32874aea 6780 in_commasep_string("password", methods, methlen);
86916870 6781 s->can_keyb_inter = ssh->cfg.try_ki_auth &&
761187b6 6782 in_commasep_string("keyboard-interactive", methods, methlen);
1408a877 6783 }
65a22376 6784
51470298 6785 s->method = 0;
6786 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
954a9540 6787 s->need_pw = FALSE;
65a22376 6788
0405e71f 6789 /*
6790 * Most password/passphrase prompts will be
6791 * non-echoing, so we set this to 0 by default.
6792 * Exception is that some keyboard-interactive prompts
6793 * can be echoing, in which case we'll set this to 1.
6794 */
51470298 6795 s->echo = 0;
0405e71f 6796
51470298 6797 if (!s->method && s->can_pubkey &&
6798 agent_exists() && !s->tried_agent) {
1983e559 6799 /*
6800 * Attempt public-key authentication using Pageant.
6801 */
1983e559 6802 void *r;
51470298 6803 s->authed = FALSE;
1983e559 6804
51470298 6805 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
6806 ssh->pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
00db133f 6807
51470298 6808 s->tried_agent = TRUE;
1983e559 6809
6810 logevent("Pageant is running. Requesting keys.");
6811
6812 /* Request the keys held by the agent. */
51470298 6813 PUT_32BIT(s->request, 1);
6814 s->request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
839f10db 6815 if (!agent_query(s->request, 5, &r, &s->responselen,
6816 ssh_agent_callback, ssh)) {
6817 do {
6818 crReturnV;
ff3187f6 6819 if (pktin) {
839f10db 6820 bombout(("Unexpected data from server while"
6821 " waiting for agent response"));
6822 crStopV;
6823 }
ff3187f6 6824 } while (pktin || inlen > 0);
839f10db 6825 r = ssh->agent_response;
6826 s->responselen = ssh->agent_response_len;
6827 }
51470298 6828 s->response = (unsigned char *) r;
6829 if (s->response && s->responselen >= 5 &&
6830 s->response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
6831 s->p = s->response + 5;
6832 s->nkeys = GET_32BIT(s->p);
6833 s->p += 4;
2e85c969 6834 logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
51470298 6835 for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
2d466ffd 6836 void *vret;
1983e559 6837
fb983202 6838 logeventf(ssh, "Trying Pageant key #%d", s->keyi);
51470298 6839 s->pklen = GET_32BIT(s->p);
6840 s->p += 4;
6841 if (s->publickey_blob &&
6842 s->pklen == s->publickey_bloblen &&
6843 !memcmp(s->p, s->publickey_blob,
6844 s->publickey_bloblen)) {
396778f1 6845 logevent("This key matches configured key file");
51470298 6846 s->tried_pubkey_config = 1;
396778f1 6847 }
d8baa528 6848 s->pkblob = (char *)s->p;
51470298 6849 s->p += s->pklen;
6850 s->alglen = GET_32BIT(s->pkblob);
6851 s->alg = s->pkblob + 4;
6852 s->commentlen = GET_32BIT(s->p);
6853 s->p += 4;
d8baa528 6854 s->commentp = (char *)s->p;
51470298 6855 s->p += s->commentlen;
ff3187f6 6856 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
6857 ssh2_pkt_addstring(s->pktout, s->username);
6858 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
6859 ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
6860 ssh2_pkt_addbool(s->pktout, FALSE); /* no signature included */
6861 ssh2_pkt_addstring_start(s->pktout);
6862 ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
6863 ssh2_pkt_addstring_start(s->pktout);
6864 ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
6865 ssh2_pkt_send(ssh, s->pktout);
6866
6867 crWaitUntilV(pktin);
6868 if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
1983e559 6869 logevent("Key refused");
6870 continue;
6871 }
6872
32874aea 6873 if (flags & FLAG_VERBOSE) {
51470298 6874 c_write_str(ssh, "Authenticating with "
6875 "public key \"");
6876 c_write(ssh, s->commentp, s->commentlen);
6877 c_write_str(ssh, "\" from agent\r\n");
32874aea 6878 }
1983e559 6879
6880 /*
6881 * Server is willing to accept the key.
6882 * Construct a SIGN_REQUEST.
6883 */
ff3187f6 6884 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
6885 ssh2_pkt_addstring(s->pktout, s->username);
6886 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
6887 ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
6888 ssh2_pkt_addbool(s->pktout, TRUE);
6889 ssh2_pkt_addstring_start(s->pktout);
6890 ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
6891 ssh2_pkt_addstring_start(s->pktout);
6892 ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
6893
b672f405 6894 s->siglen = s->pktout->length - 5 + 4 +
6895 ssh->v2_session_id_len;
dda87a28 6896 if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
6897 s->siglen -= 4;
51470298 6898 s->len = 1; /* message type */
6899 s->len += 4 + s->pklen; /* key blob */
6900 s->len += 4 + s->siglen; /* data to sign */
6901 s->len += 4; /* flags */
3d88e64d 6902 s->agentreq = snewn(4 + s->len, char);
51470298 6903 PUT_32BIT(s->agentreq, s->len);
6904 s->q = s->agentreq + 4;
6905 *s->q++ = SSH2_AGENTC_SIGN_REQUEST;
6906 PUT_32BIT(s->q, s->pklen);
6907 s->q += 4;
6908 memcpy(s->q, s->pkblob, s->pklen);
6909 s->q += s->pklen;
6910 PUT_32BIT(s->q, s->siglen);
6911 s->q += 4;
1983e559 6912 /* Now the data to be signed... */
dda87a28 6913 if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
b672f405 6914 PUT_32BIT(s->q, ssh->v2_session_id_len);
dda87a28 6915 s->q += 4;
6916 }
b672f405 6917 memcpy(s->q, ssh->v2_session_id,
6918 ssh->v2_session_id_len);
6919 s->q += ssh->v2_session_id_len;
ff3187f6 6920 memcpy(s->q, s->pktout->data + 5,
6921 s->pktout->length - 5);
6922 s->q += s->pktout->length - 5;
1983e559 6923 /* And finally the (zero) flags word. */
51470298 6924 PUT_32BIT(s->q, 0);
839f10db 6925 if (!agent_query(s->agentreq, s->len + 4,
6926 &vret, &s->retlen,
6927 ssh_agent_callback, ssh)) {
6928 do {
6929 crReturnV;
ff3187f6 6930 if (pktin) {
839f10db 6931 bombout(("Unexpected data from server"
6932 " while waiting for agent"
6933 " response"));
6934 crStopV;
6935 }
ff3187f6 6936 } while (pktin || inlen > 0);
839f10db 6937 vret = ssh->agent_response;
6938 s->retlen = ssh->agent_response_len;
6939 }
51470298 6940 s->ret = vret;
6941 sfree(s->agentreq);
6942 if (s->ret) {
6943 if (s->ret[4] == SSH2_AGENT_SIGN_RESPONSE) {
1983e559 6944 logevent("Sending Pageant's response");
ff3187f6 6945 ssh2_add_sigblob(ssh, s->pktout,
6946 s->pkblob, s->pklen,
51470298 6947 s->ret + 9,
6948 GET_32BIT(s->ret + 5));
ff3187f6 6949 ssh2_pkt_send(ssh, s->pktout);
51470298 6950 s->authed = TRUE;
1983e559 6951 break;
6952 } else {
32874aea 6953 logevent
6954 ("Pageant failed to answer challenge");
51470298 6955 sfree(s->ret);
1983e559 6956 }
6957 }
6958 }
51470298 6959 if (s->authed)
1983e559 6960 continue;
6961 }
29b1d0b3 6962 sfree(s->response);
1983e559 6963 }
6964
51470298 6965 if (!s->method && s->can_pubkey && s->publickey_blob
6966 && !s->tried_pubkey_config) {
1408a877 6967 unsigned char *pub_blob;
6968 char *algorithm, *comment;
6969 int pub_blob_len;
65a22376 6970
51470298 6971 s->tried_pubkey_config = TRUE;
65a22376 6972
51470298 6973 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
6974 ssh->pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
00db133f 6975
65a22376 6976 /*
1408a877 6977 * Try the public key supplied in the configuration.
6978 *
6979 * First, offer the public blob to see if the server is
6980 * willing to accept it.
65a22376 6981 */
d8baa528 6982 pub_blob =
9a30e26b 6983 (unsigned char *)ssh2_userkey_loadpub(&ssh->cfg.keyfile,
d8baa528 6984 &algorithm,
222d54dc 6985 &pub_blob_len,
06897bd7 6986 NULL, NULL);
1408a877 6987 if (pub_blob) {
ff3187f6 6988 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
6989 ssh2_pkt_addstring(s->pktout, s->username);
6990 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
6991 ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
6992 ssh2_pkt_addbool(s->pktout, FALSE); /* no signature included */
6993 ssh2_pkt_addstring(s->pktout, algorithm);
6994 ssh2_pkt_addstring_start(s->pktout);
6995 ssh2_pkt_addstring_data(s->pktout, (char *)pub_blob,
d8baa528 6996 pub_blob_len);
ff3187f6 6997 ssh2_pkt_send(ssh, s->pktout);
a03c9f9c 6998 logevent("Offered public key");
1408a877 6999
ff3187f6 7000 crWaitUntilV(pktin);
7001 if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
51470298 7002 s->gotit = TRUE;
7003 s->type = AUTH_TYPE_PUBLICKEY_OFFER_LOUD;
32874aea 7004 continue; /* key refused; give up on it */
1408a877 7005 }
65a22376 7006
1408a877 7007 logevent("Offer of public key accepted");
65a22376 7008 /*
1408a877 7009 * Actually attempt a serious authentication using
7010 * the key.
65a22376 7011 */
9a30e26b 7012 if (ssh2_userkey_encrypted(&ssh->cfg.keyfile, &comment)) {
51470298 7013 sprintf(s->pwprompt,
32874aea 7014 "Passphrase for key \"%.100s\": ",
7015 comment);
51470298 7016 s->need_pw = TRUE;
1408a877 7017 } else {
51470298 7018 s->need_pw = FALSE;
1408a877 7019 }
4e520718 7020 if (flags & FLAG_VERBOSE) {
7021 c_write_str(ssh, "Authenticating with public key \"");
7022 c_write_str(ssh, comment);
7023 c_write_str(ssh, "\"\r\n");
7024 }
51470298 7025 s->method = AUTH_PUBLICKEY_FILE;
65a22376 7026 }
1408a877 7027 }
7028
6f64ce13 7029 if (!s->method && s->can_keyb_inter && !s->kbd_inter_refused &&
7030 !s->kbd_inter_running) {
51470298 7031 s->method = AUTH_KEYBOARD_INTERACTIVE;
7032 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
af659722 7033
51470298 7034 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
7035 ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER;
00db133f 7036
ff3187f6 7037 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
7038 ssh2_pkt_addstring(s->pktout, s->username);
7039 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
7040 ssh2_pkt_addstring(s->pktout, "keyboard-interactive"); /* method */
7041 ssh2_pkt_addstring(s->pktout, ""); /* lang */
7042 ssh2_pkt_addstring(s->pktout, "");
7043 ssh2_pkt_send(ssh, s->pktout);
7044
7045 crWaitUntilV(pktin);
7046 if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
7047 if (pktin->type == SSH2_MSG_USERAUTH_FAILURE)
51470298 7048 s->gotit = TRUE;
af659722 7049 logevent("Keyboard-interactive authentication refused");
51470298 7050 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET;
6ac3a551 7051 s->kbd_inter_refused = TRUE; /* don't try it again */
af659722 7052 continue;
7053 }
7054
fb2ec557 7055 c_write_str(ssh, "Using keyboard-interactive authentication.\r\n");
51470298 7056 s->kbd_inter_running = TRUE;
7057 s->curr_prompt = 0;
af659722 7058 }
7059
51470298 7060 if (s->kbd_inter_running) {
7061 s->method = AUTH_KEYBOARD_INTERACTIVE;
7062 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
af659722 7063
51470298 7064 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
7065 ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER;
00db133f 7066
51470298 7067 if (s->curr_prompt == 0) {
45068b27 7068 /*
7069 * We've got a fresh USERAUTH_INFO_REQUEST.
7070 * Display header data, and start going through
7071 * the prompts.
7072 */
7073 char *name, *inst, *lang;
7074 int name_len, inst_len, lang_len;
7075
ff3187f6 7076 ssh_pkt_getstring(pktin, &name, &name_len);
7077 ssh_pkt_getstring(pktin, &inst, &inst_len);
7078 ssh_pkt_getstring(pktin, &lang, &lang_len);
45068b27 7079 if (name_len > 0) {
51470298 7080 c_write_untrusted(ssh, name, name_len);
7081 c_write_str(ssh, "\r\n");
45068b27 7082 }
7083 if (inst_len > 0) {
51470298 7084 c_write_untrusted(ssh, inst, inst_len);
7085 c_write_str(ssh, "\r\n");
45068b27 7086 }
ff3187f6 7087 s->num_prompts = ssh_pkt_getuint32(pktin);
45068b27 7088 }
af659722 7089
45068b27 7090 /*
7091 * If there are prompts remaining in the packet,
7092 * display one and get a response.
7093 */
51470298 7094 if (s->curr_prompt < s->num_prompts) {
45068b27 7095 char *prompt;
7096 int prompt_len;
af659722 7097
ff3187f6 7098 ssh_pkt_getstring(pktin, &prompt, &prompt_len);
45068b27 7099 if (prompt_len > 0) {
85fdbe25 7100 static const char trunc[] = "<prompt truncated>: ";
7101 static const int prlen = sizeof(s->pwprompt) -
7102 lenof(trunc);
7103 if (prompt_len > prlen) {
7104 memcpy(s->pwprompt, prompt, prlen);
7105 strcpy(s->pwprompt + prlen, trunc);
7106 } else {
7107 memcpy(s->pwprompt, prompt, prompt_len);
7108 s->pwprompt[prompt_len] = '\0';
7109 }
45068b27 7110 } else {
51470298 7111 strcpy(s->pwprompt,
45068b27 7112 "<server failed to send prompt>: ");
7113 }
ff3187f6 7114 s->echo = ssh2_pkt_getbool(pktin);
51470298 7115 s->need_pw = TRUE;
45068b27 7116 } else
51470298 7117 s->need_pw = FALSE;
af659722 7118 }
7119
51470298 7120 if (!s->method && s->can_passwd) {
7121 s->method = AUTH_PASSWORD;
7122 ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
7123 ssh->pkt_ctx |= SSH2_PKTCTX_PASSWORD;
7124 sprintf(s->pwprompt, "%.90s@%.90s's password: ", s->username,
7125 ssh->savedhost);
7126 s->need_pw = TRUE;
1408a877 7127 }
7128
51470298 7129 if (s->need_pw) {
fa17a66e 7130 if (ssh_get_line) {
51470298 7131 if (!ssh_get_line(s->pwprompt, s->password,
7132 sizeof(s->password), TRUE)) {
1408a877 7133 /*
fa17a66e 7134 * get_line failed to get a password (for
7135 * example because one was supplied on the
7136 * command line which has already failed to
7137 * work). Terminate.
1408a877 7138 */
9e296bfa 7139 ssh_disconnect(ssh, NULL, "Unable to authenticate",
7140 SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
7141 FALSE);
7ffdbc1a 7142 crStopV;
1408a877 7143 }
7144 } else {
51470298 7145 int ret; /* need not be saved across crReturn */
7146 c_write_untrusted(ssh, s->pwprompt, strlen(s->pwprompt));
7147 ssh->send_ok = 1;
1408a877 7148
51470298 7149 setup_userpass_input(ssh, s->password,
7150 sizeof(s->password), s->echo);
0405e71f 7151 do {
ff3187f6 7152 crWaitUntilV(!pktin);
51470298 7153 ret = process_userpass_input(ssh, in, inlen);
0405e71f 7154 } while (ret == 0);
7155 if (ret < 0)
7156 cleanup_exit(0);
51470298 7157 c_write_str(ssh, "\r\n");
65a22376 7158 }
65a22376 7159 }
65a22376 7160
51470298 7161 if (s->method == AUTH_PUBLICKEY_FILE) {
1408a877 7162 /*
7163 * We have our passphrase. Now try the actual authentication.
7164 */
7165 struct ssh2_userkey *key;
222d54dc 7166 const char *error = NULL;
65a22376 7167
222d54dc 7168 key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password,
7169 &error);
1408a877 7170 if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
7171 if (key == SSH2_WRONG_PASSPHRASE) {
51470298 7172 c_write_str(ssh, "Wrong passphrase\r\n");
7173 s->tried_pubkey_config = FALSE;
1408a877 7174 } else {
222d54dc 7175 c_write_str(ssh, "Unable to load private key (");
7176 c_write_str(ssh, error);
7177 c_write_str(ssh, ")\r\n");
51470298 7178 s->tried_pubkey_config = TRUE;
1408a877 7179 }
7180 /* Send a spurious AUTH_NONE to return to the top. */
ff3187f6 7181 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
7182 ssh2_pkt_addstring(s->pktout, s->username);
7183 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
7184 ssh2_pkt_addstring(s->pktout, "none"); /* method */
7185 ssh2_pkt_send(ssh, s->pktout);
51470298 7186 s->type = AUTH_TYPE_NONE;
1408a877 7187 } else {
1dd353b5 7188 unsigned char *pkblob, *sigblob, *sigdata;
7189 int pkblob_len, sigblob_len, sigdata_len;
dda87a28 7190 int p;
65a22376 7191
1408a877 7192 /*
7193 * We have loaded the private key and the server
7194 * has announced that it's willing to accept it.
7195 * Hallelujah. Generate a signature and send it.
7196 */
ff3187f6 7197 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
7198 ssh2_pkt_addstring(s->pktout, s->username);
7199 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
7200 ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
7201 ssh2_pkt_addbool(s->pktout, TRUE);
7202 ssh2_pkt_addstring(s->pktout, key->alg->name);
1dd353b5 7203 pkblob = key->alg->public_blob(key->data, &pkblob_len);
ff3187f6 7204 ssh2_pkt_addstring_start(s->pktout);
7205 ssh2_pkt_addstring_data(s->pktout, (char *)pkblob, pkblob_len);
1408a877 7206
7207 /*
7208 * The data to be signed is:
7209 *
7210 * string session-id
7211 *
7212 * followed by everything so far placed in the
7213 * outgoing packet.
7214 */
b672f405 7215 sigdata_len = s->pktout->length - 5 + 4 +
7216 ssh->v2_session_id_len;
dda87a28 7217 if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
7218 sigdata_len -= 4;
92d60585 7219 sigdata = snewn(sigdata_len, unsigned char);
dda87a28 7220 p = 0;
7221 if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
b672f405 7222 PUT_32BIT(sigdata+p, ssh->v2_session_id_len);
dda87a28 7223 p += 4;
7224 }
b672f405 7225 memcpy(sigdata+p, ssh->v2_session_id,
7226 ssh->v2_session_id_len);
7227 p += ssh->v2_session_id_len;
ff3187f6 7228 memcpy(sigdata+p, s->pktout->data + 5,
7229 s->pktout->length - 5);
7230 p += s->pktout->length - 5;
dda87a28 7231 assert(p == sigdata_len);
d8baa528 7232 sigblob = key->alg->sign(key->data, (char *)sigdata,
1dd353b5 7233 sigdata_len, &sigblob_len);
ff3187f6 7234 ssh2_add_sigblob(ssh, s->pktout, pkblob, pkblob_len,
1dd353b5 7235 sigblob, sigblob_len);
7236 sfree(pkblob);
7237 sfree(sigblob);
1408a877 7238 sfree(sigdata);
7239
ff3187f6 7240 ssh2_pkt_send(ssh, s->pktout);
51470298 7241 s->type = AUTH_TYPE_PUBLICKEY;
75374b2f 7242 key->alg->freekey(key->data);
1408a877 7243 }
51470298 7244 } else if (s->method == AUTH_PASSWORD) {
65a22376 7245 /*
95d2d262 7246 * We pad out the password packet to 256 bytes to make
7247 * it harder for an attacker to find the length of the
7248 * user's password.
1408a877 7249 *
95d2d262 7250 * Anyone using a password longer than 256 bytes
7251 * probably doesn't have much to worry about from
1408a877 7252 * people who find out how long their password is!
65a22376 7253 */
ff3187f6 7254 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
95d2d262 7255 s->pktout->forcepad = 256;
ff3187f6 7256 ssh2_pkt_addstring(s->pktout, s->username);
7257 ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
7258 ssh2_pkt_addstring(s->pktout, "password");
7259 ssh2_pkt_addbool(s->pktout, FALSE);
7260 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
7261 ssh2_pkt_addstring(s->pktout, s->password);
1409c1b3 7262 memset(s->password, 0, sizeof(s->password));
ff3187f6 7263 end_log_omission(ssh, s->pktout);
95d2d262 7264 ssh2_pkt_send(ssh, s->pktout);
0d43337a 7265 logevent("Sent password");
51470298 7266 s->type = AUTH_TYPE_PASSWORD;
7267 } else if (s->method == AUTH_KEYBOARD_INTERACTIVE) {
7268 if (s->curr_prompt == 0) {
ff3187f6 7269 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
10e09fb5 7270 s->pktout->forcepad = 256;
ff3187f6 7271 ssh2_pkt_adduint32(s->pktout, s->num_prompts);
45068b27 7272 }
51470298 7273 if (s->need_pw) { /* only add pw if we just got one! */
ff3187f6 7274 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
7275 ssh2_pkt_addstring(s->pktout, s->password);
51470298 7276 memset(s->password, 0, sizeof(s->password));
ff3187f6 7277 end_log_omission(ssh, s->pktout);
51470298 7278 s->curr_prompt++;
45068b27 7279 }
51470298 7280 if (s->curr_prompt >= s->num_prompts) {
ff3187f6 7281 ssh2_pkt_send(ssh, s->pktout);
45068b27 7282 } else {
7283 /*
7284 * If there are prompts remaining, we set
7285 * `gotit' so that we won't attempt to get
7286 * another packet. Then we go back round the
7287 * loop and will end up retrieving another
7288 * prompt out of the existing packet. Funky or
7289 * what?
7290 */
51470298 7291 s->gotit = TRUE;
45068b27 7292 }
51470298 7293 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
1408a877 7294 } else {
9e296bfa 7295 ssh_disconnect(ssh, NULL,
7296 "No supported authentication methods available",
7297 SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
7298 FALSE);
7ffdbc1a 7299 crStopV;
65a22376 7300 }
65a22376 7301 }
a1a1fae4 7302 }
6bbce591 7303 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = NULL;
7cca0d81 7304
7305 /*
a1a1fae4 7306 * Now the connection protocol has started, one way or another.
7cca0d81 7307 */
7308
0ed48730 7309 ssh->channels = newtree234(ssh_channelcmp);
7310
7cca0d81 7311 /*
b09eaa88 7312 * Set up handlers for some connection protocol messages, so we
7313 * don't have to handle them repeatedly in this coroutine.
7314 */
7315 ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] =
7316 ssh2_msg_channel_window_adjust;
51df0ab5 7317 ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] =
7318 ssh2_msg_global_request;
b09eaa88 7319
7320 /*
0ed48730 7321 * Create the main session channel.
7cca0d81 7322 */
0ed48730 7323 if (!ssh->cfg.ssh_no_shell) {
7324 ssh->mainchan = snew(struct ssh_channel);
7325 ssh->mainchan->ssh = ssh;
7326 ssh->mainchan->localid = alloc_channel_id(ssh);
ff3187f6 7327 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
7328 ssh2_pkt_addstring(s->pktout, "session");
7329 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
0ed48730 7330 ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
ff3187f6 7331 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
954d5c5a 7332 ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT); /* our max pkt size */
ff3187f6 7333 ssh2_pkt_send(ssh, s->pktout);
7334 crWaitUntilV(pktin);
7335 if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
0ed48730 7336 bombout(("Server refused to open a session"));
7337 crStopV;
7338 /* FIXME: error data comes back in FAILURE packet */
7339 }
ff3187f6 7340 if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
0ed48730 7341 bombout(("Server's channel confirmation cited wrong channel"));
7342 crStopV;
7343 }
ff3187f6 7344 ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
64d6ff88 7345 ssh->mainchan->halfopen = FALSE;
0ed48730 7346 ssh->mainchan->type = CHAN_MAINSESSION;
7347 ssh->mainchan->closes = 0;
ff3187f6 7348 ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
7349 ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
0ed48730 7350 bufchain_init(&ssh->mainchan->v.v2.outbuffer);
7351 add234(ssh->channels, ssh->mainchan);
62638676 7352 update_specials_menu(ssh->frontend);
0ed48730 7353 logevent("Opened channel for session");
7354 } else
7355 ssh->mainchan = NULL;
7cca0d81 7356
7357 /*
51df0ab5 7358 * Now we have a channel, make dispatch table entries for
7359 * general channel-based messages.
7360 */
7361 ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] =
7362 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] =
7363 ssh2_msg_channel_data;
7364 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = ssh2_msg_channel_eof;
7365 ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = ssh2_msg_channel_close;
7366 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] =
7367 ssh2_msg_channel_open_confirmation;
7368 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] =
7369 ssh2_msg_channel_open_failure;
7370 ssh->packet_dispatch[SSH2_MSG_CHANNEL_REQUEST] =
7371 ssh2_msg_channel_request;
7372 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] =
7373 ssh2_msg_channel_open;
7374
7375 /*
783415f8 7376 * Potentially enable X11 forwarding.
7377 */
0ed48730 7378 if (ssh->mainchan && ssh->cfg.x11_forward) {
32874aea 7379 char proto[20], data[64];
7380 logevent("Requesting X11 forwarding");
302121de 7381 ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
86916870 7382 data, sizeof(data), ssh->cfg.x11_auth);
7383 x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display);
ff3187f6 7384 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
7385 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
7386 ssh2_pkt_addstring(s->pktout, "x11-req");
7387 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7388 ssh2_pkt_addbool(s->pktout, 0); /* many connections */
7389 ssh2_pkt_addstring(s->pktout, proto);
f68353be 7390 /*
7391 * Note that while we blank the X authentication data here, we don't
7392 * take any special action to blank the start of an X11 channel,
7393 * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection
7394 * without having session blanking enabled is likely to leak your
7395 * cookie into the log.
7396 */
178c3872 7397 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
ff3187f6 7398 ssh2_pkt_addstring(s->pktout, data);
178c3872 7399 end_log_omission(ssh, s->pktout);
ff3187f6 7400 ssh2_pkt_adduint32(s->pktout, x11_get_screen_number(ssh->cfg.x11_display));
7401 ssh2_pkt_send(ssh, s->pktout);
32874aea 7402
b09eaa88 7403 crWaitUntilV(pktin);
32874aea 7404
ff3187f6 7405 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
7406 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
6b5cf8b4 7407 bombout(("Unexpected response to X11 forwarding request:"
ff3187f6 7408 " packet type %d", pktin->type));
7ffdbc1a 7409 crStopV;
32874aea 7410 }
7411 logevent("X11 forwarding refused");
7412 } else {
7413 logevent("X11 forwarding enabled");
51470298 7414 ssh->X11_fwd_enabled = TRUE;
32874aea 7415 }
783415f8 7416 }
7417
7418 /*
bc240b21 7419 * Enable port forwardings.
7420 */
06fadff5 7421 ssh_setup_portfwd(ssh, &ssh->cfg);
bc240b21 7422
7423 /*
36c2a3e9 7424 * Potentially enable agent forwarding.
7425 */
0ed48730 7426 if (ssh->mainchan && ssh->cfg.agentfwd && agent_exists()) {
32874aea 7427 logevent("Requesting OpenSSH-style agent forwarding");
ff3187f6 7428 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
7429 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
7430 ssh2_pkt_addstring(s->pktout, "auth-agent-req@openssh.com");
7431 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7432 ssh2_pkt_send(ssh, s->pktout);
32874aea 7433
b09eaa88 7434 crWaitUntilV(pktin);
32874aea 7435
ff3187f6 7436 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
7437 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
6b5cf8b4 7438 bombout(("Unexpected response to agent forwarding request:"
ff3187f6 7439 " packet type %d", pktin->type));
7ffdbc1a 7440 crStopV;
32874aea 7441 }
7442 logevent("Agent forwarding refused");
7443 } else {
7444 logevent("Agent forwarding enabled");
51470298 7445 ssh->agentfwd_enabled = TRUE;
32874aea 7446 }
36c2a3e9 7447 }
7448
7449 /*
7cca0d81 7450 * Now allocate a pty for the session.
7451 */
0ed48730 7452 if (ssh->mainchan && !ssh->cfg.nopty) {
a5dd8467 7453 /* Unpick the terminal-speed string. */
7454 /* XXX perhaps we should allow no speeds to be sent. */
db219738 7455 ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
7456 sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
a5dd8467 7457 /* Build the pty request. */
ff3187f6 7458 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
7459 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid); /* recipient channel */
7460 ssh2_pkt_addstring(s->pktout, "pty-req");
7461 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7462 ssh2_pkt_addstring(s->pktout, ssh->cfg.termtype);
7463 ssh2_pkt_adduint32(s->pktout, ssh->term_width);
7464 ssh2_pkt_adduint32(s->pktout, ssh->term_height);
7465 ssh2_pkt_adduint32(s->pktout, 0); /* pixel width */
7466 ssh2_pkt_adduint32(s->pktout, 0); /* pixel height */
7467 ssh2_pkt_addstring_start(s->pktout);
c6ccd5c2 7468 parse_ttymodes(ssh, ssh->cfg.ttymodes,
7469 ssh2_send_ttymode, (void *)s->pktout);
7470 ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_ISPEED);
ff3187f6 7471 ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
c6ccd5c2 7472 ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_OSPEED);
ff3187f6 7473 ssh2_pkt_adduint32(s->pktout, ssh->ospeed);
7474 ssh2_pkt_addstring_data(s->pktout, "\0", 1); /* TTY_OP_END */
7475 ssh2_pkt_send(ssh, s->pktout);
51470298 7476 ssh->state = SSH_STATE_INTERMED;
32874aea 7477
b09eaa88 7478 crWaitUntilV(pktin);
32874aea 7479
ff3187f6 7480 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
7481 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
6b5cf8b4 7482 bombout(("Unexpected response to pty request:"
ff3187f6 7483 " packet type %d", pktin->type));
7ffdbc1a 7484 crStopV;
32874aea 7485 }
51470298 7486 c_write_str(ssh, "Server refused to allocate pty\r\n");
7487 ssh->editing = ssh->echoing = 1;
32874aea 7488 } else {
a5dd8467 7489 logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
db219738 7490 ssh->ospeed, ssh->ispeed);
32874aea 7491 }
0965bee0 7492 } else {
51470298 7493 ssh->editing = ssh->echoing = 1;
7cca0d81 7494 }
7495
7496 /*
73feed4f 7497 * Send environment variables.
7498 *
7499 * Simplest thing here is to send all the requests at once, and
7500 * then wait for a whole bunch of successes or failures.
7501 */
7502 if (ssh->mainchan && *ssh->cfg.environmt) {
7503 char *e = ssh->cfg.environmt;
7504 char *var, *varend, *val;
7505
7506 s->num_env = 0;
7507
7508 while (*e) {
7509 var = e;
7510 while (*e && *e != '\t') e++;
7511 varend = e;
7512 if (*e == '\t') e++;
7513 val = e;
7514 while (*e) e++;
7515 e++;
7516
ff3187f6 7517 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
7518 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
7519 ssh2_pkt_addstring(s->pktout, "env");
7520 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7521 ssh2_pkt_addstring_start(s->pktout);
7522 ssh2_pkt_addstring_data(s->pktout, var, varend-var);
7523 ssh2_pkt_addstring(s->pktout, val);
7524 ssh2_pkt_send(ssh, s->pktout);
73feed4f 7525
7526 s->num_env++;
7527 }
7528
7529 logeventf(ssh, "Sent %d environment variables", s->num_env);
7530
7531 s->env_ok = 0;
7532 s->env_left = s->num_env;
7533
7534 while (s->env_left > 0) {
b09eaa88 7535 crWaitUntilV(pktin);
73feed4f 7536
ff3187f6 7537 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
7538 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
73feed4f 7539 bombout(("Unexpected response to environment request:"
ff3187f6 7540 " packet type %d", pktin->type));
73feed4f 7541 crStopV;
7542 }
7543 } else {
7544 s->env_ok++;
7545 }
7546
7547 s->env_left--;
7548 }
7549
7550 if (s->env_ok == s->num_env) {
7551 logevent("All environment variables successfully set");
7552 } else if (s->env_ok == 0) {
7553 logevent("All environment variables refused");
7554 c_write_str(ssh, "Server refused to set environment variables\r\n");
7555 } else {
7556 logeventf(ssh, "%d environment variables refused",
7557 s->num_env - s->env_ok);
7558 c_write_str(ssh, "Server refused to set all environment variables\r\n");
7559 }
7560 }
7561
7562 /*
fd5e5847 7563 * Start a shell or a remote command. We may have to attempt
7564 * this twice if the config data has provided a second choice
7565 * of command.
7cca0d81 7566 */
0ed48730 7567 if (ssh->mainchan) while (1) {
fd5e5847 7568 int subsys;
7569 char *cmd;
7570
51470298 7571 if (ssh->fallback_cmd) {
86916870 7572 subsys = ssh->cfg.ssh_subsys2;
7573 cmd = ssh->cfg.remote_cmd_ptr2;
fd5e5847 7574 } else {
86916870 7575 subsys = ssh->cfg.ssh_subsys;
7576 cmd = ssh->cfg.remote_cmd_ptr;
04c52f10 7577 if (!cmd) cmd = ssh->cfg.remote_cmd;
fd5e5847 7578 }
7579
ff3187f6 7580 s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
7581 ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid); /* recipient channel */
fd5e5847 7582 if (subsys) {
ff3187f6 7583 ssh2_pkt_addstring(s->pktout, "subsystem");
7584 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7585 ssh2_pkt_addstring(s->pktout, cmd);
fd5e5847 7586 } else if (*cmd) {
ff3187f6 7587 ssh2_pkt_addstring(s->pktout, "exec");
7588 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
7589 ssh2_pkt_addstring(s->pktout, cmd);
fd5e5847 7590 } else {
ff3187f6 7591 ssh2_pkt_addstring(s->pktout, "shell");
7592 ssh2_pkt_addbool(s->pktout, 1); /* want reply */
32874aea 7593 }
ff3187f6 7594 ssh2_pkt_send(ssh, s->pktout);
b09eaa88 7595
7596 crWaitUntilV(pktin);
7597
ff3187f6 7598 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
7599 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
6b5cf8b4 7600 bombout(("Unexpected response to shell/command request:"
ff3187f6 7601 " packet type %d", pktin->type));
7ffdbc1a 7602 crStopV;
fd5e5847 7603 }
7604 /*
7605 * We failed to start the command. If this is the
7606 * fallback command, we really are finished; if it's
7607 * not, and if the fallback command exists, try falling
7608 * back to it before complaining.
7609 */
86916870 7610 if (!ssh->fallback_cmd && ssh->cfg.remote_cmd_ptr2 != NULL) {
fd5e5847 7611 logevent("Primary command failed; attempting fallback");
51470298 7612 ssh->fallback_cmd = TRUE;
fd5e5847 7613 continue;
7614 }
6b5cf8b4 7615 bombout(("Server refused to start a shell/command"));
7ffdbc1a 7616 crStopV;
fd5e5847 7617 } else {
7618 logevent("Started a shell/command");
32874aea 7619 }
fd5e5847 7620 break;
7cca0d81 7621 }
7622
51470298 7623 ssh->state = SSH_STATE_SESSION;
7624 if (ssh->size_needed)
7625 ssh_size(ssh, ssh->term_width, ssh->term_height);
7626 if (ssh->eof_needed)
7627 ssh_special(ssh, TS_EOF);
6e48c3fe 7628
7cca0d81 7629 /*
7630 * Transfer data!
7631 */
b9d7bcad 7632 if (ssh->ldisc)
7633 ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
0ed48730 7634 if (ssh->mainchan)
7635 ssh->send_ok = 1;
7cca0d81 7636 while (1) {
e5574168 7637 crReturnV;
51470298 7638 s->try_send = FALSE;
ff3187f6 7639 if (pktin) {
2b7540a7 7640
51df0ab5 7641 /*
7642 * _All_ the connection-layer packets we expect to
7643 * receive are now handled by the dispatch table.
7644 * Anything that reaches here must be bogus.
7645 */
32874aea 7646
51df0ab5 7647 bombout(("Strange packet received: type %d", pktin->type));
7648 crStopV;
0ed48730 7649 } else if (ssh->mainchan) {
32874aea 7650 /*
7651 * We have spare data. Add it to the channel buffer.
7652 */
d8baa528 7653 ssh2_add_channel_data(ssh->mainchan, (char *)in, inlen);
51470298 7654 s->try_send = TRUE;
32874aea 7655 }
51470298 7656 if (s->try_send) {
32874aea 7657 int i;
7658 struct ssh_channel *c;
7659 /*
7660 * Try to send data on all channels if we can.
7661 */
1bfc7e93 7662 for (i = 0; NULL != (c = index234(ssh->channels, i)); i++)
7663 ssh2_try_send_and_unthrottle(c);
7cca0d81 7664 }
e5574168 7665 }
7666
7667 crFinishV;
7668}
7669
7670/*
2e85c969 7671 * Handlers for SSH-2 messages that might arrive at any moment.
b09eaa88 7672 */
409bfa77 7673static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
b09eaa88 7674{
7675 /* log reason code in disconnect message */
7676 char *buf, *msg;
7677 int nowlen, reason, msglen;
7678
7679 reason = ssh_pkt_getuint32(pktin);
7680 ssh_pkt_getstring(pktin, &msg, &msglen);
7681
7682 if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
7683 buf = dupprintf("Received disconnect message (%s)",
7684 ssh2_disconnect_reasons[reason]);
7685 } else {
7686 buf = dupprintf("Received disconnect message (unknown"
7687 " type %d)", reason);
7688 }
7689 logevent(buf);
7690 sfree(buf);
7691 buf = dupprintf("Disconnection message text: %n%.*s",
7692 &nowlen, msglen, msg);
7693 logevent(buf);
7694 bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"",
7695 reason,
7696 (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
7697 ssh2_disconnect_reasons[reason] : "unknown",
7698 buf+nowlen));
7699 sfree(buf);
7700}
7701
409bfa77 7702static void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
b09eaa88 7703{
7704 /* log the debug message */
fb983202 7705 char *msg;
b09eaa88 7706 int msglen;
7707 int always_display;
7708
7709 /* XXX maybe we should actually take notice of this */
7710 always_display = ssh2_pkt_getbool(pktin);
7711 ssh_pkt_getstring(pktin, &msg, &msglen);
7712
fb983202 7713 logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
b09eaa88 7714}
7715
409bfa77 7716static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)
b09eaa88 7717{
7718 struct Packet *pktout;
7719 pktout = ssh2_pkt_init(SSH2_MSG_UNIMPLEMENTED);
7720 ssh2_pkt_adduint32(pktout, pktin->sequence);
7721 /*
7722 * UNIMPLEMENTED messages MUST appear in the same order as the
7723 * messages they respond to. Hence, never queue them.
7724 */
7725 ssh2_pkt_send_noqueue(ssh, pktout);
7726}
7727
7728/*
2e85c969 7729 * Handle the top-level SSH-2 protocol.
7cca0d81 7730 */
b09eaa88 7731static void ssh2_protocol_setup(Ssh ssh)
7732{
7733 int i;
7734
7735 /*
7736 * Most messages cause SSH2_MSG_UNIMPLEMENTED.
7737 */
7738 for (i = 0; i < 256; i++)
7739 ssh->packet_dispatch[i] = ssh2_msg_something_unimplemented;
7740
7741 /*
7742 * Any message we actually understand, we set to NULL so that
7743 * the coroutines will get it.
7744 */
7745 ssh->packet_dispatch[SSH2_MSG_UNIMPLEMENTED] = NULL;
7746 ssh->packet_dispatch[SSH2_MSG_SERVICE_REQUEST] = NULL;
7747 ssh->packet_dispatch[SSH2_MSG_SERVICE_ACCEPT] = NULL;
7748 ssh->packet_dispatch[SSH2_MSG_KEXINIT] = NULL;
7749 ssh->packet_dispatch[SSH2_MSG_NEWKEYS] = NULL;
7750 ssh->packet_dispatch[SSH2_MSG_KEXDH_INIT] = NULL;
7751 ssh->packet_dispatch[SSH2_MSG_KEXDH_REPLY] = NULL;
7752 /* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REQUEST] = NULL; duplicate case value */
7753 /* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_GROUP] = NULL; duplicate case value */
7754 ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_INIT] = NULL;
7755 ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REPLY] = NULL;
7756 ssh->packet_dispatch[SSH2_MSG_USERAUTH_REQUEST] = NULL;
7757 ssh->packet_dispatch[SSH2_MSG_USERAUTH_FAILURE] = NULL;
7758 ssh->packet_dispatch[SSH2_MSG_USERAUTH_SUCCESS] = NULL;
7759 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = NULL;
7760 ssh->packet_dispatch[SSH2_MSG_USERAUTH_PK_OK] = NULL;
7761 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ] = NULL; duplicate case value */
7762 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_REQUEST] = NULL; duplicate case value */
7763 ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_RESPONSE] = NULL;
7764 ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] = NULL;
7765 ssh->packet_dispatch[SSH2_MSG_REQUEST_SUCCESS] = NULL;
7766 ssh->packet_dispatch[SSH2_MSG_REQUEST_FAILURE] = NULL;
7767 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] = NULL;
7768 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] = NULL;
7769 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] = NULL;
7770 ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] = NULL;
7771 ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] = NULL;
7772 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] = NULL;
7773 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = NULL;
7774 ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = NULL;
7775 ssh->packet_dispatch[SSH2_MSG_CHANNEL_REQUEST] = NULL;
7776 ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = NULL;
7777 ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = NULL;
7778
7779 /*
7780 * These special message types we install handlers for.
7781 */
7782 ssh->packet_dispatch[SSH2_MSG_DISCONNECT] = ssh2_msg_disconnect;
2e85c969 7783 ssh->packet_dispatch[SSH2_MSG_IGNORE] = ssh_msg_ignore; /* shared with SSH-1 */
b09eaa88 7784 ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
7785}
7786
9442dd57 7787static void ssh2_timer(void *ctx, long now)
7788{
7789 Ssh ssh = (Ssh)ctx;
7790
ecbb0000 7791 if (ssh->state == SSH_STATE_CLOSED)
7792 return;
7793
e6c1536e 7794 if (!ssh->kex_in_progress && ssh->cfg.ssh_rekey_time != 0 &&
9442dd57 7795 now - ssh->next_rekey >= 0) {
f382c87d 7796 do_ssh2_transport(ssh, "timeout", -1, NULL);
9442dd57 7797 }
7798}
7799
1c1a7262 7800static void ssh2_protocol(Ssh ssh, void *vin, int inlen,
ff3187f6 7801 struct Packet *pktin)
7cca0d81 7802{
1c1a7262 7803 unsigned char *in = (unsigned char *)vin;
b09eaa88 7804 if (ssh->state == SSH_STATE_CLOSED)
7805 return;
7806
9442dd57 7807 if (pktin) {
7808 ssh->incoming_data_size += pktin->encrypted_len;
7809 if (!ssh->kex_in_progress &&
d57f70af 7810 ssh->max_data_size != 0 &&
7811 ssh->incoming_data_size > ssh->max_data_size)
f382c87d 7812 do_ssh2_transport(ssh, "too much data received", -1, NULL);
9442dd57 7813 }
7814
b09eaa88 7815 if (pktin && ssh->packet_dispatch[pktin->type]) {
7816 ssh->packet_dispatch[pktin->type](ssh, pktin);
32874aea 7817 return;
b09eaa88 7818 }
7819
7820 if (!ssh->protocol_initial_phase_done ||
7821 (pktin && pktin->type >= 20 && pktin->type < 50)) {
7822 if (do_ssh2_transport(ssh, in, inlen, pktin) &&
7823 !ssh->protocol_initial_phase_done) {
7824 ssh->protocol_initial_phase_done = TRUE;
7825 /*
7826 * Allow authconn to initialise itself.
7827 */
7828 do_ssh2_authconn(ssh, NULL, 0, NULL);
7829 }
7830 } else {
7831 do_ssh2_authconn(ssh, in, inlen, pktin);
7832 }
7cca0d81 7833}
7834
7835/*
8df7a775 7836 * Called to set up the connection.
374330e2 7837 *
7838 * Returns an error message, or NULL on success.
374330e2 7839 */
cbe2d68f 7840static const char *ssh_init(void *frontend_handle, void **backend_handle,
7841 Config *cfg,
79bf227b 7842 char *host, int port, char **realhost, int nodelay,
7843 int keepalive)
32874aea 7844{
cbe2d68f 7845 const char *p;
51470298 7846 Ssh ssh;
7847
3d88e64d 7848 ssh = snew(struct ssh_tag);
86916870 7849 ssh->cfg = *cfg; /* STRUCTURE COPY */
125105d1 7850 ssh->version = 0; /* when not ready yet */
51470298 7851 ssh->s = NULL;
7852 ssh->cipher = NULL;
371e569c 7853 ssh->v1_cipher_ctx = NULL;
0183b242 7854 ssh->crcda_ctx = NULL;
51470298 7855 ssh->cscipher = NULL;
371e569c 7856 ssh->cs_cipher_ctx = NULL;
51470298 7857 ssh->sccipher = NULL;
371e569c 7858 ssh->sc_cipher_ctx = NULL;
51470298 7859 ssh->csmac = NULL;
a8327734 7860 ssh->cs_mac_ctx = NULL;
51470298 7861 ssh->scmac = NULL;
e0e1a00d 7862 ssh->sc_mac_ctx = NULL;
51470298 7863 ssh->cscomp = NULL;
5366aed8 7864 ssh->cs_comp_ctx = NULL;
51470298 7865 ssh->sccomp = NULL;
5366aed8 7866 ssh->sc_comp_ctx = NULL;
51470298 7867 ssh->kex = NULL;
389aa499 7868 ssh->kex_ctx = NULL;
51470298 7869 ssh->hostkey = NULL;
7870 ssh->exitcode = -1;
ac934965 7871 ssh->close_expected = FALSE;
9e296bfa 7872 ssh->clean_exit = FALSE;
51470298 7873 ssh->state = SSH_STATE_PREPACKET;
7874 ssh->size_needed = FALSE;
7875 ssh->eof_needed = FALSE;
b9d7bcad 7876 ssh->ldisc = NULL;
a8327734 7877 ssh->logctx = NULL;
51470298 7878 ssh->deferred_send_data = NULL;
7879 ssh->deferred_len = 0;
7880 ssh->deferred_size = 0;
7881 ssh->fallback_cmd = 0;
7882 ssh->pkt_ctx = 0;
302121de 7883 ssh->x11auth = NULL;
be738459 7884 ssh->v1_compressing = FALSE;
51470298 7885 ssh->v2_outgoing_sequence = 0;
7886 ssh->ssh1_rdpkt_crstate = 0;
7887 ssh->ssh2_rdpkt_crstate = 0;
7888 ssh->do_ssh_init_crstate = 0;
7889 ssh->ssh_gotdata_crstate = 0;
b09eaa88 7890 ssh->do_ssh1_connection_crstate = 0;
51470298 7891 ssh->do_ssh1_login_crstate = 0;
7892 ssh->do_ssh2_transport_crstate = 0;
7893 ssh->do_ssh2_authconn_crstate = 0;
7894 ssh->do_ssh_init_state = NULL;
7895 ssh->do_ssh1_login_state = NULL;
7896 ssh->do_ssh2_transport_state = NULL;
7897 ssh->do_ssh2_authconn_state = NULL;
4320baf7 7898 ssh->v_c = NULL;
7899 ssh->v_s = NULL;
6571dbfd 7900 ssh->mainchan = NULL;
968d2d92 7901 ssh->throttled_all = 0;
7902 ssh->v1_stdout_throttling = 0;
590f6a5f 7903 ssh->queue = NULL;
7904 ssh->queuelen = ssh->queuesize = 0;
7905 ssh->queueing = FALSE;
06fadff5 7906 ssh->qhead = ssh->qtail = NULL;
e13bba36 7907 ssh->deferred_rekey_reason = NULL;
3d9449a1 7908 bufchain_init(&ssh->queued_incoming_data);
7909 ssh->frozen = FALSE;
51470298 7910
7911 *backend_handle = ssh;
32874aea 7912
8f203108 7913#ifdef MSCRYPTOAPI
32874aea 7914 if (crypto_startup() == 0)
8f203108 7915 return "Microsoft high encryption pack not installed!";
7916#endif
374330e2 7917
51470298 7918 ssh->frontend = frontend_handle;
86916870 7919 ssh->term_width = ssh->cfg.width;
7920 ssh->term_height = ssh->cfg.height;
887035a5 7921
fabd1805 7922 ssh->channels = NULL;
7923 ssh->rportfwds = NULL;
f47a5ffb 7924 ssh->portfwds = NULL;
fabd1805 7925
51470298 7926 ssh->send_ok = 0;
7927 ssh->editing = 0;
7928 ssh->echoing = 0;
7929 ssh->v1_throttle_count = 0;
7930 ssh->overall_bufsize = 0;
7931 ssh->fallback_cmd = 0;
8df7a775 7932
3648d4c5 7933 ssh->protocol = NULL;
7934
b09eaa88 7935 ssh->protocol_initial_phase_done = FALSE;
7936
39934deb 7937 ssh->pinger = NULL;
7938
9442dd57 7939 ssh->incoming_data_size = ssh->outgoing_data_size =
7940 ssh->deferred_data_size = 0L;
d57f70af 7941 ssh->max_data_size = parse_blocksize(ssh->cfg.ssh_rekey_data);
9442dd57 7942 ssh->kex_in_progress = FALSE;
7943
79bf227b 7944 p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
fb09bf1c 7945 if (p != NULL)
7946 return p;
374330e2 7947
5d17ccfc 7948 random_ref();
7949
374330e2 7950 return NULL;
7951}
7952
fabd1805 7953static void ssh_free(void *handle)
7954{
7955 Ssh ssh = (Ssh) handle;
7956 struct ssh_channel *c;
7957 struct ssh_rportfwd *pf;
7958
7959 if (ssh->v1_cipher_ctx)
7960 ssh->cipher->free_context(ssh->v1_cipher_ctx);
7961 if (ssh->cs_cipher_ctx)
7962 ssh->cscipher->free_context(ssh->cs_cipher_ctx);
7963 if (ssh->sc_cipher_ctx)
7964 ssh->sccipher->free_context(ssh->sc_cipher_ctx);
7965 if (ssh->cs_mac_ctx)
7966 ssh->csmac->free_context(ssh->cs_mac_ctx);
7967 if (ssh->sc_mac_ctx)
7968 ssh->scmac->free_context(ssh->sc_mac_ctx);
29b1d0b3 7969 if (ssh->cs_comp_ctx) {
7970 if (ssh->cscomp)
7971 ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
7972 else
7973 zlib_compress_cleanup(ssh->cs_comp_ctx);
7974 }
7975 if (ssh->sc_comp_ctx) {
7976 if (ssh->sccomp)
7977 ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);
7978 else
7979 zlib_decompress_cleanup(ssh->sc_comp_ctx);
7980 }
fabd1805 7981 if (ssh->kex_ctx)
7982 dh_cleanup(ssh->kex_ctx);
7983 sfree(ssh->savedhost);
7984
590f6a5f 7985 while (ssh->queuelen-- > 0)
7986 ssh_free_packet(ssh->queue[ssh->queuelen]);
7987 sfree(ssh->queue);
7988
06fadff5 7989 while (ssh->qhead) {
7990 struct queued_handler *qh = ssh->qhead;
7991 ssh->qhead = qh->next;
7992 sfree(ssh->qhead);
7993 }
7994 ssh->qhead = ssh->qtail = NULL;
7995
fabd1805 7996 if (ssh->channels) {
7997 while ((c = delpos234(ssh->channels, 0)) != NULL) {
7998 switch (c->type) {
7999 case CHAN_X11:
8000 if (c->u.x11.s != NULL)
8001 x11_close(c->u.x11.s);
8002 break;
8003 case CHAN_SOCKDATA:
8004 if (c->u.pfd.s != NULL)
8005 pfd_close(c->u.pfd.s);
8006 break;
8007 }
8008 sfree(c);
8009 }
8010 freetree234(ssh->channels);
cdb52705 8011 ssh->channels = NULL;
fabd1805 8012 }
8013
8014 if (ssh->rportfwds) {
8015 while ((pf = delpos234(ssh->rportfwds, 0)) != NULL)
8016 sfree(pf);
8017 freetree234(ssh->rportfwds);
cdb52705 8018 ssh->rportfwds = NULL;
fabd1805 8019 }
8020 sfree(ssh->deferred_send_data);
8021 if (ssh->x11auth)
8022 x11_free_auth(ssh->x11auth);
8023 sfree(ssh->do_ssh_init_state);
8024 sfree(ssh->do_ssh1_login_state);
8025 sfree(ssh->do_ssh2_transport_state);
8026 sfree(ssh->do_ssh2_authconn_state);
4320baf7 8027 sfree(ssh->v_c);
8028 sfree(ssh->v_s);
679539d7 8029 if (ssh->crcda_ctx) {
8030 crcda_free_context(ssh->crcda_ctx);
8031 ssh->crcda_ctx = NULL;
8032 }
fabd1805 8033 if (ssh->s)
ac934965 8034 ssh_do_close(ssh, TRUE);
9442dd57 8035 expire_timer_context(ssh);
39934deb 8036 if (ssh->pinger)
8037 pinger_free(ssh->pinger);
3d9449a1 8038 bufchain_clear(&ssh->queued_incoming_data);
ee50e8b6 8039 sfree(ssh);
5d17ccfc 8040
8041 random_unref();
fabd1805 8042}
8043
374330e2 8044/*
86916870 8045 * Reconfigure the SSH backend.
86916870 8046 */
8047static void ssh_reconfig(void *handle, Config *cfg)
8048{
8049 Ssh ssh = (Ssh) handle;
e13bba36 8050 char *rekeying = NULL, rekey_mandatory = FALSE;
e6c1536e 8051 unsigned long old_max_data_size;
8052
39934deb 8053 pinger_reconfig(ssh->pinger, &ssh->cfg, cfg);
3b6606c7 8054 if (ssh->portfwds)
8055 ssh_setup_portfwd(ssh, cfg);
e6c1536e 8056
8057 if (ssh->cfg.ssh_rekey_time != cfg->ssh_rekey_time &&
8058 cfg->ssh_rekey_time != 0) {
8059 long new_next = ssh->last_rekey + cfg->ssh_rekey_time*60*TICKSPERSEC;
8060 long now = GETTICKCOUNT();
8061
8062 if (new_next - now < 0) {
f382c87d 8063 rekeying = "timeout shortened";
e6c1536e 8064 } else {
8065 ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
8066 }
8067 }
8068
8069 old_max_data_size = ssh->max_data_size;
8070 ssh->max_data_size = parse_blocksize(cfg->ssh_rekey_data);
8071 if (old_max_data_size != ssh->max_data_size &&
8072 ssh->max_data_size != 0) {
8073 if (ssh->outgoing_data_size > ssh->max_data_size ||
8074 ssh->incoming_data_size > ssh->max_data_size)
f382c87d 8075 rekeying = "data limit lowered";
e6c1536e 8076 }
8077
e13bba36 8078 if (ssh->cfg.compression != cfg->compression) {
f382c87d 8079 rekeying = "compression setting changed";
e13bba36 8080 rekey_mandatory = TRUE;
8081 }
8082
8083 if (ssh->cfg.ssh2_des_cbc != cfg->ssh2_des_cbc ||
8084 memcmp(ssh->cfg.ssh_cipherlist, cfg->ssh_cipherlist,
8085 sizeof(ssh->cfg.ssh_cipherlist))) {
f382c87d 8086 rekeying = "cipher settings changed";
e13bba36 8087 rekey_mandatory = TRUE;
e6c1536e 8088 }
8089
86916870 8090 ssh->cfg = *cfg; /* STRUCTURE COPY */
e13bba36 8091
8092 if (rekeying) {
8093 if (!ssh->kex_in_progress) {
8094 do_ssh2_transport(ssh, rekeying, -1, NULL);
8095 } else if (rekey_mandatory) {
8096 ssh->deferred_rekey_reason = rekeying;
8097 }
8098 }
86916870 8099}
8100
8101/*
86dc445a 8102 * Called to send data down the SSH connection.
374330e2 8103 */
51470298 8104static int ssh_send(void *handle, char *buf, int len)
32874aea 8105{
51470298 8106 Ssh ssh = (Ssh) handle;
8107
8108 if (ssh == NULL || ssh->s == NULL || ssh->protocol == NULL)
5471d09a 8109 return 0;
374330e2 8110
d8baa528 8111 ssh->protocol(ssh, (unsigned char *)buf, len, 0);
5471d09a 8112
51470298 8113 return ssh_sendbuffer(ssh);
5471d09a 8114}
8115
8116/*
8117 * Called to query the current amount of buffered stdin data.
8118 */
51470298 8119static int ssh_sendbuffer(void *handle)
5471d09a 8120{
51470298 8121 Ssh ssh = (Ssh) handle;
5471d09a 8122 int override_value;
8123
51470298 8124 if (ssh == NULL || ssh->s == NULL || ssh->protocol == NULL)
5471d09a 8125 return 0;
8126
8127 /*
8128 * If the SSH socket itself has backed up, add the total backup
8129 * size on that to any individual buffer on the stdin channel.
8130 */
8131 override_value = 0;
51470298 8132 if (ssh->throttled_all)
8133 override_value = ssh->overall_bufsize;
5471d09a 8134
51470298 8135 if (ssh->version == 1) {
5471d09a 8136 return override_value;
51470298 8137 } else if (ssh->version == 2) {
8138 if (!ssh->mainchan || ssh->mainchan->closes > 0)
5471d09a 8139 return override_value;
8140 else
51470298 8141 return (override_value +
8142 bufchain_size(&ssh->mainchan->v.v2.outbuffer));
5471d09a 8143 }
8144
8145 return 0;
374330e2 8146}
8147
8148/*
6e48c3fe 8149 * Called to set the size of the window from SSH's POV.
374330e2 8150 */
51470298 8151static void ssh_size(void *handle, int width, int height)
32874aea 8152{
51470298 8153 Ssh ssh = (Ssh) handle;
ff3187f6 8154 struct Packet *pktout;
51470298 8155
8156 ssh->term_width = width;
8157 ssh->term_height = height;
f278d6f8 8158
51470298 8159 switch (ssh->state) {
374330e2 8160 case SSH_STATE_BEFORE_SIZE:
3687d221 8161 case SSH_STATE_PREPACKET:
21248260 8162 case SSH_STATE_CLOSED:
374330e2 8163 break; /* do nothing */
8164 case SSH_STATE_INTERMED:
51470298 8165 ssh->size_needed = TRUE; /* buffer for later */
374330e2 8166 break;
8167 case SSH_STATE_SESSION:
86916870 8168 if (!ssh->cfg.nopty) {
51470298 8169 if (ssh->version == 1) {
8170 send_packet(ssh, SSH1_CMSG_WINDOW_SIZE,
8171 PKT_INT, ssh->term_height,
8172 PKT_INT, ssh->term_width,
32874aea 8173 PKT_INT, 0, PKT_INT, 0, PKT_END);
0ed48730 8174 } else if (ssh->mainchan) {
ff3187f6 8175 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
8176 ssh2_pkt_adduint32(pktout, ssh->mainchan->remoteid);
8177 ssh2_pkt_addstring(pktout, "window-change");
8178 ssh2_pkt_addbool(pktout, 0);
8179 ssh2_pkt_adduint32(pktout, ssh->term_width);
8180 ssh2_pkt_adduint32(pktout, ssh->term_height);
8181 ssh2_pkt_adduint32(pktout, 0);
8182 ssh2_pkt_adduint32(pktout, 0);
8183 ssh2_pkt_send(ssh, pktout);
32874aea 8184 }
8185 }
8186 break;
374330e2 8187 }
8188}
8189
8190/*
125105d1 8191 * Return a list of the special codes that make sense in this
8192 * protocol.
8193 */
8194static const struct telnet_special *ssh_get_specials(void *handle)
8195{
786ba75e 8196 static const struct telnet_special ssh1_ignore_special[] = {
8197 {"IGNORE message", TS_NOP}
8198 };
8199 static const struct telnet_special ssh2_transport_specials[] = {
62638676 8200 {"IGNORE message", TS_NOP},
9442dd57 8201 {"Repeat key exchange", TS_REKEY},
62638676 8202 };
8203 static const struct telnet_special ssh2_session_specials[] = {
6f2d0cde 8204 {NULL, TS_SEP},
8205 {"Break", TS_BRK},
786ba75e 8206 /* These are the signal names defined by draft-ietf-secsh-connect-23.
6f2d0cde 8207 * They include all the ISO C signals, but are a subset of the POSIX
8208 * required signals. */
8209 {"SIGINT (Interrupt)", TS_SIGINT},
8210 {"SIGTERM (Terminate)", TS_SIGTERM},
8211 {"SIGKILL (Kill)", TS_SIGKILL},
8212 {"SIGQUIT (Quit)", TS_SIGQUIT},
8213 {"SIGHUP (Hangup)", TS_SIGHUP},
8214 {"More signals", TS_SUBMENU},
8215 {"SIGABRT", TS_SIGABRT}, {"SIGALRM", TS_SIGALRM},
8216 {"SIGFPE", TS_SIGFPE}, {"SIGILL", TS_SIGILL},
8217 {"SIGPIPE", TS_SIGPIPE}, {"SIGSEGV", TS_SIGSEGV},
8218 {"SIGUSR1", TS_SIGUSR1}, {"SIGUSR2", TS_SIGUSR2},
8219 {NULL, TS_EXITMENU}
62638676 8220 };
8221 static const struct telnet_special specials_end[] = {
6f2d0cde 8222 {NULL, TS_EXITMENU}
62638676 8223 };
786ba75e 8224 /* XXX review this length for any changes: */
8225 static struct telnet_special ssh_specials[lenof(ssh2_transport_specials) +
62638676 8226 lenof(ssh2_session_specials) +
8227 lenof(specials_end)];
125105d1 8228 Ssh ssh = (Ssh) handle;
62638676 8229 int i = 0;
8230#define ADD_SPECIALS(name) \
8231 do { \
8232 assert((i + lenof(name)) <= lenof(ssh_specials)); \
8233 memcpy(&ssh_specials[i], name, sizeof name); \
8234 i += lenof(name); \
8235 } while(0)
125105d1 8236
8237 if (ssh->version == 1) {
62638676 8238 /* Don't bother offering IGNORE if we've decided the remote
8239 * won't cope with it, since we wouldn't bother sending it if
8240 * asked anyway. */
8241 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE))
786ba75e 8242 ADD_SPECIALS(ssh1_ignore_special);
125105d1 8243 } else if (ssh->version == 2) {
786ba75e 8244 ADD_SPECIALS(ssh2_transport_specials);
62638676 8245 if (ssh->mainchan)
8246 ADD_SPECIALS(ssh2_session_specials);
8247 } /* else we're not ready yet */
8248
8249 if (i) {
8250 ADD_SPECIALS(specials_end);
8251 return ssh_specials;
8252 } else {
125105d1 8253 return NULL;
62638676 8254 }
8255#undef ADD_SPECIALS
125105d1 8256}
8257
8258/*
86dc445a 8259 * Send special codes. TS_EOF is useful for `plink', so you
6abbf9e3 8260 * can send an EOF and collect resulting output (e.g. `plink
8261 * hostname sort').
374330e2 8262 */
51470298 8263static void ssh_special(void *handle, Telnet_Special code)
32874aea 8264{
51470298 8265 Ssh ssh = (Ssh) handle;
ff3187f6 8266 struct Packet *pktout;
51470298 8267
6abbf9e3 8268 if (code == TS_EOF) {
51470298 8269 if (ssh->state != SSH_STATE_SESSION) {
32874aea 8270 /*
8271 * Buffer the EOF in case we are pre-SESSION, so we can
8272 * send it as soon as we reach SESSION.
8273 */
8274 if (code == TS_EOF)
51470298 8275 ssh->eof_needed = TRUE;
32874aea 8276 return;
8277 }
51470298 8278 if (ssh->version == 1) {
8279 send_packet(ssh, SSH1_CMSG_EOF, PKT_END);
0ed48730 8280 } else if (ssh->mainchan) {
ff3187f6 8281 struct Packet *pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_EOF);
8282 ssh2_pkt_adduint32(pktout, ssh->mainchan->remoteid);
8283 ssh2_pkt_send(ssh, pktout);
00a0b113 8284 ssh->send_ok = 0; /* now stop trying to read from stdin */
32874aea 8285 }
8286 logevent("Sent EOF message");
125105d1 8287 } else if (code == TS_PING || code == TS_NOP) {
51470298 8288 if (ssh->state == SSH_STATE_CLOSED
8289 || ssh->state == SSH_STATE_PREPACKET) return;
8290 if (ssh->version == 1) {
8291 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE))
8292 send_packet(ssh, SSH1_MSG_IGNORE, PKT_STR, "", PKT_END);
32874aea 8293 } else {
ff3187f6 8294 pktout = ssh2_pkt_init(SSH2_MSG_IGNORE);
8295 ssh2_pkt_addstring_start(pktout);
590f6a5f 8296 ssh2_pkt_send_noqueue(ssh, pktout);
32874aea 8297 }
9442dd57 8298 } else if (code == TS_REKEY) {
8299 if (!ssh->kex_in_progress && ssh->version == 2) {
f382c87d 8300 do_ssh2_transport(ssh, "at user request", -1, NULL);
9442dd57 8301 }
125105d1 8302 } else if (code == TS_BRK) {
8303 if (ssh->state == SSH_STATE_CLOSED
8304 || ssh->state == SSH_STATE_PREPACKET) return;
8305 if (ssh->version == 1) {
2e85c969 8306 logevent("Unable to send BREAK signal in SSH-1");
0ed48730 8307 } else if (ssh->mainchan) {
ff3187f6 8308 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
8309 ssh2_pkt_adduint32(pktout, ssh->mainchan->remoteid);
8310 ssh2_pkt_addstring(pktout, "break");
8311 ssh2_pkt_addbool(pktout, 0);
8312 ssh2_pkt_adduint32(pktout, 0); /* default break length */
8313 ssh2_pkt_send(ssh, pktout);
125105d1 8314 }
6abbf9e3 8315 } else {
6f2d0cde 8316 /* Is is a POSIX signal? */
8317 char *signame = NULL;
8318 if (code == TS_SIGABRT) signame = "ABRT";
8319 if (code == TS_SIGALRM) signame = "ALRM";
8320 if (code == TS_SIGFPE) signame = "FPE";
8321 if (code == TS_SIGHUP) signame = "HUP";
8322 if (code == TS_SIGILL) signame = "ILL";
8323 if (code == TS_SIGINT) signame = "INT";
8324 if (code == TS_SIGKILL) signame = "KILL";
8325 if (code == TS_SIGPIPE) signame = "PIPE";
8326 if (code == TS_SIGQUIT) signame = "QUIT";
8327 if (code == TS_SIGSEGV) signame = "SEGV";
8328 if (code == TS_SIGTERM) signame = "TERM";
8329 if (code == TS_SIGUSR1) signame = "USR1";
8330 if (code == TS_SIGUSR2) signame = "USR2";
8331 /* The SSH-2 protocol does in principle support arbitrary named
8332 * signals, including signame@domain, but we don't support those. */
8333 if (signame) {
8334 /* It's a signal. */
8335 if (ssh->version == 2 && ssh->mainchan) {
ff3187f6 8336 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
8337 ssh2_pkt_adduint32(pktout, ssh->mainchan->remoteid);
8338 ssh2_pkt_addstring(pktout, "signal");
8339 ssh2_pkt_addbool(pktout, 0);
8340 ssh2_pkt_addstring(pktout, signame);
8341 ssh2_pkt_send(ssh, pktout);
6f2d0cde 8342 logeventf(ssh, "Sent signal SIG%s", signame);
8343 }
8344 } else {
8345 /* Never heard of it. Do nothing */
8346 }
6abbf9e3 8347 }
374330e2 8348}
8349
51470298 8350void *new_sock_channel(void *handle, Socket s)
d74d141c 8351{
51470298 8352 Ssh ssh = (Ssh) handle;
d74d141c 8353 struct ssh_channel *c;
3d88e64d 8354 c = snew(struct ssh_channel);
51470298 8355 c->ssh = ssh;
d74d141c 8356
8357 if (c) {
64d6ff88 8358 c->halfopen = TRUE;
51470298 8359 c->localid = alloc_channel_id(ssh);
d74d141c 8360 c->closes = 0;
bc240b21 8361 c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */
d74d141c 8362 c->u.pfd.s = s;
013dd8c0 8363 bufchain_init(&c->v.v2.outbuffer);
51470298 8364 add234(ssh->channels, c);
d74d141c 8365 }
8366 return c;
8367}
8368
5471d09a 8369/*
8370 * This is called when stdout/stderr (the entity to which
8371 * from_backend sends data) manages to clear some backlog.
8372 */
ae9ae89f 8373static void ssh_unthrottle(void *handle, int bufsize)
5471d09a 8374{
51470298 8375 Ssh ssh = (Ssh) handle;
8376 if (ssh->version == 1) {
8377 if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
8378 ssh->v1_stdout_throttling = 0;
8379 ssh1_throttle(ssh, -1);
5471d09a 8380 }
8381 } else {
51470298 8382 if (ssh->mainchan && ssh->mainchan->closes == 0)
8383 ssh2_set_window(ssh->mainchan, OUR_V2_WINSIZE - bufsize);
5471d09a 8384 }
8385}
8386
6b78788a 8387void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
d74d141c 8388{
8389 struct ssh_channel *c = (struct ssh_channel *)channel;
6b78788a 8390 Ssh ssh = c->ssh;
ff3187f6 8391 struct Packet *pktout;
d74d141c 8392
57356d63 8393 logeventf(ssh, "Opening forwarded connection to %s:%d", hostname, port);
d74d141c 8394
51470298 8395 if (ssh->version == 1) {
8396 send_packet(ssh, SSH1_MSG_PORT_OPEN,
bc240b21 8397 PKT_INT, c->localid,
8398 PKT_STR, hostname,
8399 PKT_INT, port,
31fb1866 8400 /* PKT_STR, <org:orgport>, */
bc240b21 8401 PKT_END);
8402 } else {
ff3187f6 8403 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
8404 ssh2_pkt_addstring(pktout, "direct-tcpip");
8405 ssh2_pkt_adduint32(pktout, c->localid);
5471d09a 8406 c->v.v2.locwindow = OUR_V2_WINSIZE;
ff3187f6 8407 ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
954d5c5a 8408 ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
ff3187f6 8409 ssh2_pkt_addstring(pktout, hostname);
8410 ssh2_pkt_adduint32(pktout, port);
bc240b21 8411 /*
8412 * We make up values for the originator data; partly it's
8413 * too much hassle to keep track, and partly I'm not
8414 * convinced the server should be told details like that
8415 * about my local network configuration.
8416 */
ff3187f6 8417 ssh2_pkt_addstring(pktout, "client-side-connection");
8418 ssh2_pkt_adduint32(pktout, 0);
8419 ssh2_pkt_send(ssh, pktout);
bc240b21 8420 }
d74d141c 8421}
8422
51470298 8423static Socket ssh_socket(void *handle)
32874aea 8424{
51470298 8425 Ssh ssh = (Ssh) handle;
8426 return ssh->s;
32874aea 8427}
8ccc75b0 8428
51470298 8429static int ssh_sendok(void *handle)
32874aea 8430{
51470298 8431 Ssh ssh = (Ssh) handle;
8432 return ssh->send_ok;
32874aea 8433}
fb09bf1c 8434
51470298 8435static int ssh_ldisc(void *handle, int option)
32874aea 8436{
51470298 8437 Ssh ssh = (Ssh) handle;
32874aea 8438 if (option == LD_ECHO)
51470298 8439 return ssh->echoing;
32874aea 8440 if (option == LD_EDIT)
51470298 8441 return ssh->editing;
0965bee0 8442 return FALSE;
8443}
8444
b9d7bcad 8445static void ssh_provide_ldisc(void *handle, void *ldisc)
8446{
8447 Ssh ssh = (Ssh) handle;
8448 ssh->ldisc = ldisc;
8449}
8450
a8327734 8451static void ssh_provide_logctx(void *handle, void *logctx)
8452{
8453 Ssh ssh = (Ssh) handle;
8454 ssh->logctx = logctx;
8455}
8456
51470298 8457static int ssh_return_exitcode(void *handle)
8458{
8459 Ssh ssh = (Ssh) handle;
3bb2f322 8460 if (ssh->s != NULL)
8461 return -1;
8462 else
8463 return (ssh->exitcode >= 0 ? ssh->exitcode : 0);
51470298 8464}
8465
8466/*
f89c3294 8467 * cfg_info for SSH is the currently running version of the
8468 * protocol. (1 for 1; 2 for 2; 0 for not-decided-yet.)
8469 */
8470static int ssh_cfg_info(void *handle)
8471{
8472 Ssh ssh = (Ssh) handle;
8473 return ssh->version;
8474}
8475
8476/*
51470298 8477 * Gross hack: pscp will try to start SFTP but fall back to scp1 if
8478 * that fails. This variable is the means by which scp.c can reach
8479 * into the SSH code and find out which one it got.
8480 */
8481extern int ssh_fallback_cmd(void *handle)
d8d6c7e5 8482{
51470298 8483 Ssh ssh = (Ssh) handle;
8484 return ssh->fallback_cmd;
d8d6c7e5 8485}
8486
374330e2 8487Backend ssh_backend = {
8488 ssh_init,
fabd1805 8489 ssh_free,
86916870 8490 ssh_reconfig,
374330e2 8491 ssh_send,
5471d09a 8492 ssh_sendbuffer,
374330e2 8493 ssh_size,
4017be6d 8494 ssh_special,
125105d1 8495 ssh_get_specials,
8ccc75b0 8496 ssh_socket,
d8d6c7e5 8497 ssh_return_exitcode,
97db3be4 8498 ssh_sendok,
0965bee0 8499 ssh_ldisc,
b9d7bcad 8500 ssh_provide_ldisc,
a8327734 8501 ssh_provide_logctx,
5471d09a 8502 ssh_unthrottle,
f89c3294 8503 ssh_cfg_info,
97db3be4 8504 22
bc240b21 8505};