blob: 6dfd492a14cbfa8ba788fe088a6b46b9b685620c [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 Millerfd7c9111999-11-08 16:15:55 +110018RCSID("$Id: packet.c,v 1.2 1999/11/08 05:15:55 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,
239 int cipher, int is_client)
240{
241 cipher_type = cipher;
242 if (cipher == SSH_CIPHER_RC4)
243 {
244 if (is_client)
245 { /* In client: use first half for receiving, second for sending. */
246 cipher_set_key(&receive_context, cipher, key, keylen / 2, 0);
247 cipher_set_key(&send_context, cipher, key + keylen / 2,
248 keylen / 2, 1);
249 }
250 else
251 { /* In server: use first half for sending, second for receiving. */
252 cipher_set_key(&receive_context, cipher, key + keylen / 2,
253 keylen / 2, 0);
254 cipher_set_key(&send_context, cipher, key, keylen / 2, 1);
255 }
256 }
257 else
258 {
259 /* All other ciphers use the same key in both directions for now. */
260 cipher_set_key(&receive_context, cipher, key, keylen, 0);
261 cipher_set_key(&send_context, cipher, key, keylen, 1);
262 }
263}
264
265/* Starts constructing a packet to send. */
266
267void
268packet_start(int type)
269{
270 char buf[9];
271
272 buffer_clear(&outgoing_packet);
273 memset(buf, 0, 8);
274 buf[8] = type;
275 buffer_append(&outgoing_packet, buf, 9);
276}
277
278/* Appends a character to the packet data. */
279
280void
281packet_put_char(int value)
282{
283 char ch = value;
284 buffer_append(&outgoing_packet, &ch, 1);
285}
286
287/* Appends an integer to the packet data. */
288
289void
290packet_put_int(unsigned int value)
291{
292 buffer_put_int(&outgoing_packet, value);
293}
294
295/* Appends a string to packet data. */
296
297void
298packet_put_string(const char *buf, unsigned int len)
299{
300 buffer_put_string(&outgoing_packet, buf, len);
301}
302
303/* Appends an arbitrary precision integer to packet data. */
304
305void
306packet_put_bignum(BIGNUM *value)
307{
308 buffer_put_bignum(&outgoing_packet, value);
309}
310
311/* Finalizes and sends the packet. If the encryption key has been set,
312 encrypts the packet before sending. */
313
314void
315packet_send()
316{
317 char buf[8], *cp;
318 int i, padding, len;
319 unsigned int checksum;
320 u_int32_t rand = 0;
321
322 /* If using packet compression, compress the payload of the outgoing
323 packet. */
324 if (packet_compression)
325 {
326 buffer_clear(&compression_buffer);
327 buffer_consume(&outgoing_packet, 8); /* Skip padding. */
328 buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
329 buffer_compress(&outgoing_packet, &compression_buffer);
330 buffer_clear(&outgoing_packet);
331 buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
332 buffer_len(&compression_buffer));
333 }
334
335 /* Compute packet length without padding (add checksum, remove padding). */
336 len = buffer_len(&outgoing_packet) + 4 - 8;
337
338 /* Insert padding. */
339 padding = 8 - len % 8;
340 if (cipher_type != SSH_CIPHER_NONE)
341 {
342 cp = buffer_ptr(&outgoing_packet);
343 for (i = 0; i < padding; i++) {
344 if (i % 4 == 0)
345 rand = arc4random();
346 cp[7 - i] = rand & 0xff;
347 rand >>= 8;
348 }
349 }
350 buffer_consume(&outgoing_packet, 8 - padding);
351
352 /* Add check bytes. */
353 checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
354 buffer_len(&outgoing_packet));
355 PUT_32BIT(buf, checksum);
356 buffer_append(&outgoing_packet, buf, 4);
357
358#ifdef PACKET_DEBUG
359 fprintf(stderr, "packet_send plain: ");
360 buffer_dump(&outgoing_packet);
361#endif
362
363 /* Append to output. */
364 PUT_32BIT(buf, len);
365 buffer_append(&output, buf, 4);
366 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
367 packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
368 buffer_len(&outgoing_packet));
369
370#ifdef PACKET_DEBUG
371 fprintf(stderr, "encrypted: "); buffer_dump(&output);
372#endif
373
374 buffer_clear(&outgoing_packet);
375
376 /* Note that the packet is now only buffered in output. It won\'t be
377 actually sent until packet_write_wait or packet_write_poll is called. */
378}
379
380/* Waits until a packet has been received, and returns its type. Note that
381 no other data is processed until this returns, so this function should
382 not be used during the interactive session. */
383
384int
385packet_read(int *payload_len_ptr)
386{
387 int type, len;
388 fd_set set;
389 char buf[8192];
390
391 /* Since we are blocking, ensure that all written packets have been sent. */
392 packet_write_wait();
393
394 /* Stay in the loop until we have received a complete packet. */
395 for (;;)
396 {
397 /* Try to read a packet from the buffer. */
398 type = packet_read_poll(payload_len_ptr);
399 if (type == SSH_SMSG_SUCCESS
400 || type == SSH_SMSG_FAILURE
401 || type == SSH_CMSG_EOF
402 || type == SSH_CMSG_EXIT_CONFIRMATION)
403 packet_integrity_check(*payload_len_ptr, 0, type);
404 /* If we got a packet, return it. */
405 if (type != SSH_MSG_NONE)
406 return type;
407 /* Otherwise, wait for some data to arrive, add it to the buffer,
408 and try again. */
409 FD_ZERO(&set);
410 FD_SET(connection_in, &set);
411 /* Wait for some data to arrive. */
412 select(connection_in + 1, &set, NULL, NULL, NULL);
413 /* Read data from the socket. */
414 len = read(connection_in, buf, sizeof(buf));
415 if (len == 0)
416 fatal("Connection closed by remote host.");
417 if (len < 0)
418 fatal("Read from socket failed: %.100s", strerror(errno));
419 /* Append it to the buffer. */
420 packet_process_incoming(buf, len);
421 }
422 /*NOTREACHED*/
423}
424
425/* Waits until a packet has been received, verifies that its type matches
426 that given, and gives a fatal error and exits if there is a mismatch. */
427
428void
429packet_read_expect(int *payload_len_ptr, int expected_type)
430{
431 int type;
432
433 type = packet_read(payload_len_ptr);
434 if (type != expected_type)
435 packet_disconnect("Protocol error: expected packet type %d, got %d",
436 expected_type, type);
437}
438
439/* Checks if a full packet is available in the data received so far via
440 packet_process_incoming. If so, reads the packet; otherwise returns
441 SSH_MSG_NONE. This does not wait for data from the connection.
442
443 SSH_MSG_DISCONNECT is handled specially here. Also,
444 SSH_MSG_IGNORE messages are skipped by this function and are never returned
445 to higher levels.
446
447 The returned payload_len does include space consumed by:
448 Packet length
449 Padding
450 Packet type
451 Check bytes
452
453
454 */
455
456int
457packet_read_poll(int *payload_len_ptr)
458{
459 unsigned int len, padded_len;
460 unsigned char *ucp;
461 char buf[8], *cp;
462 unsigned int checksum, stored_checksum;
463
464 restart:
465
466 /* Check if input size is less than minimum packet size. */
467 if (buffer_len(&input) < 4 + 8)
468 return SSH_MSG_NONE;
469 /* Get length of incoming packet. */
470 ucp = (unsigned char *)buffer_ptr(&input);
471 len = GET_32BIT(ucp);
472 if (len < 1 + 2 + 2 || len > 256*1024)
473 packet_disconnect("Bad packet length %d.", len);
474 padded_len = (len + 8) & ~7;
475
476 /* Check if the packet has been entirely received. */
477 if (buffer_len(&input) < 4 + padded_len)
478 return SSH_MSG_NONE;
479
480 /* The entire packet is in buffer. */
481
482 /* Consume packet length. */
483 buffer_consume(&input, 4);
484
485 /* Copy data to incoming_packet. */
486 buffer_clear(&incoming_packet);
487 buffer_append_space(&incoming_packet, &cp, padded_len);
488 packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
489 buffer_consume(&input, padded_len);
490
491#ifdef PACKET_DEBUG
492 fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
493#endif
494
495 /* Compute packet checksum. */
496 checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
497 buffer_len(&incoming_packet) - 4);
498
499 /* Skip padding. */
500 buffer_consume(&incoming_packet, 8 - len % 8);
501
502 /* Test check bytes. */
Damien Millerfd7c9111999-11-08 16:15:55 +1100503
504 if (len != buffer_len(&incoming_packet))
505 packet_disconnect("packet_read_poll: len %d != buffer_len %d.",
506 len, buffer_len(&incoming_packet));
507
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000508 ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
509 stored_checksum = GET_32BIT(ucp);
510 if (checksum != stored_checksum)
511 packet_disconnect("Corrupted check bytes on input.");
512 buffer_consume_end(&incoming_packet, 4);
513
514 /* If using packet compression, decompress the packet. */
515 if (packet_compression)
516 {
517 buffer_clear(&compression_buffer);
518 buffer_uncompress(&incoming_packet, &compression_buffer);
519 buffer_clear(&incoming_packet);
520 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
521 buffer_len(&compression_buffer));
522 }
523
524 /* Get packet type. */
525 buffer_get(&incoming_packet, &buf[0], 1);
526
527 /* Return length of payload (without type field). */
528 *payload_len_ptr = buffer_len(&incoming_packet);
529
530 /* Handle disconnect message. */
531 if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
532 fatal("%.900s", packet_get_string(NULL));
533
534 /* Ignore ignore messages. */
535 if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
536 goto restart;
537
538 /* Send debug messages as debugging output. */
539 if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
540 {
541 debug("Remote: %.900s", packet_get_string(NULL));
542 goto restart;
543 }
544
545 /* Return type. */
546 return (unsigned char)buf[0];
547}
548
549/* Buffers the given amount of input characters. This is intended to be
550 used together with packet_read_poll. */
551
552void
553packet_process_incoming(const char *buf, unsigned int len)
554{
555 buffer_append(&input, buf, len);
556}
557
558/* Returns a character from the packet. */
559
560unsigned int
561packet_get_char()
562{
563 char ch;
564 buffer_get(&incoming_packet, &ch, 1);
565 return (unsigned char)ch;
566}
567
568/* Returns an integer from the packet data. */
569
570unsigned int
571packet_get_int()
572{
573 return buffer_get_int(&incoming_packet);
574}
575
576/* Returns an arbitrary precision integer from the packet data. The integer
577 must have been initialized before this call. */
578
579void
580packet_get_bignum(BIGNUM *value, int *length_ptr)
581{
582 *length_ptr = buffer_get_bignum(&incoming_packet, value);
583}
584
585/* Returns a string from the packet data. The string is allocated using
586 xmalloc; it is the responsibility of the calling program to free it when
587 no longer needed. The length_ptr argument may be NULL, or point to an
588 integer into which the length of the string is stored. */
589
590char
591*packet_get_string(unsigned int *length_ptr)
592{
593 return buffer_get_string(&incoming_packet, length_ptr);
594}
595
596/* Sends a diagnostic message from the server to the client. This message
597 can be sent at any time (but not while constructing another message).
598 The message is printed immediately, but only if the client is being
599 executed in verbose mode. These messages are primarily intended to
600 ease debugging authentication problems. The length of the formatted
601 message must not exceed 1024 bytes. This will automatically call
602 packet_write_wait. */
603
604void
605packet_send_debug(const char *fmt, ...)
606{
607 char buf[1024];
608 va_list args;
609
610 va_start(args, fmt);
611 vsnprintf(buf, sizeof(buf), fmt, args);
612 va_end(args);
613
614 packet_start(SSH_MSG_DEBUG);
615 packet_put_string(buf, strlen(buf));
616 packet_send();
617 packet_write_wait();
618}
619
620/* Logs the error plus constructs and sends a disconnect
621 packet, closes the connection, and exits. This function never returns.
622 The error message should not contain a newline. The length of the
623 formatted message must not exceed 1024 bytes. */
624
625void
626packet_disconnect(const char *fmt, ...)
627{
628 char buf[1024];
629 va_list args;
630 static int disconnecting = 0;
631 if (disconnecting) /* Guard against recursive invocations. */
632 fatal("packet_disconnect called recursively.");
633 disconnecting = 1;
634
635 /* Format the message. Note that the caller must make sure the message
636 is of limited size. */
637 va_start(args, fmt);
638 vsnprintf(buf, sizeof(buf), fmt, args);
639 va_end(args);
640
641 /* Send the disconnect message to the other side, and wait for it to get
642 sent. */
643 packet_start(SSH_MSG_DISCONNECT);
644 packet_put_string(buf, strlen(buf));
645 packet_send();
646 packet_write_wait();
647
648 /* Stop listening for connections. */
649 channel_stop_listening();
650
651 /* Close the connection. */
652 packet_close();
653
654 /* Display the error locally and exit. */
655 fatal("Local: %.100s", buf);
656}
657
658/* Checks if there is any buffered output, and tries to write some of the
659 output. */
660
661void
662packet_write_poll()
663{
664 int len = buffer_len(&output);
665 if (len > 0)
666 {
667 len = write(connection_out, buffer_ptr(&output), len);
668 if (len <= 0) {
669 if (errno == EAGAIN)
670 return;
671 else
672 fatal("Write failed: %.100s", strerror(errno));
673 }
674 buffer_consume(&output, len);
675 }
676}
677
678/* Calls packet_write_poll repeatedly until all pending output data has
679 been written. */
680
681void
682packet_write_wait()
683{
684 packet_write_poll();
685 while (packet_have_data_to_write())
686 {
687 fd_set set;
688 FD_ZERO(&set);
689 FD_SET(connection_out, &set);
690 select(connection_out + 1, NULL, &set, NULL, NULL);
691 packet_write_poll();
692 }
693}
694
695/* Returns true if there is buffered data to write to the connection. */
696
697int
698packet_have_data_to_write()
699{
700 return buffer_len(&output) != 0;
701}
702
703/* Returns true if there is not too much data to write to the connection. */
704
705int
706packet_not_very_much_data_to_write()
707{
708 if (interactive_mode)
709 return buffer_len(&output) < 16384;
710 else
711 return buffer_len(&output) < 128*1024;
712}
713
714/* Informs that the current session is interactive. Sets IP flags for that. */
715
716void
717packet_set_interactive(int interactive, int keepalives)
718{
719 int on = 1;
720
721 /* Record that we are in interactive mode. */
722 interactive_mode = interactive;
723
724 /* Only set socket options if using a socket (as indicated by the descriptors
725 being the same). */
726 if (connection_in != connection_out)
727 return;
728
729 if (keepalives)
730 {
731 /* Set keepalives if requested. */
732 if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
733 sizeof(on)) < 0)
734 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
735 }
736
737 if (interactive)
738 {
739 /* Set IP options for an interactive connection. Use IPTOS_LOWDELAY
740 and TCP_NODELAY. */
741 int lowdelay = IPTOS_LOWDELAY;
742 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay,
743 sizeof(lowdelay)) < 0)
744 error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
745 if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
746 sizeof(on)) < 0)
747 error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
748 }
749 else
750 {
751 /* Set IP options for a non-interactive connection. Use
752 IPTOS_THROUGHPUT. */
753 int throughput = IPTOS_THROUGHPUT;
754 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput,
755 sizeof(throughput)) < 0)
756 error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
757 }
758}
759
760/* Returns true if the current connection is interactive. */
761
762int
763packet_is_interactive()
764{
765 return interactive_mode;
766}