packet.c revision 113908
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"
40113908SdesRCSID("$OpenBSD: packet.c,v 1.104 2003/04/01 10:22:21 markus Exp $");
4157429Smarkm
4257429Smarkm#include "xmalloc.h"
4357429Smarkm#include "buffer.h"
4457429Smarkm#include "packet.h"
4557429Smarkm#include "bufaux.h"
4657429Smarkm#include "crc32.h"
4757429Smarkm#include "getput.h"
4857429Smarkm
4957429Smarkm#include "compress.h"
5057429Smarkm#include "deattack.h"
5160573Skris#include "channels.h"
5257429Smarkm
5360573Skris#include "compat.h"
5476259Sgreen#include "ssh1.h"
5560573Skris#include "ssh2.h"
5660573Skris
5769587Sgreen#include "cipher.h"
5860573Skris#include "kex.h"
5976259Sgreen#include "mac.h"
6076259Sgreen#include "log.h"
6176259Sgreen#include "canohost.h"
6292555Sdes#include "misc.h"
6398675Sdes#include "ssh.h"
6460573Skris
6560573Skris#ifdef PACKET_DEBUG
6660573Skris#define DBG(x) x
6760573Skris#else
6860573Skris#define DBG(x)
6960573Skris#endif
7060573Skris
7157429Smarkm/*
7257429Smarkm * This variable contains the file descriptors used for communicating with
7357429Smarkm * the other side.  connection_in is used for reading; connection_out for
7457429Smarkm * writing.  These can be the same descriptor, in which case it is assumed to
7557429Smarkm * be a socket.
7657429Smarkm */
7757429Smarkmstatic int connection_in = -1;
7857429Smarkmstatic int connection_out = -1;
7957429Smarkm
8057429Smarkm/* Protocol flags for the remote side. */
8176259Sgreenstatic u_int remote_protocol_flags = 0;
8257429Smarkm
8357429Smarkm/* Encryption context for receiving data.  This is only used for decryption. */
8457429Smarkmstatic CipherContext receive_context;
8557429Smarkm
8657429Smarkm/* Encryption context for sending data.  This is only used for encryption. */
8757429Smarkmstatic CipherContext send_context;
8857429Smarkm
8957429Smarkm/* Buffer for raw input data from the socket. */
9098675SdesBuffer input;
9157429Smarkm
9257429Smarkm/* Buffer for raw output data going to the socket. */
9398675SdesBuffer output;
9457429Smarkm
9557429Smarkm/* Buffer for the partial outgoing packet being constructed. */
9657429Smarkmstatic Buffer outgoing_packet;
9757429Smarkm
9857429Smarkm/* Buffer for the incoming packet currently being processed. */
9957429Smarkmstatic Buffer incoming_packet;
10057429Smarkm
10157429Smarkm/* Scratch buffer for packet compression/decompression. */
10257429Smarkmstatic Buffer compression_buffer;
10376259Sgreenstatic int compression_buffer_ready = 0;
10457429Smarkm
10557429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */
10657429Smarkmstatic int packet_compression = 0;
10757429Smarkm
10857429Smarkm/* default maximum packet size */
10957429Smarkmint max_packet_size = 32768;
11057429Smarkm
11157429Smarkm/* Flag indicating whether this module has been initialized. */
11257429Smarkmstatic int initialized = 0;
11357429Smarkm
11457429Smarkm/* Set to true if the connection is interactive. */
11557429Smarkmstatic int interactive_mode = 0;
11657429Smarkm
11760573Skris/* Session key information for Encryption and MAC */
11876259SgreenNewkeys *newkeys[MODE_MAX];
11998675Sdesstatic u_int32_t read_seqnr = 0;
12098675Sdesstatic u_int32_t send_seqnr = 0;
12160573Skris
12298675Sdes/* Session key for protocol v1 */
12398675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
12498675Sdesstatic u_int ssh1_keylen;
12598675Sdes
12692555Sdes/* roundup current message to extra_pad bytes */
12792555Sdesstatic u_char extra_pad = 0;
12860573Skris
12957429Smarkm/*
13057429Smarkm * Sets the descriptors used for communication.  Disables encryption until
13157429Smarkm * packet_set_encryption_key is called.
13257429Smarkm */
13357429Smarkmvoid
13457429Smarkmpacket_set_connection(int fd_in, int fd_out)
13557429Smarkm{
13669587Sgreen	Cipher *none = cipher_by_name("none");
137106121Sdes
13869587Sgreen	if (none == NULL)
13969587Sgreen		fatal("packet_set_connection: cannot load cipher 'none'");
14057429Smarkm	connection_in = fd_in;
14157429Smarkm	connection_out = fd_out;
14292555Sdes	cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT);
14392555Sdes	cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
14492555Sdes	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
14557429Smarkm	if (!initialized) {
14657429Smarkm		initialized = 1;
14757429Smarkm		buffer_init(&input);
14857429Smarkm		buffer_init(&output);
14957429Smarkm		buffer_init(&outgoing_packet);
15057429Smarkm		buffer_init(&incoming_packet);
15157429Smarkm	}
15257429Smarkm	/* Kludge: arrange the close function to be called from fatal(). */
15357429Smarkm	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
15457429Smarkm}
15557429Smarkm
15657429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
15757429Smarkm
15857429Smarkmint
15992555Sdespacket_connection_is_on_socket(void)
16057429Smarkm{
16157429Smarkm	struct sockaddr_storage from, to;
16257429Smarkm	socklen_t fromlen, tolen;
16357429Smarkm
16457429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
16557429Smarkm	if (connection_in == connection_out)
16657429Smarkm		return 1;
16757429Smarkm	fromlen = sizeof(from);
16857429Smarkm	memset(&from, 0, sizeof(from));
16957429Smarkm	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
17057429Smarkm		return 0;
17157429Smarkm	tolen = sizeof(to);
17257429Smarkm	memset(&to, 0, sizeof(to));
17357429Smarkm	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
17457429Smarkm		return 0;
17557429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
17657429Smarkm		return 0;
17757429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
17857429Smarkm		return 0;
17957429Smarkm	return 1;
18057429Smarkm}
18157429Smarkm
18298675Sdes/*
18398675Sdes * Exports an IV from the CipherContext required to export the key
18498675Sdes * state back from the unprivileged child to the privileged parent
18598675Sdes * process.
18698675Sdes */
18798675Sdes
18898675Sdesvoid
18998675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
19098675Sdes{
19198675Sdes	CipherContext *cc;
19298675Sdes
19398675Sdes	if (mode == MODE_OUT)
19498675Sdes		cc = &send_context;
19598675Sdes	else
19698675Sdes		cc = &receive_context;
19798675Sdes
19898675Sdes	cipher_get_keyiv(cc, iv, len);
19998675Sdes}
20098675Sdes
20198675Sdesint
20298675Sdespacket_get_keycontext(int mode, u_char *dat)
20398675Sdes{
20498675Sdes	CipherContext *cc;
20598675Sdes
20698675Sdes	if (mode == MODE_OUT)
20798675Sdes		cc = &send_context;
20898675Sdes	else
20998675Sdes		cc = &receive_context;
21098675Sdes
21198675Sdes	return (cipher_get_keycontext(cc, dat));
21298675Sdes}
21398675Sdes
21498675Sdesvoid
21598675Sdespacket_set_keycontext(int mode, u_char *dat)
21698675Sdes{
21798675Sdes	CipherContext *cc;
21898675Sdes
21998675Sdes	if (mode == MODE_OUT)
22098675Sdes		cc = &send_context;
22198675Sdes	else
22298675Sdes		cc = &receive_context;
22398675Sdes
22498675Sdes	cipher_set_keycontext(cc, dat);
22598675Sdes}
22698675Sdes
22798675Sdesint
22898675Sdespacket_get_keyiv_len(int mode)
22998675Sdes{
23098675Sdes	CipherContext *cc;
23198675Sdes
23298675Sdes	if (mode == MODE_OUT)
23398675Sdes		cc = &send_context;
23498675Sdes	else
23598675Sdes		cc = &receive_context;
23698675Sdes
23798675Sdes	return (cipher_get_keyiv_len(cc));
23898675Sdes}
23998675Sdesvoid
24098675Sdespacket_set_iv(int mode, u_char *dat)
24198675Sdes{
24298675Sdes	CipherContext *cc;
24398675Sdes
24498675Sdes	if (mode == MODE_OUT)
24598675Sdes		cc = &send_context;
24698675Sdes	else
24798675Sdes		cc = &receive_context;
24898675Sdes
24998675Sdes	cipher_set_keyiv(cc, dat);
25098675Sdes}
25198675Sdesint
25298675Sdespacket_get_ssh1_cipher()
25398675Sdes{
25498675Sdes	return (cipher_get_number(receive_context.cipher));
25598675Sdes}
25698675Sdes
25798675Sdes
25898675Sdesu_int32_t
25998675Sdespacket_get_seqnr(int mode)
26098675Sdes{
26198675Sdes	return (mode == MODE_IN ? read_seqnr : send_seqnr);
26298675Sdes}
26398675Sdes
26498675Sdesvoid
26598675Sdespacket_set_seqnr(int mode, u_int32_t seqnr)
26698675Sdes{
26798675Sdes	if (mode == MODE_IN)
26898675Sdes		read_seqnr = seqnr;
26998675Sdes	else if (mode == MODE_OUT)
27098675Sdes		send_seqnr = seqnr;
27198675Sdes	else
27298675Sdes		fatal("packet_set_seqnr: bad mode %d", mode);
27398675Sdes}
27498675Sdes
27557429Smarkm/* returns 1 if connection is via ipv4 */
27657429Smarkm
27757429Smarkmint
27892555Sdespacket_connection_is_ipv4(void)
27957429Smarkm{
28057429Smarkm	struct sockaddr_storage to;
28157429Smarkm	socklen_t tolen = sizeof(to);
28257429Smarkm
28357429Smarkm	memset(&to, 0, sizeof(to));
28457429Smarkm	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
28557429Smarkm		return 0;
28698937Sdes	if (to.ss_family == AF_INET)
28798937Sdes		return 1;
28898937Sdes#ifdef IPV4_IN_IPV6
28998937Sdes	if (to.ss_family == AF_INET6 &&
29098937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
29198937Sdes		return 1;
29298937Sdes#endif
29398937Sdes	return 0;
29457429Smarkm}
29557429Smarkm
29657429Smarkm/* Sets the connection into non-blocking mode. */
29757429Smarkm
29857429Smarkmvoid
29992555Sdespacket_set_nonblocking(void)
30057429Smarkm{
30157429Smarkm	/* Set the socket into non-blocking mode. */
30257429Smarkm	if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
30357429Smarkm		error("fcntl O_NONBLOCK: %.100s", strerror(errno));
30457429Smarkm
30557429Smarkm	if (connection_out != connection_in) {
30657429Smarkm		if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
30757429Smarkm			error("fcntl O_NONBLOCK: %.100s", strerror(errno));
30857429Smarkm	}
30957429Smarkm}
31057429Smarkm
31157429Smarkm/* Returns the socket used for reading. */
31257429Smarkm
31357429Smarkmint
31492555Sdespacket_get_connection_in(void)
31557429Smarkm{
31657429Smarkm	return connection_in;
31757429Smarkm}
31857429Smarkm
31957429Smarkm/* Returns the descriptor used for writing. */
32057429Smarkm
32157429Smarkmint
32292555Sdespacket_get_connection_out(void)
32357429Smarkm{
32457429Smarkm	return connection_out;
32557429Smarkm}
32657429Smarkm
32757429Smarkm/* Closes the connection and clears and frees internal data structures. */
32857429Smarkm
32957429Smarkmvoid
33092555Sdespacket_close(void)
33157429Smarkm{
33257429Smarkm	if (!initialized)
33357429Smarkm		return;
33457429Smarkm	initialized = 0;
33557429Smarkm	if (connection_in == connection_out) {
33657429Smarkm		shutdown(connection_out, SHUT_RDWR);
33757429Smarkm		close(connection_out);
33857429Smarkm	} else {
33957429Smarkm		close(connection_in);
34057429Smarkm		close(connection_out);
34157429Smarkm	}
34257429Smarkm	buffer_free(&input);
34357429Smarkm	buffer_free(&output);
34457429Smarkm	buffer_free(&outgoing_packet);
34557429Smarkm	buffer_free(&incoming_packet);
34676259Sgreen	if (compression_buffer_ready) {
34757429Smarkm		buffer_free(&compression_buffer);
34857429Smarkm		buffer_compress_uninit();
34957429Smarkm	}
35092555Sdes	cipher_cleanup(&send_context);
35192555Sdes	cipher_cleanup(&receive_context);
35257429Smarkm}
35357429Smarkm
35457429Smarkm/* Sets remote side protocol flags. */
35557429Smarkm
35657429Smarkmvoid
35776259Sgreenpacket_set_protocol_flags(u_int protocol_flags)
35857429Smarkm{
35957429Smarkm	remote_protocol_flags = protocol_flags;
36057429Smarkm}
36157429Smarkm
36257429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
36357429Smarkm
36476259Sgreenu_int
36592555Sdespacket_get_protocol_flags(void)
36657429Smarkm{
36757429Smarkm	return remote_protocol_flags;
36857429Smarkm}
36957429Smarkm
37057429Smarkm/*
37157429Smarkm * Starts packet compression from the next packet on in both directions.
37257429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
37357429Smarkm */
37457429Smarkm
37592555Sdesstatic void
37692555Sdespacket_init_compression(void)
37776259Sgreen{
37876259Sgreen	if (compression_buffer_ready == 1)
37976259Sgreen		return;
38076259Sgreen	compression_buffer_ready = 1;
38176259Sgreen	buffer_init(&compression_buffer);
38276259Sgreen}
38376259Sgreen
38476259Sgreenvoid
38557429Smarkmpacket_start_compression(int level)
38657429Smarkm{
38792555Sdes	if (packet_compression && !compat20)
38857429Smarkm		fatal("Compression already enabled.");
38957429Smarkm	packet_compression = 1;
39076259Sgreen	packet_init_compression();
39176259Sgreen	buffer_compress_init_send(level);
39276259Sgreen	buffer_compress_init_recv();
39357429Smarkm}
39457429Smarkm
39557429Smarkm/*
39657429Smarkm * Causes any further packets to be encrypted using the given key.  The same
39757429Smarkm * key is used for both sending and reception.  However, both directions are
39857429Smarkm * encrypted independently of each other.
39957429Smarkm */
40098675Sdes
40157429Smarkmvoid
40276259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen,
40369587Sgreen    int number)
40457429Smarkm{
40569587Sgreen	Cipher *cipher = cipher_by_number(number);
406106121Sdes
40769587Sgreen	if (cipher == NULL)
40869587Sgreen		fatal("packet_set_encryption_key: unknown cipher number %d", number);
40960573Skris	if (keylen < 20)
41069587Sgreen		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
41198675Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
41298675Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
41398675Sdes	memcpy(ssh1_key, key, keylen);
41498675Sdes	ssh1_keylen = keylen;
41592555Sdes	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
41692555Sdes	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
41757429Smarkm}
41857429Smarkm
41998675Sdesu_int
42098675Sdespacket_get_encryption_key(u_char *key)
42198675Sdes{
42298675Sdes	if (key == NULL)
42398675Sdes		return (ssh1_keylen);
42498675Sdes	memcpy(key, ssh1_key, ssh1_keylen);
42598675Sdes	return (ssh1_keylen);
42698675Sdes}
42798675Sdes
42892555Sdes/* Start constructing a packet to send. */
42957429Smarkmvoid
43092555Sdespacket_start(u_char type)
43157429Smarkm{
43292555Sdes	u_char buf[9];
43392555Sdes	int len;
43457429Smarkm
43592555Sdes	DBG(debug("packet_start[%d]", type));
43692555Sdes	len = compat20 ? 6 : 9;
43792555Sdes	memset(buf, 0, len - 1);
43892555Sdes	buf[len - 1] = type;
43957429Smarkm	buffer_clear(&outgoing_packet);
44092555Sdes	buffer_append(&outgoing_packet, buf, len);
44157429Smarkm}
44257429Smarkm
44392555Sdes/* Append payload. */
44460573Skrisvoid
44557429Smarkmpacket_put_char(int value)
44657429Smarkm{
44757429Smarkm	char ch = value;
448106121Sdes
44957429Smarkm	buffer_append(&outgoing_packet, &ch, 1);
45057429Smarkm}
45157429Smarkmvoid
45276259Sgreenpacket_put_int(u_int value)
45357429Smarkm{
45457429Smarkm	buffer_put_int(&outgoing_packet, value);
45557429Smarkm}
45657429Smarkmvoid
45792555Sdespacket_put_string(const void *buf, u_int len)
45857429Smarkm{
45957429Smarkm	buffer_put_string(&outgoing_packet, buf, len);
46057429Smarkm}
46160573Skrisvoid
46260573Skrispacket_put_cstring(const char *str)
46360573Skris{
46492555Sdes	buffer_put_cstring(&outgoing_packet, str);
46560573Skris}
46660573Skrisvoid
46792555Sdespacket_put_raw(const void *buf, u_int len)
46860573Skris{
46960573Skris	buffer_append(&outgoing_packet, buf, len);
47060573Skris}
47157429Smarkmvoid
47257429Smarkmpacket_put_bignum(BIGNUM * value)
47357429Smarkm{
47457429Smarkm	buffer_put_bignum(&outgoing_packet, value);
47557429Smarkm}
47660573Skrisvoid
47760573Skrispacket_put_bignum2(BIGNUM * value)
47860573Skris{
47960573Skris	buffer_put_bignum2(&outgoing_packet, value);
48060573Skris}
48157429Smarkm
48257429Smarkm/*
48357429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
48457429Smarkm * encrypts the packet before sending.
48557429Smarkm */
48657429Smarkm
48792555Sdesstatic void
48876259Sgreenpacket_send1(void)
48957429Smarkm{
49092555Sdes	u_char buf[8], *cp;
49157429Smarkm	int i, padding, len;
49276259Sgreen	u_int checksum;
49357429Smarkm	u_int32_t rand = 0;
49457429Smarkm
49557429Smarkm	/*
49657429Smarkm	 * If using packet compression, compress the payload of the outgoing
49757429Smarkm	 * packet.
49857429Smarkm	 */
49957429Smarkm	if (packet_compression) {
50057429Smarkm		buffer_clear(&compression_buffer);
50157429Smarkm		/* Skip padding. */
50257429Smarkm		buffer_consume(&outgoing_packet, 8);
50357429Smarkm		/* padding */
50457429Smarkm		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
50557429Smarkm		buffer_compress(&outgoing_packet, &compression_buffer);
50657429Smarkm		buffer_clear(&outgoing_packet);
50757429Smarkm		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
50892555Sdes		    buffer_len(&compression_buffer));
50957429Smarkm	}
51057429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
51157429Smarkm	len = buffer_len(&outgoing_packet) + 4 - 8;
51257429Smarkm
51360573Skris	/* Insert padding. Initialized to zero in packet_start1() */
51457429Smarkm	padding = 8 - len % 8;
51592555Sdes	if (!send_context.plaintext) {
51657429Smarkm		cp = buffer_ptr(&outgoing_packet);
51757429Smarkm		for (i = 0; i < padding; i++) {
51857429Smarkm			if (i % 4 == 0)
51957429Smarkm				rand = arc4random();
52057429Smarkm			cp[7 - i] = rand & 0xff;
52157429Smarkm			rand >>= 8;
52257429Smarkm		}
52357429Smarkm	}
52457429Smarkm	buffer_consume(&outgoing_packet, 8 - padding);
52557429Smarkm
52657429Smarkm	/* Add check bytes. */
52792555Sdes	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
52865668Skris	    buffer_len(&outgoing_packet));
52957429Smarkm	PUT_32BIT(buf, checksum);
53057429Smarkm	buffer_append(&outgoing_packet, buf, 4);
53157429Smarkm
53257429Smarkm#ifdef PACKET_DEBUG
53357429Smarkm	fprintf(stderr, "packet_send plain: ");
53457429Smarkm	buffer_dump(&outgoing_packet);
53557429Smarkm#endif
53657429Smarkm
53757429Smarkm	/* Append to output. */
53857429Smarkm	PUT_32BIT(buf, len);
53957429Smarkm	buffer_append(&output, buf, 4);
54092555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
54192555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
54292555Sdes	    buffer_len(&outgoing_packet));
54357429Smarkm
54457429Smarkm#ifdef PACKET_DEBUG
54557429Smarkm	fprintf(stderr, "encrypted: ");
54657429Smarkm	buffer_dump(&output);
54757429Smarkm#endif
54857429Smarkm
54957429Smarkm	buffer_clear(&outgoing_packet);
55057429Smarkm
55157429Smarkm	/*
55257429Smarkm	 * Note that the packet is now only buffered in output.  It won\'t be
55357429Smarkm	 * actually sent until packet_write_wait or packet_write_poll is
55457429Smarkm	 * called.
55557429Smarkm	 */
55657429Smarkm}
55757429Smarkm
55898675Sdesvoid
55976259Sgreenset_newkeys(int mode)
56076259Sgreen{
56176259Sgreen	Enc *enc;
56276259Sgreen	Mac *mac;
56376259Sgreen	Comp *comp;
56476259Sgreen	CipherContext *cc;
56592555Sdes	int encrypt;
56676259Sgreen
567113908Sdes	debug2("set_newkeys: mode %d", mode);
56876259Sgreen
56992555Sdes	if (mode == MODE_OUT) {
57092555Sdes		cc = &send_context;
57192555Sdes		encrypt = CIPHER_ENCRYPT;
57292555Sdes	} else {
57392555Sdes		cc = &receive_context;
57492555Sdes		encrypt = CIPHER_DECRYPT;
57592555Sdes	}
57676259Sgreen	if (newkeys[mode] != NULL) {
577113908Sdes		debug("set_newkeys: rekeying");
57892555Sdes		cipher_cleanup(cc);
57976259Sgreen		enc  = &newkeys[mode]->enc;
58076259Sgreen		mac  = &newkeys[mode]->mac;
58176259Sgreen		comp = &newkeys[mode]->comp;
58276259Sgreen		memset(mac->key, 0, mac->key_len);
58376259Sgreen		xfree(enc->name);
58476259Sgreen		xfree(enc->iv);
58576259Sgreen		xfree(enc->key);
58676259Sgreen		xfree(mac->name);
58776259Sgreen		xfree(mac->key);
58876259Sgreen		xfree(comp->name);
58976259Sgreen		xfree(newkeys[mode]);
59076259Sgreen	}
59176259Sgreen	newkeys[mode] = kex_get_newkeys(mode);
59276259Sgreen	if (newkeys[mode] == NULL)
59376259Sgreen		fatal("newkeys: no keys for mode %d", mode);
59476259Sgreen	enc  = &newkeys[mode]->enc;
59576259Sgreen	mac  = &newkeys[mode]->mac;
59676259Sgreen	comp = &newkeys[mode]->comp;
59776259Sgreen	if (mac->md != NULL)
59876259Sgreen		mac->enabled = 1;
59976259Sgreen	DBG(debug("cipher_init_context: %d", mode));
60092555Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
60192555Sdes	    enc->iv, enc->block_size, encrypt);
60298675Sdes	/* Deleting the keys does not gain extra security */
60398675Sdes	/* memset(enc->iv,  0, enc->block_size);
60498675Sdes	   memset(enc->key, 0, enc->key_len); */
60576259Sgreen	if (comp->type != 0 && comp->enabled == 0) {
60676259Sgreen		packet_init_compression();
60776259Sgreen		if (mode == MODE_OUT)
60876259Sgreen			buffer_compress_init_send(6);
60976259Sgreen		else
61076259Sgreen			buffer_compress_init_recv();
61176259Sgreen		comp->enabled = 1;
61276259Sgreen	}
61376259Sgreen}
61476259Sgreen
61557429Smarkm/*
61660573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
61760573Skris */
61892555Sdesstatic void
61976259Sgreenpacket_send2(void)
62060573Skris{
62192555Sdes	u_char type, *cp, *macbuf = NULL;
62292555Sdes	u_char padlen, pad;
62376259Sgreen	u_int packet_length = 0;
62492555Sdes	u_int i, len;
62560573Skris	u_int32_t rand = 0;
62660573Skris	Enc *enc   = NULL;
62760573Skris	Mac *mac   = NULL;
62860573Skris	Comp *comp = NULL;
62960573Skris	int block_size;
63060573Skris
63176259Sgreen	if (newkeys[MODE_OUT] != NULL) {
63276259Sgreen		enc  = &newkeys[MODE_OUT]->enc;
63376259Sgreen		mac  = &newkeys[MODE_OUT]->mac;
63476259Sgreen		comp = &newkeys[MODE_OUT]->comp;
63560573Skris	}
63692555Sdes	block_size = enc ? enc->block_size : 8;
63760573Skris
63860573Skris	cp = buffer_ptr(&outgoing_packet);
63992555Sdes	type = cp[5];
64060573Skris
64160573Skris#ifdef PACKET_DEBUG
64260573Skris	fprintf(stderr, "plain:     ");
64360573Skris	buffer_dump(&outgoing_packet);
64460573Skris#endif
64560573Skris
64660573Skris	if (comp && comp->enabled) {
64760573Skris		len = buffer_len(&outgoing_packet);
64860573Skris		/* skip header, compress only payload */
64960573Skris		buffer_consume(&outgoing_packet, 5);
65060573Skris		buffer_clear(&compression_buffer);
65160573Skris		buffer_compress(&outgoing_packet, &compression_buffer);
65260573Skris		buffer_clear(&outgoing_packet);
65360573Skris		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
65460573Skris		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
65560573Skris		    buffer_len(&compression_buffer));
65660573Skris		DBG(debug("compression: raw %d compressed %d", len,
65760573Skris		    buffer_len(&outgoing_packet)));
65860573Skris	}
65960573Skris
66060573Skris	/* sizeof (packet_len + pad_len + payload) */
66160573Skris	len = buffer_len(&outgoing_packet);
66260573Skris
66360573Skris	/*
66460573Skris	 * calc size of padding, alloc space, get random data,
66560573Skris	 * minimum padding is 4 bytes
66660573Skris	 */
66760573Skris	padlen = block_size - (len % block_size);
66860573Skris	if (padlen < 4)
66960573Skris		padlen += block_size;
67092555Sdes	if (extra_pad) {
67192555Sdes		/* will wrap if extra_pad+padlen > 255 */
67292555Sdes		extra_pad  = roundup(extra_pad, block_size);
67392555Sdes		pad = extra_pad - ((len + padlen) % extra_pad);
67498675Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
67592555Sdes		    pad, len, padlen, extra_pad);
67692555Sdes		padlen += pad;
67792555Sdes		extra_pad = 0;
67892555Sdes	}
67992555Sdes	cp = buffer_append_space(&outgoing_packet, padlen);
68092555Sdes	if (enc && !send_context.plaintext) {
68160573Skris		/* random padding */
68260573Skris		for (i = 0; i < padlen; i++) {
68360573Skris			if (i % 4 == 0)
68460573Skris				rand = arc4random();
68560573Skris			cp[i] = rand & 0xff;
68676259Sgreen			rand >>= 8;
68760573Skris		}
68860573Skris	} else {
68960573Skris		/* clear padding */
69060573Skris		memset(cp, 0, padlen);
69160573Skris	}
69260573Skris	/* packet_length includes payload, padding and padding length field */
69360573Skris	packet_length = buffer_len(&outgoing_packet) - 4;
69460573Skris	cp = buffer_ptr(&outgoing_packet);
69560573Skris	PUT_32BIT(cp, packet_length);
69692555Sdes	cp[4] = padlen;
69760573Skris	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
69860573Skris
69960573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
70060573Skris	if (mac && mac->enabled) {
70198675Sdes		macbuf = mac_compute(mac, send_seqnr,
70292555Sdes		    buffer_ptr(&outgoing_packet),
70376259Sgreen		    buffer_len(&outgoing_packet));
70498675Sdes		DBG(debug("done calc MAC out #%d", send_seqnr));
70560573Skris	}
70660573Skris	/* encrypt packet and append to output buffer. */
70792555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
70892555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
70960573Skris	    buffer_len(&outgoing_packet));
71060573Skris	/* append unencrypted MAC */
71160573Skris	if (mac && mac->enabled)
71260573Skris		buffer_append(&output, (char *)macbuf, mac->mac_len);
71360573Skris#ifdef PACKET_DEBUG
71460573Skris	fprintf(stderr, "encrypted: ");
71560573Skris	buffer_dump(&output);
71660573Skris#endif
71760573Skris	/* increment sequence number for outgoing packets */
71898675Sdes	if (++send_seqnr == 0)
71960573Skris		log("outgoing seqnr wraps around");
72060573Skris	buffer_clear(&outgoing_packet);
72160573Skris
72276259Sgreen	if (type == SSH2_MSG_NEWKEYS)
72376259Sgreen		set_newkeys(MODE_OUT);
72460573Skris}
72560573Skris
72660573Skrisvoid
72792555Sdespacket_send(void)
72860573Skris{
72992555Sdes	if (compat20)
73060573Skris		packet_send2();
73160573Skris	else
73260573Skris		packet_send1();
73360573Skris	DBG(debug("packet_send done"));
73460573Skris}
73560573Skris
73660573Skris/*
73757429Smarkm * Waits until a packet has been received, and returns its type.  Note that
73857429Smarkm * no other data is processed until this returns, so this function should not
73957429Smarkm * be used during the interactive session.
74057429Smarkm */
74157429Smarkm
74257429Smarkmint
74392555Sdespacket_read_seqnr(u_int32_t *seqnr_p)
74457429Smarkm{
74557429Smarkm	int type, len;
74676259Sgreen	fd_set *setp;
74757429Smarkm	char buf[8192];
74860573Skris	DBG(debug("packet_read()"));
74957429Smarkm
75076259Sgreen	setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
75176259Sgreen	    sizeof(fd_mask));
75276259Sgreen
75357429Smarkm	/* Since we are blocking, ensure that all written packets have been sent. */
75457429Smarkm	packet_write_wait();
75557429Smarkm
75657429Smarkm	/* Stay in the loop until we have received a complete packet. */
75757429Smarkm	for (;;) {
75857429Smarkm		/* Try to read a packet from the buffer. */
75992555Sdes		type = packet_read_poll_seqnr(seqnr_p);
76092555Sdes		if (!compat20 && (
76160573Skris		    type == SSH_SMSG_SUCCESS
76257429Smarkm		    || type == SSH_SMSG_FAILURE
76357429Smarkm		    || type == SSH_CMSG_EOF
76460573Skris		    || type == SSH_CMSG_EXIT_CONFIRMATION))
76592555Sdes			packet_check_eom();
76657429Smarkm		/* If we got a packet, return it. */
76776259Sgreen		if (type != SSH_MSG_NONE) {
76876259Sgreen			xfree(setp);
76957429Smarkm			return type;
77076259Sgreen		}
77157429Smarkm		/*
77257429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
77357429Smarkm		 * buffer, and try again.
77457429Smarkm		 */
77576259Sgreen		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
77676259Sgreen		    sizeof(fd_mask));
77776259Sgreen		FD_SET(connection_in, setp);
77857429Smarkm
77957429Smarkm		/* Wait for some data to arrive. */
78076259Sgreen		while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
78176259Sgreen		    (errno == EAGAIN || errno == EINTR))
78276259Sgreen			;
78357429Smarkm
78457429Smarkm		/* Read data from the socket. */
78557429Smarkm		len = read(connection_in, buf, sizeof(buf));
78657429Smarkm		if (len == 0) {
78757429Smarkm			log("Connection closed by %.200s", get_remote_ipaddr());
78857429Smarkm			fatal_cleanup();
78957429Smarkm		}
79057429Smarkm		if (len < 0)
79157429Smarkm			fatal("Read from socket failed: %.100s", strerror(errno));
79257429Smarkm		/* Append it to the buffer. */
79357429Smarkm		packet_process_incoming(buf, len);
79457429Smarkm	}
79557429Smarkm	/* NOTREACHED */
79657429Smarkm}
79757429Smarkm
79892555Sdesint
79992555Sdespacket_read(void)
80092555Sdes{
80192555Sdes	return packet_read_seqnr(NULL);
80292555Sdes}
80392555Sdes
80457429Smarkm/*
80557429Smarkm * Waits until a packet has been received, verifies that its type matches
80657429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
80757429Smarkm */
80857429Smarkm
80957429Smarkmvoid
81092555Sdespacket_read_expect(int expected_type)
81157429Smarkm{
81257429Smarkm	int type;
81357429Smarkm
81492555Sdes	type = packet_read();
81557429Smarkm	if (type != expected_type)
81657429Smarkm		packet_disconnect("Protocol error: expected packet type %d, got %d",
81760573Skris		    expected_type, type);
81857429Smarkm}
81957429Smarkm
82057429Smarkm/* Checks if a full packet is available in the data received so far via
82157429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
82257429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
82357429Smarkm *
82457429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
82557429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
82657429Smarkm * to higher levels.
82757429Smarkm */
82857429Smarkm
82992555Sdesstatic int
83092555Sdespacket_read_poll1(void)
83157429Smarkm{
83276259Sgreen	u_int len, padded_len;
83392555Sdes	u_char *cp, type;
83476259Sgreen	u_int checksum, stored_checksum;
83557429Smarkm
83657429Smarkm	/* Check if input size is less than minimum packet size. */
83757429Smarkm	if (buffer_len(&input) < 4 + 8)
83857429Smarkm		return SSH_MSG_NONE;
83957429Smarkm	/* Get length of incoming packet. */
84092555Sdes	cp = buffer_ptr(&input);
84192555Sdes	len = GET_32BIT(cp);
84257429Smarkm	if (len < 1 + 2 + 2 || len > 256 * 1024)
843113908Sdes		packet_disconnect("Bad packet length %u.", len);
84457429Smarkm	padded_len = (len + 8) & ~7;
84557429Smarkm
84657429Smarkm	/* Check if the packet has been entirely received. */
84757429Smarkm	if (buffer_len(&input) < 4 + padded_len)
84857429Smarkm		return SSH_MSG_NONE;
84957429Smarkm
85057429Smarkm	/* The entire packet is in buffer. */
85157429Smarkm
85257429Smarkm	/* Consume packet length. */
85357429Smarkm	buffer_consume(&input, 4);
85457429Smarkm
85592555Sdes	/*
85692555Sdes	 * Cryptographic attack detector for ssh
85792555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
85892555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
85992555Sdes	 */
86092555Sdes	if (!receive_context.plaintext &&
86192555Sdes	    detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)
86292555Sdes		packet_disconnect("crc32 compensation attack: network attack detected");
86392555Sdes
86492555Sdes	/* Decrypt data to incoming_packet. */
86557429Smarkm	buffer_clear(&incoming_packet);
86692555Sdes	cp = buffer_append_space(&incoming_packet, padded_len);
86792555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
86892555Sdes
86957429Smarkm	buffer_consume(&input, padded_len);
87057429Smarkm
87157429Smarkm#ifdef PACKET_DEBUG
87257429Smarkm	fprintf(stderr, "read_poll plain: ");
87357429Smarkm	buffer_dump(&incoming_packet);
87457429Smarkm#endif
87557429Smarkm
87657429Smarkm	/* Compute packet checksum. */
87792555Sdes	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
87860573Skris	    buffer_len(&incoming_packet) - 4);
87957429Smarkm
88057429Smarkm	/* Skip padding. */
88157429Smarkm	buffer_consume(&incoming_packet, 8 - len % 8);
88257429Smarkm
88357429Smarkm	/* Test check bytes. */
88457429Smarkm	if (len != buffer_len(&incoming_packet))
88592555Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
88660573Skris		    len, buffer_len(&incoming_packet));
88757429Smarkm
88892555Sdes	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
88992555Sdes	stored_checksum = GET_32BIT(cp);
89057429Smarkm	if (checksum != stored_checksum)
89157429Smarkm		packet_disconnect("Corrupted check bytes on input.");
89257429Smarkm	buffer_consume_end(&incoming_packet, 4);
89357429Smarkm
89457429Smarkm	if (packet_compression) {
89557429Smarkm		buffer_clear(&compression_buffer);
89657429Smarkm		buffer_uncompress(&incoming_packet, &compression_buffer);
89757429Smarkm		buffer_clear(&incoming_packet);
89857429Smarkm		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
89960573Skris		    buffer_len(&compression_buffer));
90057429Smarkm	}
90192555Sdes	type = buffer_get_char(&incoming_packet);
90292555Sdes	return type;
90360573Skris}
90457429Smarkm
90592555Sdesstatic int
90692555Sdespacket_read_poll2(u_int32_t *seqnr_p)
90760573Skris{
90876259Sgreen	static u_int packet_length = 0;
90976259Sgreen	u_int padlen, need;
91092555Sdes	u_char *macbuf, *cp, type;
91160573Skris	int maclen, block_size;
91260573Skris	Enc *enc   = NULL;
91360573Skris	Mac *mac   = NULL;
91460573Skris	Comp *comp = NULL;
91557429Smarkm
91676259Sgreen	if (newkeys[MODE_IN] != NULL) {
91776259Sgreen		enc  = &newkeys[MODE_IN]->enc;
91876259Sgreen		mac  = &newkeys[MODE_IN]->mac;
91976259Sgreen		comp = &newkeys[MODE_IN]->comp;
92057429Smarkm	}
92160573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
92292555Sdes	block_size = enc ? enc->block_size : 8;
92360573Skris
92460573Skris	if (packet_length == 0) {
92560573Skris		/*
92660573Skris		 * check if input size is less than the cipher block size,
92760573Skris		 * decrypt first block and extract length of incoming packet
92860573Skris		 */
92960573Skris		if (buffer_len(&input) < block_size)
93060573Skris			return SSH_MSG_NONE;
93160573Skris		buffer_clear(&incoming_packet);
93292555Sdes		cp = buffer_append_space(&incoming_packet, block_size);
93392555Sdes		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
93460573Skris		    block_size);
93592555Sdes		cp = buffer_ptr(&incoming_packet);
93692555Sdes		packet_length = GET_32BIT(cp);
93760573Skris		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
93860573Skris			buffer_dump(&incoming_packet);
939113908Sdes			packet_disconnect("Bad packet length %u.", packet_length);
94060573Skris		}
941113908Sdes		DBG(debug("input: packet len %u", packet_length+4));
94260573Skris		buffer_consume(&input, block_size);
94360573Skris	}
94460573Skris	/* we have a partial packet of block_size bytes */
94560573Skris	need = 4 + packet_length - block_size;
94660573Skris	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
94760573Skris	    need, maclen));
94860573Skris	if (need % block_size != 0)
94960573Skris		fatal("padding error: need %d block %d mod %d",
95060573Skris		    need, block_size, need % block_size);
95160573Skris	/*
95260573Skris	 * check if the entire packet has been received and
95360573Skris	 * decrypt into incoming_packet
95460573Skris	 */
95560573Skris	if (buffer_len(&input) < need + maclen)
95660573Skris		return SSH_MSG_NONE;
95760573Skris#ifdef PACKET_DEBUG
95860573Skris	fprintf(stderr, "read_poll enc/full: ");
95960573Skris	buffer_dump(&input);
96060573Skris#endif
96192555Sdes	cp = buffer_append_space(&incoming_packet, need);
96292555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
96360573Skris	buffer_consume(&input, need);
96460573Skris	/*
96560573Skris	 * compute MAC over seqnr and packet,
96660573Skris	 * increment sequence number for incoming packet
96760573Skris	 */
96860573Skris	if (mac && mac->enabled) {
96998675Sdes		macbuf = mac_compute(mac, read_seqnr,
97092555Sdes		    buffer_ptr(&incoming_packet),
97176259Sgreen		    buffer_len(&incoming_packet));
97260573Skris		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
97369587Sgreen			packet_disconnect("Corrupted MAC on input.");
97498675Sdes		DBG(debug("MAC #%d ok", read_seqnr));
97560573Skris		buffer_consume(&input, mac->mac_len);
97660573Skris	}
97792555Sdes	if (seqnr_p != NULL)
97898675Sdes		*seqnr_p = read_seqnr;
97998675Sdes	if (++read_seqnr == 0)
98060573Skris		log("incoming seqnr wraps around");
98160573Skris
98260573Skris	/* get padlen */
98392555Sdes	cp = buffer_ptr(&incoming_packet);
98492555Sdes	padlen = cp[4];
98560573Skris	DBG(debug("input: padlen %d", padlen));
98660573Skris	if (padlen < 4)
98760573Skris		packet_disconnect("Corrupted padlen %d on input.", padlen);
98860573Skris
98960573Skris	/* skip packet size + padlen, discard padding */
99060573Skris	buffer_consume(&incoming_packet, 4 + 1);
99160573Skris	buffer_consume_end(&incoming_packet, padlen);
99260573Skris
99360573Skris	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
99460573Skris	if (comp && comp->enabled) {
99560573Skris		buffer_clear(&compression_buffer);
99660573Skris		buffer_uncompress(&incoming_packet, &compression_buffer);
99760573Skris		buffer_clear(&incoming_packet);
99860573Skris		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
99960573Skris		    buffer_len(&compression_buffer));
1000106121Sdes		DBG(debug("input: len after de-compress %d",
1001106121Sdes		    buffer_len(&incoming_packet)));
100260573Skris	}
100360573Skris	/*
100460573Skris	 * get packet type, implies consume.
100560573Skris	 * return length of payload (without type field)
100660573Skris	 */
100792555Sdes	type = buffer_get_char(&incoming_packet);
100876259Sgreen	if (type == SSH2_MSG_NEWKEYS)
100976259Sgreen		set_newkeys(MODE_IN);
101060573Skris#ifdef PACKET_DEBUG
101176259Sgreen	fprintf(stderr, "read/plain[%d]:\r\n", type);
101260573Skris	buffer_dump(&incoming_packet);
101360573Skris#endif
101492555Sdes	/* reset for next packet */
101592555Sdes	packet_length = 0;
101692555Sdes	return type;
101757429Smarkm}
101857429Smarkm
101960573Skrisint
102092555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
102160573Skris{
102299060Sdes	u_int reason, seqnr;
102392555Sdes	u_char type;
102460573Skris	char *msg;
102592555Sdes
102660573Skris	for (;;) {
102792555Sdes		if (compat20) {
102892555Sdes			type = packet_read_poll2(seqnr_p);
102992555Sdes			if (type)
103060573Skris				DBG(debug("received packet type %d", type));
103192555Sdes			switch (type) {
103260573Skris			case SSH2_MSG_IGNORE:
103360573Skris				break;
103460573Skris			case SSH2_MSG_DEBUG:
103560573Skris				packet_get_char();
103660573Skris				msg = packet_get_string(NULL);
103760573Skris				debug("Remote: %.900s", msg);
103860573Skris				xfree(msg);
103960573Skris				msg = packet_get_string(NULL);
104060573Skris				xfree(msg);
104160573Skris				break;
104260573Skris			case SSH2_MSG_DISCONNECT:
104360573Skris				reason = packet_get_int();
104460573Skris				msg = packet_get_string(NULL);
104599060Sdes				log("Received disconnect from %s: %u: %.400s",
104699060Sdes				    get_remote_ipaddr(), reason, msg);
104760573Skris				xfree(msg);
104860573Skris				fatal_cleanup();
104960573Skris				break;
105092555Sdes			case SSH2_MSG_UNIMPLEMENTED:
105192555Sdes				seqnr = packet_get_int();
105299060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
105399060Sdes				    seqnr);
105492555Sdes				break;
105560573Skris			default:
105660573Skris				return type;
105760573Skris				break;
105876259Sgreen			}
105960573Skris		} else {
106092555Sdes			type = packet_read_poll1();
106192555Sdes			switch (type) {
106260573Skris			case SSH_MSG_IGNORE:
106360573Skris				break;
106460573Skris			case SSH_MSG_DEBUG:
106560573Skris				msg = packet_get_string(NULL);
106660573Skris				debug("Remote: %.900s", msg);
106760573Skris				xfree(msg);
106860573Skris				break;
106960573Skris			case SSH_MSG_DISCONNECT:
107060573Skris				msg = packet_get_string(NULL);
107199060Sdes				log("Received disconnect from %s: %.400s",
107299060Sdes				    get_remote_ipaddr(), msg);
107360573Skris				fatal_cleanup();
107460573Skris				xfree(msg);
107560573Skris				break;
107660573Skris			default:
107792555Sdes				if (type)
107860573Skris					DBG(debug("received packet type %d", type));
107960573Skris				return type;
108060573Skris				break;
108176259Sgreen			}
108260573Skris		}
108360573Skris	}
108460573Skris}
108560573Skris
108692555Sdesint
108792555Sdespacket_read_poll(void)
108892555Sdes{
108992555Sdes	return packet_read_poll_seqnr(NULL);
109092555Sdes}
109192555Sdes
109257429Smarkm/*
109357429Smarkm * Buffers the given amount of input characters.  This is intended to be used
109457429Smarkm * together with packet_read_poll.
109557429Smarkm */
109657429Smarkm
109757429Smarkmvoid
109876259Sgreenpacket_process_incoming(const char *buf, u_int len)
109957429Smarkm{
110057429Smarkm	buffer_append(&input, buf, len);
110157429Smarkm}
110257429Smarkm
110357429Smarkm/* Returns a character from the packet. */
110457429Smarkm
110576259Sgreenu_int
110692555Sdespacket_get_char(void)
110757429Smarkm{
110857429Smarkm	char ch;
1109106121Sdes
111057429Smarkm	buffer_get(&incoming_packet, &ch, 1);
111176259Sgreen	return (u_char) ch;
111257429Smarkm}
111357429Smarkm
111457429Smarkm/* Returns an integer from the packet data. */
111557429Smarkm
111676259Sgreenu_int
111792555Sdespacket_get_int(void)
111857429Smarkm{
111957429Smarkm	return buffer_get_int(&incoming_packet);
112057429Smarkm}
112157429Smarkm
112257429Smarkm/*
112357429Smarkm * Returns an arbitrary precision integer from the packet data.  The integer
112457429Smarkm * must have been initialized before this call.
112557429Smarkm */
112657429Smarkm
112757429Smarkmvoid
112892555Sdespacket_get_bignum(BIGNUM * value)
112957429Smarkm{
113092555Sdes	buffer_get_bignum(&incoming_packet, value);
113157429Smarkm}
113257429Smarkm
113360573Skrisvoid
113492555Sdespacket_get_bignum2(BIGNUM * value)
113560573Skris{
113692555Sdes	buffer_get_bignum2(&incoming_packet, value);
113760573Skris}
113860573Skris
113992555Sdesvoid *
114060573Skrispacket_get_raw(int *length_ptr)
114160573Skris{
114260573Skris	int bytes = buffer_len(&incoming_packet);
1143106121Sdes
114460573Skris	if (length_ptr != NULL)
114560573Skris		*length_ptr = bytes;
114660573Skris	return buffer_ptr(&incoming_packet);
114760573Skris}
114860573Skris
114960573Skrisint
115060573Skrispacket_remaining(void)
115160573Skris{
115260573Skris	return buffer_len(&incoming_packet);
115360573Skris}
115460573Skris
115557429Smarkm/*
115657429Smarkm * Returns a string from the packet data.  The string is allocated using
115757429Smarkm * xmalloc; it is the responsibility of the calling program to free it when
115857429Smarkm * no longer needed.  The length_ptr argument may be NULL, or point to an
115957429Smarkm * integer into which the length of the string is stored.
116057429Smarkm */
116157429Smarkm
116292555Sdesvoid *
116376259Sgreenpacket_get_string(u_int *length_ptr)
116457429Smarkm{
116557429Smarkm	return buffer_get_string(&incoming_packet, length_ptr);
116657429Smarkm}
116757429Smarkm
116857429Smarkm/*
116957429Smarkm * Sends a diagnostic message from the server to the client.  This message
117057429Smarkm * can be sent at any time (but not while constructing another message). The
117157429Smarkm * message is printed immediately, but only if the client is being executed
117257429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
117357429Smarkm * authentication problems.   The length of the formatted message must not
117457429Smarkm * exceed 1024 bytes.  This will automatically call packet_write_wait.
117557429Smarkm */
117657429Smarkm
117757429Smarkmvoid
117857429Smarkmpacket_send_debug(const char *fmt,...)
117957429Smarkm{
118057429Smarkm	char buf[1024];
118157429Smarkm	va_list args;
118257429Smarkm
118376259Sgreen	if (compat20 && (datafellows & SSH_BUG_DEBUG))
118476259Sgreen		return;
118576259Sgreen
118657429Smarkm	va_start(args, fmt);
118757429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
118857429Smarkm	va_end(args);
118957429Smarkm
119060573Skris	if (compat20) {
119160573Skris		packet_start(SSH2_MSG_DEBUG);
119260573Skris		packet_put_char(0);	/* bool: always display */
119360573Skris		packet_put_cstring(buf);
119460573Skris		packet_put_cstring("");
119560573Skris	} else {
119660573Skris		packet_start(SSH_MSG_DEBUG);
119760573Skris		packet_put_cstring(buf);
119860573Skris	}
119957429Smarkm	packet_send();
120057429Smarkm	packet_write_wait();
120157429Smarkm}
120257429Smarkm
120357429Smarkm/*
120457429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
120557429Smarkm * connection, and exits.  This function never returns. The error message
120657429Smarkm * should not contain a newline.  The length of the formatted message must
120757429Smarkm * not exceed 1024 bytes.
120857429Smarkm */
120957429Smarkm
121057429Smarkmvoid
121157429Smarkmpacket_disconnect(const char *fmt,...)
121257429Smarkm{
121357429Smarkm	char buf[1024];
121457429Smarkm	va_list args;
121557429Smarkm	static int disconnecting = 0;
1216106121Sdes
121757429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
121857429Smarkm		fatal("packet_disconnect called recursively.");
121957429Smarkm	disconnecting = 1;
122057429Smarkm
122157429Smarkm	/*
122257429Smarkm	 * Format the message.  Note that the caller must make sure the
122357429Smarkm	 * message is of limited size.
122457429Smarkm	 */
122557429Smarkm	va_start(args, fmt);
122657429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
122757429Smarkm	va_end(args);
122857429Smarkm
1229113908Sdes	/* Display the error locally */
1230113908Sdes	log("Disconnecting: %.100s", buf);
1231113908Sdes
123257429Smarkm	/* Send the disconnect message to the other side, and wait for it to get sent. */
123360573Skris	if (compat20) {
123460573Skris		packet_start(SSH2_MSG_DISCONNECT);
123560573Skris		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
123660573Skris		packet_put_cstring(buf);
123760573Skris		packet_put_cstring("");
123860573Skris	} else {
123960573Skris		packet_start(SSH_MSG_DISCONNECT);
124092555Sdes		packet_put_cstring(buf);
124160573Skris	}
124257429Smarkm	packet_send();
124357429Smarkm	packet_write_wait();
124457429Smarkm
124557429Smarkm	/* Stop listening for connections. */
124692555Sdes	channel_close_all();
124757429Smarkm
124857429Smarkm	/* Close the connection. */
124957429Smarkm	packet_close();
125057429Smarkm
125157429Smarkm	fatal_cleanup();
125257429Smarkm}
125357429Smarkm
125457429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */
125557429Smarkm
125657429Smarkmvoid
125792555Sdespacket_write_poll(void)
125857429Smarkm{
125957429Smarkm	int len = buffer_len(&output);
1260106121Sdes
126157429Smarkm	if (len > 0) {
126257429Smarkm		len = write(connection_out, buffer_ptr(&output), len);
126357429Smarkm		if (len <= 0) {
126457429Smarkm			if (errno == EAGAIN)
126557429Smarkm				return;
126657429Smarkm			else
126757429Smarkm				fatal("Write failed: %.100s", strerror(errno));
126857429Smarkm		}
126957429Smarkm		buffer_consume(&output, len);
127057429Smarkm	}
127157429Smarkm}
127257429Smarkm
127357429Smarkm/*
127457429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
127557429Smarkm * written.
127657429Smarkm */
127757429Smarkm
127857429Smarkmvoid
127992555Sdespacket_write_wait(void)
128057429Smarkm{
128176259Sgreen	fd_set *setp;
128276259Sgreen
128376259Sgreen	setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
128476259Sgreen	    sizeof(fd_mask));
128557429Smarkm	packet_write_poll();
128657429Smarkm	while (packet_have_data_to_write()) {
128776259Sgreen		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
128876259Sgreen		    sizeof(fd_mask));
128976259Sgreen		FD_SET(connection_out, setp);
129076259Sgreen		while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
129176259Sgreen		    (errno == EAGAIN || errno == EINTR))
129276259Sgreen			;
129357429Smarkm		packet_write_poll();
129457429Smarkm	}
129576259Sgreen	xfree(setp);
129657429Smarkm}
129757429Smarkm
129857429Smarkm/* Returns true if there is buffered data to write to the connection. */
129957429Smarkm
130057429Smarkmint
130192555Sdespacket_have_data_to_write(void)
130257429Smarkm{
130357429Smarkm	return buffer_len(&output) != 0;
130457429Smarkm}
130557429Smarkm
130657429Smarkm/* Returns true if there is not too much data to write to the connection. */
130757429Smarkm
130857429Smarkmint
130992555Sdespacket_not_very_much_data_to_write(void)
131057429Smarkm{
131157429Smarkm	if (interactive_mode)
131257429Smarkm		return buffer_len(&output) < 16384;
131357429Smarkm	else
131457429Smarkm		return buffer_len(&output) < 128 * 1024;
131557429Smarkm}
131657429Smarkm
1317113908Sdesstatic void
1318113908Sdespacket_set_tos(int interactive)
1319113908Sdes{
1320113908Sdes	int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
1321113908Sdes
1322113908Sdes	if (!packet_connection_is_on_socket() ||
1323113908Sdes	    !packet_connection_is_ipv4())
1324113908Sdes		return;
1325113908Sdes	if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1326113908Sdes	    sizeof(tos)) < 0)
1327113908Sdes		error("setsockopt IP_TOS %d: %.100s:",
1328113908Sdes		    tos, strerror(errno));
1329113908Sdes}
1330113908Sdes
133157429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
133257429Smarkm
133357429Smarkmvoid
133476259Sgreenpacket_set_interactive(int interactive)
133557429Smarkm{
133676259Sgreen	static int called = 0;
133757429Smarkm
133876259Sgreen	if (called)
133976259Sgreen		return;
134076259Sgreen	called = 1;
134176259Sgreen
134257429Smarkm	/* Record that we are in interactive mode. */
134357429Smarkm	interactive_mode = interactive;
134457429Smarkm
134557429Smarkm	/* Only set socket options if using a socket.  */
134657429Smarkm	if (!packet_connection_is_on_socket())
1347113908Sdes	if (interactive)
134892555Sdes		set_nodelay(connection_in);
134998937Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1350113908Sdes	packet_set_tos(interactive);
135198937Sdes#endif
1352113908Sdes
135357429Smarkm}
135457429Smarkm
135557429Smarkm/* Returns true if the current connection is interactive. */
135657429Smarkm
135757429Smarkmint
135892555Sdespacket_is_interactive(void)
135957429Smarkm{
136057429Smarkm	return interactive_mode;
136157429Smarkm}
136257429Smarkm
136357429Smarkmint
136457429Smarkmpacket_set_maxsize(int s)
136557429Smarkm{
136657429Smarkm	static int called = 0;
1367106121Sdes
136857429Smarkm	if (called) {
136960573Skris		log("packet_set_maxsize: called twice: old %d new %d",
137060573Skris		    max_packet_size, s);
137157429Smarkm		return -1;
137257429Smarkm	}
137357429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
137457429Smarkm		log("packet_set_maxsize: bad size %d", s);
137557429Smarkm		return -1;
137657429Smarkm	}
137792555Sdes	called = 1;
137892555Sdes	debug("packet_set_maxsize: setting to %d", s);
137957429Smarkm	max_packet_size = s;
138057429Smarkm	return s;
138157429Smarkm}
138276259Sgreen
138392555Sdes/* roundup current message to pad bytes */
138492555Sdesvoid
138592555Sdespacket_add_padding(u_char pad)
138692555Sdes{
138792555Sdes	extra_pad = pad;
138892555Sdes}
138992555Sdes
139076259Sgreen/*
139176259Sgreen * 9.2.  Ignored Data Message
139276259Sgreen *
139376259Sgreen *   byte      SSH_MSG_IGNORE
139476259Sgreen *   string    data
139576259Sgreen *
139676259Sgreen * All implementations MUST understand (and ignore) this message at any
139776259Sgreen * time (after receiving the protocol version). No implementation is
139876259Sgreen * required to send them. This message can be used as an additional
139976259Sgreen * protection measure against advanced traffic analysis techniques.
140076259Sgreen */
140176259Sgreenvoid
140276259Sgreenpacket_send_ignore(int nbytes)
140376259Sgreen{
140476259Sgreen	u_int32_t rand = 0;
140576259Sgreen	int i;
140676259Sgreen
140776259Sgreen	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
140876259Sgreen	packet_put_int(nbytes);
140992555Sdes	for (i = 0; i < nbytes; i++) {
141076259Sgreen		if (i % 4 == 0)
141176259Sgreen			rand = arc4random();
141276259Sgreen		packet_put_char(rand & 0xff);
141376259Sgreen		rand >>= 8;
141476259Sgreen	}
141576259Sgreen}
1416