Deleted Added
sdiff udiff text old ( 116791 ) new ( 124208 )
full compact
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 * This file contains code implementing the packet protocol and communication
6 * with the other side. This same code is used both on client and server side.
7 *
8 * As far as I am concerned, the code I have written for this software

--- 23 unchanged lines hidden (view full) ---

32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "includes.h"
40RCSID("$OpenBSD: packet.c,v 1.110 2003/09/19 09:02:02 markus Exp $");
41
42#include "openbsd-compat/sys-queue.h"
43
44#include "xmalloc.h"
45#include "buffer.h"
46#include "packet.h"
47#include "bufaux.h"
48#include "crc32.h"
49#include "getput.h"
50
51#include "compress.h"

--- 51 unchanged lines hidden (view full) ---

103/* Scratch buffer for packet compression/decompression. */
104static Buffer compression_buffer;
105static int compression_buffer_ready = 0;
106
107/* Flag indicating whether packet compression/decompression is enabled. */
108static int packet_compression = 0;
109
110/* default maximum packet size */
111u_int max_packet_size = 32768;
112
113/* Flag indicating whether this module has been initialized. */
114static int initialized = 0;
115
116/* Set to true if the connection is interactive. */
117static int interactive_mode = 0;
118
119/* Session key information for Encryption and MAC */
120Newkeys *newkeys[MODE_MAX];
121static struct packet_state {
122 u_int32_t seqnr;
123 u_int32_t packets;
124 u_int64_t blocks;
125} p_read, p_send;
126
127static u_int64_t max_blocks_in, max_blocks_out;
128static u_int32_t rekey_limit;
129
130/* Session key for protocol v1 */
131static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
132static u_int ssh1_keylen;
133
134/* roundup current message to extra_pad bytes */
135static u_char extra_pad = 0;
136
137struct packet {
138 TAILQ_ENTRY(packet) next;
139 u_char type;
140 Buffer payload;
141};
142TAILQ_HEAD(, packet) outgoing;
143
144/*
145 * Sets the descriptors used for communication. Disables encryption until
146 * packet_set_encryption_key is called.
147 */
148void
149packet_set_connection(int fd_in, int fd_out)
150{
151 Cipher *none = cipher_by_name("none");

--- 6 unchanged lines hidden (view full) ---

158 cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
159 newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
160 if (!initialized) {
161 initialized = 1;
162 buffer_init(&input);
163 buffer_init(&output);
164 buffer_init(&outgoing_packet);
165 buffer_init(&incoming_packet);
166 TAILQ_INIT(&outgoing);
167 }
168 /* Kludge: arrange the close function to be called from fatal(). */
169 fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
170}
171
172/* Returns 1 if remote host is connected via socket, 0 if not. */
173
174int

--- 85 unchanged lines hidden (view full) ---

260 if (mode == MODE_OUT)
261 cc = &send_context;
262 else
263 cc = &receive_context;
264
265 cipher_set_keyiv(cc, dat);
266}
267int
268packet_get_ssh1_cipher(void)
269{
270 return (cipher_get_number(receive_context.cipher));
271}
272
273void
274packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
275{
276 struct packet_state *state;
277
278 state = (mode == MODE_IN) ? &p_read : &p_send;
279 *seqnr = state->seqnr;
280 *blocks = state->blocks;
281 *packets = state->packets;
282}
283
284void
285packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
286{
287 struct packet_state *state;
288
289 state = (mode == MODE_IN) ? &p_read : &p_send;
290 state->seqnr = seqnr;
291 state->blocks = blocks;
292 state->packets = packets;
293}
294
295/* returns 1 if connection is via ipv4 */
296
297int
298packet_connection_is_ipv4(void)
299{
300 struct sockaddr_storage to;

--- 276 unchanged lines hidden (view full) ---

577
578void
579set_newkeys(int mode)
580{
581 Enc *enc;
582 Mac *mac;
583 Comp *comp;
584 CipherContext *cc;
585 u_int64_t *max_blocks;
586 int encrypt;
587
588 debug2("set_newkeys: mode %d", mode);
589
590 if (mode == MODE_OUT) {
591 cc = &send_context;
592 encrypt = CIPHER_ENCRYPT;
593 p_send.packets = p_send.blocks = 0;
594 max_blocks = &max_blocks_out;
595 } else {
596 cc = &receive_context;
597 encrypt = CIPHER_DECRYPT;
598 p_read.packets = p_read.blocks = 0;
599 max_blocks = &max_blocks_in;
600 }
601 if (newkeys[mode] != NULL) {
602 debug("set_newkeys: rekeying");
603 cipher_cleanup(cc);
604 enc = &newkeys[mode]->enc;
605 mac = &newkeys[mode]->mac;
606 comp = &newkeys[mode]->comp;
607 memset(mac->key, 0, mac->key_len);

--- 22 unchanged lines hidden (view full) ---

630 if (comp->type != 0 && comp->enabled == 0) {
631 packet_init_compression();
632 if (mode == MODE_OUT)
633 buffer_compress_init_send(6);
634 else
635 buffer_compress_init_recv();
636 comp->enabled = 1;
637 }
638 /*
639 * The 2^(blocksize*2) limit is too expensive for 3DES,
640 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
641 */
642 if (enc->block_size >= 16)
643 *max_blocks = (u_int64_t)1 << (enc->block_size*2);
644 else
645 *max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
646 if (rekey_limit)
647 *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
648}
649
650/*
651 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
652 */
653static void
654packet_send2_wrapped(void)
655{
656 u_char type, *cp, *macbuf = NULL;
657 u_char padlen, pad;
658 u_int packet_length = 0;
659 u_int i, len;
660 u_int32_t rand = 0;
661 Enc *enc = NULL;
662 Mac *mac = NULL;

--- 65 unchanged lines hidden (view full) ---

728 packet_length = buffer_len(&outgoing_packet) - 4;
729 cp = buffer_ptr(&outgoing_packet);
730 PUT_32BIT(cp, packet_length);
731 cp[4] = padlen;
732 DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
733
734 /* compute MAC over seqnr and packet(length fields, payload, padding) */
735 if (mac && mac->enabled) {
736 macbuf = mac_compute(mac, p_send.seqnr,
737 buffer_ptr(&outgoing_packet),
738 buffer_len(&outgoing_packet));
739 DBG(debug("done calc MAC out #%d", p_send.seqnr));
740 }
741 /* encrypt packet and append to output buffer. */
742 cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
743 cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
744 buffer_len(&outgoing_packet));
745 /* append unencrypted MAC */
746 if (mac && mac->enabled)
747 buffer_append(&output, (char *)macbuf, mac->mac_len);
748#ifdef PACKET_DEBUG
749 fprintf(stderr, "encrypted: ");
750 buffer_dump(&output);
751#endif
752 /* increment sequence number for outgoing packets */
753 if (++p_send.seqnr == 0)
754 logit("outgoing seqnr wraps around");
755 if (++p_send.packets == 0)
756 if (!(datafellows & SSH_BUG_NOREKEY))
757 fatal("XXX too many packets with same key");
758 p_send.blocks += (packet_length + 4) / block_size;
759 buffer_clear(&outgoing_packet);
760
761 if (type == SSH2_MSG_NEWKEYS)
762 set_newkeys(MODE_OUT);
763}
764
765static void
766packet_send2(void)
767{
768 static int rekeying = 0;
769 struct packet *p;
770 u_char type, *cp;
771
772 cp = buffer_ptr(&outgoing_packet);
773 type = cp[5];
774
775 /* during rekeying we can only send key exchange messages */
776 if (rekeying) {
777 if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
778 (type <= SSH2_MSG_TRANSPORT_MAX))) {
779 debug("enqueue packet: %u", type);
780 p = xmalloc(sizeof(*p));
781 p->type = type;
782 memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
783 buffer_init(&outgoing_packet);
784 TAILQ_INSERT_TAIL(&outgoing, p, next);
785 return;
786 }
787 }
788
789 /* rekeying starts with sending KEXINIT */
790 if (type == SSH2_MSG_KEXINIT)
791 rekeying = 1;
792
793 packet_send2_wrapped();
794
795 /* after a NEWKEYS message we can send the complete queue */
796 if (type == SSH2_MSG_NEWKEYS) {
797 rekeying = 0;
798 while ((p = TAILQ_FIRST(&outgoing))) {
799 type = p->type;
800 debug("dequeue packet: %u", type);
801 buffer_free(&outgoing_packet);
802 memcpy(&outgoing_packet, &p->payload,
803 sizeof(Buffer));
804 TAILQ_REMOVE(&outgoing, p, next);
805 xfree(p);
806 packet_send2_wrapped();
807 }
808 }
809}
810
811void
812packet_send(void)
813{
814 if (compat20)
815 packet_send2();
816 else
817 packet_send1();
818 DBG(debug("packet_send done"));

--- 45 unchanged lines hidden (view full) ---

864 /* Wait for some data to arrive. */
865 while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
866 (errno == EAGAIN || errno == EINTR))
867 ;
868
869 /* Read data from the socket. */
870 len = read(connection_in, buf, sizeof(buf));
871 if (len == 0) {
872 logit("Connection closed by %.200s", get_remote_ipaddr());
873 fatal_cleanup();
874 }
875 if (len < 0)
876 fatal("Read from socket failed: %.100s", strerror(errno));
877 /* Append it to the buffer. */
878 packet_process_incoming(buf, len);
879 }
880 /* NOTREACHED */

--- 134 unchanged lines hidden (view full) ---

1015 return SSH_MSG_NONE;
1016 buffer_clear(&incoming_packet);
1017 cp = buffer_append_space(&incoming_packet, block_size);
1018 cipher_crypt(&receive_context, cp, buffer_ptr(&input),
1019 block_size);
1020 cp = buffer_ptr(&incoming_packet);
1021 packet_length = GET_32BIT(cp);
1022 if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
1023#ifdef PACKET_DEBUG
1024 buffer_dump(&incoming_packet);
1025#endif
1026 packet_disconnect("Bad packet length %u.", packet_length);
1027 }
1028 DBG(debug("input: packet len %u", packet_length+4));
1029 buffer_consume(&input, block_size);
1030 }
1031 /* we have a partial packet of block_size bytes */
1032 need = 4 + packet_length - block_size;
1033 DBG(debug("partial packet %d, need %d, maclen %d", block_size,

--- 14 unchanged lines hidden (view full) ---

1048 cp = buffer_append_space(&incoming_packet, need);
1049 cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
1050 buffer_consume(&input, need);
1051 /*
1052 * compute MAC over seqnr and packet,
1053 * increment sequence number for incoming packet
1054 */
1055 if (mac && mac->enabled) {
1056 macbuf = mac_compute(mac, p_read.seqnr,
1057 buffer_ptr(&incoming_packet),
1058 buffer_len(&incoming_packet));
1059 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
1060 packet_disconnect("Corrupted MAC on input.");
1061 DBG(debug("MAC #%d ok", p_read.seqnr));
1062 buffer_consume(&input, mac->mac_len);
1063 }
1064 if (seqnr_p != NULL)
1065 *seqnr_p = p_read.seqnr;
1066 if (++p_read.seqnr == 0)
1067 logit("incoming seqnr wraps around");
1068 if (++p_read.packets == 0)
1069 if (!(datafellows & SSH_BUG_NOREKEY))
1070 fatal("XXX too many packets with same key");
1071 p_read.blocks += (packet_length + 4) / block_size;
1072
1073 /* get padlen */
1074 cp = buffer_ptr(&incoming_packet);
1075 padlen = cp[4];
1076 DBG(debug("input: padlen %d", padlen));
1077 if (padlen < 4)
1078 packet_disconnect("Corrupted padlen %d on input.", padlen);
1079

--- 48 unchanged lines hidden (view full) ---

1128 debug("Remote: %.900s", msg);
1129 xfree(msg);
1130 msg = packet_get_string(NULL);
1131 xfree(msg);
1132 break;
1133 case SSH2_MSG_DISCONNECT:
1134 reason = packet_get_int();
1135 msg = packet_get_string(NULL);
1136 logit("Received disconnect from %s: %u: %.400s",
1137 get_remote_ipaddr(), reason, msg);
1138 xfree(msg);
1139 fatal_cleanup();
1140 break;
1141 case SSH2_MSG_UNIMPLEMENTED:
1142 seqnr = packet_get_int();
1143 debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
1144 seqnr);

--- 9 unchanged lines hidden (view full) ---

1154 break;
1155 case SSH_MSG_DEBUG:
1156 msg = packet_get_string(NULL);
1157 debug("Remote: %.900s", msg);
1158 xfree(msg);
1159 break;
1160 case SSH_MSG_DISCONNECT:
1161 msg = packet_get_string(NULL);
1162 logit("Received disconnect from %s: %.400s",
1163 get_remote_ipaddr(), msg);
1164 fatal_cleanup();
1165 xfree(msg);
1166 break;
1167 default:
1168 if (type)
1169 DBG(debug("received packet type %d", type));
1170 return type;

--- 142 unchanged lines hidden (view full) ---

1313 * Format the message. Note that the caller must make sure the
1314 * message is of limited size.
1315 */
1316 va_start(args, fmt);
1317 vsnprintf(buf, sizeof(buf), fmt, args);
1318 va_end(args);
1319
1320 /* Display the error locally */
1321 logit("Disconnecting: %.100s", buf);
1322
1323 /* Send the disconnect message to the other side, and wait for it to get sent. */
1324 if (compat20) {
1325 packet_start(SSH2_MSG_DISCONNECT);
1326 packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
1327 packet_put_cstring(buf);
1328 packet_put_cstring("");
1329 } else {

--- 70 unchanged lines hidden (view full) ---

1400packet_not_very_much_data_to_write(void)
1401{
1402 if (interactive_mode)
1403 return buffer_len(&output) < 16384;
1404 else
1405 return buffer_len(&output) < 128 * 1024;
1406}
1407
1408
1409#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1410static void
1411packet_set_tos(int interactive)
1412{
1413 int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
1414
1415 if (!packet_connection_is_on_socket() ||
1416 !packet_connection_is_ipv4())
1417 return;
1418 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1419 sizeof(tos)) < 0)
1420 error("setsockopt IP_TOS %d: %.100s:",
1421 tos, strerror(errno));
1422}
1423#endif
1424
1425/* Informs that the current session is interactive. Sets IP flags for that. */
1426
1427void
1428packet_set_interactive(int interactive)
1429{
1430 static int called = 0;
1431

--- 18 unchanged lines hidden (view full) ---

1450/* Returns true if the current connection is interactive. */
1451
1452int
1453packet_is_interactive(void)
1454{
1455 return interactive_mode;
1456}
1457
1458u_int
1459packet_set_maxsize(u_int s)
1460{
1461 static int called = 0;
1462
1463 if (called) {
1464 logit("packet_set_maxsize: called twice: old %d new %d",
1465 max_packet_size, s);
1466 return -1;
1467 }
1468 if (s < 4 * 1024 || s > 1024 * 1024) {
1469 logit("packet_set_maxsize: bad size %d", s);
1470 return -1;
1471 }
1472 called = 1;
1473 debug("packet_set_maxsize: setting to %d", s);
1474 max_packet_size = s;
1475 return s;
1476}
1477

--- 25 unchanged lines hidden (view full) ---

1503 packet_put_int(nbytes);
1504 for (i = 0; i < nbytes; i++) {
1505 if (i % 4 == 0)
1506 rand = arc4random();
1507 packet_put_char(rand & 0xff);
1508 rand >>= 8;
1509 }
1510}
1511
1512#define MAX_PACKETS (1<<31)
1513int
1514packet_need_rekeying(void)
1515{
1516 if (datafellows & SSH_BUG_NOREKEY)
1517 return 0;
1518 return
1519 (p_send.packets > MAX_PACKETS) ||
1520 (p_read.packets > MAX_PACKETS) ||
1521 (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1522 (max_blocks_in && (p_read.blocks > max_blocks_in));
1523}
1524
1525void
1526packet_set_rekey_limit(u_int32_t bytes)
1527{
1528 rekey_limit = bytes;
1529}