13 #include "tree234.h"
\r
16 #include "sshgssc.h"
\r
27 #define SSH1_MSG_DISCONNECT 1 /* 0x1 */
\r
28 #define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */
\r
29 #define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */
\r
30 #define SSH1_CMSG_USER 4 /* 0x4 */
\r
31 #define SSH1_CMSG_AUTH_RSA 6 /* 0x6 */
\r
32 #define SSH1_SMSG_AUTH_RSA_CHALLENGE 7 /* 0x7 */
\r
33 #define SSH1_CMSG_AUTH_RSA_RESPONSE 8 /* 0x8 */
\r
34 #define SSH1_CMSG_AUTH_PASSWORD 9 /* 0x9 */
\r
35 #define SSH1_CMSG_REQUEST_PTY 10 /* 0xa */
\r
36 #define SSH1_CMSG_WINDOW_SIZE 11 /* 0xb */
\r
37 #define SSH1_CMSG_EXEC_SHELL 12 /* 0xc */
\r
38 #define SSH1_CMSG_EXEC_CMD 13 /* 0xd */
\r
39 #define SSH1_SMSG_SUCCESS 14 /* 0xe */
\r
40 #define SSH1_SMSG_FAILURE 15 /* 0xf */
\r
41 #define SSH1_CMSG_STDIN_DATA 16 /* 0x10 */
\r
42 #define SSH1_SMSG_STDOUT_DATA 17 /* 0x11 */
\r
43 #define SSH1_SMSG_STDERR_DATA 18 /* 0x12 */
\r
44 #define SSH1_CMSG_EOF 19 /* 0x13 */
\r
45 #define SSH1_SMSG_EXIT_STATUS 20 /* 0x14 */
\r
46 #define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* 0x15 */
\r
47 #define SSH1_MSG_CHANNEL_OPEN_FAILURE 22 /* 0x16 */
\r
48 #define SSH1_MSG_CHANNEL_DATA 23 /* 0x17 */
\r
49 #define SSH1_MSG_CHANNEL_CLOSE 24 /* 0x18 */
\r
50 #define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* 0x19 */
\r
51 #define SSH1_SMSG_X11_OPEN 27 /* 0x1b */
\r
52 #define SSH1_CMSG_PORT_FORWARD_REQUEST 28 /* 0x1c */
\r
53 #define SSH1_MSG_PORT_OPEN 29 /* 0x1d */
\r
54 #define SSH1_CMSG_AGENT_REQUEST_FORWARDING 30 /* 0x1e */
\r
55 #define SSH1_SMSG_AGENT_OPEN 31 /* 0x1f */
\r
56 #define SSH1_MSG_IGNORE 32 /* 0x20 */
\r
57 #define SSH1_CMSG_EXIT_CONFIRMATION 33 /* 0x21 */
\r
58 #define SSH1_CMSG_X11_REQUEST_FORWARDING 34 /* 0x22 */
\r
59 #define SSH1_CMSG_AUTH_RHOSTS_RSA 35 /* 0x23 */
\r
60 #define SSH1_MSG_DEBUG 36 /* 0x24 */
\r
61 #define SSH1_CMSG_REQUEST_COMPRESSION 37 /* 0x25 */
\r
62 #define SSH1_CMSG_AUTH_TIS 39 /* 0x27 */
\r
63 #define SSH1_SMSG_AUTH_TIS_CHALLENGE 40 /* 0x28 */
\r
64 #define SSH1_CMSG_AUTH_TIS_RESPONSE 41 /* 0x29 */
\r
65 #define SSH1_CMSG_AUTH_CCARD 70 /* 0x46 */
\r
66 #define SSH1_SMSG_AUTH_CCARD_CHALLENGE 71 /* 0x47 */
\r
67 #define SSH1_CMSG_AUTH_CCARD_RESPONSE 72 /* 0x48 */
\r
69 #define SSH1_AUTH_RHOSTS 1 /* 0x1 */
\r
70 #define SSH1_AUTH_RSA 2 /* 0x2 */
\r
71 #define SSH1_AUTH_PASSWORD 3 /* 0x3 */
\r
72 #define SSH1_AUTH_RHOSTS_RSA 4 /* 0x4 */
\r
73 #define SSH1_AUTH_TIS 5 /* 0x5 */
\r
74 #define SSH1_AUTH_CCARD 16 /* 0x10 */
\r
76 #define SSH1_PROTOFLAG_SCREEN_NUMBER 1 /* 0x1 */
\r
77 /* Mask for protoflags we will echo back to server if seen */
\r
78 #define SSH1_PROTOFLAGS_SUPPORTED 0 /* 0x1 */
\r
80 #define SSH2_MSG_DISCONNECT 1 /* 0x1 */
\r
81 #define SSH2_MSG_IGNORE 2 /* 0x2 */
\r
82 #define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
\r
83 #define SSH2_MSG_DEBUG 4 /* 0x4 */
\r
84 #define SSH2_MSG_SERVICE_REQUEST 5 /* 0x5 */
\r
85 #define SSH2_MSG_SERVICE_ACCEPT 6 /* 0x6 */
\r
86 #define SSH2_MSG_KEXINIT 20 /* 0x14 */
\r
87 #define SSH2_MSG_NEWKEYS 21 /* 0x15 */
\r
88 #define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
\r
89 #define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
\r
90 #define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
\r
91 #define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
\r
92 #define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
\r
93 #define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */
\r
94 #define SSH2_MSG_KEXRSA_PUBKEY 30 /* 0x1e */
\r
95 #define SSH2_MSG_KEXRSA_SECRET 31 /* 0x1f */
\r
96 #define SSH2_MSG_KEXRSA_DONE 32 /* 0x20 */
\r
97 #define SSH2_MSG_USERAUTH_REQUEST 50 /* 0x32 */
\r
98 #define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
\r
99 #define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */
\r
100 #define SSH2_MSG_USERAUTH_BANNER 53 /* 0x35 */
\r
101 #define SSH2_MSG_USERAUTH_PK_OK 60 /* 0x3c */
\r
102 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 /* 0x3c */
\r
103 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 /* 0x3c */
\r
104 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* 0x3d */
\r
105 #define SSH2_MSG_GLOBAL_REQUEST 80 /* 0x50 */
\r
106 #define SSH2_MSG_REQUEST_SUCCESS 81 /* 0x51 */
\r
107 #define SSH2_MSG_REQUEST_FAILURE 82 /* 0x52 */
\r
108 #define SSH2_MSG_CHANNEL_OPEN 90 /* 0x5a */
\r
109 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 /* 0x5b */
\r
110 #define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 /* 0x5c */
\r
111 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 /* 0x5d */
\r
112 #define SSH2_MSG_CHANNEL_DATA 94 /* 0x5e */
\r
113 #define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 /* 0x5f */
\r
114 #define SSH2_MSG_CHANNEL_EOF 96 /* 0x60 */
\r
115 #define SSH2_MSG_CHANNEL_CLOSE 97 /* 0x61 */
\r
116 #define SSH2_MSG_CHANNEL_REQUEST 98 /* 0x62 */
\r
117 #define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
\r
118 #define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */
\r
119 #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60
\r
120 #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61
\r
121 #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63
\r
122 #define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64
\r
123 #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65
\r
124 #define SSH2_MSG_USERAUTH_GSSAPI_MIC 66
\r
127 * Packet type contexts, so that ssh2_pkt_type can correctly decode
\r
128 * the ambiguous type numbers back into the correct type strings.
\r
132 SSH2_PKTCTX_DHGROUP,
\r
137 SSH2_PKTCTX_NOAUTH,
\r
138 SSH2_PKTCTX_PUBLICKEY,
\r
139 SSH2_PKTCTX_PASSWORD,
\r
140 SSH2_PKTCTX_GSSAPI,
\r
141 SSH2_PKTCTX_KBDINTER
\r
144 #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */
\r
145 #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */
\r
146 #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */
\r
147 #define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 /* 0x4 */
\r
148 #define SSH2_DISCONNECT_MAC_ERROR 5 /* 0x5 */
\r
149 #define SSH2_DISCONNECT_COMPRESSION_ERROR 6 /* 0x6 */
\r
150 #define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 /* 0x7 */
\r
151 #define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 /* 0x8 */
\r
152 #define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 /* 0x9 */
\r
153 #define SSH2_DISCONNECT_CONNECTION_LOST 10 /* 0xa */
\r
154 #define SSH2_DISCONNECT_BY_APPLICATION 11 /* 0xb */
\r
155 #define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 /* 0xc */
\r
156 #define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 /* 0xd */
\r
157 #define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 /* 0xe */
\r
158 #define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* 0xf */
\r
160 static const char *const ssh2_disconnect_reasons[] = {
\r
162 "host not allowed to connect",
\r
164 "key exchange failed",
\r
165 "host authentication failed",
\r
167 "compression error",
\r
168 "service not available",
\r
169 "protocol version not supported",
\r
170 "host key not verifiable",
\r
173 "too many connections",
\r
174 "auth cancelled by user",
\r
175 "no more auth methods available",
\r
176 "illegal user name",
\r
179 #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 /* 0x1 */
\r
180 #define SSH2_OPEN_CONNECT_FAILED 2 /* 0x2 */
\r
181 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 /* 0x3 */
\r
182 #define SSH2_OPEN_RESOURCE_SHORTAGE 4 /* 0x4 */
\r
184 #define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
\r
187 * Various remote-bug flags.
\r
189 #define BUG_CHOKES_ON_SSH1_IGNORE 1
\r
190 #define BUG_SSH2_HMAC 2
\r
191 #define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
\r
192 #define BUG_CHOKES_ON_RSA 8
\r
193 #define BUG_SSH2_RSA_PADDING 16
\r
194 #define BUG_SSH2_DERIVEKEY 32
\r
195 #define BUG_SSH2_REKEY 64
\r
196 #define BUG_SSH2_PK_SESSIONID 128
\r
197 #define BUG_SSH2_MAXPKT 256
\r
198 #define BUG_CHOKES_ON_SSH2_IGNORE 512
\r
199 #define BUG_CHOKES_ON_WINADJ 1024
\r
202 * Codes for terminal modes.
\r
203 * Most of these are the same in SSH-1 and SSH-2.
\r
204 * This list is derived from RFC 4254 and
\r
205 * SSH-1 RFC-1.2.31.
\r
207 static const struct {
\r
208 const char* const mode;
\r
210 enum { TTY_OP_CHAR, TTY_OP_BOOL } type;
\r
211 } ssh_ttymodes[] = {
\r
212 /* "V" prefix discarded for special characters relative to SSH specs */
\r
213 { "INTR", 1, TTY_OP_CHAR },
\r
214 { "QUIT", 2, TTY_OP_CHAR },
\r
215 { "ERASE", 3, TTY_OP_CHAR },
\r
216 { "KILL", 4, TTY_OP_CHAR },
\r
217 { "EOF", 5, TTY_OP_CHAR },
\r
218 { "EOL", 6, TTY_OP_CHAR },
\r
219 { "EOL2", 7, TTY_OP_CHAR },
\r
220 { "START", 8, TTY_OP_CHAR },
\r
221 { "STOP", 9, TTY_OP_CHAR },
\r
222 { "SUSP", 10, TTY_OP_CHAR },
\r
223 { "DSUSP", 11, TTY_OP_CHAR },
\r
224 { "REPRINT", 12, TTY_OP_CHAR },
\r
225 { "WERASE", 13, TTY_OP_CHAR },
\r
226 { "LNEXT", 14, TTY_OP_CHAR },
\r
227 { "FLUSH", 15, TTY_OP_CHAR },
\r
228 { "SWTCH", 16, TTY_OP_CHAR },
\r
229 { "STATUS", 17, TTY_OP_CHAR },
\r
230 { "DISCARD", 18, TTY_OP_CHAR },
\r
231 { "IGNPAR", 30, TTY_OP_BOOL },
\r
232 { "PARMRK", 31, TTY_OP_BOOL },
\r
233 { "INPCK", 32, TTY_OP_BOOL },
\r
234 { "ISTRIP", 33, TTY_OP_BOOL },
\r
235 { "INLCR", 34, TTY_OP_BOOL },
\r
236 { "IGNCR", 35, TTY_OP_BOOL },
\r
237 { "ICRNL", 36, TTY_OP_BOOL },
\r
238 { "IUCLC", 37, TTY_OP_BOOL },
\r
239 { "IXON", 38, TTY_OP_BOOL },
\r
240 { "IXANY", 39, TTY_OP_BOOL },
\r
241 { "IXOFF", 40, TTY_OP_BOOL },
\r
242 { "IMAXBEL", 41, TTY_OP_BOOL },
\r
243 { "ISIG", 50, TTY_OP_BOOL },
\r
244 { "ICANON", 51, TTY_OP_BOOL },
\r
245 { "XCASE", 52, TTY_OP_BOOL },
\r
246 { "ECHO", 53, TTY_OP_BOOL },
\r
247 { "ECHOE", 54, TTY_OP_BOOL },
\r
248 { "ECHOK", 55, TTY_OP_BOOL },
\r
249 { "ECHONL", 56, TTY_OP_BOOL },
\r
250 { "NOFLSH", 57, TTY_OP_BOOL },
\r
251 { "TOSTOP", 58, TTY_OP_BOOL },
\r
252 { "IEXTEN", 59, TTY_OP_BOOL },
\r
253 { "ECHOCTL", 60, TTY_OP_BOOL },
\r
254 { "ECHOKE", 61, TTY_OP_BOOL },
\r
255 { "PENDIN", 62, TTY_OP_BOOL }, /* XXX is this a real mode? */
\r
256 { "OPOST", 70, TTY_OP_BOOL },
\r
257 { "OLCUC", 71, TTY_OP_BOOL },
\r
258 { "ONLCR", 72, TTY_OP_BOOL },
\r
259 { "OCRNL", 73, TTY_OP_BOOL },
\r
260 { "ONOCR", 74, TTY_OP_BOOL },
\r
261 { "ONLRET", 75, TTY_OP_BOOL },
\r
262 { "CS7", 90, TTY_OP_BOOL },
\r
263 { "CS8", 91, TTY_OP_BOOL },
\r
264 { "PARENB", 92, TTY_OP_BOOL },
\r
265 { "PARODD", 93, TTY_OP_BOOL }
\r
268 /* Miscellaneous other tty-related constants. */
\r
269 #define SSH_TTY_OP_END 0
\r
270 /* The opcodes for ISPEED/OSPEED differ between SSH-1 and SSH-2. */
\r
271 #define SSH1_TTY_OP_ISPEED 192
\r
272 #define SSH1_TTY_OP_OSPEED 193
\r
273 #define SSH2_TTY_OP_ISPEED 128
\r
274 #define SSH2_TTY_OP_OSPEED 129
\r
276 /* Helper functions for parsing tty-related config. */
\r
277 static unsigned int ssh_tty_parse_specchar(char *s)
\r
282 ret = ctrlparse(s, &next);
\r
283 if (!next) ret = s[0];
\r
285 ret = 255; /* special value meaning "don't set" */
\r
289 static unsigned int ssh_tty_parse_boolean(char *s)
\r
291 if (stricmp(s, "yes") == 0 ||
\r
292 stricmp(s, "on") == 0 ||
\r
293 stricmp(s, "true") == 0 ||
\r
294 stricmp(s, "+") == 0)
\r
295 return 1; /* true */
\r
296 else if (stricmp(s, "no") == 0 ||
\r
297 stricmp(s, "off") == 0 ||
\r
298 stricmp(s, "false") == 0 ||
\r
299 stricmp(s, "-") == 0)
\r
300 return 0; /* false */
\r
302 return (atoi(s) != 0);
\r
305 #define translate(x) if (type == x) return #x
\r
306 #define translatek(x,ctx) if (type == x && (pkt_kctx == ctx)) return #x
\r
307 #define translatea(x,ctx) if (type == x && (pkt_actx == ctx)) return #x
\r
308 static char *ssh1_pkt_type(int type)
\r
310 translate(SSH1_MSG_DISCONNECT);
\r
311 translate(SSH1_SMSG_PUBLIC_KEY);
\r
312 translate(SSH1_CMSG_SESSION_KEY);
\r
313 translate(SSH1_CMSG_USER);
\r
314 translate(SSH1_CMSG_AUTH_RSA);
\r
315 translate(SSH1_SMSG_AUTH_RSA_CHALLENGE);
\r
316 translate(SSH1_CMSG_AUTH_RSA_RESPONSE);
\r
317 translate(SSH1_CMSG_AUTH_PASSWORD);
\r
318 translate(SSH1_CMSG_REQUEST_PTY);
\r
319 translate(SSH1_CMSG_WINDOW_SIZE);
\r
320 translate(SSH1_CMSG_EXEC_SHELL);
\r
321 translate(SSH1_CMSG_EXEC_CMD);
\r
322 translate(SSH1_SMSG_SUCCESS);
\r
323 translate(SSH1_SMSG_FAILURE);
\r
324 translate(SSH1_CMSG_STDIN_DATA);
\r
325 translate(SSH1_SMSG_STDOUT_DATA);
\r
326 translate(SSH1_SMSG_STDERR_DATA);
\r
327 translate(SSH1_CMSG_EOF);
\r
328 translate(SSH1_SMSG_EXIT_STATUS);
\r
329 translate(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
\r
330 translate(SSH1_MSG_CHANNEL_OPEN_FAILURE);
\r
331 translate(SSH1_MSG_CHANNEL_DATA);
\r
332 translate(SSH1_MSG_CHANNEL_CLOSE);
\r
333 translate(SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION);
\r
334 translate(SSH1_SMSG_X11_OPEN);
\r
335 translate(SSH1_CMSG_PORT_FORWARD_REQUEST);
\r
336 translate(SSH1_MSG_PORT_OPEN);
\r
337 translate(SSH1_CMSG_AGENT_REQUEST_FORWARDING);
\r
338 translate(SSH1_SMSG_AGENT_OPEN);
\r
339 translate(SSH1_MSG_IGNORE);
\r
340 translate(SSH1_CMSG_EXIT_CONFIRMATION);
\r
341 translate(SSH1_CMSG_X11_REQUEST_FORWARDING);
\r
342 translate(SSH1_CMSG_AUTH_RHOSTS_RSA);
\r
343 translate(SSH1_MSG_DEBUG);
\r
344 translate(SSH1_CMSG_REQUEST_COMPRESSION);
\r
345 translate(SSH1_CMSG_AUTH_TIS);
\r
346 translate(SSH1_SMSG_AUTH_TIS_CHALLENGE);
\r
347 translate(SSH1_CMSG_AUTH_TIS_RESPONSE);
\r
348 translate(SSH1_CMSG_AUTH_CCARD);
\r
349 translate(SSH1_SMSG_AUTH_CCARD_CHALLENGE);
\r
350 translate(SSH1_CMSG_AUTH_CCARD_RESPONSE);
\r
353 static char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
\r
355 translatea(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,SSH2_PKTCTX_GSSAPI);
\r
356 translatea(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,SSH2_PKTCTX_GSSAPI);
\r
357 translatea(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,SSH2_PKTCTX_GSSAPI);
\r
358 translatea(SSH2_MSG_USERAUTH_GSSAPI_ERROR,SSH2_PKTCTX_GSSAPI);
\r
359 translatea(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,SSH2_PKTCTX_GSSAPI);
\r
360 translatea(SSH2_MSG_USERAUTH_GSSAPI_MIC, SSH2_PKTCTX_GSSAPI);
\r
361 translate(SSH2_MSG_DISCONNECT);
\r
362 translate(SSH2_MSG_IGNORE);
\r
363 translate(SSH2_MSG_UNIMPLEMENTED);
\r
364 translate(SSH2_MSG_DEBUG);
\r
365 translate(SSH2_MSG_SERVICE_REQUEST);
\r
366 translate(SSH2_MSG_SERVICE_ACCEPT);
\r
367 translate(SSH2_MSG_KEXINIT);
\r
368 translate(SSH2_MSG_NEWKEYS);
\r
369 translatek(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);
\r
370 translatek(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);
\r
371 translatek(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);
\r
372 translatek(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);
\r
373 translatek(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);
\r
374 translatek(SSH2_MSG_KEX_DH_GEX_REPLY, SSH2_PKTCTX_DHGEX);
\r
375 translatek(SSH2_MSG_KEXRSA_PUBKEY, SSH2_PKTCTX_RSAKEX);
\r
376 translatek(SSH2_MSG_KEXRSA_SECRET, SSH2_PKTCTX_RSAKEX);
\r
377 translatek(SSH2_MSG_KEXRSA_DONE, SSH2_PKTCTX_RSAKEX);
\r
378 translate(SSH2_MSG_USERAUTH_REQUEST);
\r
379 translate(SSH2_MSG_USERAUTH_FAILURE);
\r
380 translate(SSH2_MSG_USERAUTH_SUCCESS);
\r
381 translate(SSH2_MSG_USERAUTH_BANNER);
\r
382 translatea(SSH2_MSG_USERAUTH_PK_OK, SSH2_PKTCTX_PUBLICKEY);
\r
383 translatea(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, SSH2_PKTCTX_PASSWORD);
\r
384 translatea(SSH2_MSG_USERAUTH_INFO_REQUEST, SSH2_PKTCTX_KBDINTER);
\r
385 translatea(SSH2_MSG_USERAUTH_INFO_RESPONSE, SSH2_PKTCTX_KBDINTER);
\r
386 translate(SSH2_MSG_GLOBAL_REQUEST);
\r
387 translate(SSH2_MSG_REQUEST_SUCCESS);
\r
388 translate(SSH2_MSG_REQUEST_FAILURE);
\r
389 translate(SSH2_MSG_CHANNEL_OPEN);
\r
390 translate(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
\r
391 translate(SSH2_MSG_CHANNEL_OPEN_FAILURE);
\r
392 translate(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
\r
393 translate(SSH2_MSG_CHANNEL_DATA);
\r
394 translate(SSH2_MSG_CHANNEL_EXTENDED_DATA);
\r
395 translate(SSH2_MSG_CHANNEL_EOF);
\r
396 translate(SSH2_MSG_CHANNEL_CLOSE);
\r
397 translate(SSH2_MSG_CHANNEL_REQUEST);
\r
398 translate(SSH2_MSG_CHANNEL_SUCCESS);
\r
399 translate(SSH2_MSG_CHANNEL_FAILURE);
\r
405 /* Enumeration values for fields in SSH-1 packets */
\r
407 PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,
\r
408 /* These values are for communicating relevant semantics of
\r
409 * fields to the packet logging code. */
\r
410 PKTT_OTHER, PKTT_PASSWORD, PKTT_DATA
\r
414 * Coroutine mechanics for the sillier bits of the code. If these
\r
415 * macros look impenetrable to you, you might find it helpful to
\r
418 * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
\r
420 * which explains the theory behind these macros.
\r
422 * In particular, if you are getting `case expression not constant'
\r
423 * errors when building with MS Visual Studio, this is because MS's
\r
424 * Edit and Continue debugging feature causes their compiler to
\r
425 * violate ANSI C. To disable Edit and Continue debugging:
\r
427 * - right-click ssh.c in the FileView
\r
429 * - select the C/C++ tab and the General category
\r
430 * - under `Debug info:', select anything _other_ than `Program
\r
431 * Database for Edit and Continue'.
\r
433 #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
\r
434 #define crBeginState crBegin(s->crLine)
\r
435 #define crStateP(t, v) \
\r
437 if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
\r
439 #define crState(t) crStateP(t, ssh->t)
\r
440 #define crFinish(z) } *crLine = 0; return (z); }
\r
441 #define crFinishV } *crLine = 0; return; }
\r
442 #define crFinishFree(z) } sfree(s); return (z); }
\r
443 #define crFinishFreeV } sfree(s); return; }
\r
444 #define crReturn(z) \
\r
446 *crLine =__LINE__; return (z); case __LINE__:;\
\r
448 #define crReturnV \
\r
450 *crLine=__LINE__; return; case __LINE__:;\
\r
452 #define crStop(z) do{ *crLine = 0; return (z); }while(0)
\r
453 #define crStopV do{ *crLine = 0; return; }while(0)
\r
454 #define crWaitUntil(c) do { crReturn(0); } while (!(c))
\r
455 #define crWaitUntilV(c) do { crReturnV; } while (!(c))
\r
457 typedef struct ssh_tag *Ssh;
\r
460 static struct Packet *ssh1_pkt_init(int pkt_type);
\r
461 static struct Packet *ssh2_pkt_init(int pkt_type);
\r
462 static void ssh_pkt_ensure(struct Packet *, int length);
\r
463 static void ssh_pkt_adddata(struct Packet *, const void *data, int len);
\r
464 static void ssh_pkt_addbyte(struct Packet *, unsigned char value);
\r
465 static void ssh2_pkt_addbool(struct Packet *, unsigned char value);
\r
466 static void ssh_pkt_adduint32(struct Packet *, unsigned long value);
\r
467 static void ssh_pkt_addstring_start(struct Packet *);
\r
468 static void ssh_pkt_addstring_str(struct Packet *, const char *data);
\r
469 static void ssh_pkt_addstring_data(struct Packet *, const char *data, int len);
\r
470 static void ssh_pkt_addstring(struct Packet *, const char *data);
\r
471 static unsigned char *ssh2_mpint_fmt(Bignum b, int *len);
\r
472 static void ssh1_pkt_addmp(struct Packet *, Bignum b);
\r
473 static void ssh2_pkt_addmp(struct Packet *, Bignum b);
\r
474 static int ssh2_pkt_construct(Ssh, struct Packet *);
\r
475 static void ssh2_pkt_send(Ssh, struct Packet *);
\r
476 static void ssh2_pkt_send_noqueue(Ssh, struct Packet *);
\r
477 static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
\r
478 struct Packet *pktin);
\r
479 static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
\r
480 struct Packet *pktin);
\r
481 static void ssh2_channel_check_close(struct ssh_channel *c);
\r
482 static void ssh_channel_destroy(struct ssh_channel *c);
\r
485 * Buffer management constants. There are several of these for
\r
486 * various different purposes:
\r
488 * - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
\r
489 * on a local data stream before we throttle the whole SSH
\r
490 * connection (in SSH-1 only). Throttling the whole connection is
\r
491 * pretty drastic so we set this high in the hope it won't
\r
492 * happen very often.
\r
494 * - SSH_MAX_BACKLOG is the amount of backlog that must build up
\r
495 * on the SSH connection itself before we defensively throttle
\r
496 * _all_ local data streams. This is pretty drastic too (though
\r
497 * thankfully unlikely in SSH-2 since the window mechanism should
\r
498 * ensure that the server never has any need to throttle its end
\r
499 * of the connection), so we set this high as well.
\r
501 * - OUR_V2_WINSIZE is the maximum window size we present on SSH-2
\r
504 * - OUR_V2_BIGWIN is the window size we advertise for the only
\r
505 * channel in a simple connection. It must be <= INT_MAX.
\r
507 * - OUR_V2_MAXPKT is the official "maximum packet size" we send
\r
508 * to the remote side. This actually has nothing to do with the
\r
509 * size of the _packet_, but is instead a limit on the amount
\r
510 * of data we're willing to receive in a single SSH2 channel
\r
513 * - OUR_V2_PACKETLIMIT is actually the maximum size of SSH
\r
514 * _packet_ we're prepared to cope with. It must be a multiple
\r
515 * of the cipher block size, and must be at least 35000.
\r
518 #define SSH1_BUFFER_LIMIT 32768
\r
519 #define SSH_MAX_BACKLOG 32768
\r
520 #define OUR_V2_WINSIZE 16384
\r
521 #define OUR_V2_BIGWIN 0x7fffffff
\r
522 #define OUR_V2_MAXPKT 0x4000UL
\r
523 #define OUR_V2_PACKETLIMIT 0x9000UL
\r
525 const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss };
\r
527 const static struct ssh_mac *macs[] = {
\r
528 &ssh_hmac_sha256, &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5
\r
530 const static struct ssh_mac *buggymacs[] = {
\r
531 &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5
\r
534 static void *ssh_comp_none_init(void)
\r
538 static void ssh_comp_none_cleanup(void *handle)
\r
541 static int ssh_comp_none_block(void *handle, unsigned char *block, int len,
\r
542 unsigned char **outblock, int *outlen)
\r
546 static int ssh_comp_none_disable(void *handle)
\r
550 const static struct ssh_compress ssh_comp_none = {
\r
552 ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
\r
553 ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
\r
554 ssh_comp_none_disable, NULL
\r
556 extern const struct ssh_compress ssh_zlib;
\r
557 const static struct ssh_compress *compressions[] = {
\r
558 &ssh_zlib, &ssh_comp_none
\r
561 enum { /* channel types */
\r
566 CHAN_SOCKDATA_DORMANT, /* one the remote hasn't confirmed */
\r
568 * CHAN_ZOMBIE is used to indicate a channel for which we've
\r
569 * already destroyed the local data source: for instance, if a
\r
570 * forwarded port experiences a socket error on the local side, we
\r
571 * immediately destroy its local socket and turn the SSH channel
\r
572 * into CHAN_ZOMBIE.
\r
577 typedef void (*handler_fn_t)(Ssh ssh, struct Packet *pktin);
\r
578 typedef void (*chandler_fn_t)(Ssh ssh, struct Packet *pktin, void *ctx);
\r
579 typedef void (*cchandler_fn_t)(struct ssh_channel *, struct Packet *, void *);
\r
582 * Each channel has a queue of outstanding CHANNEL_REQUESTS and their
\r
585 struct outstanding_channel_request {
\r
586 cchandler_fn_t handler;
\r
588 struct outstanding_channel_request *next;
\r
592 * 2-3-4 tree storing channels.
\r
594 struct ssh_channel {
\r
595 Ssh ssh; /* pointer back to main context */
\r
596 unsigned remoteid, localid;
\r
598 /* True if we opened this channel but server hasn't confirmed. */
\r
601 * In SSH-1, this value contains four bits:
\r
603 * 1 We have sent SSH1_MSG_CHANNEL_CLOSE.
\r
604 * 2 We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
\r
605 * 4 We have received SSH1_MSG_CHANNEL_CLOSE.
\r
606 * 8 We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
\r
608 * A channel is completely finished with when all four bits are set.
\r
610 * In SSH-2, the four bits mean:
\r
612 * 1 We have sent SSH2_MSG_CHANNEL_EOF.
\r
613 * 2 We have sent SSH2_MSG_CHANNEL_CLOSE.
\r
614 * 4 We have received SSH2_MSG_CHANNEL_EOF.
\r
615 * 8 We have received SSH2_MSG_CHANNEL_CLOSE.
\r
617 * A channel is completely finished with when we have both sent
\r
618 * and received CLOSE.
\r
620 * The symbolic constants below use the SSH-2 terminology, which
\r
621 * is a bit confusing in SSH-1, but we have to use _something_.
\r
623 #define CLOSES_SENT_EOF 1
\r
624 #define CLOSES_SENT_CLOSE 2
\r
625 #define CLOSES_RCVD_EOF 4
\r
626 #define CLOSES_RCVD_CLOSE 8
\r
630 * This flag indicates that an EOF is pending on the outgoing side
\r
631 * of the channel: that is, wherever we're getting the data for
\r
632 * this channel has sent us some data followed by EOF. We can't
\r
633 * actually send the EOF until we've finished sending the data, so
\r
634 * we set this flag instead to remind us to do so once our buffer
\r
640 * True if this channel is causing the underlying connection to be
\r
643 int throttling_conn;
\r
645 struct ssh2_data_channel {
\r
646 bufchain outbuffer;
\r
647 unsigned remwindow, remmaxpkt;
\r
648 /* locwindow is signed so we can cope with excess data. */
\r
649 int locwindow, locmaxwin;
\r
651 * remlocwin is the amount of local window that we think
\r
652 * the remote end had available to it after it sent the
\r
653 * last data packet or window adjust ack.
\r
657 * These store the list of channel requests that haven't
\r
660 struct outstanding_channel_request *chanreq_head, *chanreq_tail;
\r
661 enum { THROTTLED, UNTHROTTLING, UNTHROTTLED } throttle_state;
\r
665 struct ssh_agent_channel {
\r
666 unsigned char *message;
\r
667 unsigned char msglen[4];
\r
668 unsigned lensofar, totallen;
\r
669 int outstanding_requests;
\r
671 struct ssh_x11_channel {
\r
674 struct ssh_pfd_channel {
\r
681 * 2-3-4 tree storing remote->local port forwardings. SSH-1 and SSH-2
\r
682 * use this structure in different ways, reflecting SSH-2's
\r
683 * altogether saner approach to port forwarding.
\r
685 * In SSH-1, you arrange a remote forwarding by sending the server
\r
686 * the remote port number, and the local destination host:port.
\r
687 * When a connection comes in, the server sends you back that
\r
688 * host:port pair, and you connect to it. This is a ready-made
\r
689 * security hole if you're not on the ball: a malicious server
\r
690 * could send you back _any_ host:port pair, so if you trustingly
\r
691 * connect to the address it gives you then you've just opened the
\r
692 * entire inside of your corporate network just by connecting
\r
693 * through it to a dodgy SSH server. Hence, we must store a list of
\r
694 * host:port pairs we _are_ trying to forward to, and reject a
\r
695 * connection request from the server if it's not in the list.
\r
697 * In SSH-2, each side of the connection minds its own business and
\r
698 * doesn't send unnecessary information to the other. You arrange a
\r
699 * remote forwarding by sending the server just the remote port
\r
700 * number. When a connection comes in, the server tells you which
\r
701 * of its ports was connected to; and _you_ have to remember what
\r
702 * local host:port pair went with that port number.
\r
704 * Hence, in SSH-1 this structure is indexed by destination
\r
705 * host:port pair, whereas in SSH-2 it is indexed by source port.
\r
707 struct ssh_portfwd; /* forward declaration */
\r
709 struct ssh_rportfwd {
\r
710 unsigned sport, dport;
\r
713 struct ssh_portfwd *pfrec;
\r
715 #define free_rportfwd(pf) ( \
\r
716 ((pf) ? (sfree((pf)->sportdesc)) : (void)0 ), sfree(pf) )
\r
719 * Separately to the rportfwd tree (which is for looking up port
\r
720 * open requests from the server), a tree of _these_ structures is
\r
721 * used to keep track of all the currently open port forwardings,
\r
722 * so that we can reconfigure in mid-session if the user requests
\r
725 struct ssh_portfwd {
\r
726 enum { DESTROY, KEEP, CREATE } status;
\r
728 unsigned sport, dport;
\r
729 char *saddr, *daddr;
\r
730 char *sserv, *dserv;
\r
731 struct ssh_rportfwd *remote;
\r
735 #define free_portfwd(pf) ( \
\r
736 ((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr), \
\r
737 sfree((pf)->sserv), sfree((pf)->dserv)) : (void)0 ), sfree(pf) )
\r
740 long length; /* length of `data' actually used */
\r
741 long forcepad; /* SSH-2: force padding to at least this length */
\r
742 int type; /* only used for incoming packets */
\r
743 unsigned long sequence; /* SSH-2 incoming sequence number */
\r
744 unsigned char *data; /* allocated storage */
\r
745 unsigned char *body; /* offset of payload within `data' */
\r
746 long savedpos; /* temporary index into `data' (for strings) */
\r
747 long maxlen; /* amount of storage allocated for `data' */
\r
748 long encrypted_len; /* for SSH-2 total-size counting */
\r
751 * State associated with packet logging
\r
755 struct logblank_t *blanks;
\r
758 static void ssh1_protocol(Ssh ssh, void *vin, int inlen,
\r
759 struct Packet *pktin);
\r
760 static void ssh2_protocol(Ssh ssh, void *vin, int inlen,
\r
761 struct Packet *pktin);
\r
762 static void ssh1_protocol_setup(Ssh ssh);
\r
763 static void ssh2_protocol_setup(Ssh ssh);
\r
764 static void ssh_size(void *handle, int width, int height);
\r
765 static void ssh_special(void *handle, Telnet_Special);
\r
766 static int ssh2_try_send(struct ssh_channel *c);
\r
767 static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);
\r
768 static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
\r
769 static void ssh2_set_window(struct ssh_channel *c, int newwin);
\r
770 static int ssh_sendbuffer(void *handle);
\r
771 static int ssh_do_close(Ssh ssh, int notify_exit);
\r
772 static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
\r
773 static int ssh2_pkt_getbool(struct Packet *pkt);
\r
774 static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);
\r
775 static void ssh2_timer(void *ctx, unsigned long now);
\r
776 static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
\r
777 struct Packet *pktin);
\r
778 static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin);
\r
780 struct rdpkt1_state_tag {
\r
781 long len, pad, biglen, to_read;
\r
782 unsigned long realcrc, gotcrc;
\r
786 struct Packet *pktin;
\r
789 struct rdpkt2_state_tag {
\r
790 long len, pad, payload, packetlen, maclen;
\r
793 unsigned long incoming_sequence;
\r
794 struct Packet *pktin;
\r
797 struct queued_handler;
\r
798 struct queued_handler {
\r
800 chandler_fn_t handler;
\r
802 struct queued_handler *next;
\r
806 const struct plug_function_table *fn;
\r
807 /* the above field _must_ be first in the structure */
\r
817 unsigned char session_key[32];
\r
818 int v1_compressing;
\r
819 int v1_remote_protoflags;
\r
820 int v1_local_protoflags;
\r
821 int agentfwd_enabled;
\r
822 int X11_fwd_enabled;
\r
824 const struct ssh_cipher *cipher;
\r
825 void *v1_cipher_ctx;
\r
827 const struct ssh2_cipher *cscipher, *sccipher;
\r
828 void *cs_cipher_ctx, *sc_cipher_ctx;
\r
829 const struct ssh_mac *csmac, *scmac;
\r
830 void *cs_mac_ctx, *sc_mac_ctx;
\r
831 const struct ssh_compress *cscomp, *sccomp;
\r
832 void *cs_comp_ctx, *sc_comp_ctx;
\r
833 const struct ssh_kex *kex;
\r
834 const struct ssh_signkey *hostkey;
\r
835 unsigned char v2_session_id[SSH2_KEX_MAX_HASH_LEN];
\r
836 int v2_session_id_len;
\r
842 int echoing, editing;
\r
846 int ospeed, ispeed; /* temporaries */
\r
847 int term_width, term_height;
\r
849 tree234 *channels; /* indexed by local id */
\r
850 struct ssh_channel *mainchan; /* primary session channel */
\r
851 int ncmode; /* is primary channel direct-tcpip? */
\r
853 int close_expected;
\r
856 tree234 *rportfwds, *portfwds;
\r
859 SSH_STATE_PREPACKET,
\r
860 SSH_STATE_BEFORE_SIZE,
\r
861 SSH_STATE_INTERMED,
\r
866 int size_needed, eof_needed;
\r
867 int sent_console_eof;
\r
868 int got_pty; /* affects EOF behaviour on main channel */
\r
870 struct Packet **queue;
\r
871 int queuelen, queuesize;
\r
873 unsigned char *deferred_send_data;
\r
874 int deferred_len, deferred_size;
\r
877 * Gross hack: pscp will try to start SFTP but fall back to
\r
878 * scp1 if that fails. This variable is the means by which
\r
879 * scp.c can reach into the SSH code and find out which one it
\r
884 bufchain banner; /* accumulates banners during do_ssh2_authconn */
\r
889 struct X11Display *x11disp;
\r
892 int conn_throttle_count;
\r
893 int overall_bufsize;
\r
895 int v1_stdout_throttling;
\r
896 unsigned long v2_outgoing_sequence;
\r
898 int ssh1_rdpkt_crstate;
\r
899 int ssh2_rdpkt_crstate;
\r
900 int ssh_gotdata_crstate;
\r
901 int do_ssh1_connection_crstate;
\r
903 void *do_ssh_init_state;
\r
904 void *do_ssh1_login_state;
\r
905 void *do_ssh2_transport_state;
\r
906 void *do_ssh2_authconn_state;
\r
908 struct rdpkt1_state_tag rdpkt1_state;
\r
909 struct rdpkt2_state_tag rdpkt2_state;
\r
911 /* SSH-1 and SSH-2 use this for different things, but both use it */
\r
912 int protocol_initial_phase_done;
\r
914 void (*protocol) (Ssh ssh, void *vin, int inlen,
\r
915 struct Packet *pkt);
\r
916 struct Packet *(*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
\r
919 * We maintain our own copy of a Conf structure here. That way,
\r
920 * when we're passed a new one for reconfiguration, we can check
\r
921 * the differences and potentially reconfigure port forwardings
\r
922 * etc in mid-session.
\r
927 * Values cached out of conf so as to avoid the tree234 lookup
\r
928 * cost every time they're used.
\r
933 * Dynamically allocated username string created during SSH
\r
934 * login. Stored in here rather than in the coroutine state so
\r
935 * that it'll be reliably freed if we shut down the SSH session
\r
936 * at some unexpected moment.
\r
941 * Used to transfer data back from async callbacks.
\r
943 void *agent_response;
\r
944 int agent_response_len;
\r
948 * The SSH connection can be set as `frozen', meaning we are
\r
949 * not currently accepting incoming data from the network. This
\r
950 * is slightly more serious than setting the _socket_ as
\r
951 * frozen, because we may already have had data passed to us
\r
952 * from the network which we need to delay processing until
\r
953 * after the freeze is lifted, so we also need a bufchain to
\r
957 bufchain queued_incoming_data;
\r
960 * Dispatch table for packet types that we may have to deal
\r
961 * with at any time.
\r
963 handler_fn_t packet_dispatch[256];
\r
966 * Queues of one-off handler functions for success/failure
\r
967 * indications from a request.
\r
969 struct queued_handler *qhead, *qtail;
\r
970 handler_fn_t q_saved_handler1, q_saved_handler2;
\r
973 * This module deals with sending keepalives.
\r
978 * Track incoming and outgoing data sizes and time, for
\r
979 * size-based rekeys.
\r
981 unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
\r
982 unsigned long max_data_size;
\r
983 int kex_in_progress;
\r
984 unsigned long next_rekey, last_rekey;
\r
985 char *deferred_rekey_reason; /* points to STATIC string; don't free */
\r
988 * Fully qualified host name, which we need if doing GSSAPI.
\r
990 char *fullhostname;
\r
994 * GSSAPI libraries for this session.
\r
996 struct ssh_gss_liblist *gsslibs;
\r
1000 #define logevent(s) logevent(ssh->frontend, s)
\r
1002 /* logevent, only printf-formatted. */
\r
1003 static void logeventf(Ssh ssh, const char *fmt, ...)
\r
1008 va_start(ap, fmt);
\r
1009 buf = dupvprintf(fmt, ap);
\r
1015 static void bomb_out(Ssh ssh, char *text)
\r
1017 ssh_do_close(ssh, FALSE);
\r
1019 connection_fatal(ssh->frontend, "%s", text);
\r
1023 #define bombout(msg) bomb_out(ssh, dupprintf msg)
\r
1025 /* Functions to leave bits out of the SSH packet log file. */
\r
1027 static void dont_log_password(Ssh ssh, struct Packet *pkt, int blanktype)
\r
1029 if (conf_get_int(ssh->conf, CONF_logomitpass))
\r
1030 pkt->logmode = blanktype;
\r
1033 static void dont_log_data(Ssh ssh, struct Packet *pkt, int blanktype)
\r
1035 if (ssh->logomitdata)
\r
1036 pkt->logmode = blanktype;
\r
1039 static void end_log_omission(Ssh ssh, struct Packet *pkt)
\r
1041 pkt->logmode = PKTLOG_EMIT;
\r
1044 /* Helper function for common bits of parsing ttymodes. */
\r
1045 static void parse_ttymodes(Ssh ssh,
\r
1046 void (*do_mode)(void *data, char *mode, char *val),
\r
1051 for (val = conf_get_str_strs(ssh->conf, CONF_ttymodes, NULL, &key);
\r
1053 val = conf_get_str_strs(ssh->conf, CONF_ttymodes, key, &key)) {
\r
1055 * val[0] is either 'V', indicating that an explicit value
\r
1056 * follows it, or 'A' indicating that we should pass the
\r
1057 * value through from the local environment via get_ttymode.
\r
1059 if (val[0] == 'A') {
\r
1060 val = get_ttymode(ssh->frontend, key);
\r
1062 do_mode(data, key, val);
\r
1066 do_mode(data, key, val + 1); /* skip the 'V' */
\r
1070 static int ssh_channelcmp(void *av, void *bv)
\r
1072 struct ssh_channel *a = (struct ssh_channel *) av;
\r
1073 struct ssh_channel *b = (struct ssh_channel *) bv;
\r
1074 if (a->localid < b->localid)
\r
1076 if (a->localid > b->localid)
\r
1080 static int ssh_channelfind(void *av, void *bv)
\r
1082 unsigned *a = (unsigned *) av;
\r
1083 struct ssh_channel *b = (struct ssh_channel *) bv;
\r
1084 if (*a < b->localid)
\r
1086 if (*a > b->localid)
\r
1091 static int ssh_rportcmp_ssh1(void *av, void *bv)
\r
1093 struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;
\r
1094 struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
\r
1096 if ( (i = strcmp(a->dhost, b->dhost)) != 0)
\r
1097 return i < 0 ? -1 : +1;
\r
1098 if (a->dport > b->dport)
\r
1100 if (a->dport < b->dport)
\r
1105 static int ssh_rportcmp_ssh2(void *av, void *bv)
\r
1107 struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;
\r
1108 struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
\r
1110 if (a->sport > b->sport)
\r
1112 if (a->sport < b->sport)
\r
1118 * Special form of strcmp which can cope with NULL inputs. NULL is
\r
1119 * defined to sort before even the empty string.
\r
1121 static int nullstrcmp(const char *a, const char *b)
\r
1123 if (a == NULL && b == NULL)
\r
1129 return strcmp(a, b);
\r
1132 static int ssh_portcmp(void *av, void *bv)
\r
1134 struct ssh_portfwd *a = (struct ssh_portfwd *) av;
\r
1135 struct ssh_portfwd *b = (struct ssh_portfwd *) bv;
\r
1137 if (a->type > b->type)
\r
1139 if (a->type < b->type)
\r
1141 if (a->addressfamily > b->addressfamily)
\r
1143 if (a->addressfamily < b->addressfamily)
\r
1145 if ( (i = nullstrcmp(a->saddr, b->saddr)) != 0)
\r
1146 return i < 0 ? -1 : +1;
\r
1147 if (a->sport > b->sport)
\r
1149 if (a->sport < b->sport)
\r
1151 if (a->type != 'D') {
\r
1152 if ( (i = nullstrcmp(a->daddr, b->daddr)) != 0)
\r
1153 return i < 0 ? -1 : +1;
\r
1154 if (a->dport > b->dport)
\r
1156 if (a->dport < b->dport)
\r
1162 static int alloc_channel_id(Ssh ssh)
\r
1164 const unsigned CHANNEL_NUMBER_OFFSET = 256;
\r
1165 unsigned low, high, mid;
\r
1167 struct ssh_channel *c;
\r
1170 * First-fit allocation of channel numbers: always pick the
\r
1171 * lowest unused one. To do this, binary-search using the
\r
1172 * counted B-tree to find the largest channel ID which is in a
\r
1173 * contiguous sequence from the beginning. (Precisely
\r
1174 * everything in that sequence must have ID equal to its tree
\r
1175 * index plus CHANNEL_NUMBER_OFFSET.)
\r
1177 tsize = count234(ssh->channels);
\r
1181 while (high - low > 1) {
\r
1182 mid = (high + low) / 2;
\r
1183 c = index234(ssh->channels, mid);
\r
1184 if (c->localid == mid + CHANNEL_NUMBER_OFFSET)
\r
1185 low = mid; /* this one is fine */
\r
1187 high = mid; /* this one is past it */
\r
1190 * Now low points to either -1, or the tree index of the
\r
1191 * largest ID in the initial sequence.
\r
1194 unsigned i = low + 1 + CHANNEL_NUMBER_OFFSET;
\r
1195 assert(NULL == find234(ssh->channels, &i, ssh_channelfind));
\r
1197 return low + 1 + CHANNEL_NUMBER_OFFSET;
\r
1200 static void c_write_stderr(int trusted, const char *buf, int len)
\r
1203 for (i = 0; i < len; i++)
\r
1204 if (buf[i] != '\r' && (trusted || buf[i] == '\n' || (buf[i] & 0x60)))
\r
1205 fputc(buf[i], stderr);
\r
1208 static void c_write(Ssh ssh, const char *buf, int len)
\r
1210 if (flags & FLAG_STDERR)
\r
1211 c_write_stderr(1, buf, len);
\r
1213 from_backend(ssh->frontend, 1, buf, len);
\r
1216 static void c_write_untrusted(Ssh ssh, const char *buf, int len)
\r
1218 if (flags & FLAG_STDERR)
\r
1219 c_write_stderr(0, buf, len);
\r
1221 from_backend_untrusted(ssh->frontend, buf, len);
\r
1224 static void c_write_str(Ssh ssh, const char *buf)
\r
1226 c_write(ssh, buf, strlen(buf));
\r
1229 static void ssh_free_packet(struct Packet *pkt)
\r
1234 static struct Packet *ssh_new_packet(void)
\r
1236 struct Packet *pkt = snew(struct Packet);
\r
1238 pkt->body = pkt->data = NULL;
\r
1240 pkt->logmode = PKTLOG_EMIT;
\r
1242 pkt->blanks = NULL;
\r
1248 * Collect incoming data in the incoming packet buffer.
\r
1249 * Decipher and verify the packet when it is completely read.
\r
1250 * Drop SSH1_MSG_DEBUG and SSH1_MSG_IGNORE packets.
\r
1251 * Update the *data and *datalen variables.
\r
1252 * Return a Packet structure when a packet is completed.
\r
1254 static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
\r
1256 struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;
\r
1258 crBegin(ssh->ssh1_rdpkt_crstate);
\r
1260 st->pktin = ssh_new_packet();
\r
1262 st->pktin->type = 0;
\r
1263 st->pktin->length = 0;
\r
1265 for (st->i = st->len = 0; st->i < 4; st->i++) {
\r
1266 while ((*datalen) == 0)
\r
1268 st->len = (st->len << 8) + **data;
\r
1269 (*data)++, (*datalen)--;
\r
1272 st->pad = 8 - (st->len % 8);
\r
1273 st->biglen = st->len + st->pad;
\r
1274 st->pktin->length = st->len - 5;
\r
1276 if (st->biglen < 0) {
\r
1277 bombout(("Extremely large packet length from server suggests"
\r
1278 " data stream corruption"));
\r
1279 ssh_free_packet(st->pktin);
\r
1283 st->pktin->maxlen = st->biglen;
\r
1284 st->pktin->data = snewn(st->biglen + APIEXTRA, unsigned char);
\r
1286 st->to_read = st->biglen;
\r
1287 st->p = st->pktin->data;
\r
1288 while (st->to_read > 0) {
\r
1289 st->chunk = st->to_read;
\r
1290 while ((*datalen) == 0)
\r
1292 if (st->chunk > (*datalen))
\r
1293 st->chunk = (*datalen);
\r
1294 memcpy(st->p, *data, st->chunk);
\r
1295 *data += st->chunk;
\r
1296 *datalen -= st->chunk;
\r
1297 st->p += st->chunk;
\r
1298 st->to_read -= st->chunk;
\r
1301 if (ssh->cipher && detect_attack(ssh->crcda_ctx, st->pktin->data,
\r
1302 st->biglen, NULL)) {
\r
1303 bombout(("Network attack (CRC compensation) detected!"));
\r
1304 ssh_free_packet(st->pktin);
\r
1309 ssh->cipher->decrypt(ssh->v1_cipher_ctx, st->pktin->data, st->biglen);
\r
1311 st->realcrc = crc32_compute(st->pktin->data, st->biglen - 4);
\r
1312 st->gotcrc = GET_32BIT(st->pktin->data + st->biglen - 4);
\r
1313 if (st->gotcrc != st->realcrc) {
\r
1314 bombout(("Incorrect CRC received on packet"));
\r
1315 ssh_free_packet(st->pktin);
\r
1319 st->pktin->body = st->pktin->data + st->pad + 1;
\r
1320 st->pktin->savedpos = 0;
\r
1322 if (ssh->v1_compressing) {
\r
1323 unsigned char *decompblk;
\r
1325 if (!zlib_decompress_block(ssh->sc_comp_ctx,
\r
1326 st->pktin->body - 1, st->pktin->length + 1,
\r
1327 &decompblk, &decomplen)) {
\r
1328 bombout(("Zlib decompression encountered invalid data"));
\r
1329 ssh_free_packet(st->pktin);
\r
1333 if (st->pktin->maxlen < st->pad + decomplen) {
\r
1334 st->pktin->maxlen = st->pad + decomplen;
\r
1335 st->pktin->data = sresize(st->pktin->data,
\r
1336 st->pktin->maxlen + APIEXTRA,
\r
1338 st->pktin->body = st->pktin->data + st->pad + 1;
\r
1341 memcpy(st->pktin->body - 1, decompblk, decomplen);
\r
1343 st->pktin->length = decomplen - 1;
\r
1346 st->pktin->type = st->pktin->body[-1];
\r
1349 * Log incoming packet, possibly omitting sensitive fields.
\r
1351 if (ssh->logctx) {
\r
1353 struct logblank_t blank;
\r
1354 if (ssh->logomitdata) {
\r
1355 int do_blank = FALSE, blank_prefix = 0;
\r
1356 /* "Session data" packets - omit the data field */
\r
1357 if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||
\r
1358 (st->pktin->type == SSH1_SMSG_STDERR_DATA)) {
\r
1359 do_blank = TRUE; blank_prefix = 4;
\r
1360 } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {
\r
1361 do_blank = TRUE; blank_prefix = 8;
\r
1364 blank.offset = blank_prefix;
\r
1365 blank.len = st->pktin->length;
\r
1366 blank.type = PKTLOG_OMIT;
\r
1370 log_packet(ssh->logctx,
\r
1371 PKT_INCOMING, st->pktin->type,
\r
1372 ssh1_pkt_type(st->pktin->type),
\r
1373 st->pktin->body, st->pktin->length,
\r
1374 nblanks, &blank, NULL);
\r
1377 crFinish(st->pktin);
\r
1380 static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
\r
1382 struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;
\r
1384 crBegin(ssh->ssh2_rdpkt_crstate);
\r
1386 st->pktin = ssh_new_packet();
\r
1388 st->pktin->type = 0;
\r
1389 st->pktin->length = 0;
\r
1390 if (ssh->sccipher)
\r
1391 st->cipherblk = ssh->sccipher->blksize;
\r
1393 st->cipherblk = 8;
\r
1394 if (st->cipherblk < 8)
\r
1395 st->cipherblk = 8;
\r
1396 st->maclen = ssh->scmac ? ssh->scmac->len : 0;
\r
1398 if (ssh->sccipher && (ssh->sccipher->flags & SSH_CIPHER_IS_CBC) &&
\r
1401 * When dealing with a CBC-mode cipher, we want to avoid the
\r
1402 * possibility of an attacker's tweaking the ciphertext stream
\r
1403 * so as to cause us to feed the same block to the block
\r
1404 * cipher more than once and thus leak information
\r
1405 * (VU#958563). The way we do this is not to take any
\r
1406 * decisions on the basis of anything we've decrypted until
\r
1407 * we've verified it with a MAC. That includes the packet
\r
1408 * length, so we just read data and check the MAC repeatedly,
\r
1409 * and when the MAC passes, see if the length we've got is
\r
1413 /* May as well allocate the whole lot now. */
\r
1414 st->pktin->data = snewn(OUR_V2_PACKETLIMIT + st->maclen + APIEXTRA,
\r
1417 /* Read an amount corresponding to the MAC. */
\r
1418 for (st->i = 0; st->i < st->maclen; st->i++) {
\r
1419 while ((*datalen) == 0)
\r
1421 st->pktin->data[st->i] = *(*data)++;
\r
1425 st->packetlen = 0;
\r
1427 unsigned char seq[4];
\r
1428 ssh->scmac->start(ssh->sc_mac_ctx);
\r
1429 PUT_32BIT(seq, st->incoming_sequence);
\r
1430 ssh->scmac->bytes(ssh->sc_mac_ctx, seq, 4);
\r
1433 for (;;) { /* Once around this loop per cipher block. */
\r
1434 /* Read another cipher-block's worth, and tack it onto the end. */
\r
1435 for (st->i = 0; st->i < st->cipherblk; st->i++) {
\r
1436 while ((*datalen) == 0)
\r
1438 st->pktin->data[st->packetlen+st->maclen+st->i] = *(*data)++;
\r
1441 /* Decrypt one more block (a little further back in the stream). */
\r
1442 ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
\r
1443 st->pktin->data + st->packetlen,
\r
1445 /* Feed that block to the MAC. */
\r
1446 ssh->scmac->bytes(ssh->sc_mac_ctx,
\r
1447 st->pktin->data + st->packetlen, st->cipherblk);
\r
1448 st->packetlen += st->cipherblk;
\r
1449 /* See if that gives us a valid packet. */
\r
1450 if (ssh->scmac->verresult(ssh->sc_mac_ctx,
\r
1451 st->pktin->data + st->packetlen) &&
\r
1452 ((st->len = toint(GET_32BIT(st->pktin->data))) ==
\r
1455 if (st->packetlen >= OUR_V2_PACKETLIMIT) {
\r
1456 bombout(("No valid incoming packet found"));
\r
1457 ssh_free_packet(st->pktin);
\r
1461 st->pktin->maxlen = st->packetlen + st->maclen;
\r
1462 st->pktin->data = sresize(st->pktin->data,
\r
1463 st->pktin->maxlen + APIEXTRA,
\r
1466 st->pktin->data = snewn(st->cipherblk + APIEXTRA, unsigned char);
\r
1469 * Acquire and decrypt the first block of the packet. This will
\r
1470 * contain the length and padding details.
\r
1472 for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {
\r
1473 while ((*datalen) == 0)
\r
1475 st->pktin->data[st->i] = *(*data)++;
\r
1479 if (ssh->sccipher)
\r
1480 ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
\r
1481 st->pktin->data, st->cipherblk);
\r
1484 * Now get the length figure.
\r
1486 st->len = toint(GET_32BIT(st->pktin->data));
\r
1489 * _Completely_ silly lengths should be stomped on before they
\r
1490 * do us any more damage.
\r
1492 if (st->len < 0 || st->len > OUR_V2_PACKETLIMIT ||
\r
1493 (st->len + 4) % st->cipherblk != 0) {
\r
1494 bombout(("Incoming packet was garbled on decryption"));
\r
1495 ssh_free_packet(st->pktin);
\r
1500 * So now we can work out the total packet length.
\r
1502 st->packetlen = st->len + 4;
\r
1505 * Allocate memory for the rest of the packet.
\r
1507 st->pktin->maxlen = st->packetlen + st->maclen;
\r
1508 st->pktin->data = sresize(st->pktin->data,
\r
1509 st->pktin->maxlen + APIEXTRA,
\r
1513 * Read and decrypt the remainder of the packet.
\r
1515 for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;
\r
1517 while ((*datalen) == 0)
\r
1519 st->pktin->data[st->i] = *(*data)++;
\r
1522 /* Decrypt everything _except_ the MAC. */
\r
1523 if (ssh->sccipher)
\r
1524 ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
\r
1525 st->pktin->data + st->cipherblk,
\r
1526 st->packetlen - st->cipherblk);
\r
1532 && !ssh->scmac->verify(ssh->sc_mac_ctx, st->pktin->data,
\r
1533 st->len + 4, st->incoming_sequence)) {
\r
1534 bombout(("Incorrect MAC received on packet"));
\r
1535 ssh_free_packet(st->pktin);
\r
1539 /* Get and sanity-check the amount of random padding. */
\r
1540 st->pad = st->pktin->data[4];
\r
1541 if (st->pad < 4 || st->len - st->pad < 1) {
\r
1542 bombout(("Invalid padding length on received packet"));
\r
1543 ssh_free_packet(st->pktin);
\r
1547 * This enables us to deduce the payload length.
\r
1549 st->payload = st->len - st->pad - 1;
\r
1551 st->pktin->length = st->payload + 5;
\r
1552 st->pktin->encrypted_len = st->packetlen;
\r
1554 st->pktin->sequence = st->incoming_sequence++;
\r
1557 * Decompress packet payload.
\r
1560 unsigned char *newpayload;
\r
1562 if (ssh->sccomp &&
\r
1563 ssh->sccomp->decompress(ssh->sc_comp_ctx,
\r
1564 st->pktin->data + 5, st->pktin->length - 5,
\r
1565 &newpayload, &newlen)) {
\r
1566 if (st->pktin->maxlen < newlen + 5) {
\r
1567 st->pktin->maxlen = newlen + 5;
\r
1568 st->pktin->data = sresize(st->pktin->data,
\r
1569 st->pktin->maxlen + APIEXTRA,
\r
1572 st->pktin->length = 5 + newlen;
\r
1573 memcpy(st->pktin->data + 5, newpayload, newlen);
\r
1574 sfree(newpayload);
\r
1578 st->pktin->savedpos = 6;
\r
1579 st->pktin->body = st->pktin->data;
\r
1580 st->pktin->type = st->pktin->data[5];
\r
1583 * Log incoming packet, possibly omitting sensitive fields.
\r
1585 if (ssh->logctx) {
\r
1587 struct logblank_t blank;
\r
1588 if (ssh->logomitdata) {
\r
1589 int do_blank = FALSE, blank_prefix = 0;
\r
1590 /* "Session data" packets - omit the data field */
\r
1591 if (st->pktin->type == SSH2_MSG_CHANNEL_DATA) {
\r
1592 do_blank = TRUE; blank_prefix = 8;
\r
1593 } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
\r
1594 do_blank = TRUE; blank_prefix = 12;
\r
1597 blank.offset = blank_prefix;
\r
1598 blank.len = (st->pktin->length-6) - blank_prefix;
\r
1599 blank.type = PKTLOG_OMIT;
\r
1603 log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,
\r
1604 ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
\r
1606 st->pktin->data+6, st->pktin->length-6,
\r
1607 nblanks, &blank, &st->pktin->sequence);
\r
1610 crFinish(st->pktin);
\r
1613 static int s_wrpkt_prepare(Ssh ssh, struct Packet *pkt, int *offset_p)
\r
1615 int pad, biglen, i, pktoffs;
\r
1616 unsigned long crc;
\r
1619 * XXX various versions of SC (including 8.8.4) screw up the
\r
1620 * register allocation in this function and use the same register
\r
1621 * (D6) for len and as a temporary, with predictable results. The
\r
1622 * following sledgehammer prevents this.
\r
1629 log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[12],
\r
1630 ssh1_pkt_type(pkt->data[12]),
\r
1631 pkt->body, pkt->length - (pkt->body - pkt->data),
\r
1632 pkt->nblanks, pkt->blanks, NULL);
\r
1633 sfree(pkt->blanks); pkt->blanks = NULL;
\r
1636 if (ssh->v1_compressing) {
\r
1637 unsigned char *compblk;
\r
1639 zlib_compress_block(ssh->cs_comp_ctx,
\r
1640 pkt->data + 12, pkt->length - 12,
\r
1641 &compblk, &complen);
\r
1642 ssh_pkt_ensure(pkt, complen + 2); /* just in case it's got bigger */
\r
1643 memcpy(pkt->data + 12, compblk, complen);
\r
1645 pkt->length = complen + 12;
\r
1648 ssh_pkt_ensure(pkt, pkt->length + 4); /* space for CRC */
\r
1650 len = pkt->length - 4 - 8; /* len(type+data+CRC) */
\r
1651 pad = 8 - (len % 8);
\r
1652 pktoffs = 8 - pad;
\r
1653 biglen = len + pad; /* len(padding+type+data+CRC) */
\r
1655 for (i = pktoffs; i < 4+8; i++)
\r
1656 pkt->data[i] = random_byte();
\r
1657 crc = crc32_compute(pkt->data + pktoffs + 4, biglen - 4); /* all ex len */
\r
1658 PUT_32BIT(pkt->data + pktoffs + 4 + biglen - 4, crc);
\r
1659 PUT_32BIT(pkt->data + pktoffs, len);
\r
1662 ssh->cipher->encrypt(ssh->v1_cipher_ctx,
\r
1663 pkt->data + pktoffs + 4, biglen);
\r
1665 if (offset_p) *offset_p = pktoffs;
\r
1666 return biglen + 4; /* len(length+padding+type+data+CRC) */
\r
1669 static int s_write(Ssh ssh, void *data, int len)
\r
1672 log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len,
\r
1674 return sk_write(ssh->s, (char *)data, len);
\r
1677 static void s_wrpkt(Ssh ssh, struct Packet *pkt)
\r
1679 int len, backlog, offset;
\r
1680 len = s_wrpkt_prepare(ssh, pkt, &offset);
\r
1681 backlog = s_write(ssh, pkt->data + offset, len);
\r
1682 if (backlog > SSH_MAX_BACKLOG)
\r
1683 ssh_throttle_all(ssh, 1, backlog);
\r
1684 ssh_free_packet(pkt);
\r
1687 static void s_wrpkt_defer(Ssh ssh, struct Packet *pkt)
\r
1690 len = s_wrpkt_prepare(ssh, pkt, &offset);
\r
1691 if (ssh->deferred_len + len > ssh->deferred_size) {
\r
1692 ssh->deferred_size = ssh->deferred_len + len + 128;
\r
1693 ssh->deferred_send_data = sresize(ssh->deferred_send_data,
\r
1694 ssh->deferred_size,
\r
1697 memcpy(ssh->deferred_send_data + ssh->deferred_len,
\r
1698 pkt->data + offset, len);
\r
1699 ssh->deferred_len += len;
\r
1700 ssh_free_packet(pkt);
\r
1704 * Construct a SSH-1 packet with the specified contents.
\r
1705 * (This all-at-once interface used to be the only one, but now SSH-1
\r
1706 * packets can also be constructed incrementally.)
\r
1708 static struct Packet *construct_packet(Ssh ssh, int pkttype, va_list ap)
\r
1712 struct Packet *pkt;
\r
1714 pkt = ssh1_pkt_init(pkttype);
\r
1716 while ((argtype = va_arg(ap, int)) != PKT_END) {
\r
1717 unsigned char *argp, argchar;
\r
1719 unsigned long argint;
\r
1721 switch (argtype) {
\r
1722 /* Actual fields in the packet */
\r
1724 argint = va_arg(ap, int);
\r
1725 ssh_pkt_adduint32(pkt, argint);
\r
1728 argchar = (unsigned char) va_arg(ap, int);
\r
1729 ssh_pkt_addbyte(pkt, argchar);
\r
1732 argp = va_arg(ap, unsigned char *);
\r
1733 arglen = va_arg(ap, int);
\r
1734 ssh_pkt_adddata(pkt, argp, arglen);
\r
1737 sargp = va_arg(ap, char *);
\r
1738 ssh_pkt_addstring(pkt, sargp);
\r
1741 bn = va_arg(ap, Bignum);
\r
1742 ssh1_pkt_addmp(pkt, bn);
\r
1744 /* Tokens for modifications to packet logging */
\r
1745 case PKTT_PASSWORD:
\r
1746 dont_log_password(ssh, pkt, PKTLOG_BLANK);
\r
1749 dont_log_data(ssh, pkt, PKTLOG_OMIT);
\r
1752 end_log_omission(ssh, pkt);
\r
1760 static void send_packet(Ssh ssh, int pkttype, ...)
\r
1762 struct Packet *pkt;
\r
1764 va_start(ap, pkttype);
\r
1765 pkt = construct_packet(ssh, pkttype, ap);
\r
1767 s_wrpkt(ssh, pkt);
\r
1770 static void defer_packet(Ssh ssh, int pkttype, ...)
\r
1772 struct Packet *pkt;
\r
1774 va_start(ap, pkttype);
\r
1775 pkt = construct_packet(ssh, pkttype, ap);
\r
1777 s_wrpkt_defer(ssh, pkt);
\r
1780 static int ssh_versioncmp(char *a, char *b)
\r
1783 unsigned long av, bv;
\r
1785 av = strtoul(a, &ae, 10);
\r
1786 bv = strtoul(b, &be, 10);
\r
1788 return (av < bv ? -1 : +1);
\r
1793 av = strtoul(ae, &ae, 10);
\r
1794 bv = strtoul(be, &be, 10);
\r
1796 return (av < bv ? -1 : +1);
\r
1801 * Utility routines for putting an SSH-protocol `string' and
\r
1802 * `uint32' into a hash state.
\r
1804 static void hash_string(const struct ssh_hash *h, void *s, void *str, int len)
\r
1806 unsigned char lenblk[4];
\r
1807 PUT_32BIT(lenblk, len);
\r
1808 h->bytes(s, lenblk, 4);
\r
1809 h->bytes(s, str, len);
\r
1812 static void hash_uint32(const struct ssh_hash *h, void *s, unsigned i)
\r
1814 unsigned char intblk[4];
\r
1815 PUT_32BIT(intblk, i);
\r
1816 h->bytes(s, intblk, 4);
\r
1820 * Packet construction functions. Mostly shared between SSH-1 and SSH-2.
\r
1822 static void ssh_pkt_ensure(struct Packet *pkt, int length)
\r
1824 if (pkt->maxlen < length) {
\r
1825 unsigned char *body = pkt->body;
\r
1826 int offset = body ? body - pkt->data : 0;
\r
1827 pkt->maxlen = length + 256;
\r
1828 pkt->data = sresize(pkt->data, pkt->maxlen + APIEXTRA, unsigned char);
\r
1829 if (body) pkt->body = pkt->data + offset;
\r
1832 static void ssh_pkt_adddata(struct Packet *pkt, const void *data, int len)
\r
1834 if (pkt->logmode != PKTLOG_EMIT) {
\r
1836 pkt->blanks = sresize(pkt->blanks, pkt->nblanks, struct logblank_t);
\r
1837 assert(pkt->body);
\r
1838 pkt->blanks[pkt->nblanks-1].offset = pkt->length -
\r
1839 (pkt->body - pkt->data);
\r
1840 pkt->blanks[pkt->nblanks-1].len = len;
\r
1841 pkt->blanks[pkt->nblanks-1].type = pkt->logmode;
\r
1843 pkt->length += len;
\r
1844 ssh_pkt_ensure(pkt, pkt->length);
\r
1845 memcpy(pkt->data + pkt->length - len, data, len);
\r
1847 static void ssh_pkt_addbyte(struct Packet *pkt, unsigned char byte)
\r
1849 ssh_pkt_adddata(pkt, &byte, 1);
\r
1851 static void ssh2_pkt_addbool(struct Packet *pkt, unsigned char value)
\r
1853 ssh_pkt_adddata(pkt, &value, 1);
\r
1855 static void ssh_pkt_adduint32(struct Packet *pkt, unsigned long value)
\r
1857 unsigned char x[4];
\r
1858 PUT_32BIT(x, value);
\r
1859 ssh_pkt_adddata(pkt, x, 4);
\r
1861 static void ssh_pkt_addstring_start(struct Packet *pkt)
\r
1863 ssh_pkt_adduint32(pkt, 0);
\r
1864 pkt->savedpos = pkt->length;
\r
1866 static void ssh_pkt_addstring_str(struct Packet *pkt, const char *data)
\r
1868 ssh_pkt_adddata(pkt, data, strlen(data));
\r
1869 PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
\r
1871 static void ssh_pkt_addstring_data(struct Packet *pkt, const char *data,
\r
1874 ssh_pkt_adddata(pkt, data, len);
\r
1875 PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
\r
1877 static void ssh_pkt_addstring(struct Packet *pkt, const char *data)
\r
1879 ssh_pkt_addstring_start(pkt);
\r
1880 ssh_pkt_addstring_str(pkt, data);
\r
1882 static void ssh1_pkt_addmp(struct Packet *pkt, Bignum b)
\r
1884 int len = ssh1_bignum_length(b);
\r
1885 unsigned char *data = snewn(len, unsigned char);
\r
1886 (void) ssh1_write_bignum(data, b);
\r
1887 ssh_pkt_adddata(pkt, data, len);
\r
1890 static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
\r
1893 int i, n = (bignum_bitcount(b) + 7) / 8;
\r
1894 p = snewn(n + 1, unsigned char);
\r
1896 for (i = 1; i <= n; i++)
\r
1897 p[i] = bignum_byte(b, n - i);
\r
1899 while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)
\r
1901 memmove(p, p + i, n + 1 - i);
\r
1905 static void ssh2_pkt_addmp(struct Packet *pkt, Bignum b)
\r
1909 p = ssh2_mpint_fmt(b, &len);
\r
1910 ssh_pkt_addstring_start(pkt);
\r
1911 ssh_pkt_addstring_data(pkt, (char *)p, len);
\r
1915 static struct Packet *ssh1_pkt_init(int pkt_type)
\r
1917 struct Packet *pkt = ssh_new_packet();
\r
1918 pkt->length = 4 + 8; /* space for length + max padding */
\r
1919 ssh_pkt_addbyte(pkt, pkt_type);
\r
1920 pkt->body = pkt->data + pkt->length;
\r
1924 /* For legacy code (SSH-1 and -2 packet construction used to be separate) */
\r
1925 #define ssh2_pkt_ensure(pkt, length) ssh_pkt_ensure(pkt, length)
\r
1926 #define ssh2_pkt_adddata(pkt, data, len) ssh_pkt_adddata(pkt, data, len)
\r
1927 #define ssh2_pkt_addbyte(pkt, byte) ssh_pkt_addbyte(pkt, byte)
\r
1928 #define ssh2_pkt_adduint32(pkt, value) ssh_pkt_adduint32(pkt, value)
\r
1929 #define ssh2_pkt_addstring_start(pkt) ssh_pkt_addstring_start(pkt)
\r
1930 #define ssh2_pkt_addstring_str(pkt, data) ssh_pkt_addstring_str(pkt, data)
\r
1931 #define ssh2_pkt_addstring_data(pkt, data, len) ssh_pkt_addstring_data(pkt, data, len)
\r
1932 #define ssh2_pkt_addstring(pkt, data) ssh_pkt_addstring(pkt, data)
\r
1934 static struct Packet *ssh2_pkt_init(int pkt_type)
\r
1936 struct Packet *pkt = ssh_new_packet();
\r
1937 pkt->length = 5; /* space for packet length + padding length */
\r
1938 pkt->forcepad = 0;
\r
1939 ssh_pkt_addbyte(pkt, (unsigned char) pkt_type);
\r
1940 pkt->body = pkt->data + pkt->length; /* after packet type */
\r
1945 * Construct an SSH-2 final-form packet: compress it, encrypt it,
\r
1946 * put the MAC on it. Final packet, ready to be sent, is stored in
\r
1947 * pkt->data. Total length is returned.
\r
1949 static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)
\r
1951 int cipherblk, maclen, padding, i;
\r
1954 log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[5],
\r
1955 ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx, pkt->data[5]),
\r
1956 pkt->body, pkt->length - (pkt->body - pkt->data),
\r
1957 pkt->nblanks, pkt->blanks, &ssh->v2_outgoing_sequence);
\r
1958 sfree(pkt->blanks); pkt->blanks = NULL;
\r
1962 * Compress packet payload.
\r
1965 unsigned char *newpayload;
\r
1967 if (ssh->cscomp &&
\r
1968 ssh->cscomp->compress(ssh->cs_comp_ctx, pkt->data + 5,
\r
1970 &newpayload, &newlen)) {
\r
1972 ssh2_pkt_adddata(pkt, newpayload, newlen);
\r
1973 sfree(newpayload);
\r
1978 * Add padding. At least four bytes, and must also bring total
\r
1979 * length (minus MAC) up to a multiple of the block size.
\r
1980 * If pkt->forcepad is set, make sure the packet is at least that size
\r
1983 cipherblk = ssh->cscipher ? ssh->cscipher->blksize : 8; /* block size */
\r
1984 cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
\r
1986 if (pkt->length + padding < pkt->forcepad)
\r
1987 padding = pkt->forcepad - pkt->length;
\r
1989 (cipherblk - (pkt->length + padding) % cipherblk) % cipherblk;
\r
1990 assert(padding <= 255);
\r
1991 maclen = ssh->csmac ? ssh->csmac->len : 0;
\r
1992 ssh2_pkt_ensure(pkt, pkt->length + padding + maclen);
\r
1993 pkt->data[4] = padding;
\r
1994 for (i = 0; i < padding; i++)
\r
1995 pkt->data[pkt->length + i] = random_byte();
\r
1996 PUT_32BIT(pkt->data, pkt->length + padding - 4);
\r
1998 ssh->csmac->generate(ssh->cs_mac_ctx, pkt->data,
\r
1999 pkt->length + padding,
\r
2000 ssh->v2_outgoing_sequence);
\r
2001 ssh->v2_outgoing_sequence++; /* whether or not we MACed */
\r
2003 if (ssh->cscipher)
\r
2004 ssh->cscipher->encrypt(ssh->cs_cipher_ctx,
\r
2005 pkt->data, pkt->length + padding);
\r
2007 pkt->encrypted_len = pkt->length + padding;
\r
2009 /* Ready-to-send packet starts at pkt->data. We return length. */
\r
2010 return pkt->length + padding + maclen;
\r
2014 * Routines called from the main SSH code to send packets. There
\r
2015 * are quite a few of these, because we have two separate
\r
2016 * mechanisms for delaying the sending of packets:
\r
2018 * - In order to send an IGNORE message and a password message in
\r
2019 * a single fixed-length blob, we require the ability to
\r
2020 * concatenate the encrypted forms of those two packets _into_ a
\r
2021 * single blob and then pass it to our <network.h> transport
\r
2022 * layer in one go. Hence, there's a deferment mechanism which
\r
2023 * works after packet encryption.
\r
2025 * - In order to avoid sending any connection-layer messages
\r
2026 * during repeat key exchange, we have to queue up any such
\r
2027 * outgoing messages _before_ they are encrypted (and in
\r
2028 * particular before they're allocated sequence numbers), and
\r
2029 * then send them once we've finished.
\r
2031 * I call these mechanisms `defer' and `queue' respectively, so as
\r
2032 * to distinguish them reasonably easily.
\r
2034 * The functions send_noqueue() and defer_noqueue() free the packet
\r
2035 * structure they are passed. Every outgoing packet goes through
\r
2036 * precisely one of these functions in its life; packets passed to
\r
2037 * ssh2_pkt_send() or ssh2_pkt_defer() either go straight to one of
\r
2038 * these or get queued, and then when the queue is later emptied
\r
2039 * the packets are all passed to defer_noqueue().
\r
2041 * When using a CBC-mode cipher, it's necessary to ensure that an
\r
2042 * attacker can't provide data to be encrypted using an IV that they
\r
2043 * know. We ensure this by prefixing each packet that might contain
\r
2044 * user data with an SSH_MSG_IGNORE. This is done using the deferral
\r
2045 * mechanism, so in this case send_noqueue() ends up redirecting to
\r
2046 * defer_noqueue(). If you don't like this inefficiency, don't use
\r
2050 static void ssh2_pkt_defer_noqueue(Ssh, struct Packet *, int);
\r
2051 static void ssh_pkt_defersend(Ssh);
\r
2054 * Send an SSH-2 packet immediately, without queuing or deferring.
\r
2056 static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)
\r
2060 if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) {
\r
2061 /* We need to send two packets, so use the deferral mechanism. */
\r
2062 ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
\r
2063 ssh_pkt_defersend(ssh);
\r
2066 len = ssh2_pkt_construct(ssh, pkt);
\r
2067 backlog = s_write(ssh, pkt->data, len);
\r
2068 if (backlog > SSH_MAX_BACKLOG)
\r
2069 ssh_throttle_all(ssh, 1, backlog);
\r
2071 ssh->outgoing_data_size += pkt->encrypted_len;
\r
2072 if (!ssh->kex_in_progress &&
\r
2073 ssh->max_data_size != 0 &&
\r
2074 ssh->outgoing_data_size > ssh->max_data_size)
\r
2075 do_ssh2_transport(ssh, "too much data sent", -1, NULL);
\r
2077 ssh_free_packet(pkt);
\r
2081 * Defer an SSH-2 packet.
\r
2083 static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt, int noignore)
\r
2086 if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) &&
\r
2087 ssh->deferred_len == 0 && !noignore &&
\r
2088 !(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {
\r
2090 * Interpose an SSH_MSG_IGNORE to ensure that user data don't
\r
2091 * get encrypted with a known IV.
\r
2093 struct Packet *ipkt = ssh2_pkt_init(SSH2_MSG_IGNORE);
\r
2094 ssh2_pkt_addstring_start(ipkt);
\r
2095 ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE);
\r
2097 len = ssh2_pkt_construct(ssh, pkt);
\r
2098 if (ssh->deferred_len + len > ssh->deferred_size) {
\r
2099 ssh->deferred_size = ssh->deferred_len + len + 128;
\r
2100 ssh->deferred_send_data = sresize(ssh->deferred_send_data,
\r
2101 ssh->deferred_size,
\r
2104 memcpy(ssh->deferred_send_data + ssh->deferred_len, pkt->data, len);
\r
2105 ssh->deferred_len += len;
\r
2106 ssh->deferred_data_size += pkt->encrypted_len;
\r
2107 ssh_free_packet(pkt);
\r
2111 * Queue an SSH-2 packet.
\r
2113 static void ssh2_pkt_queue(Ssh ssh, struct Packet *pkt)
\r
2115 assert(ssh->queueing);
\r
2117 if (ssh->queuelen >= ssh->queuesize) {
\r
2118 ssh->queuesize = ssh->queuelen + 32;
\r
2119 ssh->queue = sresize(ssh->queue, ssh->queuesize, struct Packet *);
\r
2122 ssh->queue[ssh->queuelen++] = pkt;
\r
2126 * Either queue or send a packet, depending on whether queueing is
\r
2129 static void ssh2_pkt_send(Ssh ssh, struct Packet *pkt)
\r
2131 if (ssh->queueing)
\r
2132 ssh2_pkt_queue(ssh, pkt);
\r
2134 ssh2_pkt_send_noqueue(ssh, pkt);
\r
2138 * Either queue or defer a packet, depending on whether queueing is
\r
2141 static void ssh2_pkt_defer(Ssh ssh, struct Packet *pkt)
\r
2143 if (ssh->queueing)
\r
2144 ssh2_pkt_queue(ssh, pkt);
\r
2146 ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
\r
2150 * Send the whole deferred data block constructed by
\r
2151 * ssh2_pkt_defer() or SSH-1's defer_packet().
\r
2153 * The expected use of the defer mechanism is that you call
\r
2154 * ssh2_pkt_defer() a few times, then call ssh_pkt_defersend(). If
\r
2155 * not currently queueing, this simply sets up deferred_send_data
\r
2156 * and then sends it. If we _are_ currently queueing, the calls to
\r
2157 * ssh2_pkt_defer() put the deferred packets on to the queue
\r
2158 * instead, and therefore ssh_pkt_defersend() has no deferred data
\r
2159 * to send. Hence, there's no need to make it conditional on
\r
2162 static void ssh_pkt_defersend(Ssh ssh)
\r
2165 backlog = s_write(ssh, ssh->deferred_send_data, ssh->deferred_len);
\r
2166 ssh->deferred_len = ssh->deferred_size = 0;
\r
2167 sfree(ssh->deferred_send_data);
\r
2168 ssh->deferred_send_data = NULL;
\r
2169 if (backlog > SSH_MAX_BACKLOG)
\r
2170 ssh_throttle_all(ssh, 1, backlog);
\r
2172 ssh->outgoing_data_size += ssh->deferred_data_size;
\r
2173 if (!ssh->kex_in_progress &&
\r
2174 ssh->max_data_size != 0 &&
\r
2175 ssh->outgoing_data_size > ssh->max_data_size)
\r
2176 do_ssh2_transport(ssh, "too much data sent", -1, NULL);
\r
2177 ssh->deferred_data_size = 0;
\r
2181 * Send a packet whose length needs to be disguised (typically
\r
2182 * passwords or keyboard-interactive responses).
\r
2184 static void ssh2_pkt_send_with_padding(Ssh ssh, struct Packet *pkt,
\r
2190 * The simplest way to do this is to adjust the
\r
2191 * variable-length padding field in the outgoing packet.
\r
2193 * Currently compiled out, because some Cisco SSH servers
\r
2194 * don't like excessively padded packets (bah, why's it
\r
2197 pkt->forcepad = padsize;
\r
2198 ssh2_pkt_send(ssh, pkt);
\r
2203 * If we can't do that, however, an alternative approach is
\r
2204 * to use the pkt_defer mechanism to bundle the packet
\r
2205 * tightly together with an SSH_MSG_IGNORE such that their
\r
2206 * combined length is a constant. So first we construct the
\r
2207 * final form of this packet and defer its sending.
\r
2209 ssh2_pkt_defer(ssh, pkt);
\r
2212 * Now construct an SSH_MSG_IGNORE which includes a string
\r
2213 * that's an exact multiple of the cipher block size. (If
\r
2214 * the cipher is NULL so that the block size is
\r
2215 * unavailable, we don't do this trick at all, because we
\r
2216 * gain nothing by it.)
\r
2218 if (ssh->cscipher &&
\r
2219 !(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {
\r
2222 stringlen = (256 - ssh->deferred_len);
\r
2223 stringlen += ssh->cscipher->blksize - 1;
\r
2224 stringlen -= (stringlen % ssh->cscipher->blksize);
\r
2225 if (ssh->cscomp) {
\r
2227 * Temporarily disable actual compression, so we
\r
2228 * can guarantee to get this string exactly the
\r
2229 * length we want it. The compression-disabling
\r
2230 * routine should return an integer indicating how
\r
2231 * many bytes we should adjust our string length
\r
2235 ssh->cscomp->disable_compression(ssh->cs_comp_ctx);
\r
2237 pkt = ssh2_pkt_init(SSH2_MSG_IGNORE);
\r
2238 ssh2_pkt_addstring_start(pkt);
\r
2239 for (i = 0; i < stringlen; i++) {
\r
2240 char c = (char) random_byte();
\r
2241 ssh2_pkt_addstring_data(pkt, &c, 1);
\r
2243 ssh2_pkt_defer(ssh, pkt);
\r
2245 ssh_pkt_defersend(ssh);
\r
2250 * Send all queued SSH-2 packets. We send them by means of
\r
2251 * ssh2_pkt_defer_noqueue(), in case they included a pair of
\r
2252 * packets that needed to be lumped together.
\r
2254 static void ssh2_pkt_queuesend(Ssh ssh)
\r
2258 assert(!ssh->queueing);
\r
2260 for (i = 0; i < ssh->queuelen; i++)
\r
2261 ssh2_pkt_defer_noqueue(ssh, ssh->queue[i], FALSE);
\r
2262 ssh->queuelen = 0;
\r
2264 ssh_pkt_defersend(ssh);
\r
2268 void bndebug(char *string, Bignum b)
\r
2272 p = ssh2_mpint_fmt(b, &len);
\r
2273 debug(("%s", string));
\r
2274 for (i = 0; i < len; i++)
\r
2275 debug((" %02x", p[i]));
\r
2281 static void hash_mpint(const struct ssh_hash *h, void *s, Bignum b)
\r
2285 p = ssh2_mpint_fmt(b, &len);
\r
2286 hash_string(h, s, p, len);
\r
2291 * Packet decode functions for both SSH-1 and SSH-2.
\r
2293 static unsigned long ssh_pkt_getuint32(struct Packet *pkt)
\r
2295 unsigned long value;
\r
2296 if (pkt->length - pkt->savedpos < 4)
\r
2297 return 0; /* arrgh, no way to decline (FIXME?) */
\r
2298 value = GET_32BIT(pkt->body + pkt->savedpos);
\r
2299 pkt->savedpos += 4;
\r
2302 static int ssh2_pkt_getbool(struct Packet *pkt)
\r
2304 unsigned long value;
\r
2305 if (pkt->length - pkt->savedpos < 1)
\r
2306 return 0; /* arrgh, no way to decline (FIXME?) */
\r
2307 value = pkt->body[pkt->savedpos] != 0;
\r
2311 static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length)
\r
2316 if (pkt->length - pkt->savedpos < 4)
\r
2318 len = toint(GET_32BIT(pkt->body + pkt->savedpos));
\r
2322 pkt->savedpos += 4;
\r
2323 if (pkt->length - pkt->savedpos < *length)
\r
2325 *p = (char *)(pkt->body + pkt->savedpos);
\r
2326 pkt->savedpos += *length;
\r
2328 static void *ssh_pkt_getdata(struct Packet *pkt, int length)
\r
2330 if (pkt->length - pkt->savedpos < length)
\r
2332 pkt->savedpos += length;
\r
2333 return pkt->body + (pkt->savedpos - length);
\r
2335 static int ssh1_pkt_getrsakey(struct Packet *pkt, struct RSAKey *key,
\r
2336 unsigned char **keystr)
\r
2340 j = makekey(pkt->body + pkt->savedpos,
\r
2341 pkt->length - pkt->savedpos,
\r
2347 pkt->savedpos += j;
\r
2348 assert(pkt->savedpos < pkt->length);
\r
2352 static Bignum ssh1_pkt_getmp(struct Packet *pkt)
\r
2357 j = ssh1_read_bignum(pkt->body + pkt->savedpos,
\r
2358 pkt->length - pkt->savedpos, &b);
\r
2363 pkt->savedpos += j;
\r
2366 static Bignum ssh2_pkt_getmp(struct Packet *pkt)
\r
2372 ssh_pkt_getstring(pkt, &p, &length);
\r
2377 b = bignum_from_bytes((unsigned char *)p, length);
\r
2382 * Helper function to add an SSH-2 signature blob to a packet.
\r
2383 * Expects to be shown the public key blob as well as the signature
\r
2384 * blob. Normally works just like ssh2_pkt_addstring, but will
\r
2385 * fiddle with the signature packet if necessary for
\r
2386 * BUG_SSH2_RSA_PADDING.
\r
2388 static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
\r
2389 void *pkblob_v, int pkblob_len,
\r
2390 void *sigblob_v, int sigblob_len)
\r
2392 unsigned char *pkblob = (unsigned char *)pkblob_v;
\r
2393 unsigned char *sigblob = (unsigned char *)sigblob_v;
\r
2395 /* dmemdump(pkblob, pkblob_len); */
\r
2396 /* dmemdump(sigblob, sigblob_len); */
\r
2399 * See if this is in fact an ssh-rsa signature and a buggy
\r
2400 * server; otherwise we can just do this the easy way.
\r
2402 if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) && pkblob_len > 4+7+4 &&
\r
2403 (GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
\r
2404 int pos, len, siglen;
\r
2407 * Find the byte length of the modulus.
\r
2410 pos = 4+7; /* skip over "ssh-rsa" */
\r
2411 len = toint(GET_32BIT(pkblob+pos)); /* get length of exponent */
\r
2412 if (len < 0 || len > pkblob_len - pos - 4)
\r
2414 pos += 4 + len; /* skip over exponent */
\r
2415 if (pkblob_len - pos < 4)
\r
2417 len = toint(GET_32BIT(pkblob+pos)); /* find length of modulus */
\r
2418 if (len < 0 || len > pkblob_len - pos - 4)
\r
2420 pos += 4; /* find modulus itself */
\r
2421 while (len > 0 && pkblob[pos] == 0)
\r
2423 /* debug(("modulus length is %d\n", len)); */
\r
2426 * Now find the signature integer.
\r
2428 pos = 4+7; /* skip over "ssh-rsa" */
\r
2429 if (sigblob_len < pos+4)
\r
2431 siglen = toint(GET_32BIT(sigblob+pos));
\r
2432 if (siglen != sigblob_len - pos - 4)
\r
2434 /* debug(("signature length is %d\n", siglen)); */
\r
2436 if (len != siglen) {
\r
2437 unsigned char newlen[4];
\r
2438 ssh2_pkt_addstring_start(pkt);
\r
2439 ssh2_pkt_addstring_data(pkt, (char *)sigblob, pos);
\r
2440 /* dmemdump(sigblob, pos); */
\r
2441 pos += 4; /* point to start of actual sig */
\r
2442 PUT_32BIT(newlen, len);
\r
2443 ssh2_pkt_addstring_data(pkt, (char *)newlen, 4);
\r
2444 /* dmemdump(newlen, 4); */
\r
2446 while (len-- > siglen) {
\r
2447 ssh2_pkt_addstring_data(pkt, (char *)newlen, 1);
\r
2448 /* dmemdump(newlen, 1); */
\r
2450 ssh2_pkt_addstring_data(pkt, (char *)(sigblob+pos), siglen);
\r
2451 /* dmemdump(sigblob+pos, siglen); */
\r
2455 /* Otherwise fall through and do it the easy way. We also come
\r
2456 * here as a fallback if we discover above that the key blob
\r
2457 * is misformatted in some way. */
\r
2461 ssh2_pkt_addstring_start(pkt);
\r
2462 ssh2_pkt_addstring_data(pkt, (char *)sigblob, sigblob_len);
\r
2466 * Examine the remote side's version string and compare it against
\r
2467 * a list of known buggy implementations.
\r
2469 static void ssh_detect_bugs(Ssh ssh, char *vstring)
\r
2471 char *imp; /* pointer to implementation part */
\r
2473 imp += strcspn(imp, "-");
\r
2475 imp += strcspn(imp, "-");
\r
2478 ssh->remote_bugs = 0;
\r
2481 * General notes on server version strings:
\r
2482 * - Not all servers reporting "Cisco-1.25" have all the bugs listed
\r
2483 * here -- in particular, we've heard of one that's perfectly happy
\r
2484 * with SSH1_MSG_IGNOREs -- but this string never seems to change,
\r
2485 * so we can't distinguish them.
\r
2487 if (conf_get_int(ssh->conf, CONF_sshbug_ignore1) == FORCE_ON ||
\r
2488 (conf_get_int(ssh->conf, CONF_sshbug_ignore1) == AUTO &&
\r
2489 (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
\r
2490 !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
\r
2491 !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||
\r
2492 !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {
\r
2494 * These versions don't support SSH1_MSG_IGNORE, so we have
\r
2495 * to use a different defence against password length
\r
2498 ssh->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
\r
2499 logevent("We believe remote version has SSH-1 ignore bug");
\r
2502 if (conf_get_int(ssh->conf, CONF_sshbug_plainpw1) == FORCE_ON ||
\r
2503 (conf_get_int(ssh->conf, CONF_sshbug_plainpw1) == AUTO &&
\r
2504 (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {
\r
2506 * These versions need a plain password sent; they can't
\r
2507 * handle having a null and a random length of data after
\r
2510 ssh->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
\r
2511 logevent("We believe remote version needs a plain SSH-1 password");
\r
2514 if (conf_get_int(ssh->conf, CONF_sshbug_rsa1) == FORCE_ON ||
\r
2515 (conf_get_int(ssh->conf, CONF_sshbug_rsa1) == AUTO &&
\r
2516 (!strcmp(imp, "Cisco-1.25")))) {
\r
2518 * These versions apparently have no clue whatever about
\r
2519 * RSA authentication and will panic and die if they see
\r
2520 * an AUTH_RSA message.
\r
2522 ssh->remote_bugs |= BUG_CHOKES_ON_RSA;
\r
2523 logevent("We believe remote version can't handle SSH-1 RSA authentication");
\r
2526 if (conf_get_int(ssh->conf, CONF_sshbug_hmac2) == FORCE_ON ||
\r
2527 (conf_get_int(ssh->conf, CONF_sshbug_hmac2) == AUTO &&
\r
2528 !wc_match("* VShell", imp) &&
\r
2529 (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
\r
2530 wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
\r
2531 wc_match("2.1 *", imp)))) {
\r
2533 * These versions have the HMAC bug.
\r
2535 ssh->remote_bugs |= BUG_SSH2_HMAC;
\r
2536 logevent("We believe remote version has SSH-2 HMAC bug");
\r
2539 if (conf_get_int(ssh->conf, CONF_sshbug_derivekey2) == FORCE_ON ||
\r
2540 (conf_get_int(ssh->conf, CONF_sshbug_derivekey2) == AUTO &&
\r
2541 !wc_match("* VShell", imp) &&
\r
2542 (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {
\r
2544 * These versions have the key-derivation bug (failing to
\r
2545 * include the literal shared secret in the hashes that
\r
2546 * generate the keys).
\r
2548 ssh->remote_bugs |= BUG_SSH2_DERIVEKEY;
\r
2549 logevent("We believe remote version has SSH-2 key-derivation bug");
\r
2552 if (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
\r
2553 (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == AUTO &&
\r
2554 (wc_match("OpenSSH_2.[5-9]*", imp) ||
\r
2555 wc_match("OpenSSH_3.[0-2]*", imp)))) {
\r
2557 * These versions have the SSH-2 RSA padding bug.
\r
2559 ssh->remote_bugs |= BUG_SSH2_RSA_PADDING;
\r
2560 logevent("We believe remote version has SSH-2 RSA padding bug");
\r
2563 if (conf_get_int(ssh->conf, CONF_sshbug_pksessid2) == FORCE_ON ||
\r
2564 (conf_get_int(ssh->conf, CONF_sshbug_pksessid2) == AUTO &&
\r
2565 wc_match("OpenSSH_2.[0-2]*", imp))) {
\r
2567 * These versions have the SSH-2 session-ID bug in
\r
2568 * public-key authentication.
\r
2570 ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;
\r
2571 logevent("We believe remote version has SSH-2 public-key-session-ID bug");
\r
2574 if (conf_get_int(ssh->conf, CONF_sshbug_rekey2) == FORCE_ON ||
\r
2575 (conf_get_int(ssh->conf, CONF_sshbug_rekey2) == AUTO &&
\r
2576 (wc_match("DigiSSH_2.0", imp) ||
\r
2577 wc_match("OpenSSH_2.[0-4]*", imp) ||
\r
2578 wc_match("OpenSSH_2.5.[0-3]*", imp) ||
\r
2579 wc_match("Sun_SSH_1.0", imp) ||
\r
2580 wc_match("Sun_SSH_1.0.1", imp) ||
\r
2581 /* All versions <= 1.2.6 (they changed their format in 1.2.7) */
\r
2582 wc_match("WeOnlyDo-*", imp)))) {
\r
2584 * These versions have the SSH-2 rekey bug.
\r
2586 ssh->remote_bugs |= BUG_SSH2_REKEY;
\r
2587 logevent("We believe remote version has SSH-2 rekey bug");
\r
2590 if (conf_get_int(ssh->conf, CONF_sshbug_maxpkt2) == FORCE_ON ||
\r
2591 (conf_get_int(ssh->conf, CONF_sshbug_maxpkt2) == AUTO &&
\r
2592 (wc_match("1.36_sshlib GlobalSCAPE", imp) ||
\r
2593 wc_match("1.36 sshlib: GlobalScape", imp)))) {
\r
2595 * This version ignores our makpkt and needs to be throttled.
\r
2597 ssh->remote_bugs |= BUG_SSH2_MAXPKT;
\r
2598 logevent("We believe remote version ignores SSH-2 maximum packet size");
\r
2601 if (conf_get_int(ssh->conf, CONF_sshbug_ignore2) == FORCE_ON) {
\r
2603 * Servers that don't support SSH2_MSG_IGNORE. Currently,
\r
2604 * none detected automatically.
\r
2606 ssh->remote_bugs |= BUG_CHOKES_ON_SSH2_IGNORE;
\r
2607 logevent("We believe remote version has SSH-2 ignore bug");
\r
2610 if (conf_get_int(ssh->conf, CONF_sshbug_winadj) == FORCE_ON) {
\r
2612 * Servers that don't support our winadj request for one
\r
2613 * reason or another. Currently, none detected automatically.
\r
2615 ssh->remote_bugs |= BUG_CHOKES_ON_WINADJ;
\r
2616 logevent("We believe remote version has winadj bug");
\r
2621 * The `software version' part of an SSH version string is required
\r
2622 * to contain no spaces or minus signs.
\r
2624 static void ssh_fix_verstring(char *str)
\r
2626 /* Eat "SSH-<protoversion>-". */
\r
2627 assert(*str == 'S'); str++;
\r
2628 assert(*str == 'S'); str++;
\r
2629 assert(*str == 'H'); str++;
\r
2630 assert(*str == '-'); str++;
\r
2631 while (*str && *str != '-') str++;
\r
2632 assert(*str == '-'); str++;
\r
2634 /* Convert minus signs and spaces in the remaining string into
\r
2637 if (*str == '-' || *str == ' ')
\r
2644 * Send an appropriate SSH version string.
\r
2646 static void ssh_send_verstring(Ssh ssh, char *svers)
\r
2650 if (ssh->version == 2) {
\r
2652 * Construct a v2 version string.
\r
2654 verstring = dupprintf("SSH-2.0-%s\015\012", sshver);
\r
2657 * Construct a v1 version string.
\r
2659 verstring = dupprintf("SSH-%s-%s\012",
\r
2660 (ssh_versioncmp(svers, "1.5") <= 0 ?
\r
2665 ssh_fix_verstring(verstring);
\r
2667 if (ssh->version == 2) {
\r
2670 * Record our version string.
\r
2672 len = strcspn(verstring, "\015\012");
\r
2673 ssh->v_c = snewn(len + 1, char);
\r
2674 memcpy(ssh->v_c, verstring, len);
\r
2675 ssh->v_c[len] = 0;
\r
2678 logeventf(ssh, "We claim version: %.*s",
\r
2679 strcspn(verstring, "\015\012"), verstring);
\r
2680 s_write(ssh, verstring, strlen(verstring));
\r
2684 static int do_ssh_init(Ssh ssh, unsigned char c)
\r
2686 struct do_ssh_init_state {
\r
2693 int proto1, proto2;
\r
2695 crState(do_ssh_init_state);
\r
2699 /* Search for a line beginning with the string "SSH-" in the input. */
\r
2701 if (c != 'S') goto no;
\r
2703 if (c != 'S') goto no;
\r
2705 if (c != 'H') goto no;
\r
2707 if (c != '-') goto no;
\r
2710 while (c != '\012')
\r
2716 s->vstring = snewn(s->vstrsize, char);
\r
2717 strcpy(s->vstring, "SSH-");
\r
2721 crReturn(1); /* get another char */
\r
2722 if (s->vslen >= s->vstrsize - 1) {
\r
2723 s->vstrsize += 16;
\r
2724 s->vstring = sresize(s->vstring, s->vstrsize, char);
\r
2726 s->vstring[s->vslen++] = c;
\r
2729 s->version[s->i] = '\0';
\r
2731 } else if (s->i < sizeof(s->version) - 1)
\r
2732 s->version[s->i++] = c;
\r
2733 } else if (c == '\012')
\r
2737 ssh->agentfwd_enabled = FALSE;
\r
2738 ssh->rdpkt2_state.incoming_sequence = 0;
\r
2740 s->vstring[s->vslen] = 0;
\r
2741 s->vstring[strcspn(s->vstring, "\015\012")] = '\0';/* remove EOL chars */
\r
2742 logeventf(ssh, "Server version: %s", s->vstring);
\r
2743 ssh_detect_bugs(ssh, s->vstring);
\r
2746 * Decide which SSH protocol version to support.
\r
2749 /* Anything strictly below "2.0" means protocol 1 is supported. */
\r
2750 s->proto1 = ssh_versioncmp(s->version, "2.0") < 0;
\r
2751 /* Anything greater or equal to "1.99" means protocol 2 is supported. */
\r
2752 s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
\r
2754 if (conf_get_int(ssh->conf, CONF_sshprot) == 0 && !s->proto1) {
\r
2755 bombout(("SSH protocol version 1 required by user but not provided by server"));
\r
2758 if (conf_get_int(ssh->conf, CONF_sshprot) == 3 && !s->proto2) {
\r
2759 bombout(("SSH protocol version 2 required by user but not provided by server"));
\r
2763 if (s->proto2 && (conf_get_int(ssh->conf, CONF_sshprot) >= 2 || !s->proto1))
\r
2768 logeventf(ssh, "Using SSH protocol version %d", ssh->version);
\r
2770 /* Send the version string, if we haven't already */
\r
2771 if (conf_get_int(ssh->conf, CONF_sshprot) != 3)
\r
2772 ssh_send_verstring(ssh, s->version);
\r
2774 if (ssh->version == 2) {
\r
2777 * Record their version string.
\r
2779 len = strcspn(s->vstring, "\015\012");
\r
2780 ssh->v_s = snewn(len + 1, char);
\r
2781 memcpy(ssh->v_s, s->vstring, len);
\r
2782 ssh->v_s[len] = 0;
\r
2785 * Initialise SSH-2 protocol.
\r
2787 ssh->protocol = ssh2_protocol;
\r
2788 ssh2_protocol_setup(ssh);
\r
2789 ssh->s_rdpkt = ssh2_rdpkt;
\r
2792 * Initialise SSH-1 protocol.
\r
2794 ssh->protocol = ssh1_protocol;
\r
2795 ssh1_protocol_setup(ssh);
\r
2796 ssh->s_rdpkt = ssh1_rdpkt;
\r
2798 if (ssh->version == 2)
\r
2799 do_ssh2_transport(ssh, NULL, -1, NULL);
\r
2801 update_specials_menu(ssh->frontend);
\r
2802 ssh->state = SSH_STATE_BEFORE_SIZE;
\r
2803 ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh);
\r
2805 sfree(s->vstring);
\r
2810 static void ssh_process_incoming_data(Ssh ssh,
\r
2811 unsigned char **data, int *datalen)
\r
2813 struct Packet *pktin;
\r
2815 pktin = ssh->s_rdpkt(ssh, data, datalen);
\r
2817 ssh->protocol(ssh, NULL, 0, pktin);
\r
2818 ssh_free_packet(pktin);
\r
2822 static void ssh_queue_incoming_data(Ssh ssh,
\r
2823 unsigned char **data, int *datalen)
\r
2825 bufchain_add(&ssh->queued_incoming_data, *data, *datalen);
\r
2826 *data += *datalen;
\r
2830 static void ssh_process_queued_incoming_data(Ssh ssh)
\r
2833 unsigned char *data;
\r
2836 while (!ssh->frozen && bufchain_size(&ssh->queued_incoming_data)) {
\r
2837 bufchain_prefix(&ssh->queued_incoming_data, &vdata, &len);
\r
2841 while (!ssh->frozen && len > 0)
\r
2842 ssh_process_incoming_data(ssh, &data, &len);
\r
2844 if (origlen > len)
\r
2845 bufchain_consume(&ssh->queued_incoming_data, origlen - len);
\r
2849 static void ssh_set_frozen(Ssh ssh, int frozen)
\r
2852 sk_set_frozen(ssh->s, frozen);
\r
2853 ssh->frozen = frozen;
\r
2856 static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)
\r
2858 /* Log raw data, if we're in that mode. */
\r
2860 log_packet(ssh->logctx, PKT_INCOMING, -1, NULL, data, datalen,
\r
2863 crBegin(ssh->ssh_gotdata_crstate);
\r
2866 * To begin with, feed the characters one by one to the
\r
2867 * protocol initialisation / selection function do_ssh_init().
\r
2868 * When that returns 0, we're done with the initial greeting
\r
2869 * exchange and can move on to packet discipline.
\r
2872 int ret; /* need not be kept across crReturn */
\r
2874 crReturnV; /* more data please */
\r
2875 ret = do_ssh_init(ssh, *data);
\r
2883 * We emerge from that loop when the initial negotiation is
\r
2884 * over and we have selected an s_rdpkt function. Now pass
\r
2885 * everything to s_rdpkt, and then pass the resulting packets
\r
2886 * to the proper protocol handler.
\r
2890 while (bufchain_size(&ssh->queued_incoming_data) > 0 || datalen > 0) {
\r
2891 if (ssh->frozen) {
\r
2892 ssh_queue_incoming_data(ssh, &data, &datalen);
\r
2893 /* This uses up all data and cannot cause anything interesting
\r
2894 * to happen; indeed, for anything to happen at all, we must
\r
2895 * return, so break out. */
\r
2897 } else if (bufchain_size(&ssh->queued_incoming_data) > 0) {
\r
2898 /* This uses up some or all data, and may freeze the
\r
2900 ssh_process_queued_incoming_data(ssh);
\r
2902 /* This uses up some or all data, and may freeze the
\r
2904 ssh_process_incoming_data(ssh, &data, &datalen);
\r
2906 /* FIXME this is probably EBW. */
\r
2907 if (ssh->state == SSH_STATE_CLOSED)
\r
2910 /* We're out of data. Go and get some more. */
\r
2916 static int ssh_do_close(Ssh ssh, int notify_exit)
\r
2919 struct ssh_channel *c;
\r
2921 ssh->state = SSH_STATE_CLOSED;
\r
2922 expire_timer_context(ssh);
\r
2927 notify_remote_exit(ssh->frontend);
\r
2932 * Now we must shut down any port- and X-forwarded channels going
\r
2933 * through this connection.
\r
2935 if (ssh->channels) {
\r
2936 while (NULL != (c = index234(ssh->channels, 0))) {
\r
2937 switch (c->type) {
\r
2939 x11_close(c->u.x11.s);
\r
2941 case CHAN_SOCKDATA:
\r
2942 case CHAN_SOCKDATA_DORMANT:
\r
2943 pfd_close(c->u.pfd.s);
\r
2946 del234(ssh->channels, c); /* moving next one to index 0 */
\r
2947 if (ssh->version == 2)
\r
2948 bufchain_clear(&c->v.v2.outbuffer);
\r
2953 * Go through port-forwardings, and close any associated
\r
2954 * listening sockets.
\r
2956 if (ssh->portfwds) {
\r
2957 struct ssh_portfwd *pf;
\r
2958 while (NULL != (pf = index234(ssh->portfwds, 0))) {
\r
2959 /* Dispose of any listening socket. */
\r
2961 pfd_terminate(pf->local);
\r
2962 del234(ssh->portfwds, pf); /* moving next one to index 0 */
\r
2965 freetree234(ssh->portfwds);
\r
2966 ssh->portfwds = NULL;
\r
2972 static void ssh_log(Plug plug, int type, SockAddr addr, int port,
\r
2973 const char *error_msg, int error_code)
\r
2975 Ssh ssh = (Ssh) plug;
\r
2976 char addrbuf[256], *msg;
\r
2978 sk_getaddr(addr, addrbuf, lenof(addrbuf));
\r
2981 msg = dupprintf("Connecting to %s port %d", addrbuf, port);
\r
2983 msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
\r
2989 static int ssh_closing(Plug plug, const char *error_msg, int error_code,
\r
2992 Ssh ssh = (Ssh) plug;
\r
2993 int need_notify = ssh_do_close(ssh, FALSE);
\r
2996 if (!ssh->close_expected)
\r
2997 error_msg = "Server unexpectedly closed network connection";
\r
2999 error_msg = "Server closed network connection";
\r
3002 if (ssh->close_expected && ssh->clean_exit && ssh->exitcode < 0)
\r
3003 ssh->exitcode = 0;
\r
3006 notify_remote_exit(ssh->frontend);
\r
3009 logevent(error_msg);
\r
3010 if (!ssh->close_expected || !ssh->clean_exit)
\r
3011 connection_fatal(ssh->frontend, "%s", error_msg);
\r
3015 static int ssh_receive(Plug plug, int urgent, char *data, int len)
\r
3017 Ssh ssh = (Ssh) plug;
\r
3018 ssh_gotdata(ssh, (unsigned char *)data, len);
\r
3019 if (ssh->state == SSH_STATE_CLOSED) {
\r
3020 ssh_do_close(ssh, TRUE);
\r
3026 static void ssh_sent(Plug plug, int bufsize)
\r
3028 Ssh ssh = (Ssh) plug;
\r
3030 * If the send backlog on the SSH socket itself clears, we
\r
3031 * should unthrottle the whole world if it was throttled.
\r
3033 if (bufsize < SSH_MAX_BACKLOG)
\r
3034 ssh_throttle_all(ssh, 0, bufsize);
\r
3038 * Connect to specified host and port.
\r
3039 * Returns an error message, or NULL on success.
\r
3040 * Also places the canonical host name into `realhost'. It must be
\r
3041 * freed by the caller.
\r
3043 static const char *connect_to_host(Ssh ssh, char *host, int port,
\r
3044 char **realhost, int nodelay, int keepalive)
\r
3046 static const struct plug_function_table fn_table = {
\r
3057 int addressfamily, sshprot;
\r
3059 loghost = conf_get_str(ssh->conf, CONF_loghost);
\r
3063 ssh->savedhost = dupstr(loghost);
\r
3064 ssh->savedport = 22; /* default ssh port */
\r
3067 * A colon suffix on savedhost also lets us affect
\r
3070 * (FIXME: do something about IPv6 address literals here.)
\r
3072 colon = strrchr(ssh->savedhost, ':');
\r
3076 ssh->savedport = atoi(colon);
\r
3079 ssh->savedhost = dupstr(host);
\r
3081 port = 22; /* default ssh port */
\r
3082 ssh->savedport = port;
\r
3086 * Try to find host.
\r
3088 addressfamily = conf_get_int(ssh->conf, CONF_addressfamily);
\r
3089 logeventf(ssh, "Looking up host \"%s\"%s", host,
\r
3090 (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
\r
3091 (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
\r
3092 addr = name_lookup(host, port, realhost, ssh->conf, addressfamily);
\r
3093 if ((err = sk_addr_error(addr)) != NULL) {
\r
3094 sk_addr_free(addr);
\r
3097 ssh->fullhostname = dupstr(*realhost); /* save in case of GSSAPI */
\r
3102 ssh->fn = &fn_table;
\r
3103 ssh->s = new_connection(addr, *realhost, port,
\r
3104 0, 1, nodelay, keepalive, (Plug) ssh, ssh->conf);
\r
3105 if ((err = sk_socket_error(ssh->s)) != NULL) {
\r
3107 notify_remote_exit(ssh->frontend);
\r
3112 * If the SSH version number's fixed, set it now, and if it's SSH-2,
\r
3113 * send the version string too.
\r
3115 sshprot = conf_get_int(ssh->conf, CONF_sshprot);
\r
3118 if (sshprot == 3) {
\r
3120 ssh_send_verstring(ssh, NULL);
\r
3124 * loghost, if configured, overrides realhost.
\r
3128 *realhost = dupstr(loghost);
\r
3135 * Throttle or unthrottle the SSH connection.
\r
3137 static void ssh_throttle_conn(Ssh ssh, int adjust)
\r
3139 int old_count = ssh->conn_throttle_count;
\r
3140 ssh->conn_throttle_count += adjust;
\r
3141 assert(ssh->conn_throttle_count >= 0);
\r
3142 if (ssh->conn_throttle_count && !old_count) {
\r
3143 ssh_set_frozen(ssh, 1);
\r
3144 } else if (!ssh->conn_throttle_count && old_count) {
\r
3145 ssh_set_frozen(ssh, 0);
\r
3150 * Throttle or unthrottle _all_ local data streams (for when sends
\r
3151 * on the SSH connection itself back up).
\r
3153 static void ssh_throttle_all(Ssh ssh, int enable, int bufsize)
\r
3156 struct ssh_channel *c;
\r
3158 if (enable == ssh->throttled_all)
\r
3160 ssh->throttled_all = enable;
\r
3161 ssh->overall_bufsize = bufsize;
\r
3162 if (!ssh->channels)
\r
3164 for (i = 0; NULL != (c = index234(ssh->channels, i)); i++) {
\r
3165 switch (c->type) {
\r
3166 case CHAN_MAINSESSION:
\r
3168 * This is treated separately, outside the switch.
\r
3172 x11_override_throttle(c->u.x11.s, enable);
\r
3175 /* Agent channels require no buffer management. */
\r
3177 case CHAN_SOCKDATA:
\r
3178 pfd_override_throttle(c->u.pfd.s, enable);
\r
3184 static void ssh_agent_callback(void *sshv, void *reply, int replylen)
\r
3186 Ssh ssh = (Ssh) sshv;
\r
3188 ssh->agent_response = reply;
\r
3189 ssh->agent_response_len = replylen;
\r
3191 if (ssh->version == 1)
\r
3192 do_ssh1_login(ssh, NULL, -1, NULL);
\r
3194 do_ssh2_authconn(ssh, NULL, -1, NULL);
\r
3197 static void ssh_dialog_callback(void *sshv, int ret)
\r
3199 Ssh ssh = (Ssh) sshv;
\r
3201 ssh->user_response = ret;
\r
3203 if (ssh->version == 1)
\r
3204 do_ssh1_login(ssh, NULL, -1, NULL);
\r
3206 do_ssh2_transport(ssh, NULL, -1, NULL);
\r
3209 * This may have unfrozen the SSH connection, so do a
\r
3210 * queued-data run.
\r
3212 ssh_process_queued_incoming_data(ssh);
\r
3215 static void ssh_agentf_callback(void *cv, void *reply, int replylen)
\r
3217 struct ssh_channel *c = (struct ssh_channel *)cv;
\r
3219 void *sentreply = reply;
\r
3221 c->u.a.outstanding_requests--;
\r
3223 /* Fake SSH_AGENT_FAILURE. */
\r
3224 sentreply = "\0\0\0\1\5";
\r
3227 if (ssh->version == 2) {
\r
3228 ssh2_add_channel_data(c, sentreply, replylen);
\r
3231 send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
\r
3232 PKT_INT, c->remoteid,
\r
3233 PKT_INT, replylen,
\r
3235 PKT_DATA, sentreply, replylen,
\r
3242 * If we've already seen an incoming EOF but haven't sent an
\r
3243 * outgoing one, this may be the moment to send it.
\r
3245 if (c->u.a.outstanding_requests == 0 && (c->closes & CLOSES_RCVD_EOF))
\r
3246 sshfwd_write_eof(c);
\r
3250 * Client-initiated disconnection. Send a DISCONNECT if `wire_reason'
\r
3251 * non-NULL, otherwise just close the connection. `client_reason' == NULL
\r
3252 * => log `wire_reason'.
\r
3254 static void ssh_disconnect(Ssh ssh, char *client_reason, char *wire_reason,
\r
3255 int code, int clean_exit)
\r
3258 if (!client_reason)
\r
3259 client_reason = wire_reason;
\r
3260 if (client_reason)
\r
3261 error = dupprintf("Disconnected: %s", client_reason);
\r
3263 error = dupstr("Disconnected");
\r
3264 if (wire_reason) {
\r
3265 if (ssh->version == 1) {
\r
3266 send_packet(ssh, SSH1_MSG_DISCONNECT, PKT_STR, wire_reason,
\r
3268 } else if (ssh->version == 2) {
\r
3269 struct Packet *pktout = ssh2_pkt_init(SSH2_MSG_DISCONNECT);
\r
3270 ssh2_pkt_adduint32(pktout, code);
\r
3271 ssh2_pkt_addstring(pktout, wire_reason);
\r
3272 ssh2_pkt_addstring(pktout, "en"); /* language tag */
\r
3273 ssh2_pkt_send_noqueue(ssh, pktout);
\r
3276 ssh->close_expected = TRUE;
\r
3277 ssh->clean_exit = clean_exit;
\r
3278 ssh_closing((Plug)ssh, error, 0, 0);
\r
3283 * Handle the key exchange and user authentication phases.
\r
3285 static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
\r
3286 struct Packet *pktin)
\r
3289 unsigned char cookie[8], *ptr;
\r
3290 struct MD5Context md5c;
\r
3291 struct do_ssh1_login_state {
\r
3294 unsigned char *rsabuf, *keystr1, *keystr2;
\r
3295 unsigned long supported_ciphers_mask, supported_auths_mask;
\r
3296 int tried_publickey, tried_agent;
\r
3297 int tis_auth_refused, ccard_auth_refused;
\r
3298 unsigned char session_id[16];
\r
3300 void *publickey_blob;
\r
3301 int publickey_bloblen;
\r
3302 char *publickey_comment;
\r
3303 int publickey_encrypted;
\r
3304 prompts_t *cur_prompt;
\r
3307 unsigned char request[5], *response, *p;
\r
3311 struct RSAKey key;
\r
3316 Filename *keyfile;
\r
3317 struct RSAKey servkey, hostkey;
\r
3319 crState(do_ssh1_login_state);
\r
3324 crWaitUntil(pktin);
\r
3326 if (pktin->type != SSH1_SMSG_PUBLIC_KEY) {
\r
3327 bombout(("Public key packet not received"));
\r
3331 logevent("Received public keys");
\r
3333 ptr = ssh_pkt_getdata(pktin, 8);
\r
3335 bombout(("SSH-1 public key packet stopped before random cookie"));
\r
3338 memcpy(cookie, ptr, 8);
\r
3340 if (!ssh1_pkt_getrsakey(pktin, &s->servkey, &s->keystr1) ||
\r
3341 !ssh1_pkt_getrsakey(pktin, &s->hostkey, &s->keystr2)) {
\r
3342 bombout(("Failed to read SSH-1 public keys from public key packet"));
\r
3347 * Log the host key fingerprint.
\r
3351 logevent("Host key fingerprint is:");
\r
3352 strcpy(logmsg, " ");
\r
3353 s->hostkey.comment = NULL;
\r
3354 rsa_fingerprint(logmsg + strlen(logmsg),
\r
3355 sizeof(logmsg) - strlen(logmsg), &s->hostkey);
\r
3359 ssh->v1_remote_protoflags = ssh_pkt_getuint32(pktin);
\r
3360 s->supported_ciphers_mask = ssh_pkt_getuint32(pktin);
\r
3361 s->supported_auths_mask = ssh_pkt_getuint32(pktin);
\r
3362 if ((ssh->remote_bugs & BUG_CHOKES_ON_RSA))
\r
3363 s->supported_auths_mask &= ~(1 << SSH1_AUTH_RSA);
\r
3365 ssh->v1_local_protoflags =
\r
3366 ssh->v1_remote_protoflags & SSH1_PROTOFLAGS_SUPPORTED;
\r
3367 ssh->v1_local_protoflags |= SSH1_PROTOFLAG_SCREEN_NUMBER;
\r
3370 MD5Update(&md5c, s->keystr2, s->hostkey.bytes);
\r
3371 MD5Update(&md5c, s->keystr1, s->servkey.bytes);
\r
3372 MD5Update(&md5c, cookie, 8);
\r
3373 MD5Final(s->session_id, &md5c);
\r
3375 for (i = 0; i < 32; i++)
\r
3376 ssh->session_key[i] = random_byte();
\r
3379 * Verify that the `bits' and `bytes' parameters match.
\r
3381 if (s->hostkey.bits > s->hostkey.bytes * 8 ||
\r
3382 s->servkey.bits > s->servkey.bytes * 8) {
\r
3383 bombout(("SSH-1 public keys were badly formatted"));
\r
3387 s->len = (s->hostkey.bytes > s->servkey.bytes ?
\r
3388 s->hostkey.bytes : s->servkey.bytes);
\r
3390 s->rsabuf = snewn(s->len, unsigned char);
\r
3393 * Verify the host key.
\r
3397 * First format the key into a string.
\r
3399 int len = rsastr_len(&s->hostkey);
\r
3400 char fingerprint[100];
\r
3401 char *keystr = snewn(len, char);
\r
3402 rsastr_fmt(keystr, &s->hostkey);
\r
3403 rsa_fingerprint(fingerprint, sizeof(fingerprint), &s->hostkey);
\r
3405 ssh_set_frozen(ssh, 1);
\r
3406 s->dlgret = verify_ssh_host_key(ssh->frontend,
\r
3407 ssh->savedhost, ssh->savedport,
\r
3408 "rsa", keystr, fingerprint,
\r
3409 ssh_dialog_callback, ssh);
\r
3411 if (s->dlgret < 0) {
\r
3415 bombout(("Unexpected data from server while waiting"
\r
3416 " for user host key response"));
\r
3419 } while (pktin || inlen > 0);
\r
3420 s->dlgret = ssh->user_response;
\r
3422 ssh_set_frozen(ssh, 0);
\r
3424 if (s->dlgret == 0) {
\r
3425 ssh_disconnect(ssh, "User aborted at host key verification",
\r
3431 for (i = 0; i < 32; i++) {
\r
3432 s->rsabuf[i] = ssh->session_key[i];
\r
3434 s->rsabuf[i] ^= s->session_id[i];
\r
3437 if (s->hostkey.bytes > s->servkey.bytes) {
\r
3438 ret = rsaencrypt(s->rsabuf, 32, &s->servkey);
\r
3440 ret = rsaencrypt(s->rsabuf, s->servkey.bytes, &s->hostkey);
\r
3442 ret = rsaencrypt(s->rsabuf, 32, &s->hostkey);
\r
3444 ret = rsaencrypt(s->rsabuf, s->hostkey.bytes, &s->servkey);
\r
3447 bombout(("SSH-1 public key encryptions failed due to bad formatting"));
\r
3451 logevent("Encrypted session key");
\r
3454 int cipher_chosen = 0, warn = 0;
\r
3455 char *cipher_string = NULL;
\r
3457 for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
\r
3458 int next_cipher = conf_get_int_int(ssh->conf,
\r
3459 CONF_ssh_cipherlist, i);
\r
3460 if (next_cipher == CIPHER_WARN) {
\r
3461 /* If/when we choose a cipher, warn about it */
\r
3463 } else if (next_cipher == CIPHER_AES) {
\r
3464 /* XXX Probably don't need to mention this. */
\r
3465 logevent("AES not supported in SSH-1, skipping");
\r
3467 switch (next_cipher) {
\r
3468 case CIPHER_3DES: s->cipher_type = SSH_CIPHER_3DES;
\r
3469 cipher_string = "3DES"; break;
\r
3470 case CIPHER_BLOWFISH: s->cipher_type = SSH_CIPHER_BLOWFISH;
\r
3471 cipher_string = "Blowfish"; break;
\r
3472 case CIPHER_DES: s->cipher_type = SSH_CIPHER_DES;
\r
3473 cipher_string = "single-DES"; break;
\r
3475 if (s->supported_ciphers_mask & (1 << s->cipher_type))
\r
3476 cipher_chosen = 1;
\r
3479 if (!cipher_chosen) {
\r
3480 if ((s->supported_ciphers_mask & (1 << SSH_CIPHER_3DES)) == 0)
\r
3481 bombout(("Server violates SSH-1 protocol by not "
\r
3482 "supporting 3DES encryption"));
\r
3484 /* shouldn't happen */
\r
3485 bombout(("No supported ciphers found"));
\r
3489 /* Warn about chosen cipher if necessary. */
\r
3491 ssh_set_frozen(ssh, 1);
\r
3492 s->dlgret = askalg(ssh->frontend, "cipher", cipher_string,
\r
3493 ssh_dialog_callback, ssh);
\r
3494 if (s->dlgret < 0) {
\r
3498 bombout(("Unexpected data from server while waiting"
\r
3499 " for user response"));
\r
3502 } while (pktin || inlen > 0);
\r
3503 s->dlgret = ssh->user_response;
\r
3505 ssh_set_frozen(ssh, 0);
\r
3506 if (s->dlgret == 0) {
\r
3507 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
\r
3514 switch (s->cipher_type) {
\r
3515 case SSH_CIPHER_3DES:
\r
3516 logevent("Using 3DES encryption");
\r
3518 case SSH_CIPHER_DES:
\r
3519 logevent("Using single-DES encryption");
\r
3521 case SSH_CIPHER_BLOWFISH:
\r
3522 logevent("Using Blowfish encryption");
\r
3526 send_packet(ssh, SSH1_CMSG_SESSION_KEY,
\r
3527 PKT_CHAR, s->cipher_type,
\r
3528 PKT_DATA, cookie, 8,
\r
3529 PKT_CHAR, (s->len * 8) >> 8, PKT_CHAR, (s->len * 8) & 0xFF,
\r
3530 PKT_DATA, s->rsabuf, s->len,
\r
3531 PKT_INT, ssh->v1_local_protoflags, PKT_END);
\r
3533 logevent("Trying to enable encryption...");
\r
3537 ssh->cipher = (s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
\r
3538 s->cipher_type == SSH_CIPHER_DES ? &ssh_des :
\r
3540 ssh->v1_cipher_ctx = ssh->cipher->make_context();
\r
3541 ssh->cipher->sesskey(ssh->v1_cipher_ctx, ssh->session_key);
\r
3542 logeventf(ssh, "Initialised %s encryption", ssh->cipher->text_name);
\r
3544 ssh->crcda_ctx = crcda_make_context();
\r
3545 logevent("Installing CRC compensation attack detector");
\r
3547 if (s->servkey.modulus) {
\r
3548 sfree(s->servkey.modulus);
\r
3549 s->servkey.modulus = NULL;
\r
3551 if (s->servkey.exponent) {
\r
3552 sfree(s->servkey.exponent);
\r
3553 s->servkey.exponent = NULL;
\r
3555 if (s->hostkey.modulus) {
\r
3556 sfree(s->hostkey.modulus);
\r
3557 s->hostkey.modulus = NULL;
\r
3559 if (s->hostkey.exponent) {
\r
3560 sfree(s->hostkey.exponent);
\r
3561 s->hostkey.exponent = NULL;
\r
3563 crWaitUntil(pktin);
\r
3565 if (pktin->type != SSH1_SMSG_SUCCESS) {
\r
3566 bombout(("Encryption not successfully enabled"));
\r
3570 logevent("Successfully started encryption");
\r
3572 fflush(stdout); /* FIXME eh? */
\r
3574 if ((ssh->username = get_remote_username(ssh->conf)) == NULL) {
\r
3575 int ret; /* need not be kept over crReturn */
\r
3576 s->cur_prompt = new_prompts(ssh->frontend);
\r
3577 s->cur_prompt->to_server = TRUE;
\r
3578 s->cur_prompt->name = dupstr("SSH login name");
\r
3579 add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
\r
3580 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
3583 crWaitUntil(!pktin);
\r
3584 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
3589 * Failed to get a username. Terminate.
\r
3591 free_prompts(s->cur_prompt);
\r
3592 ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
\r
3595 ssh->username = dupstr(s->cur_prompt->prompts[0]->result);
\r
3596 free_prompts(s->cur_prompt);
\r
3599 send_packet(ssh, SSH1_CMSG_USER, PKT_STR, ssh->username, PKT_END);
\r
3601 char *userlog = dupprintf("Sent username \"%s\"", ssh->username);
\r
3602 logevent(userlog);
\r
3603 if (flags & FLAG_INTERACTIVE &&
\r
3604 (!((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)))) {
\r
3605 c_write_str(ssh, userlog);
\r
3606 c_write_str(ssh, "\r\n");
\r
3612 crWaitUntil(pktin);
\r
3614 if ((s->supported_auths_mask & (1 << SSH1_AUTH_RSA)) == 0) {
\r
3615 /* We must not attempt PK auth. Pretend we've already tried it. */
\r
3616 s->tried_publickey = s->tried_agent = 1;
\r
3618 s->tried_publickey = s->tried_agent = 0;
\r
3620 s->tis_auth_refused = s->ccard_auth_refused = 0;
\r
3622 * Load the public half of any configured keyfile for later use.
\r
3624 s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
\r
3625 if (!filename_is_null(s->keyfile)) {
\r
3627 logeventf(ssh, "Reading private key file \"%.150s\"",
\r
3628 filename_to_str(s->keyfile));
\r
3629 keytype = key_type(s->keyfile);
\r
3630 if (keytype == SSH_KEYTYPE_SSH1) {
\r
3631 const char *error;
\r
3632 if (rsakey_pubblob(s->keyfile,
\r
3633 &s->publickey_blob, &s->publickey_bloblen,
\r
3634 &s->publickey_comment, &error)) {
\r
3635 s->publickey_encrypted = rsakey_encrypted(s->keyfile,
\r
3639 logeventf(ssh, "Unable to load private key (%s)", error);
\r
3640 msgbuf = dupprintf("Unable to load private key file "
\r
3641 "\"%.150s\" (%s)\r\n",
\r
3642 filename_to_str(s->keyfile),
\r
3644 c_write_str(ssh, msgbuf);
\r
3646 s->publickey_blob = NULL;
\r
3650 logeventf(ssh, "Unable to use this key file (%s)",
\r
3651 key_type_to_str(keytype));
\r
3652 msgbuf = dupprintf("Unable to use key file \"%.150s\""
\r
3654 filename_to_str(s->keyfile),
\r
3655 key_type_to_str(keytype));
\r
3656 c_write_str(ssh, msgbuf);
\r
3658 s->publickey_blob = NULL;
\r
3661 s->publickey_blob = NULL;
\r
3663 while (pktin->type == SSH1_SMSG_FAILURE) {
\r
3664 s->pwpkt_type = SSH1_CMSG_AUTH_PASSWORD;
\r
3666 if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists() && !s->tried_agent) {
\r
3668 * Attempt RSA authentication using Pageant.
\r
3672 s->authed = FALSE;
\r
3673 s->tried_agent = 1;
\r
3674 logevent("Pageant is running. Requesting keys.");
\r
3676 /* Request the keys held by the agent. */
\r
3677 PUT_32BIT(s->request, 1);
\r
3678 s->request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
\r
3679 if (!agent_query(s->request, 5, &r, &s->responselen,
\r
3680 ssh_agent_callback, ssh)) {
\r
3684 bombout(("Unexpected data from server while waiting"
\r
3685 " for agent response"));
\r
3688 } while (pktin || inlen > 0);
\r
3689 r = ssh->agent_response;
\r
3690 s->responselen = ssh->agent_response_len;
\r
3692 s->response = (unsigned char *) r;
\r
3693 if (s->response && s->responselen >= 5 &&
\r
3694 s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
\r
3695 s->p = s->response + 5;
\r
3696 s->nkeys = toint(GET_32BIT(s->p));
\r
3697 if (s->nkeys < 0) {
\r
3698 logeventf(ssh, "Pageant reported negative key count %d",
\r
3703 logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
\r
3704 for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
\r
3705 unsigned char *pkblob = s->p;
\r
3708 int n, ok = FALSE;
\r
3709 do { /* do while (0) to make breaking easy */
\r
3710 n = ssh1_read_bignum
\r
3711 (s->p, toint(s->responselen-(s->p-s->response)),
\r
3712 &s->key.exponent);
\r
3716 n = ssh1_read_bignum
\r
3717 (s->p, toint(s->responselen-(s->p-s->response)),
\r
3722 if (s->responselen - (s->p-s->response) < 4)
\r
3724 s->commentlen = toint(GET_32BIT(s->p));
\r
3726 if (s->commentlen < 0 ||
\r
3727 toint(s->responselen - (s->p-s->response)) <
\r
3730 s->commentp = (char *)s->p;
\r
3731 s->p += s->commentlen;
\r
3735 logevent("Pageant key list packet was truncated");
\r
3739 if (s->publickey_blob) {
\r
3740 if (!memcmp(pkblob, s->publickey_blob,
\r
3741 s->publickey_bloblen)) {
\r
3742 logeventf(ssh, "Pageant key #%d matches "
\r
3743 "configured key file", s->keyi);
\r
3744 s->tried_publickey = 1;
\r
3746 /* Skip non-configured key */
\r
3749 logeventf(ssh, "Trying Pageant key #%d", s->keyi);
\r
3750 send_packet(ssh, SSH1_CMSG_AUTH_RSA,
\r
3751 PKT_BIGNUM, s->key.modulus, PKT_END);
\r
3752 crWaitUntil(pktin);
\r
3753 if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
\r
3754 logevent("Key refused");
\r
3757 logevent("Received RSA challenge");
\r
3758 if ((s->challenge = ssh1_pkt_getmp(pktin)) == NULL) {
\r
3759 bombout(("Server's RSA challenge was badly formatted"));
\r
3764 char *agentreq, *q, *ret;
\r
3767 len = 1 + 4; /* message type, bit count */
\r
3768 len += ssh1_bignum_length(s->key.exponent);
\r
3769 len += ssh1_bignum_length(s->key.modulus);
\r
3770 len += ssh1_bignum_length(s->challenge);
\r
3771 len += 16; /* session id */
\r
3772 len += 4; /* response format */
\r
3773 agentreq = snewn(4 + len, char);
\r
3774 PUT_32BIT(agentreq, len);
\r
3776 *q++ = SSH1_AGENTC_RSA_CHALLENGE;
\r
3777 PUT_32BIT(q, bignum_bitcount(s->key.modulus));
\r
3779 q += ssh1_write_bignum(q, s->key.exponent);
\r
3780 q += ssh1_write_bignum(q, s->key.modulus);
\r
3781 q += ssh1_write_bignum(q, s->challenge);
\r
3782 memcpy(q, s->session_id, 16);
\r
3784 PUT_32BIT(q, 1); /* response format */
\r
3785 if (!agent_query(agentreq, len + 4, &vret, &retlen,
\r
3786 ssh_agent_callback, ssh)) {
\r
3791 bombout(("Unexpected data from server"
\r
3792 " while waiting for agent"
\r
3796 } while (pktin || inlen > 0);
\r
3797 vret = ssh->agent_response;
\r
3798 retlen = ssh->agent_response_len;
\r
3803 if (ret[4] == SSH1_AGENT_RSA_RESPONSE) {
\r
3804 logevent("Sending Pageant's response");
\r
3805 send_packet(ssh, SSH1_CMSG_AUTH_RSA_RESPONSE,
\r
3806 PKT_DATA, ret + 5, 16,
\r
3809 crWaitUntil(pktin);
\r
3810 if (pktin->type == SSH1_SMSG_SUCCESS) {
\r
3812 ("Pageant's response accepted");
\r
3813 if (flags & FLAG_VERBOSE) {
\r
3814 c_write_str(ssh, "Authenticated using"
\r
3816 c_write(ssh, s->commentp,
\r
3818 c_write_str(ssh, "\" from agent\r\n");
\r
3823 ("Pageant's response not accepted");
\r
3826 ("Pageant failed to answer challenge");
\r
3830 logevent("No reply received from Pageant");
\r
3833 freebn(s->key.exponent);
\r
3834 freebn(s->key.modulus);
\r
3835 freebn(s->challenge);
\r
3839 sfree(s->response);
\r
3840 if (s->publickey_blob && !s->tried_publickey)
\r
3841 logevent("Configured key file not in Pageant");
\r
3843 logevent("Failed to get reply from Pageant");
\r
3848 if (s->publickey_blob && !s->tried_publickey) {
\r
3850 * Try public key authentication with the specified
\r
3853 int got_passphrase; /* need not be kept over crReturn */
\r
3854 if (flags & FLAG_VERBOSE)
\r
3855 c_write_str(ssh, "Trying public key authentication.\r\n");
\r
3856 s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
\r
3857 logeventf(ssh, "Trying public key \"%s\"",
\r
3858 filename_to_str(s->keyfile));
\r
3859 s->tried_publickey = 1;
\r
3860 got_passphrase = FALSE;
\r
3861 while (!got_passphrase) {
\r
3863 * Get a passphrase, if necessary.
\r
3865 char *passphrase = NULL; /* only written after crReturn */
\r
3866 const char *error;
\r
3867 if (!s->publickey_encrypted) {
\r
3868 if (flags & FLAG_VERBOSE)
\r
3869 c_write_str(ssh, "No passphrase required.\r\n");
\r
3870 passphrase = NULL;
\r
3872 int ret; /* need not be kept over crReturn */
\r
3873 s->cur_prompt = new_prompts(ssh->frontend);
\r
3874 s->cur_prompt->to_server = FALSE;
\r
3875 s->cur_prompt->name = dupstr("SSH key passphrase");
\r
3876 add_prompt(s->cur_prompt,
\r
3877 dupprintf("Passphrase for key \"%.100s\": ",
\r
3878 s->publickey_comment), FALSE);
\r
3879 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
3882 crWaitUntil(!pktin);
\r
3883 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
3887 /* Failed to get a passphrase. Terminate. */
\r
3888 free_prompts(s->cur_prompt);
\r
3889 ssh_disconnect(ssh, NULL, "Unable to authenticate",
\r
3893 passphrase = dupstr(s->cur_prompt->prompts[0]->result);
\r
3894 free_prompts(s->cur_prompt);
\r
3897 * Try decrypting key with passphrase.
\r
3899 s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
\r
3900 ret = loadrsakey(s->keyfile, &s->key, passphrase,
\r
3903 smemclr(passphrase, strlen(passphrase));
\r
3904 sfree(passphrase);
\r
3907 /* Correct passphrase. */
\r
3908 got_passphrase = TRUE;
\r
3909 } else if (ret == 0) {
\r
3910 c_write_str(ssh, "Couldn't load private key from ");
\r
3911 c_write_str(ssh, filename_to_str(s->keyfile));
\r
3912 c_write_str(ssh, " (");
\r
3913 c_write_str(ssh, error);
\r
3914 c_write_str(ssh, ").\r\n");
\r
3915 got_passphrase = FALSE;
\r
3916 break; /* go and try something else */
\r
3917 } else if (ret == -1) {
\r
3918 c_write_str(ssh, "Wrong passphrase.\r\n"); /* FIXME */
\r
3919 got_passphrase = FALSE;
\r
3920 /* and try again */
\r
3922 assert(0 && "unexpected return from loadrsakey()");
\r
3923 got_passphrase = FALSE; /* placate optimisers */
\r
3927 if (got_passphrase) {
\r
3930 * Send a public key attempt.
\r
3932 send_packet(ssh, SSH1_CMSG_AUTH_RSA,
\r
3933 PKT_BIGNUM, s->key.modulus, PKT_END);
\r
3935 crWaitUntil(pktin);
\r
3936 if (pktin->type == SSH1_SMSG_FAILURE) {
\r
3937 c_write_str(ssh, "Server refused our public key.\r\n");
\r
3938 continue; /* go and try something else */
\r
3940 if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
\r
3941 bombout(("Bizarre response to offer of public key"));
\r
3947 unsigned char buffer[32];
\r
3948 Bignum challenge, response;
\r
3950 if ((challenge = ssh1_pkt_getmp(pktin)) == NULL) {
\r
3951 bombout(("Server's RSA challenge was badly formatted"));
\r
3954 response = rsadecrypt(challenge, &s->key);
\r
3955 freebn(s->key.private_exponent);/* burn the evidence */
\r
3957 for (i = 0; i < 32; i++) {
\r
3958 buffer[i] = bignum_byte(response, 31 - i);
\r
3962 MD5Update(&md5c, buffer, 32);
\r
3963 MD5Update(&md5c, s->session_id, 16);
\r
3964 MD5Final(buffer, &md5c);
\r
3966 send_packet(ssh, SSH1_CMSG_AUTH_RSA_RESPONSE,
\r
3967 PKT_DATA, buffer, 16, PKT_END);
\r
3969 freebn(challenge);
\r
3973 crWaitUntil(pktin);
\r
3974 if (pktin->type == SSH1_SMSG_FAILURE) {
\r
3975 if (flags & FLAG_VERBOSE)
\r
3976 c_write_str(ssh, "Failed to authenticate with"
\r
3977 " our public key.\r\n");
\r
3978 continue; /* go and try something else */
\r
3979 } else if (pktin->type != SSH1_SMSG_SUCCESS) {
\r
3980 bombout(("Bizarre response to RSA authentication response"));
\r
3984 break; /* we're through! */
\r
3990 * Otherwise, try various forms of password-like authentication.
\r
3992 s->cur_prompt = new_prompts(ssh->frontend);
\r
3994 if (conf_get_int(ssh->conf, CONF_try_tis_auth) &&
\r
3995 (s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
\r
3996 !s->tis_auth_refused) {
\r
3997 s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
\r
3998 logevent("Requested TIS authentication");
\r
3999 send_packet(ssh, SSH1_CMSG_AUTH_TIS, PKT_END);
\r
4000 crWaitUntil(pktin);
\r
4001 if (pktin->type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
\r
4002 logevent("TIS authentication declined");
\r
4003 if (flags & FLAG_INTERACTIVE)
\r
4004 c_write_str(ssh, "TIS authentication refused.\r\n");
\r
4005 s->tis_auth_refused = 1;
\r
4010 char *instr_suf, *prompt;
\r
4012 ssh_pkt_getstring(pktin, &challenge, &challengelen);
\r
4014 bombout(("TIS challenge packet was badly formed"));
\r
4017 logevent("Received TIS challenge");
\r
4018 s->cur_prompt->to_server = TRUE;
\r
4019 s->cur_prompt->name = dupstr("SSH TIS authentication");
\r
4020 /* Prompt heuristic comes from OpenSSH */
\r
4021 if (memchr(challenge, '\n', challengelen)) {
\r
4022 instr_suf = dupstr("");
\r
4023 prompt = dupprintf("%.*s", challengelen, challenge);
\r
4025 instr_suf = dupprintf("%.*s", challengelen, challenge);
\r
4026 prompt = dupstr("Response: ");
\r
4028 s->cur_prompt->instruction =
\r
4029 dupprintf("Using TIS authentication.%s%s",
\r
4030 (*instr_suf) ? "\n" : "",
\r
4032 s->cur_prompt->instr_reqd = TRUE;
\r
4033 add_prompt(s->cur_prompt, prompt, FALSE);
\r
4037 if (conf_get_int(ssh->conf, CONF_try_tis_auth) &&
\r
4038 (s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
\r
4039 !s->ccard_auth_refused) {
\r
4040 s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
\r
4041 logevent("Requested CryptoCard authentication");
\r
4042 send_packet(ssh, SSH1_CMSG_AUTH_CCARD, PKT_END);
\r
4043 crWaitUntil(pktin);
\r
4044 if (pktin->type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
\r
4045 logevent("CryptoCard authentication declined");
\r
4046 c_write_str(ssh, "CryptoCard authentication refused.\r\n");
\r
4047 s->ccard_auth_refused = 1;
\r
4052 char *instr_suf, *prompt;
\r
4054 ssh_pkt_getstring(pktin, &challenge, &challengelen);
\r
4056 bombout(("CryptoCard challenge packet was badly formed"));
\r
4059 logevent("Received CryptoCard challenge");
\r
4060 s->cur_prompt->to_server = TRUE;
\r
4061 s->cur_prompt->name = dupstr("SSH CryptoCard authentication");
\r
4062 s->cur_prompt->name_reqd = FALSE;
\r
4063 /* Prompt heuristic comes from OpenSSH */
\r
4064 if (memchr(challenge, '\n', challengelen)) {
\r
4065 instr_suf = dupstr("");
\r
4066 prompt = dupprintf("%.*s", challengelen, challenge);
\r
4068 instr_suf = dupprintf("%.*s", challengelen, challenge);
\r
4069 prompt = dupstr("Response: ");
\r
4071 s->cur_prompt->instruction =
\r
4072 dupprintf("Using CryptoCard authentication.%s%s",
\r
4073 (*instr_suf) ? "\n" : "",
\r
4075 s->cur_prompt->instr_reqd = TRUE;
\r
4076 add_prompt(s->cur_prompt, prompt, FALSE);
\r
4080 if (s->pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
\r
4081 if ((s->supported_auths_mask & (1 << SSH1_AUTH_PASSWORD)) == 0) {
\r
4082 bombout(("No supported authentication methods available"));
\r
4085 s->cur_prompt->to_server = TRUE;
\r
4086 s->cur_prompt->name = dupstr("SSH password");
\r
4087 add_prompt(s->cur_prompt, dupprintf("%s@%s's password: ",
\r
4088 ssh->username, ssh->savedhost),
\r
4093 * Show password prompt, having first obtained it via a TIS
\r
4094 * or CryptoCard exchange if we're doing TIS or CryptoCard
\r
4098 int ret; /* need not be kept over crReturn */
\r
4099 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
4102 crWaitUntil(!pktin);
\r
4103 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
4108 * Failed to get a password (for example
\r
4109 * because one was supplied on the command line
\r
4110 * which has already failed to work). Terminate.
\r
4112 free_prompts(s->cur_prompt);
\r
4113 ssh_disconnect(ssh, NULL, "Unable to authenticate", 0, TRUE);
\r
4118 if (s->pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
\r
4120 * Defence against traffic analysis: we send a
\r
4121 * whole bunch of packets containing strings of
\r
4122 * different lengths. One of these strings is the
\r
4123 * password, in a SSH1_CMSG_AUTH_PASSWORD packet.
\r
4124 * The others are all random data in
\r
4125 * SSH1_MSG_IGNORE packets. This way a passive
\r
4126 * listener can't tell which is the password, and
\r
4127 * hence can't deduce the password length.
\r
4129 * Anybody with a password length greater than 16
\r
4130 * bytes is going to have enough entropy in their
\r
4131 * password that a listener won't find it _that_
\r
4132 * much help to know how long it is. So what we'll
\r
4135 * - if password length < 16, we send 15 packets
\r
4136 * containing string lengths 1 through 15
\r
4138 * - otherwise, we let N be the nearest multiple
\r
4139 * of 8 below the password length, and send 8
\r
4140 * packets containing string lengths N through
\r
4141 * N+7. This won't obscure the order of
\r
4142 * magnitude of the password length, but it will
\r
4143 * introduce a bit of extra uncertainty.
\r
4145 * A few servers can't deal with SSH1_MSG_IGNORE, at
\r
4146 * least in this context. For these servers, we need
\r
4147 * an alternative defence. We make use of the fact
\r
4148 * that the password is interpreted as a C string:
\r
4149 * so we can append a NUL, then some random data.
\r
4151 * A few servers can deal with neither SSH1_MSG_IGNORE
\r
4152 * here _nor_ a padded password string.
\r
4153 * For these servers we are left with no defences
\r
4154 * against password length sniffing.
\r
4156 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE) &&
\r
4157 !(ssh->remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
\r
4159 * The server can deal with SSH1_MSG_IGNORE, so
\r
4160 * we can use the primary defence.
\r
4162 int bottom, top, pwlen, i;
\r
4165 pwlen = strlen(s->cur_prompt->prompts[0]->result);
\r
4167 bottom = 0; /* zero length passwords are OK! :-) */
\r
4170 bottom = pwlen & ~7;
\r
4174 assert(pwlen >= bottom && pwlen <= top);
\r
4176 randomstr = snewn(top + 1, char);
\r
4178 for (i = bottom; i <= top; i++) {
\r
4180 defer_packet(ssh, s->pwpkt_type,
\r
4181 PKTT_PASSWORD, PKT_STR,
\r
4182 s->cur_prompt->prompts[0]->result,
\r
4183 PKTT_OTHER, PKT_END);
\r
4185 for (j = 0; j < i; j++) {
\r
4187 randomstr[j] = random_byte();
\r
4188 } while (randomstr[j] == '\0');
\r
4190 randomstr[i] = '\0';
\r
4191 defer_packet(ssh, SSH1_MSG_IGNORE,
\r
4192 PKT_STR, randomstr, PKT_END);
\r
4195 logevent("Sending password with camouflage packets");
\r
4196 ssh_pkt_defersend(ssh);
\r
4199 else if (!(ssh->remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
\r
4201 * The server can't deal with SSH1_MSG_IGNORE
\r
4202 * but can deal with padded passwords, so we
\r
4203 * can use the secondary defence.
\r
4209 len = strlen(s->cur_prompt->prompts[0]->result);
\r
4210 if (len < sizeof(string)) {
\r
4212 strcpy(string, s->cur_prompt->prompts[0]->result);
\r
4213 len++; /* cover the zero byte */
\r
4214 while (len < sizeof(string)) {
\r
4215 string[len++] = (char) random_byte();
\r
4218 ss = s->cur_prompt->prompts[0]->result;
\r
4220 logevent("Sending length-padded password");
\r
4221 send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
\r
4222 PKT_INT, len, PKT_DATA, ss, len,
\r
4223 PKTT_OTHER, PKT_END);
\r
4226 * The server is believed unable to cope with
\r
4227 * any of our password camouflage methods.
\r
4230 len = strlen(s->cur_prompt->prompts[0]->result);
\r
4231 logevent("Sending unpadded password");
\r
4232 send_packet(ssh, s->pwpkt_type,
\r
4233 PKTT_PASSWORD, PKT_INT, len,
\r
4234 PKT_DATA, s->cur_prompt->prompts[0]->result, len,
\r
4235 PKTT_OTHER, PKT_END);
\r
4238 send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
\r
4239 PKT_STR, s->cur_prompt->prompts[0]->result,
\r
4240 PKTT_OTHER, PKT_END);
\r
4242 logevent("Sent password");
\r
4243 free_prompts(s->cur_prompt);
\r
4244 crWaitUntil(pktin);
\r
4245 if (pktin->type == SSH1_SMSG_FAILURE) {
\r
4246 if (flags & FLAG_VERBOSE)
\r
4247 c_write_str(ssh, "Access denied\r\n");
\r
4248 logevent("Authentication refused");
\r
4249 } else if (pktin->type != SSH1_SMSG_SUCCESS) {
\r
4250 bombout(("Strange packet received, type %d", pktin->type));
\r
4256 if (s->publickey_blob) {
\r
4257 sfree(s->publickey_blob);
\r
4258 sfree(s->publickey_comment);
\r
4261 logevent("Authentication successful");
\r
4266 static void ssh_channel_try_eof(struct ssh_channel *c)
\r
4269 assert(c->pending_eof); /* precondition for calling us */
\r
4271 return; /* can't close: not even opened yet */
\r
4272 if (ssh->version == 2 && bufchain_size(&c->v.v2.outbuffer) > 0)
\r
4273 return; /* can't send EOF: pending outgoing data */
\r
4275 c->pending_eof = FALSE; /* we're about to send it */
\r
4276 if (ssh->version == 1) {
\r
4277 send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid,
\r
4279 c->closes |= CLOSES_SENT_EOF;
\r
4281 struct Packet *pktout;
\r
4282 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_EOF);
\r
4283 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
4284 ssh2_pkt_send(ssh, pktout);
\r
4285 c->closes |= CLOSES_SENT_EOF;
\r
4286 ssh2_channel_check_close(c);
\r
4290 void sshfwd_write_eof(struct ssh_channel *c)
\r
4294 if (ssh->state == SSH_STATE_CLOSED)
\r
4297 if (c->closes & CLOSES_SENT_EOF)
\r
4300 c->pending_eof = TRUE;
\r
4301 ssh_channel_try_eof(c);
\r
4304 void sshfwd_unclean_close(struct ssh_channel *c)
\r
4308 if (ssh->state == SSH_STATE_CLOSED)
\r
4311 switch (c->type) {
\r
4313 x11_close(c->u.x11.s);
\r
4314 logevent("Forwarded X11 connection terminated due to local error");
\r
4316 case CHAN_SOCKDATA:
\r
4317 case CHAN_SOCKDATA_DORMANT:
\r
4318 pfd_close(c->u.pfd.s);
\r
4319 logevent("Forwarded port closed due to local error");
\r
4322 c->type = CHAN_ZOMBIE;
\r
4324 ssh2_channel_check_close(c);
\r
4327 int sshfwd_write(struct ssh_channel *c, char *buf, int len)
\r
4331 if (ssh->state == SSH_STATE_CLOSED)
\r
4334 if (ssh->version == 1) {
\r
4335 send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
\r
4336 PKT_INT, c->remoteid,
\r
4337 PKT_INT, len, PKTT_DATA, PKT_DATA, buf, len,
\r
4338 PKTT_OTHER, PKT_END);
\r
4340 * In SSH-1 we can return 0 here - implying that forwarded
\r
4341 * connections are never individually throttled - because
\r
4342 * the only circumstance that can cause throttling will be
\r
4343 * the whole SSH connection backing up, in which case
\r
4344 * _everything_ will be throttled as a whole.
\r
4348 ssh2_add_channel_data(c, buf, len);
\r
4349 return ssh2_try_send(c);
\r
4353 void sshfwd_unthrottle(struct ssh_channel *c, int bufsize)
\r
4358 if (ssh->state == SSH_STATE_CLOSED)
\r
4361 if (ssh->version == 1) {
\r
4362 buflimit = SSH1_BUFFER_LIMIT;
\r
4364 buflimit = c->v.v2.locmaxwin;
\r
4365 ssh2_set_window(c, bufsize < buflimit ? buflimit - bufsize : 0);
\r
4367 if (c->throttling_conn && bufsize <= buflimit) {
\r
4368 c->throttling_conn = 0;
\r
4369 ssh_throttle_conn(ssh, -1);
\r
4373 static void ssh_queueing_handler(Ssh ssh, struct Packet *pktin)
\r
4375 struct queued_handler *qh = ssh->qhead;
\r
4377 assert(qh != NULL);
\r
4379 assert(pktin->type == qh->msg1 || pktin->type == qh->msg2);
\r
4381 if (qh->msg1 > 0) {
\r
4382 assert(ssh->packet_dispatch[qh->msg1] == ssh_queueing_handler);
\r
4383 ssh->packet_dispatch[qh->msg1] = ssh->q_saved_handler1;
\r
4385 if (qh->msg2 > 0) {
\r
4386 assert(ssh->packet_dispatch[qh->msg2] == ssh_queueing_handler);
\r
4387 ssh->packet_dispatch[qh->msg2] = ssh->q_saved_handler2;
\r
4391 ssh->qhead = qh->next;
\r
4393 if (ssh->qhead->msg1 > 0) {
\r
4394 ssh->q_saved_handler1 = ssh->packet_dispatch[ssh->qhead->msg1];
\r
4395 ssh->packet_dispatch[ssh->qhead->msg1] = ssh_queueing_handler;
\r
4397 if (ssh->qhead->msg2 > 0) {
\r
4398 ssh->q_saved_handler2 = ssh->packet_dispatch[ssh->qhead->msg2];
\r
4399 ssh->packet_dispatch[ssh->qhead->msg2] = ssh_queueing_handler;
\r
4402 ssh->qhead = ssh->qtail = NULL;
\r
4405 qh->handler(ssh, pktin, qh->ctx);
\r
4410 static void ssh_queue_handler(Ssh ssh, int msg1, int msg2,
\r
4411 chandler_fn_t handler, void *ctx)
\r
4413 struct queued_handler *qh;
\r
4415 qh = snew(struct queued_handler);
\r
4418 qh->handler = handler;
\r
4422 if (ssh->qtail == NULL) {
\r
4425 if (qh->msg1 > 0) {
\r
4426 ssh->q_saved_handler1 = ssh->packet_dispatch[ssh->qhead->msg1];
\r
4427 ssh->packet_dispatch[qh->msg1] = ssh_queueing_handler;
\r
4429 if (qh->msg2 > 0) {
\r
4430 ssh->q_saved_handler2 = ssh->packet_dispatch[ssh->qhead->msg2];
\r
4431 ssh->packet_dispatch[qh->msg2] = ssh_queueing_handler;
\r
4434 ssh->qtail->next = qh;
\r
4439 static void ssh_rportfwd_succfail(Ssh ssh, struct Packet *pktin, void *ctx)
\r
4441 struct ssh_rportfwd *rpf, *pf = (struct ssh_rportfwd *)ctx;
\r
4443 if (pktin->type == (ssh->version == 1 ? SSH1_SMSG_SUCCESS :
\r
4444 SSH2_MSG_REQUEST_SUCCESS)) {
\r
4445 logeventf(ssh, "Remote port forwarding from %s enabled",
\r
4448 logeventf(ssh, "Remote port forwarding from %s refused",
\r
4451 rpf = del234(ssh->rportfwds, pf);
\r
4452 assert(rpf == pf);
\r
4453 pf->pfrec->remote = NULL;
\r
4454 free_rportfwd(pf);
\r
4458 static void ssh_setup_portfwd(Ssh ssh, Conf *conf)
\r
4460 struct ssh_portfwd *epf;
\r
4464 if (!ssh->portfwds) {
\r
4465 ssh->portfwds = newtree234(ssh_portcmp);
\r
4468 * Go through the existing port forwardings and tag them
\r
4469 * with status==DESTROY. Any that we want to keep will be
\r
4470 * re-enabled (status==KEEP) as we go through the
\r
4471 * configuration and find out which bits are the same as
\r
4472 * they were before.
\r
4474 struct ssh_portfwd *epf;
\r
4476 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
\r
4477 epf->status = DESTROY;
\r
4480 for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
\r
4482 val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
\r
4483 char *kp, *kp2, *vp, *vp2;
\r
4484 char address_family, type;
\r
4485 int sport,dport,sserv,dserv;
\r
4486 char *sports, *dports, *saddr, *host;
\r
4490 address_family = 'A';
\r
4492 if (*kp == 'A' || *kp == '4' || *kp == '6')
\r
4493 address_family = *kp++;
\r
4494 if (*kp == 'L' || *kp == 'R')
\r
4497 if ((kp2 = strchr(kp, ':')) != NULL) {
\r
4499 * There's a colon in the middle of the source port
\r
4500 * string, which means that the part before it is
\r
4501 * actually a source address.
\r
4503 saddr = dupprintf("%.*s", (int)(kp2 - kp), kp);
\r
4509 sport = atoi(sports);
\r
4513 sport = net_service_lookup(sports);
\r
4515 logeventf(ssh, "Service lookup failed for source"
\r
4516 " port \"%s\"", sports);
\r
4520 if (type == 'L' && !strcmp(val, "D")) {
\r
4521 /* dynamic forwarding */
\r
4528 /* ordinary forwarding */
\r
4530 vp2 = vp + strcspn(vp, ":");
\r
4531 host = dupprintf("%.*s", (int)(vp2 - vp), vp);
\r
4535 dport = atoi(dports);
\r
4539 dport = net_service_lookup(dports);
\r
4541 logeventf(ssh, "Service lookup failed for destination"
\r
4542 " port \"%s\"", dports);
\r
4547 if (sport && dport) {
\r
4548 /* Set up a description of the source port. */
\r
4549 struct ssh_portfwd *pfrec, *epfrec;
\r
4551 pfrec = snew(struct ssh_portfwd);
\r
4552 pfrec->type = type;
\r
4553 pfrec->saddr = saddr;
\r
4554 pfrec->sserv = sserv ? dupstr(sports) : NULL;
\r
4555 pfrec->sport = sport;
\r
4556 pfrec->daddr = host;
\r
4557 pfrec->dserv = dserv ? dupstr(dports) : NULL;
\r
4558 pfrec->dport = dport;
\r
4559 pfrec->local = NULL;
\r
4560 pfrec->remote = NULL;
\r
4561 pfrec->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
\r
4562 address_family == '6' ? ADDRTYPE_IPV6 :
\r
4565 epfrec = add234(ssh->portfwds, pfrec);
\r
4566 if (epfrec != pfrec) {
\r
4567 if (epfrec->status == DESTROY) {
\r
4569 * We already have a port forwarding up and running
\r
4570 * with precisely these parameters. Hence, no need
\r
4571 * to do anything; simply re-tag the existing one
\r
4574 epfrec->status = KEEP;
\r
4577 * Anything else indicates that there was a duplicate
\r
4578 * in our input, which we'll silently ignore.
\r
4580 free_portfwd(pfrec);
\r
4582 pfrec->status = CREATE;
\r
4591 * Now go through and destroy any port forwardings which were
\r
4594 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
\r
4595 if (epf->status == DESTROY) {
\r
4598 message = dupprintf("%s port forwarding from %s%s%d",
\r
4599 epf->type == 'L' ? "local" :
\r
4600 epf->type == 'R' ? "remote" : "dynamic",
\r
4601 epf->saddr ? epf->saddr : "",
\r
4602 epf->saddr ? ":" : "",
\r
4605 if (epf->type != 'D') {
\r
4606 char *msg2 = dupprintf("%s to %s:%d", message,
\r
4607 epf->daddr, epf->dport);
\r
4612 logeventf(ssh, "Cancelling %s", message);
\r
4615 /* epf->remote or epf->local may be NULL if setting up a
\r
4616 * forwarding failed. */
\r
4617 if (epf->remote) {
\r
4618 struct ssh_rportfwd *rpf = epf->remote;
\r
4619 struct Packet *pktout;
\r
4622 * Cancel the port forwarding at the server
\r
4625 if (ssh->version == 1) {
\r
4627 * We cannot cancel listening ports on the
\r
4628 * server side in SSH-1! There's no message
\r
4629 * to support it. Instead, we simply remove
\r
4630 * the rportfwd record from the local end
\r
4631 * so that any connections the server tries
\r
4632 * to make on it are rejected.
\r
4635 pktout = ssh2_pkt_init(SSH2_MSG_GLOBAL_REQUEST);
\r
4636 ssh2_pkt_addstring(pktout, "cancel-tcpip-forward");
\r
4637 ssh2_pkt_addbool(pktout, 0);/* _don't_ want reply */
\r
4639 ssh2_pkt_addstring(pktout, epf->saddr);
\r
4640 } else if (conf_get_int(conf, CONF_rport_acceptall)) {
\r
4641 /* XXX: rport_acceptall may not represent
\r
4642 * what was used to open the original connection,
\r
4643 * since it's reconfigurable. */
\r
4644 ssh2_pkt_addstring(pktout, "");
\r
4646 ssh2_pkt_addstring(pktout, "localhost");
\r
4648 ssh2_pkt_adduint32(pktout, epf->sport);
\r
4649 ssh2_pkt_send(ssh, pktout);
\r
4652 del234(ssh->rportfwds, rpf);
\r
4653 free_rportfwd(rpf);
\r
4654 } else if (epf->local) {
\r
4655 pfd_terminate(epf->local);
\r
4658 delpos234(ssh->portfwds, i);
\r
4659 free_portfwd(epf);
\r
4660 i--; /* so we don't skip one in the list */
\r
4664 * And finally, set up any new port forwardings (status==CREATE).
\r
4666 for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
\r
4667 if (epf->status == CREATE) {
\r
4668 char *sportdesc, *dportdesc;
\r
4669 sportdesc = dupprintf("%s%s%s%s%d%s",
\r
4670 epf->saddr ? epf->saddr : "",
\r
4671 epf->saddr ? ":" : "",
\r
4672 epf->sserv ? epf->sserv : "",
\r
4673 epf->sserv ? "(" : "",
\r
4675 epf->sserv ? ")" : "");
\r
4676 if (epf->type == 'D') {
\r
4679 dportdesc = dupprintf("%s:%s%s%d%s",
\r
4681 epf->dserv ? epf->dserv : "",
\r
4682 epf->dserv ? "(" : "",
\r
4684 epf->dserv ? ")" : "");
\r
4687 if (epf->type == 'L') {
\r
4688 const char *err = pfd_addforward(epf->daddr, epf->dport,
\r
4689 epf->saddr, epf->sport,
\r
4692 epf->addressfamily);
\r
4694 logeventf(ssh, "Local %sport %s forwarding to %s%s%s",
\r
4695 epf->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
\r
4696 epf->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
\r
4697 sportdesc, dportdesc,
\r
4698 err ? " failed: " : "", err ? err : "");
\r
4699 } else if (epf->type == 'D') {
\r
4700 const char *err = pfd_addforward(NULL, -1,
\r
4701 epf->saddr, epf->sport,
\r
4704 epf->addressfamily);
\r
4706 logeventf(ssh, "Local %sport %s SOCKS dynamic forwarding%s%s",
\r
4707 epf->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
\r
4708 epf->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
\r
4710 err ? " failed: " : "", err ? err : "");
\r
4712 struct ssh_rportfwd *pf;
\r
4715 * Ensure the remote port forwardings tree exists.
\r
4717 if (!ssh->rportfwds) {
\r
4718 if (ssh->version == 1)
\r
4719 ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);
\r
4721 ssh->rportfwds = newtree234(ssh_rportcmp_ssh2);
\r
4724 pf = snew(struct ssh_rportfwd);
\r
4725 strncpy(pf->dhost, epf->daddr, lenof(pf->dhost)-1);
\r
4726 pf->dhost[lenof(pf->dhost)-1] = '\0';
\r
4727 pf->dport = epf->dport;
\r
4728 pf->sport = epf->sport;
\r
4729 if (add234(ssh->rportfwds, pf) != pf) {
\r
4730 logeventf(ssh, "Duplicate remote port forwarding to %s:%d",
\r
4731 epf->daddr, epf->dport);
\r
4734 logeventf(ssh, "Requesting remote port %s"
\r
4735 " forward to %s", sportdesc, dportdesc);
\r
4737 pf->sportdesc = sportdesc;
\r
4742 if (ssh->version == 1) {
\r
4743 send_packet(ssh, SSH1_CMSG_PORT_FORWARD_REQUEST,
\r
4744 PKT_INT, epf->sport,
\r
4745 PKT_STR, epf->daddr,
\r
4746 PKT_INT, epf->dport,
\r
4748 ssh_queue_handler(ssh, SSH1_SMSG_SUCCESS,
\r
4749 SSH1_SMSG_FAILURE,
\r
4750 ssh_rportfwd_succfail, pf);
\r
4752 struct Packet *pktout;
\r
4753 pktout = ssh2_pkt_init(SSH2_MSG_GLOBAL_REQUEST);
\r
4754 ssh2_pkt_addstring(pktout, "tcpip-forward");
\r
4755 ssh2_pkt_addbool(pktout, 1);/* want reply */
\r
4757 ssh2_pkt_addstring(pktout, epf->saddr);
\r
4758 } else if (conf_get_int(conf, CONF_rport_acceptall)) {
\r
4759 ssh2_pkt_addstring(pktout, "");
\r
4761 ssh2_pkt_addstring(pktout, "localhost");
\r
4763 ssh2_pkt_adduint32(pktout, epf->sport);
\r
4764 ssh2_pkt_send(ssh, pktout);
\r
4766 ssh_queue_handler(ssh, SSH2_MSG_REQUEST_SUCCESS,
\r
4767 SSH2_MSG_REQUEST_FAILURE,
\r
4768 ssh_rportfwd_succfail, pf);
\r
4777 static void ssh1_smsg_stdout_stderr_data(Ssh ssh, struct Packet *pktin)
\r
4780 int stringlen, bufsize;
\r
4782 ssh_pkt_getstring(pktin, &string, &stringlen);
\r
4783 if (string == NULL) {
\r
4784 bombout(("Incoming terminal data packet was badly formed"));
\r
4788 bufsize = from_backend(ssh->frontend, pktin->type == SSH1_SMSG_STDERR_DATA,
\r
4789 string, stringlen);
\r
4790 if (!ssh->v1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
\r
4791 ssh->v1_stdout_throttling = 1;
\r
4792 ssh_throttle_conn(ssh, +1);
\r
4796 static void ssh1_smsg_x11_open(Ssh ssh, struct Packet *pktin)
\r
4798 /* Remote side is trying to open a channel to talk to our
\r
4799 * X-Server. Give them back a local channel number. */
\r
4800 struct ssh_channel *c;
\r
4801 int remoteid = ssh_pkt_getuint32(pktin);
\r
4803 logevent("Received X11 connect request");
\r
4804 /* Refuse if X11 forwarding is disabled. */
\r
4805 if (!ssh->X11_fwd_enabled) {
\r
4806 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
\r
4807 PKT_INT, remoteid, PKT_END);
\r
4808 logevent("Rejected X11 connect request");
\r
4810 c = snew(struct ssh_channel);
\r
4813 if (x11_init(&c->u.x11.s, ssh->x11disp, c,
\r
4814 NULL, -1, ssh->conf) != NULL) {
\r
4815 logevent("Opening X11 forward connection failed");
\r
4817 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
\r
4818 PKT_INT, remoteid, PKT_END);
\r
4821 ("Opening X11 forward connection succeeded");
\r
4822 c->remoteid = remoteid;
\r
4823 c->halfopen = FALSE;
\r
4824 c->localid = alloc_channel_id(ssh);
\r
4826 c->pending_eof = FALSE;
\r
4827 c->throttling_conn = 0;
\r
4828 c->type = CHAN_X11; /* identify channel type */
\r
4829 add234(ssh->channels, c);
\r
4830 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
\r
4831 PKT_INT, c->remoteid, PKT_INT,
\r
4832 c->localid, PKT_END);
\r
4833 logevent("Opened X11 forward channel");
\r
4838 static void ssh1_smsg_agent_open(Ssh ssh, struct Packet *pktin)
\r
4840 /* Remote side is trying to open a channel to talk to our
\r
4841 * agent. Give them back a local channel number. */
\r
4842 struct ssh_channel *c;
\r
4843 int remoteid = ssh_pkt_getuint32(pktin);
\r
4845 /* Refuse if agent forwarding is disabled. */
\r
4846 if (!ssh->agentfwd_enabled) {
\r
4847 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
\r
4848 PKT_INT, remoteid, PKT_END);
\r
4850 c = snew(struct ssh_channel);
\r
4852 c->remoteid = remoteid;
\r
4853 c->halfopen = FALSE;
\r
4854 c->localid = alloc_channel_id(ssh);
\r
4856 c->pending_eof = FALSE;
\r
4857 c->throttling_conn = 0;
\r
4858 c->type = CHAN_AGENT; /* identify channel type */
\r
4859 c->u.a.lensofar = 0;
\r
4860 c->u.a.message = NULL;
\r
4861 c->u.a.outstanding_requests = 0;
\r
4862 add234(ssh->channels, c);
\r
4863 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
\r
4864 PKT_INT, c->remoteid, PKT_INT, c->localid,
\r
4869 static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
\r
4871 /* Remote side is trying to open a channel to talk to a
\r
4872 * forwarded port. Give them back a local channel number. */
\r
4873 struct ssh_rportfwd pf, *pfp;
\r
4875 int hostsize, port;
\r
4879 remoteid = ssh_pkt_getuint32(pktin);
\r
4880 ssh_pkt_getstring(pktin, &host, &hostsize);
\r
4881 port = ssh_pkt_getuint32(pktin);
\r
4883 if (hostsize >= lenof(pf.dhost))
\r
4884 hostsize = lenof(pf.dhost)-1;
\r
4885 memcpy(pf.dhost, host, hostsize);
\r
4886 pf.dhost[hostsize] = '\0';
\r
4888 pfp = find234(ssh->rportfwds, &pf, NULL);
\r
4890 if (pfp == NULL) {
\r
4891 logeventf(ssh, "Rejected remote port open request for %s:%d",
\r
4893 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
\r
4894 PKT_INT, remoteid, PKT_END);
\r
4896 struct ssh_channel *c = snew(struct ssh_channel);
\r
4899 logeventf(ssh, "Received remote port open request for %s:%d",
\r
4901 e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
\r
4902 c, ssh->conf, pfp->pfrec->addressfamily);
\r
4904 logeventf(ssh, "Port open failed: %s", e);
\r
4906 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
\r
4907 PKT_INT, remoteid, PKT_END);
\r
4909 c->remoteid = remoteid;
\r
4910 c->halfopen = FALSE;
\r
4911 c->localid = alloc_channel_id(ssh);
\r
4913 c->pending_eof = FALSE;
\r
4914 c->throttling_conn = 0;
\r
4915 c->type = CHAN_SOCKDATA; /* identify channel type */
\r
4916 add234(ssh->channels, c);
\r
4917 send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
\r
4918 PKT_INT, c->remoteid, PKT_INT,
\r
4919 c->localid, PKT_END);
\r
4920 logevent("Forwarded port opened successfully");
\r
4925 static void ssh1_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
\r
4927 unsigned int remoteid = ssh_pkt_getuint32(pktin);
\r
4928 unsigned int localid = ssh_pkt_getuint32(pktin);
\r
4929 struct ssh_channel *c;
\r
4931 c = find234(ssh->channels, &remoteid, ssh_channelfind);
\r
4932 if (c && c->type == CHAN_SOCKDATA_DORMANT) {
\r
4933 c->remoteid = localid;
\r
4934 c->halfopen = FALSE;
\r
4935 c->type = CHAN_SOCKDATA;
\r
4936 c->throttling_conn = 0;
\r
4937 pfd_confirm(c->u.pfd.s);
\r
4940 if (c && c->pending_eof) {
\r
4942 * We have a pending close on this channel,
\r
4943 * which we decided on before the server acked
\r
4944 * the channel open. So now we know the
\r
4945 * remoteid, we can close it again.
\r
4947 ssh_channel_try_eof(c);
\r
4951 static void ssh1_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
\r
4953 unsigned int remoteid = ssh_pkt_getuint32(pktin);
\r
4954 struct ssh_channel *c;
\r
4956 c = find234(ssh->channels, &remoteid, ssh_channelfind);
\r
4957 if (c && c->type == CHAN_SOCKDATA_DORMANT) {
\r
4958 logevent("Forwarded connection refused by server");
\r
4959 pfd_close(c->u.pfd.s);
\r
4960 del234(ssh->channels, c);
\r
4965 static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
\r
4967 /* Remote side closes a channel. */
\r
4968 unsigned i = ssh_pkt_getuint32(pktin);
\r
4969 struct ssh_channel *c;
\r
4970 c = find234(ssh->channels, &i, ssh_channelfind);
\r
4971 if (c && !c->halfopen) {
\r
4973 if (pktin->type == SSH1_MSG_CHANNEL_CLOSE &&
\r
4974 !(c->closes & CLOSES_RCVD_EOF)) {
\r
4976 * Received CHANNEL_CLOSE, which we translate into
\r
4979 int send_close = FALSE;
\r
4981 c->closes |= CLOSES_RCVD_EOF;
\r
4983 switch (c->type) {
\r
4986 x11_send_eof(c->u.x11.s);
\r
4988 send_close = TRUE;
\r
4990 case CHAN_SOCKDATA:
\r
4992 pfd_send_eof(c->u.pfd.s);
\r
4994 send_close = TRUE;
\r
4997 send_close = TRUE;
\r
5001 if (send_close && !(c->closes & CLOSES_SENT_EOF)) {
\r
5002 send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid,
\r
5004 c->closes |= CLOSES_SENT_EOF;
\r
5008 if (pktin->type == SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION &&
\r
5009 !(c->closes & CLOSES_RCVD_CLOSE)) {
\r
5011 if (!(c->closes & CLOSES_SENT_EOF)) {
\r
5012 bombout(("Received CHANNEL_CLOSE_CONFIRMATION for channel %d"
\r
5013 " for which we never sent CHANNEL_CLOSE\n", i));
\r
5016 c->closes |= CLOSES_RCVD_CLOSE;
\r
5019 if (!((CLOSES_SENT_EOF | CLOSES_RCVD_EOF) & ~c->closes) &&
\r
5020 !(c->closes & CLOSES_SENT_CLOSE)) {
\r
5021 send_packet(ssh, SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION,
\r
5022 PKT_INT, c->remoteid, PKT_END);
\r
5023 c->closes |= CLOSES_SENT_CLOSE;
\r
5026 if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes))
\r
5027 ssh_channel_destroy(c);
\r
5029 bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n",
\r
5030 pktin->type == SSH1_MSG_CHANNEL_CLOSE ? "" :
\r
5031 "_CONFIRMATION", c ? "half-open" : "nonexistent",
\r
5036 static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
\r
5038 /* Data sent down one of our channels. */
\r
5039 int i = ssh_pkt_getuint32(pktin);
\r
5042 struct ssh_channel *c;
\r
5044 ssh_pkt_getstring(pktin, &p, &len);
\r
5046 c = find234(ssh->channels, &i, ssh_channelfind);
\r
5049 switch (c->type) {
\r
5051 bufsize = x11_send(c->u.x11.s, p, len);
\r
5053 case CHAN_SOCKDATA:
\r
5054 bufsize = pfd_send(c->u.pfd.s, p, len);
\r
5057 /* Data for an agent message. Buffer it. */
\r
5059 if (c->u.a.lensofar < 4) {
\r
5060 unsigned int l = min(4 - c->u.a.lensofar, (unsigned)len);
\r
5061 memcpy(c->u.a.msglen + c->u.a.lensofar, p,
\r
5065 c->u.a.lensofar += l;
\r
5067 if (c->u.a.lensofar == 4) {
\r
5069 4 + GET_32BIT(c->u.a.msglen);
\r
5070 c->u.a.message = snewn(c->u.a.totallen,
\r
5072 memcpy(c->u.a.message, c->u.a.msglen, 4);
\r
5074 if (c->u.a.lensofar >= 4 && len > 0) {
\r
5076 min(c->u.a.totallen - c->u.a.lensofar,
\r
5078 memcpy(c->u.a.message + c->u.a.lensofar, p,
\r
5082 c->u.a.lensofar += l;
\r
5084 if (c->u.a.lensofar == c->u.a.totallen) {
\r
5087 c->u.a.outstanding_requests++;
\r
5088 if (agent_query(c->u.a.message,
\r
5090 &reply, &replylen,
\r
5091 ssh_agentf_callback, c))
\r
5092 ssh_agentf_callback(c, reply, replylen);
\r
5093 sfree(c->u.a.message);
\r
5094 c->u.a.lensofar = 0;
\r
5097 bufsize = 0; /* agent channels never back up */
\r
5100 if (!c->throttling_conn && bufsize > SSH1_BUFFER_LIMIT) {
\r
5101 c->throttling_conn = 1;
\r
5102 ssh_throttle_conn(ssh, +1);
\r
5107 static void ssh1_smsg_exit_status(Ssh ssh, struct Packet *pktin)
\r
5109 ssh->exitcode = ssh_pkt_getuint32(pktin);
\r
5110 logeventf(ssh, "Server sent command exit status %d", ssh->exitcode);
\r
5111 send_packet(ssh, SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
\r
5113 * In case `helpful' firewalls or proxies tack
\r
5114 * extra human-readable text on the end of the
\r
5115 * session which we might mistake for another
\r
5116 * encrypted packet, we close the session once
\r
5117 * we've sent EXIT_CONFIRMATION.
\r
5119 ssh_disconnect(ssh, NULL, NULL, 0, TRUE);
\r
5122 /* Helper function to deal with sending tty modes for REQUEST_PTY */
\r
5123 static void ssh1_send_ttymode(void *data, char *mode, char *val)
\r
5125 struct Packet *pktout = (struct Packet *)data;
\r
5127 unsigned int arg = 0;
\r
5128 while (strcmp(mode, ssh_ttymodes[i].mode) != 0) i++;
\r
5129 if (i == lenof(ssh_ttymodes)) return;
\r
5130 switch (ssh_ttymodes[i].type) {
\r
5132 arg = ssh_tty_parse_specchar(val);
\r
5135 arg = ssh_tty_parse_boolean(val);
\r
5138 ssh2_pkt_addbyte(pktout, ssh_ttymodes[i].opcode);
\r
5139 ssh2_pkt_addbyte(pktout, arg);
\r
5143 static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
\r
5144 struct Packet *pktin)
\r
5146 crBegin(ssh->do_ssh1_connection_crstate);
\r
5148 ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] =
\r
5149 ssh->packet_dispatch[SSH1_SMSG_STDERR_DATA] =
\r
5150 ssh1_smsg_stdout_stderr_data;
\r
5152 ssh->packet_dispatch[SSH1_MSG_CHANNEL_OPEN_CONFIRMATION] =
\r
5153 ssh1_msg_channel_open_confirmation;
\r
5154 ssh->packet_dispatch[SSH1_MSG_CHANNEL_OPEN_FAILURE] =
\r
5155 ssh1_msg_channel_open_failure;
\r
5156 ssh->packet_dispatch[SSH1_MSG_CHANNEL_CLOSE] =
\r
5157 ssh->packet_dispatch[SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION] =
\r
5158 ssh1_msg_channel_close;
\r
5159 ssh->packet_dispatch[SSH1_MSG_CHANNEL_DATA] = ssh1_msg_channel_data;
\r
5160 ssh->packet_dispatch[SSH1_SMSG_EXIT_STATUS] = ssh1_smsg_exit_status;
\r
5162 if (conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists()) {
\r
5163 logevent("Requesting agent forwarding");
\r
5164 send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
\r
5168 if (pktin->type != SSH1_SMSG_SUCCESS
\r
5169 && pktin->type != SSH1_SMSG_FAILURE) {
\r
5170 bombout(("Protocol confusion"));
\r
5172 } else if (pktin->type == SSH1_SMSG_FAILURE) {
\r
5173 logevent("Agent forwarding refused");
\r
5175 logevent("Agent forwarding enabled");
\r
5176 ssh->agentfwd_enabled = TRUE;
\r
5177 ssh->packet_dispatch[SSH1_SMSG_AGENT_OPEN] = ssh1_smsg_agent_open;
\r
5181 if (conf_get_int(ssh->conf, CONF_x11_forward) &&
\r
5182 (ssh->x11disp = x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
\r
5183 conf_get_int(ssh->conf, CONF_x11_auth), ssh->conf))) {
\r
5184 logevent("Requesting X11 forwarding");
\r
5186 * Note that while we blank the X authentication data here, we don't
\r
5187 * take any special action to blank the start of an X11 channel,
\r
5188 * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection
\r
5189 * without having session blanking enabled is likely to leak your
\r
5190 * cookie into the log.
\r
5192 if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
\r
5193 send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
\r
5194 PKT_STR, ssh->x11disp->remoteauthprotoname,
\r
5196 PKT_STR, ssh->x11disp->remoteauthdatastring,
\r
5198 PKT_INT, ssh->x11disp->screennum,
\r
5201 send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
\r
5202 PKT_STR, ssh->x11disp->remoteauthprotoname,
\r
5204 PKT_STR, ssh->x11disp->remoteauthdatastring,
\r
5211 if (pktin->type != SSH1_SMSG_SUCCESS
\r
5212 && pktin->type != SSH1_SMSG_FAILURE) {
\r
5213 bombout(("Protocol confusion"));
\r
5215 } else if (pktin->type == SSH1_SMSG_FAILURE) {
\r
5216 logevent("X11 forwarding refused");
\r
5218 logevent("X11 forwarding enabled");
\r
5219 ssh->X11_fwd_enabled = TRUE;
\r
5220 ssh->packet_dispatch[SSH1_SMSG_X11_OPEN] = ssh1_smsg_x11_open;
\r
5224 ssh_setup_portfwd(ssh, ssh->conf);
\r
5225 ssh->packet_dispatch[SSH1_MSG_PORT_OPEN] = ssh1_msg_port_open;
\r
5227 if (!conf_get_int(ssh->conf, CONF_nopty)) {
\r
5228 struct Packet *pkt;
\r
5229 /* Unpick the terminal-speed string. */
\r
5230 /* XXX perhaps we should allow no speeds to be sent. */
\r
5231 ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
\r
5232 sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed);
\r
5233 /* Send the pty request. */
\r
5234 pkt = ssh1_pkt_init(SSH1_CMSG_REQUEST_PTY);
\r
5235 ssh_pkt_addstring(pkt, conf_get_str(ssh->conf, CONF_termtype));
\r
5236 ssh_pkt_adduint32(pkt, ssh->term_height);
\r
5237 ssh_pkt_adduint32(pkt, ssh->term_width);
\r
5238 ssh_pkt_adduint32(pkt, 0); /* width in pixels */
\r
5239 ssh_pkt_adduint32(pkt, 0); /* height in pixels */
\r
5240 parse_ttymodes(ssh, ssh1_send_ttymode, (void *)pkt);
\r
5241 ssh_pkt_addbyte(pkt, SSH1_TTY_OP_ISPEED);
\r
5242 ssh_pkt_adduint32(pkt, ssh->ispeed);
\r
5243 ssh_pkt_addbyte(pkt, SSH1_TTY_OP_OSPEED);
\r
5244 ssh_pkt_adduint32(pkt, ssh->ospeed);
\r
5245 ssh_pkt_addbyte(pkt, SSH_TTY_OP_END);
\r
5246 s_wrpkt(ssh, pkt);
\r
5247 ssh->state = SSH_STATE_INTERMED;
\r
5251 if (pktin->type != SSH1_SMSG_SUCCESS
\r
5252 && pktin->type != SSH1_SMSG_FAILURE) {
\r
5253 bombout(("Protocol confusion"));
\r
5255 } else if (pktin->type == SSH1_SMSG_FAILURE) {
\r
5256 c_write_str(ssh, "Server refused to allocate pty\r\n");
\r
5257 ssh->editing = ssh->echoing = 1;
\r
5259 logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
\r
5260 ssh->ospeed, ssh->ispeed);
\r
5261 ssh->got_pty = TRUE;
\r
5264 ssh->editing = ssh->echoing = 1;
\r
5267 if (conf_get_int(ssh->conf, CONF_compression)) {
\r
5268 send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
\r
5272 if (pktin->type != SSH1_SMSG_SUCCESS
\r
5273 && pktin->type != SSH1_SMSG_FAILURE) {
\r
5274 bombout(("Protocol confusion"));
\r
5276 } else if (pktin->type == SSH1_SMSG_FAILURE) {
\r
5277 c_write_str(ssh, "Server refused to compress\r\n");
\r
5279 logevent("Started compression");
\r
5280 ssh->v1_compressing = TRUE;
\r
5281 ssh->cs_comp_ctx = zlib_compress_init();
\r
5282 logevent("Initialised zlib (RFC1950) compression");
\r
5283 ssh->sc_comp_ctx = zlib_decompress_init();
\r
5284 logevent("Initialised zlib (RFC1950) decompression");
\r
5288 * Start the shell or command.
\r
5290 * Special case: if the first-choice command is an SSH-2
\r
5291 * subsystem (hence not usable here) and the second choice
\r
5292 * exists, we fall straight back to that.
\r
5295 char *cmd = conf_get_str(ssh->conf, CONF_remote_cmd);
\r
5297 if (conf_get_int(ssh->conf, CONF_ssh_subsys) &&
\r
5298 conf_get_str(ssh->conf, CONF_remote_cmd2)) {
\r
5299 cmd = conf_get_str(ssh->conf, CONF_remote_cmd2);
\r
5300 ssh->fallback_cmd = TRUE;
\r
5303 send_packet(ssh, SSH1_CMSG_EXEC_CMD, PKT_STR, cmd, PKT_END);
\r
5305 send_packet(ssh, SSH1_CMSG_EXEC_SHELL, PKT_END);
\r
5306 logevent("Started session");
\r
5309 ssh->state = SSH_STATE_SESSION;
\r
5310 if (ssh->size_needed)
\r
5311 ssh_size(ssh, ssh->term_width, ssh->term_height);
\r
5312 if (ssh->eof_needed)
\r
5313 ssh_special(ssh, TS_EOF);
\r
5316 ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
\r
5318 ssh->channels = newtree234(ssh_channelcmp);
\r
5322 * By this point, most incoming packets are already being
\r
5323 * handled by the dispatch table, and we need only pay
\r
5324 * attention to the unusual ones.
\r
5329 if (pktin->type == SSH1_SMSG_SUCCESS) {
\r
5330 /* may be from EXEC_SHELL on some servers */
\r
5331 } else if (pktin->type == SSH1_SMSG_FAILURE) {
\r
5332 /* may be from EXEC_SHELL on some servers
\r
5333 * if no pty is available or in other odd cases. Ignore */
\r
5335 bombout(("Strange packet received: type %d", pktin->type));
\r
5339 while (inlen > 0) {
\r
5340 int len = min(inlen, 512);
\r
5341 send_packet(ssh, SSH1_CMSG_STDIN_DATA,
\r
5342 PKT_INT, len, PKTT_DATA, PKT_DATA, in, len,
\r
5343 PKTT_OTHER, PKT_END);
\r
5354 * Handle the top-level SSH-2 protocol.
\r
5356 static void ssh1_msg_debug(Ssh ssh, struct Packet *pktin)
\r
5361 ssh_pkt_getstring(pktin, &msg, &msglen);
\r
5362 logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
\r
5365 static void ssh1_msg_disconnect(Ssh ssh, struct Packet *pktin)
\r
5367 /* log reason code in disconnect message */
\r
5371 ssh_pkt_getstring(pktin, &msg, &msglen);
\r
5372 bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));
\r
5375 static void ssh_msg_ignore(Ssh ssh, struct Packet *pktin)
\r
5377 /* Do nothing, because we're ignoring it! Duhh. */
\r
5380 static void ssh1_protocol_setup(Ssh ssh)
\r
5385 * Most messages are handled by the coroutines.
\r
5387 for (i = 0; i < 256; i++)
\r
5388 ssh->packet_dispatch[i] = NULL;
\r
5391 * These special message types we install handlers for.
\r
5393 ssh->packet_dispatch[SSH1_MSG_DISCONNECT] = ssh1_msg_disconnect;
\r
5394 ssh->packet_dispatch[SSH1_MSG_IGNORE] = ssh_msg_ignore;
\r
5395 ssh->packet_dispatch[SSH1_MSG_DEBUG] = ssh1_msg_debug;
\r
5398 static void ssh1_protocol(Ssh ssh, void *vin, int inlen,
\r
5399 struct Packet *pktin)
\r
5401 unsigned char *in=(unsigned char*)vin;
\r
5402 if (ssh->state == SSH_STATE_CLOSED)
\r
5405 if (pktin && ssh->packet_dispatch[pktin->type]) {
\r
5406 ssh->packet_dispatch[pktin->type](ssh, pktin);
\r
5410 if (!ssh->protocol_initial_phase_done) {
\r
5411 if (do_ssh1_login(ssh, in, inlen, pktin))
\r
5412 ssh->protocol_initial_phase_done = TRUE;
\r
5417 do_ssh1_connection(ssh, in, inlen, pktin);
\r
5421 * Utility routine for decoding comma-separated strings in KEXINIT.
\r
5423 static int in_commasep_string(char *needle, char *haystack, int haylen)
\r
5426 if (!needle || !haystack) /* protect against null pointers */
\r
5428 needlen = strlen(needle);
\r
5431 * Is it at the start of the string?
\r
5433 if (haylen >= needlen && /* haystack is long enough */
\r
5434 !memcmp(needle, haystack, needlen) && /* initial match */
\r
5435 (haylen == needlen || haystack[needlen] == ',')
\r
5436 /* either , or EOS follows */
\r
5440 * If not, search for the next comma and resume after that.
\r
5441 * If no comma found, terminate.
\r
5443 while (haylen > 0 && *haystack != ',')
\r
5444 haylen--, haystack++;
\r
5447 haylen--, haystack++; /* skip over comma itself */
\r
5452 * Similar routine for checking whether we have the first string in a list.
\r
5454 static int first_in_commasep_string(char *needle, char *haystack, int haylen)
\r
5457 if (!needle || !haystack) /* protect against null pointers */
\r
5459 needlen = strlen(needle);
\r
5461 * Is it at the start of the string?
\r
5463 if (haylen >= needlen && /* haystack is long enough */
\r
5464 !memcmp(needle, haystack, needlen) && /* initial match */
\r
5465 (haylen == needlen || haystack[needlen] == ',')
\r
5466 /* either , or EOS follows */
\r
5474 * SSH-2 key creation method.
\r
5475 * (Currently assumes 2 lots of any hash are sufficient to generate
\r
5476 * keys/IVs for any cipher/MAC. SSH2_MKKEY_ITERS documents this assumption.)
\r
5478 #define SSH2_MKKEY_ITERS (2)
\r
5479 static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H, char chr,
\r
5480 unsigned char *keyspace)
\r
5482 const struct ssh_hash *h = ssh->kex->hash;
\r
5484 /* First hlen bytes. */
\r
5486 if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
\r
5487 hash_mpint(h, s, K);
\r
5488 h->bytes(s, H, h->hlen);
\r
5489 h->bytes(s, &chr, 1);
\r
5490 h->bytes(s, ssh->v2_session_id, ssh->v2_session_id_len);
\r
5491 h->final(s, keyspace);
\r
5492 /* Next hlen bytes. */
\r
5494 if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
\r
5495 hash_mpint(h, s, K);
\r
5496 h->bytes(s, H, h->hlen);
\r
5497 h->bytes(s, keyspace, h->hlen);
\r
5498 h->final(s, keyspace + h->hlen);
\r
5502 * Handle the SSH-2 transport layer.
\r
5504 static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
\r
5505 struct Packet *pktin)
\r
5507 unsigned char *in = (unsigned char *)vin;
\r
5508 struct do_ssh2_transport_state {
\r
5510 int nbits, pbits, warn_kex, warn_cscipher, warn_sccipher;
\r
5511 Bignum p, g, e, f, K;
\r
5512 void *our_kexinit;
\r
5513 int our_kexinitlen;
\r
5514 int kex_init_value, kex_reply_value;
\r
5515 const struct ssh_mac **maclist;
\r
5517 const struct ssh2_cipher *cscipher_tobe;
\r
5518 const struct ssh2_cipher *sccipher_tobe;
\r
5519 const struct ssh_mac *csmac_tobe;
\r
5520 const struct ssh_mac *scmac_tobe;
\r
5521 const struct ssh_compress *cscomp_tobe;
\r
5522 const struct ssh_compress *sccomp_tobe;
\r
5523 char *hostkeydata, *sigdata, *rsakeydata, *keystr, *fingerprint;
\r
5524 int hostkeylen, siglen, rsakeylen;
\r
5525 void *hkey; /* actual host key */
\r
5526 void *rsakey; /* for RSA kex */
\r
5527 unsigned char exchange_hash[SSH2_KEX_MAX_HASH_LEN];
\r
5528 int n_preferred_kex;
\r
5529 const struct ssh_kexes *preferred_kex[KEX_MAX];
\r
5530 int n_preferred_ciphers;
\r
5531 const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
\r
5532 const struct ssh_compress *preferred_comp;
\r
5533 int userauth_succeeded; /* for delayed compression */
\r
5534 int pending_compression;
\r
5535 int got_session_id, activated_authconn;
\r
5536 struct Packet *pktout;
\r
5541 crState(do_ssh2_transport_state);
\r
5545 s->cscipher_tobe = s->sccipher_tobe = NULL;
\r
5546 s->csmac_tobe = s->scmac_tobe = NULL;
\r
5547 s->cscomp_tobe = s->sccomp_tobe = NULL;
\r
5549 s->got_session_id = s->activated_authconn = FALSE;
\r
5550 s->userauth_succeeded = FALSE;
\r
5551 s->pending_compression = FALSE;
\r
5554 * Be prepared to work around the buggy MAC problem.
\r
5556 if (ssh->remote_bugs & BUG_SSH2_HMAC)
\r
5557 s->maclist = buggymacs, s->nmacs = lenof(buggymacs);
\r
5559 s->maclist = macs, s->nmacs = lenof(macs);
\r
5561 begin_key_exchange:
\r
5562 ssh->pkt_kctx = SSH2_PKTCTX_NOKEX;
\r
5564 int i, j, k, commalist_started;
\r
5567 * Set up the preferred key exchange. (NULL => warn below here)
\r
5569 s->n_preferred_kex = 0;
\r
5570 for (i = 0; i < KEX_MAX; i++) {
\r
5571 switch (conf_get_int_int(ssh->conf, CONF_ssh_kexlist, i)) {
\r
5573 s->preferred_kex[s->n_preferred_kex++] =
\r
5574 &ssh_diffiehellman_gex;
\r
5576 case KEX_DHGROUP14:
\r
5577 s->preferred_kex[s->n_preferred_kex++] =
\r
5578 &ssh_diffiehellman_group14;
\r
5580 case KEX_DHGROUP1:
\r
5581 s->preferred_kex[s->n_preferred_kex++] =
\r
5582 &ssh_diffiehellman_group1;
\r
5585 s->preferred_kex[s->n_preferred_kex++] =
\r
5589 /* Flag for later. Don't bother if it's the last in
\r
5591 if (i < KEX_MAX - 1) {
\r
5592 s->preferred_kex[s->n_preferred_kex++] = NULL;
\r
5599 * Set up the preferred ciphers. (NULL => warn below here)
\r
5601 s->n_preferred_ciphers = 0;
\r
5602 for (i = 0; i < CIPHER_MAX; i++) {
\r
5603 switch (conf_get_int_int(ssh->conf, CONF_ssh_cipherlist, i)) {
\r
5604 case CIPHER_BLOWFISH:
\r
5605 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;
\r
5608 if (conf_get_int(ssh->conf, CONF_ssh2_des_cbc)) {
\r
5609 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;
\r
5613 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_3des;
\r
5616 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_aes;
\r
5618 case CIPHER_ARCFOUR:
\r
5619 s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_arcfour;
\r
5622 /* Flag for later. Don't bother if it's the last in
\r
5624 if (i < CIPHER_MAX - 1) {
\r
5625 s->preferred_ciphers[s->n_preferred_ciphers++] = NULL;
\r
5632 * Set up preferred compression.
\r
5634 if (conf_get_int(ssh->conf, CONF_compression))
\r
5635 s->preferred_comp = &ssh_zlib;
\r
5637 s->preferred_comp = &ssh_comp_none;
\r
5640 * Enable queueing of outgoing auth- or connection-layer
\r
5641 * packets while we are in the middle of a key exchange.
\r
5643 ssh->queueing = TRUE;
\r
5646 * Flag that KEX is in progress.
\r
5648 ssh->kex_in_progress = TRUE;
\r
5651 * Construct and send our key exchange packet.
\r
5653 s->pktout = ssh2_pkt_init(SSH2_MSG_KEXINIT);
\r
5654 for (i = 0; i < 16; i++)
\r
5655 ssh2_pkt_addbyte(s->pktout, (unsigned char) random_byte());
\r
5656 /* List key exchange algorithms. */
\r
5657 ssh2_pkt_addstring_start(s->pktout);
\r
5658 commalist_started = 0;
\r
5659 for (i = 0; i < s->n_preferred_kex; i++) {
\r
5660 const struct ssh_kexes *k = s->preferred_kex[i];
\r
5661 if (!k) continue; /* warning flag */
\r
5662 for (j = 0; j < k->nkexes; j++) {
\r
5663 if (commalist_started)
\r
5664 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5665 ssh2_pkt_addstring_str(s->pktout, k->list[j]->name);
\r
5666 commalist_started = 1;
\r
5669 /* List server host key algorithms. */
\r
5670 ssh2_pkt_addstring_start(s->pktout);
\r
5671 for (i = 0; i < lenof(hostkey_algs); i++) {
\r
5672 ssh2_pkt_addstring_str(s->pktout, hostkey_algs[i]->name);
\r
5673 if (i < lenof(hostkey_algs) - 1)
\r
5674 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5676 /* List encryption algorithms (client->server then server->client). */
\r
5677 for (k = 0; k < 2; k++) {
\r
5678 ssh2_pkt_addstring_start(s->pktout);
\r
5679 commalist_started = 0;
\r
5680 for (i = 0; i < s->n_preferred_ciphers; i++) {
\r
5681 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
\r
5682 if (!c) continue; /* warning flag */
\r
5683 for (j = 0; j < c->nciphers; j++) {
\r
5684 if (commalist_started)
\r
5685 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5686 ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);
\r
5687 commalist_started = 1;
\r
5691 /* List MAC algorithms (client->server then server->client). */
\r
5692 for (j = 0; j < 2; j++) {
\r
5693 ssh2_pkt_addstring_start(s->pktout);
\r
5694 for (i = 0; i < s->nmacs; i++) {
\r
5695 ssh2_pkt_addstring_str(s->pktout, s->maclist[i]->name);
\r
5696 if (i < s->nmacs - 1)
\r
5697 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5700 /* List client->server compression algorithms,
\r
5701 * then server->client compression algorithms. (We use the
\r
5702 * same set twice.) */
\r
5703 for (j = 0; j < 2; j++) {
\r
5704 ssh2_pkt_addstring_start(s->pktout);
\r
5705 assert(lenof(compressions) > 1);
\r
5706 /* Prefer non-delayed versions */
\r
5707 ssh2_pkt_addstring_str(s->pktout, s->preferred_comp->name);
\r
5708 /* We don't even list delayed versions of algorithms until
\r
5709 * they're allowed to be used, to avoid a race. See the end of
\r
5710 * this function. */
\r
5711 if (s->userauth_succeeded && s->preferred_comp->delayed_name) {
\r
5712 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5713 ssh2_pkt_addstring_str(s->pktout,
\r
5714 s->preferred_comp->delayed_name);
\r
5716 for (i = 0; i < lenof(compressions); i++) {
\r
5717 const struct ssh_compress *c = compressions[i];
\r
5718 if (c != s->preferred_comp) {
\r
5719 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5720 ssh2_pkt_addstring_str(s->pktout, c->name);
\r
5721 if (s->userauth_succeeded && c->delayed_name) {
\r
5722 ssh2_pkt_addstring_str(s->pktout, ",");
\r
5723 ssh2_pkt_addstring_str(s->pktout, c->delayed_name);
\r
5728 /* List client->server languages. Empty list. */
\r
5729 ssh2_pkt_addstring_start(s->pktout);
\r
5730 /* List server->client languages. Empty list. */
\r
5731 ssh2_pkt_addstring_start(s->pktout);
\r
5732 /* First KEX packet does _not_ follow, because we're not that brave. */
\r
5733 ssh2_pkt_addbool(s->pktout, FALSE);
\r
5735 ssh2_pkt_adduint32(s->pktout, 0);
\r
5738 s->our_kexinitlen = s->pktout->length - 5;
\r
5739 s->our_kexinit = snewn(s->our_kexinitlen, unsigned char);
\r
5740 memcpy(s->our_kexinit, s->pktout->data + 5, s->our_kexinitlen);
\r
5742 ssh2_pkt_send_noqueue(ssh, s->pktout);
\r
5745 crWaitUntilV(pktin);
\r
5748 * Now examine the other side's KEXINIT to see what we're up
\r
5752 char *str, *preferred;
\r
5755 if (pktin->type != SSH2_MSG_KEXINIT) {
\r
5756 bombout(("expected key exchange packet from server"));
\r
5760 ssh->hostkey = NULL;
\r
5761 s->cscipher_tobe = NULL;
\r
5762 s->sccipher_tobe = NULL;
\r
5763 s->csmac_tobe = NULL;
\r
5764 s->scmac_tobe = NULL;
\r
5765 s->cscomp_tobe = NULL;
\r
5766 s->sccomp_tobe = NULL;
\r
5767 s->warn_kex = s->warn_cscipher = s->warn_sccipher = FALSE;
\r
5769 pktin->savedpos += 16; /* skip garbage cookie */
\r
5770 ssh_pkt_getstring(pktin, &str, &len); /* key exchange algorithms */
\r
5773 for (i = 0; i < s->n_preferred_kex; i++) {
\r
5774 const struct ssh_kexes *k = s->preferred_kex[i];
\r
5776 s->warn_kex = TRUE;
\r
5778 for (j = 0; j < k->nkexes; j++) {
\r
5779 if (!preferred) preferred = k->list[j]->name;
\r
5780 if (in_commasep_string(k->list[j]->name, str, len)) {
\r
5781 ssh->kex = k->list[j];
\r
5790 bombout(("Couldn't agree a key exchange algorithm (available: %s)",
\r
5791 str ? str : "(null)"));
\r
5795 * Note that the server's guess is considered wrong if it doesn't match
\r
5796 * the first algorithm in our list, even if it's still the algorithm
\r
5797 * we end up using.
\r
5799 s->guessok = first_in_commasep_string(preferred, str, len);
\r
5800 ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */
\r
5801 for (i = 0; i < lenof(hostkey_algs); i++) {
\r
5802 if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
\r
5803 ssh->hostkey = hostkey_algs[i];
\r
5807 if (!ssh->hostkey) {
\r
5808 bombout(("Couldn't agree a host key algorithm (available: %s)",
\r
5809 str ? str : "(null)"));
\r
5813 s->guessok = s->guessok &&
\r
5814 first_in_commasep_string(hostkey_algs[0]->name, str, len);
\r
5815 ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */
\r
5816 for (i = 0; i < s->n_preferred_ciphers; i++) {
\r
5817 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
\r
5819 s->warn_cscipher = TRUE;
\r
5821 for (j = 0; j < c->nciphers; j++) {
\r
5822 if (in_commasep_string(c->list[j]->name, str, len)) {
\r
5823 s->cscipher_tobe = c->list[j];
\r
5828 if (s->cscipher_tobe)
\r
5831 if (!s->cscipher_tobe) {
\r
5832 bombout(("Couldn't agree a client-to-server cipher (available: %s)",
\r
5833 str ? str : "(null)"));
\r
5837 ssh_pkt_getstring(pktin, &str, &len); /* server->client cipher */
\r
5838 for (i = 0; i < s->n_preferred_ciphers; i++) {
\r
5839 const struct ssh2_ciphers *c = s->preferred_ciphers[i];
\r
5841 s->warn_sccipher = TRUE;
\r
5843 for (j = 0; j < c->nciphers; j++) {
\r
5844 if (in_commasep_string(c->list[j]->name, str, len)) {
\r
5845 s->sccipher_tobe = c->list[j];
\r
5850 if (s->sccipher_tobe)
\r
5853 if (!s->sccipher_tobe) {
\r
5854 bombout(("Couldn't agree a server-to-client cipher (available: %s)",
\r
5855 str ? str : "(null)"));
\r
5859 ssh_pkt_getstring(pktin, &str, &len); /* client->server mac */
\r
5860 for (i = 0; i < s->nmacs; i++) {
\r
5861 if (in_commasep_string(s->maclist[i]->name, str, len)) {
\r
5862 s->csmac_tobe = s->maclist[i];
\r
5866 ssh_pkt_getstring(pktin, &str, &len); /* server->client mac */
\r
5867 for (i = 0; i < s->nmacs; i++) {
\r
5868 if (in_commasep_string(s->maclist[i]->name, str, len)) {
\r
5869 s->scmac_tobe = s->maclist[i];
\r
5873 ssh_pkt_getstring(pktin, &str, &len); /* client->server compression */
\r
5874 for (i = 0; i < lenof(compressions) + 1; i++) {
\r
5875 const struct ssh_compress *c =
\r
5876 i == 0 ? s->preferred_comp : compressions[i - 1];
\r
5877 if (in_commasep_string(c->name, str, len)) {
\r
5878 s->cscomp_tobe = c;
\r
5880 } else if (in_commasep_string(c->delayed_name, str, len)) {
\r
5881 if (s->userauth_succeeded) {
\r
5882 s->cscomp_tobe = c;
\r
5885 s->pending_compression = TRUE; /* try this later */
\r
5889 ssh_pkt_getstring(pktin, &str, &len); /* server->client compression */
\r
5890 for (i = 0; i < lenof(compressions) + 1; i++) {
\r
5891 const struct ssh_compress *c =
\r
5892 i == 0 ? s->preferred_comp : compressions[i - 1];
\r
5893 if (in_commasep_string(c->name, str, len)) {
\r
5894 s->sccomp_tobe = c;
\r
5896 } else if (in_commasep_string(c->delayed_name, str, len)) {
\r
5897 if (s->userauth_succeeded) {
\r
5898 s->sccomp_tobe = c;
\r
5901 s->pending_compression = TRUE; /* try this later */
\r
5905 if (s->pending_compression) {
\r
5906 logevent("Server supports delayed compression; "
\r
5907 "will try this later");
\r
5909 ssh_pkt_getstring(pktin, &str, &len); /* client->server language */
\r
5910 ssh_pkt_getstring(pktin, &str, &len); /* server->client language */
\r
5911 s->ignorepkt = ssh2_pkt_getbool(pktin) && !s->guessok;
\r
5913 ssh->exhash = ssh->kex->hash->init();
\r
5914 hash_string(ssh->kex->hash, ssh->exhash, ssh->v_c, strlen(ssh->v_c));
\r
5915 hash_string(ssh->kex->hash, ssh->exhash, ssh->v_s, strlen(ssh->v_s));
\r
5916 hash_string(ssh->kex->hash, ssh->exhash,
\r
5917 s->our_kexinit, s->our_kexinitlen);
\r
5918 sfree(s->our_kexinit);
\r
5919 if (pktin->length > 5)
\r
5920 hash_string(ssh->kex->hash, ssh->exhash,
\r
5921 pktin->data + 5, pktin->length - 5);
\r
5923 if (s->warn_kex) {
\r
5924 ssh_set_frozen(ssh, 1);
\r
5925 s->dlgret = askalg(ssh->frontend, "key-exchange algorithm",
\r
5927 ssh_dialog_callback, ssh);
\r
5928 if (s->dlgret < 0) {
\r
5932 bombout(("Unexpected data from server while"
\r
5933 " waiting for user response"));
\r
5936 } while (pktin || inlen > 0);
\r
5937 s->dlgret = ssh->user_response;
\r
5939 ssh_set_frozen(ssh, 0);
\r
5940 if (s->dlgret == 0) {
\r
5941 ssh_disconnect(ssh, "User aborted at kex warning", NULL,
\r
5947 if (s->warn_cscipher) {
\r
5948 ssh_set_frozen(ssh, 1);
\r
5949 s->dlgret = askalg(ssh->frontend,
\r
5950 "client-to-server cipher",
\r
5951 s->cscipher_tobe->name,
\r
5952 ssh_dialog_callback, ssh);
\r
5953 if (s->dlgret < 0) {
\r
5957 bombout(("Unexpected data from server while"
\r
5958 " waiting for user response"));
\r
5961 } while (pktin || inlen > 0);
\r
5962 s->dlgret = ssh->user_response;
\r
5964 ssh_set_frozen(ssh, 0);
\r
5965 if (s->dlgret == 0) {
\r
5966 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
\r
5972 if (s->warn_sccipher) {
\r
5973 ssh_set_frozen(ssh, 1);
\r
5974 s->dlgret = askalg(ssh->frontend,
\r
5975 "server-to-client cipher",
\r
5976 s->sccipher_tobe->name,
\r
5977 ssh_dialog_callback, ssh);
\r
5978 if (s->dlgret < 0) {
\r
5982 bombout(("Unexpected data from server while"
\r
5983 " waiting for user response"));
\r
5986 } while (pktin || inlen > 0);
\r
5987 s->dlgret = ssh->user_response;
\r
5989 ssh_set_frozen(ssh, 0);
\r
5990 if (s->dlgret == 0) {
\r
5991 ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
\r
5997 if (s->ignorepkt) /* first_kex_packet_follows */
\r
5998 crWaitUntilV(pktin); /* Ignore packet */
\r
6001 if (ssh->kex->main_type == KEXTYPE_DH) {
\r
6003 * Work out the number of bits of key we will need from the
\r
6004 * key exchange. We start with the maximum key length of
\r
6005 * either cipher...
\r
6008 int csbits, scbits;
\r
6010 csbits = s->cscipher_tobe->keylen;
\r
6011 scbits = s->sccipher_tobe->keylen;
\r
6012 s->nbits = (csbits > scbits ? csbits : scbits);
\r
6014 /* The keys only have hlen-bit entropy, since they're based on
\r
6015 * a hash. So cap the key size at hlen bits. */
\r
6016 if (s->nbits > ssh->kex->hash->hlen * 8)
\r
6017 s->nbits = ssh->kex->hash->hlen * 8;
\r
6020 * If we're doing Diffie-Hellman group exchange, start by
\r
6021 * requesting a group.
\r
6023 if (!ssh->kex->pdata) {
\r
6024 logevent("Doing Diffie-Hellman group exchange");
\r
6025 ssh->pkt_kctx = SSH2_PKTCTX_DHGEX;
\r
6027 * Work out how big a DH group we will need to allow that
\r
6030 s->pbits = 512 << ((s->nbits - 1) / 64);
\r
6031 s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
\r
6032 ssh2_pkt_adduint32(s->pktout, s->pbits);
\r
6033 ssh2_pkt_send_noqueue(ssh, s->pktout);
\r
6035 crWaitUntilV(pktin);
\r
6036 if (pktin->type != SSH2_MSG_KEX_DH_GEX_GROUP) {
\r
6037 bombout(("expected key exchange group packet from server"));
\r
6040 s->p = ssh2_pkt_getmp(pktin);
\r
6041 s->g = ssh2_pkt_getmp(pktin);
\r
6042 if (!s->p || !s->g) {
\r
6043 bombout(("unable to read mp-ints from incoming group packet"));
\r
6046 ssh->kex_ctx = dh_setup_gex(s->p, s->g);
\r
6047 s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
\r
6048 s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
\r
6050 ssh->pkt_kctx = SSH2_PKTCTX_DHGROUP;
\r
6051 ssh->kex_ctx = dh_setup_group(ssh->kex);
\r
6052 s->kex_init_value = SSH2_MSG_KEXDH_INIT;
\r
6053 s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;
\r
6054 logeventf(ssh, "Using Diffie-Hellman with standard group \"%s\"",
\r
6055 ssh->kex->groupname);
\r
6058 logeventf(ssh, "Doing Diffie-Hellman key exchange with hash %s",
\r
6059 ssh->kex->hash->text_name);
\r
6061 * Now generate and send e for Diffie-Hellman.
\r
6063 set_busy_status(ssh->frontend, BUSY_CPU); /* this can take a while */
\r
6064 s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);
\r
6065 s->pktout = ssh2_pkt_init(s->kex_init_value);
\r
6066 ssh2_pkt_addmp(s->pktout, s->e);
\r
6067 ssh2_pkt_send_noqueue(ssh, s->pktout);
\r
6069 set_busy_status(ssh->frontend, BUSY_WAITING); /* wait for server */
\r
6070 crWaitUntilV(pktin);
\r
6071 if (pktin->type != s->kex_reply_value) {
\r
6072 bombout(("expected key exchange reply packet from server"));
\r
6075 set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */
\r
6076 ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
\r
6077 s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen);
\r
6078 s->f = ssh2_pkt_getmp(pktin);
\r
6080 bombout(("unable to parse key exchange reply packet"));
\r
6083 ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
\r
6085 s->K = dh_find_K(ssh->kex_ctx, s->f);
\r
6087 /* We assume everything from now on will be quick, and it might
\r
6088 * involve user interaction. */
\r
6089 set_busy_status(ssh->frontend, BUSY_NOT);
\r
6091 hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen);
\r
6092 if (!ssh->kex->pdata) {
\r
6093 hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits);
\r
6094 hash_mpint(ssh->kex->hash, ssh->exhash, s->p);
\r
6095 hash_mpint(ssh->kex->hash, ssh->exhash, s->g);
\r
6097 hash_mpint(ssh->kex->hash, ssh->exhash, s->e);
\r
6098 hash_mpint(ssh->kex->hash, ssh->exhash, s->f);
\r
6100 dh_cleanup(ssh->kex_ctx);
\r
6102 if (!ssh->kex->pdata) {
\r
6107 logeventf(ssh, "Doing RSA key exchange with hash %s",
\r
6108 ssh->kex->hash->text_name);
\r
6109 ssh->pkt_kctx = SSH2_PKTCTX_RSAKEX;
\r
6111 * RSA key exchange. First expect a KEXRSA_PUBKEY packet
\r
6112 * from the server.
\r
6114 crWaitUntilV(pktin);
\r
6115 if (pktin->type != SSH2_MSG_KEXRSA_PUBKEY) {
\r
6116 bombout(("expected RSA public key packet from server"));
\r
6120 ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
\r
6121 hash_string(ssh->kex->hash, ssh->exhash,
\r
6122 s->hostkeydata, s->hostkeylen);
\r
6123 s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen);
\r
6127 ssh_pkt_getstring(pktin, &keydata, &s->rsakeylen);
\r
6128 s->rsakeydata = snewn(s->rsakeylen, char);
\r
6129 memcpy(s->rsakeydata, keydata, s->rsakeylen);
\r
6132 s->rsakey = ssh_rsakex_newkey(s->rsakeydata, s->rsakeylen);
\r
6134 sfree(s->rsakeydata);
\r
6135 bombout(("unable to parse RSA public key from server"));
\r
6139 hash_string(ssh->kex->hash, ssh->exhash, s->rsakeydata, s->rsakeylen);
\r
6142 * Next, set up a shared secret K, of precisely KLEN -
\r
6143 * 2*HLEN - 49 bits, where KLEN is the bit length of the
\r
6144 * RSA key modulus and HLEN is the bit length of the hash
\r
6148 int klen = ssh_rsakex_klen(s->rsakey);
\r
6149 int nbits = klen - (2*ssh->kex->hash->hlen*8 + 49);
\r
6151 unsigned char *kstr1, *kstr2, *outstr;
\r
6152 int kstr1len, kstr2len, outstrlen;
\r
6154 s->K = bn_power_2(nbits - 1);
\r
6156 for (i = 0; i < nbits; i++) {
\r
6157 if ((i & 7) == 0) {
\r
6158 byte = random_byte();
\r
6160 bignum_set_bit(s->K, i, (byte >> (i & 7)) & 1);
\r
6164 * Encode this as an mpint.
\r
6166 kstr1 = ssh2_mpint_fmt(s->K, &kstr1len);
\r
6167 kstr2 = snewn(kstr2len = 4 + kstr1len, unsigned char);
\r
6168 PUT_32BIT(kstr2, kstr1len);
\r
6169 memcpy(kstr2 + 4, kstr1, kstr1len);
\r
6172 * Encrypt it with the given RSA key.
\r
6174 outstrlen = (klen + 7) / 8;
\r
6175 outstr = snewn(outstrlen, unsigned char);
\r
6176 ssh_rsakex_encrypt(ssh->kex->hash, kstr2, kstr2len,
\r
6177 outstr, outstrlen, s->rsakey);
\r
6180 * And send it off in a return packet.
\r
6182 s->pktout = ssh2_pkt_init(SSH2_MSG_KEXRSA_SECRET);
\r
6183 ssh2_pkt_addstring_start(s->pktout);
\r
6184 ssh2_pkt_addstring_data(s->pktout, (char *)outstr, outstrlen);
\r
6185 ssh2_pkt_send_noqueue(ssh, s->pktout);
\r
6187 hash_string(ssh->kex->hash, ssh->exhash, outstr, outstrlen);
\r
6194 ssh_rsakex_freekey(s->rsakey);
\r
6196 crWaitUntilV(pktin);
\r
6197 if (pktin->type != SSH2_MSG_KEXRSA_DONE) {
\r
6198 sfree(s->rsakeydata);
\r
6199 bombout(("expected signature packet from server"));
\r
6203 ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
\r
6205 sfree(s->rsakeydata);
\r
6208 hash_mpint(ssh->kex->hash, ssh->exhash, s->K);
\r
6209 assert(ssh->kex->hash->hlen <= sizeof(s->exchange_hash));
\r
6210 ssh->kex->hash->final(ssh->exhash, s->exchange_hash);
\r
6212 ssh->kex_ctx = NULL;
\r
6215 debug(("Exchange hash is:\n"));
\r
6216 dmemdump(s->exchange_hash, ssh->kex->hash->hlen);
\r
6220 !ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,
\r
6221 (char *)s->exchange_hash,
\r
6222 ssh->kex->hash->hlen)) {
\r
6223 bombout(("Server's host key did not match the signature supplied"));
\r
6228 * Authenticate remote host: verify host key. (We've already
\r
6229 * checked the signature of the exchange hash.)
\r
6231 s->keystr = ssh->hostkey->fmtkey(s->hkey);
\r
6232 s->fingerprint = ssh->hostkey->fingerprint(s->hkey);
\r
6233 ssh_set_frozen(ssh, 1);
\r
6234 s->dlgret = verify_ssh_host_key(ssh->frontend,
\r
6235 ssh->savedhost, ssh->savedport,
\r
6236 ssh->hostkey->keytype, s->keystr,
\r
6238 ssh_dialog_callback, ssh);
\r
6239 if (s->dlgret < 0) {
\r
6243 bombout(("Unexpected data from server while waiting"
\r
6244 " for user host key response"));
\r
6247 } while (pktin || inlen > 0);
\r
6248 s->dlgret = ssh->user_response;
\r
6250 ssh_set_frozen(ssh, 0);
\r
6251 if (s->dlgret == 0) {
\r
6252 ssh_disconnect(ssh, "User aborted at host key verification", NULL,
\r
6256 if (!s->got_session_id) { /* don't bother logging this in rekeys */
\r
6257 logevent("Host key fingerprint is:");
\r
6258 logevent(s->fingerprint);
\r
6260 sfree(s->fingerprint);
\r
6262 ssh->hostkey->freekey(s->hkey);
\r
6265 * The exchange hash from the very first key exchange is also
\r
6266 * the session id, used in session key construction and
\r
6269 if (!s->got_session_id) {
\r
6270 assert(sizeof(s->exchange_hash) <= sizeof(ssh->v2_session_id));
\r
6271 memcpy(ssh->v2_session_id, s->exchange_hash,
\r
6272 sizeof(s->exchange_hash));
\r
6273 ssh->v2_session_id_len = ssh->kex->hash->hlen;
\r
6274 assert(ssh->v2_session_id_len <= sizeof(ssh->v2_session_id));
\r
6275 s->got_session_id = TRUE;
\r
6279 * Send SSH2_MSG_NEWKEYS.
\r
6281 s->pktout = ssh2_pkt_init(SSH2_MSG_NEWKEYS);
\r
6282 ssh2_pkt_send_noqueue(ssh, s->pktout);
\r
6283 ssh->outgoing_data_size = 0; /* start counting from here */
\r
6286 * We've sent client NEWKEYS, so create and initialise
\r
6287 * client-to-server session keys.
\r
6289 if (ssh->cs_cipher_ctx)
\r
6290 ssh->cscipher->free_context(ssh->cs_cipher_ctx);
\r
6291 ssh->cscipher = s->cscipher_tobe;
\r
6292 ssh->cs_cipher_ctx = ssh->cscipher->make_context();
\r
6294 if (ssh->cs_mac_ctx)
\r
6295 ssh->csmac->free_context(ssh->cs_mac_ctx);
\r
6296 ssh->csmac = s->csmac_tobe;
\r
6297 ssh->cs_mac_ctx = ssh->csmac->make_context();
\r
6299 if (ssh->cs_comp_ctx)
\r
6300 ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
\r
6301 ssh->cscomp = s->cscomp_tobe;
\r
6302 ssh->cs_comp_ctx = ssh->cscomp->compress_init();
\r
6305 * Set IVs on client-to-server keys. Here we use the exchange
\r
6306 * hash from the _first_ key exchange.
\r
6309 unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS];
\r
6310 assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6311 ssh2_mkkey(ssh,s->K,s->exchange_hash,'C',keyspace);
\r
6312 assert((ssh->cscipher->keylen+7) / 8 <=
\r
6313 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6314 ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);
\r
6315 ssh2_mkkey(ssh,s->K,s->exchange_hash,'A',keyspace);
\r
6316 assert(ssh->cscipher->blksize <=
\r
6317 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6318 ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);
\r
6319 ssh2_mkkey(ssh,s->K,s->exchange_hash,'E',keyspace);
\r
6320 assert(ssh->csmac->len <=
\r
6321 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6322 ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
\r
6323 smemclr(keyspace, sizeof(keyspace));
\r
6326 logeventf(ssh, "Initialised %.200s client->server encryption",
\r
6327 ssh->cscipher->text_name);
\r
6328 logeventf(ssh, "Initialised %.200s client->server MAC algorithm",
\r
6329 ssh->csmac->text_name);
\r
6330 if (ssh->cscomp->text_name)
\r
6331 logeventf(ssh, "Initialised %s compression",
\r
6332 ssh->cscomp->text_name);
\r
6335 * Now our end of the key exchange is complete, we can send all
\r
6336 * our queued higher-layer packets.
\r
6338 ssh->queueing = FALSE;
\r
6339 ssh2_pkt_queuesend(ssh);
\r
6342 * Expect SSH2_MSG_NEWKEYS from server.
\r
6344 crWaitUntilV(pktin);
\r
6345 if (pktin->type != SSH2_MSG_NEWKEYS) {
\r
6346 bombout(("expected new-keys packet from server"));
\r
6349 ssh->incoming_data_size = 0; /* start counting from here */
\r
6352 * We've seen server NEWKEYS, so create and initialise
\r
6353 * server-to-client session keys.
\r
6355 if (ssh->sc_cipher_ctx)
\r
6356 ssh->sccipher->free_context(ssh->sc_cipher_ctx);
\r
6357 ssh->sccipher = s->sccipher_tobe;
\r
6358 ssh->sc_cipher_ctx = ssh->sccipher->make_context();
\r
6360 if (ssh->sc_mac_ctx)
\r
6361 ssh->scmac->free_context(ssh->sc_mac_ctx);
\r
6362 ssh->scmac = s->scmac_tobe;
\r
6363 ssh->sc_mac_ctx = ssh->scmac->make_context();
\r
6365 if (ssh->sc_comp_ctx)
\r
6366 ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);
\r
6367 ssh->sccomp = s->sccomp_tobe;
\r
6368 ssh->sc_comp_ctx = ssh->sccomp->decompress_init();
\r
6371 * Set IVs on server-to-client keys. Here we use the exchange
\r
6372 * hash from the _first_ key exchange.
\r
6375 unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS];
\r
6376 assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6377 ssh2_mkkey(ssh,s->K,s->exchange_hash,'D',keyspace);
\r
6378 assert((ssh->sccipher->keylen+7) / 8 <=
\r
6379 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6380 ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);
\r
6381 ssh2_mkkey(ssh,s->K,s->exchange_hash,'B',keyspace);
\r
6382 assert(ssh->sccipher->blksize <=
\r
6383 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6384 ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
\r
6385 ssh2_mkkey(ssh,s->K,s->exchange_hash,'F',keyspace);
\r
6386 assert(ssh->scmac->len <=
\r
6387 ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
\r
6388 ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
\r
6389 smemclr(keyspace, sizeof(keyspace));
\r
6391 logeventf(ssh, "Initialised %.200s server->client encryption",
\r
6392 ssh->sccipher->text_name);
\r
6393 logeventf(ssh, "Initialised %.200s server->client MAC algorithm",
\r
6394 ssh->scmac->text_name);
\r
6395 if (ssh->sccomp->text_name)
\r
6396 logeventf(ssh, "Initialised %s decompression",
\r
6397 ssh->sccomp->text_name);
\r
6400 * Free shared secret.
\r
6405 * Key exchange is over. Loop straight back round if we have a
\r
6406 * deferred rekey reason.
\r
6408 if (ssh->deferred_rekey_reason) {
\r
6409 logevent(ssh->deferred_rekey_reason);
\r
6411 ssh->deferred_rekey_reason = NULL;
\r
6412 goto begin_key_exchange;
\r
6416 * Otherwise, schedule a timer for our next rekey.
\r
6418 ssh->kex_in_progress = FALSE;
\r
6419 ssh->last_rekey = GETTICKCOUNT();
\r
6420 if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0)
\r
6421 ssh->next_rekey = schedule_timer(conf_get_int(ssh->conf, CONF_ssh_rekey_time)*60*TICKSPERSEC,
\r
6425 * Now we're encrypting. Begin returning 1 to the protocol main
\r
6426 * function so that other things can run on top of the
\r
6427 * transport. If we ever see a KEXINIT, we must go back to the
\r
6430 * We _also_ go back to the start if we see pktin==NULL and
\r
6431 * inlen negative, because this is a special signal meaning
\r
6432 * `initiate client-driven rekey', and `in' contains a message
\r
6433 * giving the reason for the rekey.
\r
6435 * inlen==-1 means always initiate a rekey;
\r
6436 * inlen==-2 means that userauth has completed successfully and
\r
6437 * we should consider rekeying (for delayed compression).
\r
6439 while (!((pktin && pktin->type == SSH2_MSG_KEXINIT) ||
\r
6440 (!pktin && inlen < 0))) {
\r
6442 if (!ssh->protocol_initial_phase_done) {
\r
6443 ssh->protocol_initial_phase_done = TRUE;
\r
6445 * Allow authconn to initialise itself.
\r
6447 do_ssh2_authconn(ssh, NULL, 0, NULL);
\r
6452 logevent("Server initiated key re-exchange");
\r
6454 if (inlen == -2) {
\r
6456 * authconn has seen a USERAUTH_SUCCEEDED. Time to enable
\r
6457 * delayed compression, if it's available.
\r
6459 * draft-miller-secsh-compression-delayed-00 says that you
\r
6460 * negotiate delayed compression in the first key exchange, and
\r
6461 * both sides start compressing when the server has sent
\r
6462 * USERAUTH_SUCCESS. This has a race condition -- the server
\r
6463 * can't know when the client has seen it, and thus which incoming
\r
6464 * packets it should treat as compressed.
\r
6466 * Instead, we do the initial key exchange without offering the
\r
6467 * delayed methods, but note if the server offers them; when we
\r
6468 * get here, if a delayed method was available that was higher
\r
6469 * on our list than what we got, we initiate a rekey in which we
\r
6470 * _do_ list the delayed methods (and hopefully get it as a
\r
6471 * result). Subsequent rekeys will do the same.
\r
6473 assert(!s->userauth_succeeded); /* should only happen once */
\r
6474 s->userauth_succeeded = TRUE;
\r
6475 if (!s->pending_compression)
\r
6476 /* Can't see any point rekeying. */
\r
6477 goto wait_for_rekey; /* this is utterly horrid */
\r
6478 /* else fall through to rekey... */
\r
6479 s->pending_compression = FALSE;
\r
6482 * Now we've decided to rekey.
\r
6484 * Special case: if the server bug is set that doesn't
\r
6485 * allow rekeying, we give a different log message and
\r
6486 * continue waiting. (If such a server _initiates_ a rekey,
\r
6487 * we process it anyway!)
\r
6489 if ((ssh->remote_bugs & BUG_SSH2_REKEY)) {
\r
6490 logeventf(ssh, "Server bug prevents key re-exchange (%s)",
\r
6492 /* Reset the counters, so that at least this message doesn't
\r
6493 * hit the event log _too_ often. */
\r
6494 ssh->outgoing_data_size = 0;
\r
6495 ssh->incoming_data_size = 0;
\r
6496 if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0) {
\r
6498 schedule_timer(conf_get_int(ssh->conf, CONF_ssh_rekey_time)*60*TICKSPERSEC,
\r
6501 goto wait_for_rekey; /* this is still utterly horrid */
\r
6503 logeventf(ssh, "Initiating key re-exchange (%s)", (char *)in);
\r
6506 goto begin_key_exchange;
\r
6512 * Add data to an SSH-2 channel output buffer.
\r
6514 static void ssh2_add_channel_data(struct ssh_channel *c, char *buf,
\r
6517 bufchain_add(&c->v.v2.outbuffer, buf, len);
\r
6521 * Attempt to send data on an SSH-2 channel.
\r
6523 static int ssh2_try_send(struct ssh_channel *c)
\r
6526 struct Packet *pktout;
\r
6529 while (c->v.v2.remwindow > 0 && bufchain_size(&c->v.v2.outbuffer) > 0) {
\r
6532 bufchain_prefix(&c->v.v2.outbuffer, &data, &len);
\r
6533 if ((unsigned)len > c->v.v2.remwindow)
\r
6534 len = c->v.v2.remwindow;
\r
6535 if ((unsigned)len > c->v.v2.remmaxpkt)
\r
6536 len = c->v.v2.remmaxpkt;
\r
6537 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
\r
6538 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
6539 ssh2_pkt_addstring_start(pktout);
\r
6540 dont_log_data(ssh, pktout, PKTLOG_OMIT);
\r
6541 ssh2_pkt_addstring_data(pktout, data, len);
\r
6542 end_log_omission(ssh, pktout);
\r
6543 ssh2_pkt_send(ssh, pktout);
\r
6544 bufchain_consume(&c->v.v2.outbuffer, len);
\r
6545 c->v.v2.remwindow -= len;
\r
6549 * After having sent as much data as we can, return the amount
\r
6552 ret = bufchain_size(&c->v.v2.outbuffer);
\r
6555 * And if there's no data pending but we need to send an EOF, send
\r
6558 if (!ret && c->pending_eof)
\r
6559 ssh_channel_try_eof(c);
\r
6564 static void ssh2_try_send_and_unthrottle(Ssh ssh, struct ssh_channel *c)
\r
6567 if (c->closes & CLOSES_SENT_EOF)
\r
6568 return; /* don't send on channels we've EOFed */
\r
6569 bufsize = ssh2_try_send(c);
\r
6570 if (bufsize == 0) {
\r
6571 switch (c->type) {
\r
6572 case CHAN_MAINSESSION:
\r
6573 /* stdin need not receive an unthrottle
\r
6574 * notification since it will be polled */
\r
6577 x11_unthrottle(c->u.x11.s);
\r
6580 /* agent sockets are request/response and need no
\r
6581 * buffer management */
\r
6583 case CHAN_SOCKDATA:
\r
6584 pfd_unthrottle(c->u.pfd.s);
\r
6591 * Set up most of a new ssh_channel for SSH-2.
\r
6593 static void ssh2_channel_init(struct ssh_channel *c)
\r
6596 c->localid = alloc_channel_id(ssh);
\r
6598 c->pending_eof = FALSE;
\r
6599 c->throttling_conn = FALSE;
\r
6600 c->v.v2.locwindow = c->v.v2.locmaxwin = c->v.v2.remlocwin =
\r
6601 conf_get_int(ssh->conf, CONF_ssh_simple) ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
\r
6602 c->v.v2.chanreq_head = NULL;
\r
6603 c->v.v2.throttle_state = UNTHROTTLED;
\r
6604 bufchain_init(&c->v.v2.outbuffer);
\r
6608 * Construct the common parts of a CHANNEL_OPEN.
\r
6610 static struct Packet *ssh2_chanopen_init(struct ssh_channel *c, char *type)
\r
6612 struct Packet *pktout;
\r
6614 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
\r
6615 ssh2_pkt_addstring(pktout, type);
\r
6616 ssh2_pkt_adduint32(pktout, c->localid);
\r
6617 ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
\r
6618 ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
\r
6623 * CHANNEL_FAILURE doesn't come with any indication of what message
\r
6624 * caused it, so we have to keep track of the outstanding
\r
6625 * CHANNEL_REQUESTs ourselves.
\r
6627 static void ssh2_queue_chanreq_handler(struct ssh_channel *c,
\r
6628 cchandler_fn_t handler, void *ctx)
\r
6630 struct outstanding_channel_request *ocr =
\r
6631 snew(struct outstanding_channel_request);
\r
6633 assert(!(c->closes & (CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE)));
\r
6634 ocr->handler = handler;
\r
6637 if (!c->v.v2.chanreq_head)
\r
6638 c->v.v2.chanreq_head = ocr;
\r
6640 c->v.v2.chanreq_tail->next = ocr;
\r
6641 c->v.v2.chanreq_tail = ocr;
\r
6645 * Construct the common parts of a CHANNEL_REQUEST. If handler is not
\r
6646 * NULL then a reply will be requested and the handler will be called
\r
6647 * when it arrives. The returned packet is ready to have any
\r
6648 * request-specific data added and be sent. Note that if a handler is
\r
6649 * provided, it's essential that the request actually be sent.
\r
6651 * The handler will usually be passed the response packet in pktin.
\r
6652 * If pktin is NULL, this means that no reply will ever be forthcoming
\r
6653 * (e.g. because the entire connection is being destroyed) and the
\r
6654 * handler should free any storage it's holding.
\r
6656 static struct Packet *ssh2_chanreq_init(struct ssh_channel *c, char *type,
\r
6657 cchandler_fn_t handler, void *ctx)
\r
6659 struct Packet *pktout;
\r
6661 assert(!(c->closes & (CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE)));
\r
6662 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
\r
6663 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
6664 ssh2_pkt_addstring(pktout, type);
\r
6665 ssh2_pkt_addbool(pktout, handler != NULL);
\r
6666 if (handler != NULL)
\r
6667 ssh2_queue_chanreq_handler(c, handler, ctx);
\r
6672 * Potentially enlarge the window on an SSH-2 channel.
\r
6674 static void ssh2_handle_winadj_response(struct ssh_channel *, struct Packet *,
\r
6676 static void ssh2_set_window(struct ssh_channel *c, int newwin)
\r
6681 * Never send WINDOW_ADJUST for a channel that the remote side has
\r
6682 * already sent EOF on; there's no point, since it won't be
\r
6683 * sending any more data anyway. Ditto if _we've_ already sent
\r
6686 if (c->closes & (CLOSES_RCVD_EOF | CLOSES_SENT_CLOSE))
\r
6690 * If the remote end has a habit of ignoring maxpkt, limit the
\r
6691 * window so that it has no choice (assuming it doesn't ignore the
\r
6692 * window as well).
\r
6694 if ((ssh->remote_bugs & BUG_SSH2_MAXPKT) && newwin > OUR_V2_MAXPKT)
\r
6695 newwin = OUR_V2_MAXPKT;
\r
6698 * Only send a WINDOW_ADJUST if there's significantly more window
\r
6699 * available than the other end thinks there is. This saves us
\r
6700 * sending a WINDOW_ADJUST for every character in a shell session.
\r
6702 * "Significant" is arbitrarily defined as half the window size.
\r
6704 if (newwin / 2 >= c->v.v2.locwindow) {
\r
6705 struct Packet *pktout;
\r
6709 * In order to keep track of how much window the client
\r
6710 * actually has available, we'd like it to acknowledge each
\r
6711 * WINDOW_ADJUST. We can't do that directly, so we accompany
\r
6712 * it with a CHANNEL_REQUEST that has to be acknowledged.
\r
6714 * This is only necessary if we're opening the window wide.
\r
6715 * If we're not, then throughput is being constrained by
\r
6716 * something other than the maximum window size anyway.
\r
6718 if (newwin == c->v.v2.locmaxwin &&
\r
6719 !(ssh->remote_bugs & BUG_CHOKES_ON_WINADJ)) {
\r
6720 up = snew(unsigned);
\r
6721 *up = newwin - c->v.v2.locwindow;
\r
6722 pktout = ssh2_chanreq_init(c, "winadj@putty.projects.tartarus.org",
\r
6723 ssh2_handle_winadj_response, up);
\r
6724 ssh2_pkt_send(ssh, pktout);
\r
6726 if (c->v.v2.throttle_state != UNTHROTTLED)
\r
6727 c->v.v2.throttle_state = UNTHROTTLING;
\r
6729 /* Pretend the WINDOW_ADJUST was acked immediately. */
\r
6730 c->v.v2.remlocwin = newwin;
\r
6731 c->v.v2.throttle_state = THROTTLED;
\r
6733 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
\r
6734 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
6735 ssh2_pkt_adduint32(pktout, newwin - c->v.v2.locwindow);
\r
6736 ssh2_pkt_send(ssh, pktout);
\r
6737 c->v.v2.locwindow = newwin;
\r
6742 * Find the channel associated with a message. If there's no channel,
\r
6743 * or it's not properly open, make a noise about it and return NULL.
\r
6745 static struct ssh_channel *ssh2_channel_msg(Ssh ssh, struct Packet *pktin)
\r
6747 unsigned localid = ssh_pkt_getuint32(pktin);
\r
6748 struct ssh_channel *c;
\r
6750 c = find234(ssh->channels, &localid, ssh_channelfind);
\r
6752 (c->halfopen && pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
\r
6753 pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE)) {
\r
6754 char *buf = dupprintf("Received %s for %s channel %u",
\r
6755 ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
\r
6757 c ? "half-open" : "nonexistent", localid);
\r
6758 ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
\r
6765 static void ssh2_handle_winadj_response(struct ssh_channel *c,
\r
6766 struct Packet *pktin, void *ctx)
\r
6768 unsigned *sizep = ctx;
\r
6771 * Winadj responses should always be failures. However, at least
\r
6772 * one server ("boks_sshd") is known to return SUCCESS for channel
\r
6773 * requests it's never heard of, such as "winadj@putty". Raised
\r
6774 * with foxt.com as bug 090916-090424, but for the sake of a quiet
\r
6775 * life, we don't worry about what kind of response we got.
\r
6778 c->v.v2.remlocwin += *sizep;
\r
6781 * winadj messages are only sent when the window is fully open, so
\r
6782 * if we get an ack of one, we know any pending unthrottle is
\r
6785 if (c->v.v2.throttle_state == UNTHROTTLING)
\r
6786 c->v.v2.throttle_state = UNTHROTTLED;
\r
6789 static void ssh2_msg_channel_response(Ssh ssh, struct Packet *pktin)
\r
6791 struct ssh_channel *c = ssh2_channel_msg(ssh, pktin);
\r
6792 struct outstanding_channel_request *ocr;
\r
6795 ocr = c->v.v2.chanreq_head;
\r
6797 ssh2_msg_unexpected(ssh, pktin);
\r
6800 ocr->handler(c, pktin, ocr->ctx);
\r
6801 c->v.v2.chanreq_head = ocr->next;
\r
6804 * We may now initiate channel-closing procedures, if that
\r
6805 * CHANNEL_REQUEST was the last thing outstanding before we send
\r
6808 ssh2_channel_check_close(c);
\r
6811 static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
\r
6813 struct ssh_channel *c;
\r
6814 c = ssh2_channel_msg(ssh, pktin);
\r
6817 if (!(c->closes & CLOSES_SENT_EOF)) {
\r
6818 c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
\r
6819 ssh2_try_send_and_unthrottle(ssh, c);
\r
6823 static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
\r
6827 struct ssh_channel *c;
\r
6828 c = ssh2_channel_msg(ssh, pktin);
\r
6831 if (pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA &&
\r
6832 ssh_pkt_getuint32(pktin) != SSH2_EXTENDED_DATA_STDERR)
\r
6833 return; /* extended but not stderr */
\r
6834 ssh_pkt_getstring(pktin, &data, &length);
\r
6837 c->v.v2.locwindow -= length;
\r
6838 c->v.v2.remlocwin -= length;
\r
6839 switch (c->type) {
\r
6840 case CHAN_MAINSESSION:
\r
6842 from_backend(ssh->frontend, pktin->type ==
\r
6843 SSH2_MSG_CHANNEL_EXTENDED_DATA,
\r
6847 bufsize = x11_send(c->u.x11.s, data, length);
\r
6849 case CHAN_SOCKDATA:
\r
6850 bufsize = pfd_send(c->u.pfd.s, data, length);
\r
6853 while (length > 0) {
\r
6854 if (c->u.a.lensofar < 4) {
\r
6855 unsigned int l = min(4 - c->u.a.lensofar,
\r
6856 (unsigned)length);
\r
6857 memcpy(c->u.a.msglen + c->u.a.lensofar,
\r
6861 c->u.a.lensofar += l;
\r
6863 if (c->u.a.lensofar == 4) {
\r
6865 4 + GET_32BIT(c->u.a.msglen);
\r
6866 c->u.a.message = snewn(c->u.a.totallen,
\r
6868 memcpy(c->u.a.message, c->u.a.msglen, 4);
\r
6870 if (c->u.a.lensofar >= 4 && length > 0) {
\r
6872 min(c->u.a.totallen - c->u.a.lensofar,
\r
6873 (unsigned)length);
\r
6874 memcpy(c->u.a.message + c->u.a.lensofar,
\r
6878 c->u.a.lensofar += l;
\r
6880 if (c->u.a.lensofar == c->u.a.totallen) {
\r
6883 c->u.a.outstanding_requests++;
\r
6884 if (agent_query(c->u.a.message,
\r
6886 &reply, &replylen,
\r
6887 ssh_agentf_callback, c))
\r
6888 ssh_agentf_callback(c, reply, replylen);
\r
6889 sfree(c->u.a.message);
\r
6890 c->u.a.message = NULL;
\r
6891 c->u.a.lensofar = 0;
\r
6898 * If it looks like the remote end hit the end of its window,
\r
6899 * and we didn't want it to do that, think about using a
\r
6902 if (c->v.v2.remlocwin <= 0 && c->v.v2.throttle_state == UNTHROTTLED &&
\r
6903 c->v.v2.locmaxwin < 0x40000000)
\r
6904 c->v.v2.locmaxwin += OUR_V2_WINSIZE;
\r
6906 * If we are not buffering too much data,
\r
6907 * enlarge the window again at the remote side.
\r
6908 * If we are buffering too much, we may still
\r
6909 * need to adjust the window if the server's
\r
6910 * sent excess data.
\r
6912 ssh2_set_window(c, bufsize < c->v.v2.locmaxwin ?
\r
6913 c->v.v2.locmaxwin - bufsize : 0);
\r
6915 * If we're either buffering way too much data, or if we're
\r
6916 * buffering anything at all and we're in "simple" mode,
\r
6917 * throttle the whole channel.
\r
6919 if ((bufsize > c->v.v2.locmaxwin ||
\r
6920 (conf_get_int(ssh->conf, CONF_ssh_simple) && bufsize > 0)) &&
\r
6921 !c->throttling_conn) {
\r
6922 c->throttling_conn = 1;
\r
6923 ssh_throttle_conn(ssh, +1);
\r
6928 static void ssh_channel_destroy(struct ssh_channel *c)
\r
6932 switch (c->type) {
\r
6933 case CHAN_MAINSESSION:
\r
6934 ssh->mainchan = NULL;
\r
6935 update_specials_menu(ssh->frontend);
\r
6938 if (c->u.x11.s != NULL)
\r
6939 x11_close(c->u.x11.s);
\r
6940 logevent("Forwarded X11 connection terminated");
\r
6943 sfree(c->u.a.message);
\r
6945 case CHAN_SOCKDATA:
\r
6946 if (c->u.pfd.s != NULL)
\r
6947 pfd_close(c->u.pfd.s);
\r
6948 logevent("Forwarded port closed");
\r
6952 del234(ssh->channels, c);
\r
6953 if (ssh->version == 2) {
\r
6954 bufchain_clear(&c->v.v2.outbuffer);
\r
6955 assert(c->v.v2.chanreq_head == NULL);
\r
6960 * See if that was the last channel left open.
\r
6961 * (This is only our termination condition if we're
\r
6962 * not running in -N mode.)
\r
6964 if (ssh->version == 2 &&
\r
6965 !conf_get_int(ssh->conf, CONF_ssh_no_shell) &&
\r
6966 count234(ssh->channels) == 0) {
\r
6968 * We used to send SSH_MSG_DISCONNECT here,
\r
6969 * because I'd believed that _every_ conforming
\r
6970 * SSH-2 connection had to end with a disconnect
\r
6971 * being sent by at least one side; apparently
\r
6972 * I was wrong and it's perfectly OK to
\r
6973 * unceremoniously slam the connection shut
\r
6974 * when you're done, and indeed OpenSSH feels
\r
6975 * this is more polite than sending a
\r
6976 * DISCONNECT. So now we don't.
\r
6978 ssh_disconnect(ssh, "All channels closed", NULL, 0, TRUE);
\r
6982 static void ssh2_channel_check_close(struct ssh_channel *c)
\r
6985 struct Packet *pktout;
\r
6987 if ((!((CLOSES_SENT_EOF | CLOSES_RCVD_EOF) & ~c->closes) ||
\r
6988 c->type == CHAN_ZOMBIE) &&
\r
6989 !c->v.v2.chanreq_head &&
\r
6990 !(c->closes & CLOSES_SENT_CLOSE)) {
\r
6992 * We have both sent and received EOF (or the channel is a
\r
6993 * zombie), and we have no outstanding channel requests, which
\r
6994 * means the channel is in final wind-up. But we haven't sent
\r
6995 * CLOSE, so let's do so now.
\r
6997 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
\r
6998 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
6999 ssh2_pkt_send(ssh, pktout);
\r
7000 c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE;
\r
7003 if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes)) {
\r
7004 assert(c->v.v2.chanreq_head == NULL);
\r
7006 * We have both sent and received CLOSE, which means we're
\r
7007 * completely done with the channel.
\r
7009 ssh_channel_destroy(c);
\r
7013 static void ssh2_channel_got_eof(struct ssh_channel *c)
\r
7015 if (c->closes & CLOSES_RCVD_EOF)
\r
7016 return; /* already seen EOF */
\r
7017 c->closes |= CLOSES_RCVD_EOF;
\r
7019 if (c->type == CHAN_X11) {
\r
7020 x11_send_eof(c->u.x11.s);
\r
7021 } else if (c->type == CHAN_AGENT) {
\r
7022 if (c->u.a.outstanding_requests == 0) {
\r
7023 /* Manufacture an outgoing EOF in response to the incoming one. */
\r
7024 sshfwd_write_eof(c);
\r
7026 } else if (c->type == CHAN_SOCKDATA) {
\r
7027 pfd_send_eof(c->u.pfd.s);
\r
7028 } else if (c->type == CHAN_MAINSESSION) {
\r
7031 if (!ssh->sent_console_eof &&
\r
7032 (from_backend_eof(ssh->frontend) || ssh->got_pty)) {
\r
7034 * Either from_backend_eof told us that the front end
\r
7035 * wants us to close the outgoing side of the connection
\r
7036 * as soon as we see EOF from the far end, or else we've
\r
7037 * unilaterally decided to do that because we've allocated
\r
7038 * a remote pty and hence EOF isn't a particularly
\r
7039 * meaningful concept.
\r
7041 sshfwd_write_eof(c);
\r
7043 ssh->sent_console_eof = TRUE;
\r
7046 ssh2_channel_check_close(c);
\r
7049 static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
\r
7051 struct ssh_channel *c;
\r
7053 c = ssh2_channel_msg(ssh, pktin);
\r
7056 ssh2_channel_got_eof(c);
\r
7059 static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin)
\r
7061 struct ssh_channel *c;
\r
7063 c = ssh2_channel_msg(ssh, pktin);
\r
7068 * When we receive CLOSE on a channel, we assume it comes with an
\r
7069 * implied EOF if we haven't seen EOF yet.
\r
7071 ssh2_channel_got_eof(c);
\r
7074 * And we also send an outgoing EOF, if we haven't already, on the
\r
7075 * assumption that CLOSE is a pretty forceful announcement that
\r
7076 * the remote side is doing away with the entire channel. (If it
\r
7077 * had wanted to send us EOF and continue receiving data from us,
\r
7078 * it would have just sent CHANNEL_EOF.)
\r
7080 if (!(c->closes & CLOSES_SENT_EOF)) {
\r
7082 * Make sure we don't read any more from whatever our local
\r
7083 * data source is for this channel.
\r
7085 switch (c->type) {
\r
7086 case CHAN_MAINSESSION:
\r
7087 ssh->send_ok = 0; /* stop trying to read from stdin */
\r
7090 x11_override_throttle(c->u.x11.s, 1);
\r
7092 case CHAN_SOCKDATA:
\r
7093 pfd_override_throttle(c->u.pfd.s, 1);
\r
7098 * Abandon any buffered data we still wanted to send to this
\r
7099 * channel. Receiving a CHANNEL_CLOSE is an indication that
\r
7100 * the server really wants to get on and _destroy_ this
\r
7101 * channel, and it isn't going to send us any further
\r
7102 * WINDOW_ADJUSTs to permit us to send pending stuff.
\r
7104 bufchain_clear(&c->v.v2.outbuffer);
\r
7107 * Send outgoing EOF.
\r
7109 sshfwd_write_eof(c);
\r
7113 * Now process the actual close.
\r
7115 if (!(c->closes & CLOSES_RCVD_CLOSE)) {
\r
7116 c->closes |= CLOSES_RCVD_CLOSE;
\r
7117 ssh2_channel_check_close(c);
\r
7121 static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
\r
7123 struct ssh_channel *c;
\r
7125 c = ssh2_channel_msg(ssh, pktin);
\r
7128 if (c->type != CHAN_SOCKDATA_DORMANT)
\r
7129 return; /* dunno why they're confirming this */
\r
7130 c->remoteid = ssh_pkt_getuint32(pktin);
\r
7131 c->halfopen = FALSE;
\r
7132 c->type = CHAN_SOCKDATA;
\r
7133 c->v.v2.remwindow = ssh_pkt_getuint32(pktin);
\r
7134 c->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
\r
7136 pfd_confirm(c->u.pfd.s);
\r
7137 if (c->pending_eof)
\r
7138 ssh_channel_try_eof(c);
\r
7141 static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
\r
7143 static const char *const reasons[] = {
\r
7144 "<unknown reason code>",
\r
7145 "Administratively prohibited",
\r
7147 "Unknown channel type",
\r
7148 "Resource shortage",
\r
7150 unsigned reason_code;
\r
7151 char *reason_string;
\r
7152 int reason_length;
\r
7153 struct ssh_channel *c;
\r
7154 c = ssh2_channel_msg(ssh, pktin);
\r
7157 if (c->type != CHAN_SOCKDATA_DORMANT)
\r
7158 return; /* dunno why they're failing this */
\r
7160 reason_code = ssh_pkt_getuint32(pktin);
\r
7161 if (reason_code >= lenof(reasons))
\r
7162 reason_code = 0; /* ensure reasons[reason_code] in range */
\r
7163 ssh_pkt_getstring(pktin, &reason_string, &reason_length);
\r
7164 logeventf(ssh, "Forwarded connection refused by server: %s [%.*s]",
\r
7165 reasons[reason_code], reason_length, reason_string);
\r
7167 pfd_close(c->u.pfd.s);
\r
7169 del234(ssh->channels, c);
\r
7173 static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin)
\r
7176 int typelen, want_reply;
\r
7177 int reply = SSH2_MSG_CHANNEL_FAILURE; /* default */
\r
7178 struct ssh_channel *c;
\r
7179 struct Packet *pktout;
\r
7181 c = ssh2_channel_msg(ssh, pktin);
\r
7184 ssh_pkt_getstring(pktin, &type, &typelen);
\r
7185 want_reply = ssh2_pkt_getbool(pktin);
\r
7188 * Having got the channel number, we now look at
\r
7189 * the request type string to see if it's something
\r
7192 if (c == ssh->mainchan) {
\r
7194 * We recognise "exit-status" and "exit-signal" on
\r
7195 * the primary channel.
\r
7197 if (typelen == 11 &&
\r
7198 !memcmp(type, "exit-status", 11)) {
\r
7200 ssh->exitcode = ssh_pkt_getuint32(pktin);
\r
7201 logeventf(ssh, "Server sent command exit status %d",
\r
7203 reply = SSH2_MSG_CHANNEL_SUCCESS;
\r
7205 } else if (typelen == 11 &&
\r
7206 !memcmp(type, "exit-signal", 11)) {
\r
7208 int is_plausible = TRUE, is_int = FALSE;
\r
7209 char *fmt_sig = "", *fmt_msg = "";
\r
7211 int msglen = 0, core = FALSE;
\r
7212 /* ICK: older versions of OpenSSH (e.g. 3.4p1)
\r
7213 * provide an `int' for the signal, despite its
\r
7214 * having been a `string' in the drafts of RFC 4254 since at
\r
7215 * least 2001. (Fixed in session.c 1.147.) Try to
\r
7216 * infer which we can safely parse it as. */
\r
7218 unsigned char *p = pktin->body +
\r
7220 long len = pktin->length - pktin->savedpos;
\r
7221 unsigned long num = GET_32BIT(p); /* what is it? */
\r
7222 /* If it's 0, it hardly matters; assume string */
\r
7226 int maybe_int = FALSE, maybe_str = FALSE;
\r
7227 #define CHECK_HYPOTHESIS(offset, result) \
\r
7230 int q = toint(offset); \
\r
7231 if (q >= 0 && q+4 <= len) { \
\r
7232 q = toint(q + 4 + GET_32BIT(p+q)); \
\r
7233 if (q >= 0 && q+4 <= len && \
\r
7234 ((q = toint(q + 4 + GET_32BIT(p+q))) != 0) && \
\r
7239 CHECK_HYPOTHESIS(4+1, maybe_int);
\r
7240 CHECK_HYPOTHESIS(4+num+1, maybe_str);
\r
7241 #undef CHECK_HYPOTHESIS
\r
7242 if (maybe_int && !maybe_str)
\r
7244 else if (!maybe_int && maybe_str)
\r
7247 /* Crikey. Either or neither. Panic. */
\r
7248 is_plausible = FALSE;
\r
7251 ssh->exitcode = 128; /* means `unknown signal' */
\r
7252 if (is_plausible) {
\r
7254 /* Old non-standard OpenSSH. */
\r
7255 int signum = ssh_pkt_getuint32(pktin);
\r
7256 fmt_sig = dupprintf(" %d", signum);
\r
7257 ssh->exitcode = 128 + signum;
\r
7259 /* As per RFC 4254. */
\r
7262 ssh_pkt_getstring(pktin, &sig, &siglen);
\r
7263 /* Signal name isn't supposed to be blank, but
\r
7264 * let's cope gracefully if it is. */
\r
7266 fmt_sig = dupprintf(" \"%.*s\"",
\r
7271 * Really hideous method of translating the
\r
7272 * signal description back into a locally
\r
7273 * meaningful number.
\r
7278 #define TRANSLATE_SIGNAL(s) \
\r
7279 else if (siglen == lenof(#s)-1 && !memcmp(sig, #s, siglen)) \
\r
7280 ssh->exitcode = 128 + SIG ## s
\r
7282 TRANSLATE_SIGNAL(ABRT);
\r
7285 TRANSLATE_SIGNAL(ALRM);
\r
7288 TRANSLATE_SIGNAL(FPE);
\r
7291 TRANSLATE_SIGNAL(HUP);
\r
7294 TRANSLATE_SIGNAL(ILL);
\r
7297 TRANSLATE_SIGNAL(INT);
\r
7300 TRANSLATE_SIGNAL(KILL);
\r
7303 TRANSLATE_SIGNAL(PIPE);
\r
7306 TRANSLATE_SIGNAL(QUIT);
\r
7309 TRANSLATE_SIGNAL(SEGV);
\r
7312 TRANSLATE_SIGNAL(TERM);
\r
7315 TRANSLATE_SIGNAL(USR1);
\r
7318 TRANSLATE_SIGNAL(USR2);
\r
7320 #undef TRANSLATE_SIGNAL
\r
7322 ssh->exitcode = 128;
\r
7324 core = ssh2_pkt_getbool(pktin);
\r
7325 ssh_pkt_getstring(pktin, &msg, &msglen);
\r
7327 fmt_msg = dupprintf(" (\"%.*s\")", msglen, msg);
\r
7329 /* ignore lang tag */
\r
7330 } /* else don't attempt to parse */
\r
7331 logeventf(ssh, "Server exited on signal%s%s%s",
\r
7332 fmt_sig, core ? " (core dumped)" : "",
\r
7334 if (*fmt_sig) sfree(fmt_sig);
\r
7335 if (*fmt_msg) sfree(fmt_msg);
\r
7336 reply = SSH2_MSG_CHANNEL_SUCCESS;
\r
7341 * This is a channel request we don't know
\r
7342 * about, so we now either ignore the request
\r
7343 * or respond with CHANNEL_FAILURE, depending
\r
7346 reply = SSH2_MSG_CHANNEL_FAILURE;
\r
7349 pktout = ssh2_pkt_init(reply);
\r
7350 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
7351 ssh2_pkt_send(ssh, pktout);
\r
7355 static void ssh2_msg_global_request(Ssh ssh, struct Packet *pktin)
\r
7358 int typelen, want_reply;
\r
7359 struct Packet *pktout;
\r
7361 ssh_pkt_getstring(pktin, &type, &typelen);
\r
7362 want_reply = ssh2_pkt_getbool(pktin);
\r
7365 * We currently don't support any global requests
\r
7366 * at all, so we either ignore the request or
\r
7367 * respond with REQUEST_FAILURE, depending on
\r
7371 pktout = ssh2_pkt_init(SSH2_MSG_REQUEST_FAILURE);
\r
7372 ssh2_pkt_send(ssh, pktout);
\r
7376 static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
\r
7383 char *error = NULL;
\r
7384 struct ssh_channel *c;
\r
7385 unsigned remid, winsize, pktsize;
\r
7386 struct Packet *pktout;
\r
7388 ssh_pkt_getstring(pktin, &type, &typelen);
\r
7389 c = snew(struct ssh_channel);
\r
7392 remid = ssh_pkt_getuint32(pktin);
\r
7393 winsize = ssh_pkt_getuint32(pktin);
\r
7394 pktsize = ssh_pkt_getuint32(pktin);
\r
7396 if (typelen == 3 && !memcmp(type, "x11", 3)) {
\r
7398 const char *x11err;
\r
7400 ssh_pkt_getstring(pktin, &peeraddr, &peeraddrlen);
\r
7401 addrstr = snewn(peeraddrlen+1, char);
\r
7402 memcpy(addrstr, peeraddr, peeraddrlen);
\r
7403 addrstr[peeraddrlen] = '\0';
\r
7404 peerport = ssh_pkt_getuint32(pktin);
\r
7406 logeventf(ssh, "Received X11 connect request from %s:%d",
\r
7407 addrstr, peerport);
\r
7409 if (!ssh->X11_fwd_enabled)
\r
7410 error = "X11 forwarding is not enabled";
\r
7411 else if ((x11err = x11_init(&c->u.x11.s, ssh->x11disp, c,
\r
7412 addrstr, peerport, ssh->conf)) != NULL) {
\r
7413 logeventf(ssh, "Local X11 connection failed: %s", x11err);
\r
7414 error = "Unable to open an X11 connection";
\r
7416 logevent("Opening X11 forward connection succeeded");
\r
7417 c->type = CHAN_X11;
\r
7421 } else if (typelen == 15 &&
\r
7422 !memcmp(type, "forwarded-tcpip", 15)) {
\r
7423 struct ssh_rportfwd pf, *realpf;
\r
7426 ssh_pkt_getstring(pktin, &dummy, &dummylen);/* skip address */
\r
7427 pf.sport = ssh_pkt_getuint32(pktin);
\r
7428 ssh_pkt_getstring(pktin, &peeraddr, &peeraddrlen);
\r
7429 peerport = ssh_pkt_getuint32(pktin);
\r
7430 realpf = find234(ssh->rportfwds, &pf, NULL);
\r
7431 logeventf(ssh, "Received remote port %d open request "
\r
7432 "from %s:%d", pf.sport, peeraddr, peerport);
\r
7433 if (realpf == NULL) {
\r
7434 error = "Remote port is not recognised";
\r
7436 const char *e = pfd_newconnect(&c->u.pfd.s,
\r
7440 realpf->pfrec->addressfamily);
\r
7441 logeventf(ssh, "Attempting to forward remote port to "
\r
7442 "%s:%d", realpf->dhost, realpf->dport);
\r
7444 logeventf(ssh, "Port open failed: %s", e);
\r
7445 error = "Port open failed";
\r
7447 logevent("Forwarded port opened successfully");
\r
7448 c->type = CHAN_SOCKDATA;
\r
7451 } else if (typelen == 22 &&
\r
7452 !memcmp(type, "auth-agent@openssh.com", 22)) {
\r
7453 if (!ssh->agentfwd_enabled)
\r
7454 error = "Agent forwarding is not enabled";
\r
7456 c->type = CHAN_AGENT; /* identify channel type */
\r
7457 c->u.a.lensofar = 0;
\r
7458 c->u.a.outstanding_requests = 0;
\r
7461 error = "Unsupported channel type requested";
\r
7464 c->remoteid = remid;
\r
7465 c->halfopen = FALSE;
\r
7467 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_FAILURE);
\r
7468 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
7469 ssh2_pkt_adduint32(pktout, SSH2_OPEN_CONNECT_FAILED);
\r
7470 ssh2_pkt_addstring(pktout, error);
\r
7471 ssh2_pkt_addstring(pktout, "en"); /* language tag */
\r
7472 ssh2_pkt_send(ssh, pktout);
\r
7473 logeventf(ssh, "Rejected channel open: %s", error);
\r
7476 ssh2_channel_init(c);
\r
7477 c->v.v2.remwindow = winsize;
\r
7478 c->v.v2.remmaxpkt = pktsize;
\r
7479 add234(ssh->channels, c);
\r
7480 pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
\r
7481 ssh2_pkt_adduint32(pktout, c->remoteid);
\r
7482 ssh2_pkt_adduint32(pktout, c->localid);
\r
7483 ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);
\r
7484 ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
\r
7485 ssh2_pkt_send(ssh, pktout);
\r
7490 * Buffer banner messages for later display at some convenient point,
\r
7491 * if we're going to display them.
\r
7493 static void ssh2_msg_userauth_banner(Ssh ssh, struct Packet *pktin)
\r
7495 /* Arbitrary limit to prevent unbounded inflation of buffer */
\r
7496 if (conf_get_int(ssh->conf, CONF_ssh_show_banner) &&
\r
7497 bufchain_size(&ssh->banner) <= 131072) {
\r
7498 char *banner = NULL;
\r
7500 ssh_pkt_getstring(pktin, &banner, &size);
\r
7502 bufchain_add(&ssh->banner, banner, size);
\r
7506 /* Helper function to deal with sending tty modes for "pty-req" */
\r
7507 static void ssh2_send_ttymode(void *data, char *mode, char *val)
\r
7509 struct Packet *pktout = (struct Packet *)data;
\r
7511 unsigned int arg = 0;
\r
7512 while (strcmp(mode, ssh_ttymodes[i].mode) != 0) i++;
\r
7513 if (i == lenof(ssh_ttymodes)) return;
\r
7514 switch (ssh_ttymodes[i].type) {
\r
7516 arg = ssh_tty_parse_specchar(val);
\r
7519 arg = ssh_tty_parse_boolean(val);
\r
7522 ssh2_pkt_addbyte(pktout, ssh_ttymodes[i].opcode);
\r
7523 ssh2_pkt_adduint32(pktout, arg);
\r
7526 static void ssh2_setup_x11(struct ssh_channel *c, struct Packet *pktin,
\r
7529 struct ssh2_setup_x11_state {
\r
7533 struct Packet *pktout;
\r
7534 crStateP(ssh2_setup_x11_state, ctx);
\r
7538 logevent("Requesting X11 forwarding");
\r
7539 pktout = ssh2_chanreq_init(ssh->mainchan, "x11-req",
\r
7540 ssh2_setup_x11, s);
\r
7541 ssh2_pkt_addbool(pktout, 0); /* many connections */
\r
7542 ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthprotoname);
\r
7544 * Note that while we blank the X authentication data here, we don't
\r
7545 * take any special action to blank the start of an X11 channel,
\r
7546 * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection
\r
7547 * without having session blanking enabled is likely to leak your
\r
7548 * cookie into the log.
\r
7550 dont_log_password(ssh, pktout, PKTLOG_BLANK);
\r
7551 ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthdatastring);
\r
7552 end_log_omission(ssh, pktout);
\r
7553 ssh2_pkt_adduint32(pktout, ssh->x11disp->screennum);
\r
7554 ssh2_pkt_send(ssh, pktout);
\r
7556 /* Wait to be called back with either a response packet, or NULL
\r
7557 * meaning clean up and free our data */
\r
7561 if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) {
\r
7562 logevent("X11 forwarding enabled");
\r
7563 ssh->X11_fwd_enabled = TRUE;
\r
7565 logevent("X11 forwarding refused");
\r
7571 static void ssh2_setup_agent(struct ssh_channel *c, struct Packet *pktin,
\r
7574 struct ssh2_setup_agent_state {
\r
7578 struct Packet *pktout;
\r
7579 crStateP(ssh2_setup_agent_state, ctx);
\r
7583 logevent("Requesting OpenSSH-style agent forwarding");
\r
7584 pktout = ssh2_chanreq_init(ssh->mainchan, "auth-agent-req@openssh.com",
\r
7585 ssh2_setup_agent, s);
\r
7586 ssh2_pkt_send(ssh, pktout);
\r
7588 /* Wait to be called back with either a response packet, or NULL
\r
7589 * meaning clean up and free our data */
\r
7593 if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) {
\r
7594 logevent("Agent forwarding enabled");
\r
7595 ssh->agentfwd_enabled = TRUE;
\r
7597 logevent("Agent forwarding refused");
\r
7603 static void ssh2_setup_pty(struct ssh_channel *c, struct Packet *pktin,
\r
7606 struct ssh2_setup_pty_state {
\r
7610 struct Packet *pktout;
\r
7611 crStateP(ssh2_setup_pty_state, ctx);
\r
7615 /* Unpick the terminal-speed string. */
\r
7616 /* XXX perhaps we should allow no speeds to be sent. */
\r
7617 ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
\r
7618 sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed);
\r
7619 /* Build the pty request. */
\r
7620 pktout = ssh2_chanreq_init(ssh->mainchan, "pty-req",
\r
7621 ssh2_setup_pty, s);
\r
7622 ssh2_pkt_addstring(pktout, conf_get_str(ssh->conf, CONF_termtype));
\r
7623 ssh2_pkt_adduint32(pktout, ssh->term_width);
\r
7624 ssh2_pkt_adduint32(pktout, ssh->term_height);
\r
7625 ssh2_pkt_adduint32(pktout, 0); /* pixel width */
\r
7626 ssh2_pkt_adduint32(pktout, 0); /* pixel height */
\r
7627 ssh2_pkt_addstring_start(pktout);
\r
7628 parse_ttymodes(ssh, ssh2_send_ttymode, (void *)pktout);
\r
7629 ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_ISPEED);
\r
7630 ssh2_pkt_adduint32(pktout, ssh->ispeed);
\r
7631 ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_OSPEED);
\r
7632 ssh2_pkt_adduint32(pktout, ssh->ospeed);
\r
7633 ssh2_pkt_addstring_data(pktout, "\0", 1); /* TTY_OP_END */
\r
7634 ssh2_pkt_send(ssh, pktout);
\r
7635 ssh->state = SSH_STATE_INTERMED;
\r
7637 /* Wait to be called back with either a response packet, or NULL
\r
7638 * meaning clean up and free our data */
\r
7642 if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) {
\r
7643 logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)",
\r
7644 ssh->ospeed, ssh->ispeed);
\r
7645 ssh->got_pty = TRUE;
\r
7647 c_write_str(ssh, "Server refused to allocate pty\r\n");
\r
7648 ssh->editing = ssh->echoing = 1;
\r
7655 static void ssh2_setup_env(struct ssh_channel *c, struct Packet *pktin,
\r
7658 struct ssh2_setup_env_state {
\r
7660 int num_env, env_left, env_ok;
\r
7663 struct Packet *pktout;
\r
7664 crStateP(ssh2_setup_env_state, ctx);
\r
7669 * Send environment variables.
\r
7671 * Simplest thing here is to send all the requests at once, and
\r
7672 * then wait for a whole bunch of successes or failures.
\r
7678 for (val = conf_get_str_strs(ssh->conf, CONF_environmt, NULL, &key);
\r
7680 val = conf_get_str_strs(ssh->conf, CONF_environmt, key, &key)) {
\r
7681 pktout = ssh2_chanreq_init(ssh->mainchan, "env", ssh2_setup_env, s);
\r
7682 ssh2_pkt_addstring(pktout, key);
\r
7683 ssh2_pkt_addstring(pktout, val);
\r
7684 ssh2_pkt_send(ssh, pktout);
\r
7689 logeventf(ssh, "Sent %d environment variables", s->num_env);
\r
7694 s->env_left = s->num_env;
\r
7696 while (s->env_left > 0) {
\r
7697 /* Wait to be called back with either a response packet,
\r
7698 * or NULL meaning clean up and free our data */
\r
7700 if (!pktin) goto out;
\r
7701 if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS)
\r
7706 if (s->env_ok == s->num_env) {
\r
7707 logevent("All environment variables successfully set");
\r
7708 } else if (s->env_ok == 0) {
\r
7709 logevent("All environment variables refused");
\r
7710 c_write_str(ssh, "Server refused to set environment variables\r\n");
\r
7712 logeventf(ssh, "%d environment variables refused",
\r
7713 s->num_env - s->env_ok);
\r
7714 c_write_str(ssh, "Server refused to set all environment variables\r\n");
\r
7722 * Handle the SSH-2 userauth and connection layers.
\r
7724 static void ssh2_msg_authconn(Ssh ssh, struct Packet *pktin)
\r
7726 do_ssh2_authconn(ssh, NULL, 0, pktin);
\r
7729 static void ssh2_response_authconn(struct ssh_channel *c, struct Packet *pktin,
\r
7732 do_ssh2_authconn(c->ssh, NULL, 0, pktin);
\r
7735 static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
\r
7736 struct Packet *pktin)
\r
7738 struct do_ssh2_authconn_state {
\r
7742 AUTH_TYPE_PUBLICKEY,
\r
7743 AUTH_TYPE_PUBLICKEY_OFFER_LOUD,
\r
7744 AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
\r
7745 AUTH_TYPE_PASSWORD,
\r
7746 AUTH_TYPE_GSSAPI, /* always QUIET */
\r
7747 AUTH_TYPE_KEYBOARD_INTERACTIVE,
\r
7748 AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET
\r
7750 int done_service_req;
\r
7751 int gotit, need_pw, can_pubkey, can_passwd, can_keyb_inter;
\r
7752 int tried_pubkey_config, done_agent;
\r
7757 int kbd_inter_refused;
\r
7758 int we_are_in, userauth_success;
\r
7759 prompts_t *cur_prompt;
\r
7764 void *publickey_blob;
\r
7765 int publickey_bloblen;
\r
7766 int publickey_encrypted;
\r
7767 char *publickey_algorithm;
\r
7768 char *publickey_comment;
\r
7769 unsigned char agent_request[5], *agent_response, *agentp;
\r
7770 int agent_responselen;
\r
7771 unsigned char *pkblob_in_agent;
\r
7773 char *pkblob, *alg, *commentp;
\r
7774 int pklen, alglen, commentlen;
\r
7775 int siglen, retlen, len;
\r
7776 char *q, *agentreq, *ret;
\r
7778 struct Packet *pktout;
\r
7779 Filename *keyfile;
\r
7781 struct ssh_gss_library *gsslib;
\r
7782 Ssh_gss_ctx gss_ctx;
\r
7783 Ssh_gss_buf gss_buf;
\r
7784 Ssh_gss_buf gss_rcvtok, gss_sndtok;
\r
7785 Ssh_gss_name gss_srv_name;
\r
7786 Ssh_gss_stat gss_stat;
\r
7789 crState(do_ssh2_authconn_state);
\r
7793 /* Register as a handler for all the messages this coroutine handles. */
\r
7794 ssh->packet_dispatch[SSH2_MSG_SERVICE_ACCEPT] = ssh2_msg_authconn;
\r
7795 ssh->packet_dispatch[SSH2_MSG_USERAUTH_REQUEST] = ssh2_msg_authconn;
\r
7796 ssh->packet_dispatch[SSH2_MSG_USERAUTH_FAILURE] = ssh2_msg_authconn;
\r
7797 ssh->packet_dispatch[SSH2_MSG_USERAUTH_SUCCESS] = ssh2_msg_authconn;
\r
7798 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = ssh2_msg_authconn;
\r
7799 ssh->packet_dispatch[SSH2_MSG_USERAUTH_PK_OK] = ssh2_msg_authconn;
\r
7800 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ] = ssh2_msg_authconn; duplicate case value */
\r
7801 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_REQUEST] = ssh2_msg_authconn; duplicate case value */
\r
7802 ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_RESPONSE] = ssh2_msg_authconn;
\r
7803 ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] = ssh2_msg_authconn;
\r
7804 ssh->packet_dispatch[SSH2_MSG_REQUEST_SUCCESS] = ssh2_msg_authconn;
\r
7805 ssh->packet_dispatch[SSH2_MSG_REQUEST_FAILURE] = ssh2_msg_authconn;
\r
7806 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] = ssh2_msg_authconn;
\r
7807 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] = ssh2_msg_authconn;
\r
7808 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] = ssh2_msg_authconn;
\r
7809 ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] = ssh2_msg_authconn;
\r
7810 ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] = ssh2_msg_authconn;
\r
7811 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] = ssh2_msg_authconn;
\r
7812 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = ssh2_msg_authconn;
\r
7813 ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = ssh2_msg_authconn;
\r
7815 s->done_service_req = FALSE;
\r
7816 s->we_are_in = s->userauth_success = FALSE;
\r
7818 s->tried_gssapi = FALSE;
\r
7821 if (!conf_get_int(ssh->conf, CONF_ssh_no_userauth)) {
\r
7823 * Request userauth protocol, and await a response to it.
\r
7825 s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
\r
7826 ssh2_pkt_addstring(s->pktout, "ssh-userauth");
\r
7827 ssh2_pkt_send(ssh, s->pktout);
\r
7828 crWaitUntilV(pktin);
\r
7829 if (pktin->type == SSH2_MSG_SERVICE_ACCEPT)
\r
7830 s->done_service_req = TRUE;
\r
7832 if (!s->done_service_req) {
\r
7834 * Request connection protocol directly, without authentication.
\r
7836 s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
\r
7837 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
7838 ssh2_pkt_send(ssh, s->pktout);
\r
7839 crWaitUntilV(pktin);
\r
7840 if (pktin->type == SSH2_MSG_SERVICE_ACCEPT) {
\r
7841 s->we_are_in = TRUE; /* no auth required */
\r
7843 bombout(("Server refused service request"));
\r
7848 /* Arrange to be able to deal with any BANNERs that come in.
\r
7849 * (We do this now as packets may come in during the next bit.) */
\r
7850 bufchain_init(&ssh->banner);
\r
7851 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] =
\r
7852 ssh2_msg_userauth_banner;
\r
7855 * Misc one-time setup for authentication.
\r
7857 s->publickey_blob = NULL;
\r
7858 if (!s->we_are_in) {
\r
7861 * Load the public half of any configured public key file
\r
7864 s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
\r
7865 if (!filename_is_null(s->keyfile)) {
\r
7867 logeventf(ssh, "Reading private key file \"%.150s\"",
\r
7868 filename_to_str(s->keyfile));
\r
7869 keytype = key_type(s->keyfile);
\r
7870 if (keytype == SSH_KEYTYPE_SSH2) {
\r
7871 const char *error;
\r
7872 s->publickey_blob =
\r
7873 ssh2_userkey_loadpub(s->keyfile,
\r
7874 &s->publickey_algorithm,
\r
7875 &s->publickey_bloblen,
\r
7876 &s->publickey_comment, &error);
\r
7877 if (s->publickey_blob) {
\r
7878 s->publickey_encrypted =
\r
7879 ssh2_userkey_encrypted(s->keyfile, NULL);
\r
7882 logeventf(ssh, "Unable to load private key (%s)",
\r
7884 msgbuf = dupprintf("Unable to load private key file "
\r
7885 "\"%.150s\" (%s)\r\n",
\r
7886 filename_to_str(s->keyfile),
\r
7888 c_write_str(ssh, msgbuf);
\r
7893 logeventf(ssh, "Unable to use this key file (%s)",
\r
7894 key_type_to_str(keytype));
\r
7895 msgbuf = dupprintf("Unable to use key file \"%.150s\""
\r
7897 filename_to_str(s->keyfile),
\r
7898 key_type_to_str(keytype));
\r
7899 c_write_str(ssh, msgbuf);
\r
7901 s->publickey_blob = NULL;
\r
7906 * Find out about any keys Pageant has (but if there's a
\r
7907 * public key configured, filter out all others).
\r
7910 s->agent_response = NULL;
\r
7911 s->pkblob_in_agent = NULL;
\r
7912 if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
\r
7916 logevent("Pageant is running. Requesting keys.");
\r
7918 /* Request the keys held by the agent. */
\r
7919 PUT_32BIT(s->agent_request, 1);
\r
7920 s->agent_request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
\r
7921 if (!agent_query(s->agent_request, 5, &r, &s->agent_responselen,
\r
7922 ssh_agent_callback, ssh)) {
\r
7926 bombout(("Unexpected data from server while"
\r
7927 " waiting for agent response"));
\r
7930 } while (pktin || inlen > 0);
\r
7931 r = ssh->agent_response;
\r
7932 s->agent_responselen = ssh->agent_response_len;
\r
7934 s->agent_response = (unsigned char *) r;
\r
7935 if (s->agent_response && s->agent_responselen >= 5 &&
\r
7936 s->agent_response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
\r
7939 p = s->agent_response + 5;
\r
7940 s->nkeys = toint(GET_32BIT(p));
\r
7943 * Vet the Pageant response to ensure that the key
\r
7944 * count and blob lengths make sense.
\r
7946 if (s->nkeys < 0) {
\r
7947 logeventf(ssh, "Pageant response contained a negative"
\r
7948 " key count %d", s->nkeys);
\r
7950 goto done_agent_query;
\r
7952 unsigned char *q = p + 4;
\r
7953 int lenleft = s->agent_responselen - 5 - 4;
\r
7955 for (keyi = 0; keyi < s->nkeys; keyi++) {
\r
7956 int bloblen, commentlen;
\r
7957 if (lenleft < 4) {
\r
7958 logeventf(ssh, "Pageant response was truncated");
\r
7960 goto done_agent_query;
\r
7962 bloblen = toint(GET_32BIT(q));
\r
7963 if (bloblen < 0 || bloblen > lenleft) {
\r
7964 logeventf(ssh, "Pageant response was truncated");
\r
7966 goto done_agent_query;
\r
7968 lenleft -= 4 + bloblen;
\r
7970 commentlen = toint(GET_32BIT(q));
\r
7971 if (commentlen < 0 || commentlen > lenleft) {
\r
7972 logeventf(ssh, "Pageant response was truncated");
\r
7974 goto done_agent_query;
\r
7976 lenleft -= 4 + commentlen;
\r
7977 q += 4 + commentlen;
\r
7982 logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
\r
7983 if (s->publickey_blob) {
\r
7984 /* See if configured key is in agent. */
\r
7985 for (keyi = 0; keyi < s->nkeys; keyi++) {
\r
7986 s->pklen = toint(GET_32BIT(p));
\r
7987 if (s->pklen == s->publickey_bloblen &&
\r
7988 !memcmp(p+4, s->publickey_blob,
\r
7989 s->publickey_bloblen)) {
\r
7990 logeventf(ssh, "Pageant key #%d matches "
\r
7991 "configured key file", keyi);
\r
7993 s->pkblob_in_agent = p;
\r
7996 p += 4 + s->pklen;
\r
7997 p += toint(GET_32BIT(p)) + 4; /* comment */
\r
7999 if (!s->pkblob_in_agent) {
\r
8000 logevent("Configured key file not in Pageant");
\r
8005 logevent("Failed to get reply from Pageant");
\r
8007 done_agent_query:;
\r
8013 * We repeat this whole loop, including the username prompt,
\r
8014 * until we manage a successful authentication. If the user
\r
8015 * types the wrong _password_, they can be sent back to the
\r
8016 * beginning to try another username, if this is configured on.
\r
8017 * (If they specify a username in the config, they are never
\r
8018 * asked, even if they do give a wrong password.)
\r
8020 * I think this best serves the needs of
\r
8022 * - the people who have no configuration, no keys, and just
\r
8023 * want to try repeated (username,password) pairs until they
\r
8024 * type both correctly
\r
8026 * - people who have keys and configuration but occasionally
\r
8027 * need to fall back to passwords
\r
8029 * - people with a key held in Pageant, who might not have
\r
8030 * logged in to a particular machine before; so they want to
\r
8031 * type a username, and then _either_ their key will be
\r
8032 * accepted, _or_ they will type a password. If they mistype
\r
8033 * the username they will want to be able to get back and
\r
8036 s->got_username = FALSE;
\r
8037 while (!s->we_are_in) {
\r
8041 if (s->got_username && !conf_get_int(ssh->conf, CONF_change_username)) {
\r
8043 * We got a username last time round this loop, and
\r
8044 * with change_username turned off we don't try to get
\r
8047 } else if ((ssh->username = get_remote_username(ssh->conf)) == NULL) {
\r
8048 int ret; /* need not be kept over crReturn */
\r
8049 s->cur_prompt = new_prompts(ssh->frontend);
\r
8050 s->cur_prompt->to_server = TRUE;
\r
8051 s->cur_prompt->name = dupstr("SSH login name");
\r
8052 add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
\r
8053 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
8056 crWaitUntilV(!pktin);
\r
8057 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
8062 * get_userpass_input() failed to get a username.
\r
8065 free_prompts(s->cur_prompt);
\r
8066 ssh_disconnect(ssh, "No username provided", NULL, 0, TRUE);
\r
8069 ssh->username = dupstr(s->cur_prompt->prompts[0]->result);
\r
8070 free_prompts(s->cur_prompt);
\r
8073 if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
\r
8074 stuff = dupprintf("Using username \"%s\".\r\n", ssh->username);
\r
8075 c_write_str(ssh, stuff);
\r
8079 s->got_username = TRUE;
\r
8082 * Send an authentication request using method "none": (a)
\r
8083 * just in case it succeeds, and (b) so that we know what
\r
8084 * authentication methods we can usefully try next.
\r
8086 ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
\r
8088 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8089 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8090 ssh2_pkt_addstring(s->pktout, "ssh-connection");/* service requested */
\r
8091 ssh2_pkt_addstring(s->pktout, "none"); /* method */
\r
8092 ssh2_pkt_send(ssh, s->pktout);
\r
8093 s->type = AUTH_TYPE_NONE;
\r
8095 s->we_are_in = FALSE;
\r
8097 s->tried_pubkey_config = FALSE;
\r
8098 s->kbd_inter_refused = FALSE;
\r
8100 /* Reset agent request state. */
\r
8101 s->done_agent = FALSE;
\r
8102 if (s->agent_response) {
\r
8103 if (s->pkblob_in_agent) {
\r
8104 s->agentp = s->pkblob_in_agent;
\r
8106 s->agentp = s->agent_response + 5 + 4;
\r
8112 char *methods = NULL;
\r
8116 * Wait for the result of the last authentication request.
\r
8119 crWaitUntilV(pktin);
\r
8121 * Now is a convenient point to spew any banner material
\r
8122 * that we've accumulated. (This should ensure that when
\r
8123 * we exit the auth loop, we haven't any left to deal
\r
8127 int size = bufchain_size(&ssh->banner);
\r
8129 * Don't show the banner if we're operating in
\r
8130 * non-verbose non-interactive mode. (It's probably
\r
8131 * a script, which means nobody will read the
\r
8132 * banner _anyway_, and moreover the printing of
\r
8133 * the banner will screw up processing on the
\r
8134 * output of (say) plink.)
\r
8136 if (size && (flags & (FLAG_VERBOSE | FLAG_INTERACTIVE))) {
\r
8137 char *banner = snewn(size, char);
\r
8138 bufchain_fetch(&ssh->banner, banner, size);
\r
8139 c_write_untrusted(ssh, banner, size);
\r
8142 bufchain_clear(&ssh->banner);
\r
8144 if (pktin->type == SSH2_MSG_USERAUTH_SUCCESS) {
\r
8145 logevent("Access granted");
\r
8146 s->we_are_in = s->userauth_success = TRUE;
\r
8150 if (pktin->type != SSH2_MSG_USERAUTH_FAILURE && s->type != AUTH_TYPE_GSSAPI) {
\r
8151 bombout(("Strange packet received during authentication: "
\r
8152 "type %d", pktin->type));
\r
8159 * OK, we're now sitting on a USERAUTH_FAILURE message, so
\r
8160 * we can look at the string in it and know what we can
\r
8161 * helpfully try next.
\r
8163 if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
\r
8164 ssh_pkt_getstring(pktin, &methods, &methlen);
\r
8165 if (!ssh2_pkt_getbool(pktin)) {
\r
8167 * We have received an unequivocal Access
\r
8168 * Denied. This can translate to a variety of
\r
8169 * messages, or no message at all.
\r
8171 * For forms of authentication which are attempted
\r
8172 * implicitly, by which I mean without printing
\r
8173 * anything in the window indicating that we're
\r
8174 * trying them, we should never print 'Access
\r
8177 * If we do print a message saying that we're
\r
8178 * attempting some kind of authentication, it's OK
\r
8179 * to print a followup message saying it failed -
\r
8180 * but the message may sometimes be more specific
\r
8181 * than simply 'Access denied'.
\r
8183 * Additionally, if we'd just tried password
\r
8184 * authentication, we should break out of this
\r
8185 * whole loop so as to go back to the username
\r
8186 * prompt (iff we're configured to allow
\r
8187 * username change attempts).
\r
8189 if (s->type == AUTH_TYPE_NONE) {
\r
8191 } else if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD ||
\r
8192 s->type == AUTH_TYPE_PUBLICKEY_OFFER_QUIET) {
\r
8193 if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD)
\r
8194 c_write_str(ssh, "Server refused our key\r\n");
\r
8195 logevent("Server refused our key");
\r
8196 } else if (s->type == AUTH_TYPE_PUBLICKEY) {
\r
8197 /* This _shouldn't_ happen except by a
\r
8198 * protocol bug causing client and server to
\r
8199 * disagree on what is a correct signature. */
\r
8200 c_write_str(ssh, "Server refused public-key signature"
\r
8201 " despite accepting key!\r\n");
\r
8202 logevent("Server refused public-key signature"
\r
8203 " despite accepting key!");
\r
8204 } else if (s->type==AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET) {
\r
8205 /* quiet, so no c_write */
\r
8206 logevent("Server refused keyboard-interactive authentication");
\r
8207 } else if (s->type==AUTH_TYPE_GSSAPI) {
\r
8208 /* always quiet, so no c_write */
\r
8209 /* also, the code down in the GSSAPI block has
\r
8210 * already logged this in the Event Log */
\r
8211 } else if (s->type == AUTH_TYPE_KEYBOARD_INTERACTIVE) {
\r
8212 logevent("Keyboard-interactive authentication failed");
\r
8213 c_write_str(ssh, "Access denied\r\n");
\r
8215 assert(s->type == AUTH_TYPE_PASSWORD);
\r
8216 logevent("Password authentication failed");
\r
8217 c_write_str(ssh, "Access denied\r\n");
\r
8219 if (conf_get_int(ssh->conf, CONF_change_username)) {
\r
8220 /* XXX perhaps we should allow
\r
8221 * keyboard-interactive to do this too? */
\r
8222 s->we_are_in = FALSE;
\r
8227 c_write_str(ssh, "Further authentication required\r\n");
\r
8228 logevent("Further authentication required");
\r
8232 in_commasep_string("publickey", methods, methlen);
\r
8234 in_commasep_string("password", methods, methlen);
\r
8235 s->can_keyb_inter = conf_get_int(ssh->conf, CONF_try_ki_auth) &&
\r
8236 in_commasep_string("keyboard-interactive", methods, methlen);
\r
8238 if (!ssh->gsslibs)
\r
8239 ssh->gsslibs = ssh_gss_setup(ssh->conf);
\r
8240 s->can_gssapi = conf_get_int(ssh->conf, CONF_try_gssapi_auth) &&
\r
8241 in_commasep_string("gssapi-with-mic", methods, methlen) &&
\r
8242 ssh->gsslibs->nlibraries > 0;
\r
8246 ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
\r
8248 if (s->can_pubkey && !s->done_agent && s->nkeys) {
\r
8251 * Attempt public-key authentication using a key from Pageant.
\r
8254 ssh->pkt_actx = SSH2_PKTCTX_PUBLICKEY;
\r
8256 logeventf(ssh, "Trying Pageant key #%d", s->keyi);
\r
8258 /* Unpack key from agent response */
\r
8259 s->pklen = toint(GET_32BIT(s->agentp));
\r
8261 s->pkblob = (char *)s->agentp;
\r
8262 s->agentp += s->pklen;
\r
8263 s->alglen = toint(GET_32BIT(s->pkblob));
\r
8264 s->alg = s->pkblob + 4;
\r
8265 s->commentlen = toint(GET_32BIT(s->agentp));
\r
8267 s->commentp = (char *)s->agentp;
\r
8268 s->agentp += s->commentlen;
\r
8269 /* s->agentp now points at next key, if any */
\r
8271 /* See if server will accept it */
\r
8272 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8273 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8274 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8275 /* service requested */
\r
8276 ssh2_pkt_addstring(s->pktout, "publickey");
\r
8278 ssh2_pkt_addbool(s->pktout, FALSE); /* no signature included */
\r
8279 ssh2_pkt_addstring_start(s->pktout);
\r
8280 ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
\r
8281 ssh2_pkt_addstring_start(s->pktout);
\r
8282 ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
\r
8283 ssh2_pkt_send(ssh, s->pktout);
\r
8284 s->type = AUTH_TYPE_PUBLICKEY_OFFER_QUIET;
\r
8286 crWaitUntilV(pktin);
\r
8287 if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
\r
8289 /* Offer of key refused. */
\r
8296 if (flags & FLAG_VERBOSE) {
\r
8297 c_write_str(ssh, "Authenticating with "
\r
8299 c_write(ssh, s->commentp, s->commentlen);
\r
8300 c_write_str(ssh, "\" from agent\r\n");
\r
8304 * Server is willing to accept the key.
\r
8305 * Construct a SIGN_REQUEST.
\r
8307 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8308 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8309 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8310 /* service requested */
\r
8311 ssh2_pkt_addstring(s->pktout, "publickey");
\r
8313 ssh2_pkt_addbool(s->pktout, TRUE); /* signature included */
\r
8314 ssh2_pkt_addstring_start(s->pktout);
\r
8315 ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
\r
8316 ssh2_pkt_addstring_start(s->pktout);
\r
8317 ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
\r
8319 /* Ask agent for signature. */
\r
8320 s->siglen = s->pktout->length - 5 + 4 +
\r
8321 ssh->v2_session_id_len;
\r
8322 if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
\r
8324 s->len = 1; /* message type */
\r
8325 s->len += 4 + s->pklen; /* key blob */
\r
8326 s->len += 4 + s->siglen; /* data to sign */
\r
8327 s->len += 4; /* flags */
\r
8328 s->agentreq = snewn(4 + s->len, char);
\r
8329 PUT_32BIT(s->agentreq, s->len);
\r
8330 s->q = s->agentreq + 4;
\r
8331 *s->q++ = SSH2_AGENTC_SIGN_REQUEST;
\r
8332 PUT_32BIT(s->q, s->pklen);
\r
8334 memcpy(s->q, s->pkblob, s->pklen);
\r
8336 PUT_32BIT(s->q, s->siglen);
\r
8338 /* Now the data to be signed... */
\r
8339 if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
\r
8340 PUT_32BIT(s->q, ssh->v2_session_id_len);
\r
8343 memcpy(s->q, ssh->v2_session_id,
\r
8344 ssh->v2_session_id_len);
\r
8345 s->q += ssh->v2_session_id_len;
\r
8346 memcpy(s->q, s->pktout->data + 5,
\r
8347 s->pktout->length - 5);
\r
8348 s->q += s->pktout->length - 5;
\r
8349 /* And finally the (zero) flags word. */
\r
8350 PUT_32BIT(s->q, 0);
\r
8351 if (!agent_query(s->agentreq, s->len + 4,
\r
8352 &vret, &s->retlen,
\r
8353 ssh_agent_callback, ssh)) {
\r
8357 bombout(("Unexpected data from server"
\r
8358 " while waiting for agent"
\r
8362 } while (pktin || inlen > 0);
\r
8363 vret = ssh->agent_response;
\r
8364 s->retlen = ssh->agent_response_len;
\r
8367 sfree(s->agentreq);
\r
8369 if (s->retlen >= 9 &&
\r
8370 s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
\r
8371 GET_32BIT(s->ret + 5) <= (unsigned)(s->retlen-9)) {
\r
8372 logevent("Sending Pageant's response");
\r
8373 ssh2_add_sigblob(ssh, s->pktout,
\r
8374 s->pkblob, s->pklen,
\r
8376 GET_32BIT(s->ret + 5));
\r
8377 ssh2_pkt_send(ssh, s->pktout);
\r
8378 s->type = AUTH_TYPE_PUBLICKEY;
\r
8380 /* FIXME: less drastic response */
\r
8381 bombout(("Pageant failed to answer challenge"));
\r
8387 /* Do we have any keys left to try? */
\r
8388 if (s->pkblob_in_agent) {
\r
8389 s->done_agent = TRUE;
\r
8390 s->tried_pubkey_config = TRUE;
\r
8393 if (s->keyi >= s->nkeys)
\r
8394 s->done_agent = TRUE;
\r
8397 } else if (s->can_pubkey && s->publickey_blob &&
\r
8398 !s->tried_pubkey_config) {
\r
8400 struct ssh2_userkey *key; /* not live over crReturn */
\r
8401 char *passphrase; /* not live over crReturn */
\r
8403 ssh->pkt_actx = SSH2_PKTCTX_PUBLICKEY;
\r
8405 s->tried_pubkey_config = TRUE;
\r
8408 * Try the public key supplied in the configuration.
\r
8410 * First, offer the public blob to see if the server is
\r
8411 * willing to accept it.
\r
8413 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8414 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8415 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8416 /* service requested */
\r
8417 ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
\r
8418 ssh2_pkt_addbool(s->pktout, FALSE);
\r
8419 /* no signature included */
\r
8420 ssh2_pkt_addstring(s->pktout, s->publickey_algorithm);
\r
8421 ssh2_pkt_addstring_start(s->pktout);
\r
8422 ssh2_pkt_addstring_data(s->pktout,
\r
8423 (char *)s->publickey_blob,
\r
8424 s->publickey_bloblen);
\r
8425 ssh2_pkt_send(ssh, s->pktout);
\r
8426 logevent("Offered public key");
\r
8428 crWaitUntilV(pktin);
\r
8429 if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
\r
8430 /* Key refused. Give up. */
\r
8431 s->gotit = TRUE; /* reconsider message next loop */
\r
8432 s->type = AUTH_TYPE_PUBLICKEY_OFFER_LOUD;
\r
8433 continue; /* process this new message */
\r
8435 logevent("Offer of public key accepted");
\r
8438 * Actually attempt a serious authentication using
\r
8441 if (flags & FLAG_VERBOSE) {
\r
8442 c_write_str(ssh, "Authenticating with public key \"");
\r
8443 c_write_str(ssh, s->publickey_comment);
\r
8444 c_write_str(ssh, "\"\r\n");
\r
8448 const char *error; /* not live over crReturn */
\r
8449 if (s->publickey_encrypted) {
\r
8451 * Get a passphrase from the user.
\r
8453 int ret; /* need not be kept over crReturn */
\r
8454 s->cur_prompt = new_prompts(ssh->frontend);
\r
8455 s->cur_prompt->to_server = FALSE;
\r
8456 s->cur_prompt->name = dupstr("SSH key passphrase");
\r
8457 add_prompt(s->cur_prompt,
\r
8458 dupprintf("Passphrase for key \"%.100s\": ",
\r
8459 s->publickey_comment),
\r
8461 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
8464 crWaitUntilV(!pktin);
\r
8465 ret = get_userpass_input(s->cur_prompt,
\r
8470 /* Failed to get a passphrase. Terminate. */
\r
8471 free_prompts(s->cur_prompt);
\r
8472 ssh_disconnect(ssh, NULL,
\r
8473 "Unable to authenticate",
\r
8474 SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
\r
8479 dupstr(s->cur_prompt->prompts[0]->result);
\r
8480 free_prompts(s->cur_prompt);
\r
8482 passphrase = NULL; /* no passphrase needed */
\r
8486 * Try decrypting the key.
\r
8488 s->keyfile = conf_get_filename(ssh->conf, CONF_keyfile);
\r
8489 key = ssh2_load_userkey(s->keyfile, passphrase, &error);
\r
8491 /* burn the evidence */
\r
8492 smemclr(passphrase, strlen(passphrase));
\r
8493 sfree(passphrase);
\r
8495 if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
\r
8497 (key == SSH2_WRONG_PASSPHRASE)) {
\r
8498 c_write_str(ssh, "Wrong passphrase\r\n");
\r
8500 /* and loop again */
\r
8502 c_write_str(ssh, "Unable to load private key (");
\r
8503 c_write_str(ssh, error);
\r
8504 c_write_str(ssh, ")\r\n");
\r
8506 break; /* try something else */
\r
8512 unsigned char *pkblob, *sigblob, *sigdata;
\r
8513 int pkblob_len, sigblob_len, sigdata_len;
\r
8517 * We have loaded the private key and the server
\r
8518 * has announced that it's willing to accept it.
\r
8519 * Hallelujah. Generate a signature and send it.
\r
8521 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8522 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8523 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8524 /* service requested */
\r
8525 ssh2_pkt_addstring(s->pktout, "publickey");
\r
8527 ssh2_pkt_addbool(s->pktout, TRUE);
\r
8528 /* signature follows */
\r
8529 ssh2_pkt_addstring(s->pktout, key->alg->name);
\r
8530 pkblob = key->alg->public_blob(key->data,
\r
8532 ssh2_pkt_addstring_start(s->pktout);
\r
8533 ssh2_pkt_addstring_data(s->pktout, (char *)pkblob,
\r
8537 * The data to be signed is:
\r
8539 * string session-id
\r
8541 * followed by everything so far placed in the
\r
8542 * outgoing packet.
\r
8544 sigdata_len = s->pktout->length - 5 + 4 +
\r
8545 ssh->v2_session_id_len;
\r
8546 if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
\r
8548 sigdata = snewn(sigdata_len, unsigned char);
\r
8550 if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
\r
8551 PUT_32BIT(sigdata+p, ssh->v2_session_id_len);
\r
8554 memcpy(sigdata+p, ssh->v2_session_id,
\r
8555 ssh->v2_session_id_len);
\r
8556 p += ssh->v2_session_id_len;
\r
8557 memcpy(sigdata+p, s->pktout->data + 5,
\r
8558 s->pktout->length - 5);
\r
8559 p += s->pktout->length - 5;
\r
8560 assert(p == sigdata_len);
\r
8561 sigblob = key->alg->sign(key->data, (char *)sigdata,
\r
8562 sigdata_len, &sigblob_len);
\r
8563 ssh2_add_sigblob(ssh, s->pktout, pkblob, pkblob_len,
\r
8564 sigblob, sigblob_len);
\r
8569 ssh2_pkt_send(ssh, s->pktout);
\r
8570 logevent("Sent public key signature");
\r
8571 s->type = AUTH_TYPE_PUBLICKEY;
\r
8572 key->alg->freekey(key->data);
\r
8576 } else if (s->can_gssapi && !s->tried_gssapi) {
\r
8578 /* GSSAPI Authentication */
\r
8580 int micoffset, len;
\r
8583 s->type = AUTH_TYPE_GSSAPI;
\r
8584 s->tried_gssapi = TRUE;
\r
8586 ssh->pkt_actx = SSH2_PKTCTX_GSSAPI;
\r
8589 * Pick the highest GSS library on the preference
\r
8595 for (i = 0; i < ngsslibs; i++) {
\r
8596 int want_id = conf_get_int_int(ssh->conf,
\r
8597 CONF_ssh_gsslist, i);
\r
8598 for (j = 0; j < ssh->gsslibs->nlibraries; j++)
\r
8599 if (ssh->gsslibs->libraries[j].id == want_id) {
\r
8600 s->gsslib = &ssh->gsslibs->libraries[j];
\r
8601 goto got_gsslib; /* double break */
\r
8606 * We always expect to have found something in
\r
8607 * the above loop: we only came here if there
\r
8608 * was at least one viable GSS library, and the
\r
8609 * preference list should always mention
\r
8610 * everything and only change the order.
\r
8612 assert(s->gsslib);
\r
8615 if (s->gsslib->gsslogmsg)
\r
8616 logevent(s->gsslib->gsslogmsg);
\r
8618 /* Sending USERAUTH_REQUEST with "gssapi-with-mic" method */
\r
8619 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8620 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8621 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8622 ssh2_pkt_addstring(s->pktout, "gssapi-with-mic");
\r
8623 logevent("Attempting GSSAPI authentication");
\r
8625 /* add mechanism info */
\r
8626 s->gsslib->indicate_mech(s->gsslib, &s->gss_buf);
\r
8628 /* number of GSSAPI mechanisms */
\r
8629 ssh2_pkt_adduint32(s->pktout,1);
\r
8631 /* length of OID + 2 */
\r
8632 ssh2_pkt_adduint32(s->pktout, s->gss_buf.length + 2);
\r
8633 ssh2_pkt_addbyte(s->pktout, SSH2_GSS_OIDTYPE);
\r
8635 /* length of OID */
\r
8636 ssh2_pkt_addbyte(s->pktout, (unsigned char) s->gss_buf.length);
\r
8638 ssh_pkt_adddata(s->pktout, s->gss_buf.value,
\r
8639 s->gss_buf.length);
\r
8640 ssh2_pkt_send(ssh, s->pktout);
\r
8641 crWaitUntilV(pktin);
\r
8642 if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) {
\r
8643 logevent("GSSAPI authentication request refused");
\r
8647 /* check returned packet ... */
\r
8649 ssh_pkt_getstring(pktin, &data, &len);
\r
8650 s->gss_rcvtok.value = data;
\r
8651 s->gss_rcvtok.length = len;
\r
8652 if (s->gss_rcvtok.length != s->gss_buf.length + 2 ||
\r
8653 ((char *)s->gss_rcvtok.value)[0] != SSH2_GSS_OIDTYPE ||
\r
8654 ((char *)s->gss_rcvtok.value)[1] != s->gss_buf.length ||
\r
8655 memcmp((char *)s->gss_rcvtok.value + 2,
\r
8656 s->gss_buf.value,s->gss_buf.length) ) {
\r
8657 logevent("GSSAPI authentication - wrong response from server");
\r
8661 /* now start running */
\r
8662 s->gss_stat = s->gsslib->import_name(s->gsslib,
\r
8663 ssh->fullhostname,
\r
8664 &s->gss_srv_name);
\r
8665 if (s->gss_stat != SSH_GSS_OK) {
\r
8666 if (s->gss_stat == SSH_GSS_BAD_HOST_NAME)
\r
8667 logevent("GSSAPI import name failed - Bad service name");
\r
8669 logevent("GSSAPI import name failed");
\r
8673 /* fetch TGT into GSS engine */
\r
8674 s->gss_stat = s->gsslib->acquire_cred(s->gsslib, &s->gss_ctx);
\r
8676 if (s->gss_stat != SSH_GSS_OK) {
\r
8677 logevent("GSSAPI authentication failed to get credentials");
\r
8678 s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
\r
8682 /* initial tokens are empty */
\r
8683 SSH_GSS_CLEAR_BUF(&s->gss_rcvtok);
\r
8684 SSH_GSS_CLEAR_BUF(&s->gss_sndtok);
\r
8686 /* now enter the loop */
\r
8688 s->gss_stat = s->gsslib->init_sec_context
\r
8692 conf_get_int(ssh->conf, CONF_gssapifwd),
\r
8696 if (s->gss_stat!=SSH_GSS_S_COMPLETE &&
\r
8697 s->gss_stat!=SSH_GSS_S_CONTINUE_NEEDED) {
\r
8698 logevent("GSSAPI authentication initialisation failed");
\r
8700 if (s->gsslib->display_status(s->gsslib, s->gss_ctx,
\r
8701 &s->gss_buf) == SSH_GSS_OK) {
\r
8702 logevent(s->gss_buf.value);
\r
8703 sfree(s->gss_buf.value);
\r
8708 logevent("GSSAPI authentication initialised");
\r
8710 /* Client and server now exchange tokens until GSSAPI
\r
8711 * no longer says CONTINUE_NEEDED */
\r
8713 if (s->gss_sndtok.length != 0) {
\r
8714 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
\r
8715 ssh_pkt_addstring_start(s->pktout);
\r
8716 ssh_pkt_addstring_data(s->pktout,s->gss_sndtok.value,s->gss_sndtok.length);
\r
8717 ssh2_pkt_send(ssh, s->pktout);
\r
8718 s->gsslib->free_tok(s->gsslib, &s->gss_sndtok);
\r
8721 if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) {
\r
8722 crWaitUntilV(pktin);
\r
8723 if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_TOKEN) {
\r
8724 logevent("GSSAPI authentication - bad server response");
\r
8725 s->gss_stat = SSH_GSS_FAILURE;
\r
8728 ssh_pkt_getstring(pktin, &data, &len);
\r
8729 s->gss_rcvtok.value = data;
\r
8730 s->gss_rcvtok.length = len;
\r
8732 } while (s-> gss_stat == SSH_GSS_S_CONTINUE_NEEDED);
\r
8734 if (s->gss_stat != SSH_GSS_OK) {
\r
8735 s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
\r
8736 s->gsslib->release_cred(s->gsslib, &s->gss_ctx);
\r
8739 logevent("GSSAPI authentication loop finished OK");
\r
8741 /* Now send the MIC */
\r
8743 s->pktout = ssh2_pkt_init(0);
\r
8744 micoffset = s->pktout->length;
\r
8745 ssh_pkt_addstring_start(s->pktout);
\r
8746 ssh_pkt_addstring_data(s->pktout, (char *)ssh->v2_session_id, ssh->v2_session_id_len);
\r
8747 ssh_pkt_addbyte(s->pktout, SSH2_MSG_USERAUTH_REQUEST);
\r
8748 ssh_pkt_addstring(s->pktout, ssh->username);
\r
8749 ssh_pkt_addstring(s->pktout, "ssh-connection");
\r
8750 ssh_pkt_addstring(s->pktout, "gssapi-with-mic");
\r
8752 s->gss_buf.value = (char *)s->pktout->data + micoffset;
\r
8753 s->gss_buf.length = s->pktout->length - micoffset;
\r
8755 s->gsslib->get_mic(s->gsslib, s->gss_ctx, &s->gss_buf, &mic);
\r
8756 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_GSSAPI_MIC);
\r
8757 ssh_pkt_addstring_start(s->pktout);
\r
8758 ssh_pkt_addstring_data(s->pktout, mic.value, mic.length);
\r
8759 ssh2_pkt_send(ssh, s->pktout);
\r
8760 s->gsslib->free_mic(s->gsslib, &mic);
\r
8764 s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
\r
8765 s->gsslib->release_cred(s->gsslib, &s->gss_ctx);
\r
8768 } else if (s->can_keyb_inter && !s->kbd_inter_refused) {
\r
8771 * Keyboard-interactive authentication.
\r
8774 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
\r
8776 ssh->pkt_actx = SSH2_PKTCTX_KBDINTER;
\r
8778 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8779 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8780 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8781 /* service requested */
\r
8782 ssh2_pkt_addstring(s->pktout, "keyboard-interactive");
\r
8784 ssh2_pkt_addstring(s->pktout, ""); /* lang */
\r
8785 ssh2_pkt_addstring(s->pktout, ""); /* submethods */
\r
8786 ssh2_pkt_send(ssh, s->pktout);
\r
8788 logevent("Attempting keyboard-interactive authentication");
\r
8790 crWaitUntilV(pktin);
\r
8791 if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
\r
8792 /* Server is not willing to do keyboard-interactive
\r
8793 * at all (or, bizarrely but legally, accepts the
\r
8794 * user without actually issuing any prompts).
\r
8795 * Give up on it entirely. */
\r
8797 s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET;
\r
8798 s->kbd_inter_refused = TRUE; /* don't try it again */
\r
8803 * Loop while the server continues to send INFO_REQUESTs.
\r
8805 while (pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) {
\r
8807 char *name, *inst, *lang;
\r
8808 int name_len, inst_len, lang_len;
\r
8812 * We've got a fresh USERAUTH_INFO_REQUEST.
\r
8813 * Get the preamble and start building a prompt.
\r
8815 ssh_pkt_getstring(pktin, &name, &name_len);
\r
8816 ssh_pkt_getstring(pktin, &inst, &inst_len);
\r
8817 ssh_pkt_getstring(pktin, &lang, &lang_len);
\r
8818 s->cur_prompt = new_prompts(ssh->frontend);
\r
8819 s->cur_prompt->to_server = TRUE;
\r
8822 * Get any prompt(s) from the packet.
\r
8824 s->num_prompts = ssh_pkt_getuint32(pktin);
\r
8825 for (i = 0; i < s->num_prompts; i++) {
\r
8829 static char noprompt[] =
\r
8830 "<server failed to send prompt>: ";
\r
8832 ssh_pkt_getstring(pktin, &prompt, &prompt_len);
\r
8833 echo = ssh2_pkt_getbool(pktin);
\r
8834 if (!prompt_len) {
\r
8835 prompt = noprompt;
\r
8836 prompt_len = lenof(noprompt)-1;
\r
8838 add_prompt(s->cur_prompt,
\r
8839 dupprintf("%.*s", prompt_len, prompt),
\r
8844 /* FIXME: better prefix to distinguish from
\r
8845 * local prompts? */
\r
8846 s->cur_prompt->name =
\r
8847 dupprintf("SSH server: %.*s", name_len, name);
\r
8848 s->cur_prompt->name_reqd = TRUE;
\r
8850 s->cur_prompt->name =
\r
8851 dupstr("SSH server authentication");
\r
8852 s->cur_prompt->name_reqd = FALSE;
\r
8854 /* We add a prefix to try to make it clear that a prompt
\r
8855 * has come from the server.
\r
8856 * FIXME: ugly to print "Using..." in prompt _every_
\r
8857 * time round. Can this be done more subtly? */
\r
8858 /* Special case: for reasons best known to themselves,
\r
8859 * some servers send k-i requests with no prompts and
\r
8860 * nothing to display. Keep quiet in this case. */
\r
8861 if (s->num_prompts || name_len || inst_len) {
\r
8862 s->cur_prompt->instruction =
\r
8863 dupprintf("Using keyboard-interactive authentication.%s%.*s",
\r
8864 inst_len ? "\n" : "", inst_len, inst);
\r
8865 s->cur_prompt->instr_reqd = TRUE;
\r
8867 s->cur_prompt->instr_reqd = FALSE;
\r
8871 * Display any instructions, and get the user's
\r
8875 int ret; /* not live over crReturn */
\r
8876 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
8879 crWaitUntilV(!pktin);
\r
8880 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
8885 * Failed to get responses. Terminate.
\r
8887 free_prompts(s->cur_prompt);
\r
8888 ssh_disconnect(ssh, NULL, "Unable to authenticate",
\r
8889 SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
\r
8896 * Send the response(s) to the server.
\r
8898 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
\r
8899 ssh2_pkt_adduint32(s->pktout, s->num_prompts);
\r
8900 for (i=0; i < s->num_prompts; i++) {
\r
8901 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
\r
8902 ssh2_pkt_addstring(s->pktout,
\r
8903 s->cur_prompt->prompts[i]->result);
\r
8904 end_log_omission(ssh, s->pktout);
\r
8906 ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
\r
8909 * Free the prompts structure from this iteration.
\r
8910 * If there's another, a new one will be allocated
\r
8911 * when we return to the top of this while loop.
\r
8913 free_prompts(s->cur_prompt);
\r
8916 * Get the next packet in case it's another
\r
8919 crWaitUntilV(pktin);
\r
8924 * We should have SUCCESS or FAILURE now.
\r
8928 } else if (s->can_passwd) {
\r
8931 * Plain old password authentication.
\r
8933 int ret; /* not live over crReturn */
\r
8934 int changereq_first_time; /* not live over crReturn */
\r
8936 ssh->pkt_actx = SSH2_PKTCTX_PASSWORD;
\r
8938 s->cur_prompt = new_prompts(ssh->frontend);
\r
8939 s->cur_prompt->to_server = TRUE;
\r
8940 s->cur_prompt->name = dupstr("SSH password");
\r
8941 add_prompt(s->cur_prompt, dupprintf("%s@%s's password: ",
\r
8946 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
8949 crWaitUntilV(!pktin);
\r
8950 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
8955 * Failed to get responses. Terminate.
\r
8957 free_prompts(s->cur_prompt);
\r
8958 ssh_disconnect(ssh, NULL, "Unable to authenticate",
\r
8959 SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
\r
8964 * Squirrel away the password. (We may need it later if
\r
8965 * asked to change it.)
\r
8967 s->password = dupstr(s->cur_prompt->prompts[0]->result);
\r
8968 free_prompts(s->cur_prompt);
\r
8971 * Send the password packet.
\r
8973 * We pad out the password packet to 256 bytes to make
\r
8974 * it harder for an attacker to find the length of the
\r
8975 * user's password.
\r
8977 * Anyone using a password longer than 256 bytes
\r
8978 * probably doesn't have much to worry about from
\r
8979 * people who find out how long their password is!
\r
8981 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
8982 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
8983 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
8984 /* service requested */
\r
8985 ssh2_pkt_addstring(s->pktout, "password");
\r
8986 ssh2_pkt_addbool(s->pktout, FALSE);
\r
8987 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
\r
8988 ssh2_pkt_addstring(s->pktout, s->password);
\r
8989 end_log_omission(ssh, s->pktout);
\r
8990 ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
\r
8991 logevent("Sent password");
\r
8992 s->type = AUTH_TYPE_PASSWORD;
\r
8995 * Wait for next packet, in case it's a password change
\r
8998 crWaitUntilV(pktin);
\r
8999 changereq_first_time = TRUE;
\r
9001 while (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) {
\r
9004 * We're being asked for a new password
\r
9005 * (perhaps not for the first time).
\r
9006 * Loop until the server accepts it.
\r
9009 int got_new = FALSE; /* not live over crReturn */
\r
9010 char *prompt; /* not live over crReturn */
\r
9011 int prompt_len; /* not live over crReturn */
\r
9015 if (changereq_first_time)
\r
9016 msg = "Server requested password change";
\r
9018 msg = "Server rejected new password";
\r
9020 c_write_str(ssh, msg);
\r
9021 c_write_str(ssh, "\r\n");
\r
9024 ssh_pkt_getstring(pktin, &prompt, &prompt_len);
\r
9026 s->cur_prompt = new_prompts(ssh->frontend);
\r
9027 s->cur_prompt->to_server = TRUE;
\r
9028 s->cur_prompt->name = dupstr("New SSH password");
\r
9029 s->cur_prompt->instruction =
\r
9030 dupprintf("%.*s", prompt_len, prompt);
\r
9031 s->cur_prompt->instr_reqd = TRUE;
\r
9033 * There's no explicit requirement in the protocol
\r
9034 * for the "old" passwords in the original and
\r
9035 * password-change messages to be the same, and
\r
9036 * apparently some Cisco kit supports password change
\r
9037 * by the user entering a blank password originally
\r
9038 * and the real password subsequently, so,
\r
9039 * reluctantly, we prompt for the old password again.
\r
9041 * (On the other hand, some servers don't even bother
\r
9042 * to check this field.)
\r
9044 add_prompt(s->cur_prompt,
\r
9045 dupstr("Current password (blank for previously entered password): "),
\r
9047 add_prompt(s->cur_prompt, dupstr("Enter new password: "),
\r
9049 add_prompt(s->cur_prompt, dupstr("Confirm new password: "),
\r
9053 * Loop until the user manages to enter the same
\r
9056 while (!got_new) {
\r
9058 ret = get_userpass_input(s->cur_prompt, NULL, 0);
\r
9061 crWaitUntilV(!pktin);
\r
9062 ret = get_userpass_input(s->cur_prompt, in, inlen);
\r
9067 * Failed to get responses. Terminate.
\r
9069 /* burn the evidence */
\r
9070 free_prompts(s->cur_prompt);
\r
9071 smemclr(s->password, strlen(s->password));
\r
9072 sfree(s->password);
\r
9073 ssh_disconnect(ssh, NULL, "Unable to authenticate",
\r
9074 SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
\r
9080 * If the user specified a new original password
\r
9081 * (IYSWIM), overwrite any previously specified
\r
9083 * (A side effect is that the user doesn't have to
\r
9084 * re-enter it if they louse up the new password.)
\r
9086 if (s->cur_prompt->prompts[0]->result[0]) {
\r
9087 smemclr(s->password, strlen(s->password));
\r
9088 /* burn the evidence */
\r
9089 sfree(s->password);
\r
9091 dupstr(s->cur_prompt->prompts[0]->result);
\r
9095 * Check the two new passwords match.
\r
9097 got_new = (strcmp(s->cur_prompt->prompts[1]->result,
\r
9098 s->cur_prompt->prompts[2]->result)
\r
9101 /* They don't. Silly user. */
\r
9102 c_write_str(ssh, "Passwords do not match\r\n");
\r
9107 * Send the new password (along with the old one).
\r
9108 * (see above for padding rationale)
\r
9110 s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
\r
9111 ssh2_pkt_addstring(s->pktout, ssh->username);
\r
9112 ssh2_pkt_addstring(s->pktout, "ssh-connection");
\r
9113 /* service requested */
\r
9114 ssh2_pkt_addstring(s->pktout, "password");
\r
9115 ssh2_pkt_addbool(s->pktout, TRUE);
\r
9116 dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
\r
9117 ssh2_pkt_addstring(s->pktout, s->password);
\r
9118 ssh2_pkt_addstring(s->pktout,
\r
9119 s->cur_prompt->prompts[1]->result);
\r
9120 free_prompts(s->cur_prompt);
\r
9121 end_log_omission(ssh, s->pktout);
\r
9122 ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
\r
9123 logevent("Sent new password");
\r
9126 * Now see what the server has to say about it.
\r
9127 * (If it's CHANGEREQ again, it's not happy with the
\r
9130 crWaitUntilV(pktin);
\r
9131 changereq_first_time = FALSE;
\r
9136 * We need to reexamine the current pktin at the top
\r
9137 * of the loop. Either:
\r
9138 * - we weren't asked to change password at all, in
\r
9139 * which case it's a SUCCESS or FAILURE with the
\r
9141 * - we sent a new password, and the server was
\r
9142 * either OK with it (SUCCESS or FAILURE w/partial
\r
9143 * success) or unhappy with the _old_ password
\r
9144 * (FAILURE w/o partial success)
\r
9145 * In any of these cases, we go back to the top of
\r
9146 * the loop and start again.
\r
9151 * We don't need the old password any more, in any
\r
9152 * case. Burn the evidence.
\r
9154 smemclr(s->password, strlen(s->password));
\r
9155 sfree(s->password);
\r
9158 char *str = dupprintf("No supported authentication methods available"
\r
9159 " (server sent: %.*s)",
\r
9160 methlen, methods);
\r
9162 ssh_disconnect(ssh, str,
\r
9163 "No supported authentication methods available",
\r
9164 SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
\r
9174 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = NULL;
\r
9176 /* Clear up various bits and pieces from authentication. */
\r
9177 if (s->publickey_blob) {
\r
9178 sfree(s->publickey_blob);
\r
9179 sfree(s->publickey_comment);
\r
9181 if (s->agent_response)
\r
9182 sfree(s->agent_response);
\r
9184 if (s->userauth_success) {
\r
9186 * We've just received USERAUTH_SUCCESS, and we haven't sent any
\r
9187 * packets since. Signal the transport layer to consider enacting
\r
9188 * delayed compression.
\r
9190 * (Relying on we_are_in is not sufficient, as
\r
9191 * draft-miller-secsh-compression-delayed is quite clear that it
\r
9192 * triggers on USERAUTH_SUCCESS specifically, and we_are_in can
\r
9193 * become set for other reasons.)
\r
9195 do_ssh2_transport(ssh, "enabling delayed compression", -2, NULL);
\r
9199 * Now the connection protocol has started, one way or another.
\r
9202 ssh->channels = newtree234(ssh_channelcmp);
\r
9205 * Set up handlers for some connection protocol messages, so we
\r
9206 * don't have to handle them repeatedly in this coroutine.
\r
9208 ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] =
\r
9209 ssh2_msg_channel_window_adjust;
\r
9210 ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] =
\r
9211 ssh2_msg_global_request;
\r
9214 * Create the main session channel.
\r
9216 if (conf_get_int(ssh->conf, CONF_ssh_no_shell)) {
\r
9217 ssh->mainchan = NULL;
\r
9219 ssh->mainchan = snew(struct ssh_channel);
\r
9220 ssh->mainchan->ssh = ssh;
\r
9221 ssh2_channel_init(ssh->mainchan);
\r
9223 if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) {
\r
9225 * Just start a direct-tcpip channel and use it as the main
\r
9228 ssh_send_port_open(ssh->mainchan,
\r
9229 conf_get_str(ssh->conf, CONF_ssh_nc_host),
\r
9230 conf_get_int(ssh->conf, CONF_ssh_nc_port),
\r
9232 ssh->ncmode = TRUE;
\r
9234 s->pktout = ssh2_chanopen_init(ssh->mainchan, "session");
\r
9235 logevent("Opening session as main channel");
\r
9236 ssh2_pkt_send(ssh, s->pktout);
\r
9237 ssh->ncmode = FALSE;
\r
9239 crWaitUntilV(pktin);
\r
9240 if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
\r
9241 bombout(("Server refused to open channel"));
\r
9243 /* FIXME: error data comes back in FAILURE packet */
\r
9245 if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
\r
9246 bombout(("Server's channel confirmation cited wrong channel"));
\r
9249 ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
\r
9250 ssh->mainchan->halfopen = FALSE;
\r
9251 ssh->mainchan->type = CHAN_MAINSESSION;
\r
9252 ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
\r
9253 ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
\r
9254 add234(ssh->channels, ssh->mainchan);
\r
9255 update_specials_menu(ssh->frontend);
\r
9256 logevent("Opened main channel");
\r
9260 * Now we have a channel, make dispatch table entries for
\r
9261 * general channel-based messages.
\r
9263 ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] =
\r
9264 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] =
\r
9265 ssh2_msg_channel_data;
\r
9266 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = ssh2_msg_channel_eof;
\r
9267 ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = ssh2_msg_channel_close;
\r
9268 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] =
\r
9269 ssh2_msg_channel_open_confirmation;
\r
9270 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] =
\r
9271 ssh2_msg_channel_open_failure;
\r
9272 ssh->packet_dispatch[SSH2_MSG_CHANNEL_REQUEST] =
\r
9273 ssh2_msg_channel_request;
\r
9274 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] =
\r
9275 ssh2_msg_channel_open;
\r
9276 ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = ssh2_msg_channel_response;
\r
9277 ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = ssh2_msg_channel_response;
\r
9280 if (ssh->mainchan && conf_get_int(ssh->conf, CONF_ssh_simple)) {
\r
9282 * This message indicates to the server that we promise
\r
9283 * not to try to run any other channel in parallel with
\r
9284 * this one, so it's safe for it to advertise a very large
\r
9285 * window and leave the flow control to TCP.
\r
9287 s->pktout = ssh2_chanreq_init(ssh->mainchan,
\r
9288 "simple@putty.projects.tartarus.org",
\r
9290 ssh2_pkt_send(ssh, s->pktout);
\r
9294 * Enable port forwardings.
\r
9296 ssh_setup_portfwd(ssh, ssh->conf);
\r
9298 if (ssh->mainchan && !ssh->ncmode) {
\r
9300 * Send the CHANNEL_REQUESTS for the main session channel.
\r
9301 * Each one is handled by its own little asynchronous
\r
9305 /* Potentially enable X11 forwarding. */
\r
9306 if (conf_get_int(ssh->conf, CONF_x11_forward) &&
\r
9308 x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
\r
9309 conf_get_int(ssh->conf, CONF_x11_auth),
\r
9311 ssh2_setup_x11(ssh->mainchan, NULL, NULL);
\r
9313 /* Potentially enable agent forwarding. */
\r
9314 if (conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists())
\r
9315 ssh2_setup_agent(ssh->mainchan, NULL, NULL);
\r
9317 /* Now allocate a pty for the session. */
\r
9318 if (!conf_get_int(ssh->conf, CONF_nopty))
\r
9319 ssh2_setup_pty(ssh->mainchan, NULL, NULL);
\r
9321 /* Send environment variables. */
\r
9322 ssh2_setup_env(ssh->mainchan, NULL, NULL);
\r
9325 * Start a shell or a remote command. We may have to attempt
\r
9326 * this twice if the config data has provided a second choice
\r
9333 if (ssh->fallback_cmd) {
\r
9334 subsys = conf_get_int(ssh->conf, CONF_ssh_subsys2);
\r
9335 cmd = conf_get_str(ssh->conf, CONF_remote_cmd2);
\r
9337 subsys = conf_get_int(ssh->conf, CONF_ssh_subsys);
\r
9338 cmd = conf_get_str(ssh->conf, CONF_remote_cmd);
\r
9342 s->pktout = ssh2_chanreq_init(ssh->mainchan, "subsystem",
\r
9343 ssh2_response_authconn, NULL);
\r
9344 ssh2_pkt_addstring(s->pktout, cmd);
\r
9345 } else if (*cmd) {
\r
9346 s->pktout = ssh2_chanreq_init(ssh->mainchan, "exec",
\r
9347 ssh2_response_authconn, NULL);
\r
9348 ssh2_pkt_addstring(s->pktout, cmd);
\r
9350 s->pktout = ssh2_chanreq_init(ssh->mainchan, "shell",
\r
9351 ssh2_response_authconn, NULL);
\r
9353 ssh2_pkt_send(ssh, s->pktout);
\r
9355 crWaitUntilV(pktin);
\r
9357 if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
\r
9358 if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
\r
9359 bombout(("Unexpected response to shell/command request:"
\r
9360 " packet type %d", pktin->type));
\r
9364 * We failed to start the command. If this is the
\r
9365 * fallback command, we really are finished; if it's
\r
9366 * not, and if the fallback command exists, try falling
\r
9367 * back to it before complaining.
\r
9369 if (!ssh->fallback_cmd &&
\r
9370 *conf_get_str(ssh->conf, CONF_remote_cmd2)) {
\r
9371 logevent("Primary command failed; attempting fallback");
\r
9372 ssh->fallback_cmd = TRUE;
\r
9375 bombout(("Server refused to start a shell/command"));
\r
9378 logevent("Started a shell/command");
\r
9383 ssh->editing = ssh->echoing = TRUE;
\r
9386 ssh->state = SSH_STATE_SESSION;
\r
9387 if (ssh->size_needed)
\r
9388 ssh_size(ssh, ssh->term_width, ssh->term_height);
\r
9389 if (ssh->eof_needed)
\r
9390 ssh_special(ssh, TS_EOF);
\r
9396 ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
\r
9397 if (ssh->mainchan)
\r
9401 s->try_send = FALSE;
\r
9405 * _All_ the connection-layer packets we expect to
\r
9406 * receive are now handled by the dispatch table.
\r
9407 * Anything that reaches here must be bogus.
\r
9410 bombout(("Strange packet received: type %d", pktin->type));
\r
9412 } else if (ssh->mainchan) {
\r
9414 * We have spare data. Add it to the channel buffer.
\r
9416 ssh2_add_channel_data(ssh->mainchan, (char *)in, inlen);
\r
9417 s->try_send = TRUE;
\r
9419 if (s->try_send) {
\r
9421 struct ssh_channel *c;
\r
9423 * Try to send data on all channels if we can.
\r
9425 for (i = 0; NULL != (c = index234(ssh->channels, i)); i++)
\r
9426 ssh2_try_send_and_unthrottle(ssh, c);
\r
9434 * Handlers for SSH-2 messages that might arrive at any moment.
\r
9436 static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
\r
9438 /* log reason code in disconnect message */
\r
9440 int reason, msglen;
\r
9442 reason = ssh_pkt_getuint32(pktin);
\r
9443 ssh_pkt_getstring(pktin, &msg, &msglen);
\r
9445 if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
\r
9446 buf = dupprintf("Received disconnect message (%s)",
\r
9447 ssh2_disconnect_reasons[reason]);
\r
9449 buf = dupprintf("Received disconnect message (unknown"
\r
9450 " type %d)", reason);
\r
9454 buf = dupprintf("Disconnection message text: %.*s",
\r
9457 bombout(("Server sent disconnect message\ntype %d (%s):\n\"%.*s\"",
\r
9459 (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
\r
9460 ssh2_disconnect_reasons[reason] : "unknown",
\r
9465 static void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
\r
9467 /* log the debug message */
\r
9471 /* XXX maybe we should actually take notice of the return value */
\r
9472 ssh2_pkt_getbool(pktin);
\r
9473 ssh_pkt_getstring(pktin, &msg, &msglen);
\r
9475 logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
\r
9478 static void ssh2_msg_transport(Ssh ssh, struct Packet *pktin)
\r
9480 do_ssh2_transport(ssh, NULL, 0, pktin);
\r
9484 * Called if we receive a packet that isn't allowed by the protocol.
\r
9485 * This only applies to packets whose meaning PuTTY understands.
\r
9486 * Entirely unknown packets are handled below.
\r
9488 static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin)
\r
9490 char *buf = dupprintf("Server protocol violation: unexpected %s packet",
\r
9491 ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
\r
9493 ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
\r
9497 static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)
\r
9499 struct Packet *pktout;
\r
9500 pktout = ssh2_pkt_init(SSH2_MSG_UNIMPLEMENTED);
\r
9501 ssh2_pkt_adduint32(pktout, pktin->sequence);
\r
9503 * UNIMPLEMENTED messages MUST appear in the same order as the
\r
9504 * messages they respond to. Hence, never queue them.
\r
9506 ssh2_pkt_send_noqueue(ssh, pktout);
\r
9510 * Handle the top-level SSH-2 protocol.
\r
9512 static void ssh2_protocol_setup(Ssh ssh)
\r
9517 * Most messages cause SSH2_MSG_UNIMPLEMENTED.
\r
9519 for (i = 0; i < 256; i++)
\r
9520 ssh->packet_dispatch[i] = ssh2_msg_something_unimplemented;
\r
9523 * Initially, we only accept transport messages (and a few generic
\r
9524 * ones). do_ssh2_authconn will add more when it starts.
\r
9525 * Messages that are understood but not currently acceptable go to
\r
9526 * ssh2_msg_unexpected.
\r
9528 ssh->packet_dispatch[SSH2_MSG_UNIMPLEMENTED] = ssh2_msg_unexpected;
\r
9529 ssh->packet_dispatch[SSH2_MSG_SERVICE_REQUEST] = ssh2_msg_unexpected;
\r
9530 ssh->packet_dispatch[SSH2_MSG_SERVICE_ACCEPT] = ssh2_msg_unexpected;
\r
9531 ssh->packet_dispatch[SSH2_MSG_KEXINIT] = ssh2_msg_transport;
\r
9532 ssh->packet_dispatch[SSH2_MSG_NEWKEYS] = ssh2_msg_transport;
\r
9533 ssh->packet_dispatch[SSH2_MSG_KEXDH_INIT] = ssh2_msg_transport;
\r
9534 ssh->packet_dispatch[SSH2_MSG_KEXDH_REPLY] = ssh2_msg_transport;
\r
9535 /* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REQUEST] = ssh2_msg_transport; duplicate case value */
\r
9536 /* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_GROUP] = ssh2_msg_transport; duplicate case value */
\r
9537 ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_INIT] = ssh2_msg_transport;
\r
9538 ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REPLY] = ssh2_msg_transport;
\r
9539 ssh->packet_dispatch[SSH2_MSG_USERAUTH_REQUEST] = ssh2_msg_unexpected;
\r
9540 ssh->packet_dispatch[SSH2_MSG_USERAUTH_FAILURE] = ssh2_msg_unexpected;
\r
9541 ssh->packet_dispatch[SSH2_MSG_USERAUTH_SUCCESS] = ssh2_msg_unexpected;
\r
9542 ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = ssh2_msg_unexpected;
\r
9543 ssh->packet_dispatch[SSH2_MSG_USERAUTH_PK_OK] = ssh2_msg_unexpected;
\r
9544 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ] = ssh2_msg_unexpected; duplicate case value */
\r
9545 /* ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_REQUEST] = ssh2_msg_unexpected; duplicate case value */
\r
9546 ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_RESPONSE] = ssh2_msg_unexpected;
\r
9547 ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] = ssh2_msg_unexpected;
\r
9548 ssh->packet_dispatch[SSH2_MSG_REQUEST_SUCCESS] = ssh2_msg_unexpected;
\r
9549 ssh->packet_dispatch[SSH2_MSG_REQUEST_FAILURE] = ssh2_msg_unexpected;
\r
9550 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] = ssh2_msg_unexpected;
\r
9551 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] = ssh2_msg_unexpected;
\r
9552 ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] = ssh2_msg_unexpected;
\r
9553 ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] = ssh2_msg_unexpected;
\r
9554 ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] = ssh2_msg_unexpected;
\r
9555 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] = ssh2_msg_unexpected;
\r
9556 ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = ssh2_msg_unexpected;
\r
9557 ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = ssh2_msg_unexpected;
\r
9558 ssh->packet_dispatch[SSH2_MSG_CHANNEL_REQUEST] = ssh2_msg_unexpected;
\r
9559 ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = ssh2_msg_unexpected;
\r
9560 ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = ssh2_msg_unexpected;
\r
9563 * These messages have a special handler from the start.
\r
9565 ssh->packet_dispatch[SSH2_MSG_DISCONNECT] = ssh2_msg_disconnect;
\r
9566 ssh->packet_dispatch[SSH2_MSG_IGNORE] = ssh_msg_ignore; /* shared with SSH-1 */
\r
9567 ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
\r
9570 static void ssh2_timer(void *ctx, unsigned long now)
\r
9572 Ssh ssh = (Ssh)ctx;
\r
9574 if (ssh->state == SSH_STATE_CLOSED)
\r
9577 if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 &&
\r
9578 now == ssh->next_rekey) {
\r
9579 do_ssh2_transport(ssh, "timeout", -1, NULL);
\r
9583 static void ssh2_protocol(Ssh ssh, void *vin, int inlen,
\r
9584 struct Packet *pktin)
\r
9586 unsigned char *in = (unsigned char *)vin;
\r
9587 if (ssh->state == SSH_STATE_CLOSED)
\r
9591 ssh->incoming_data_size += pktin->encrypted_len;
\r
9592 if (!ssh->kex_in_progress &&
\r
9593 ssh->max_data_size != 0 &&
\r
9594 ssh->incoming_data_size > ssh->max_data_size)
\r
9595 do_ssh2_transport(ssh, "too much data received", -1, NULL);
\r
9599 ssh->packet_dispatch[pktin->type](ssh, pktin);
\r
9600 else if (!ssh->protocol_initial_phase_done)
\r
9601 do_ssh2_transport(ssh, in, inlen, pktin);
\r
9603 do_ssh2_authconn(ssh, in, inlen, pktin);
\r
9606 static void ssh_cache_conf_values(Ssh ssh)
\r
9608 ssh->logomitdata = conf_get_int(ssh->conf, CONF_logomitdata);
\r
9612 * Called to set up the connection.
\r
9614 * Returns an error message, or NULL on success.
\r
9616 static const char *ssh_init(void *frontend_handle, void **backend_handle,
\r
9617 Conf *conf, char *host, int port, char **realhost,
\r
9618 int nodelay, int keepalive)
\r
9623 ssh = snew(struct ssh_tag);
\r
9624 ssh->conf = conf_copy(conf);
\r
9625 ssh_cache_conf_values(ssh);
\r
9626 ssh->version = 0; /* when not ready yet */
\r
9628 ssh->cipher = NULL;
\r
9629 ssh->v1_cipher_ctx = NULL;
\r
9630 ssh->crcda_ctx = NULL;
\r
9631 ssh->cscipher = NULL;
\r
9632 ssh->cs_cipher_ctx = NULL;
\r
9633 ssh->sccipher = NULL;
\r
9634 ssh->sc_cipher_ctx = NULL;
\r
9635 ssh->csmac = NULL;
\r
9636 ssh->cs_mac_ctx = NULL;
\r
9637 ssh->scmac = NULL;
\r
9638 ssh->sc_mac_ctx = NULL;
\r
9639 ssh->cscomp = NULL;
\r
9640 ssh->cs_comp_ctx = NULL;
\r
9641 ssh->sccomp = NULL;
\r
9642 ssh->sc_comp_ctx = NULL;
\r
9644 ssh->kex_ctx = NULL;
\r
9645 ssh->hostkey = NULL;
\r
9646 ssh->exitcode = -1;
\r
9647 ssh->close_expected = FALSE;
\r
9648 ssh->clean_exit = FALSE;
\r
9649 ssh->state = SSH_STATE_PREPACKET;
\r
9650 ssh->size_needed = FALSE;
\r
9651 ssh->eof_needed = FALSE;
\r
9652 ssh->ldisc = NULL;
\r
9653 ssh->logctx = NULL;
\r
9654 ssh->deferred_send_data = NULL;
\r
9655 ssh->deferred_len = 0;
\r
9656 ssh->deferred_size = 0;
\r
9657 ssh->fallback_cmd = 0;
\r
9658 ssh->pkt_kctx = SSH2_PKTCTX_NOKEX;
\r
9659 ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
\r
9660 ssh->x11disp = NULL;
\r
9661 ssh->v1_compressing = FALSE;
\r
9662 ssh->v2_outgoing_sequence = 0;
\r
9663 ssh->ssh1_rdpkt_crstate = 0;
\r
9664 ssh->ssh2_rdpkt_crstate = 0;
\r
9665 ssh->ssh_gotdata_crstate = 0;
\r
9666 ssh->do_ssh1_connection_crstate = 0;
\r
9667 ssh->do_ssh_init_state = NULL;
\r
9668 ssh->do_ssh1_login_state = NULL;
\r
9669 ssh->do_ssh2_transport_state = NULL;
\r
9670 ssh->do_ssh2_authconn_state = NULL;
\r
9673 ssh->mainchan = NULL;
\r
9674 ssh->throttled_all = 0;
\r
9675 ssh->v1_stdout_throttling = 0;
\r
9676 ssh->queue = NULL;
\r
9677 ssh->queuelen = ssh->queuesize = 0;
\r
9678 ssh->queueing = FALSE;
\r
9679 ssh->qhead = ssh->qtail = NULL;
\r
9680 ssh->deferred_rekey_reason = NULL;
\r
9681 bufchain_init(&ssh->queued_incoming_data);
\r
9682 ssh->frozen = FALSE;
\r
9683 ssh->username = NULL;
\r
9684 ssh->sent_console_eof = FALSE;
\r
9685 ssh->got_pty = FALSE;
\r
9687 *backend_handle = ssh;
\r
9689 #ifdef MSCRYPTOAPI
\r
9690 if (crypto_startup() == 0)
\r
9691 return "Microsoft high encryption pack not installed!";
\r
9694 ssh->frontend = frontend_handle;
\r
9695 ssh->term_width = conf_get_int(ssh->conf, CONF_width);
\r
9696 ssh->term_height = conf_get_int(ssh->conf, CONF_height);
\r
9698 ssh->channels = NULL;
\r
9699 ssh->rportfwds = NULL;
\r
9700 ssh->portfwds = NULL;
\r
9705 ssh->conn_throttle_count = 0;
\r
9706 ssh->overall_bufsize = 0;
\r
9707 ssh->fallback_cmd = 0;
\r
9709 ssh->protocol = NULL;
\r
9711 ssh->protocol_initial_phase_done = FALSE;
\r
9713 ssh->pinger = NULL;
\r
9715 ssh->incoming_data_size = ssh->outgoing_data_size =
\r
9716 ssh->deferred_data_size = 0L;
\r
9717 ssh->max_data_size = parse_blocksize(conf_get_str(ssh->conf,
\r
9718 CONF_ssh_rekey_data));
\r
9719 ssh->kex_in_progress = FALSE;
\r
9722 ssh->gsslibs = NULL;
\r
9725 p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
\r
9734 static void ssh_free(void *handle)
\r
9736 Ssh ssh = (Ssh) handle;
\r
9737 struct ssh_channel *c;
\r
9738 struct ssh_rportfwd *pf;
\r
9740 if (ssh->v1_cipher_ctx)
\r
9741 ssh->cipher->free_context(ssh->v1_cipher_ctx);
\r
9742 if (ssh->cs_cipher_ctx)
\r
9743 ssh->cscipher->free_context(ssh->cs_cipher_ctx);
\r
9744 if (ssh->sc_cipher_ctx)
\r
9745 ssh->sccipher->free_context(ssh->sc_cipher_ctx);
\r
9746 if (ssh->cs_mac_ctx)
\r
9747 ssh->csmac->free_context(ssh->cs_mac_ctx);
\r
9748 if (ssh->sc_mac_ctx)
\r
9749 ssh->scmac->free_context(ssh->sc_mac_ctx);
\r
9750 if (ssh->cs_comp_ctx) {
\r
9752 ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
\r
9754 zlib_compress_cleanup(ssh->cs_comp_ctx);
\r
9756 if (ssh->sc_comp_ctx) {
\r
9758 ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);
\r
9760 zlib_decompress_cleanup(ssh->sc_comp_ctx);
\r
9763 dh_cleanup(ssh->kex_ctx);
\r
9764 sfree(ssh->savedhost);
\r
9766 while (ssh->queuelen-- > 0)
\r
9767 ssh_free_packet(ssh->queue[ssh->queuelen]);
\r
9768 sfree(ssh->queue);
\r
9770 while (ssh->qhead) {
\r
9771 struct queued_handler *qh = ssh->qhead;
\r
9772 ssh->qhead = qh->next;
\r
9775 ssh->qhead = ssh->qtail = NULL;
\r
9777 if (ssh->channels) {
\r
9778 while ((c = delpos234(ssh->channels, 0)) != NULL) {
\r
9779 switch (c->type) {
\r
9781 if (c->u.x11.s != NULL)
\r
9782 x11_close(c->u.x11.s);
\r
9784 case CHAN_SOCKDATA:
\r
9785 case CHAN_SOCKDATA_DORMANT:
\r
9786 if (c->u.pfd.s != NULL)
\r
9787 pfd_close(c->u.pfd.s);
\r
9790 if (ssh->version == 2) {
\r
9791 struct outstanding_channel_request *ocr, *nocr;
\r
9792 ocr = c->v.v2.chanreq_head;
\r
9794 ocr->handler(c, NULL, ocr->ctx);
\r
9799 bufchain_clear(&c->v.v2.outbuffer);
\r
9803 freetree234(ssh->channels);
\r
9804 ssh->channels = NULL;
\r
9807 if (ssh->rportfwds) {
\r
9808 while ((pf = delpos234(ssh->rportfwds, 0)) != NULL)
\r
9809 free_rportfwd(pf);
\r
9810 freetree234(ssh->rportfwds);
\r
9811 ssh->rportfwds = NULL;
\r
9813 sfree(ssh->deferred_send_data);
\r
9815 x11_free_display(ssh->x11disp);
\r
9816 sfree(ssh->do_ssh_init_state);
\r
9817 sfree(ssh->do_ssh1_login_state);
\r
9818 sfree(ssh->do_ssh2_transport_state);
\r
9819 sfree(ssh->do_ssh2_authconn_state);
\r
9822 sfree(ssh->fullhostname);
\r
9823 if (ssh->crcda_ctx) {
\r
9824 crcda_free_context(ssh->crcda_ctx);
\r
9825 ssh->crcda_ctx = NULL;
\r
9828 ssh_do_close(ssh, TRUE);
\r
9829 expire_timer_context(ssh);
\r
9831 pinger_free(ssh->pinger);
\r
9832 bufchain_clear(&ssh->queued_incoming_data);
\r
9833 sfree(ssh->username);
\r
9834 conf_free(ssh->conf);
\r
9837 ssh_gss_cleanup(ssh->gsslibs);
\r
9845 * Reconfigure the SSH backend.
\r
9847 static void ssh_reconfig(void *handle, Conf *conf)
\r
9849 Ssh ssh = (Ssh) handle;
\r
9850 char *rekeying = NULL, rekey_mandatory = FALSE;
\r
9851 unsigned long old_max_data_size;
\r
9852 int i, rekey_time;
\r
9854 pinger_reconfig(ssh->pinger, ssh->conf, conf);
\r
9855 if (ssh->portfwds)
\r
9856 ssh_setup_portfwd(ssh, conf);
\r
9858 rekey_time = conf_get_int(conf, CONF_ssh_rekey_time);
\r
9859 if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time &&
\r
9860 rekey_time != 0) {
\r
9861 unsigned long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
\r
9862 unsigned long now = GETTICKCOUNT();
\r
9864 if (now - ssh->last_rekey > rekey_time*60*TICKSPERSEC) {
\r
9865 rekeying = "timeout shortened";
\r
9867 ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
\r
9871 old_max_data_size = ssh->max_data_size;
\r
9872 ssh->max_data_size = parse_blocksize(conf_get_str(ssh->conf,
\r
9873 CONF_ssh_rekey_data));
\r
9874 if (old_max_data_size != ssh->max_data_size &&
\r
9875 ssh->max_data_size != 0) {
\r
9876 if (ssh->outgoing_data_size > ssh->max_data_size ||
\r
9877 ssh->incoming_data_size > ssh->max_data_size)
\r
9878 rekeying = "data limit lowered";
\r
9881 if (conf_get_int(ssh->conf, CONF_compression) !=
\r
9882 conf_get_int(conf, CONF_compression)) {
\r
9883 rekeying = "compression setting changed";
\r
9884 rekey_mandatory = TRUE;
\r
9887 for (i = 0; i < CIPHER_MAX; i++)
\r
9888 if (conf_get_int_int(ssh->conf, CONF_ssh_cipherlist, i) !=
\r
9889 conf_get_int_int(conf, CONF_ssh_cipherlist, i)) {
\r
9890 rekeying = "cipher settings changed";
\r
9891 rekey_mandatory = TRUE;
\r
9893 if (conf_get_int(ssh->conf, CONF_ssh2_des_cbc) !=
\r
9894 conf_get_int(conf, CONF_ssh2_des_cbc)) {
\r
9895 rekeying = "cipher settings changed";
\r
9896 rekey_mandatory = TRUE;
\r
9899 conf_free(ssh->conf);
\r
9900 ssh->conf = conf_copy(conf);
\r
9901 ssh_cache_conf_values(ssh);
\r
9904 if (!ssh->kex_in_progress) {
\r
9905 do_ssh2_transport(ssh, rekeying, -1, NULL);
\r
9906 } else if (rekey_mandatory) {
\r
9907 ssh->deferred_rekey_reason = rekeying;
\r
9913 * Called to send data down the SSH connection.
\r
9915 static int ssh_send(void *handle, char *buf, int len)
\r
9917 Ssh ssh = (Ssh) handle;
\r
9919 if (ssh == NULL || ssh->s == NULL || ssh->protocol == NULL)
\r
9922 ssh->protocol(ssh, (unsigned char *)buf, len, 0);
\r
9924 return ssh_sendbuffer(ssh);
\r
9928 * Called to query the current amount of buffered stdin data.
\r
9930 static int ssh_sendbuffer(void *handle)
\r
9932 Ssh ssh = (Ssh) handle;
\r
9933 int override_value;
\r
9935 if (ssh == NULL || ssh->s == NULL || ssh->protocol == NULL)
\r
9939 * If the SSH socket itself has backed up, add the total backup
\r
9940 * size on that to any individual buffer on the stdin channel.
\r
9942 override_value = 0;
\r
9943 if (ssh->throttled_all)
\r
9944 override_value = ssh->overall_bufsize;
\r
9946 if (ssh->version == 1) {
\r
9947 return override_value;
\r
9948 } else if (ssh->version == 2) {
\r
9949 if (!ssh->mainchan)
\r
9950 return override_value;
\r
9952 return (override_value +
\r
9953 bufchain_size(&ssh->mainchan->v.v2.outbuffer));
\r
9960 * Called to set the size of the window from SSH's POV.
\r
9962 static void ssh_size(void *handle, int width, int height)
\r
9964 Ssh ssh = (Ssh) handle;
\r
9965 struct Packet *pktout;
\r
9967 ssh->term_width = width;
\r
9968 ssh->term_height = height;
\r
9970 switch (ssh->state) {
\r
9971 case SSH_STATE_BEFORE_SIZE:
\r
9972 case SSH_STATE_PREPACKET:
\r
9973 case SSH_STATE_CLOSED:
\r
9974 break; /* do nothing */
\r
9975 case SSH_STATE_INTERMED:
\r
9976 ssh->size_needed = TRUE; /* buffer for later */
\r
9978 case SSH_STATE_SESSION:
\r
9979 if (!conf_get_int(ssh->conf, CONF_nopty)) {
\r
9980 if (ssh->version == 1) {
\r
9981 send_packet(ssh, SSH1_CMSG_WINDOW_SIZE,
\r
9982 PKT_INT, ssh->term_height,
\r
9983 PKT_INT, ssh->term_width,
\r
9984 PKT_INT, 0, PKT_INT, 0, PKT_END);
\r
9985 } else if (ssh->mainchan) {
\r
9986 pktout = ssh2_chanreq_init(ssh->mainchan, "window-change",
\r
9988 ssh2_pkt_adduint32(pktout, ssh->term_width);
\r
9989 ssh2_pkt_adduint32(pktout, ssh->term_height);
\r
9990 ssh2_pkt_adduint32(pktout, 0);
\r
9991 ssh2_pkt_adduint32(pktout, 0);
\r
9992 ssh2_pkt_send(ssh, pktout);
\r
10000 * Return a list of the special codes that make sense in this
\r
10003 static const struct telnet_special *ssh_get_specials(void *handle)
\r
10005 static const struct telnet_special ssh1_ignore_special[] = {
\r
10006 {"IGNORE message", TS_NOP}
\r
10008 static const struct telnet_special ssh2_ignore_special[] = {
\r
10009 {"IGNORE message", TS_NOP},
\r
10011 static const struct telnet_special ssh2_rekey_special[] = {
\r
10012 {"Repeat key exchange", TS_REKEY},
\r
10014 static const struct telnet_special ssh2_session_specials[] = {
\r
10016 {"Break", TS_BRK},
\r
10017 /* These are the signal names defined by RFC 4254.
\r
10018 * They include all the ISO C signals, but are a subset of the POSIX
\r
10019 * required signals. */
\r
10020 {"SIGINT (Interrupt)", TS_SIGINT},
\r
10021 {"SIGTERM (Terminate)", TS_SIGTERM},
\r
10022 {"SIGKILL (Kill)", TS_SIGKILL},
\r
10023 {"SIGQUIT (Quit)", TS_SIGQUIT},
\r
10024 {"SIGHUP (Hangup)", TS_SIGHUP},
\r
10025 {"More signals", TS_SUBMENU},
\r
10026 {"SIGABRT", TS_SIGABRT}, {"SIGALRM", TS_SIGALRM},
\r
10027 {"SIGFPE", TS_SIGFPE}, {"SIGILL", TS_SIGILL},
\r
10028 {"SIGPIPE", TS_SIGPIPE}, {"SIGSEGV", TS_SIGSEGV},
\r
10029 {"SIGUSR1", TS_SIGUSR1}, {"SIGUSR2", TS_SIGUSR2},
\r
10030 {NULL, TS_EXITMENU}
\r
10032 static const struct telnet_special specials_end[] = {
\r
10033 {NULL, TS_EXITMENU}
\r
10035 /* XXX review this length for any changes: */
\r
10036 static struct telnet_special ssh_specials[lenof(ssh2_ignore_special) +
\r
10037 lenof(ssh2_rekey_special) +
\r
10038 lenof(ssh2_session_specials) +
\r
10039 lenof(specials_end)];
\r
10040 Ssh ssh = (Ssh) handle;
\r
10042 #define ADD_SPECIALS(name) \
\r
10044 assert((i + lenof(name)) <= lenof(ssh_specials)); \
\r
10045 memcpy(&ssh_specials[i], name, sizeof name); \
\r
10046 i += lenof(name); \
\r
10049 if (ssh->version == 1) {
\r
10050 /* Don't bother offering IGNORE if we've decided the remote
\r
10051 * won't cope with it, since we wouldn't bother sending it if
\r
10052 * asked anyway. */
\r
10053 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE))
\r
10054 ADD_SPECIALS(ssh1_ignore_special);
\r
10055 } else if (ssh->version == 2) {
\r
10056 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE))
\r
10057 ADD_SPECIALS(ssh2_ignore_special);
\r
10058 if (!(ssh->remote_bugs & BUG_SSH2_REKEY))
\r
10059 ADD_SPECIALS(ssh2_rekey_special);
\r
10060 if (ssh->mainchan)
\r
10061 ADD_SPECIALS(ssh2_session_specials);
\r
10062 } /* else we're not ready yet */
\r
10065 ADD_SPECIALS(specials_end);
\r
10066 return ssh_specials;
\r
10070 #undef ADD_SPECIALS
\r
10074 * Send special codes. TS_EOF is useful for `plink', so you
\r
10075 * can send an EOF and collect resulting output (e.g. `plink
\r
10076 * hostname sort').
\r
10078 static void ssh_special(void *handle, Telnet_Special code)
\r
10080 Ssh ssh = (Ssh) handle;
\r
10081 struct Packet *pktout;
\r
10083 if (code == TS_EOF) {
\r
10084 if (ssh->state != SSH_STATE_SESSION) {
\r
10086 * Buffer the EOF in case we are pre-SESSION, so we can
\r
10087 * send it as soon as we reach SESSION.
\r
10089 if (code == TS_EOF)
\r
10090 ssh->eof_needed = TRUE;
\r
10093 if (ssh->version == 1) {
\r
10094 send_packet(ssh, SSH1_CMSG_EOF, PKT_END);
\r
10095 } else if (ssh->mainchan) {
\r
10096 sshfwd_write_eof(ssh->mainchan);
\r
10097 ssh->send_ok = 0; /* now stop trying to read from stdin */
\r
10099 logevent("Sent EOF message");
\r
10100 } else if (code == TS_PING || code == TS_NOP) {
\r
10101 if (ssh->state == SSH_STATE_CLOSED
\r
10102 || ssh->state == SSH_STATE_PREPACKET) return;
\r
10103 if (ssh->version == 1) {
\r
10104 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE))
\r
10105 send_packet(ssh, SSH1_MSG_IGNORE, PKT_STR, "", PKT_END);
\r
10107 if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {
\r
10108 pktout = ssh2_pkt_init(SSH2_MSG_IGNORE);
\r
10109 ssh2_pkt_addstring_start(pktout);
\r
10110 ssh2_pkt_send_noqueue(ssh, pktout);
\r
10113 } else if (code == TS_REKEY) {
\r
10114 if (!ssh->kex_in_progress && ssh->version == 2) {
\r
10115 do_ssh2_transport(ssh, "at user request", -1, NULL);
\r
10117 } else if (code == TS_BRK) {
\r
10118 if (ssh->state == SSH_STATE_CLOSED
\r
10119 || ssh->state == SSH_STATE_PREPACKET) return;
\r
10120 if (ssh->version == 1) {
\r
10121 logevent("Unable to send BREAK signal in SSH-1");
\r
10122 } else if (ssh->mainchan) {
\r
10123 pktout = ssh2_chanreq_init(ssh->mainchan, "break", NULL, NULL);
\r
10124 ssh2_pkt_adduint32(pktout, 0); /* default break length */
\r
10125 ssh2_pkt_send(ssh, pktout);
\r
10128 /* Is is a POSIX signal? */
\r
10129 char *signame = NULL;
\r
10130 if (code == TS_SIGABRT) signame = "ABRT";
\r
10131 if (code == TS_SIGALRM) signame = "ALRM";
\r
10132 if (code == TS_SIGFPE) signame = "FPE";
\r
10133 if (code == TS_SIGHUP) signame = "HUP";
\r
10134 if (code == TS_SIGILL) signame = "ILL";
\r
10135 if (code == TS_SIGINT) signame = "INT";
\r
10136 if (code == TS_SIGKILL) signame = "KILL";
\r
10137 if (code == TS_SIGPIPE) signame = "PIPE";
\r
10138 if (code == TS_SIGQUIT) signame = "QUIT";
\r
10139 if (code == TS_SIGSEGV) signame = "SEGV";
\r
10140 if (code == TS_SIGTERM) signame = "TERM";
\r
10141 if (code == TS_SIGUSR1) signame = "USR1";
\r
10142 if (code == TS_SIGUSR2) signame = "USR2";
\r
10143 /* The SSH-2 protocol does in principle support arbitrary named
\r
10144 * signals, including signame@domain, but we don't support those. */
\r
10146 /* It's a signal. */
\r
10147 if (ssh->version == 2 && ssh->mainchan) {
\r
10148 pktout = ssh2_chanreq_init(ssh->mainchan, "signal", NULL, NULL);
\r
10149 ssh2_pkt_addstring(pktout, signame);
\r
10150 ssh2_pkt_send(ssh, pktout);
\r
10151 logeventf(ssh, "Sent signal SIG%s", signame);
\r
10154 /* Never heard of it. Do nothing */
\r
10159 void *new_sock_channel(void *handle, Socket s)
\r
10161 Ssh ssh = (Ssh) handle;
\r
10162 struct ssh_channel *c;
\r
10163 c = snew(struct ssh_channel);
\r
10166 ssh2_channel_init(c);
\r
10167 c->halfopen = TRUE;
\r
10168 c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */
\r
10170 add234(ssh->channels, c);
\r
10175 * This is called when stdout/stderr (the entity to which
\r
10176 * from_backend sends data) manages to clear some backlog.
\r
10178 static void ssh_unthrottle(void *handle, int bufsize)
\r
10180 Ssh ssh = (Ssh) handle;
\r
10183 if (ssh->version == 1) {
\r
10184 if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
\r
10185 ssh->v1_stdout_throttling = 0;
\r
10186 ssh_throttle_conn(ssh, -1);
\r
10189 if (ssh->mainchan) {
\r
10190 ssh2_set_window(ssh->mainchan,
\r
10191 bufsize < ssh->mainchan->v.v2.locmaxwin ?
\r
10192 ssh->mainchan->v.v2.locmaxwin - bufsize : 0);
\r
10193 if (conf_get_int(ssh->conf, CONF_ssh_simple))
\r
10196 buflimit = ssh->mainchan->v.v2.locmaxwin;
\r
10197 if (ssh->mainchan->throttling_conn && bufsize <= buflimit) {
\r
10198 ssh->mainchan->throttling_conn = 0;
\r
10199 ssh_throttle_conn(ssh, -1);
\r
10205 * Now process any SSH connection data that was stashed in our
\r
10206 * queue while we were frozen.
\r
10208 ssh_process_queued_incoming_data(ssh);
\r
10211 void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
\r
10213 struct ssh_channel *c = (struct ssh_channel *)channel;
\r
10214 Ssh ssh = c->ssh;
\r
10215 struct Packet *pktout;
\r
10217 logeventf(ssh, "Opening connection to %s:%d for %s", hostname, port, org);
\r
10219 if (ssh->version == 1) {
\r
10220 send_packet(ssh, SSH1_MSG_PORT_OPEN,
\r
10221 PKT_INT, c->localid,
\r
10222 PKT_STR, hostname,
\r
10224 /* PKT_STR, <org:orgport>, */
\r
10227 pktout = ssh2_chanopen_init(c, "direct-tcpip");
\r
10228 ssh2_pkt_addstring(pktout, hostname);
\r
10229 ssh2_pkt_adduint32(pktout, port);
\r
10231 * We make up values for the originator data; partly it's
\r
10232 * too much hassle to keep track, and partly I'm not
\r
10233 * convinced the server should be told details like that
\r
10234 * about my local network configuration.
\r
10235 * The "originator IP address" is syntactically a numeric
\r
10236 * IP address, and some servers (e.g., Tectia) get upset
\r
10237 * if it doesn't match this syntax.
\r
10239 ssh2_pkt_addstring(pktout, "0.0.0.0");
\r
10240 ssh2_pkt_adduint32(pktout, 0);
\r
10241 ssh2_pkt_send(ssh, pktout);
\r
10245 static int ssh_connected(void *handle)
\r
10247 Ssh ssh = (Ssh) handle;
\r
10248 return ssh->s != NULL;
\r
10251 static int ssh_sendok(void *handle)
\r
10253 Ssh ssh = (Ssh) handle;
\r
10254 return ssh->send_ok;
\r
10257 static int ssh_ldisc(void *handle, int option)
\r
10259 Ssh ssh = (Ssh) handle;
\r
10260 if (option == LD_ECHO)
\r
10261 return ssh->echoing;
\r
10262 if (option == LD_EDIT)
\r
10263 return ssh->editing;
\r
10267 static void ssh_provide_ldisc(void *handle, void *ldisc)
\r
10269 Ssh ssh = (Ssh) handle;
\r
10270 ssh->ldisc = ldisc;
\r
10273 static void ssh_provide_logctx(void *handle, void *logctx)
\r
10275 Ssh ssh = (Ssh) handle;
\r
10276 ssh->logctx = logctx;
\r
10279 static int ssh_return_exitcode(void *handle)
\r
10281 Ssh ssh = (Ssh) handle;
\r
10282 if (ssh->s != NULL)
\r
10285 return (ssh->exitcode >= 0 ? ssh->exitcode : INT_MAX);
\r
10289 * cfg_info for SSH is the currently running version of the
\r
10290 * protocol. (1 for 1; 2 for 2; 0 for not-decided-yet.)
\r
10292 static int ssh_cfg_info(void *handle)
\r
10294 Ssh ssh = (Ssh) handle;
\r
10295 return ssh->version;
\r
10299 * Gross hack: pscp will try to start SFTP but fall back to scp1 if
\r
10300 * that fails. This variable is the means by which scp.c can reach
\r
10301 * into the SSH code and find out which one it got.
\r
10303 extern int ssh_fallback_cmd(void *handle)
\r
10305 Ssh ssh = (Ssh) handle;
\r
10306 return ssh->fallback_cmd;
\r
10309 Backend ssh_backend = {
\r
10317 ssh_get_specials,
\r
10319 ssh_return_exitcode,
\r
10322 ssh_provide_ldisc,
\r
10323 ssh_provide_logctx,
\r