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.104 2003/04/01 10:22:21 markus Exp $");
41
42#include "xmalloc.h"
43#include "buffer.h"
44#include "packet.h"
45#include "bufaux.h"
46#include "crc32.h"
47#include "getput.h"
48
49#include "compress.h"

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

101/* Scratch buffer for packet compression/decompression. */
102static Buffer compression_buffer;
103static int compression_buffer_ready = 0;
104
105/* Flag indicating whether packet compression/decompression is enabled. */
106static int packet_compression = 0;
107
108/* default maximum packet size */
109int max_packet_size = 32768;
110
111/* Flag indicating whether this module has been initialized. */
112static int initialized = 0;
113
114/* Set to true if the connection is interactive. */
115static int interactive_mode = 0;
116
117/* Session key information for Encryption and MAC */
118Newkeys *newkeys[MODE_MAX];
119static u_int32_t read_seqnr = 0;
120static u_int32_t send_seqnr = 0;
121
122/* Session key for protocol v1 */
123static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
124static u_int ssh1_keylen;
125
126/* roundup current message to extra_pad bytes */
127static u_char extra_pad = 0;
128
129/*
130 * Sets the descriptors used for communication. Disables encryption until
131 * packet_set_encryption_key is called.
132 */
133void
134packet_set_connection(int fd_in, int fd_out)
135{
136 Cipher *none = cipher_by_name("none");

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

143 cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
144 newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
145 if (!initialized) {
146 initialized = 1;
147 buffer_init(&input);
148 buffer_init(&output);
149 buffer_init(&outgoing_packet);
150 buffer_init(&incoming_packet);
151 }
152 /* Kludge: arrange the close function to be called from fatal(). */
153 fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
154}
155
156/* Returns 1 if remote host is connected via socket, 0 if not. */
157
158int

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

244 if (mode == MODE_OUT)
245 cc = &send_context;
246 else
247 cc = &receive_context;
248
249 cipher_set_keyiv(cc, dat);
250}
251int
252packet_get_ssh1_cipher()
253{
254 return (cipher_get_number(receive_context.cipher));
255}
256
257
258u_int32_t
259packet_get_seqnr(int mode)
260{
261 return (mode == MODE_IN ? read_seqnr : send_seqnr);
262}
263
264void
265packet_set_seqnr(int mode, u_int32_t seqnr)
266{
267 if (mode == MODE_IN)
268 read_seqnr = seqnr;
269 else if (mode == MODE_OUT)
270 send_seqnr = seqnr;
271 else
272 fatal("packet_set_seqnr: bad mode %d", mode);
273}
274
275/* returns 1 if connection is via ipv4 */
276
277int
278packet_connection_is_ipv4(void)
279{
280 struct sockaddr_storage to;

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

557
558void
559set_newkeys(int mode)
560{
561 Enc *enc;
562 Mac *mac;
563 Comp *comp;
564 CipherContext *cc;
565 int encrypt;
566
567 debug2("set_newkeys: mode %d", mode);
568
569 if (mode == MODE_OUT) {
570 cc = &send_context;
571 encrypt = CIPHER_ENCRYPT;
572 } else {
573 cc = &receive_context;
574 encrypt = CIPHER_DECRYPT;
575 }
576 if (newkeys[mode] != NULL) {
577 debug("set_newkeys: rekeying");
578 cipher_cleanup(cc);
579 enc = &newkeys[mode]->enc;
580 mac = &newkeys[mode]->mac;
581 comp = &newkeys[mode]->comp;
582 memset(mac->key, 0, mac->key_len);

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

605 if (comp->type != 0 && comp->enabled == 0) {
606 packet_init_compression();
607 if (mode == MODE_OUT)
608 buffer_compress_init_send(6);
609 else
610 buffer_compress_init_recv();
611 comp->enabled = 1;
612 }
613}
614
615/*
616 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
617 */
618static void
619packet_send2(void)
620{
621 u_char type, *cp, *macbuf = NULL;
622 u_char padlen, pad;
623 u_int packet_length = 0;
624 u_int i, len;
625 u_int32_t rand = 0;
626 Enc *enc = NULL;
627 Mac *mac = NULL;

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

693 packet_length = buffer_len(&outgoing_packet) - 4;
694 cp = buffer_ptr(&outgoing_packet);
695 PUT_32BIT(cp, packet_length);
696 cp[4] = padlen;
697 DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
698
699 /* compute MAC over seqnr and packet(length fields, payload, padding) */
700 if (mac && mac->enabled) {
701 macbuf = mac_compute(mac, send_seqnr,
702 buffer_ptr(&outgoing_packet),
703 buffer_len(&outgoing_packet));
704 DBG(debug("done calc MAC out #%d", send_seqnr));
705 }
706 /* encrypt packet and append to output buffer. */
707 cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
708 cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
709 buffer_len(&outgoing_packet));
710 /* append unencrypted MAC */
711 if (mac && mac->enabled)
712 buffer_append(&output, (char *)macbuf, mac->mac_len);
713#ifdef PACKET_DEBUG
714 fprintf(stderr, "encrypted: ");
715 buffer_dump(&output);
716#endif
717 /* increment sequence number for outgoing packets */
718 if (++send_seqnr == 0)
719 log("outgoing seqnr wraps around");
720 buffer_clear(&outgoing_packet);
721
722 if (type == SSH2_MSG_NEWKEYS)
723 set_newkeys(MODE_OUT);
724}
725
726void
727packet_send(void)
728{
729 if (compat20)
730 packet_send2();
731 else
732 packet_send1();
733 DBG(debug("packet_send done"));

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

779 /* Wait for some data to arrive. */
780 while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
781 (errno == EAGAIN || errno == EINTR))
782 ;
783
784 /* Read data from the socket. */
785 len = read(connection_in, buf, sizeof(buf));
786 if (len == 0) {
787 log("Connection closed by %.200s", get_remote_ipaddr());
788 fatal_cleanup();
789 }
790 if (len < 0)
791 fatal("Read from socket failed: %.100s", strerror(errno));
792 /* Append it to the buffer. */
793 packet_process_incoming(buf, len);
794 }
795 /* NOTREACHED */

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

930 return SSH_MSG_NONE;
931 buffer_clear(&incoming_packet);
932 cp = buffer_append_space(&incoming_packet, block_size);
933 cipher_crypt(&receive_context, cp, buffer_ptr(&input),
934 block_size);
935 cp = buffer_ptr(&incoming_packet);
936 packet_length = GET_32BIT(cp);
937 if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
938 buffer_dump(&incoming_packet);
939 packet_disconnect("Bad packet length %u.", packet_length);
940 }
941 DBG(debug("input: packet len %u", packet_length+4));
942 buffer_consume(&input, block_size);
943 }
944 /* we have a partial packet of block_size bytes */
945 need = 4 + packet_length - block_size;
946 DBG(debug("partial packet %d, need %d, maclen %d", block_size,

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

961 cp = buffer_append_space(&incoming_packet, need);
962 cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
963 buffer_consume(&input, need);
964 /*
965 * compute MAC over seqnr and packet,
966 * increment sequence number for incoming packet
967 */
968 if (mac && mac->enabled) {
969 macbuf = mac_compute(mac, read_seqnr,
970 buffer_ptr(&incoming_packet),
971 buffer_len(&incoming_packet));
972 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
973 packet_disconnect("Corrupted MAC on input.");
974 DBG(debug("MAC #%d ok", read_seqnr));
975 buffer_consume(&input, mac->mac_len);
976 }
977 if (seqnr_p != NULL)
978 *seqnr_p = read_seqnr;
979 if (++read_seqnr == 0)
980 log("incoming seqnr wraps around");
981
982 /* get padlen */
983 cp = buffer_ptr(&incoming_packet);
984 padlen = cp[4];
985 DBG(debug("input: padlen %d", padlen));
986 if (padlen < 4)
987 packet_disconnect("Corrupted padlen %d on input.", padlen);
988

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

1037 debug("Remote: %.900s", msg);
1038 xfree(msg);
1039 msg = packet_get_string(NULL);
1040 xfree(msg);
1041 break;
1042 case SSH2_MSG_DISCONNECT:
1043 reason = packet_get_int();
1044 msg = packet_get_string(NULL);
1045 log("Received disconnect from %s: %u: %.400s",
1046 get_remote_ipaddr(), reason, msg);
1047 xfree(msg);
1048 fatal_cleanup();
1049 break;
1050 case SSH2_MSG_UNIMPLEMENTED:
1051 seqnr = packet_get_int();
1052 debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
1053 seqnr);

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

1063 break;
1064 case SSH_MSG_DEBUG:
1065 msg = packet_get_string(NULL);
1066 debug("Remote: %.900s", msg);
1067 xfree(msg);
1068 break;
1069 case SSH_MSG_DISCONNECT:
1070 msg = packet_get_string(NULL);
1071 log("Received disconnect from %s: %.400s",
1072 get_remote_ipaddr(), msg);
1073 fatal_cleanup();
1074 xfree(msg);
1075 break;
1076 default:
1077 if (type)
1078 DBG(debug("received packet type %d", type));
1079 return type;

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

1222 * Format the message. Note that the caller must make sure the
1223 * message is of limited size.
1224 */
1225 va_start(args, fmt);
1226 vsnprintf(buf, sizeof(buf), fmt, args);
1227 va_end(args);
1228
1229 /* Display the error locally */
1230 log("Disconnecting: %.100s", buf);
1231
1232 /* Send the disconnect message to the other side, and wait for it to get sent. */
1233 if (compat20) {
1234 packet_start(SSH2_MSG_DISCONNECT);
1235 packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
1236 packet_put_cstring(buf);
1237 packet_put_cstring("");
1238 } else {

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

1309packet_not_very_much_data_to_write(void)
1310{
1311 if (interactive_mode)
1312 return buffer_len(&output) < 16384;
1313 else
1314 return buffer_len(&output) < 128 * 1024;
1315}
1316
1317static void
1318packet_set_tos(int interactive)
1319{
1320 int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
1321
1322 if (!packet_connection_is_on_socket() ||
1323 !packet_connection_is_ipv4())
1324 return;
1325 if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1326 sizeof(tos)) < 0)
1327 error("setsockopt IP_TOS %d: %.100s:",
1328 tos, strerror(errno));
1329}
1330
1331/* Informs that the current session is interactive. Sets IP flags for that. */
1332
1333void
1334packet_set_interactive(int interactive)
1335{
1336 static int called = 0;
1337

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

1356/* Returns true if the current connection is interactive. */
1357
1358int
1359packet_is_interactive(void)
1360{
1361 return interactive_mode;
1362}
1363
1364int
1365packet_set_maxsize(int s)
1366{
1367 static int called = 0;
1368
1369 if (called) {
1370 log("packet_set_maxsize: called twice: old %d new %d",
1371 max_packet_size, s);
1372 return -1;
1373 }
1374 if (s < 4 * 1024 || s > 1024 * 1024) {
1375 log("packet_set_maxsize: bad size %d", s);
1376 return -1;
1377 }
1378 called = 1;
1379 debug("packet_set_maxsize: setting to %d", s);
1380 max_packet_size = s;
1381 return s;
1382}
1383

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

1409 packet_put_int(nbytes);
1410 for (i = 0; i < nbytes; i++) {
1411 if (i % 4 == 0)
1412 rand = arc4random();
1413 packet_put_char(rand & 0xff);
1414 rand >>= 8;
1415 }
1416}