blob: 9c2a4f86e8ddcd880b3fe48d0d81fdf962034590 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
2
3packet.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Sat Mar 18 02:40:40 1995 ylo
11
12This file contains code implementing the packet protocol and communication
13with the other side. This same code is used both on client and server side.
14
15*/
16
17#include "includes.h"
Damien Miller7e8e8201999-11-16 13:37:16 +110018RCSID("$Id: packet.c,v 1.3 1999/11/16 02:37:16 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"
31
32/* This variable contains the file descriptors used for communicating with
33 the other side. connection_in is used for reading; connection_out
34 for writing. These can be the same descriptor, in which case it is
35 assumed to be a socket. */
36static int connection_in = -1;
37static int connection_out = -1;
38
39/* Cipher type. This value is only used to determine whether to pad the
40 packets with zeroes or random data. */
41static int cipher_type = SSH_CIPHER_NONE;
42
43/* Protocol flags for the remote side. */
44static unsigned int remote_protocol_flags = 0;
45
46/* Encryption context for receiving data. This is only used for decryption. */
47static CipherContext receive_context;
48/* Encryption coontext for sending data. This is only used for encryption. */
49static CipherContext send_context;
50
51/* Buffer for raw input data from the socket. */
52static Buffer input;
53
54/* Buffer for raw output data going to the socket. */
55static Buffer output;
56
57/* Buffer for the partial outgoing packet being constructed. */
58static Buffer outgoing_packet;
59
60/* Buffer for the incoming packet currently being processed. */
61static Buffer incoming_packet;
62
63/* Scratch buffer for packet compression/decompression. */
64static Buffer compression_buffer;
65
66/* Flag indicating whether packet compression/decompression is enabled. */
67static int packet_compression = 0;
68
69/* Flag indicating whether this module has been initialized. */
70static int initialized = 0;
71
72/* Set to true if the connection is interactive. */
73static int interactive_mode = 0;
74
75/* Sets the descriptors used for communication. Disables encryption until
76 packet_set_encryption_key is called. */
77
78void
79packet_set_connection(int fd_in, int fd_out)
80{
81 connection_in = fd_in;
82 connection_out = fd_out;
83 cipher_type = SSH_CIPHER_NONE;
84 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1);
85 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0);
86 if (!initialized)
87 {
88 initialized = 1;
89 buffer_init(&input);
90 buffer_init(&output);
91 buffer_init(&outgoing_packet);
92 buffer_init(&incoming_packet);
93 }
94
95 /* Kludge: arrange the close function to be called from fatal(). */
96 fatal_add_cleanup((void (*)(void *))packet_close, NULL);
97}
98
99/* Sets the connection into non-blocking mode. */
100
101void
102packet_set_nonblocking()
103{
104 /* Set the socket into non-blocking mode. */
105 if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
106 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
107
108 if (connection_out != connection_in)
109 {
110 if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
111 error("fcntl O_NONBLOCK: %.100s", strerror(errno));
112 }
113}
114
115/* Returns the socket used for reading. */
116
117int
118packet_get_connection_in()
119{
120 return connection_in;
121}
122
123/* Returns the descriptor used for writing. */
124
125int
126packet_get_connection_out()
127{
128 return connection_out;
129}
130
131/* Closes the connection and clears and frees internal data structures. */
132
133void
134packet_close()
135{
136 if (!initialized)
137 return;
138 initialized = 0;
139 if (connection_in == connection_out)
140 {
141 shutdown(connection_out, SHUT_RDWR);
142 close(connection_out);
143 }
144 else
145 {
146 close(connection_in);
147 close(connection_out);
148 }
149 buffer_free(&input);
150 buffer_free(&output);
151 buffer_free(&outgoing_packet);
152 buffer_free(&incoming_packet);
153 if (packet_compression)
154 {
155 buffer_free(&compression_buffer);
156 buffer_compress_uninit();
157 }
158}
159
160/* Sets remote side protocol flags. */
161
162void
163packet_set_protocol_flags(unsigned int protocol_flags)
164{
165 remote_protocol_flags = protocol_flags;
166 channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
167}
168
169/* Returns the remote protocol flags set earlier by the above function. */
170
171unsigned int
172packet_get_protocol_flags()
173{
174 return remote_protocol_flags;
175}
176
177/* Starts packet compression from the next packet on in both directions.
178 Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
179
180void
181packet_start_compression(int level)
182{
183 if (packet_compression)
184 fatal("Compression already enabled.");
185 packet_compression = 1;
186 buffer_init(&compression_buffer);
187 buffer_compress_init(level);
188}
189
190/* Encrypts the given number of bytes, copying from src to dest.
191 bytes is known to be a multiple of 8. */
192
193void
194packet_encrypt(CipherContext *cc, void *dest, void *src,
195 unsigned int bytes)
196{
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000197 cipher_encrypt(cc, dest, src, bytes);
198}
199
200/* Decrypts the given number of bytes, copying from src to dest.
201 bytes is known to be a multiple of 8. */
202
203void
204packet_decrypt(CipherContext *cc, void *dest, void *src,
205 unsigned int bytes)
206{
207 int i;
208
Damien Millerfd7c9111999-11-08 16:15:55 +1100209 if ((bytes % 8) != 0)
210 fatal("packet_decrypt: bad ciphertext length %d", bytes);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000211
212 /*
213 Cryptographic attack detector for ssh - Modifications for packet.c
214 (C)1998 CORE-SDI, Buenos Aires Argentina
215 Ariel Futoransky(futo@core-sdi.com)
216 */
217 switch (cc->type)
218 {
219 case SSH_CIPHER_NONE:
220 i = DEATTACK_OK;
221 break;
222 default:
223 i = detect_attack(src, bytes, NULL);
224 break;
225 }
226
227 if (i == DEATTACK_DETECTED)
228 packet_disconnect("crc32 compensation attack: network attack detected");
229
230 cipher_decrypt(cc, dest, src, bytes);
231}
232
233/* Causes any further packets to be encrypted using the given key. The same
234 key is used for both sending and reception. However, both directions
235 are encrypted independently of each other. */
236
237void
238packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
Damien Miller7e8e8201999-11-16 13:37:16 +1100239 int cipher)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000240{
Damien Miller7e8e8201999-11-16 13:37:16 +1100241 /* All other ciphers use the same key in both directions for now. */
242 cipher_set_key(&receive_context, cipher, key, keylen, 0);
243 cipher_set_key(&send_context, cipher, key, keylen, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000244}
245
246/* Starts constructing a packet to send. */
247
248void
249packet_start(int type)
250{
251 char buf[9];
252
253 buffer_clear(&outgoing_packet);
254 memset(buf, 0, 8);
255 buf[8] = type;
256 buffer_append(&outgoing_packet, buf, 9);
257}
258
259/* Appends a character to the packet data. */
260
261void
262packet_put_char(int value)
263{
264 char ch = value;
265 buffer_append(&outgoing_packet, &ch, 1);
266}
267
268/* Appends an integer to the packet data. */
269
270void
271packet_put_int(unsigned int value)
272{
273 buffer_put_int(&outgoing_packet, value);
274}
275
276/* Appends a string to packet data. */
277
278void
279packet_put_string(const char *buf, unsigned int len)
280{
281 buffer_put_string(&outgoing_packet, buf, len);
282}
283
284/* Appends an arbitrary precision integer to packet data. */
285
286void
287packet_put_bignum(BIGNUM *value)
288{
289 buffer_put_bignum(&outgoing_packet, value);
290}
291
292/* Finalizes and sends the packet. If the encryption key has been set,
293 encrypts the packet before sending. */
294
295void
296packet_send()
297{
298 char buf[8], *cp;
299 int i, padding, len;
300 unsigned int checksum;
301 u_int32_t rand = 0;
302
303 /* If using packet compression, compress the payload of the outgoing
304 packet. */
305 if (packet_compression)
306 {
307 buffer_clear(&compression_buffer);
308 buffer_consume(&outgoing_packet, 8); /* Skip padding. */
309 buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
310 buffer_compress(&outgoing_packet, &compression_buffer);
311 buffer_clear(&outgoing_packet);
312 buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
313 buffer_len(&compression_buffer));
314 }
315
316 /* Compute packet length without padding (add checksum, remove padding). */
317 len = buffer_len(&outgoing_packet) + 4 - 8;
318
319 /* Insert padding. */
320 padding = 8 - len % 8;
321 if (cipher_type != SSH_CIPHER_NONE)
322 {
323 cp = buffer_ptr(&outgoing_packet);
324 for (i = 0; i < padding; i++) {
325 if (i % 4 == 0)
326 rand = arc4random();
327 cp[7 - i] = rand & 0xff;
328 rand >>= 8;
329 }
330 }
331 buffer_consume(&outgoing_packet, 8 - padding);
332
333 /* Add check bytes. */
334 checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
335 buffer_len(&outgoing_packet));
336 PUT_32BIT(buf, checksum);
337 buffer_append(&outgoing_packet, buf, 4);
338
339#ifdef PACKET_DEBUG
340 fprintf(stderr, "packet_send plain: ");
341 buffer_dump(&outgoing_packet);
342#endif
343
344 /* Append to output. */
345 PUT_32BIT(buf, len);
346 buffer_append(&output, buf, 4);
347 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
348 packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
349 buffer_len(&outgoing_packet));
350
351#ifdef PACKET_DEBUG
352 fprintf(stderr, "encrypted: "); buffer_dump(&output);
353#endif
354
355 buffer_clear(&outgoing_packet);
356
357 /* Note that the packet is now only buffered in output. It won\'t be
358 actually sent until packet_write_wait or packet_write_poll is called. */
359}
360
361/* Waits until a packet has been received, and returns its type. Note that
362 no other data is processed until this returns, so this function should
363 not be used during the interactive session. */
364
365int
366packet_read(int *payload_len_ptr)
367{
368 int type, len;
369 fd_set set;
370 char buf[8192];
371
372 /* Since we are blocking, ensure that all written packets have been sent. */
373 packet_write_wait();
374
375 /* Stay in the loop until we have received a complete packet. */
376 for (;;)
377 {
378 /* Try to read a packet from the buffer. */
379 type = packet_read_poll(payload_len_ptr);
380 if (type == SSH_SMSG_SUCCESS
381 || type == SSH_SMSG_FAILURE
382 || type == SSH_CMSG_EOF
383 || type == SSH_CMSG_EXIT_CONFIRMATION)
384 packet_integrity_check(*payload_len_ptr, 0, type);
385 /* If we got a packet, return it. */
386 if (type != SSH_MSG_NONE)
387 return type;
388 /* Otherwise, wait for some data to arrive, add it to the buffer,
389 and try again. */
390 FD_ZERO(&set);
391 FD_SET(connection_in, &set);
392 /* Wait for some data to arrive. */
393 select(connection_in + 1, &set, NULL, NULL, NULL);
394 /* Read data from the socket. */
395 len = read(connection_in, buf, sizeof(buf));
396 if (len == 0)
397 fatal("Connection closed by remote host.");
398 if (len < 0)
399 fatal("Read from socket failed: %.100s", strerror(errno));
400 /* Append it to the buffer. */
401 packet_process_incoming(buf, len);
402 }
403 /*NOTREACHED*/
404}
405
406/* Waits until a packet has been received, verifies that its type matches
407 that given, and gives a fatal error and exits if there is a mismatch. */
408
409void
410packet_read_expect(int *payload_len_ptr, int expected_type)
411{
412 int type;
413
414 type = packet_read(payload_len_ptr);
415 if (type != expected_type)
416 packet_disconnect("Protocol error: expected packet type %d, got %d",
417 expected_type, type);
418}
419
420/* Checks if a full packet is available in the data received so far via
421 packet_process_incoming. If so, reads the packet; otherwise returns
422 SSH_MSG_NONE. This does not wait for data from the connection.
423
424 SSH_MSG_DISCONNECT is handled specially here. Also,
425 SSH_MSG_IGNORE messages are skipped by this function and are never returned
426 to higher levels.
427
428 The returned payload_len does include space consumed by:
429 Packet length
430 Padding
431 Packet type
432 Check bytes
433
434
435 */
436
437int
438packet_read_poll(int *payload_len_ptr)
439{
440 unsigned int len, padded_len;
441 unsigned char *ucp;
442 char buf[8], *cp;
443 unsigned int checksum, stored_checksum;
444
445 restart:
446
447 /* Check if input size is less than minimum packet size. */
448 if (buffer_len(&input) < 4 + 8)
449 return SSH_MSG_NONE;
450 /* Get length of incoming packet. */
451 ucp = (unsigned char *)buffer_ptr(&input);
452 len = GET_32BIT(ucp);
453 if (len < 1 + 2 + 2 || len > 256*1024)
454 packet_disconnect("Bad packet length %d.", len);
455 padded_len = (len + 8) & ~7;
456
457 /* Check if the packet has been entirely received. */
458 if (buffer_len(&input) < 4 + padded_len)
459 return SSH_MSG_NONE;
460
461 /* The entire packet is in buffer. */
462
463 /* Consume packet length. */
464 buffer_consume(&input, 4);
465
466 /* Copy data to incoming_packet. */
467 buffer_clear(&incoming_packet);
468 buffer_append_space(&incoming_packet, &cp, padded_len);
469 packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
470 buffer_consume(&input, padded_len);
471
472#ifdef PACKET_DEBUG
473 fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
474#endif
475
476 /* Compute packet checksum. */
477 checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
478 buffer_len(&incoming_packet) - 4);
479
480 /* Skip padding. */
481 buffer_consume(&incoming_packet, 8 - len % 8);
482
483 /* Test check bytes. */
Damien Millerfd7c9111999-11-08 16:15:55 +1100484
485 if (len != buffer_len(&incoming_packet))
486 packet_disconnect("packet_read_poll: len %d != buffer_len %d.",
487 len, buffer_len(&incoming_packet));
488
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000489 ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
490 stored_checksum = GET_32BIT(ucp);
491 if (checksum != stored_checksum)
492 packet_disconnect("Corrupted check bytes on input.");
493 buffer_consume_end(&incoming_packet, 4);
494
495 /* If using packet compression, decompress the packet. */
496 if (packet_compression)
497 {
498 buffer_clear(&compression_buffer);
499 buffer_uncompress(&incoming_packet, &compression_buffer);
500 buffer_clear(&incoming_packet);
501 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
502 buffer_len(&compression_buffer));
503 }
504
505 /* Get packet type. */
506 buffer_get(&incoming_packet, &buf[0], 1);
507
508 /* Return length of payload (without type field). */
509 *payload_len_ptr = buffer_len(&incoming_packet);
510
511 /* Handle disconnect message. */
512 if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
513 fatal("%.900s", packet_get_string(NULL));
514
515 /* Ignore ignore messages. */
516 if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
517 goto restart;
518
519 /* Send debug messages as debugging output. */
520 if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
521 {
522 debug("Remote: %.900s", packet_get_string(NULL));
523 goto restart;
524 }
525
526 /* Return type. */
527 return (unsigned char)buf[0];
528}
529
530/* Buffers the given amount of input characters. This is intended to be
531 used together with packet_read_poll. */
532
533void
534packet_process_incoming(const char *buf, unsigned int len)
535{
536 buffer_append(&input, buf, len);
537}
538
539/* Returns a character from the packet. */
540
541unsigned int
542packet_get_char()
543{
544 char ch;
545 buffer_get(&incoming_packet, &ch, 1);
546 return (unsigned char)ch;
547}
548
549/* Returns an integer from the packet data. */
550
551unsigned int
552packet_get_int()
553{
554 return buffer_get_int(&incoming_packet);
555}
556
557/* Returns an arbitrary precision integer from the packet data. The integer
558 must have been initialized before this call. */
559
560void
561packet_get_bignum(BIGNUM *value, int *length_ptr)
562{
563 *length_ptr = buffer_get_bignum(&incoming_packet, value);
564}
565
566/* Returns a string from the packet data. The string is allocated using
567 xmalloc; it is the responsibility of the calling program to free it when
568 no longer needed. The length_ptr argument may be NULL, or point to an
569 integer into which the length of the string is stored. */
570
571char
572*packet_get_string(unsigned int *length_ptr)
573{
574 return buffer_get_string(&incoming_packet, length_ptr);
575}
576
577/* Sends a diagnostic message from the server to the client. This message
578 can be sent at any time (but not while constructing another message).
579 The message is printed immediately, but only if the client is being
580 executed in verbose mode. These messages are primarily intended to
581 ease debugging authentication problems. The length of the formatted
582 message must not exceed 1024 bytes. This will automatically call
583 packet_write_wait. */
584
585void
586packet_send_debug(const char *fmt, ...)
587{
588 char buf[1024];
589 va_list args;
590
591 va_start(args, fmt);
592 vsnprintf(buf, sizeof(buf), fmt, args);
593 va_end(args);
594
595 packet_start(SSH_MSG_DEBUG);
596 packet_put_string(buf, strlen(buf));
597 packet_send();
598 packet_write_wait();
599}
600
601/* Logs the error plus constructs and sends a disconnect
602 packet, closes the connection, and exits. This function never returns.
603 The error message should not contain a newline. The length of the
604 formatted message must not exceed 1024 bytes. */
605
606void
607packet_disconnect(const char *fmt, ...)
608{
609 char buf[1024];
610 va_list args;
611 static int disconnecting = 0;
612 if (disconnecting) /* Guard against recursive invocations. */
613 fatal("packet_disconnect called recursively.");
614 disconnecting = 1;
615
616 /* Format the message. Note that the caller must make sure the message
617 is of limited size. */
618 va_start(args, fmt);
619 vsnprintf(buf, sizeof(buf), fmt, args);
620 va_end(args);
621
622 /* Send the disconnect message to the other side, and wait for it to get
623 sent. */
624 packet_start(SSH_MSG_DISCONNECT);
625 packet_put_string(buf, strlen(buf));
626 packet_send();
627 packet_write_wait();
628
629 /* Stop listening for connections. */
630 channel_stop_listening();
631
632 /* Close the connection. */
633 packet_close();
634
635 /* Display the error locally and exit. */
636 fatal("Local: %.100s", buf);
637}
638
639/* Checks if there is any buffered output, and tries to write some of the
640 output. */
641
642void
643packet_write_poll()
644{
645 int len = buffer_len(&output);
646 if (len > 0)
647 {
648 len = write(connection_out, buffer_ptr(&output), len);
649 if (len <= 0) {
650 if (errno == EAGAIN)
651 return;
652 else
653 fatal("Write failed: %.100s", strerror(errno));
654 }
655 buffer_consume(&output, len);
656 }
657}
658
659/* Calls packet_write_poll repeatedly until all pending output data has
660 been written. */
661
662void
663packet_write_wait()
664{
665 packet_write_poll();
666 while (packet_have_data_to_write())
667 {
668 fd_set set;
669 FD_ZERO(&set);
670 FD_SET(connection_out, &set);
671 select(connection_out + 1, NULL, &set, NULL, NULL);
672 packet_write_poll();
673 }
674}
675
676/* Returns true if there is buffered data to write to the connection. */
677
678int
679packet_have_data_to_write()
680{
681 return buffer_len(&output) != 0;
682}
683
684/* Returns true if there is not too much data to write to the connection. */
685
686int
687packet_not_very_much_data_to_write()
688{
689 if (interactive_mode)
690 return buffer_len(&output) < 16384;
691 else
692 return buffer_len(&output) < 128*1024;
693}
694
695/* Informs that the current session is interactive. Sets IP flags for that. */
696
697void
698packet_set_interactive(int interactive, int keepalives)
699{
700 int on = 1;
701
702 /* Record that we are in interactive mode. */
703 interactive_mode = interactive;
704
705 /* Only set socket options if using a socket (as indicated by the descriptors
706 being the same). */
707 if (connection_in != connection_out)
708 return;
709
710 if (keepalives)
711 {
712 /* Set keepalives if requested. */
713 if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
714 sizeof(on)) < 0)
715 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
716 }
717
718 if (interactive)
719 {
720 /* Set IP options for an interactive connection. Use IPTOS_LOWDELAY
721 and TCP_NODELAY. */
722 int lowdelay = IPTOS_LOWDELAY;
723 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay,
724 sizeof(lowdelay)) < 0)
725 error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
726 if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
727 sizeof(on)) < 0)
728 error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
729 }
730 else
731 {
732 /* Set IP options for a non-interactive connection. Use
733 IPTOS_THROUGHPUT. */
734 int throughput = IPTOS_THROUGHPUT;
735 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput,
736 sizeof(throughput)) < 0)
737 error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
738 }
739}
740
741/* Returns true if the current connection is interactive. */
742
743int
744packet_is_interactive()
745{
746 return interactive_mode;
747}