blob: ffce2c74508231d2d050b149b190b1b48f7db5dd [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 *
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 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100016
17#include "includes.h"
Damien Millerb38eff82000-04-01 11:09:21 +100018RCSID("$Id: packet.c,v 1.13 2000/04/01 01:09:25 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100019
20#include "xmalloc.h"
21#include "buffer.h"
22#include "packet.h"
23#include "bufaux.h"
24#include "ssh.h"
25#include "crc32.h"
26#include "cipher.h"
27#include "getput.h"
28
29#include "compress.h"
30#include "deattack.h"
Damien Millerb38eff82000-04-01 11:09:21 +100031#include "channels.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100032
Damien Miller5428f641999-11-25 11:54:57 +110033/*
34 * This variable contains the file descriptors used for communicating with
35 * the other side. connection_in is used for reading; connection_out for
36 * writing. These can be the same descriptor, in which case it is assumed to
37 * be a socket.
38 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100039static int connection_in = -1;
40static int connection_out = -1;
41
Damien Miller5428f641999-11-25 11:54:57 +110042/*
43 * Cipher type. This value is only used to determine whether to pad the
44 * packets with zeroes or random data.
45 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100046static int cipher_type = SSH_CIPHER_NONE;
47
48/* Protocol flags for the remote side. */
49static unsigned int remote_protocol_flags = 0;
50
51/* Encryption context for receiving data. This is only used for decryption. */
52static CipherContext receive_context;
Damien Miller95def091999-11-25 00:26:21 +110053
54/* Encryption context for sending data. This is only used for encryption. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100055static CipherContext send_context;
56
57/* Buffer for raw input data from the socket. */
58static Buffer input;
59
60/* Buffer for raw output data going to the socket. */
61static Buffer output;
62
63/* Buffer for the partial outgoing packet being constructed. */
64static Buffer outgoing_packet;
65
66/* Buffer for the incoming packet currently being processed. */
67static Buffer incoming_packet;
68
69/* Scratch buffer for packet compression/decompression. */
70static Buffer compression_buffer;
71
72/* Flag indicating whether packet compression/decompression is enabled. */
73static int packet_compression = 0;
74
Damien Miller6162d121999-11-21 13:23:52 +110075/* default maximum packet size */
76int max_packet_size = 32768;
77
Damien Millerd4a8b7e1999-10-27 13:42:43 +100078/* Flag indicating whether this module has been initialized. */
79static int initialized = 0;
80
81/* Set to true if the connection is interactive. */
82static int interactive_mode = 0;
83
Damien Miller5428f641999-11-25 11:54:57 +110084/*
85 * Sets the descriptors used for communication. Disables encryption until
86 * packet_set_encryption_key is called.
87 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100088
89void
90packet_set_connection(int fd_in, int fd_out)
91{
Damien Miller95def091999-11-25 00:26:21 +110092 connection_in = fd_in;
93 connection_out = fd_out;
94 cipher_type = SSH_CIPHER_NONE;
95 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 1);
96 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 0);
97 if (!initialized) {
98 initialized = 1;
99 buffer_init(&input);
100 buffer_init(&output);
101 buffer_init(&outgoing_packet);
102 buffer_init(&incoming_packet);
103 }
104 /* Kludge: arrange the close function to be called from fatal(). */
105 fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000106}
107
Damien Miller34132e52000-01-14 15:45:46 +1100108/* Returns 1 if remote host is connected via socket, 0 if not. */
109
110int
111packet_connection_is_on_socket()
112{
113 struct sockaddr_storage from, to;
114 socklen_t fromlen, tolen;
115
116 /* filedescriptors in and out are the same, so it's a socket */
117 if (connection_in == connection_out)
118 return 1;
119 fromlen = sizeof(from);
120 memset(&from, 0, sizeof(from));
Damien Millerf052aaf2000-01-22 19:47:21 +1100121 if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
Damien Miller34132e52000-01-14 15:45:46 +1100122 return 0;
123 tolen = sizeof(to);
124 memset(&to, 0, sizeof(to));
Damien Millerf052aaf2000-01-22 19:47:21 +1100125 if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
Damien Miller34132e52000-01-14 15:45:46 +1100126 return 0;
127 if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
128 return 0;
129 if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
130 return 0;
131 return 1;
132}
133
134/* returns 1 if connection is via ipv4 */
135
136int
137packet_connection_is_ipv4()
138{
139 struct sockaddr_storage to;
Damien Miller6fe375d2000-01-23 09:38:00 +1100140 socklen_t tolen = sizeof(to);
Damien Miller34132e52000-01-14 15:45:46 +1100141
142 memset(&to, 0, sizeof(to));
143 if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
144 return 0;
145 if (to.ss_family != AF_INET)
146 return 0;
147 return 1;
148}
149
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000150/* Sets the connection into non-blocking mode. */
151
152void
153packet_set_nonblocking()
154{
Damien Miller95def091999-11-25 00:26:21 +1100155 /* Set the socket into non-blocking mode. */
156 if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
157 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000158
Damien Miller95def091999-11-25 00:26:21 +1100159 if (connection_out != connection_in) {
160 if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
161 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
162 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000163}
164
165/* Returns the socket used for reading. */
166
167int
168packet_get_connection_in()
169{
Damien Miller95def091999-11-25 00:26:21 +1100170 return connection_in;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000171}
172
173/* Returns the descriptor used for writing. */
174
175int
176packet_get_connection_out()
177{
Damien Miller95def091999-11-25 00:26:21 +1100178 return connection_out;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000179}
180
181/* Closes the connection and clears and frees internal data structures. */
182
183void
184packet_close()
185{
Damien Miller95def091999-11-25 00:26:21 +1100186 if (!initialized)
187 return;
188 initialized = 0;
189 if (connection_in == connection_out) {
190 shutdown(connection_out, SHUT_RDWR);
191 close(connection_out);
192 } else {
193 close(connection_in);
194 close(connection_out);
195 }
196 buffer_free(&input);
197 buffer_free(&output);
198 buffer_free(&outgoing_packet);
199 buffer_free(&incoming_packet);
200 if (packet_compression) {
201 buffer_free(&compression_buffer);
202 buffer_compress_uninit();
203 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000204}
205
206/* Sets remote side protocol flags. */
207
208void
209packet_set_protocol_flags(unsigned int protocol_flags)
210{
Damien Miller95def091999-11-25 00:26:21 +1100211 remote_protocol_flags = protocol_flags;
212 channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000213}
214
215/* Returns the remote protocol flags set earlier by the above function. */
216
217unsigned int
218packet_get_protocol_flags()
219{
Damien Miller95def091999-11-25 00:26:21 +1100220 return remote_protocol_flags;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000221}
222
Damien Miller5428f641999-11-25 11:54:57 +1100223/*
224 * Starts packet compression from the next packet on in both directions.
225 * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
226 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000227
228void
229packet_start_compression(int level)
230{
Damien Miller95def091999-11-25 00:26:21 +1100231 if (packet_compression)
232 fatal("Compression already enabled.");
233 packet_compression = 1;
234 buffer_init(&compression_buffer);
235 buffer_compress_init(level);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000236}
237
Damien Miller5428f641999-11-25 11:54:57 +1100238/*
239 * Encrypts the given number of bytes, copying from src to dest. bytes is
240 * known to be a multiple of 8.
241 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000242
243void
Damien Miller95def091999-11-25 00:26:21 +1100244packet_encrypt(CipherContext * cc, void *dest, void *src,
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000245 unsigned int bytes)
246{
Damien Miller95def091999-11-25 00:26:21 +1100247 cipher_encrypt(cc, dest, src, bytes);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000248}
249
Damien Miller5428f641999-11-25 11:54:57 +1100250/*
251 * Decrypts the given number of bytes, copying from src to dest. bytes is
252 * known to be a multiple of 8.
253 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000254
255void
Damien Miller95def091999-11-25 00:26:21 +1100256packet_decrypt(CipherContext * cc, void *dest, void *src,
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000257 unsigned int bytes)
258{
Damien Miller95def091999-11-25 00:26:21 +1100259 int i;
260
261 if ((bytes % 8) != 0)
262 fatal("packet_decrypt: bad ciphertext length %d", bytes);
263
Damien Miller5428f641999-11-25 11:54:57 +1100264 /*
265 * Cryptographic attack detector for ssh - Modifications for packet.c
266 * (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com)
267 */
Damien Miller95def091999-11-25 00:26:21 +1100268
269 switch (cc->type) {
270 case SSH_CIPHER_NONE:
271 i = DEATTACK_OK;
272 break;
273 default:
274 i = detect_attack(src, bytes, NULL);
275 break;
276 }
277
278 if (i == DEATTACK_DETECTED)
279 packet_disconnect("crc32 compensation attack: network attack detected");
280
281 cipher_decrypt(cc, dest, src, bytes);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000282}
283
Damien Miller5428f641999-11-25 11:54:57 +1100284/*
285 * Causes any further packets to be encrypted using the given key. The same
286 * key is used for both sending and reception. However, both directions are
287 * encrypted independently of each other.
288 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000289
290void
291packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
Damien Miller7e8e8201999-11-16 13:37:16 +1100292 int cipher)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000293{
Damien Miller95def091999-11-25 00:26:21 +1100294 /* All other ciphers use the same key in both directions for now. */
295 cipher_set_key(&receive_context, cipher, key, keylen, 0);
296 cipher_set_key(&send_context, cipher, key, keylen, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000297}
298
299/* Starts constructing a packet to send. */
300
301void
302packet_start(int type)
303{
Damien Miller95def091999-11-25 00:26:21 +1100304 char buf[9];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000305
Damien Miller95def091999-11-25 00:26:21 +1100306 buffer_clear(&outgoing_packet);
307 memset(buf, 0, 8);
308 buf[8] = type;
309 buffer_append(&outgoing_packet, buf, 9);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000310}
311
312/* Appends a character to the packet data. */
313
314void
315packet_put_char(int value)
316{
Damien Miller95def091999-11-25 00:26:21 +1100317 char ch = value;
318 buffer_append(&outgoing_packet, &ch, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000319}
320
321/* Appends an integer to the packet data. */
322
323void
324packet_put_int(unsigned int value)
325{
Damien Miller95def091999-11-25 00:26:21 +1100326 buffer_put_int(&outgoing_packet, value);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000327}
328
329/* Appends a string to packet data. */
330
331void
332packet_put_string(const char *buf, unsigned int len)
333{
Damien Miller95def091999-11-25 00:26:21 +1100334 buffer_put_string(&outgoing_packet, buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000335}
336
337/* Appends an arbitrary precision integer to packet data. */
338
339void
Damien Miller95def091999-11-25 00:26:21 +1100340packet_put_bignum(BIGNUM * value)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000341{
Damien Miller95def091999-11-25 00:26:21 +1100342 buffer_put_bignum(&outgoing_packet, value);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000343}
344
Damien Miller5428f641999-11-25 11:54:57 +1100345/*
346 * Finalizes and sends the packet. If the encryption key has been set,
347 * encrypts the packet before sending.
348 */
Damien Miller95def091999-11-25 00:26:21 +1100349
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000350void
351packet_send()
352{
Damien Miller95def091999-11-25 00:26:21 +1100353 char buf[8], *cp;
354 int i, padding, len;
355 unsigned int checksum;
356 u_int32_t rand = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000357
Damien Miller5428f641999-11-25 11:54:57 +1100358 /*
359 * If using packet compression, compress the payload of the outgoing
360 * packet.
361 */
Damien Miller95def091999-11-25 00:26:21 +1100362 if (packet_compression) {
363 buffer_clear(&compression_buffer);
364 /* Skip padding. */
365 buffer_consume(&outgoing_packet, 8);
366 /* padding */
367 buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
368 buffer_compress(&outgoing_packet, &compression_buffer);
369 buffer_clear(&outgoing_packet);
370 buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
371 buffer_len(&compression_buffer));
372 }
373 /* Compute packet length without padding (add checksum, remove padding). */
374 len = buffer_len(&outgoing_packet) + 4 - 8;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000375
Damien Miller95def091999-11-25 00:26:21 +1100376 /* Insert padding. */
377 padding = 8 - len % 8;
378 if (cipher_type != SSH_CIPHER_NONE) {
379 cp = buffer_ptr(&outgoing_packet);
380 for (i = 0; i < padding; i++) {
381 if (i % 4 == 0)
382 rand = arc4random();
383 cp[7 - i] = rand & 0xff;
384 rand >>= 8;
385 }
386 }
387 buffer_consume(&outgoing_packet, 8 - padding);
388
389 /* Add check bytes. */
390 checksum = crc32((unsigned char *) buffer_ptr(&outgoing_packet),
391 buffer_len(&outgoing_packet));
392 PUT_32BIT(buf, checksum);
393 buffer_append(&outgoing_packet, buf, 4);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000394
395#ifdef PACKET_DEBUG
Damien Miller95def091999-11-25 00:26:21 +1100396 fprintf(stderr, "packet_send plain: ");
397 buffer_dump(&outgoing_packet);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000398#endif
399
Damien Miller95def091999-11-25 00:26:21 +1100400 /* Append to output. */
401 PUT_32BIT(buf, len);
402 buffer_append(&output, buf, 4);
403 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
404 packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
405 buffer_len(&outgoing_packet));
406
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000407#ifdef PACKET_DEBUG
Damien Miller95def091999-11-25 00:26:21 +1100408 fprintf(stderr, "encrypted: ");
409 buffer_dump(&output);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000410#endif
411
Damien Miller95def091999-11-25 00:26:21 +1100412 buffer_clear(&outgoing_packet);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000413
Damien Miller5428f641999-11-25 11:54:57 +1100414 /*
415 * Note that the packet is now only buffered in output. It won\'t be
416 * actually sent until packet_write_wait or packet_write_poll is
417 * called.
418 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000419}
420
Damien Miller5428f641999-11-25 11:54:57 +1100421/*
422 * Waits until a packet has been received, and returns its type. Note that
423 * no other data is processed until this returns, so this function should not
424 * be used during the interactive session.
425 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000426
427int
428packet_read(int *payload_len_ptr)
429{
Damien Miller95def091999-11-25 00:26:21 +1100430 int type, len;
431 fd_set set;
432 char buf[8192];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000433
Damien Miller95def091999-11-25 00:26:21 +1100434 /* Since we are blocking, ensure that all written packets have been sent. */
435 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000436
Damien Miller95def091999-11-25 00:26:21 +1100437 /* Stay in the loop until we have received a complete packet. */
438 for (;;) {
439 /* Try to read a packet from the buffer. */
440 type = packet_read_poll(payload_len_ptr);
441 if (type == SSH_SMSG_SUCCESS
442 || type == SSH_SMSG_FAILURE
443 || type == SSH_CMSG_EOF
444 || type == SSH_CMSG_EXIT_CONFIRMATION)
445 packet_integrity_check(*payload_len_ptr, 0, type);
446 /* If we got a packet, return it. */
447 if (type != SSH_MSG_NONE)
448 return type;
Damien Miller5428f641999-11-25 11:54:57 +1100449 /*
450 * Otherwise, wait for some data to arrive, add it to the
451 * buffer, and try again.
452 */
Damien Miller95def091999-11-25 00:26:21 +1100453 FD_ZERO(&set);
454 FD_SET(connection_in, &set);
Damien Miller5428f641999-11-25 11:54:57 +1100455
Damien Miller95def091999-11-25 00:26:21 +1100456 /* Wait for some data to arrive. */
457 select(connection_in + 1, &set, NULL, NULL, NULL);
Damien Miller5428f641999-11-25 11:54:57 +1100458
Damien Miller95def091999-11-25 00:26:21 +1100459 /* Read data from the socket. */
460 len = read(connection_in, buf, sizeof(buf));
Damien Miller5e7c10e1999-12-16 13:18:04 +1100461 if (len == 0) {
462 log("Connection closed by %.200s", get_remote_ipaddr());
463 fatal_cleanup();
464 }
Damien Miller95def091999-11-25 00:26:21 +1100465 if (len < 0)
466 fatal("Read from socket failed: %.100s", strerror(errno));
467 /* Append it to the buffer. */
468 packet_process_incoming(buf, len);
469 }
470 /* NOTREACHED */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000471}
472
Damien Miller5428f641999-11-25 11:54:57 +1100473/*
474 * Waits until a packet has been received, verifies that its type matches
475 * that given, and gives a fatal error and exits if there is a mismatch.
476 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000477
478void
479packet_read_expect(int *payload_len_ptr, int expected_type)
480{
Damien Miller95def091999-11-25 00:26:21 +1100481 int type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000482
Damien Miller95def091999-11-25 00:26:21 +1100483 type = packet_read(payload_len_ptr);
484 if (type != expected_type)
485 packet_disconnect("Protocol error: expected packet type %d, got %d",
486 expected_type, type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000487}
488
489/* Checks if a full packet is available in the data received so far via
Damien Miller95def091999-11-25 00:26:21 +1100490 * packet_process_incoming. If so, reads the packet; otherwise returns
491 * SSH_MSG_NONE. This does not wait for data from the connection.
492 *
493 * SSH_MSG_DISCONNECT is handled specially here. Also,
494 * SSH_MSG_IGNORE messages are skipped by this function and are never returned
495 * to higher levels.
496 *
497 * The returned payload_len does include space consumed by:
498 * Packet length
499 * Padding
500 * Packet type
501 * Check bytes
502 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000503
504int
505packet_read_poll(int *payload_len_ptr)
506{
Damien Miller95def091999-11-25 00:26:21 +1100507 unsigned int len, padded_len;
508 unsigned char *ucp;
Damien Miller98c7ad62000-03-09 21:27:49 +1100509 char buf[8], *cp, *msg;
Damien Miller95def091999-11-25 00:26:21 +1100510 unsigned int checksum, stored_checksum;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000511
Damien Miller95def091999-11-25 00:26:21 +1100512restart:
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000513
Damien Miller95def091999-11-25 00:26:21 +1100514 /* Check if input size is less than minimum packet size. */
515 if (buffer_len(&input) < 4 + 8)
516 return SSH_MSG_NONE;
517 /* Get length of incoming packet. */
518 ucp = (unsigned char *) buffer_ptr(&input);
519 len = GET_32BIT(ucp);
520 if (len < 1 + 2 + 2 || len > 256 * 1024)
521 packet_disconnect("Bad packet length %d.", len);
522 padded_len = (len + 8) & ~7;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000523
Damien Miller95def091999-11-25 00:26:21 +1100524 /* Check if the packet has been entirely received. */
525 if (buffer_len(&input) < 4 + padded_len)
526 return SSH_MSG_NONE;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000527
Damien Miller95def091999-11-25 00:26:21 +1100528 /* The entire packet is in buffer. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000529
Damien Miller95def091999-11-25 00:26:21 +1100530 /* Consume packet length. */
531 buffer_consume(&input, 4);
532
533 /* Copy data to incoming_packet. */
534 buffer_clear(&incoming_packet);
535 buffer_append_space(&incoming_packet, &cp, padded_len);
536 packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
537 buffer_consume(&input, padded_len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000538
539#ifdef PACKET_DEBUG
Damien Miller95def091999-11-25 00:26:21 +1100540 fprintf(stderr, "read_poll plain: ");
541 buffer_dump(&incoming_packet);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000542#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000543
Damien Miller95def091999-11-25 00:26:21 +1100544 /* Compute packet checksum. */
545 checksum = crc32((unsigned char *) buffer_ptr(&incoming_packet),
546 buffer_len(&incoming_packet) - 4);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000547
Damien Miller95def091999-11-25 00:26:21 +1100548 /* Skip padding. */
549 buffer_consume(&incoming_packet, 8 - len % 8);
Damien Millerfd7c9111999-11-08 16:15:55 +1100550
Damien Miller95def091999-11-25 00:26:21 +1100551 /* Test check bytes. */
Damien Millerfd7c9111999-11-08 16:15:55 +1100552
Damien Miller95def091999-11-25 00:26:21 +1100553 if (len != buffer_len(&incoming_packet))
554 packet_disconnect("packet_read_poll: len %d != buffer_len %d.",
555 len, buffer_len(&incoming_packet));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000556
Damien Miller95def091999-11-25 00:26:21 +1100557 ucp = (unsigned char *) buffer_ptr(&incoming_packet) + len - 4;
558 stored_checksum = GET_32BIT(ucp);
559 if (checksum != stored_checksum)
560 packet_disconnect("Corrupted check bytes on input.");
561 buffer_consume_end(&incoming_packet, 4);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000562
Damien Miller95def091999-11-25 00:26:21 +1100563 /* If using packet compression, decompress the packet. */
564 if (packet_compression) {
565 buffer_clear(&compression_buffer);
566 buffer_uncompress(&incoming_packet, &compression_buffer);
567 buffer_clear(&incoming_packet);
568 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
569 buffer_len(&compression_buffer));
570 }
571 /* Get packet type. */
572 buffer_get(&incoming_packet, &buf[0], 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000573
Damien Miller95def091999-11-25 00:26:21 +1100574 /* Return length of payload (without type field). */
575 *payload_len_ptr = buffer_len(&incoming_packet);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000576
Damien Miller95def091999-11-25 00:26:21 +1100577 /* Handle disconnect message. */
Damien Milleraae6c611999-12-06 11:47:28 +1100578 if ((unsigned char) buf[0] == SSH_MSG_DISCONNECT) {
Damien Miller98c7ad62000-03-09 21:27:49 +1100579 msg = packet_get_string(NULL);
580 log("Received disconnect: %.900s", msg);
581 xfree(msg);
Damien Milleraae6c611999-12-06 11:47:28 +1100582 fatal_cleanup();
583 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000584
Damien Miller95def091999-11-25 00:26:21 +1100585 /* Ignore ignore messages. */
586 if ((unsigned char) buf[0] == SSH_MSG_IGNORE)
587 goto restart;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000588
Damien Miller95def091999-11-25 00:26:21 +1100589 /* Send debug messages as debugging output. */
590 if ((unsigned char) buf[0] == SSH_MSG_DEBUG) {
Damien Miller98c7ad62000-03-09 21:27:49 +1100591 msg = packet_get_string(NULL);
592 debug("Remote: %.900s", msg);
593 xfree(msg);
Damien Miller95def091999-11-25 00:26:21 +1100594 goto restart;
595 }
596 /* Return type. */
597 return (unsigned char) buf[0];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000598}
Damien Miller95def091999-11-25 00:26:21 +1100599
Damien Miller5428f641999-11-25 11:54:57 +1100600/*
601 * Buffers the given amount of input characters. This is intended to be used
602 * together with packet_read_poll.
603 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000604
605void
606packet_process_incoming(const char *buf, unsigned int len)
607{
Damien Miller95def091999-11-25 00:26:21 +1100608 buffer_append(&input, buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000609}
610
611/* Returns a character from the packet. */
612
613unsigned int
614packet_get_char()
615{
Damien Miller95def091999-11-25 00:26:21 +1100616 char ch;
617 buffer_get(&incoming_packet, &ch, 1);
618 return (unsigned char) ch;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000619}
620
621/* Returns an integer from the packet data. */
622
623unsigned int
624packet_get_int()
625{
Damien Miller95def091999-11-25 00:26:21 +1100626 return buffer_get_int(&incoming_packet);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000627}
628
Damien Miller5428f641999-11-25 11:54:57 +1100629/*
630 * Returns an arbitrary precision integer from the packet data. The integer
631 * must have been initialized before this call.
632 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000633
634void
Damien Miller95def091999-11-25 00:26:21 +1100635packet_get_bignum(BIGNUM * value, int *length_ptr)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000636{
Damien Miller95def091999-11-25 00:26:21 +1100637 *length_ptr = buffer_get_bignum(&incoming_packet, value);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000638}
639
Damien Miller5428f641999-11-25 11:54:57 +1100640/*
641 * Returns a string from the packet data. The string is allocated using
642 * xmalloc; it is the responsibility of the calling program to free it when
643 * no longer needed. The length_ptr argument may be NULL, or point to an
644 * integer into which the length of the string is stored.
645 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000646
Damien Miller5428f641999-11-25 11:54:57 +1100647char *
Damien Miller95def091999-11-25 00:26:21 +1100648packet_get_string(unsigned int *length_ptr)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000649{
Damien Miller95def091999-11-25 00:26:21 +1100650 return buffer_get_string(&incoming_packet, length_ptr);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000651}
652
Damien Miller5428f641999-11-25 11:54:57 +1100653/*
654 * Sends a diagnostic message from the server to the client. This message
655 * can be sent at any time (but not while constructing another message). The
656 * message is printed immediately, but only if the client is being executed
657 * in verbose mode. These messages are primarily intended to ease debugging
658 * authentication problems. The length of the formatted message must not
659 * exceed 1024 bytes. This will automatically call packet_write_wait.
660 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000661
662void
Damien Miller95def091999-11-25 00:26:21 +1100663packet_send_debug(const char *fmt,...)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000664{
Damien Miller95def091999-11-25 00:26:21 +1100665 char buf[1024];
666 va_list args;
667
668 va_start(args, fmt);
669 vsnprintf(buf, sizeof(buf), fmt, args);
670 va_end(args);
671
672 packet_start(SSH_MSG_DEBUG);
673 packet_put_string(buf, strlen(buf));
674 packet_send();
675 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000676}
677
Damien Miller5428f641999-11-25 11:54:57 +1100678/*
679 * Logs the error plus constructs and sends a disconnect packet, closes the
680 * connection, and exits. This function never returns. The error message
681 * should not contain a newline. The length of the formatted message must
682 * not exceed 1024 bytes.
683 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000684
685void
Damien Miller95def091999-11-25 00:26:21 +1100686packet_disconnect(const char *fmt,...)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000687{
Damien Miller95def091999-11-25 00:26:21 +1100688 char buf[1024];
689 va_list args;
690 static int disconnecting = 0;
691 if (disconnecting) /* Guard against recursive invocations. */
692 fatal("packet_disconnect called recursively.");
693 disconnecting = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000694
Damien Miller5428f641999-11-25 11:54:57 +1100695 /*
696 * Format the message. Note that the caller must make sure the
697 * message is of limited size.
698 */
Damien Miller95def091999-11-25 00:26:21 +1100699 va_start(args, fmt);
700 vsnprintf(buf, sizeof(buf), fmt, args);
701 va_end(args);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000702
Damien Miller95def091999-11-25 00:26:21 +1100703 /* Send the disconnect message to the other side, and wait for it to get sent. */
704 packet_start(SSH_MSG_DISCONNECT);
705 packet_put_string(buf, strlen(buf));
706 packet_send();
707 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000708
Damien Miller95def091999-11-25 00:26:21 +1100709 /* Stop listening for connections. */
710 channel_stop_listening();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000711
Damien Miller95def091999-11-25 00:26:21 +1100712 /* Close the connection. */
713 packet_close();
714
715 /* Display the error locally and exit. */
Damien Milleraae6c611999-12-06 11:47:28 +1100716 log("Disconnecting: %.100s", buf);
717 fatal_cleanup();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000718}
719
Damien Miller5428f641999-11-25 11:54:57 +1100720/* Checks if there is any buffered output, and tries to write some of the output. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000721
722void
723packet_write_poll()
724{
Damien Miller95def091999-11-25 00:26:21 +1100725 int len = buffer_len(&output);
726 if (len > 0) {
727 len = write(connection_out, buffer_ptr(&output), len);
728 if (len <= 0) {
729 if (errno == EAGAIN)
730 return;
731 else
732 fatal("Write failed: %.100s", strerror(errno));
733 }
734 buffer_consume(&output, len);
735 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000736}
737
Damien Miller5428f641999-11-25 11:54:57 +1100738/*
739 * Calls packet_write_poll repeatedly until all pending output data has been
740 * written.
741 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000742
743void
744packet_write_wait()
745{
Damien Miller95def091999-11-25 00:26:21 +1100746 packet_write_poll();
747 while (packet_have_data_to_write()) {
748 fd_set set;
749 FD_ZERO(&set);
750 FD_SET(connection_out, &set);
751 select(connection_out + 1, NULL, &set, NULL, NULL);
752 packet_write_poll();
753 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000754}
755
756/* Returns true if there is buffered data to write to the connection. */
757
758int
759packet_have_data_to_write()
760{
Damien Miller95def091999-11-25 00:26:21 +1100761 return buffer_len(&output) != 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000762}
763
764/* Returns true if there is not too much data to write to the connection. */
765
766int
767packet_not_very_much_data_to_write()
768{
Damien Miller95def091999-11-25 00:26:21 +1100769 if (interactive_mode)
770 return buffer_len(&output) < 16384;
771 else
772 return buffer_len(&output) < 128 * 1024;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000773}
774
775/* Informs that the current session is interactive. Sets IP flags for that. */
776
777void
778packet_set_interactive(int interactive, int keepalives)
779{
Damien Miller95def091999-11-25 00:26:21 +1100780 int on = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000781
Damien Miller95def091999-11-25 00:26:21 +1100782 /* Record that we are in interactive mode. */
783 interactive_mode = interactive;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000784
Damien Miller34132e52000-01-14 15:45:46 +1100785 /* Only set socket options if using a socket. */
786 if (!packet_connection_is_on_socket())
Damien Miller95def091999-11-25 00:26:21 +1100787 return;
Damien Miller95def091999-11-25 00:26:21 +1100788 if (keepalives) {
789 /* Set keepalives if requested. */
790 if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *) &on,
Damien Miller34132e52000-01-14 15:45:46 +1100791 sizeof(on)) < 0)
Damien Miller95def091999-11-25 00:26:21 +1100792 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
793 }
Damien Miller34132e52000-01-14 15:45:46 +1100794 /*
795 * IPTOS_LOWDELAY, TCP_NODELAY and IPTOS_THROUGHPUT are IPv4 only
796 */
797 if (!packet_connection_is_ipv4())
798 return;
Damien Miller95def091999-11-25 00:26:21 +1100799 if (interactive) {
Damien Miller5428f641999-11-25 11:54:57 +1100800 /*
801 * Set IP options for an interactive connection. Use
802 * IPTOS_LOWDELAY and TCP_NODELAY.
803 */
Damien Miller95def091999-11-25 00:26:21 +1100804 int lowdelay = IPTOS_LOWDELAY;
805 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &lowdelay,
Damien Miller34132e52000-01-14 15:45:46 +1100806 sizeof(lowdelay)) < 0)
Damien Miller95def091999-11-25 00:26:21 +1100807 error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
808 if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on,
Damien Miller34132e52000-01-14 15:45:46 +1100809 sizeof(on)) < 0)
Damien Miller95def091999-11-25 00:26:21 +1100810 error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
811 } else {
Damien Miller5428f641999-11-25 11:54:57 +1100812 /*
813 * Set IP options for a non-interactive connection. Use
814 * IPTOS_THROUGHPUT.
815 */
Damien Miller95def091999-11-25 00:26:21 +1100816 int throughput = IPTOS_THROUGHPUT;
817 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &throughput,
Damien Miller34132e52000-01-14 15:45:46 +1100818 sizeof(throughput)) < 0)
Damien Miller95def091999-11-25 00:26:21 +1100819 error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
820 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000821}
822
823/* Returns true if the current connection is interactive. */
824
825int
826packet_is_interactive()
827{
Damien Miller95def091999-11-25 00:26:21 +1100828 return interactive_mode;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000829}
Damien Miller6162d121999-11-21 13:23:52 +1100830
831int
832packet_set_maxsize(int s)
833{
Damien Miller95def091999-11-25 00:26:21 +1100834 static int called = 0;
835 if (called) {
836 log("packet_set_maxsize: called twice: old %d new %d", max_packet_size, s);
837 return -1;
838 }
839 if (s < 4 * 1024 || s > 1024 * 1024) {
840 log("packet_set_maxsize: bad size %d", s);
841 return -1;
842 }
843 log("packet_set_maxsize: setting to %d", s);
844 max_packet_size = s;
845 return s;
Damien Miller6162d121999-11-21 13:23:52 +1100846}