packet.c revision 126274
157429Smarkm/*
257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
457429Smarkm *                    All rights reserved
557429Smarkm * This file contains code implementing the packet protocol and communication
657429Smarkm * with the other side.  This same code is used both on client and server side.
760573Skris *
865668Skris * As far as I am concerned, the code I have written for this software
965668Skris * can be used freely for any purpose.  Any derived versions of this
1065668Skris * software must be clearly marked as such, and if the derived work is
1165668Skris * incompatible with the protocol description in the RFC file, it must be
1265668Skris * called by a name other than "ssh" or "Secure Shell".
1365668Skris *
1465668Skris *
1560573Skris * SSH2 packet format added by Markus Friedl.
1692555Sdes * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
1760573Skris *
1865668Skris * Redistribution and use in source and binary forms, with or without
1965668Skris * modification, are permitted provided that the following conditions
2065668Skris * are met:
2165668Skris * 1. Redistributions of source code must retain the above copyright
2265668Skris *    notice, this list of conditions and the following disclaimer.
2365668Skris * 2. Redistributions in binary form must reproduce the above copyright
2465668Skris *    notice, this list of conditions and the following disclaimer in the
2565668Skris *    documentation and/or other materials provided with the distribution.
2665668Skris *
2765668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2865668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2965668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3065668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3165668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3265668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3365668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3465668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3565668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3665668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3757429Smarkm */
3857429Smarkm
3957429Smarkm#include "includes.h"
40126274SdesRCSID("$OpenBSD: packet.c,v 1.112 2003/09/23 20:17:11 markus Exp $");
4157429Smarkm
42124208Sdes#include "openbsd-compat/sys-queue.h"
43124208Sdes
4457429Smarkm#include "xmalloc.h"
4557429Smarkm#include "buffer.h"
4657429Smarkm#include "packet.h"
4757429Smarkm#include "bufaux.h"
4857429Smarkm#include "crc32.h"
4957429Smarkm#include "getput.h"
5057429Smarkm
5157429Smarkm#include "compress.h"
5257429Smarkm#include "deattack.h"
5360573Skris#include "channels.h"
5457429Smarkm
5560573Skris#include "compat.h"
5676259Sgreen#include "ssh1.h"
5760573Skris#include "ssh2.h"
5860573Skris
5969587Sgreen#include "cipher.h"
6060573Skris#include "kex.h"
6176259Sgreen#include "mac.h"
6276259Sgreen#include "log.h"
6376259Sgreen#include "canohost.h"
6492555Sdes#include "misc.h"
6598675Sdes#include "ssh.h"
6660573Skris
6760573Skris#ifdef PACKET_DEBUG
6860573Skris#define DBG(x) x
6960573Skris#else
7060573Skris#define DBG(x)
7160573Skris#endif
7260573Skris
7357429Smarkm/*
7457429Smarkm * This variable contains the file descriptors used for communicating with
7557429Smarkm * the other side.  connection_in is used for reading; connection_out for
7657429Smarkm * writing.  These can be the same descriptor, in which case it is assumed to
7757429Smarkm * be a socket.
7857429Smarkm */
7957429Smarkmstatic int connection_in = -1;
8057429Smarkmstatic int connection_out = -1;
8157429Smarkm
8257429Smarkm/* Protocol flags for the remote side. */
8376259Sgreenstatic u_int remote_protocol_flags = 0;
8457429Smarkm
8557429Smarkm/* Encryption context for receiving data.  This is only used for decryption. */
8657429Smarkmstatic CipherContext receive_context;
8757429Smarkm
8857429Smarkm/* Encryption context for sending data.  This is only used for encryption. */
8957429Smarkmstatic CipherContext send_context;
9057429Smarkm
9157429Smarkm/* Buffer for raw input data from the socket. */
9298675SdesBuffer input;
9357429Smarkm
9457429Smarkm/* Buffer for raw output data going to the socket. */
9598675SdesBuffer output;
9657429Smarkm
9757429Smarkm/* Buffer for the partial outgoing packet being constructed. */
9857429Smarkmstatic Buffer outgoing_packet;
9957429Smarkm
10057429Smarkm/* Buffer for the incoming packet currently being processed. */
10157429Smarkmstatic Buffer incoming_packet;
10257429Smarkm
10357429Smarkm/* Scratch buffer for packet compression/decompression. */
10457429Smarkmstatic Buffer compression_buffer;
10576259Sgreenstatic int compression_buffer_ready = 0;
10657429Smarkm
10757429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */
10857429Smarkmstatic int packet_compression = 0;
10957429Smarkm
11057429Smarkm/* default maximum packet size */
111124208Sdesu_int max_packet_size = 32768;
11257429Smarkm
11357429Smarkm/* Flag indicating whether this module has been initialized. */
11457429Smarkmstatic int initialized = 0;
11557429Smarkm
11657429Smarkm/* Set to true if the connection is interactive. */
11757429Smarkmstatic int interactive_mode = 0;
11857429Smarkm
11960573Skris/* Session key information for Encryption and MAC */
12076259SgreenNewkeys *newkeys[MODE_MAX];
121124208Sdesstatic struct packet_state {
122124208Sdes	u_int32_t seqnr;
123124208Sdes	u_int32_t packets;
124124208Sdes	u_int64_t blocks;
125124208Sdes} p_read, p_send;
12660573Skris
127124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out;
128124208Sdesstatic u_int32_t rekey_limit;
129124208Sdes
13098675Sdes/* Session key for protocol v1 */
13198675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
13298675Sdesstatic u_int ssh1_keylen;
13398675Sdes
13492555Sdes/* roundup current message to extra_pad bytes */
13592555Sdesstatic u_char extra_pad = 0;
13660573Skris
137124208Sdesstruct packet {
138124208Sdes	TAILQ_ENTRY(packet) next;
139124208Sdes	u_char type;
140124208Sdes	Buffer payload;
141124208Sdes};
142124208SdesTAILQ_HEAD(, packet) outgoing;
143124208Sdes
14457429Smarkm/*
14557429Smarkm * Sets the descriptors used for communication.  Disables encryption until
14657429Smarkm * packet_set_encryption_key is called.
14757429Smarkm */
14857429Smarkmvoid
14957429Smarkmpacket_set_connection(int fd_in, int fd_out)
15057429Smarkm{
15169587Sgreen	Cipher *none = cipher_by_name("none");
152106121Sdes
15369587Sgreen	if (none == NULL)
15469587Sgreen		fatal("packet_set_connection: cannot load cipher 'none'");
15557429Smarkm	connection_in = fd_in;
15657429Smarkm	connection_out = fd_out;
15792555Sdes	cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT);
15892555Sdes	cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
15992555Sdes	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
16057429Smarkm	if (!initialized) {
16157429Smarkm		initialized = 1;
16257429Smarkm		buffer_init(&input);
16357429Smarkm		buffer_init(&output);
16457429Smarkm		buffer_init(&outgoing_packet);
16557429Smarkm		buffer_init(&incoming_packet);
166124208Sdes		TAILQ_INIT(&outgoing);
16757429Smarkm	}
16857429Smarkm}
16957429Smarkm
17057429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
17157429Smarkm
17257429Smarkmint
17392555Sdespacket_connection_is_on_socket(void)
17457429Smarkm{
17557429Smarkm	struct sockaddr_storage from, to;
17657429Smarkm	socklen_t fromlen, tolen;
17757429Smarkm
17857429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
17957429Smarkm	if (connection_in == connection_out)
18057429Smarkm		return 1;
18157429Smarkm	fromlen = sizeof(from);
18257429Smarkm	memset(&from, 0, sizeof(from));
18357429Smarkm	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
18457429Smarkm		return 0;
18557429Smarkm	tolen = sizeof(to);
18657429Smarkm	memset(&to, 0, sizeof(to));
18757429Smarkm	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
18857429Smarkm		return 0;
18957429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
19057429Smarkm		return 0;
19157429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
19257429Smarkm		return 0;
19357429Smarkm	return 1;
19457429Smarkm}
19557429Smarkm
19698675Sdes/*
19798675Sdes * Exports an IV from the CipherContext required to export the key
19898675Sdes * state back from the unprivileged child to the privileged parent
19998675Sdes * process.
20098675Sdes */
20198675Sdes
20298675Sdesvoid
20398675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
20498675Sdes{
20598675Sdes	CipherContext *cc;
20698675Sdes
20798675Sdes	if (mode == MODE_OUT)
20898675Sdes		cc = &send_context;
20998675Sdes	else
21098675Sdes		cc = &receive_context;
21198675Sdes
21298675Sdes	cipher_get_keyiv(cc, iv, len);
21398675Sdes}
21498675Sdes
21598675Sdesint
21698675Sdespacket_get_keycontext(int mode, u_char *dat)
21798675Sdes{
21898675Sdes	CipherContext *cc;
21998675Sdes
22098675Sdes	if (mode == MODE_OUT)
22198675Sdes		cc = &send_context;
22298675Sdes	else
22398675Sdes		cc = &receive_context;
22498675Sdes
22598675Sdes	return (cipher_get_keycontext(cc, dat));
22698675Sdes}
22798675Sdes
22898675Sdesvoid
22998675Sdespacket_set_keycontext(int mode, u_char *dat)
23098675Sdes{
23198675Sdes	CipherContext *cc;
23298675Sdes
23398675Sdes	if (mode == MODE_OUT)
23498675Sdes		cc = &send_context;
23598675Sdes	else
23698675Sdes		cc = &receive_context;
23798675Sdes
23898675Sdes	cipher_set_keycontext(cc, dat);
23998675Sdes}
24098675Sdes
24198675Sdesint
24298675Sdespacket_get_keyiv_len(int mode)
24398675Sdes{
24498675Sdes	CipherContext *cc;
24598675Sdes
24698675Sdes	if (mode == MODE_OUT)
24798675Sdes		cc = &send_context;
24898675Sdes	else
24998675Sdes		cc = &receive_context;
25098675Sdes
25198675Sdes	return (cipher_get_keyiv_len(cc));
25298675Sdes}
25398675Sdesvoid
25498675Sdespacket_set_iv(int mode, u_char *dat)
25598675Sdes{
25698675Sdes	CipherContext *cc;
25798675Sdes
25898675Sdes	if (mode == MODE_OUT)
25998675Sdes		cc = &send_context;
26098675Sdes	else
26198675Sdes		cc = &receive_context;
26298675Sdes
26398675Sdes	cipher_set_keyiv(cc, dat);
26498675Sdes}
26598675Sdesint
266124208Sdespacket_get_ssh1_cipher(void)
26798675Sdes{
26898675Sdes	return (cipher_get_number(receive_context.cipher));
26998675Sdes}
27098675Sdes
271124208Sdesvoid
272124208Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
273124208Sdes{
274124208Sdes	struct packet_state *state;
27598675Sdes
276124208Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
277124208Sdes	*seqnr = state->seqnr;
278124208Sdes	*blocks = state->blocks;
279124208Sdes	*packets = state->packets;
28098675Sdes}
28198675Sdes
28298675Sdesvoid
283124208Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
28498675Sdes{
285124208Sdes	struct packet_state *state;
286124208Sdes
287124208Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
288124208Sdes	state->seqnr = seqnr;
289124208Sdes	state->blocks = blocks;
290124208Sdes	state->packets = packets;
29198675Sdes}
29298675Sdes
29357429Smarkm/* returns 1 if connection is via ipv4 */
29457429Smarkm
29557429Smarkmint
29692555Sdespacket_connection_is_ipv4(void)
29757429Smarkm{
29857429Smarkm	struct sockaddr_storage to;
29957429Smarkm	socklen_t tolen = sizeof(to);
30057429Smarkm
30157429Smarkm	memset(&to, 0, sizeof(to));
30257429Smarkm	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
30357429Smarkm		return 0;
30498937Sdes	if (to.ss_family == AF_INET)
30598937Sdes		return 1;
30698937Sdes#ifdef IPV4_IN_IPV6
307126274Sdes	if (to.ss_family == AF_INET6 &&
30898937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
30998937Sdes		return 1;
31098937Sdes#endif
31198937Sdes	return 0;
31257429Smarkm}
31357429Smarkm
31457429Smarkm/* Sets the connection into non-blocking mode. */
31557429Smarkm
31657429Smarkmvoid
31792555Sdespacket_set_nonblocking(void)
31857429Smarkm{
31957429Smarkm	/* Set the socket into non-blocking mode. */
32057429Smarkm	if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
32157429Smarkm		error("fcntl O_NONBLOCK: %.100s", strerror(errno));
32257429Smarkm
32357429Smarkm	if (connection_out != connection_in) {
32457429Smarkm		if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
32557429Smarkm			error("fcntl O_NONBLOCK: %.100s", strerror(errno));
32657429Smarkm	}
32757429Smarkm}
32857429Smarkm
32957429Smarkm/* Returns the socket used for reading. */
33057429Smarkm
33157429Smarkmint
33292555Sdespacket_get_connection_in(void)
33357429Smarkm{
33457429Smarkm	return connection_in;
33557429Smarkm}
33657429Smarkm
33757429Smarkm/* Returns the descriptor used for writing. */
33857429Smarkm
33957429Smarkmint
34092555Sdespacket_get_connection_out(void)
34157429Smarkm{
34257429Smarkm	return connection_out;
34357429Smarkm}
34457429Smarkm
34557429Smarkm/* Closes the connection and clears and frees internal data structures. */
34657429Smarkm
34757429Smarkmvoid
34892555Sdespacket_close(void)
34957429Smarkm{
35057429Smarkm	if (!initialized)
35157429Smarkm		return;
35257429Smarkm	initialized = 0;
35357429Smarkm	if (connection_in == connection_out) {
35457429Smarkm		shutdown(connection_out, SHUT_RDWR);
35557429Smarkm		close(connection_out);
35657429Smarkm	} else {
35757429Smarkm		close(connection_in);
35857429Smarkm		close(connection_out);
35957429Smarkm	}
36057429Smarkm	buffer_free(&input);
36157429Smarkm	buffer_free(&output);
36257429Smarkm	buffer_free(&outgoing_packet);
36357429Smarkm	buffer_free(&incoming_packet);
36476259Sgreen	if (compression_buffer_ready) {
36557429Smarkm		buffer_free(&compression_buffer);
36657429Smarkm		buffer_compress_uninit();
36757429Smarkm	}
36892555Sdes	cipher_cleanup(&send_context);
36992555Sdes	cipher_cleanup(&receive_context);
37057429Smarkm}
37157429Smarkm
37257429Smarkm/* Sets remote side protocol flags. */
37357429Smarkm
37457429Smarkmvoid
37576259Sgreenpacket_set_protocol_flags(u_int protocol_flags)
37657429Smarkm{
37757429Smarkm	remote_protocol_flags = protocol_flags;
37857429Smarkm}
37957429Smarkm
38057429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
38157429Smarkm
38276259Sgreenu_int
38392555Sdespacket_get_protocol_flags(void)
38457429Smarkm{
38557429Smarkm	return remote_protocol_flags;
38657429Smarkm}
38757429Smarkm
38857429Smarkm/*
38957429Smarkm * Starts packet compression from the next packet on in both directions.
39057429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
39157429Smarkm */
39257429Smarkm
39392555Sdesstatic void
39492555Sdespacket_init_compression(void)
39576259Sgreen{
39676259Sgreen	if (compression_buffer_ready == 1)
39776259Sgreen		return;
39876259Sgreen	compression_buffer_ready = 1;
39976259Sgreen	buffer_init(&compression_buffer);
40076259Sgreen}
40176259Sgreen
40276259Sgreenvoid
40357429Smarkmpacket_start_compression(int level)
40457429Smarkm{
40592555Sdes	if (packet_compression && !compat20)
40657429Smarkm		fatal("Compression already enabled.");
40757429Smarkm	packet_compression = 1;
40876259Sgreen	packet_init_compression();
40976259Sgreen	buffer_compress_init_send(level);
41076259Sgreen	buffer_compress_init_recv();
41157429Smarkm}
41257429Smarkm
41357429Smarkm/*
41457429Smarkm * Causes any further packets to be encrypted using the given key.  The same
41557429Smarkm * key is used for both sending and reception.  However, both directions are
41657429Smarkm * encrypted independently of each other.
41757429Smarkm */
41898675Sdes
41957429Smarkmvoid
42076259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen,
42169587Sgreen    int number)
42257429Smarkm{
42369587Sgreen	Cipher *cipher = cipher_by_number(number);
424106121Sdes
42569587Sgreen	if (cipher == NULL)
42669587Sgreen		fatal("packet_set_encryption_key: unknown cipher number %d", number);
42760573Skris	if (keylen < 20)
42869587Sgreen		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
42998675Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
43098675Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
43198675Sdes	memcpy(ssh1_key, key, keylen);
43298675Sdes	ssh1_keylen = keylen;
43392555Sdes	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
43492555Sdes	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
43557429Smarkm}
43657429Smarkm
43798675Sdesu_int
43898675Sdespacket_get_encryption_key(u_char *key)
43998675Sdes{
44098675Sdes	if (key == NULL)
44198675Sdes		return (ssh1_keylen);
44298675Sdes	memcpy(key, ssh1_key, ssh1_keylen);
44398675Sdes	return (ssh1_keylen);
44498675Sdes}
44598675Sdes
44692555Sdes/* Start constructing a packet to send. */
44757429Smarkmvoid
44892555Sdespacket_start(u_char type)
44957429Smarkm{
45092555Sdes	u_char buf[9];
45192555Sdes	int len;
45257429Smarkm
45392555Sdes	DBG(debug("packet_start[%d]", type));
45492555Sdes	len = compat20 ? 6 : 9;
45592555Sdes	memset(buf, 0, len - 1);
45692555Sdes	buf[len - 1] = type;
45757429Smarkm	buffer_clear(&outgoing_packet);
45892555Sdes	buffer_append(&outgoing_packet, buf, len);
45957429Smarkm}
46057429Smarkm
46192555Sdes/* Append payload. */
46260573Skrisvoid
46357429Smarkmpacket_put_char(int value)
46457429Smarkm{
46557429Smarkm	char ch = value;
466106121Sdes
46757429Smarkm	buffer_append(&outgoing_packet, &ch, 1);
46857429Smarkm}
46957429Smarkmvoid
47076259Sgreenpacket_put_int(u_int value)
47157429Smarkm{
47257429Smarkm	buffer_put_int(&outgoing_packet, value);
47357429Smarkm}
47457429Smarkmvoid
47592555Sdespacket_put_string(const void *buf, u_int len)
47657429Smarkm{
47757429Smarkm	buffer_put_string(&outgoing_packet, buf, len);
47857429Smarkm}
47960573Skrisvoid
48060573Skrispacket_put_cstring(const char *str)
48160573Skris{
48292555Sdes	buffer_put_cstring(&outgoing_packet, str);
48360573Skris}
48460573Skrisvoid
48592555Sdespacket_put_raw(const void *buf, u_int len)
48660573Skris{
48760573Skris	buffer_append(&outgoing_packet, buf, len);
48860573Skris}
48957429Smarkmvoid
49057429Smarkmpacket_put_bignum(BIGNUM * value)
49157429Smarkm{
49257429Smarkm	buffer_put_bignum(&outgoing_packet, value);
49357429Smarkm}
49460573Skrisvoid
49560573Skrispacket_put_bignum2(BIGNUM * value)
49660573Skris{
49760573Skris	buffer_put_bignum2(&outgoing_packet, value);
49860573Skris}
49957429Smarkm
50057429Smarkm/*
50157429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
50257429Smarkm * encrypts the packet before sending.
50357429Smarkm */
50457429Smarkm
50592555Sdesstatic void
50676259Sgreenpacket_send1(void)
50757429Smarkm{
50892555Sdes	u_char buf[8], *cp;
50957429Smarkm	int i, padding, len;
51076259Sgreen	u_int checksum;
51157429Smarkm	u_int32_t rand = 0;
51257429Smarkm
51357429Smarkm	/*
51457429Smarkm	 * If using packet compression, compress the payload of the outgoing
51557429Smarkm	 * packet.
51657429Smarkm	 */
51757429Smarkm	if (packet_compression) {
51857429Smarkm		buffer_clear(&compression_buffer);
51957429Smarkm		/* Skip padding. */
52057429Smarkm		buffer_consume(&outgoing_packet, 8);
52157429Smarkm		/* padding */
52257429Smarkm		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
52357429Smarkm		buffer_compress(&outgoing_packet, &compression_buffer);
52457429Smarkm		buffer_clear(&outgoing_packet);
52557429Smarkm		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
52692555Sdes		    buffer_len(&compression_buffer));
52757429Smarkm	}
52857429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
52957429Smarkm	len = buffer_len(&outgoing_packet) + 4 - 8;
53057429Smarkm
53160573Skris	/* Insert padding. Initialized to zero in packet_start1() */
53257429Smarkm	padding = 8 - len % 8;
53392555Sdes	if (!send_context.plaintext) {
53457429Smarkm		cp = buffer_ptr(&outgoing_packet);
53557429Smarkm		for (i = 0; i < padding; i++) {
53657429Smarkm			if (i % 4 == 0)
53757429Smarkm				rand = arc4random();
53857429Smarkm			cp[7 - i] = rand & 0xff;
53957429Smarkm			rand >>= 8;
54057429Smarkm		}
54157429Smarkm	}
54257429Smarkm	buffer_consume(&outgoing_packet, 8 - padding);
54357429Smarkm
54457429Smarkm	/* Add check bytes. */
54592555Sdes	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
54665668Skris	    buffer_len(&outgoing_packet));
54757429Smarkm	PUT_32BIT(buf, checksum);
54857429Smarkm	buffer_append(&outgoing_packet, buf, 4);
54957429Smarkm
55057429Smarkm#ifdef PACKET_DEBUG
55157429Smarkm	fprintf(stderr, "packet_send plain: ");
55257429Smarkm	buffer_dump(&outgoing_packet);
55357429Smarkm#endif
55457429Smarkm
55557429Smarkm	/* Append to output. */
55657429Smarkm	PUT_32BIT(buf, len);
55757429Smarkm	buffer_append(&output, buf, 4);
55892555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
55992555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
56092555Sdes	    buffer_len(&outgoing_packet));
56157429Smarkm
56257429Smarkm#ifdef PACKET_DEBUG
56357429Smarkm	fprintf(stderr, "encrypted: ");
56457429Smarkm	buffer_dump(&output);
56557429Smarkm#endif
56657429Smarkm
56757429Smarkm	buffer_clear(&outgoing_packet);
56857429Smarkm
56957429Smarkm	/*
57057429Smarkm	 * Note that the packet is now only buffered in output.  It won\'t be
57157429Smarkm	 * actually sent until packet_write_wait or packet_write_poll is
57257429Smarkm	 * called.
57357429Smarkm	 */
57457429Smarkm}
57557429Smarkm
57698675Sdesvoid
57776259Sgreenset_newkeys(int mode)
57876259Sgreen{
57976259Sgreen	Enc *enc;
58076259Sgreen	Mac *mac;
58176259Sgreen	Comp *comp;
58276259Sgreen	CipherContext *cc;
583124208Sdes	u_int64_t *max_blocks;
58492555Sdes	int encrypt;
58576259Sgreen
586113908Sdes	debug2("set_newkeys: mode %d", mode);
58776259Sgreen
58892555Sdes	if (mode == MODE_OUT) {
58992555Sdes		cc = &send_context;
59092555Sdes		encrypt = CIPHER_ENCRYPT;
591124208Sdes		p_send.packets = p_send.blocks = 0;
592124208Sdes		max_blocks = &max_blocks_out;
59392555Sdes	} else {
59492555Sdes		cc = &receive_context;
59592555Sdes		encrypt = CIPHER_DECRYPT;
596124208Sdes		p_read.packets = p_read.blocks = 0;
597124208Sdes		max_blocks = &max_blocks_in;
59892555Sdes	}
59976259Sgreen	if (newkeys[mode] != NULL) {
600113908Sdes		debug("set_newkeys: rekeying");
60192555Sdes		cipher_cleanup(cc);
60276259Sgreen		enc  = &newkeys[mode]->enc;
60376259Sgreen		mac  = &newkeys[mode]->mac;
60476259Sgreen		comp = &newkeys[mode]->comp;
60576259Sgreen		memset(mac->key, 0, mac->key_len);
60676259Sgreen		xfree(enc->name);
60776259Sgreen		xfree(enc->iv);
60876259Sgreen		xfree(enc->key);
60976259Sgreen		xfree(mac->name);
61076259Sgreen		xfree(mac->key);
61176259Sgreen		xfree(comp->name);
61276259Sgreen		xfree(newkeys[mode]);
61376259Sgreen	}
61476259Sgreen	newkeys[mode] = kex_get_newkeys(mode);
61576259Sgreen	if (newkeys[mode] == NULL)
61676259Sgreen		fatal("newkeys: no keys for mode %d", mode);
61776259Sgreen	enc  = &newkeys[mode]->enc;
61876259Sgreen	mac  = &newkeys[mode]->mac;
61976259Sgreen	comp = &newkeys[mode]->comp;
62076259Sgreen	if (mac->md != NULL)
62176259Sgreen		mac->enabled = 1;
62276259Sgreen	DBG(debug("cipher_init_context: %d", mode));
62392555Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
62492555Sdes	    enc->iv, enc->block_size, encrypt);
62598675Sdes	/* Deleting the keys does not gain extra security */
62698675Sdes	/* memset(enc->iv,  0, enc->block_size);
62798675Sdes	   memset(enc->key, 0, enc->key_len); */
62876259Sgreen	if (comp->type != 0 && comp->enabled == 0) {
62976259Sgreen		packet_init_compression();
63076259Sgreen		if (mode == MODE_OUT)
63176259Sgreen			buffer_compress_init_send(6);
63276259Sgreen		else
63376259Sgreen			buffer_compress_init_recv();
63476259Sgreen		comp->enabled = 1;
63576259Sgreen	}
636124208Sdes	/*
637124208Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
638124208Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
639124208Sdes	 */
640124208Sdes	if (enc->block_size >= 16)
641124208Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
642124208Sdes	else
643124208Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
644124208Sdes	if (rekey_limit)
645124208Sdes		*max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
64676259Sgreen}
64776259Sgreen
64857429Smarkm/*
64960573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
65060573Skris */
65192555Sdesstatic void
652124208Sdespacket_send2_wrapped(void)
65360573Skris{
65492555Sdes	u_char type, *cp, *macbuf = NULL;
65592555Sdes	u_char padlen, pad;
65676259Sgreen	u_int packet_length = 0;
65792555Sdes	u_int i, len;
65860573Skris	u_int32_t rand = 0;
65960573Skris	Enc *enc   = NULL;
66060573Skris	Mac *mac   = NULL;
66160573Skris	Comp *comp = NULL;
66260573Skris	int block_size;
66360573Skris
66476259Sgreen	if (newkeys[MODE_OUT] != NULL) {
66576259Sgreen		enc  = &newkeys[MODE_OUT]->enc;
66676259Sgreen		mac  = &newkeys[MODE_OUT]->mac;
66776259Sgreen		comp = &newkeys[MODE_OUT]->comp;
66860573Skris	}
66992555Sdes	block_size = enc ? enc->block_size : 8;
67060573Skris
67160573Skris	cp = buffer_ptr(&outgoing_packet);
67292555Sdes	type = cp[5];
67360573Skris
67460573Skris#ifdef PACKET_DEBUG
67560573Skris	fprintf(stderr, "plain:     ");
67660573Skris	buffer_dump(&outgoing_packet);
67760573Skris#endif
67860573Skris
67960573Skris	if (comp && comp->enabled) {
68060573Skris		len = buffer_len(&outgoing_packet);
68160573Skris		/* skip header, compress only payload */
68260573Skris		buffer_consume(&outgoing_packet, 5);
68360573Skris		buffer_clear(&compression_buffer);
68460573Skris		buffer_compress(&outgoing_packet, &compression_buffer);
68560573Skris		buffer_clear(&outgoing_packet);
68660573Skris		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
68760573Skris		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
68860573Skris		    buffer_len(&compression_buffer));
68960573Skris		DBG(debug("compression: raw %d compressed %d", len,
69060573Skris		    buffer_len(&outgoing_packet)));
69160573Skris	}
69260573Skris
69360573Skris	/* sizeof (packet_len + pad_len + payload) */
69460573Skris	len = buffer_len(&outgoing_packet);
69560573Skris
69660573Skris	/*
69760573Skris	 * calc size of padding, alloc space, get random data,
69860573Skris	 * minimum padding is 4 bytes
69960573Skris	 */
70060573Skris	padlen = block_size - (len % block_size);
70160573Skris	if (padlen < 4)
70260573Skris		padlen += block_size;
70392555Sdes	if (extra_pad) {
70492555Sdes		/* will wrap if extra_pad+padlen > 255 */
70592555Sdes		extra_pad  = roundup(extra_pad, block_size);
70692555Sdes		pad = extra_pad - ((len + padlen) % extra_pad);
70798675Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
70892555Sdes		    pad, len, padlen, extra_pad);
70992555Sdes		padlen += pad;
71092555Sdes		extra_pad = 0;
71192555Sdes	}
71292555Sdes	cp = buffer_append_space(&outgoing_packet, padlen);
71392555Sdes	if (enc && !send_context.plaintext) {
71460573Skris		/* random padding */
71560573Skris		for (i = 0; i < padlen; i++) {
71660573Skris			if (i % 4 == 0)
71760573Skris				rand = arc4random();
71860573Skris			cp[i] = rand & 0xff;
71976259Sgreen			rand >>= 8;
72060573Skris		}
72160573Skris	} else {
72260573Skris		/* clear padding */
72360573Skris		memset(cp, 0, padlen);
72460573Skris	}
72560573Skris	/* packet_length includes payload, padding and padding length field */
72660573Skris	packet_length = buffer_len(&outgoing_packet) - 4;
72760573Skris	cp = buffer_ptr(&outgoing_packet);
72860573Skris	PUT_32BIT(cp, packet_length);
72992555Sdes	cp[4] = padlen;
73060573Skris	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
73160573Skris
73260573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
73360573Skris	if (mac && mac->enabled) {
734124208Sdes		macbuf = mac_compute(mac, p_send.seqnr,
73592555Sdes		    buffer_ptr(&outgoing_packet),
73676259Sgreen		    buffer_len(&outgoing_packet));
737124208Sdes		DBG(debug("done calc MAC out #%d", p_send.seqnr));
73860573Skris	}
73960573Skris	/* encrypt packet and append to output buffer. */
74092555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
74192555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
74260573Skris	    buffer_len(&outgoing_packet));
74360573Skris	/* append unencrypted MAC */
74460573Skris	if (mac && mac->enabled)
74560573Skris		buffer_append(&output, (char *)macbuf, mac->mac_len);
74660573Skris#ifdef PACKET_DEBUG
74760573Skris	fprintf(stderr, "encrypted: ");
74860573Skris	buffer_dump(&output);
74960573Skris#endif
75060573Skris	/* increment sequence number for outgoing packets */
751124208Sdes	if (++p_send.seqnr == 0)
752124208Sdes		logit("outgoing seqnr wraps around");
753124208Sdes	if (++p_send.packets == 0)
754124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
755124208Sdes			fatal("XXX too many packets with same key");
756124208Sdes	p_send.blocks += (packet_length + 4) / block_size;
75760573Skris	buffer_clear(&outgoing_packet);
75860573Skris
75976259Sgreen	if (type == SSH2_MSG_NEWKEYS)
76076259Sgreen		set_newkeys(MODE_OUT);
76160573Skris}
76260573Skris
763124208Sdesstatic void
764124208Sdespacket_send2(void)
765124208Sdes{
766124208Sdes	static int rekeying = 0;
767124208Sdes	struct packet *p;
768124208Sdes	u_char type, *cp;
769124208Sdes
770124208Sdes	cp = buffer_ptr(&outgoing_packet);
771124208Sdes	type = cp[5];
772124208Sdes
773124208Sdes	/* during rekeying we can only send key exchange messages */
774124208Sdes	if (rekeying) {
775124208Sdes		if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
776124208Sdes		    (type <= SSH2_MSG_TRANSPORT_MAX))) {
777124208Sdes			debug("enqueue packet: %u", type);
778124208Sdes			p = xmalloc(sizeof(*p));
779124208Sdes			p->type = type;
780124208Sdes			memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
781124208Sdes			buffer_init(&outgoing_packet);
782124208Sdes			TAILQ_INSERT_TAIL(&outgoing, p, next);
783124208Sdes			return;
784124208Sdes		}
785124208Sdes	}
786124208Sdes
787124208Sdes	/* rekeying starts with sending KEXINIT */
788124208Sdes	if (type == SSH2_MSG_KEXINIT)
789124208Sdes		rekeying = 1;
790124208Sdes
791124208Sdes	packet_send2_wrapped();
792124208Sdes
793124208Sdes	/* after a NEWKEYS message we can send the complete queue */
794124208Sdes	if (type == SSH2_MSG_NEWKEYS) {
795124208Sdes		rekeying = 0;
796124208Sdes		while ((p = TAILQ_FIRST(&outgoing))) {
797124208Sdes			type = p->type;
798124208Sdes			debug("dequeue packet: %u", type);
799124208Sdes			buffer_free(&outgoing_packet);
800124208Sdes			memcpy(&outgoing_packet, &p->payload,
801124208Sdes			    sizeof(Buffer));
802124208Sdes			TAILQ_REMOVE(&outgoing, p, next);
803124208Sdes			xfree(p);
804124208Sdes			packet_send2_wrapped();
805124208Sdes		}
806124208Sdes	}
807124208Sdes}
808124208Sdes
80960573Skrisvoid
81092555Sdespacket_send(void)
81160573Skris{
81292555Sdes	if (compat20)
81360573Skris		packet_send2();
81460573Skris	else
81560573Skris		packet_send1();
81660573Skris	DBG(debug("packet_send done"));
81760573Skris}
81860573Skris
81960573Skris/*
82057429Smarkm * Waits until a packet has been received, and returns its type.  Note that
82157429Smarkm * no other data is processed until this returns, so this function should not
82257429Smarkm * be used during the interactive session.
82357429Smarkm */
82457429Smarkm
82557429Smarkmint
82692555Sdespacket_read_seqnr(u_int32_t *seqnr_p)
82757429Smarkm{
82857429Smarkm	int type, len;
82976259Sgreen	fd_set *setp;
83057429Smarkm	char buf[8192];
83160573Skris	DBG(debug("packet_read()"));
83257429Smarkm
83376259Sgreen	setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
83476259Sgreen	    sizeof(fd_mask));
83576259Sgreen
83657429Smarkm	/* Since we are blocking, ensure that all written packets have been sent. */
83757429Smarkm	packet_write_wait();
83857429Smarkm
83957429Smarkm	/* Stay in the loop until we have received a complete packet. */
84057429Smarkm	for (;;) {
84157429Smarkm		/* Try to read a packet from the buffer. */
84292555Sdes		type = packet_read_poll_seqnr(seqnr_p);
84392555Sdes		if (!compat20 && (
84460573Skris		    type == SSH_SMSG_SUCCESS
84557429Smarkm		    || type == SSH_SMSG_FAILURE
84657429Smarkm		    || type == SSH_CMSG_EOF
84760573Skris		    || type == SSH_CMSG_EXIT_CONFIRMATION))
84892555Sdes			packet_check_eom();
84957429Smarkm		/* If we got a packet, return it. */
85076259Sgreen		if (type != SSH_MSG_NONE) {
85176259Sgreen			xfree(setp);
85257429Smarkm			return type;
85376259Sgreen		}
85457429Smarkm		/*
85557429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
85657429Smarkm		 * buffer, and try again.
85757429Smarkm		 */
85876259Sgreen		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
85976259Sgreen		    sizeof(fd_mask));
86076259Sgreen		FD_SET(connection_in, setp);
86157429Smarkm
86257429Smarkm		/* Wait for some data to arrive. */
86376259Sgreen		while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
86476259Sgreen		    (errno == EAGAIN || errno == EINTR))
86576259Sgreen			;
86657429Smarkm
86757429Smarkm		/* Read data from the socket. */
86857429Smarkm		len = read(connection_in, buf, sizeof(buf));
86957429Smarkm		if (len == 0) {
870124208Sdes			logit("Connection closed by %.200s", get_remote_ipaddr());
871126274Sdes			cleanup_exit(255);
87257429Smarkm		}
87357429Smarkm		if (len < 0)
87457429Smarkm			fatal("Read from socket failed: %.100s", strerror(errno));
87557429Smarkm		/* Append it to the buffer. */
87657429Smarkm		packet_process_incoming(buf, len);
87757429Smarkm	}
87857429Smarkm	/* NOTREACHED */
87957429Smarkm}
88057429Smarkm
88192555Sdesint
88292555Sdespacket_read(void)
88392555Sdes{
88492555Sdes	return packet_read_seqnr(NULL);
88592555Sdes}
88692555Sdes
88757429Smarkm/*
88857429Smarkm * Waits until a packet has been received, verifies that its type matches
88957429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
89057429Smarkm */
89157429Smarkm
89257429Smarkmvoid
89392555Sdespacket_read_expect(int expected_type)
89457429Smarkm{
89557429Smarkm	int type;
89657429Smarkm
89792555Sdes	type = packet_read();
89857429Smarkm	if (type != expected_type)
89957429Smarkm		packet_disconnect("Protocol error: expected packet type %d, got %d",
90060573Skris		    expected_type, type);
90157429Smarkm}
90257429Smarkm
90357429Smarkm/* Checks if a full packet is available in the data received so far via
90457429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
90557429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
90657429Smarkm *
90757429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
90857429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
90957429Smarkm * to higher levels.
91057429Smarkm */
91157429Smarkm
91292555Sdesstatic int
91392555Sdespacket_read_poll1(void)
91457429Smarkm{
91576259Sgreen	u_int len, padded_len;
91692555Sdes	u_char *cp, type;
91776259Sgreen	u_int checksum, stored_checksum;
91857429Smarkm
91957429Smarkm	/* Check if input size is less than minimum packet size. */
92057429Smarkm	if (buffer_len(&input) < 4 + 8)
92157429Smarkm		return SSH_MSG_NONE;
92257429Smarkm	/* Get length of incoming packet. */
92392555Sdes	cp = buffer_ptr(&input);
92492555Sdes	len = GET_32BIT(cp);
92557429Smarkm	if (len < 1 + 2 + 2 || len > 256 * 1024)
926113908Sdes		packet_disconnect("Bad packet length %u.", len);
92757429Smarkm	padded_len = (len + 8) & ~7;
92857429Smarkm
92957429Smarkm	/* Check if the packet has been entirely received. */
93057429Smarkm	if (buffer_len(&input) < 4 + padded_len)
93157429Smarkm		return SSH_MSG_NONE;
93257429Smarkm
93357429Smarkm	/* The entire packet is in buffer. */
93457429Smarkm
93557429Smarkm	/* Consume packet length. */
93657429Smarkm	buffer_consume(&input, 4);
93757429Smarkm
93892555Sdes	/*
93992555Sdes	 * Cryptographic attack detector for ssh
94092555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
94192555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
94292555Sdes	 */
94392555Sdes	if (!receive_context.plaintext &&
94492555Sdes	    detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)
94592555Sdes		packet_disconnect("crc32 compensation attack: network attack detected");
94692555Sdes
94792555Sdes	/* Decrypt data to incoming_packet. */
94857429Smarkm	buffer_clear(&incoming_packet);
94992555Sdes	cp = buffer_append_space(&incoming_packet, padded_len);
95092555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
95192555Sdes
95257429Smarkm	buffer_consume(&input, padded_len);
95357429Smarkm
95457429Smarkm#ifdef PACKET_DEBUG
95557429Smarkm	fprintf(stderr, "read_poll plain: ");
95657429Smarkm	buffer_dump(&incoming_packet);
95757429Smarkm#endif
95857429Smarkm
95957429Smarkm	/* Compute packet checksum. */
96092555Sdes	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
96160573Skris	    buffer_len(&incoming_packet) - 4);
96257429Smarkm
96357429Smarkm	/* Skip padding. */
96457429Smarkm	buffer_consume(&incoming_packet, 8 - len % 8);
96557429Smarkm
96657429Smarkm	/* Test check bytes. */
96757429Smarkm	if (len != buffer_len(&incoming_packet))
96892555Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
96960573Skris		    len, buffer_len(&incoming_packet));
97057429Smarkm
97192555Sdes	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
97292555Sdes	stored_checksum = GET_32BIT(cp);
97357429Smarkm	if (checksum != stored_checksum)
97457429Smarkm		packet_disconnect("Corrupted check bytes on input.");
97557429Smarkm	buffer_consume_end(&incoming_packet, 4);
97657429Smarkm
97757429Smarkm	if (packet_compression) {
97857429Smarkm		buffer_clear(&compression_buffer);
97957429Smarkm		buffer_uncompress(&incoming_packet, &compression_buffer);
98057429Smarkm		buffer_clear(&incoming_packet);
98157429Smarkm		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
98260573Skris		    buffer_len(&compression_buffer));
98357429Smarkm	}
98492555Sdes	type = buffer_get_char(&incoming_packet);
98592555Sdes	return type;
98660573Skris}
98757429Smarkm
98892555Sdesstatic int
98992555Sdespacket_read_poll2(u_int32_t *seqnr_p)
99060573Skris{
99176259Sgreen	static u_int packet_length = 0;
99276259Sgreen	u_int padlen, need;
99392555Sdes	u_char *macbuf, *cp, type;
99460573Skris	int maclen, block_size;
99560573Skris	Enc *enc   = NULL;
99660573Skris	Mac *mac   = NULL;
99760573Skris	Comp *comp = NULL;
99857429Smarkm
99976259Sgreen	if (newkeys[MODE_IN] != NULL) {
100076259Sgreen		enc  = &newkeys[MODE_IN]->enc;
100176259Sgreen		mac  = &newkeys[MODE_IN]->mac;
100276259Sgreen		comp = &newkeys[MODE_IN]->comp;
100357429Smarkm	}
100460573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
100592555Sdes	block_size = enc ? enc->block_size : 8;
100660573Skris
100760573Skris	if (packet_length == 0) {
100860573Skris		/*
100960573Skris		 * check if input size is less than the cipher block size,
101060573Skris		 * decrypt first block and extract length of incoming packet
101160573Skris		 */
101260573Skris		if (buffer_len(&input) < block_size)
101360573Skris			return SSH_MSG_NONE;
101460573Skris		buffer_clear(&incoming_packet);
101592555Sdes		cp = buffer_append_space(&incoming_packet, block_size);
101692555Sdes		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
101760573Skris		    block_size);
101892555Sdes		cp = buffer_ptr(&incoming_packet);
101992555Sdes		packet_length = GET_32BIT(cp);
102060573Skris		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
1021124208Sdes#ifdef PACKET_DEBUG
102260573Skris			buffer_dump(&incoming_packet);
1023124208Sdes#endif
1024113908Sdes			packet_disconnect("Bad packet length %u.", packet_length);
102560573Skris		}
1026113908Sdes		DBG(debug("input: packet len %u", packet_length+4));
102760573Skris		buffer_consume(&input, block_size);
102860573Skris	}
102960573Skris	/* we have a partial packet of block_size bytes */
103060573Skris	need = 4 + packet_length - block_size;
103160573Skris	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
103260573Skris	    need, maclen));
103360573Skris	if (need % block_size != 0)
103460573Skris		fatal("padding error: need %d block %d mod %d",
103560573Skris		    need, block_size, need % block_size);
103660573Skris	/*
103760573Skris	 * check if the entire packet has been received and
103860573Skris	 * decrypt into incoming_packet
103960573Skris	 */
104060573Skris	if (buffer_len(&input) < need + maclen)
104160573Skris		return SSH_MSG_NONE;
104260573Skris#ifdef PACKET_DEBUG
104360573Skris	fprintf(stderr, "read_poll enc/full: ");
104460573Skris	buffer_dump(&input);
104560573Skris#endif
104692555Sdes	cp = buffer_append_space(&incoming_packet, need);
104792555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
104860573Skris	buffer_consume(&input, need);
104960573Skris	/*
105060573Skris	 * compute MAC over seqnr and packet,
105160573Skris	 * increment sequence number for incoming packet
105260573Skris	 */
105360573Skris	if (mac && mac->enabled) {
1054124208Sdes		macbuf = mac_compute(mac, p_read.seqnr,
105592555Sdes		    buffer_ptr(&incoming_packet),
105676259Sgreen		    buffer_len(&incoming_packet));
105760573Skris		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
105869587Sgreen			packet_disconnect("Corrupted MAC on input.");
1059124208Sdes		DBG(debug("MAC #%d ok", p_read.seqnr));
106060573Skris		buffer_consume(&input, mac->mac_len);
106160573Skris	}
106292555Sdes	if (seqnr_p != NULL)
1063124208Sdes		*seqnr_p = p_read.seqnr;
1064124208Sdes	if (++p_read.seqnr == 0)
1065124208Sdes		logit("incoming seqnr wraps around");
1066124208Sdes	if (++p_read.packets == 0)
1067124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
1068124208Sdes			fatal("XXX too many packets with same key");
1069124208Sdes	p_read.blocks += (packet_length + 4) / block_size;
107060573Skris
107160573Skris	/* get padlen */
107292555Sdes	cp = buffer_ptr(&incoming_packet);
107392555Sdes	padlen = cp[4];
107460573Skris	DBG(debug("input: padlen %d", padlen));
107560573Skris	if (padlen < 4)
107660573Skris		packet_disconnect("Corrupted padlen %d on input.", padlen);
107760573Skris
107860573Skris	/* skip packet size + padlen, discard padding */
107960573Skris	buffer_consume(&incoming_packet, 4 + 1);
108060573Skris	buffer_consume_end(&incoming_packet, padlen);
108160573Skris
108260573Skris	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
108360573Skris	if (comp && comp->enabled) {
108460573Skris		buffer_clear(&compression_buffer);
108560573Skris		buffer_uncompress(&incoming_packet, &compression_buffer);
108660573Skris		buffer_clear(&incoming_packet);
108760573Skris		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
108860573Skris		    buffer_len(&compression_buffer));
1089106121Sdes		DBG(debug("input: len after de-compress %d",
1090106121Sdes		    buffer_len(&incoming_packet)));
109160573Skris	}
109260573Skris	/*
109360573Skris	 * get packet type, implies consume.
109460573Skris	 * return length of payload (without type field)
109560573Skris	 */
109692555Sdes	type = buffer_get_char(&incoming_packet);
109776259Sgreen	if (type == SSH2_MSG_NEWKEYS)
109876259Sgreen		set_newkeys(MODE_IN);
109960573Skris#ifdef PACKET_DEBUG
110076259Sgreen	fprintf(stderr, "read/plain[%d]:\r\n", type);
110160573Skris	buffer_dump(&incoming_packet);
110260573Skris#endif
110392555Sdes	/* reset for next packet */
110492555Sdes	packet_length = 0;
110592555Sdes	return type;
110657429Smarkm}
110757429Smarkm
110860573Skrisint
110992555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
111060573Skris{
111199060Sdes	u_int reason, seqnr;
111292555Sdes	u_char type;
111360573Skris	char *msg;
111492555Sdes
111560573Skris	for (;;) {
111692555Sdes		if (compat20) {
111792555Sdes			type = packet_read_poll2(seqnr_p);
111892555Sdes			if (type)
111960573Skris				DBG(debug("received packet type %d", type));
112092555Sdes			switch (type) {
112160573Skris			case SSH2_MSG_IGNORE:
112260573Skris				break;
112360573Skris			case SSH2_MSG_DEBUG:
112460573Skris				packet_get_char();
112560573Skris				msg = packet_get_string(NULL);
112660573Skris				debug("Remote: %.900s", msg);
112760573Skris				xfree(msg);
112860573Skris				msg = packet_get_string(NULL);
112960573Skris				xfree(msg);
113060573Skris				break;
113160573Skris			case SSH2_MSG_DISCONNECT:
113260573Skris				reason = packet_get_int();
113360573Skris				msg = packet_get_string(NULL);
1134124208Sdes				logit("Received disconnect from %s: %u: %.400s",
113599060Sdes				    get_remote_ipaddr(), reason, msg);
113660573Skris				xfree(msg);
1137126274Sdes				cleanup_exit(255);
113860573Skris				break;
113992555Sdes			case SSH2_MSG_UNIMPLEMENTED:
114092555Sdes				seqnr = packet_get_int();
114199060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
114299060Sdes				    seqnr);
114392555Sdes				break;
114460573Skris			default:
114560573Skris				return type;
114660573Skris				break;
114776259Sgreen			}
114860573Skris		} else {
114992555Sdes			type = packet_read_poll1();
115092555Sdes			switch (type) {
115160573Skris			case SSH_MSG_IGNORE:
115260573Skris				break;
115360573Skris			case SSH_MSG_DEBUG:
115460573Skris				msg = packet_get_string(NULL);
115560573Skris				debug("Remote: %.900s", msg);
115660573Skris				xfree(msg);
115760573Skris				break;
115860573Skris			case SSH_MSG_DISCONNECT:
115960573Skris				msg = packet_get_string(NULL);
1160124208Sdes				logit("Received disconnect from %s: %.400s",
116199060Sdes				    get_remote_ipaddr(), msg);
1162126274Sdes				cleanup_exit(255);
116360573Skris				xfree(msg);
116460573Skris				break;
116560573Skris			default:
116692555Sdes				if (type)
116760573Skris					DBG(debug("received packet type %d", type));
116860573Skris				return type;
116960573Skris				break;
117076259Sgreen			}
117160573Skris		}
117260573Skris	}
117360573Skris}
117460573Skris
117592555Sdesint
117692555Sdespacket_read_poll(void)
117792555Sdes{
117892555Sdes	return packet_read_poll_seqnr(NULL);
117992555Sdes}
118092555Sdes
118157429Smarkm/*
118257429Smarkm * Buffers the given amount of input characters.  This is intended to be used
118357429Smarkm * together with packet_read_poll.
118457429Smarkm */
118557429Smarkm
118657429Smarkmvoid
118776259Sgreenpacket_process_incoming(const char *buf, u_int len)
118857429Smarkm{
118957429Smarkm	buffer_append(&input, buf, len);
119057429Smarkm}
119157429Smarkm
119257429Smarkm/* Returns a character from the packet. */
119357429Smarkm
119476259Sgreenu_int
119592555Sdespacket_get_char(void)
119657429Smarkm{
119757429Smarkm	char ch;
1198106121Sdes
119957429Smarkm	buffer_get(&incoming_packet, &ch, 1);
120076259Sgreen	return (u_char) ch;
120157429Smarkm}
120257429Smarkm
120357429Smarkm/* Returns an integer from the packet data. */
120457429Smarkm
120576259Sgreenu_int
120692555Sdespacket_get_int(void)
120757429Smarkm{
120857429Smarkm	return buffer_get_int(&incoming_packet);
120957429Smarkm}
121057429Smarkm
121157429Smarkm/*
121257429Smarkm * Returns an arbitrary precision integer from the packet data.  The integer
121357429Smarkm * must have been initialized before this call.
121457429Smarkm */
121557429Smarkm
121657429Smarkmvoid
121792555Sdespacket_get_bignum(BIGNUM * value)
121857429Smarkm{
121992555Sdes	buffer_get_bignum(&incoming_packet, value);
122057429Smarkm}
122157429Smarkm
122260573Skrisvoid
122392555Sdespacket_get_bignum2(BIGNUM * value)
122460573Skris{
122592555Sdes	buffer_get_bignum2(&incoming_packet, value);
122660573Skris}
122760573Skris
122892555Sdesvoid *
122960573Skrispacket_get_raw(int *length_ptr)
123060573Skris{
123160573Skris	int bytes = buffer_len(&incoming_packet);
1232106121Sdes
123360573Skris	if (length_ptr != NULL)
123460573Skris		*length_ptr = bytes;
123560573Skris	return buffer_ptr(&incoming_packet);
123660573Skris}
123760573Skris
123860573Skrisint
123960573Skrispacket_remaining(void)
124060573Skris{
124160573Skris	return buffer_len(&incoming_packet);
124260573Skris}
124360573Skris
124457429Smarkm/*
124557429Smarkm * Returns a string from the packet data.  The string is allocated using
124657429Smarkm * xmalloc; it is the responsibility of the calling program to free it when
124757429Smarkm * no longer needed.  The length_ptr argument may be NULL, or point to an
124857429Smarkm * integer into which the length of the string is stored.
124957429Smarkm */
125057429Smarkm
125192555Sdesvoid *
125276259Sgreenpacket_get_string(u_int *length_ptr)
125357429Smarkm{
125457429Smarkm	return buffer_get_string(&incoming_packet, length_ptr);
125557429Smarkm}
125657429Smarkm
125757429Smarkm/*
125857429Smarkm * Sends a diagnostic message from the server to the client.  This message
125957429Smarkm * can be sent at any time (but not while constructing another message). The
126057429Smarkm * message is printed immediately, but only if the client is being executed
126157429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
126257429Smarkm * authentication problems.   The length of the formatted message must not
126357429Smarkm * exceed 1024 bytes.  This will automatically call packet_write_wait.
126457429Smarkm */
126557429Smarkm
126657429Smarkmvoid
126757429Smarkmpacket_send_debug(const char *fmt,...)
126857429Smarkm{
126957429Smarkm	char buf[1024];
127057429Smarkm	va_list args;
127157429Smarkm
127276259Sgreen	if (compat20 && (datafellows & SSH_BUG_DEBUG))
127376259Sgreen		return;
127476259Sgreen
127557429Smarkm	va_start(args, fmt);
127657429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
127757429Smarkm	va_end(args);
127857429Smarkm
127960573Skris	if (compat20) {
128060573Skris		packet_start(SSH2_MSG_DEBUG);
128160573Skris		packet_put_char(0);	/* bool: always display */
128260573Skris		packet_put_cstring(buf);
128360573Skris		packet_put_cstring("");
128460573Skris	} else {
128560573Skris		packet_start(SSH_MSG_DEBUG);
128660573Skris		packet_put_cstring(buf);
128760573Skris	}
128857429Smarkm	packet_send();
128957429Smarkm	packet_write_wait();
129057429Smarkm}
129157429Smarkm
129257429Smarkm/*
129357429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
129457429Smarkm * connection, and exits.  This function never returns. The error message
129557429Smarkm * should not contain a newline.  The length of the formatted message must
129657429Smarkm * not exceed 1024 bytes.
129757429Smarkm */
129857429Smarkm
129957429Smarkmvoid
130057429Smarkmpacket_disconnect(const char *fmt,...)
130157429Smarkm{
130257429Smarkm	char buf[1024];
130357429Smarkm	va_list args;
130457429Smarkm	static int disconnecting = 0;
1305106121Sdes
130657429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
130757429Smarkm		fatal("packet_disconnect called recursively.");
130857429Smarkm	disconnecting = 1;
130957429Smarkm
131057429Smarkm	/*
131157429Smarkm	 * Format the message.  Note that the caller must make sure the
131257429Smarkm	 * message is of limited size.
131357429Smarkm	 */
131457429Smarkm	va_start(args, fmt);
131557429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
131657429Smarkm	va_end(args);
131757429Smarkm
1318113908Sdes	/* Display the error locally */
1319124208Sdes	logit("Disconnecting: %.100s", buf);
1320113908Sdes
132157429Smarkm	/* Send the disconnect message to the other side, and wait for it to get sent. */
132260573Skris	if (compat20) {
132360573Skris		packet_start(SSH2_MSG_DISCONNECT);
132460573Skris		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
132560573Skris		packet_put_cstring(buf);
132660573Skris		packet_put_cstring("");
132760573Skris	} else {
132860573Skris		packet_start(SSH_MSG_DISCONNECT);
132992555Sdes		packet_put_cstring(buf);
133060573Skris	}
133157429Smarkm	packet_send();
133257429Smarkm	packet_write_wait();
133357429Smarkm
133457429Smarkm	/* Stop listening for connections. */
133592555Sdes	channel_close_all();
133657429Smarkm
133757429Smarkm	/* Close the connection. */
133857429Smarkm	packet_close();
1339126274Sdes	cleanup_exit(255);
134057429Smarkm}
134157429Smarkm
134257429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */
134357429Smarkm
134457429Smarkmvoid
134592555Sdespacket_write_poll(void)
134657429Smarkm{
134757429Smarkm	int len = buffer_len(&output);
1348106121Sdes
134957429Smarkm	if (len > 0) {
135057429Smarkm		len = write(connection_out, buffer_ptr(&output), len);
135157429Smarkm		if (len <= 0) {
135257429Smarkm			if (errno == EAGAIN)
135357429Smarkm				return;
135457429Smarkm			else
135557429Smarkm				fatal("Write failed: %.100s", strerror(errno));
135657429Smarkm		}
135757429Smarkm		buffer_consume(&output, len);
135857429Smarkm	}
135957429Smarkm}
136057429Smarkm
136157429Smarkm/*
136257429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
136357429Smarkm * written.
136457429Smarkm */
136557429Smarkm
136657429Smarkmvoid
136792555Sdespacket_write_wait(void)
136857429Smarkm{
136976259Sgreen	fd_set *setp;
137076259Sgreen
137176259Sgreen	setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
137276259Sgreen	    sizeof(fd_mask));
137357429Smarkm	packet_write_poll();
137457429Smarkm	while (packet_have_data_to_write()) {
137576259Sgreen		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
137676259Sgreen		    sizeof(fd_mask));
137776259Sgreen		FD_SET(connection_out, setp);
137876259Sgreen		while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
137976259Sgreen		    (errno == EAGAIN || errno == EINTR))
138076259Sgreen			;
138157429Smarkm		packet_write_poll();
138257429Smarkm	}
138376259Sgreen	xfree(setp);
138457429Smarkm}
138557429Smarkm
138657429Smarkm/* Returns true if there is buffered data to write to the connection. */
138757429Smarkm
138857429Smarkmint
138992555Sdespacket_have_data_to_write(void)
139057429Smarkm{
139157429Smarkm	return buffer_len(&output) != 0;
139257429Smarkm}
139357429Smarkm
139457429Smarkm/* Returns true if there is not too much data to write to the connection. */
139557429Smarkm
139657429Smarkmint
139792555Sdespacket_not_very_much_data_to_write(void)
139857429Smarkm{
139957429Smarkm	if (interactive_mode)
140057429Smarkm		return buffer_len(&output) < 16384;
140157429Smarkm	else
140257429Smarkm		return buffer_len(&output) < 128 * 1024;
140357429Smarkm}
140457429Smarkm
1405124208Sdes
1406113908Sdesstatic void
1407113908Sdespacket_set_tos(int interactive)
1408113908Sdes{
1409126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1410113908Sdes	int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
1411113908Sdes
1412113908Sdes	if (!packet_connection_is_on_socket() ||
1413113908Sdes	    !packet_connection_is_ipv4())
1414113908Sdes		return;
1415113908Sdes	if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1416113908Sdes	    sizeof(tos)) < 0)
1417113908Sdes		error("setsockopt IP_TOS %d: %.100s:",
1418113908Sdes		    tos, strerror(errno));
1419126274Sdes#endif
1420113908Sdes}
1421113908Sdes
142257429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
142357429Smarkm
142457429Smarkmvoid
142576259Sgreenpacket_set_interactive(int interactive)
142657429Smarkm{
142776259Sgreen	static int called = 0;
142857429Smarkm
142976259Sgreen	if (called)
143076259Sgreen		return;
143176259Sgreen	called = 1;
143276259Sgreen
143357429Smarkm	/* Record that we are in interactive mode. */
143457429Smarkm	interactive_mode = interactive;
143557429Smarkm
143657429Smarkm	/* Only set socket options if using a socket.  */
143757429Smarkm	if (!packet_connection_is_on_socket())
1438116791Sdes		return;
1439113908Sdes	if (interactive)
144092555Sdes		set_nodelay(connection_in);
1441113908Sdes	packet_set_tos(interactive);
144257429Smarkm}
144357429Smarkm
144457429Smarkm/* Returns true if the current connection is interactive. */
144557429Smarkm
144657429Smarkmint
144792555Sdespacket_is_interactive(void)
144857429Smarkm{
144957429Smarkm	return interactive_mode;
145057429Smarkm}
145157429Smarkm
1452124208Sdesu_int
1453124208Sdespacket_set_maxsize(u_int s)
145457429Smarkm{
145557429Smarkm	static int called = 0;
1456106121Sdes
145757429Smarkm	if (called) {
1458124208Sdes		logit("packet_set_maxsize: called twice: old %d new %d",
145960573Skris		    max_packet_size, s);
146057429Smarkm		return -1;
146157429Smarkm	}
146257429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
1463124208Sdes		logit("packet_set_maxsize: bad size %d", s);
146457429Smarkm		return -1;
146557429Smarkm	}
146692555Sdes	called = 1;
146792555Sdes	debug("packet_set_maxsize: setting to %d", s);
146857429Smarkm	max_packet_size = s;
146957429Smarkm	return s;
147057429Smarkm}
147176259Sgreen
147292555Sdes/* roundup current message to pad bytes */
147392555Sdesvoid
147492555Sdespacket_add_padding(u_char pad)
147592555Sdes{
147692555Sdes	extra_pad = pad;
147792555Sdes}
147892555Sdes
147976259Sgreen/*
148076259Sgreen * 9.2.  Ignored Data Message
148176259Sgreen *
148276259Sgreen *   byte      SSH_MSG_IGNORE
148376259Sgreen *   string    data
148476259Sgreen *
148576259Sgreen * All implementations MUST understand (and ignore) this message at any
148676259Sgreen * time (after receiving the protocol version). No implementation is
148776259Sgreen * required to send them. This message can be used as an additional
148876259Sgreen * protection measure against advanced traffic analysis techniques.
148976259Sgreen */
149076259Sgreenvoid
149176259Sgreenpacket_send_ignore(int nbytes)
149276259Sgreen{
149376259Sgreen	u_int32_t rand = 0;
149476259Sgreen	int i;
149576259Sgreen
149676259Sgreen	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
149776259Sgreen	packet_put_int(nbytes);
149892555Sdes	for (i = 0; i < nbytes; i++) {
149976259Sgreen		if (i % 4 == 0)
150076259Sgreen			rand = arc4random();
150176259Sgreen		packet_put_char(rand & 0xff);
150276259Sgreen		rand >>= 8;
150376259Sgreen	}
150476259Sgreen}
1505124208Sdes
1506124208Sdes#define MAX_PACKETS	(1<<31)
1507124208Sdesint
1508124208Sdespacket_need_rekeying(void)
1509124208Sdes{
1510124208Sdes	if (datafellows & SSH_BUG_NOREKEY)
1511124208Sdes		return 0;
1512124208Sdes	return
1513124208Sdes	    (p_send.packets > MAX_PACKETS) ||
1514124208Sdes	    (p_read.packets > MAX_PACKETS) ||
1515124208Sdes	    (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1516124208Sdes	    (max_blocks_in  && (p_read.blocks > max_blocks_in));
1517124208Sdes}
1518124208Sdes
1519124208Sdesvoid
1520124208Sdespacket_set_rekey_limit(u_int32_t bytes)
1521124208Sdes{
1522124208Sdes	rekey_limit = bytes;
1523124208Sdes}
1524