1 | /* |
---|
2 | |
---|
3 | packet.c |
---|
4 | |
---|
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> |
---|
6 | |
---|
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
---|
8 | All rights reserved |
---|
9 | |
---|
10 | Created: Sat Mar 18 02:40:40 1995 ylo |
---|
11 | |
---|
12 | This file contains code implementing the packet protocol and communication |
---|
13 | with the other side. This same code is used both on client and server side. |
---|
14 | |
---|
15 | */ |
---|
16 | |
---|
17 | /* |
---|
18 | * $Id: packet.c,v 1.3 1999-03-08 18:20:07 danw Exp $ |
---|
19 | * $Log: not supported by cvs2svn $ |
---|
20 | * Revision 1.2 1998/06/17 17:29:40 ghudson |
---|
21 | * Add code from a CORE SDI advisory to prevent connection hijacking. |
---|
22 | * |
---|
23 | * Revision 1.1.1.3 1999/03/08 17:43:13 danw |
---|
24 | * Import of ssh 1.2.26 |
---|
25 | * |
---|
26 | * Revision 1.1.1.2 1998/05/13 19:11:18 danw |
---|
27 | * Import of ssh 1.2.23 |
---|
28 | * |
---|
29 | * Revision 1.11 1998/06/11 00:08:44 kivinen |
---|
30 | * Crc fixing detection code. |
---|
31 | * |
---|
32 | * Revision 1.10 1998/05/23 20:22:50 kivinen |
---|
33 | * Changed () -> (void). |
---|
34 | * |
---|
35 | * Revision 1.9 1998/04/30 01:54:30 kivinen |
---|
36 | * Fixed SSH_MSG_IGNORE handling. Now it will skip the string |
---|
37 | * argument also. |
---|
38 | * |
---|
39 | * Revision 1.8 1998/03/27 16:59:02 kivinen |
---|
40 | * Added ENABLE_TCP_NODELAY support. |
---|
41 | * |
---|
42 | * Revision 1.7 1997/04/05 17:29:21 ylo |
---|
43 | * Added packet_get_len (returns the remaining length of incoming |
---|
44 | * packet). |
---|
45 | * |
---|
46 | * Revision 1.6 1997/03/19 19:26:58 kivinen |
---|
47 | * Added packet_get_all function. Added checks to |
---|
48 | * packet_read_poll that previous packet buffer must be empty |
---|
49 | * before starting to put new packet in. |
---|
50 | * |
---|
51 | * Revision 1.5 1996/11/24 08:23:46 kivinen |
---|
52 | * Changed all code that checked EAGAIN to check EWOULDBLOCK too. |
---|
53 | * Added support for debug messages that are printed always (if |
---|
54 | * the first character of debug message is * it is printed with |
---|
55 | * error function instead of debug). |
---|
56 | * |
---|
57 | * Revision 1.4 1996/10/07 11:53:24 ttsalo |
---|
58 | * From "Charles M. Hannum" <mycroft@gnu.ai.mit.edu>: |
---|
59 | * Made the use of TCP_NODELAY conditional. |
---|
60 | * |
---|
61 | * Revision 1.3 1996/09/22 21:58:38 ylo |
---|
62 | * Added code to clear keepalives properly when requested. |
---|
63 | * |
---|
64 | * Revision 1.2 1996/05/28 16:42:13 ylo |
---|
65 | * Workaround for Solaris select() bug while reading version id. |
---|
66 | * |
---|
67 | * Revision 1.1.1.1 1996/02/18 21:38:12 ylo |
---|
68 | * Imported ssh-1.2.13. |
---|
69 | * |
---|
70 | * Revision 1.6 1995/09/24 23:59:12 ylo |
---|
71 | * Added packet_get_protocol_flags. |
---|
72 | * |
---|
73 | * Revision 1.5 1995/09/09 21:26:43 ylo |
---|
74 | * /m/shadows/u2/users/ylo/ssh/README |
---|
75 | * |
---|
76 | * Revision 1.4 1995/07/27 03:59:37 ylo |
---|
77 | * Fixed a bug in new arcfour keying. |
---|
78 | * |
---|
79 | * Revision 1.3 1995/07/27 02:17:11 ylo |
---|
80 | * Changed keying for arcfour to avoid using the same key for both |
---|
81 | * directions. |
---|
82 | * |
---|
83 | * Revision 1.2 1995/07/13 01:27:33 ylo |
---|
84 | * Removed "Last modified" header. |
---|
85 | * Added cvs log. |
---|
86 | * |
---|
87 | * $Endlog$ |
---|
88 | */ |
---|
89 | |
---|
90 | #include "includes.h" |
---|
91 | #include "xmalloc.h" |
---|
92 | #include "randoms.h" |
---|
93 | #include "buffer.h" |
---|
94 | #include "packet.h" |
---|
95 | #include "bufaux.h" |
---|
96 | #include "ssh.h" |
---|
97 | #include "crc32.h" |
---|
98 | #include "cipher.h" |
---|
99 | #include "getput.h" |
---|
100 | #include "compress.h" |
---|
101 | #include "deattack.h" |
---|
102 | |
---|
103 | /* This variable contains the file descriptors used for communicating with |
---|
104 | the other side. connection_in is used for reading; connection_out |
---|
105 | for writing. These can be the same descriptor, in which case it is |
---|
106 | assumed to be a socket. */ |
---|
107 | static int connection_in = -1; |
---|
108 | static int connection_out = -1; |
---|
109 | |
---|
110 | /* Cipher type. This value is only used to determine whether to pad the |
---|
111 | packets with zeroes or random data. */ |
---|
112 | static int cipher_type = SSH_CIPHER_NONE; |
---|
113 | |
---|
114 | /* Protocol flags for the remote side. */ |
---|
115 | static unsigned int remote_protocol_flags = 0; |
---|
116 | |
---|
117 | /* Encryption context for receiving data. This is only used for decryption. */ |
---|
118 | static CipherContext receive_context; |
---|
119 | /* Encryption coontext for sending data. This is only used for encryption. */ |
---|
120 | static CipherContext send_context; |
---|
121 | |
---|
122 | /* Buffer for raw input data from the socket. */ |
---|
123 | static Buffer input; |
---|
124 | |
---|
125 | /* Buffer for raw output data going to the socket. */ |
---|
126 | static Buffer output; |
---|
127 | |
---|
128 | /* Buffer for the partial outgoing packet being constructed. */ |
---|
129 | static Buffer outgoing_packet; |
---|
130 | |
---|
131 | /* Buffer for the incoming packet currently being processed. */ |
---|
132 | static Buffer incoming_packet; |
---|
133 | |
---|
134 | /* Scratch buffer for packet compression/decompression. */ |
---|
135 | static Buffer compression_buffer; |
---|
136 | |
---|
137 | /* Flag indicating whether packet compression/decompression is enabled. */ |
---|
138 | static int packet_compression = 0; |
---|
139 | |
---|
140 | /* Pointer to the random number generator state. */ |
---|
141 | static RandomState *random_state; |
---|
142 | |
---|
143 | /* Flag indicating whether this module has been initialized. */ |
---|
144 | static int initialized = 0; |
---|
145 | |
---|
146 | /* Set to true if the connection is interactive. */ |
---|
147 | static int interactive_mode = 0; |
---|
148 | |
---|
149 | /* Maximum size of a packet. */ |
---|
150 | static unsigned int max_packet_size = (sizeof(int) < 4) ? 32000 : 256000; |
---|
151 | |
---|
152 | /* Sets the descriptors used for communication. Disables encryption until |
---|
153 | packet_set_encryption_key is called. */ |
---|
154 | |
---|
155 | void packet_set_connection(int fd_in, int fd_out, RandomState *state) |
---|
156 | { |
---|
157 | connection_in = fd_in; |
---|
158 | connection_out = fd_out; |
---|
159 | random_state = state; |
---|
160 | cipher_type = SSH_CIPHER_NONE; |
---|
161 | cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1); |
---|
162 | cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0); |
---|
163 | if (!initialized) |
---|
164 | { |
---|
165 | initialized = 1; |
---|
166 | buffer_init(&input); |
---|
167 | buffer_init(&output); |
---|
168 | buffer_init(&outgoing_packet); |
---|
169 | buffer_init(&incoming_packet); |
---|
170 | } |
---|
171 | |
---|
172 | /* Kludge: arrange the close function to be called from fatal(). */ |
---|
173 | fatal_add_cleanup((void (*)(void *))packet_close, NULL); |
---|
174 | |
---|
175 | /* Initially set the connection interactive and enable keepalives. The |
---|
176 | values will be reset to their final values later (after |
---|
177 | authentication). */ |
---|
178 | packet_set_interactive(1, 1); |
---|
179 | } |
---|
180 | |
---|
181 | /* Sets the connection into non-blocking mode. */ |
---|
182 | |
---|
183 | void packet_set_nonblocking(void) |
---|
184 | { |
---|
185 | /* Set the socket into non-blocking mode. */ |
---|
186 | #if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN) |
---|
187 | if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) |
---|
188 | error("fcntl O_NONBLOCK: %.100s", strerror(errno)); |
---|
189 | #else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ |
---|
190 | if (fcntl(connection_in, F_SETFL, O_NDELAY) < 0) |
---|
191 | error("fcntl O_NDELAY: %.100s", strerror(errno)); |
---|
192 | #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ |
---|
193 | |
---|
194 | if (connection_out != connection_in) |
---|
195 | { |
---|
196 | #if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN) |
---|
197 | if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) |
---|
198 | error("fcntl O_NONBLOCK: %.100s", strerror(errno)); |
---|
199 | #else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ |
---|
200 | if (fcntl(connection_out, F_SETFL, O_NDELAY) < 0) |
---|
201 | error("fcntl O_NDELAY: %.100s", strerror(errno)); |
---|
202 | #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ |
---|
203 | } |
---|
204 | } |
---|
205 | |
---|
206 | /* Returns the socket used for reading. */ |
---|
207 | |
---|
208 | int packet_get_connection_in(void) |
---|
209 | { |
---|
210 | return connection_in; |
---|
211 | } |
---|
212 | |
---|
213 | /* Returns the descriptor used for writing. */ |
---|
214 | |
---|
215 | int packet_get_connection_out(void) |
---|
216 | { |
---|
217 | return connection_out; |
---|
218 | } |
---|
219 | |
---|
220 | /* Closes the connection and clears and frees internal data structures. */ |
---|
221 | |
---|
222 | void packet_close(void) |
---|
223 | { |
---|
224 | if (!initialized) |
---|
225 | return; |
---|
226 | initialized = 0; |
---|
227 | if (connection_in == connection_out) |
---|
228 | { |
---|
229 | shutdown(connection_out, 2); |
---|
230 | close(connection_out); |
---|
231 | } |
---|
232 | else |
---|
233 | { |
---|
234 | close(connection_in); |
---|
235 | close(connection_out); |
---|
236 | } |
---|
237 | buffer_free(&input); |
---|
238 | buffer_free(&output); |
---|
239 | buffer_free(&outgoing_packet); |
---|
240 | buffer_free(&incoming_packet); |
---|
241 | if (packet_compression) |
---|
242 | { |
---|
243 | buffer_free(&compression_buffer); |
---|
244 | buffer_compress_uninit(); |
---|
245 | } |
---|
246 | } |
---|
247 | |
---|
248 | /* Sets remote side protocol flags. */ |
---|
249 | |
---|
250 | void packet_set_protocol_flags(unsigned int protocol_flags) |
---|
251 | { |
---|
252 | remote_protocol_flags = protocol_flags; |
---|
253 | channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0); |
---|
254 | } |
---|
255 | |
---|
256 | /* Returns the remote protocol flags set earlier by the above function. */ |
---|
257 | |
---|
258 | unsigned int packet_get_protocol_flags(void) |
---|
259 | { |
---|
260 | return remote_protocol_flags; |
---|
261 | } |
---|
262 | |
---|
263 | /* Starts packet compression from the next packet on in both directions. |
---|
264 | Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */ |
---|
265 | |
---|
266 | void packet_start_compression(int level) |
---|
267 | { |
---|
268 | if (packet_compression) |
---|
269 | fatal("Compression already enabled."); |
---|
270 | packet_compression = 1; |
---|
271 | buffer_init(&compression_buffer); |
---|
272 | buffer_compress_init(level); |
---|
273 | } |
---|
274 | |
---|
275 | /* Encrypts the given number of bytes, copying from src to dest. |
---|
276 | bytes is known to be a multiple of 8. */ |
---|
277 | |
---|
278 | void packet_encrypt(CipherContext *cc, void *dest, void *src, |
---|
279 | unsigned int bytes) |
---|
280 | { |
---|
281 | assert((bytes % 8) == 0); |
---|
282 | cipher_encrypt(cc, dest, src, bytes); |
---|
283 | } |
---|
284 | |
---|
285 | /* Decrypts the given number of bytes, copying from src to dest. |
---|
286 | bytes is known to be a multiple of 8. */ |
---|
287 | |
---|
288 | void packet_decrypt(CipherContext *cc, void *dest, void *src, |
---|
289 | unsigned int bytes) |
---|
290 | { |
---|
291 | int i; |
---|
292 | |
---|
293 | assert((bytes % 8) == 0); |
---|
294 | |
---|
295 | /* $Id: packet.c,v 1.3 1999-03-08 18:20:07 danw Exp $ |
---|
296 | * Cryptographic attack detector for ssh - Modifications for packet.c |
---|
297 | * (C)1998 CORE-SDI, Buenos Aires Argentina |
---|
298 | * Ariel Futoransky(futo@core-sdi.com) |
---|
299 | */ |
---|
300 | |
---|
301 | switch (cc->type) |
---|
302 | { |
---|
303 | #ifndef WITHOUT_IDEA |
---|
304 | case SSH_CIPHER_IDEA : |
---|
305 | i = detect_attack(src, bytes, cc->u.idea.iv); |
---|
306 | break; |
---|
307 | #endif |
---|
308 | case SSH_CIPHER_NONE : |
---|
309 | i = DEATTACK_OK; |
---|
310 | break; |
---|
311 | default: |
---|
312 | i = detect_attack(src, bytes, NULL); |
---|
313 | break; |
---|
314 | } |
---|
315 | |
---|
316 | if (i == DEATTACK_DETECTED) |
---|
317 | packet_disconnect("crc32 compensation attack: network attack detected"); |
---|
318 | |
---|
319 | cipher_decrypt(cc, dest, src, bytes); |
---|
320 | } |
---|
321 | |
---|
322 | /* Causes any further packets to be encrypted using the given key. The same |
---|
323 | key is used for both sending and reception. However, both directions |
---|
324 | are encrypted independently of each other. */ |
---|
325 | |
---|
326 | void packet_set_encryption_key(const unsigned char *key, unsigned int keylen, |
---|
327 | int cipher, int is_client) |
---|
328 | { |
---|
329 | cipher_type = cipher; |
---|
330 | if (cipher == SSH_CIPHER_ARCFOUR) |
---|
331 | { |
---|
332 | if (is_client) |
---|
333 | { /* In client: use first half for receiving, second for sending. */ |
---|
334 | cipher_set_key(&receive_context, cipher, key, keylen / 2, 0); |
---|
335 | cipher_set_key(&send_context, cipher, key + keylen / 2, |
---|
336 | keylen / 2, 1); |
---|
337 | } |
---|
338 | else |
---|
339 | { /* In server: use first half for sending, second for receiving. */ |
---|
340 | cipher_set_key(&receive_context, cipher, key + keylen / 2, |
---|
341 | keylen / 2, 0); |
---|
342 | cipher_set_key(&send_context, cipher, key, keylen / 2, 1); |
---|
343 | } |
---|
344 | } |
---|
345 | else |
---|
346 | { |
---|
347 | /* All other ciphers use the same key in both directions for now. */ |
---|
348 | cipher_set_key(&receive_context, cipher, key, keylen, 0); |
---|
349 | cipher_set_key(&send_context, cipher, key, keylen, 1); |
---|
350 | } |
---|
351 | } |
---|
352 | |
---|
353 | /* Starts constructing a packet to send. */ |
---|
354 | |
---|
355 | void packet_start(int type) |
---|
356 | { |
---|
357 | char buf[9]; |
---|
358 | |
---|
359 | buffer_clear(&outgoing_packet); |
---|
360 | memset(buf, 0, 8); |
---|
361 | buf[8] = type; |
---|
362 | buffer_append(&outgoing_packet, buf, 9); |
---|
363 | } |
---|
364 | |
---|
365 | /* Appends a character to the packet data. */ |
---|
366 | |
---|
367 | void packet_put_char(int value) |
---|
368 | { |
---|
369 | char ch = value; |
---|
370 | buffer_append(&outgoing_packet, &ch, 1); |
---|
371 | } |
---|
372 | |
---|
373 | /* Appends an integer to the packet data. */ |
---|
374 | |
---|
375 | void packet_put_int(unsigned int value) |
---|
376 | { |
---|
377 | buffer_put_int(&outgoing_packet, value); |
---|
378 | } |
---|
379 | |
---|
380 | /* Appends a string to packet data. */ |
---|
381 | |
---|
382 | void packet_put_string(const char *buf, unsigned int len) |
---|
383 | { |
---|
384 | buffer_put_string(&outgoing_packet, buf, len); |
---|
385 | } |
---|
386 | |
---|
387 | /* Appends an arbitrary precision integer to packet data. */ |
---|
388 | |
---|
389 | void packet_put_mp_int(MP_INT *value) |
---|
390 | { |
---|
391 | buffer_put_mp_int(&outgoing_packet, value); |
---|
392 | } |
---|
393 | |
---|
394 | /* Finalizes and sends the packet. If the encryption key has been set, |
---|
395 | encrypts the packet before sending. */ |
---|
396 | |
---|
397 | void packet_send(void) |
---|
398 | { |
---|
399 | char buf[8], *cp; |
---|
400 | int i, padding, len; |
---|
401 | unsigned long checksum; |
---|
402 | |
---|
403 | if (buffer_len(&outgoing_packet) >= max_packet_size - 30) |
---|
404 | fatal("packet_send: sending too big a packet: size %u, limit %u.", |
---|
405 | buffer_len(&outgoing_packet), max_packet_size); |
---|
406 | |
---|
407 | /* If using packet compression, compress the payload of the outgoing |
---|
408 | packet. */ |
---|
409 | if (packet_compression) |
---|
410 | { |
---|
411 | buffer_clear(&compression_buffer); |
---|
412 | buffer_consume(&outgoing_packet, 8); /* Skip padding. */ |
---|
413 | buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */ |
---|
414 | buffer_compress(&outgoing_packet, &compression_buffer); |
---|
415 | buffer_clear(&outgoing_packet); |
---|
416 | buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), |
---|
417 | buffer_len(&compression_buffer)); |
---|
418 | } |
---|
419 | |
---|
420 | /* Compute packet length without padding (add checksum, remove padding). */ |
---|
421 | len = buffer_len(&outgoing_packet) + 4 - 8; |
---|
422 | |
---|
423 | /* Insert padding. */ |
---|
424 | padding = 8 - len % 8; |
---|
425 | if (cipher_type != SSH_CIPHER_NONE) |
---|
426 | { |
---|
427 | cp = buffer_ptr(&outgoing_packet); |
---|
428 | for (i = 0; i < padding; i++) |
---|
429 | cp[7 - i] = random_get_byte(random_state); |
---|
430 | } |
---|
431 | buffer_consume(&outgoing_packet, 8 - padding); |
---|
432 | |
---|
433 | /* Add check bytes. */ |
---|
434 | checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet), |
---|
435 | buffer_len(&outgoing_packet)); |
---|
436 | PUT_32BIT(buf, checksum); |
---|
437 | buffer_append(&outgoing_packet, buf, 4); |
---|
438 | |
---|
439 | #ifdef PACKET_DEBUG |
---|
440 | fprintf(stderr, "packet_send plain: "); |
---|
441 | buffer_dump(&outgoing_packet); |
---|
442 | #endif |
---|
443 | |
---|
444 | /* Append to output. */ |
---|
445 | PUT_32BIT(buf, len); |
---|
446 | buffer_append(&output, buf, 4); |
---|
447 | buffer_append_space(&output, &cp, buffer_len(&outgoing_packet)); |
---|
448 | packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet), |
---|
449 | buffer_len(&outgoing_packet)); |
---|
450 | |
---|
451 | #ifdef PACKET_DEBUG |
---|
452 | fprintf(stderr, "encrypted: "); buffer_dump(&output); |
---|
453 | #endif |
---|
454 | |
---|
455 | buffer_clear(&outgoing_packet); |
---|
456 | |
---|
457 | /* Note that the packet is now only buffered in output. It won\'t be |
---|
458 | actually sent until packet_write_wait or packet_write_poll is called. */ |
---|
459 | } |
---|
460 | |
---|
461 | /* Waits until a packet has been received, and returns its type. Note that |
---|
462 | no other data is processed until this returns, so this function should |
---|
463 | not be used during the interactive session. */ |
---|
464 | |
---|
465 | int packet_read(void) |
---|
466 | { |
---|
467 | int type, len; |
---|
468 | fd_set set; |
---|
469 | char buf[8192]; |
---|
470 | |
---|
471 | /* Since we are blocking, ensure that all written packets have been sent. */ |
---|
472 | packet_write_wait(); |
---|
473 | |
---|
474 | /* Stay in the loop until we have received a complete packet. */ |
---|
475 | for (;;) |
---|
476 | { |
---|
477 | /* Try to read a packet from the buffer. */ |
---|
478 | type = packet_read_poll(); |
---|
479 | /* If we got a packet, return it. */ |
---|
480 | if (type != SSH_MSG_NONE) |
---|
481 | return type; |
---|
482 | /* Otherwise, wait for some data to arrive, add it to the buffer, |
---|
483 | and try again. */ |
---|
484 | FD_ZERO(&set); |
---|
485 | FD_SET(connection_in, &set); |
---|
486 | /* Wait for some data to arrive. */ |
---|
487 | select(connection_in + 1, &set, NULL, NULL, NULL); |
---|
488 | /* Read data from the socket. */ |
---|
489 | len = read(connection_in, buf, sizeof(buf)); |
---|
490 | if (len == 0) |
---|
491 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
492 | "Connection closed by remote host."); |
---|
493 | if (len < 0) |
---|
494 | { |
---|
495 | if (errno == EAGAIN || errno == EWOULDBLOCK) |
---|
496 | continue; |
---|
497 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
498 | "Read from socket failed: %.100s", strerror(errno)); |
---|
499 | } |
---|
500 | /* Append it to the buffer. */ |
---|
501 | packet_process_incoming(buf, len); |
---|
502 | } |
---|
503 | /*NOTREACHED*/ |
---|
504 | } |
---|
505 | |
---|
506 | /* Waits until a packet has been received, verifies that its type matches |
---|
507 | that given, and gives a fatal error and exits if there is a mismatch. */ |
---|
508 | |
---|
509 | void packet_read_expect(int expected_type) |
---|
510 | { |
---|
511 | int type; |
---|
512 | |
---|
513 | type = packet_read(); |
---|
514 | if (type != expected_type) |
---|
515 | packet_disconnect("Protocol error: expected packet type %d, got %d", |
---|
516 | expected_type, type); |
---|
517 | } |
---|
518 | |
---|
519 | /* Checks if a full packet is available in the data received so far via |
---|
520 | packet_process_incoming. If so, reads the packet; otherwise returns |
---|
521 | SSH_MSG_NONE. This does not wait for data from the connection. |
---|
522 | |
---|
523 | SSH_MSG_DISCONNECT is handled specially here. Also, |
---|
524 | SSH_MSG_IGNORE messages are skipped by this function and are never returned |
---|
525 | to higher levels. */ |
---|
526 | |
---|
527 | int packet_read_poll(void) |
---|
528 | { |
---|
529 | unsigned int len, padded_len; |
---|
530 | unsigned char *ucp; |
---|
531 | char buf[8], *cp; |
---|
532 | unsigned long checksum, stored_checksum; |
---|
533 | |
---|
534 | restart: |
---|
535 | |
---|
536 | /* Check if input size is less than minimum packet size. */ |
---|
537 | if (buffer_len(&input) < 4 + 8) |
---|
538 | return SSH_MSG_NONE; |
---|
539 | /* Get length of incoming packet. */ |
---|
540 | ucp = (unsigned char *)buffer_ptr(&input); |
---|
541 | len = GET_32BIT(ucp); |
---|
542 | if (len < 1 + 2 + 2 || len > 256*1024) |
---|
543 | packet_disconnect("Bad packet length %u.", len); |
---|
544 | padded_len = (len + 8) & ~7; |
---|
545 | |
---|
546 | /* Check if the packet has been entirely received. */ |
---|
547 | if (buffer_len(&input) < 4 + padded_len) |
---|
548 | return SSH_MSG_NONE; |
---|
549 | |
---|
550 | /* The entire packet is in buffer. */ |
---|
551 | |
---|
552 | /* Consume packet length. */ |
---|
553 | buffer_consume(&input, 4); |
---|
554 | |
---|
555 | /* Confirm that packet is empty after all data is processed from it. Calls |
---|
556 | fatal buffer is not empty. */ |
---|
557 | if (buffer_len(&incoming_packet) != 0) |
---|
558 | packet_disconnect("Junk data left to incoming packet buffer after all data processed"); |
---|
559 | |
---|
560 | /* Copy data to incoming_packet. */ |
---|
561 | buffer_clear(&incoming_packet); |
---|
562 | buffer_append_space(&incoming_packet, &cp, padded_len); |
---|
563 | packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len); |
---|
564 | buffer_consume(&input, padded_len); |
---|
565 | |
---|
566 | #ifdef PACKET_DEBUG |
---|
567 | fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet); |
---|
568 | #endif |
---|
569 | |
---|
570 | /* Compute packet checksum. */ |
---|
571 | checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet), |
---|
572 | buffer_len(&incoming_packet) - 4); |
---|
573 | |
---|
574 | /* Skip padding. */ |
---|
575 | buffer_consume(&incoming_packet, 8 - len % 8); |
---|
576 | |
---|
577 | /* Test check bytes. */ |
---|
578 | assert(len == buffer_len(&incoming_packet)); |
---|
579 | ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4; |
---|
580 | stored_checksum = GET_32BIT(ucp); |
---|
581 | if (checksum != stored_checksum) |
---|
582 | packet_disconnect("Corrupted check bytes on input."); |
---|
583 | buffer_consume_end(&incoming_packet, 4); |
---|
584 | |
---|
585 | /* If using packet compression, decompress the packet. */ |
---|
586 | if (packet_compression) |
---|
587 | { |
---|
588 | buffer_clear(&compression_buffer); |
---|
589 | buffer_uncompress(&incoming_packet, &compression_buffer); |
---|
590 | buffer_clear(&incoming_packet); |
---|
591 | buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), |
---|
592 | buffer_len(&compression_buffer)); |
---|
593 | } |
---|
594 | |
---|
595 | /* Get packet type. */ |
---|
596 | buffer_get(&incoming_packet, &buf[0], 1); |
---|
597 | |
---|
598 | /* Handle disconnect message. */ |
---|
599 | if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT) |
---|
600 | fatal_severity(SYSLOG_SEVERITY_INFO, "%.900s", packet_get_string(NULL)); |
---|
601 | |
---|
602 | /* Ignore ignore messages. */ |
---|
603 | if ((unsigned char)buf[0] == SSH_MSG_IGNORE) |
---|
604 | { |
---|
605 | char *str; |
---|
606 | str = packet_get_string(NULL); |
---|
607 | xfree(str); |
---|
608 | goto restart; |
---|
609 | } |
---|
610 | |
---|
611 | /* Send debug messages as debugging output. */ |
---|
612 | if ((unsigned char)buf[0] == SSH_MSG_DEBUG) |
---|
613 | { |
---|
614 | char *str; |
---|
615 | |
---|
616 | str = packet_get_string(NULL); |
---|
617 | if (*str == '*') /* Magical kludge to force displaying |
---|
618 | debug messages with '*' anyway, even |
---|
619 | if not in verbose mode. */ |
---|
620 | { |
---|
621 | error("Remote: %.900s", str); |
---|
622 | } |
---|
623 | else |
---|
624 | { |
---|
625 | debug("Remote: %.900s", str); |
---|
626 | } |
---|
627 | xfree(str); |
---|
628 | goto restart; |
---|
629 | } |
---|
630 | |
---|
631 | /* Return type. */ |
---|
632 | return (unsigned char)buf[0]; |
---|
633 | } |
---|
634 | |
---|
635 | /* Buffers the given amount of input characters. This is intended to be |
---|
636 | used together with packet_read_poll. */ |
---|
637 | |
---|
638 | void packet_process_incoming(const char *buf, unsigned int len) |
---|
639 | { |
---|
640 | buffer_append(&input, buf, len); |
---|
641 | } |
---|
642 | |
---|
643 | /* Returns the number of bytes left in the incoming packet. */ |
---|
644 | |
---|
645 | unsigned int packet_get_len(void) |
---|
646 | { |
---|
647 | return buffer_len(&incoming_packet); |
---|
648 | } |
---|
649 | |
---|
650 | /* Returns a character from the packet. */ |
---|
651 | |
---|
652 | unsigned int packet_get_char(void) |
---|
653 | { |
---|
654 | char ch; |
---|
655 | buffer_get(&incoming_packet, &ch, 1); |
---|
656 | return (unsigned char)ch; |
---|
657 | } |
---|
658 | |
---|
659 | /* Returns an integer from the packet data. */ |
---|
660 | |
---|
661 | unsigned int packet_get_int(void) |
---|
662 | { |
---|
663 | return buffer_get_int(&incoming_packet); |
---|
664 | } |
---|
665 | |
---|
666 | /* Returns an arbitrary precision integer from the packet data. The integer |
---|
667 | must have been initialized before this call. */ |
---|
668 | |
---|
669 | void packet_get_mp_int(MP_INT *value) |
---|
670 | { |
---|
671 | buffer_get_mp_int(&incoming_packet, value); |
---|
672 | } |
---|
673 | |
---|
674 | /* Returns a string from the packet data. The string is allocated using |
---|
675 | xmalloc; it is the responsibility of the calling program to free it when |
---|
676 | no longer needed. The length_ptr argument may be NULL, or point to an |
---|
677 | integer into which the length of the string is stored. */ |
---|
678 | |
---|
679 | char *packet_get_string(unsigned int *length_ptr) |
---|
680 | { |
---|
681 | return buffer_get_string(&incoming_packet, length_ptr); |
---|
682 | } |
---|
683 | |
---|
684 | /* Clears incoming data buffer */ |
---|
685 | |
---|
686 | void packet_get_all(void) |
---|
687 | { |
---|
688 | buffer_clear(&incoming_packet); |
---|
689 | } |
---|
690 | |
---|
691 | /* Sends a diagnostic message from the server to the client. This message |
---|
692 | can be sent at any time (but not while constructing another message). |
---|
693 | The message is printed immediately, but only if the client is being |
---|
694 | executed in verbose mode. These messages are primarily intended to |
---|
695 | ease debugging authentication problems. The length of the formatted |
---|
696 | message must not exceed 1024 bytes. This will automatically call |
---|
697 | packet_write_wait. */ |
---|
698 | |
---|
699 | void packet_send_debug(const char *fmt, ...) |
---|
700 | { |
---|
701 | char buf[1024]; |
---|
702 | va_list args; |
---|
703 | |
---|
704 | va_start(args, fmt); |
---|
705 | vsprintf(buf, fmt, args); |
---|
706 | va_end(args); |
---|
707 | |
---|
708 | packet_start(SSH_MSG_DEBUG); |
---|
709 | packet_put_string(buf, strlen(buf)); |
---|
710 | packet_send(); |
---|
711 | packet_write_wait(); |
---|
712 | } |
---|
713 | |
---|
714 | /* Logs the error plus constructs and sends a disconnect |
---|
715 | packet, closes the connection, and exits. This function never returns. |
---|
716 | The error message should not contain a newline. The length of the |
---|
717 | formatted message must not exceed 1024 bytes. */ |
---|
718 | |
---|
719 | void packet_disconnect(const char *fmt, ...) |
---|
720 | { |
---|
721 | char buf[1024]; |
---|
722 | va_list args; |
---|
723 | static int disconnecting = 0; |
---|
724 | if (disconnecting) /* Guard against recursive invocations. */ |
---|
725 | fatal("packet_disconnect called recursively."); |
---|
726 | disconnecting = 1; |
---|
727 | |
---|
728 | /* Format the message. Note that the caller must make sure the message |
---|
729 | is of limited size. */ |
---|
730 | va_start(args, fmt); |
---|
731 | vsprintf(buf, fmt, args); |
---|
732 | va_end(args); |
---|
733 | |
---|
734 | /* Send the disconnect message to the other side, and wait for it to get |
---|
735 | sent. */ |
---|
736 | packet_start(SSH_MSG_DISCONNECT); |
---|
737 | packet_put_string(buf, strlen(buf)); |
---|
738 | packet_send(); |
---|
739 | packet_write_wait(); |
---|
740 | |
---|
741 | /* Stop listening for connections. */ |
---|
742 | channel_stop_listening(); |
---|
743 | |
---|
744 | /* Close the connection. */ |
---|
745 | packet_close(); |
---|
746 | |
---|
747 | /* Display the error locally and exit. */ |
---|
748 | fatal("Local: %.100s", buf); |
---|
749 | } |
---|
750 | |
---|
751 | /* Checks if there is any buffered output, and tries to write some of the |
---|
752 | output. */ |
---|
753 | |
---|
754 | void packet_write_poll(void) |
---|
755 | { |
---|
756 | int len = buffer_len(&output); |
---|
757 | if (len > 0) |
---|
758 | { |
---|
759 | len = write(connection_out, buffer_ptr(&output), len); |
---|
760 | if (len <= 0) |
---|
761 | if (errno == EAGAIN || errno == EWOULDBLOCK) |
---|
762 | return; |
---|
763 | else |
---|
764 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
765 | "Write failed: %.100s", strerror(errno)); |
---|
766 | buffer_consume(&output, len); |
---|
767 | } |
---|
768 | } |
---|
769 | |
---|
770 | /* Calls packet_write_poll repeatedly until all pending output data has |
---|
771 | been written. */ |
---|
772 | |
---|
773 | void packet_write_wait(void) |
---|
774 | { |
---|
775 | packet_write_poll(); |
---|
776 | while (packet_have_data_to_write()) |
---|
777 | { |
---|
778 | fd_set set; |
---|
779 | FD_ZERO(&set); |
---|
780 | FD_SET(connection_out, &set); |
---|
781 | select(connection_out + 1, NULL, &set, NULL, NULL); |
---|
782 | packet_write_poll(); |
---|
783 | } |
---|
784 | } |
---|
785 | |
---|
786 | /* Returns true if there is buffered data to write to the connection. */ |
---|
787 | |
---|
788 | int packet_have_data_to_write(void) |
---|
789 | { |
---|
790 | return buffer_len(&output) != 0; |
---|
791 | } |
---|
792 | |
---|
793 | /* Returns true if there is not too much data to write to the connection. */ |
---|
794 | |
---|
795 | int packet_not_very_much_data_to_write(void) |
---|
796 | { |
---|
797 | if (interactive_mode || sizeof(int) < 4) |
---|
798 | return buffer_len(&output) < 16384; |
---|
799 | else |
---|
800 | return buffer_len(&output) < 128*1024; |
---|
801 | } |
---|
802 | |
---|
803 | /* Informs that the current session is interactive. Sets IP flags for that. */ |
---|
804 | |
---|
805 | void packet_set_interactive(int interactive, int keepalives) |
---|
806 | { |
---|
807 | int on = 1, off = 0; |
---|
808 | |
---|
809 | /* Record that we are in interactive mode. */ |
---|
810 | interactive_mode = interactive; |
---|
811 | |
---|
812 | /* Only set socket options if using a socket (as indicated by the descriptors |
---|
813 | being the same). */ |
---|
814 | if (connection_in != connection_out) |
---|
815 | return; |
---|
816 | |
---|
817 | if (keepalives) |
---|
818 | { |
---|
819 | /* Set keepalives if requested. */ |
---|
820 | if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, |
---|
821 | sizeof(on)) < 0) |
---|
822 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
---|
823 | } |
---|
824 | else |
---|
825 | { |
---|
826 | /* Clear keepalives if we don't want them. */ |
---|
827 | if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&off, |
---|
828 | sizeof(off)) < 0) |
---|
829 | error("setsockopt SO_KEEPALIVE off: %.100s", strerror(errno)); |
---|
830 | } |
---|
831 | |
---|
832 | if (interactive) |
---|
833 | { |
---|
834 | /* Set IP options for an interactive connection. Use IPTOS_LOWDELAY |
---|
835 | and TCP_NODELAY. */ |
---|
836 | #ifdef IPTOS_LOWDELAY |
---|
837 | int lowdelay = IPTOS_LOWDELAY; |
---|
838 | if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay, |
---|
839 | sizeof(lowdelay)) < 0) |
---|
840 | error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno)); |
---|
841 | #endif /* IPTOS_LOWDELAY */ |
---|
842 | #if defined(TCP_NODELAY) && defined(ENABLE_TCP_NODELAY) |
---|
843 | if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on, |
---|
844 | sizeof(on)) < 0) |
---|
845 | error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); |
---|
846 | #endif /* TCP_NODELAY */ |
---|
847 | } |
---|
848 | else |
---|
849 | { |
---|
850 | /* Set IP options for a non-interactive connection. Use |
---|
851 | IPTOS_THROUGHPUT. */ |
---|
852 | #ifdef IPTOS_THROUGHPUT |
---|
853 | int throughput = IPTOS_THROUGHPUT; |
---|
854 | if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput, |
---|
855 | sizeof(throughput)) < 0) |
---|
856 | error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); |
---|
857 | #endif /* IPTOS_THROUGHPUT */ |
---|
858 | #if defined(TCP_NODELAY) && defined(ENABLE_TCP_NODELAY) |
---|
859 | if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&off, |
---|
860 | sizeof(off)) < 0) |
---|
861 | error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); |
---|
862 | #endif /* TCP_NODELAY */ |
---|
863 | } |
---|
864 | } |
---|
865 | |
---|
866 | /* Returns true if the current connection is interactive. */ |
---|
867 | |
---|
868 | int packet_is_interactive(void) |
---|
869 | { |
---|
870 | return interactive_mode; |
---|
871 | } |
---|
872 | |
---|
873 | /* Sets the maximum packet size that can be sent to the other side. */ |
---|
874 | |
---|
875 | void packet_set_max_size(unsigned int max_size) |
---|
876 | { |
---|
877 | max_packet_size = max_size; |
---|
878 | } |
---|
879 | |
---|
880 | /* Returns the maximum packet size that can be sent to the other side. */ |
---|
881 | |
---|
882 | unsigned int packet_max_size(void) |
---|
883 | { |
---|
884 | return max_packet_size; |
---|
885 | } |
---|